Promotion gates

The gates between every pipeline stage, in order — the fair-sample quick screen, the gauntlet, the research door into paper, the paper pool and its queue, and the sequential paper→live test with the deflated Sharpe, breadth and held-back checks — plus the Strict settings that restore the old gates, safety floors, reason codes and operator overrides.

A gate is the check a strategy must pass to move from one pipeline stage to the next. Gates are where Forven kills strategies. They are the mechanical answer to "is this edge real enough to risk the next thing", where the next thing escalates from compute, to simulation, to real capital.

This page is the reference for every gate, in the order a strategy meets them: what it checks, the default thresholds, what the Strict settings restore, the reason codes it returns, and how to override one when you genuinely disagree. The source of truth in the code is policy.py (evaluate_promotion); the numbers here are the defaults: the Default stance preset, the Fair sample quick screen, the Research door into paper and the Sequential test at paper → live.

Forven is a research tool. Gate thresholds describe how a strategy behaved on historical and simulated data. They do not predict future results, and nothing here is financial advice. Passing every gate is evidence of process discipline, not a promise of profit.

The stages and the three gates

The stages are quick_screen (Quick screen) → gauntlet → paper → live_graduated (Live). A strategy that leaves the pipeline goes to the graveyard: archived, rejected or backtest_failed. The public site simplifies the names to screen → gauntlet → candidate → live, where "candidate" is the paper stage. The app and the API use the real names.

(research_only, the old "Parked" lane, is retired. It survives only as a compatibility alias; strategies that can't be fairly tested are archived as untestable.)

GateTransitionCharacterWhat it protects
Quick-screen gatequick_screen → gauntletCheap triage on a fair sample, hard guardrailsCompute: don't spend robustness tests on broken or leaky strategies
Door into papergauntlet → paperNot broken, not leaky, not clearly losing; selection-bias checks recordedPaper slots: only working strategies forward-test
Paper→live gatepaper → live_graduatedForward evidence, plus every selection-bias checkReal capital: the bar is high

Between the door and paper sits the paper pool: at most 40 strategies paper-trade at once, and a strategy that passes the door while the pool is full waits in a queue.

Paper costs nothing, so the door into paper asks "is this strategy broken, leaky or clearly losing". Live risks money, so the paper→live gate asks for forward evidence that the edge is real, and that is where every check against luck and selection bias is enforced. That achievable-paper, strict-live split is the spine of the gate policy. The gauntlet page covers the robustness tests that feed both gates.

Why the door moved

Until the October 2026 gate plan, the door into paper also enforced the deflated Sharpe, the walk-forward fold rate, regime split, parameter jitter, the robustness score and the held-back test, and almost nothing reached paper. A forward audit showed those tests did not predict forward results. Paper risks no capital, so those checks now apply where capital is at stake: paper → live. Strict paper restores the old door.

Stance presets

Every threshold below belongs to a stance preset, chosen in Settings → Lab → Pipeline stance. A preset sets every gate in one move; editing any single knob afterwards flips you to Custom.

RelaxedDefaultStrictWhere it applies by default
Quick-screen minimum trades52030Quick screen, over the widened window
Quick-screen profit factor1.01.01.1Quick screen, whole window (both slices under Strict quick screen)
Gauntlet minimum robustness score203050Recorded at the door, enforced at paper → live
Gauntlet minimum Sharpe00.10.5Gauntlet entry from any stage but the quick screen
Required gauntlet testswalk-forwardwalk-forward + param jitter+ cost stressEach needs a saved verdict before paper
Walk-forward fold pass rate25%33%50%Recorded at the door, enforced at paper → live
Param-jitter pass rate40%50%60%Recorded at the door, enforced at paper → live
Paper→live: closed paper trades51050Fixed floors (pre-plan) rule only
Paper→live: days in paper71421Fixed floors (pre-plan) rule only
Paper→live: paper Sharpe (t-stat)01.01.0Fixed floors (pre-plan) rule only
Paper→live: live profit-factor floor1.21.51.5Paper → live, either rule

Presets relax the path to paper and keep the paper→live gate as the real filter. Several settings sit outside the presets, and no preset changes them: the quick-screen rule, widest window and OOS floor, the door into paper, the paper pool, the live-gate evidence rule and its minimums, the Deflated Sharpe gate, the baseline hurdle and the held-back test. Whatever a preset or custom value says, the safety floors still clamp it.

Restoring the pre-plan gates

The Strict stance preset only moves thresholds. Each part of the October 2026 gate plan has its own switch back:

Setting (Settings → Lab)DefaultThe pre-plan option
Quick-screen rule (Quick Screen (Step 1))Fair sampleStrict quick screen: a fixed window and split in-sample/out-of-sample checks
Door into paper (Door into paper)Research doorStrict paper: every check blocks paper, the held-back test runs before paper, a missing source-reconciliation reading blocks, and multi-coin paper strategies are off
Live gate evidence rule (Paper to Live gates)Sequential testFixed floors (pre-plan): the old minimum days, closed trades, paper Sharpe and paper profit factor, with no breadth requirement
Paper pool size (Paper pool)400: no cap (set the per-market and per-family caps to 0 as well)
Quarters held back (Research)12

Strict paper and Fixed floors are independent: choosing Strict paper leaves the live-gate rule as it is.

The quick-screen gate

The first and cheapest gate. Before a strategy may spend compute in the gauntlet, the quick screen triages its backtest. By default it uses the Fair sample rule (Settings → Lab → Quick Screen (Step 1) → Quick-screen rule), which judges a fair sample instead of a fixed slice:

  • The window widens to hold the trade floor. If the screen window holds fewer trades than the minimum, it doubles — from the default backtest window of 730 days to 1,460 — as far as stored history allows; older history is backfilled first. Quick-screen widest window sets the ceiling (1460 days; 0 = never widen). Only a strategy that trades less than about five times a year is left untestable.
  • The whole window is judged, in-sample and out-of-sample together. A strategy is rejected if, over the whole window, any of these is true (Default stance):
    • fewer than 20 trades (quick_screen.min_trades)
    • Sharpe not above 0 (quick_screen.min_sharpe)
    • profit factor below 1.0 (quick_screen.min_profit_factor)
    • total return below 0% (quick_screen.min_total_return_pct)
    • max drawdown above 30% (quick_screen.max_drawdown_pct)
  • The out-of-sample slice only has to avoid losing badly. Its Sharpe must be above −0.5 (Quick-screen OOS Sharpe above).
  • The in-sample/out-of-sample gap and ratio are recorded, not enforced. They appear in the pass message. On a short slice they mostly measure noise; walk-forward and the paper→live gate judge out-of-sample consistency on far more data.

Under either rule the quick screen still rejects implausible metrics (below) and the high-win-rate trap: a win rate above 60% needs a profit factor above 1.2. A strategy that never fired on the 900-bar look-ahead probe is probed again on a 3,600-bar walk before it is reported as unverifiable, and a leak found on the longer walk still rejects.

The quick-screen robustness floor is 0 by default, because the robustness score is earned inside the gauntlet. The win-rate floor is off: momentum and breakout families win 30–40% of the time and profit on payoff.

Strict quick screen restores the pre-plan screen: a fixed window, and the in-sample and out-of-sample slices judged separately. It rejects an in-sample Sharpe at or below 0.1, an IS/OOS Sharpe gap above 1.5 or a ratio above 3×, and a profit factor below the floor on either slice.

A strategy that declares a timeframe (_timeframe, or its idea's timeframe) is judged on that timeframe only. An undeclared one is judged on its best-scoring timeframe.

Nothing measured is not a failure

Some screens can't judge a strategy at all. These are recorded as untestable, not as merit failures: the strategy is archived with status_reason = untestable:<code>: <why>, which skips the failure post-mortem and the negative learning a real failure records.

CodeWhenArchived as
zero_tradeNo trades at all in the quick-screen windowuntestable:no_signal
insufficient_tradesFewer trades than the minimum (20 by default), even on the widest windowuntestable:no_signal
data_quality_holdThe metrics contradict themselves, for example a zeroed in-sample leg beside an active out-of-sample leguntestable:data_quality_hold

Other untestable: codes you may see in the graveyard include broken_code, insufficient_history, retries_exhausted and max_demotions. The Forge shows them under the Untestable cause. Recovering an untestable strategy from the graveyard re-runs the intake checks.

Implausible metrics

A defense-in-depth guard rejects metrics that are too good: any Sharpe ≥ 5.0 or profit factor ≥ 8.0 (quick_screen.max_plausible_sharpe, quick_screen.max_plausible_profit_factor). On honest crypto data these are the signature of a look-ahead leak, such as a stray .shift(-1). The same guard runs again at the door into paper. If a strategy looks too good to be true, Forven assumes it cheated.

The OOS aliasing trap

A strategy with no distinct out-of-sample data has zero validation, not full validation. The quick screen never treats in-sample as out-of-sample. Under the fair-sample rule the whole window is judged as one sample and the out-of-sample check applies only to a distinct out-of-sample slice. Under Strict quick screen the split checks need a distinct out-of-sample slice; without one, only the basic return, drawdown and Sharpe triage runs. Either way, the walk-forward in the gauntlet is what tests the edge on data the parameters never saw. Trust OOS metrics, never IS.

Fitness scoring

Every backtest also gets a fitness score from 0 to 100, used to rank strategies and as a promotion signal out of quick_screen.

FactorWeightNotes
Sharpe30%Maxes out at a Sharpe of 3.0
Win rate20%
Profit factor20%Maxes out at a PF of about 3.3 (fitness_min_profit_factor + 2.0)
Max drawdown15%Penalty reaches 0 at the configured drawdown limit
Trade count15%Bonus scales toward a 20-trade baseline (quick_screen.fitness_min_trades)

Fitness is shape-aware: the scorer subtracts penalties for weak fundamentals (a wide IS/OOS gap, too few trades, high drawdown), so a strategy can clear every floor and still score near zero. The conventional reading is ≥ 60 paper-eligible, ≥ 70 deploy-eligible, and < 40 a retirement candidate.

The gauntlet stage

The gauntlet runs every robustness test whatever the door settings: walk-forward, parameter jitter, regime split, Monte Carlo and cost stress, after a timeframe sweep, an optimization and a confirmation backtest. Each test must save a verdict (pass or fail) before the door is judged; a test that errored is re-run, never counted. Under the research door, a FAIL is recorded and carried forward to paper → live instead of ending the run. A strategy still fails the gauntlet when it misses one of the door's floors below.

The paper gate (gauntlet → paper)

After a strategy survives the gauntlet, this gate, which Settings calls the door into paper, decides whether it earns a paper trading seat. By default it is the Research door (Settings → Lab → Door into paper → Door into paper): it admits a strategy that is not broken or clearly losing, and records the selection-bias checks instead of blocking on them. Recorded checks show in the pass message ("recorded for the live gate: …") and on the strategy, they rank the paper queue, and the paper→live gate enforces them. Strict paper enforces every check here, as before the gate plan.

CheckResearch door (default)Strict paperSetting
Confirmation trades≥ 20≥ 20 (the gauntlet minimum)Research door: min confirmation trades; gauntlet.min_trades
Total return≥ 0%≥ 0%gauntlet.min_total_return_pct
Max drawdown≤ 30%≤ 30%gauntlet.max_drawdown_pct
OOS profit factor≥ 1.0≥ 1.05Research door: min OOS profit factor; gauntlet.min_oos_profit_factor
OOS SharpeAbove 0Not checked hereResearch door: OOS Sharpe above
Implausible metricsSharpe ≥ 5 or PF ≥ 8 rejectsSamequick_screen.max_plausible_*
Monte Carlo tail drawdown95th percentile ≤ 40%Samegauntlet.mc_max_dd_p95
Cost stressMust not lose under 2× costs (stressed Sharpe above 0); the full verdict is judged at paper → liveThe verdict blocks when cost stress is a required testrobustness_thresholds.cost_stress_*
Required testswalk_forward and param_jitter must have a saved verdict; a FAIL is recordedMust pass, with fresh evidencegauntlet.required_tests
Walk-forwardRecorded≥ 2 judgeable folds, ≥ 33% of folds OOS-positivegauntlet.wfa_min_folds, robustness_thresholds.wfa_fold_pass_rate_min
Parameter jitterRecorded≥ 50% of reruns passrobustness_thresholds.param_jitter_pass_rate_min
Regime split, Monte Carlo verdictsRecorded; judged at paper → liveBlock when they are required testsgauntlet.required_tests
Robustness scoreRecorded≥ 30 / 100gauntlet.min_robustness_score
Deflated SharpeRecorded (bar 0.90)≥ 0.90robustness_thresholds.min_deflated_sharpe
Baseline hurdleMeasured and shown; does not block (observe)Samegauntlet.wfa_baseline_hurdle_paper
Held-back testRuns at paper → liveOne-shot test, pass required, runs lastHeld-back test runs at
Source reconciliationA measured divergence over 2% blocks; a missing reading doesn'tA missing reading blocks toodata_engine_settings.source_reconciliation

In the research door each recorded check can also be switched back to enforce on its own, in the pipeline config (for example "paper_door": {"deflated_sharpe": "enforce"}).

The gauntlet's entry guardrails, for a strategy entering from any stage but the quick screen, also reject the shape of a martingale curve: a win rate above 70% paired with a profit factor below 1.5.

Promotion into paper is automatic by default. The pipeline promotion mode is auto, so a strategy that passes takes a paper slot on its own, or waits in the paper queue when the pool is full; the Approvals page shows "Gauntlet → paper: Automatic". Switch to manual review there if you want to approve each one.

Deflated Sharpe gate

Strategies are optimized before they are validated, and the best of many tries always looks better than it is. The deflated Sharpe ratio (DSR) is the probability that a Sharpe is real after accounting for how many variants were tried. See metrics for how trials are counted.

The DSR gate is on by default and its bar is still 0.90. Where it bites depends on the door:

  • Research door (default). The DSR is computed and recorded at gauntlet → paper, where it ranks the paper queue. It is enforced at paper → live, computed on the backtest trades plus the strategy's forward paper trades.
  • Strict paper. It rejects below 0.90 at gauntlet → paper, as before the gate plan.

Existing installs had the gate switched on once at startup after updating; if you turn it off, it stays off. The settings live in Settings → Lab → Robustness Gauntlet (Step 2):

SettingDefaultWhat it does
Deflated Sharpe gateOnEnforce the minimum: at paper → live under the research door, at gauntlet → paper under Strict paper
Min Deflated Sharpe0.9The floor (a probability; about 0.95 is conventional significance)
DSR trade scopeWhole confirmation windowEvery trade of the confirmation backtest, in-sample and out-of-sample. "OOS tail only (legacy)" scores just the recent tail
DSR swarm-trials factorOnMultiplies the trial count by failed sibling strategies from the same family and asset
DSR swarm lookback90 daysHow far back failed siblings count (0 = all)
DSR swarm scopeSame search originCount only siblings from the candidate's own origin (AI Drop Zone, in-app agents, or another source). "All origins (legacy)" counts every one

If the DSR can't be computed (for example the per-trade returns were never stored), the research door records "not computable" and moves on; the gate that enforces it blocks with dsr_unavailable. That is missing evidence, never grounds for archiving: re-running the backtest resolves it.

Different bars on screen

The strategy page's Deflated Sharpe card still calls the DSR "advisory" and draws a 0.95 "conventional bar", and The Forge's DSR column tooltip says "≥0.95 significant". The Settings caption for Deflated Sharpe gate still describes the gauntlet → paper hop. The gate itself is on, rejects below 0.90, and by default bites at paper → live.

The held-back test

The held-back test (Settings calls it the research holdout) keeps the most recent market data away from research entirely. By default the cutoff is the start of the current quarter minus one quarter, so 3–6 months are always held back, and the oldest held-back quarter is released at each quarter start. (Before the gate plan it held back two quarters. A one-time startup step moved a stored 2 to 1; if you set 2 again, it stays.) Every backtest, walk-forward, optimizer run and agent read ends at the cutoff. Paper and live trading are never sealed.

Each candidate gets one walk-forward whose out-of-sample period is exactly the held-back data. Under the research door it runs when the strategy applies for live: automatically, once every other paper→live check passes, as the last check. Under Strict paper, or with Held-back test runs at set to Gauntlet to paper, it runs once every other paper check passes, before paper. A pass needs:

  • at least 5 trades in the held-back period,
  • a net profit over it, and
  • no failed baseline hurdle on it.

The verdict is never re-run for the same parameters, and each test spends from a per-family budget (3 tests per strategy family per quarter). Running it at paper → live means the budget is spent on genuine live candidates, not on research. Strategies created before the holdout was switched on have already seen the data, so they are exempt and judged on forward results.

Settings → Lab → Research → Held-back data (research holdout):

SettingDefault
EnabledOn
CutoffRolls quarterly (automatic); or Fixed date (manual)
Quarters held back (3–6 months at 1)1
At the gate that runs it (paper→live by default)Enforce — a pass is required to move on (or Observe, or Off)
Min trades in the held-back period5
Tests per strategy family per quarter (0 = no cap)3

Which hop runs it is Held-back test runs at under Settings → Lab → Door into paper: Paper to live (default) or Gauntlet to paper. Strict paper always runs it before paper.

CodeKindMeaning
holdout_pendingevidenceThe test hasn't run yet, is running, or errored; the next promotion attempt submits or waits for it
holdout_budget_exhaustedevidenceThe family's tests for this quarter are spent. The strategy waits where it is (in paper by default, in the gauntlet under Strict paper) until the next quarterly roll
holdout_rejectmeritThe strategy failed on the held-back data

You see the result on the strategy page under Robustness → Held-back test, with badges PASSED, FAILED, RUNNING, NOT RUN YET, EXEMPT, WAITING FOR NEXT QUARTER, ERRORED or OFF, and a Run the one-shot test now button. In The Forge's graveyard, a failure shows the cause Held-back test. Manual Backtest windows end at the cutoff and say so.

Baseline hurdle

A strategy that only beats zero may just be riding the market. The baseline hurdle takes the out-of-sample returns of every walk-forward and removes what two free alternatives made over the same days with the same costs: buy-and-hold of the same asset and a fixed trend-following rule (a Carver-style EWMAC). What's left is the strategy's alpha. It shows on the strategy page's stress matrix as Beats baselines.

Setting (Settings → Lab → Robustness Gauntlet)Default
Baseline hurdle at gauntlet->paperObserve — measured and shown, never blocks
Baseline hurdle at paper->liveEnforce — blocks going live; the strategy stays in paper and nothing is archived
Baseline hurdle: min OOS alpha0 %/yr
Baseline hurdle: min alpha t-stat0 (off)
Baseline hurdle: min OOS days60 days — fewer is insufficient evidence and never blocks

A rejection carries baseline_hurdle_reject. Enforcing it at gauntlet → paper is possible, but the estimate is noisy (about ±13%/yr over two years of out-of-sample days), so some genuine strategies would be archived.

The paper pool

Passing the door doesn't always mean a paper seat right away. Paper is a managed pool, so a wide door can't swamp the scanner:

  • A cap. At most 40 strategies paper-trade at once (0 = no cap). Forty fits inside one hourly bar close on a 4-core machine with room left for the live scanner.
  • A diversity cap. At most 3 paper strategies per market (coin) and 10 per strategy family (0 = no cap). A multi-coin paper strategy counts under its home market.
  • A queue. A strategy that passes the door while the pool, or its market or family, is full waits in the paper queue with paper_queue_full, still in the gauntlet stage. The queue is ranked by the evidence the door recorded: deflated Sharpe, robustness score and out-of-sample Sharpe, plus the breadth test verdict when one exists (General ranks a strategy higher, Home coin only lower). A free slot goes to the best-ranked strategy first. Waiting is capacity, not a rejection: it never counts toward the repeated-failure auto-archive, and the hygiene sweep never archives a queued strategy. An entry not re-confirmed for 14 days drops off the queue.

Retirement

An hourly job, forven-paper-pool-tick, retires paper strategies whose forward record shows they are losing. A retired strategy is archived with status_reason = paper_retired:<why>, which frees its slot. By default a paper strategy is retired when:

  • losing: it has 15 or more closed forward trades with a negative average and a t-stat below −1;
  • drawdown: its forward drawdown reaches 15%;
  • idle: it hasn't traded for 60 days and has nothing open; or
  • sequential_fail: its sequential test fails, because its forward trades contradict its backtest or are significantly losing.

Live strategies are never retired here. After retiring, the job admits strategies from the queue, then starts one breadth test, paper strategies first. Strategies that were already in paper when you updated moved to these rules automatically.

Settings → Lab → Paper pool:

SettingDefault
Paper pool size40 strategies (0 = no cap)
Max paper strategies per market3
Max paper strategies per family10
Retire losing paper strategies automaticallyOn
Retire: min forward trades15
Retire: t-stat below−1
Retire: forward drawdown15%
Retire: idle days60 (0 = never)
Retire when forward contradicts backtestOn

To see occupancy, the queue and the door in force: python -m forven.agent paper-pool, or GET /api/lifecycle/paper-pool.

Multi-coin paper strategies

A paper strategy whose breadth test reads General also paper-trades the coins where its unchanged rule made money in that test, as one record: its home coin first, then the best Sharpe, up to 6 coins in all. The breadth test picks the list, never you, and the list is frozen once chosen, like the parameters. Each coin sizes on 1/N of the strategy's paper equity, so the strategy risks no more than it would on one coin, and trades closed on the same UTC day count as one day of evidence. Its forward record builds faster, without counting correlated coins as independent trades.

The quick screen, the gauntlet and the door judge the home coin only; the breadth result is what admits the other coins. Going live with several coins is held with multi_coin_live_review ("Multi-coin live review pending"): the strategy keeps paper trading until the live order path is reviewed for several coins.

In Settings → Lab → Paper to Live gates, Multi-coin paper strategies is on by default and Multi-coin: most coins per strategy is 6 (2–15). Strict paper turns multi-coin off.

The strict paper→live gate

This gate guards real money. A strategy in paper must build genuine forward evidence before it can reach live_graduated, and every check the door only recorded is enforced here. By default the forward evidence is judged by a sequential evidence test (Settings → Lab → Paper to Live gates → Live gate evidence rule: Sequential test (default) or Fixed floors (pre-plan)).

The sequential evidence test

The test waits until the strategy has at least 20 closed forward trades and 30 days in paper (Live gate: min forward trades, Live gate: min paper days). Until then it reads collecting. After that it is re-run after every forward trade and asks three questions:

  1. Does forward track the backtest? The forward per-trade Sharpe must not be significantly worse than the backtest's.
  2. Is the combined evidence significant for the size of the pool? Backtest and forward evidence are combined, with the backtest weighted 0.5 because it was selected and the forward trades were not. The result must clear a bar corrected (Šidák) for how many strategies were in paper over the last 90 days, at a 5% false-positive rate (Live gate: false-positive rate). A bigger paper pool raises the bar, so luck across many strategies is discounted.
  3. Is the forward edge positive? The forward Sharpe must be positive. The backtest can add weight to forward evidence but never stand in for it.

The states are collecting, continue (keep paper trading), go and fail. A strategy fails when its forward trades contradict its backtest or are significantly losing, and by default a fail also retires it from paper. Go never promotes anything by itself: every other check below, and your typed GO LIVE, still apply.

What the gate checks

CheckDefaultSetting
Forward warm-up≥ 20 closed forward trades and ≥ 30 days in paperpaper_trading.live_min_forward_trades, paper_trading.live_min_paper_days
Sequential evidence testReads goLive gate evidence rule
Breadth testA finished, current run whose verdict isn't Home coin onlyLive gate: require the breadth test (on)
Paper total return> 0%paper_trading.min_total_return_pct
Paper max drawdown< 15%paper_trading.max_drawdown_pct
Live profit-factor floor (historical OOS)≥ 1.5paper_trading.min_profit_factor_live
OOS Sharpe no more than 1.5× IS≤ 1.5paper_trading.max_oos_is_ratio
Robustness batteryWalk-forward, Monte Carlo, cost stress and regime split at their full thresholdspaper_trading.live_strict_robustness_enabled
Checks the door recordedWalk-forward fold rate ≥ 33%, jitter ≥ 50%, robustness score ≥ 30The gauntlet settings above
Deflated Sharpe≥ 0.90, on backtest plus forward tradesrobustness_thresholds.min_deflated_sharpe
Baseline hurdleEnforcedgauntlet.wfa_baseline_hurdle_live
Held-back testOne-shot, a pass is required; runs lastHeld-back test runs at

The breadth test runs the frozen rule unchanged on 15 coins. General, Mixed and Too few coins may go live; a missing or out-of-date run is started from the gate and keeps the strategy in paper (breadth_pending), which is not a merit failure. With paper_trading.live_strict_robustness_enabled on (the default), the gate re-enforces the full robustness battery instead of trusting the gauntlet's earlier verdicts. It also checks funding-data completeness and the source reconciliation. Only paper trades recorded by the current execution engine count, so an engine upgrade restarts paper warm-up. A multi-coin strategy's forward record is pooled per UTC day before any of these checks read it.

Fixed floors (pre-plan) replaces the forward warm-up, the sequential test and the breadth requirement with the old floors: at least 14 days and 10 closed paper trades, a paper Sharpe of at least 1.0 and a paper profit factor of at least 1.2 (Default stance; the stance presets move the first three). That paper Sharpe is a per-trade t-statistic (mean / stdev * sqrt(n)), a forward-edge proof rather than an annualized headline. Every other row of the table still applies. Under Strict paper the recorded checks and the DSR were already enforced at the door, so the live gate doesn't repeat them.

The strategy page's gate card shows this checklist as Paper Trading -> Live, and The Forge's peek drawer as Paper → live checklist. The gate also reports an allocation ramp (25% of size in weeks 1–2, 50% in weeks 3–4, 100% from week 5, halved when paper profit factor is under 2.0); the strategy page labels that ramp advisory, because the live sizer doesn't enforce it.

Strategies that were already live when the gate changed were checked once against it, report-only; nothing was demoted. Read the result with python -m forven.agent live-recheck.

Real capital is unforgiving. Treat a pass as permission to risk a small, capped allocation, not as a verdict that the strategy will be profitable. Paper is the supported mode; live/mainnet is unsupported and at your own risk.

Going live: what else must be true

Passing the paper→live gate isn't enough on its own.

  • Typed GO LIVE and a ceiling. Approving a strategy for live opens a dialog that needs a Per-asset notional ceiling (USD) (required) and the typed phrase GO LIVE. There is an Allow automatic go-live setting, off by default; turning it on needs a typed LIVE when you save. See approvals.
  • Live admission (LIVE-ADMIT-1). Going live is refused, even when forced, if another live strategy already trades the same coin on the same side (one wallet holds one position per coin, so the two would refuse each other's entries), or if a wallet couldn't hold the margin of every live strategy at once. The refusal names the strategy to demote first, or the deposit you'd need.
  • No stranded live trades (STRAND-1). A strategy holding open live positions can't be moved to any stage that doesn't manage live positions (paper, the gauntlet, the graveyard), even when forced. Close the positions first. A sweep also raises a critical risk alert for any live trade whose strategy is no longer live.

See going live safely for the operator checklist.

Safety floors

Safety floors are absolute rails clamped onto the gates. They bound how far a relaxed preset, a custom config or an automated caller can soften the path:

FloorDefaultClamps
min_trades3Trade count behind a →paper promotion
wfa_min_folds2Judgeable walk-forward folds
wfa_fold_pass_rate_min20%Walk-forward fold pass rate
param_jitter_pass_rate_min30%Parameter-jitter pass rate
mc_max_dd_p9550%Monte Carlo tail drawdown (a ceiling)
live_min_closed_trades3Closed paper trades behind a →live promotion, under either evidence rule
live_max_drawdown_pct25%Paper drawdown behind a →live promotion (a ceiling)

The walk-forward and jitter floors clamp those checks wherever they are enforced: at paper → live under the research door, at the door under Strict paper. The floors are editable in Settings → Lab → Safety floors. Set one to 0 (or a ceiling to 100%) to remove that rail. The live_* floors guard the real-money gate; loosen them with care.

Stale evidence is not evidence

A verdict is trusted only if it came from the same engine and the same data semantics in use today:

  • Engine provenance. Every verdict is stamped with the backtest engine version. When metric semantics change, older results go stale and the strategy is re-queued for validation. The gate blocks with stale_engine_artifacts until fresh evidence exists.
  • Data provenance. Every persisted backtest is fingerprinted with the semantics of its enrichment streams. If those change underneath (say a funding series switches cadence), the old verdict reads as missing evidence (stale_data_artifacts) and re-runs.

Neither counts against the strategy. Both are evidence-absence codes, not merit failures.

Other gates and guards

Phantom-container gate

A strategy with no backtest results has nothing to validate. The verification gate blocks any move to paper or live unless an operator forces it.

Failed gauntlets and demotion thrash

A gauntlet that fails the door is terminal: the strategy is archived to the graveyard, as a merit failure or, when nothing was actually measured, as untestable. Under the research door, a FAIL from a recorded test (walk-forward, jitter, regime split, Monte Carlo, cost stress) is not a door failure: it is carried to paper → live. Archiving is reversible: Recover from graveyard sends a strategy back to quick_screen. A strategy demoted from the gauntlet back to quick_screen for the third time is archived as untestable:max_demotions, so a strategy that never produces evidence can't loop forever.

Repeated-failure auto-archive

A strategy that genuinely fails the same gate five times is archived. Evidence-absence and capacity rejections never count toward the five: tests still running, stale evidence, paper warm-up, a pending held-back test, an uncomputable DSR, a full paper pool (paper_queue_full), a sequential test still collecting, a pending or Home-coin-only breadth test, or a multi-coin strategy waiting for the live review.

Decay kill-switch (live retirement)

Once a strategy is live, the decay tracker watches for degradation. If its Sharpe falls by ≥ 30% over its rolling window (live_graduated.decay_kill_switch_pct), it is retired to archived. Paper strategies are retired by the paper pool instead.

Source-reconciliation gate

Backtests and paper use Binance data while live orders go to Hyperliquid. This gate refuses a capital-stage entry when the two price series diverge by more than 2% for the strategy's market (data_engine_settings.source_reconciliation). A scheduled job computes the divergence. A measured divergence over the limit blocks both paper and live. A missing or stale reading no longer blocks paper under the research door; Strict paper restores that block. Going live with no fresh reading waits with source_reconciliation_pending rather than guessing; set block_when_missing to false only if you accept unknown divergence.

Slot competition and dethrone

When a strategy would duplicate an active one on the same market, the challenger must clearly beat the incumbent to raise a dethrone recommendation; otherwise the gate returns gate_contention (or duplicate_reject) and the challenger waits. A paper incumbent is protected until it has had a fair soak: at least 7 days, and up to 14 if it has fewer than 5 closed trades. Dethrones are approved automatically by default; the Approvals strip shows the current setting.

At the paper hop, one-strategy-per-market slot competition is off by default (One strategy per market (slot competition), Settings → System). The paper pool's per-market cap is what limits how many paper strategies share a coin.

Why is it blocked? Reading rejections

Every rejection carries a reason code. The pipeline board and The Forge classify it as evidence (something hasn't happened yet), merit (the strategy genuinely failed) or untestable (it couldn't be judged).

CodeKindMeaning
artifacts_pending, missing_evidenceevidenceA required test hasn't produced a persisted result yet
validation_in_flightevidenceA test is still running at gate time
stale_engine_artifacts, stale_data_artifacts, stale_validationevidenceEvidence predates the current engine or data; re-validation is queued
wfa_window_insufficientevidenceToo few judgeable walk-forward folds for the strategy's trade rate
insufficient_paper_evidenceevidencePaper warm-up hasn't reached its days or trades minimum
live_evidence_pendingevidenceThe sequential test is still collecting, or reads continue; keep paper trading
breadth_pendingevidenceThe breadth test hasn't finished on the current rule; the gate starts it
source_reconciliation_pendingevidenceNo fresh cross-venue divergence reading yet
dsr_unavailableevidenceThe DSR gate is on but the DSR couldn't be computed
holdout_pending, holdout_budget_exhaustedevidenceThe held-back test hasn't produced a verdict, or its quarterly budget is spent
paper_queue_fullcapacityPassed the door; waiting in the paper queue for a slot
breadth_home_only, multi_coin_live_reviewholdThe breadth test reads Home coin only, or a multi-coin strategy waits for the live review; it keeps paper trading and nothing counts against it
zero_trade, insufficient_trades, data_quality_holduntestableThe quick screen had nothing to judge; archived as untestable:*
overfitting_guardrailsmeritFailed the quick-screen checks
live_evidence_failmeritForward trades contradict the backtest or are significantly losing
holdout_rejectmeritFailed the held-back test
baseline_hurdle_rejectmeritNo alpha over buy-and-hold and the trend rule (blocks only where enforced)
gate_reject and specific *_reject codesmeritFailed a robustness or capital-gate threshold (for example sharpe_reject, drawdown_reject, wfa_reject)
gate_contention, duplicate_rejectslotThe market slot is held by an incumbent
operator_approval_required—The gate passed; the change is queued for your sign-off

A paper strategy retired by the pool isn't a gate rejection: it is archived with status_reason = paper_retired:<why>.

GET /api/lifecycle/strategies/{strategy_id}/explain returns the same classification for one strategy: its blockers, evidence ages, the action that would unblock it, and the next expected transition.

Operator overrides and approvals

Capital gates are hard. Automated actors can't force past them: if agent code passes force=true toward paper or live, the force is ignored. Only you can override a capital gate, through an explicit, informed-consent control. LIVE-ADMIT-1 and STRAND-1 can't be overridden at all.

Two mechanisms are easy to confuse:

  • Override bypasses the gate evaluation. You see the rejection, choose to override, and the override is logged as a warning for audit.
  • Approval is an item queued for sign-off in Approvals. Gauntlet → paper is automatic by default (promotion mode auto); switch to manual review and each promotion waits there. Paper → live always needs your typed GO LIVE with a per-asset ceiling, unless you have turned on Allow automatic go-live.

Steps: override a gate rejection

Open the strategy page from The Forge and click its stage pill. The Move to stage panel lists each option tagged Promote, Demote, Archive or Revive.

Pick the target stage. The confirm panel asks you to confirm the move, with an optional reason. Going to Live also asks for a notional ceiling (USD) and the typed phrase GO LIVE.

Click Confirm. If the gate rejects the move, the panel shows Promotion gate blocked this: with the exact reason. Read it and make sure the failure is marginal and understood.

Click Override gate & promote. The move and the override are both recorded in the activity log.

The same thing over the API:

# Why is it blocked, and what would unblock it?
curl.exe http://127.0.0.1:8003/api/lifecycle/strategies/$StrategyId/explain

# The full readiness checklist (and the paper→live variant)
curl.exe http://127.0.0.1:8003/api/lifecycle/strategies/$StrategyId/readiness
curl.exe http://127.0.0.1:8003/api/lifecycle/strategies/$StrategyId/paper-live-readiness

# Promote to paper with an explicit operator override
curl.exe -X POST http://127.0.0.1:8003/api/strategies/$StrategyId/promote `
  -H "content-type: application/json" `
  -d '{"to_status":"paper","override":true,"reason":"edge confirmed out-of-band"}'

An override into live_graduated must also carry "confirm": "GO LIVE" and a positive live_notional_ceiling_usd.

Tuning gate thresholds

The easy way is Settings → Lab: pick a stance preset, then adjust Quick Screen (Step 1), Robustness Gauntlet (Step 2), Door into paper, Paper pool, Paper to Live gates and Safety floors as needed. The held-back test is under Settings → Lab → Research. Behind the UI, thresholds live in the pipeline config under quick_screen.*, gauntlet.*, paper_door.*, paper_pool.*, paper_trading.*, robustness_thresholds.* and safety_floors.*. Drawdown and return values are stored as fractions (0.30 = 30%) and shown as percentages.

{
  "pipeline_preset": "custom",
  "quick_screen": {
    "rule": "fair_sample",
    "max_window_days": 1460,
    "min_oos_sharpe": -0.5,
    "min_trades": 20,
    "min_profit_factor": 1.0,
    "max_plausible_sharpe": 5.0
  },
  "gauntlet": {
    "min_robustness_score": 30,
    "required_tests": ["walk_forward", "param_jitter"],
    "min_oos_profit_factor": 1.05,
    "wfa_baseline_hurdle_paper": "observe",
    "wfa_baseline_hurdle_live": "enforce"
  },
  "paper_door": {
    "mode": "research",
    "min_trades": 20,
    "min_oos_profit_factor": 1.0,
    "min_oos_sharpe": 0.0,
    "holdout_stage": "live"
  },
  "paper_pool": { "max_strategies": 40, "max_per_market": 3, "max_per_family": 10 },
  "robustness_thresholds": {
    "deflated_sharpe_gate_enabled": true,
    "min_deflated_sharpe": 0.9
  },
  "paper_trading": {
    "live_gate_mode": "sequential",
    "live_min_forward_trades": 20,
    "live_min_paper_days": 30,
    "live_require_breadth": true,
    "multi_coin_enabled": true,
    "multi_coin_max_coins": 6,
    "min_profit_factor_live": 1.5
  },
  "safety_floors": { "live_min_closed_trades": 3, "live_max_drawdown_pct": 0.25 }
}

Two safety notes:

  • Floors clamp presets and custom values, but the floors themselves are editable. Changing one is a deliberate act; the live_* floors guard real money.
  • testing_mode never opens the capital gates. It bypasses the quick-screen and gauntlet gates for rapid iteration, but always enforces the paper and live gates.

A config that drops walk_forward from the required tests is repaired on load with a warning. See the configuration reference for precedence.

Caveats

  • If you script promotions, expect force=true toward a capital stage to be ignored.
  • A wide door means more paper strategies, so the sequential test raises its bar as the pool grows. A strategy that would have gone live from a small pool can wait longer in a big one.
  • A kill-switch reset re-baselines the high-water mark to current equity, which moves where future drawdown is measured from. Understand it before resetting under live trading.
  • Paper is the supported mode, so the paper→live gate is documented but not exercised with real capital on a supported install.
  • The pipeline — the lifecycle these gates sit between, and the board that explains blockers
  • The gauntlet — the robustness tests feeding the door and the live gate
  • Metrics — what each gate reads, and how the deflated Sharpe counts trials
  • Going live safely — the operator checklist before the strict gate