001-profit-gated-time-stop (v13.3)

Question

fixed_70_30_180 의 기계적 max_hold 가 winner/loser 를 똑같이 자르는 문제를 profit-gated time stop 이 완화할 수 있는가?

Hypothesis

max_hold 도달 시점의 현재 수익률 에 따라 분기하면 risk-adjusted return 이 개선된다:

  • 수익 ≥ +20%: 추가 hold (winner 는 더 달릴 확률)
  • 수익 < 0%: 즉시 청산 (loser 는 기다릴 이유 없음)
  • 0 ~ +20%: 기존 max_hold

→ v11 best (ens_v51 × fixed_70_30_180 OOS Sharpe 2.34) 대비 OOS Sharpe 개선 혹은 MDD 축소.

Method

  • Universe: V3-p3 (snapshot)
    Base: ATH DD ≤-95%, cash/MCap ≥ 2.0, MCap ≥ 3 at trade-level (현 engine 구조 유지)
  • Entries (5): bb_20, bb_30, hammer, bb_pullback_12, ens_v51 — v11 공통
  • Baseline exit: fixed_70_30_180 (TP 70%, SL -30%, 180d)
  • PGT variants (4):
    Variantmax_daysextend_daysprofit_threshold
    pgt_180_30_2018030+20%
    pgt_180_60_2018060+20%
    pgt_180_30_1018030+10%
    pgt_365_60_3036560+30%
  • TP 70% / SL -30% 는 baseline 과 동일하게 고정
  • Portfolio: initial $100k, 12.5% 포지션, concurrent 8, cooldown 90d, slippage 0.5% 편도
  • Period: 2016-01-01 ~ 2024-12-31, OOS 시작 2024-01-01

Running

cd /Users/martian/agents/offclaw-lucky/projects/biolode-backtest
python3 research/threads/exit/experiments/001-profit-gated-time-stop/run_experiment.py

Results

Runtime 61s. 5 entries × 5 exits (1 baseline + 4 pgt variants) = 25 configs. Universe 58 unique symbols (avg 2.7/month over 114 months).

Per entry — baseline vs best PGT variant

EntryBaseline OOS ShBest PGTPGT OOS ShΔSharpeΔMDD
bb_201.56pgt_365_60_301.54−0.020
bb_300.81pgt_180_30_200.810.000
hammer1.53pgt_180_30_101.62+0.09−0.4pp
bb_pullback_120.99pgt_180_30_200.990.000
ens_v512.34pgt_180_30_102.38+0.03+0.0pp

Best overall

ens_v51 × pgt_180_30_10 — OOS Sharpe 2.38, MDD −11.8%, 31 trades (OOS).

Baseline ens_v51 × fixed_70_30_180 OOS Sharpe 2.34 → Δ +0.04 (미미).

Exit reason 분포 (ens_v51)

reasonfixed_70_30_180pgt_180_30_10차이
take_profit2425+1 (extension 중 TP 도달)
stop_loss10100
max_hold72max_hold 7개가 분화
max_hold_extended3새로 생긴 extension hold
time_stop_early1손실 중 조기 청산

→ 41 trades 중 34 개 (83%) 가 TP/SL 로 이미 처리. PGT 는 max_hold 도달 7 trades sub-population 에만 영향. 그중 3 개가 extension 으로 TP 추가 달성, 1 개가 early exit 으로 손실 확정, 2 개는 여전히 max_hold.

Conclusion

Hypothesis 부분 확인 — 작지만 양의 효과. KPI 기준 🟡 Acceptable (통계적 동등, 개선 폭 <+0.15).

근본 원인: TP 70% / SL -30% 조합에서 대부분 trade 가 max_hold 도달 전 TP/SL hit → PGT 의 분기 로직이 17% sub-population 에만 작용. 그 작은 슬라이스에서도 양방향 효과 (extension 으로 TP 증가 vs time_stop_early 로 조기 손실 확정) 로 희석.

차기 실험 후보 (이 실험이 제기한 open questions):

  1. 002-pgt-wider-max-hold — max_days 365/540 로 넓혀서 max_hold 도달 trade 비율 증가. Time-stop 로직 효과 더 드러날 가능성.
  2. 003-pgt-no-tp — TP 제거 or 대폭 상향 (TP 200%) 해서 time-stop 이 주 exit 이 되도록. PGT 순수 효과 측정.
  3. 004-pgt-hammer-deepdive — hammer entry 에서 PGT 개선 폭이 가장 큼 (+0.09). 왜? trade sample 이 hammer 에서 max_hold 도달 비율이 더 높은지 조사.
  4. 005-pgt-chandelier-combo — chandelier exit 위에 PGT 씌워 trailing + time-gated 복합.

결정: v13 에선 baseline 유지 (fixed_70_30_180). PGT 단독 채택은 데이터 부족 → 위 2~4번 실험으로 효과 재검증 후 재고.

Notes

  • simulate_profit_gated_time_exit 는 exit.py 끝에 추가, unit test 3 케이스 통과 후 이 실험에서 첫 사용
  • 4 variant 중 pgt_180_30_10 (낮은 threshold +10%) 가 가장 자주 winner — baseline vs extension 의 분기 임계를 낮추면 더 많은 trade 가 extension 혜택
  • 가장 높은 threshold (pgt_365_60_30) 는 ens_v51 에서 MDD 악화 (-14.1% vs 베이스 -11.8%) — 너무 공격적 extension 의 위험

Notes

  • simulate_profit_gated_time_exit 신규 구현 — biotech/backtest/engine/exit.py 끝에 추가
  • exit_reason 에 신규 3종 도입: time_stop_early, max_hold_extended (그리고 기존 take_profit/stop_loss/max_hold 유지)
  • 현 engine 은 price filter 를 trade-level 에서 적용. 새 thread-based 시스템이 성숙하면 universe-level 로 리팩토링 예정 (refactor plan Phase 4)