From c5f6b07a3e53834c0cacbc90ad3c324a174d8425 Mon Sep 17 00:00:00 2001 From: Dennis Thiessen Date: Tue, 30 Jun 2026 17:14:54 +0200 Subject: [PATCH] feat: extend take-profit sweep into the tail + clarify it ignores the target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avg R was still rising at the previous top level (+15%), so the optimum was off the table. Extend TP_LEVELS to 20/25/30% to reveal where letting winners run stops paying (it plateaus toward "just hold to the horizon close"). Also clarify in the panel that the take-profit model deliberately does NOT use the setup's S/R target — it's a standalone fixed-% exit; exiting at the target is the target-vs-stop model above. The two are complementary ends, not in conflict. Co-Authored-By: Claude Opus 4.8 --- app/services/backtest_service.py | 5 ++++- frontend/src/components/signals/BacktestPanel.tsx | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/services/backtest_service.py b/app/services/backtest_service.py index fac7393..147096d 100644 --- a/app/services/backtest_service.py +++ b/app/services/backtest_service.py @@ -322,7 +322,10 @@ def _bucket_stats(cands: list[dict]) -> dict: # Fixed take-profit levels (fractions) swept for the take-profit exit model. -TP_LEVELS = (0.04, 0.06, 0.08, 0.10, 0.12, 0.15) +# Extended into the tail so the avg-R peak/plateau is visible (it's where letting +# winners run stops paying). Note: this model ignores the setup's S/R target — +# it's a standalone fixed-% exit; exiting at the target is the target model. +TP_LEVELS = (0.04, 0.06, 0.08, 0.10, 0.12, 0.15, 0.20, 0.25, 0.30) def _take_profit_bucket(cands: list[dict], tp: float) -> dict: diff --git a/frontend/src/components/signals/BacktestPanel.tsx b/frontend/src/components/signals/BacktestPanel.tsx index d43fbad..f3dd116 100644 --- a/frontend/src/components/signals/BacktestPanel.tsx +++ b/frontend/src/components/signals/BacktestPanel.tsx @@ -248,7 +248,8 @@ export function BacktestPanel() { the stop, else exit at the {report.params.horizon_days}-day close. In R, so it compares to the target model above. Hit Rate = how often you'd have banked +X% (how far winners actually run) — no top-ticking, it's the level you'd really set. - ★ = best avg R. + The setup's own S/R target is not used here (exiting at that target is the model + above); this is a pure fixed-% exit. ★ = best avg R.