QuantBot은 업비트(Upbit) API를 활용하여 비트코인(BTC) 시장을 24시간 감시하고, 수학적 지표에 기반해 자동으로 매수/매도 및 리스크 관리를 수행하는 파이썬 기반의 퀀트 트레이딩 봇입니다.
단순한 수익 창출을 넘어, 철저한 **하락장 회피(필터링)**와 **변동성 기반의 자산 보호(ATR)**에 초점을 맞추어 설계되었습니다.
안정적인 24시간 무중단 운영을 위해 다음과 같은 환경에서 구축 및 관리됩니다.
- 운영 서버: Oracle Cloud (Ubuntu ARM 기반 인스턴스)
- 개발 및 동기화: macOS + Cursor IDE 기반 로컬 개발 ➡️ GitHub ➡️ 원격 서버 배포 (Git Pull)
- 프로세스 관리:
PM2를 활용한 무중단 백그라운드 실행 및 에러 자동 복구 - 서버 유지보수:
Claude Code(CLI)를 통한 실시간 서버 환경 에러 디버깅 및 분석
QuantBot V4.0은 **Top-Down 방식(다중 타임프레임 분석)**을 사용하여 큰 추세를 먼저 확인한 후, 짧은 프레임에서 정밀하게 진입합니다.
가짜 돌파(휩쏘)에 당하지 않고, 확실한 상승장에서만 매매하기 위한 안전장치입니다.
- EMA (지수이동평균선, 20 & 50): 단기(20) EMA가 장기(50) EMA 위에 있는 정배열(상승 추세) 상태인지 확인합니다. 현재가가 EMA 20보다 높아야만 진입을 허용합니다.
- ADX (평균방향성지수, 14): 추세의 '강도'를 측정합니다. ADX 값이 28 이상일 때만 시장에 뚜렷한 방향성이 있다고 판단하고 횡보장에서는 진입을 차단합니다.
상위 추세가 확인되면, 변동성 돌파 전략을 통해 타점을 잡습니다.
- Highest_60 종가 돌파: 15분봉이 과거 60개 캔들(약 15시간)의 '최고점' 위에서 마감할 때 진입합니다. 장중 틱이 잠깐 뚫는 것은 인정하지 않고 종가 기준으로만 판정하여 휩쏘(가짜 돌파)를 거릅니다. 틱 돌파 시점에는 SETUP(조기 경보) 알림만 발송됩니다.
- RSI 과매수 필터: 돌파봉의 RSI(14) 가 76 이상이면 진입을 차단하여, 단기 과열 구간에서의 평균회귀 위험을 회피합니다.
- 거래량 확인: 돌파봉의 거래량이 20봉 평균의 1.3배 이상일 때만 진입합니다. 거래량이 받쳐주지 않는 가짜 돌파를 걸러냅니다.
- 시간대 필터: KST 01~04시 의 저유동성 구간(미국·아시아 시장 모두 비활성)에서는 신규 진입을 차단합니다.
- 라이브-백테스트 완전 정합: 모든 진입 조건(돌파·RSI·거래량·ATR)은 같은 확정봉의 값으로 판정하고, 1시간봉 추세 지표(EMA/ADX)도 양쪽 모두 직전 완결봉만 사용합니다. 체결 타이밍(돌파봉 마감 직후 시장가)까지 백테스트 엔진과 동일하여, 워크포워드 검증 결과가 실거래 로직을 그대로 대변합니다.
- ATR (평균진폭): 시장의 변동성을 수치화한 지표입니다. 변동성이 클 때는 목표가와 손절가를 넓게, 작을 때는 좁게 자동 조정합니다.
- 동적 포지션 사이즈 (1% Rule): 매번 똑같은 금액을 사는 것이 아니라, 손절 시 총자산의 1%만 손실을 보도록 현재 ATR 수치에 비례하여 매수 금액을 자동 계산합니다.
- 1차 익절 (+2.0 ATR): 목표 수익에 도달하면 보유 물량의 40% 를 즉시 매도하여 수익을 확정 짓습니다. 이후 손절선은 '본절가 + 1.2 ATR'로 끌어올려(Trailing Stop) 상당한 이익을 락인한 상태로 추세를 추종합니다.
- 2차 익절 (+6.0 ATR): 강력한 상승이 나왔을 때 잔여 물량을 전량 매도하여 수익을 극대화합니다.
- 칼손절 (-1.5 ATR): 예측이 틀렸을 경우 미련 없이 전량 매도 후, 3시간 동안 매매를 쉬며(쿨다운) 뇌동매매를 방지합니다.
💡 워크포워드 검증 기반 파라미터: 위 모든 파라미터는
quant_bot_4.0.py상단의 전략 파라미터 상수 블록 한 곳에서 관리되며, 단순 그리드서치 1등이 아니라 워크포워드 검증(walkforward.py) 을 통과한 값만 채택합니다. [4개월 최적화 → 2개월 검증(OOS)] × 3폴드로 굴려본 결과, 폴드마다 재최적화한 조합은 OOS에서 현행 고정 파라미터보다 일관되게 열위였고(과최적화 실증), 현행 파라미터를 유지했습니다. 백테스트 엔진의 1시간봉 지표 look-ahead 버그(미완결 봉의 종가 참조)도 수정하여, 과거 부풀려진 성과 수치를 현실화했습니다. 파라미터 변경은 반드시python3 walkforward.py의 OOS 비교에서 현행 대비 우위를 확인한 뒤에만 반영합니다.
- 5분 봉 기준 연속된 캔들에서 -5% 이상의 비정상적인 급락이 감지되면 봇이 6시간 동안 신규 진입을 전면 차단합니다.
- 이때 보유 포지션이 있으면 내부 상태만 초기화하지 않고, 업비트 시장가 전량매도를 먼저 시도한 뒤 청산 결과를 텔레그램으로 알립니다.
- 상태 영속화:
bot_state.json에 누적 손익, 최근 거래, 포지션 상태, 진입가, 진입 ATR, TP1 완료 여부, 쿨다운, 플래시 크래시 락, 일시정지 상태를 저장합니다. PM2 재시작 후에도 봇이 기존 포지션 관리 상태를 복구합니다. - KST 명시 시간: 일일 리포트, 시간대 필터, 쿨다운, 서킷 브레이커 시간 계산은 모두
Asia/Seoul기준으로 처리합니다. 서버 로컬 타임존이 UTC여도 KST 01~04시 필터가 의도대로 동작합니다. - 부분매도 검증: TP1 40% 매도처럼 임의 비율의 시장가 매도도 잔고 감소량 기준으로 체결 성공 여부를 검증합니다.
- 실체결가 기반 손익 집계: 매도 주문의 uuid로 실제 체결 내역을 조회해 평균 체결가 기준으로 실현손익을 계산하고, 매수·매도 수수료(0.05%×2)를 차감해 기록합니다. 트리거 시점 가격 기반 추정치 대비 정확하며, 백테스트의 슬리피지 가정과 실거래의 괴리를 추적할 수 있습니다.
텔레그램 봇 API가 연동되어 있어, 밖에서도 스마트폰으로 봇의 상태를 실시간 확인하고 명령을 내릴 수 있습니다. 모든 알림은 HTML <b> 굵기와 이모지 체계(🔴 매수 / 🔵 매도 / 📈 수익 / 📉 손실 / 🚨 경고 / ⚙️ 시스템)를 활용한 대시보드 스타일로 출력되어, 거래소 앱을 켜지 않아도 핵심 숫자가 한눈에 들어오도록 설계되어 있습니다.
🔴 [신규 매수 체결] BTC/KRW
▫️ 매수가: 98,500,000원
▫️ 체결량: 0.01 BTC (약 98.5만원)
▫️ 매수 근거: 15분봉 Highest_60 돌파 (ADX 31.2, RSI 64.5)
▫️ ATR(15m): 850,000원
💰 현재 잔고: 현금 3,000,000원 (잔여 비중 75%)
실제 전송 시에는 매수가, 체결 수량, 잔고 등 핵심 숫자가 굵게 강조됩니다. 매도 알림에는 **확정 손익(+/−)**과 누적 실현손익이 함께 표시됩니다.
/status: 봇 상태(IDLE/SETUP/POSITION/일시정지), 총자산·코인 비중·현금 비중·수익률을 대시보드 형태로 요약해 보여줍니다. 누적 실현손익도 함께 표시됩니다./balance: 업비트 계좌의 KRW 잔고, 보유 BTC 수량, 총 추정 자산 및 현금 비중(%)을 확인합니다./market: 현재 BTC/KRW 시세, 24시간 변동률·거래대금, 15분봉 RSI/ATR, 1시간봉 EMA 배열·ADX, 그리고 **공포/탐욕 지수(Fear & Greed Index)**까지 출력하여 차트 없이도 시장의 온도감을 파악할 수 있습니다./history: 최근 거래 내역(매수/매도) 5건과 거래별 확정 손익, 누적 실현손익을 요약해 보여줍니다.
/pause: 신규 매수 로직만 일시 정지합니다. 이미 보유 중인 포지션의 익절/손절 청산 로직은 정상적으로 계속 동작합니다. FOMC 발표 등 큰 이벤트 관망 시 사용합니다./resume: 일시 정지된 신규 매수 로직을 다시 활성화합니다./panic: [최후의 수단] 보유한 모든 BTC를 시장가로 전량 매도하고, 자동으로 봇을일시정지대기 상태로 전환합니다. 극단적 폭락장에 대비하는 비상 스위치입니다./sell_all: [긴급 명령어] 즉시 전량 매도 후 포지션을 초기화합니다. (/panic과 달리 일시정지는 걸지 않음)/stop: 봇 프로세스를 안전하게 종료합니다. (재시작은 서버에서 PM2로 수행해야 합니다)/all: 모든 사용 가능한 명령어 리스트를 섹션별로 확인합니다.
- 실시간 체결 브리핑: 매수/매도 시 매수가·체결량·근거·현재 잔고를, 매도 시 확정 손익과 누적 실현손익을 함께 푸시합니다.
- 정기 일일 리포트 (Daily Briefing): 매일 오전 9시(일봉 마감)에 어제 하루의 성적표를 자동 전송합니다. 총자산 전일 대비 증감(%), 현재 보유 포지션 평가 손익, 공포/탐욕 지수 등을 포함합니다.
- 시스템 건강 상태 경고:
psutil로 메모리 사용률을 상시 모니터링하며, 80% 초과 시 즉시 🚨 알림을 발송하여 1GB 서버 환경에서 선제적으로 대응할 수 있게 합니다.
pip install pyupbit ta python-dotenv pyTelegramBotAPI requests psutil
2. 환경 변수 설정 (.env)
루트 디렉토리에 .env 파일을 생성하고 아래의 키를 발급받아 입력합니다. (GitHub 업로드 시 .gitignore를 통해 자동 제외됩니다)
코드 스니펫
UPBIT_ACCESS_KEY='본인의_업비트_액세스_키'
UPBIT_SECRET_KEY='본인의_업비트_시크릿_키'
TELEGRAM_TOKEN='텔레그램_봇_토큰'
TELEGRAM_CHAT_ID='본인의_텔레그램_채팅방_ID'
3. 봇 실행 (PM2 백그라운드 구동)
서버에 접속하여 봇 폴더로 이동한 뒤 아래 명령어를 실행합니다.
Bash
pm2 start quant_bot_4.0.py --name "btc-bot" --interpreter python3
4. 로그 확인
Bash
# 실시간 작동 로그 및 에러 확인
pm2 logs btc-bot