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):
Variant max_days extend_days profit_threshold pgt_180_30_20 180 30 +20% pgt_180_60_20 180 60 +20% pgt_180_30_10 180 30 +10% pgt_365_60_30 365 60 +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.pyResults
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
| Entry | Baseline OOS Sh | Best PGT | PGT OOS Sh | ΔSharpe | ΔMDD |
|---|---|---|---|---|---|
| bb_20 | 1.56 | pgt_365_60_30 | 1.54 | −0.02 | 0 |
| bb_30 | 0.81 | pgt_180_30_20 | 0.81 | 0.00 | 0 |
| hammer | 1.53 | pgt_180_30_10 | 1.62 | +0.09 | −0.4pp |
| bb_pullback_12 | 0.99 | pgt_180_30_20 | 0.99 | 0.00 | 0 |
| ens_v51 | 2.34 | pgt_180_30_10 | 2.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)
| reason | fixed_70_30_180 | pgt_180_30_10 | 차이 |
|---|---|---|---|
| take_profit | 24 | 25 | +1 (extension 중 TP 도달) |
| stop_loss | 10 | 10 | 0 |
| max_hold | 7 | 2 | max_hold 7개가 분화 |
| max_hold_extended | — | 3 | 새로 생긴 extension hold |
| time_stop_early | — | 1 | 손실 중 조기 청산 |
→ 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):
002-pgt-wider-max-hold— max_days 365/540 로 넓혀서 max_hold 도달 trade 비율 증가. Time-stop 로직 효과 더 드러날 가능성.003-pgt-no-tp— TP 제거 or 대폭 상향 (TP 200%) 해서 time-stop 이 주 exit 이 되도록. PGT 순수 효과 측정.004-pgt-hammer-deepdive— hammer entry 에서 PGT 개선 폭이 가장 큼 (+0.09). 왜? trade sample 이 hammer 에서 max_hold 도달 비율이 더 높은지 조사.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)