Files
upbit-trader/STRATEGY.md

190 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Volume Lead 전략 가이드
## 전략 개요
**거래량 선행(Volume Lead) 매집 전략** — 가격이 횡보하는 중 거래량 급증이 발생하면
매집 신호로 기록하고, 이후 일정 수준 이상 상승 시 진입하는 선진입 전략.
> 핵심 아이디어: 대형 매수자는 가격을 올리지 않고 조용히 매집한다.
> 거래량이 먼저 급증하고, 가격 상승은 그 뒤에 따라온다.
**캔들 단위: 40분봉** (Upbit `minute10` API로 수신 후 인메모리 40분 리샘플링)
---
## 진입 조건 (2단계)
### 1단계: 매집 신호 감지
다음 두 조건 동시 충족 시 `signal_price` 기록:
| 조건 | 파라미터 | 기본값 |
|------|----------|--------|
| 2h 가격 변동 < N% (횡보) | `PRICE_QUIET_PCT` | 2.0% |
| 직전 40분봉 거래량 ≥ 로컬 5h(7봉) 평균 × M배 | `VOLUME_MULTIPLIER` | 2.0x |
- 신호 발생 시 텔레그램 알림 발송
- `SIGNAL_TIMEOUT_H` 내 진입 조건 미달 시 신호 초기화 (기본: 8h)
- 신호가 이하 하락 시 즉시 초기화 (매집 실패 판단)
> **2h 횡보 체크**: Oracle DB에 저장된 실시간 가격 기록을 조회 (`get_price_n_hours_ago`)
> **거래량 체크**: `minute10` → 40분봉 resample → 직전 완성봉 vs 이전 7봉 평균
### 2단계: 추세 확인 후 진입
`signal_price` 대비 +`TREND_AFTER_VOL`% 이상 상승 확인 시 매수:
| 파라미터 | 기본값 | 설명 |
|----------|--------|------|
| `TREND_AFTER_VOL` | 4.8% | 신호가 대비 진입 임계값 |
---
## 청산 조건
### 트레일링 스탑 (ATR 기반)
- `minute10` → 40분봉 resample 후 최근 7봉(≈5h)의 평균 진폭 계산
- ATR = 평균진폭 × 1.5 계수 → 동적 손절폭 산출
- 최소 1.0% / **최대 2.0%** 범위 내 자동 조정
- 최고가 대비 손절폭 이하 하락 시 즉시 청산
- ATR 캐시: 40분마다 갱신 (캐시 TTL=2400초)
### 타임 스탑
- 보유 `TIME_STOP_HOURS`h 경과 후 수익률 < `TIME_STOP_MIN_GAIN_PCT`% 이면 청산
- 기본값: 8시간 경과 / 수익률 3% 미만
---
## 리스크 관리
### Walk-Forward (WF) 필터
| 파라미터 | 기본값 | 설명 |
|----------|--------|------|
| `WF_WINDOW` | 2 | 이력 윈도우 (직전 N건) |
| `WF_MIN_WIN_RATE` | 0.01 | 최소 승률 임계값 (1%) |
| `WF_SHADOW_WINS` | 2 | 차단 해제 조건 (가상 N연승) |
- 직전 2건 모두 손실 → 해당 종목 진입 차단
- 차단 후 가상 추적으로 2연승 달성 시 자동 복귀
- **WF 차단 상태는 Oracle DB(`wf_state` 테이블)에 영속 저장** → 재시작 후에도 복원
### 예산 관리 (복리)
- 수익 발생 시: `운용예산 = 초기예산 + 누적수익` (복리 증가)
- 손실 발생 시: `운용예산 = 초기예산 + 누적수익` (차감)
- 하한선: 초기예산의 30% (기본: 4,500,000원)
- 포지션당 크기: `운용예산 / MAX_POSITIONS`
---
## 시장 레짐 적응
| 레짐 | BTC 1h 변동 | 거래량 기준 |
|------|------------|------------|
| BULL | +5% 이상 | 1.5x |
| NEUTRAL | ±5% 이내 | 2.0x |
| BEAR | -5% 이하 | 진입 차단 |
- BEAR 레짐 감지 시 신규 진입 전면 차단
- 레짐별 `vol_mult` 조정으로 민감도 제어
---
## 운용 설정 (.env)
```env
# 핵심 전략
PRICE_QUIET_PCT=2.0 # 2h 횡보 기준 (%)
TREND_AFTER_VOL=4.8 # 진입 임계값 (신호가 대비 %)
SIGNAL_TIMEOUT_H=8.0 # 신호 유효 시간 (h)
VOLUME_MULTIPLIER=2.0 # 거래량 배수 기준
# 청산
TIME_STOP_HOURS=8 # 타임스탑 보유 시간
TIME_STOP_MIN_GAIN_PCT=3 # 타임스탑 최소 수익률
# 포트폴리오
MAX_BUDGET=15000000 # 초기 운용 예산
MAX_POSITIONS=3 # 최대 동시 보유 종목
# WF 필터
WF_WINDOW=2
WF_MIN_WIN_RATE=0.01
WF_SHADOW_WINS=2
```
---
## 백테스트 결과 요약
### A. 365일 — 1h봉, WF 적용 (`sim_365.py`)
> 기간: 2025-03-02 ~ 2026-03-02 / 데이터: Oracle DB 1h OHLCV / 20종목
| 항목 | 값 |
|------|-----|
| 초기 예산 | 15,000,000원 |
| 최종 자산 | 29,996,109원 |
| 수익률 | **+100%** |
| 최대 낙폭 | -3.81% (-57만원) |
| 거래수 | 190건 (WF 183건 차단) |
| 승률 | 46% |
| 월평균 수익 | 약 115만원 |
### B. 45일 — 40분봉 (`interval_sweep.py`)
> 기간: 2025-12-18 ~ 2026-03-02 / 데이터: Upbit minute10 캐시 리샘플링 / 20종목
> ※ WF 미적용, 단순 전략 누적 PnL 합산 기준
| 봉 단위 | 거래수 | 승률 | 누적PnL | 최대낙폭 |
|---------|--------|------|---------|---------|
| 10분 | 180 | 33.9% | +15.8% | -32.6% |
| 20분 | 120 | 36.7% | +31.0% | -16.7% |
| 30분 | 91 | 48.4% | +81.7% | -12.9% |
| **40분** | **91** | **48.4%** | **+119.4%** | **-11.2%** ← 현재 채택 |
| 50분 | 83 | 50.6% | +94.7% | -17.1% |
| 60분 | 65 | 50.8% | +88.3% | -11.9% |
### C. ATR_MAX_STOP 스윕 — 1h봉 기준 (`atr_sweep.py`)
> 데이터: Oracle DB 1h OHLCV / 20종목
| ATR_MAX | 승률 | 누적PnL | 최대낙폭 | 평균스탑 |
|---------|------|---------|---------|---------|
| 1.5% | 52.3% | +442% | -3.2% | 1.49% |
| **2.0%** | **50.8%** | **+299%** | **-4.1%** | **1.49%** ← 현재 채택 |
| 2.5% | 50.8% | +256% | -5.3% | 1.77% |
| 4.0% | 45.9% | -52% | -29.1% | 3.11% |
---
## 주요 파일
| 파일 | 역할 |
|------|------|
| `core/strategy.py` | 진입 신호 로직 (40분봉 vol-lead) |
| `core/monitor.py` | ATR 트레일링 스탑 + 타임스탑 (40분봉 ATR) |
| `core/trader.py` | 주문 실행 + 복리 예산 관리 |
| `core/market_regime.py` | 시장 레짐 감지 |
| `core/price_db.py` | 가격 DB + WF 상태 영속화 |
| `ohlcv_db.py` | OHLCV 시계열 DB 캐시 관리 |
| `sim_365.py` | 365일 복리 시뮬레이션 |
| `atr_sweep.py` | ATR_MAX_STOP 파라미터 스윕 |
| `sim10m.py` | 10분봉 vs 1h봉 전략 비교 시뮬 |
| `interval_sweep.py` | 봉 단위별 성과 비교 (10/20/30/40/50/60분) |
---
## 시뮬레이션 실행
```bash
# 봉 단위별 비교 (10m 캐시 필요)
python interval_sweep.py
# ATR_MAX_STOP 스윕 (DB에서 로드)
python atr_sweep.py
# 365일 복리 시뮬 (DB에서 로드)
python sim_365.py
# OHLCV DB 상태 확인
python ohlcv_db.py status
# 신규 봉 증분 업데이트
python ohlcv_db.py update
```