feat: adopt Phase 3 gate and paper-trade exit policy
Deploy / lint (push) Successful in 7s
Deploy / test (push) Successful in 56s
Deploy / deploy (push) Successful in 33s

Production strategy change based on the July 2026 backtest: paper trades now default to a 30-trading-day hold with the initial stop (classic momentum hold-and-rerank), while target and trailing exits remain available in Admin. The exit policy API/UI now carries hold_days and close_reason can be 'time'.

The activation confidence floor default is now 0/off because the gate ablation showed it added no per-trade edge while filtering out usable setups. Migration 015 clears stored activation_min_confidence and paper_exit_mode so the new defaults take effect; this intentionally resets Track Record comparability from this deploy.

Verification: 451 backend tests pass, ruff check app/ clean, frontend npm run build clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 15:20:34 +02:00
parent 29a61cb2ca
commit 1e82dfad7f
10 changed files with 224 additions and 43 deletions
+7 -5
View File
@@ -39,10 +39,9 @@ SUPPORTED_TICKER_UNIVERSES = {"sp500", "nasdaq100", "nasdaq_all"}
# Track Record's qualified stats. The outcome evaluator deliberately ignores
# these — every setup is evaluated so the gate itself can be validated.
#
# The core test is expected value (in R): probability-weighted asymmetry, so a
# fat-but-improbable target and a likely-but-thin one are both rejected. R:R and
# confidence are floors; high-conviction / clean-read / target-probability are
# optional tighteners (off by default — turn on to be more selective).
# The core selection is cross-sectional 12-1 momentum (top percentile of the
# universe, long-only). R:R and confidence are floors; high-conviction /
# clean-read are optional tighteners (off by default).
_ACTIVATION_FLOAT_KEYS: dict[str, str] = {
"min_momentum_percentile": "activation_min_momentum_percentile",
"min_rr": "activation_min_rr",
@@ -56,7 +55,10 @@ _ACTIVATION_BOOL_KEYS: dict[str, str] = {
ACTIVATION_DEFAULTS: dict[str, float | bool] = {
"min_momentum_percentile": 80.0,
"min_rr": 1.2,
"min_confidence": 55.0,
# 0 = off. The July 2026 gate ablation showed the confidence floor added
# nothing (identical net/trade with it removed, under both exit models)
# while cutting ~25% of qualified trades.
"min_confidence": 0.0,
"require_high_conviction": False,
"exclude_conflicts": False,
# On by default: a NEUTRAL ("no clear setup") recommendation isn't an