11 KiB
ORB Gainers Strategy Development And Validation
이 문서는 현재 ORB 전략 중 gainers_leader 계열을 어떻게 개발하고 검증하는지 정리한 운영 문서다.
목표는 단순하다.
Yahoo Finance Top Gainers처럼 당일 비정상 강세 종목을 시스템적으로 잡는다.- 장 초반 ORB 구조를 쓰되, 실제 edge는
압축 후 확장이 아니라same-day attention / catalyst / abnormal volume에서 찾는다. - 연구 helper 결과와 공식
run.py결과가 항상 같도록 검증한다.
이 문서는 “어떤 아이디어를 어떻게 실험하고”, “무엇을 official truth로 보고”, “어떤 함정을 피해야 하는지”를 남들이 그대로 따라할 수 있게 쓰였다.
1. 전략 의도
현재 ORB Gainers의 철학은 아래와 같다.
- 당일 강한 종목을 찾는다.
- 단순 compression setup보다
당일 갭,초반 거래량,프리마켓 거래대금이 중요하다.
- 단순 compression setup보다
- 09:35 이후의 ORB 구조를 이용해 진입한다.
- 첫 5분 봉 방향과 breakout 구조는 유지한다.
- 같은 날 관심이 몰린 종목만 남긴다.
- 명시적 뉴스 데이터가 없으므로
premarket dollar volume을same-day catalyst proxy로 쓴다.
- 명시적 뉴스 데이터가 없으므로
- 검증은
2026 Q1을 1차 test window로 본다.- 이 기간은 최근 구조를 반영하면서도 30일보다 충분히 길다.
2. 현재 공식 전략
공식 전략 파일:
현재 공식 파라미터의 핵심:
engine_family: gainers_leaderentry_direction: long_onlyorb_minutes: 5sim_bar_minutes: 5order_timeout_minutes: 45min_price: 10min_avg_dollar_volume: 25,000,000min_atr_14: 0.50min_rvol: 1.2min_abs_gap_pct: 0.02min_premarket_dollar_vol: 1,500,000max_gap_pct: nullmax_candidates: 12max_candidates_per_sector: 2min_candidates_to_trade: 1weight_rvol/gap/dollar_vol/premarket = 0.40 / 0.20 / 0.05 / 0.35atr_stop_multiplier: 0.5breakeven_at_r: 1.0trailing_at_r: 3.0trailing_stop_atr_multiplier: 0.3compound_returns: false
왜 이렇게 바뀌었는가:
- 예전
compression_breakout은 원래 의도와 맞지 않았다. 0.10 ATRstop은 너무 타이트해서 거의 바로 stop-out 됐다.premarket dollar volume을 강하게 쓰는 것이 Q1에서 가장 잘 작동했다.
3. Source Of Truth
ORB 개발에서 source of truth는 아래 순서다.
- 공식 전략 config
- 공식 단일 백테스트 실행기
- 연구 helper / lab
- 실험 결과물
runs/intraday_orb/...
중요:
- helper/lab은 빠른 연구용이다.
- 최종 성과와 전략 등록 판단은 반드시
apps.intraday_bt.run으로 다시 확인한다.
4. 현재 검증 기준
Primary Test
현재 primary test window는:
2026-01-02 ~ 2026-03-31
이 기간은 Q1 구간이며, 현재 ORB gainers 전략 개선은 이 구간을 기준으로 한다.
Secondary Sanity Check
추가 sanity check는:
--days 30최근 30거래일
이유:
- Q1만 좋고 최근 30일에서 activity가 0이면 전략이 죽은 상태일 수 있다.
- 반대로 최근 30일만 좋고 Q1 전체가 약하면 과적합 가능성이 높다.
5. 현재 공식 성과
공식 run.py 기준 최신 결과:
Q1 공식 검증
- 결과 파일: intraday_20260415_204341_9d8e4fee.json
- 기간:
2026-01-02 ~ 2026-03-31 - 결과:
+6.96%407 tradesSharpe 2.05Max drawdown -3.92%
최근 30일 공식 검증
- 결과 파일: intraday_20260415_204456_60bdfe03.json
- 기간:
2026-03-04 ~ 2026-04-15 - 결과:
+4.05%211 tradesSharpe 2.1530/30 days with trades
6. 개발 루프
현재 ORB gainers 개발은 아래 순서로 한다.
Step 1. 아이디어를 전략 언어로 번역
질문:
- “당일 리더를 찾는가?”
- “뉴스/촉매 proxy가 들어갔는가?”
- “큰 갭을 오히려 막고 있지 않은가?”
- “activity를 죽이는 규칙이 없는가?”
현재 유효했던 아이디어:
premarket dollar volume을same-day catalyst proxy로 사용gap + rvol + premarket attention랭킹0.5 ATR stop + 3R ATR trail
Step 2. Helper로 좁은 실험
빠른 실험은 orb_research.py의 research snapshot / tape cache를 재사용한다.
핵심은:
- full raw intraday를 매번 다시 읽지 않는다.
- 같은 Q1 구간을 여러 파라미터로 빠르게 비교한다.
최근 Q1 비교 결과 파일:
이 단계의 목적은:
- 최고의 parameter cluster를 빠르게 찾는 것
- official result를 확정하는 것이 아님
Step 3. Official run.py 재검증
helper에서 좋아 보여도 반드시 run.py로 다시 확인한다.
예시:
.venv/bin/python3 -m apps.intraday_bt.run \
--config configs/intraday/strategies/orb_gainers.yaml \
--start 2026-01-02 \
--end 2026-03-31
최근 30일 sanity:
.venv/bin/python3 -m apps.intraday_bt.run \
--config configs/intraday/strategies/orb_gainers.yaml \
--days 30
Step 4. 결과가 맞으면 config 업데이트
official result까지 확인된 뒤에만 전략 파일을 바꾼다.
7. 꼭 체크해야 할 함정
7.1 Helper와 run.py 결과가 다를 수 있다
실제로 한 번 발생했다.
원인:
run.py경로가ticker_sectors를 ORB simulator에 넘기지 않아서max_candidates_per_sector가 공식 백테스트에서 무시되고 있었다.- helper는 sector cap을 적용하고, official run은 적용하지 않아 결과가 크게 어긋났다.
수정 위치:
원칙:
- helper에서 좋은 결과가 나오면 official run으로 trade count부터 먼저 맞춰본다.
7.2 min_candidates_to_trade는 activity를 쉽게 0으로 만든다
예전 compression 전략이 최근 30일 0 trades였던 직접 원인 중 하나다.
원칙:
- gainers 계열에서는 기본적으로
min_candidates_to_trade = 1부터 시작한다.
7.3 max_gap_pct는 gainers 전략과 상충할 수 있다
top gainers 전략은 본질적으로 큰 움직임을 잡는 전략이다.
원칙:
- gainers 계열에서는
max_gap_pct를 보통null로 두고, - 대신
min_abs_gap_pct와min_premarket_dollar_vol로 품질을 걸러낸다.
7.4 0.10 ATR stop은 지나치게 타이트할 수 있다
실제 Q1 비교에서:
0.10 ATR은 매우 나빴다.0.50 ATR쪽이 명확히 우세했다.
원칙:
- gainers 계열은
0.10 ATR을 baseline으로 두지 않는다.
8. 어떤 축을 우선 튜닝할 것인가
가장 효율적인 튜닝 순서:
min_premarket_dollar_vol- ranking weights
weight_rvolweight_gapweight_premarket_dollar_vol
atr_stop_multipliertrailing_at_rtrailing_stop_atr_multipliermax_candidatesmax_candidates_per_sector
현재까지는:
premarket dollar volume이 가장 큰 설명력을 보였다.
9. Cache / Snapshot 구조
ORB 개발 속도를 위해 아래 캐시를 사용한다.
- raw daily cache: data/cache/daily
- raw intraday cache: data/cache/intraday
- research snapshot: data/cache/orb_research
- period metrics cache: data/cache/orb_eval
- prepared tape cache: data/cache/orb_tape
운영 원칙:
- helper 실험은 snapshot/tape를 적극 활용한다.
- official truth는 여전히
run.py결과다.
10. 권장 검증 명령
코드/회귀 검증
python -m py_compile \
apps/intraday_bt/run.py \
apps/intraday_bt/lab.py \
libs/intraday/orb_simulator.py
pytest -q \
tests/unit/intraday/test_run_helpers.py \
tests/unit/intraday/test_orb_lab.py \
tests/unit/intraday/test_orb_simulator.py
Q1 공식 백테스트
.venv/bin/python3 -m apps.intraday_bt.run \
--config configs/intraday/strategies/orb_gainers.yaml \
--start 2026-01-02 \
--end 2026-03-31
최근 30일 sanity
.venv/bin/python3 -m apps.intraday_bt.run \
--config configs/intraday/strategies/orb_gainers.yaml \
--days 30
Quick lab
python -u -m apps.intraday_bt.lab \
--config configs/intraday/strategies/orb_gainers.yaml \
--quick \
--beam-width 2 \
--output-dir runs/intraday_orb/lab/quick_orb_gainers
주의:
- lab 결과가 좋으면 반드시
run.py로 다시 확인한다.
11. 다음 개발자가 해야 할 일
다음 사람이 이어받으면 아래 순서로 하면 된다.
- 공식 config를 읽는다.
- Q1 official run을 먼저 돌린다.
- 최근 30일 sanity를 확인한다.
- 개선 아이디어는 먼저 helper로 좁게 비교한다.
- helper winner를 official
run.py로 검증한다. - trade count / return / sharpe가 helper와 공식 run에서 비슷한지 확인한다.
- 일치하면 config를 업데이트한다.
12. 현재 상태 요약
현재 결론은 이렇다.
compression보다gainers_leader가 전략 의도에 맞다.premarket dollar volume은 매우 중요한 품질 필터다.0.5 ATR stop + 3R ATR trail이 지금까지는 가장 실전적이다.- helper와 official run 차이는 반드시 의심하고 검증해야 한다.
- 현재 공식
ORB Gainers는:- Q1
+6.96% - 최근 30일
+4.05% - activity도 충분히 나온다.
- Q1