# 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의 파라미터 튜닝이 아닌 새 연구 트랙으로 진행해야 한다.