You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fithia2/docs/orb_gainers_v23_strategy.md

463 lines
16 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# ORB Gainers V23 전략 완전 해설
**버전:** V23 (id: 28)
**상태:** DEFINITIVE FINAL CHAMPION — 모든 개선 축 소진, 라이브 배포 중
**배포일:** 2026-04-20
**백테스트 기준일:** 200d 2025-07-XX ~ 2026-04-XX, 400d 2024-09-XX ~ 2026-04-XX
---
## 1. 전략 철학
ORB Gainers의 핵심은 **당일 비정상 관심 종목의 장 초반 돌파**를 잡는 것이다.
Yahoo Finance Top Gainers처럼 그날 강하게 움직이는 종목을 시스템으로 추린다. 진입 구조는 Opening Range Breakout(ORB) — 첫 5분봉의 고점 돌파 — 이지만, 실제 엣지의 원천은 **압축 후 확장**이 아니라 **당일 attention / catalyst / 비정상 거래량**이다.
핵심 철학:
- 당일 갭 + 프리마켓 거래대금 + 상대 거래량 = catalyst proxy
- ATR이 높은 종목만 선별해 폭발적 후속 움직임이 있는 후보만 취급
- daily_budget_reset + compound_returns=false: 단리 방식으로 매일 초기자본($10k) 기준 sizing
---
## 2. V23 개발 계보 요약
V23은 V1부터 22번의 반복 개선 끝에 도달한 최종 버전이다.
| 버전 | 핵심 발견 | 200d 성과 |
|------|-----------|-----------|
| V1-V3 | 초기 ORB 구조 실험 | -19% (regime 미적용) |
| V4-V7 | rolling loss filter, QQQ regime, min_candidate_breadth | +2~9% |
| V8 | weight_momentum=0.15 + QQQ threshold=0.0 | +19.73% |
| V9 | min_rvol=1.5 (momentum과 시너지) | +23.50% (400d) |
| V10 | trailing_at_r: 1.5→1.0 (더 일찍 트레일) | +33.17% (400d) |
| V11 | min_breakout_rel_vol=1.2 (돌파 거래량 확인) | +36.19% (400d) |
| V15 | streak_sizing + drawdown_governor + compound | +41.60% (200d) |
| V16 | max_gap_pct=0.10, simul=4, risk=0.035 | +71.01% (200d) |
| V17 | max_gap_pct=0.04, no_partial_exit, risk=0.04 | +84.36% (200d) |
| V18 | daily_reset 모드 전환, QQQ +0.15% filter, maxpos=0.80 | +103.50% (200d DR) |
| V19 | streak_win_bonus: 0.30→0.60 | +85.56% WR 60.2% |
| V21 | trailing_tighten_at_r: 2.5→2.0 | +97.25% (200d) |
| V22 | gov_threshold: 0.03→0.025, streak_bonus: 0.60→0.70 | +98.73% (200d) |
| **V23** | **min_atr_pct=0.04, maxpos: 0.80→0.70** | **+109.32% (200d 확정)** |
**V24-V32**: 9회 연속 실패 — V23이 daily_reset 국소 최적점임을 확정.
---
## 3. V23 핵심 변경사항 (from V22)
### 변경 1: `min_atr_pct: 0.04`
ATR-14 ÷ prev_close ≥ 4% 이상인 종목만 후보로 허용.
**근거**: 400d 거래 데이터 분석
- ATR/price 2-3%: WR 42.3%, 총 P&L 기여 -8%
- ATR/price 3-4%: WR 46.2%, 총 P&L 기여 -12%
- ATR/price 4-5%: WR 57.8%
- ATR/price >5%: **WR 62.4%, 총 P&L 기여 +104%**
에너지주/안정적 기술주처럼 변동성이 낮은 종목은 ORB 전략이 요구하는 **돌파 후 후속 추진력**이 없다. 이들을 걸러내면 WR이 크게 개선된다.
**효과**: 200d 수익률 +18.19pp, WR +0.1pp, DD 거의 동일
### 변경 2: `max_position_pct: 0.80 → 0.70`
ATR이 높은 종목은 개별 거래 변동성이 크다. 포지션 한도를 낮춰 포트폴리오 수준 DD를 억제.
**검증**:
- max_position_pct=0.75 + min_atr_pct=0.04: 400d DD -24.32% (**FAIL** 게이트 기준 -24% 초과)
- max_position_pct=0.70 + min_atr_pct=0.04: 400d DD -23.97% (**PASS** by 0.03pp)
### 두 변경의 시너지
min_atr_pct 단독: 400d DD -24.38% (게이트 실패)
max_position_pct 단독: 효과 미미
**함께**: 고품질 후보 선별 + 변동성 관리 → 시너지
---
## 4. 전략 파라미터 전체
```yaml
strategy_mode: orb
orb_strategy:
# === 엔진/기본 ===
engine_family: gainers_leader # 당일 강세주 추적 엔진
live_readiness: live_ready
entry_direction: long_only
orb_minutes: 5 # 9:30-9:35 첫 5분봉
sim_bar_minutes: 5
order_timeout_minutes: 45 # 9:40-10:25 진입 대기
# === 진입 허용 규칙 ===
allow_doji_breakout: true # 도지봉도 돌파 허용
allow_red_to_green_breakout: true # 갭하 후 반등도 허용
# === 후보 필터 ===
min_price: 10.0 # $10 이상
min_avg_dollar_volume: 25000000 # 평균 거래대금 $25M 이상
min_atr_14: 0.50 # ATR-14 절대값 $0.50 이상
min_atr_pct: 0.04 # ★ V23: ATR/price ≥ 4% (변동성 확인)
min_rvol: 1.5 # 상대 거래량 1.5배 이상
min_abs_gap_pct: 0.02 # 갭 2% 이상
min_premarket_dollar_vol: 1500000 # 프리마켓 거래대금 $1.5M 이상
max_gap_pct: 0.04 # 갭 상한 4% (V17에서 도입)
max_candidates: 20 # 후보 최대 20종목
max_candidates_per_sector: 3 # 섹터당 최대 3종목
min_candidates_to_trade: 1 # 최소 1종목 있으면 거래
# === 시장 레짐 필터 ===
min_candidate_breadth: 0.60 # 후보 60%가 양봉 돌파 조건 충족 시만 거래
market_regime_spy_threshold: 0.0015
market_regime_ticker: QQQ # QQQ 기준 레짐 판단
# QQQ 오픈 갭 > +0.15% → 거래 / ≤ 0.15% → 스킵 (V18에서 도입)
# === 롤링 손실 제한 ===
rolling_loss_days: 7 # 최근 7거래일
rolling_loss_threshold: -0.07 # 7일 누적 손실 -7% 이하 시 거래 중단
ticker_cooldown_days: 0 # 종목 재사용 쿨다운 없음
# === 포지션 관리 ===
max_simultaneous_entries: 3 # 동시 최대 3종목 진입
min_breakout_rel_vol: 1.2 # 돌파봉 거래량 ≥ ORB 이후 평균 1.2배 (V11에서 도입)
# === 후보 랭킹 가중치 ===
weight_rvol: 0.35 # 상대 거래량 35%
weight_gap: 0.20 # 갭 크기 20%
weight_dollar_vol: 0.05 # 당일 거래대금 5%
weight_premarket_dollar_vol: 0.25 # 프리마켓 거래대금 25%
weight_body_ratio: 0.0 # 캔들 몸통 비율 미사용
weight_momentum: 0.15 # 5일 모멘텀 15% (V8에서 도입)
# === 리스크 관리 / 스탑 ===
atr_stop_multiplier: 0.75 # 진입 후 스탑: 진입가 - 0.75×ATR
breakeven_at_r: 1.0 # 1R 도달 시 본전 스탑으로 이동
trailing_at_r: 1.0 # 1R 도달 시 트레일링 활성화 (V10에서 도입)
trailing_stop_atr_multiplier: 0.8 # 트레일링 스탑: 고점 - 0.8×ATR
trailing_tighten_at_r: 2.0 # 2R 도달 시 트레일 조임 (V21에서 2.5→2.0)
trailing_stop_atr_multiplier_tight: 0.3 # 조인 트레일: 고점 - 0.3×ATR
partial_exit_at_r: 99.0 # 사실상 부분 청산 없음 (V17에서 제거)
partial_exit_pct: 0.50
# === 사이징 ===
risk_per_trade_pct: 0.05 # 거래당 리스크 5%
max_position_pct: 0.70 # ★ V23: 일일 예산 대비 최대 포지션 70%
daily_max_loss_pct: 0.05 # 일별 최대 손실 5%
max_stops_per_day: 5 # 하루 최대 스탑아웃 5회
exit_minutes_before_close: 5 # 장 마감 5분 전 강제 청산
# === drawdown 거버너 ===
drawdown_governor_threshold: 0.025 # 피크 대비 -2.5% 이상 DD 시 사이징 축소 시작 (V22에서 0.03→0.025)
drawdown_governor_min_scale: 0.30 # DD 시 최소 30%까지 사이징 축소
# === 스트릭 사이징 ===
streak_sizing_win_bonus: 0.70 # 연승 시 70%씩 사이징 증가 (V22에서 0.60→0.70)
streak_sizing_max: 2.5 # 최대 2.5배까지
# === 실행 모드 ===
slippage_bps: 5.0 # 백테스트 슬리피지 5bp
initial_capital: 10000 # 초기 자본 $10,000
compound_returns: false # 단리 모드
daily_budget_reset: true # 매일 $10k 기준으로 사이징 리셋
settlement_days: 1 # 백테스트: T+1 결제 (라이브에선 0으로 오버라이드)
universe:
source: midlarge # mid+large cap 유니버스 (S&P400 + S&P500)
```
---
## 5. 후보 선별 메커니즘
### 5.1 프리마켓 스크리닝 (09:20 ET)
1. **유니버스 로드**: midlarge universe (S&P 400 + S&P 500)
2. **일봉 데이터 수집**: Oracle `/api/v1/price/data` 경유
3. **기본 필터**:
- min_price ≥ $10
- min_avg_dollar_volume ≥ $25M
- min_atr_14 ≥ $0.50
- **min_atr_pct ≥ 4%** (V23 신규)
4. **프리마켓 데이터**:
- Oracle snapshots API로 프리마켓 갭, 거래대금 수집
- min_abs_gap_pct ≥ 2%, max_gap_pct ≤ 4%
- min_premarket_dollar_vol ≥ $1.5M
5. **랭킹**: rvol(0.35) + gap(0.20) + dollar_vol(0.05) + premkt_dollar_vol(0.25) + momentum(0.15) 가중합
6. **상위 20종목**, 섹터당 최대 3종목
### 5.2 ORB 감지 (09:40 ET)
1. **인트라데이 9:30-9:35 5분봉** 수집 (Oracle 경유)
2. **ORB 레벨 확정**: 첫 5분봉 고가(breakout level)
3. **레짐 체크**:
- QQQ 오픈 갭 > 0.15% 이어야 거래
- 후보 중 60% 이상이 양봉 조건 충족해야 거래
4. **롤링 손실 체크**: 최근 7일 누적 -7% 초과 시 거래 스킵
### 5.3 돌파 감지 (09:40~10:25, 5분 간격)
- 현재가 > ORB 고가 → 진입 트리거
- **min_breakout_rel_vol ≥ 1.2**: 돌파봉 거래량 ≥ ORB 이후 평균 거래량 × 1.2배
- 동시 최대 3종목
- 45분 이내 미진입 → 자동 만료
---
## 6. 포지션 관리 메커니즘
### 스탑 로직 (orb_simulator.py:477-580 미러링)
```
진입 후:
초기 스탑 = 진입가 - 0.75×ATR
1R 도달 시 (수익 = 리스크×1):
스탑 → 본전 (breakeven_at_r=1.0)
트레일링 활성화
트레일링 중:
스탑 = max(현재 스탑, 최고가 - 0.8×ATR)
2R 도달 시 (trailing_tighten_at_r=2.0):
스탑 = max(현재 스탑, 최고가 - 0.3×ATR) ← 더 빠듯하게 조임
강제 청산: 15:55 ET
```
### 사이징
```python
# daily_budget_reset=true: 매일 initial_equity($10k) 기준
daily_budget = 10,000 # (compound_returns=false, 단리)
# 기본 사이징
risk_amount = daily_budget × risk_per_trade_pct(0.05) = $500
position_size = risk_amount / (ATR × atr_stop_multiplier)
max_dollars = daily_budget × max_position_pct(0.70) = $7,000
actual_position = min(position_size, max_dollars)
# drawdown 거버너 조정
# DD > 2.5% 시 0.30~1.0 스케일 적용
# 스트릭 사이징 조정
# 연승 시 +70%씩 증가, 최대 2.5배
```
---
## 7. 검증 결과
### TRUE BASELINE (확정, 2026-04-20)
200d 백테스트 (`intraday_20260420_203705_99ded639.json` + 재확인 `5597b16d`):
| 지표 | 수치 |
|------|------|
| **수익률** | **+109.32%** |
| **승률 (WR)** | **58.1%** |
| **Sharpe** | **3.01** |
| **최대 DD** | **-12.91%** |
| **거래 수** | **160건** |
> 참고: 이전 기록 +116.92%는 데이터 파이프라인 버그(AH 클로즈 포함) 결과임. 정식 기준치는 +109.32%.
### 400d 검증
| 지표 | V22 | V23 | 게이트 |
|------|-----|-----|--------|
| 수익률 | +89.62% | **+120.87%** | ≥88% ✓ |
| WR | 52.2% | **57.7%** | ≥52% ✓ |
| DD | -20.93% | -23.97% | ≥-24% ✓ (0.03pp 마진) |
| Sharpe | 1.67 | **1.94** | |
| 거래 수 | 312건 | 286건 | |
### 분기별 400d 성과 분포
| 기간 | 수익률 |
|------|--------|
| 2024-Q3 | -4.4% |
| 2024-Q4 | +1.2% |
| 2025-Q1 | -8.4% |
| 2025-Q2 | +13.0% |
| 2025-Q3 | **+42.4%** |
| 2025-Q4 | +11.0% |
| 2026-Q1 | **+35.2%** |
2024-Q3 및 2025-Q1 손실은 변동성 높은 매크로 환경에서 발생. 전략이 2024-2026 AI/crypto/biotech 모멘텀 레짐에 최적화되어 있음.
---
## 8. 리스크 관리
### 8.1 다층 리스크 필터
| 단계 | 필터 | 용도 |
|------|------|------|
| 종목 선별 | min_atr_pct ≥ 4% | 저변동성 drag 종목 제거 |
| 시장 레짐 | QQQ 갭 > 0.15% | 플랫/하락장 스킵 |
| 후보 품질 | breadth ≥ 60% | 분산된 강세 확인 |
| 롤링 손실 | 7일 -7% | 연속 손실 후 거래 중단 |
| 돌파 확인 | breakout_rel_vol ≥ 1.2 | 허위 돌파 제거 |
| 거버너 | DD > 2.5% → 사이징 축소 | 자본 보호 |
| 회로 차단기 | DD > 25% → 세션 정지 | 극단적 손실 방지 |
### 8.2 계좌 수준 회로 차단기
`apps/orb_trader/engine.py:46`:
```python
_ACCOUNT_CIRCUIT_BREAKER_PCT = 25.0
```
피크 대비 25% 이상 DD 시 해당 세션의 모든 거래 정지.
### 8.3 알려진 한계 (CRITICAL)
**600d 백테스트**: +31.16%, DD **-51.25%**
V23은 2024-2026 고ATR 모멘텀 레짐(AI/crypto/biotech)에 맞춰 최적화됨. 2023년 후반 이전 기간을 포함하면 DD가 -51%로 급증. 시장 레짐이 바뀌면 전략 성과가 크게 저하될 수 있음.
**레짐 변화 신호 모니터링 권장**:
- 7일 롤링 WR이 40% 미만으로 하락하면 전략 효능 의심
- 연속 3일 이상 "no candidates" 발생 시 레짐 체크
---
## 9. 라이브 배포
### 인프라
| 항목 | 값 |
|------|-----|
| DB | `data/paper/orb.db` |
| 세션 ID | `e492695e` |
| 세션명 | V23 ORB Gainers |
| 초기 자본 | $10,000 |
| 상태 파일 | `data/paper/.orb_auto_state.json` |
| 데몬 | `apps/orb_trader/daemon.py` |
### 일별 스케줄 (ET)
| 시간 | 동작 |
|------|------|
| 09:20 AM | `run_pre_screen()` — 일봉 + 프리마켓 스크리닝 |
| 09:30-09:35 AM | ORB 윈도우 (5분봉 형성) |
| 09:40 AM | `run_orb_detection()` — 인트라데이 바 → 후보 확정 |
| 09:40-10:25 AM | `run_breakout_check()` 매 5분 — 돌파 감지 + 진입 |
| 09:40-15:55 PM | `run_stop_check()` 매 5분 — 스탑/트레일링 체크 |
| 03:55 PM | `run_eod_exit()` — 전체 포지션 청산 |
| 04:00 PM | `run_post_close()` — 일별 스냅샷 기록 |
### Oracle 의존성 (CRITICAL)
**Oracle 서버** (`stock-oracle` 프로젝트, 로컬 `localhost:18001`)가 **09:20 ET 이전에 반드시 실행 중**이어야 한다.
- `AlpacaBroker.get_bars()` → Oracle `/api/v1/price/data`
- `AlpacaBroker.get_intraday_bars()` → Oracle
- Oracle 없이: 바 데이터 수집 실패 → 후보 0개 → 거래 없음
- **Alpaca SDK 폴백 없음** — Oracle이 유일한 데이터 경로
`run_pre_screen()` 시작 시 Oracle 헬스 체크 자동 실행 (3초 타임아웃). 미응답 시 로그에 CRITICAL 경고.
---
## 10. 소진된 개선 축 (참고용)
V23이 local optimum임을 보여주는 실패 기록. 이 축들은 더 이상 탐색할 필요 없음.
### 파라미터 스윕 (V24, 17개 변형)
- trailing/risk/governor/streak/atr_stop/rvol 조정 → 전부 -2pp 이상 열화
- min_atr_pct 0.05: 과필터 (+79%)
- min_atr_pct 0.03: 불충분 (+88%)
### 유니버스 변형
| 유니버스 | 200d | 판정 |
|----------|------|------|
| midlarge (현재) | +109.32% | CHAMPION |
| largecap | +28.1% | FAIL |
| midcap | +33.3% | FAIL |
| smallmid | +2.1% | FAIL |
| sp500 | +1.3% | FAIL |
### 레짐 필터 추가 시도 (V24 regime kill-switch)
- QQQ 50d/20d 트렌드 필터
- VIX max 25
- rolling 30일 -7%/-5% 손실 필터
- 결론: 2024년 나쁜 날들은 어떤 관측 가능한 신호로도 미리 구분 불가. 필터 추가 무의미.
### ORB 타임프레임
- 10분봉: -18.87% (재앙)
- 15분봉: -11.14% (재앙)
→ 5분봉이 유일한 최적점
### 기타 전부 실패
- compound 모드: DD -24.74% (게이트 실패)
- VWAP 확인/청산: 중립 또는 마이너스
- 진입바 클로즈 진입: -22.80pp (재앙)
- 부분 청산 1.5R/50%: 마이너스 (V17에서 제거)
---
## 11. 실행 명령어
### 백테스트
```bash
# 200d 공식 백테스트
.venv/bin/python3 -m apps.intraday_bt.run \
--config configs/intraday/strategies/orb_gainers_v23.yaml \
--days 200
# 최근 30일 sanity check
.venv/bin/python3 -m apps.intraday_bt.run \
--config configs/intraday/strategies/orb_gainers_v23.yaml \
--days 30
# 400d 검증
.venv/bin/python3 -m apps.intraday_bt.run \
--config configs/intraday/strategies/orb_gainers_v23.yaml \
--days 400
```
### 라이브 상태 확인
```bash
# 데몬 상태 확인
python -m apps.web.orb_trading_service status
# 최근 로그
tail -50 data/paper/orb_daemon.log
# DB 조회 — 오늘 거래
python -c "
import sqlite3
conn = sqlite3.connect('data/paper/orb.db')
rows = conn.execute('SELECT * FROM trades ORDER BY entry_time DESC LIMIT 20').fetchall()
for r in rows: print(r)
"
```
### 코드 검증
```bash
python -m py_compile \
apps/intraday_bt/run.py \
libs/intraday/orb_simulator.py \
apps/orb_trader/engine.py
pytest -q tests/unit/intraday/
```
---
## 12. 다음 단계 (미래 연구)
V23은 현재 아키텍처 내의 최종 버전이다. 추가 개선은 **근본적으로 다른 전략 아키텍처**를 필요로 한다:
- VWAP deviation 전략 (개장 후 VWAP 이탈 포착)
- Opening Range Reversal (ORB 실패 후 반전)
- 뉴스 데이터 통합 (현재는 프리마켓 거래대금으로 proxy 사용)
- 멀티 타임프레임 확인 (1분봉 엔트리 + 5분봉 필터)
이들은 V23의 파라미터 튜닝이 아닌 새 연구 트랙으로 진행해야 한다.