# upbit-trader 전략 가이드 ## 시스템 개요 | 데몬 | 전략 | 상태 | |------|------|------| | `tick-trader` | WebSocket 20초봉 + LLM 매수 + 트레일링 청산 | **운용 중** | | `upbit-trader` | 10분봉 Volume Lead 매집 전략 | 중지 (2026-03-06~) | --- ## 1. tick-trader (WebSocket 20초봉) ### 1.1 아키텍처 ``` WebSocket (Upbit trade tick) -> 20초봉 집계 (on_tick -> finalize_bars) -> 시그널 감지 (양봉 + VOL >= 5x + 사전 필터 3종) -> LLM 매수 판단 (get_entry_price) -> 지정가 매수 (현재가) -> 트레일링 스탑 / 손절 / 타임아웃 청산 ``` ### 1.2 감시 종목 (10개) ``` ETH, XRP, SOL, DOGE, SIGN, BARD, KITE, CFG, SXP, ARDR ``` ### 1.3 진입 조건 **시그널 감지** -- 20초봉 확정 시 다음 조건 동시 충족: | 순서 | 조건 | 파라미터 | 값 | |------|------|----------|------| | 1 | 양봉 (close > open) | -- | 필수 | | 2 | 거래량 >= 이전 61봉 평균 x N배 (trimmed mean, 상위 10% 제거) | `VOL_MIN` | 5.0x | | 3 | 20초봉 거래대금 >= 하한 | `VOL_KRW_MIN` | 5,000,000원 | | 4 | 횡보 필터: 최근 15봉 변동폭 >= 0.3% | `SPREAD_MIN` | 0.3% | | 5 | 고점 필터: 30분 구간 내 90%+ 위치 & 변동 1%+ 아닐 것 | `HIGHPOS` | 90% / 1.0% | | 6 | 연속 양봉 필터: 직전 2봉 이상 연속 양봉 | -- | >= 2 | **LLM 매수 판단** -- 사전 필터 통과 후 LLM에게 매수 여부 위임: - LLM이 DB Tool로 시장 데이터 조회 후 `buy` / `skip` 판단 - `buy` 시 현재가로 지정가 매수 (LLM은 가격 결정 안 함) - `skip` 시 텔레그램 알림 + 사유 기록 - 과거 연패/승률은 고려하지 않도록 프롬프팅 (get_trade_history 제거) **중복/한도 방지**: - 이미 보유(`positions`) 또는 매수대기(`pending_buys`) 종목은 스킵 - LLM 호출 전/후 포지션 한도(`MAX_POS`) 이중 체크 - 예산 체크: MAX_BUDGET - (보유 투자금 + 미체결 투자금) - 미체결 180초 초과 시 자동 취소 ### 1.4 청산: 트레일링 스탑 LLM 매도는 제거됨. 규칙 기반 트레일링 스탑으로 청산. | 조건 | 파라미터 | 값 | 설명 | |------|----------|------|------| | 트레일링 스탑 | `TRAIL_PCT` | -1.5% | 고점 대비 하락 시 시장가 청산 | | 최소 수익 | `MIN_PROFIT_PCT` | +0.5% | 트레일 발동 최소 수익률 | | 손절 | `STOP_LOSS_PCT` | -2.0% | 진입가 대비 -2% 시 시장가 청산 | | 타임아웃 | `TIMEOUT_SECS` | 14,400초 (4h) | 경과 시 시장가 청산 | - 실시간 tick마다 peak 갱신 + 손절/트레일 체크 (`update_positions`) - 20초봉 확정 시에도 체크 (`check_filled_positions`) ### 1.5 LLM 어드바이저 **모델**: Google Gemini 2.5 Flash (OpenRouter API) **비용**: ~5원/일 (~150원/월) -- 매도 LLM 제거 + 사전 필터로 대폭 절감 **DB Tool 4개** (매수 판단용): | Tool | 데이터 소스 | 용도 | |------|-----------|------| | `get_price_ticks` | Oracle `price_tick` | 최근 N분 가격 틱 (단기 추세) | | `get_ohlcv` | Oracle `backtest_ohlcv` | 1분봉 OHLCV (지지/저항) | | `get_ticker_context` | Oracle `ticker_context` | 종목 평판 (가격 변동, 뉴스) | | `get_btc_trend` | Oracle `backtest_ohlcv` | BTC 4시간봉 추세 | **최적화**: - Tool call 중복 제거: 동일 tool+args 호출 시 캐시된 결과 반환 - max_rounds=5: 최대 5라운드 tool calling 후 강제 응답 ### 1.6 재시작 복구 PM2 재시작 시 `restore_positions()`: 1. Upbit `get_balances()`로 보유 종목 조회 (balance + locked) 2. 포지션 복구 (트레일링 스탑 모드) 3. 미체결 매수 주문도 `pending_buys`에 복구 4. `entry_ts` 백데이팅으로 즉시 활성화 ### 1.7 가격 표시 `fp()` 헬퍼로 가격대별 소수점 자동 조정: - >= 100원: 정수 (예: 106,177,000) - >= 10원: 소수 1자리 (예: 47.5) - < 10원: 소수 2자리 (예: 0.85) --- ## 2. upbit-trader (10분봉 Volume Lead) [중지됨] > 중지 사유: tick-trader와 동일 계좌에서 동시 운용 시 예산 초과 문제 - 10분봉 Volume Lead 매집 전략 - 횡보 중 거래량 급증 -> 신호 기록 -> +4.8% 상승 확인 후 진입 - F&G 필터: <=40->6x / 41~50->5x / >50->차단 - ATR 트레일링 스탑 + 타임스탑(8h) - WF 필터: Oracle DB 영속 저장 --- ## 3. 공통 인프라 ### 3.1 데이터 수집 데몬 | 데몬 | 주기 | 역할 | |------|------|------| | `tick-collector` | 30초 | `price_tick` 30초봉 + `backtest_ohlcv` 1분봉 Oracle 저장 | | `context-collector` | 1시간 | 종목별 `ticker_context` (가격 통계 + SearXNG 뉴스) | ### 3.2 기술 스택 | 구성 | 기술 | |------|------| | 거래소 | Upbit API (REST + WebSocket) | | DB | Oracle ADB (price_tick, backtest_ohlcv, ticker_context, trade_log, wf_state, position_sync) | | LLM | Google Gemini 2.5 Flash via OpenRouter | | 알림 | Telegram Bot API | | 뉴스 | SearXNG (self-hosted) | | 프로세스 | PM2 (tick-trader, tick-collector, context-collector) | ### 3.3 예산 관리 | 파라미터 | 값 | 설명 | |----------|------|------| | `MAX_BUDGET` | 1,000,000원 | 총 운용 예산 | | `MAX_POSITIONS` | 5 | 최대 동시 보유 종목 | | 종목당 예산 | 200,000원 | `MAX_BUDGET / MAX_POSITIONS` | --- ## 4. 프로젝트 구조 ### 프로덕션 | 파일 | 역할 | |------|------| | `daemons/tick_trader.py` | WebSocket 20초봉 트레이더 (LLM 매수 + 트레일링 청산) | | `daemons/tick_collector.py` | price_tick + 1분봉 수집 | | `daemons/context_collector.py` | 종목 컨텍스트 수집 (뉴스 + 가격 통계) | | `core/llm_advisor.py` | OpenRouter LLM 매수 어드바이저 (tool calling) | | `core/notify.py` | 텔레그램 알림 | ### 설정 | 파일 | 역할 | |------|------| | `.env` | API 키, 전략 파라미터, DB 설정 | | `ecosystem.config.js` | PM2 프로세스 설정 | ### 백테스트 | 파일 | 역할 | |------|------| | `backtest_march.py` | 3월 1분봉 시뮬레이션 (Oracle DB 데이터) | --- ## 5. 운용 설정 (.env) ```env # 총 운용 예산 / 최대 동시 보유 종목 MAX_BUDGET=1000000 MAX_POSITIONS=5 # LLM (OpenRouter) OPENROUTER_API_KEY=sk-or-v1-... LLM_MODEL=google/gemini-2.5-flash # Oracle ADB ORACLE_USER=admin ORACLE_PASSWORD=... ORACLE_DSN=... ORACLE_WALLET=... # Telegram TELEGRAM_TRADE_TOKEN=... TELEGRAM_CHAT_ID=... ``` --- ## 6. 백테스트 결과 ### 3월 시뮬레이션 (1분봉, 연속양봉 필터 적용) > 기간: 2026-03-01 ~ 2026-03-06 / 10종목 / MAX_POS=3 | 항목 | 필터 전 | 연속양봉 >= 2 적용 | |------|---------|-------------------| | 시그널 | 112건 | 48건 (-57%) | | 승률 | 38.4% | **52.1%** | | 총 PNL | +11,530원 | **+17,868원** | | 평균 PNL | +0.13% | **+1.22%** | | 손절 | 31건 | 12건 | | 트레일 익절 | 13건 | 18건 | --- ## 7. 변경 이력 | 날짜 | 변경 내용 | |------|---------| | 2026-03-06 | 연속 양봉 >= 2 필터 추가 (승률 38% -> 52%) | | 2026-03-06 | 예산 변경: 100K/3pos -> 1M/5pos (종목당 200K) | | 2026-03-06 | LLM 매도 제거 -> 트레일링 스탑 전환 (TRAIL -1.5%, SL -2%, 4h timeout) | | 2026-03-06 | cascade 매도 제거 | | 2026-03-06 | 사전 필터 3종 추가 (횡보/고점/연속양봉) -> LLM 호출 ~57% 절감 | | 2026-03-06 | 종목 30개 -> 10개 축소, BTC 제외 | | 2026-03-06 | 현재가 매수 (LLM 가격 제안 제거) | | 2026-03-06 | LLM 매수 프롬프트: 연패 무시, get_trade_history 제거 | | 2026-03-06 | VOL_KRW_MIN: 2M -> 5M, BUY_TIMEOUT: 60 -> 180초 | | 2026-03-06 | 예산 체크: MAX_BUDGET - 투자금 합계 방식 | | 2026-03-06 | `_round_price` 호가 단위 수정: 10만~50만 구간 50->100원 | | 2026-03-06 | 매도 주문 실패 시 자동 재시도 | | 2026-03-06 | upbit-trader (보조 봇) 중지 | | 2026-03-05 | `tick-trader` LLM-driven 매수/매도 전환, cascade fallback 구현 | | 2026-03-05 | LLM 모델 Claude Haiku 4.5 -> Gemini 2.5 Flash (비용 7.5x 절감) | | 2026-03-05 | `restore_positions()`: 잔고 기반 포지션 복구 | | 2026-03-05 | 포지션 한도 초과 방지 3중 체크 |