Put-selling on capitulation — combined v2 (corrected gate arithmetic)
ID: S014
Slug: put-selling-capitulation-combined-v2
Failed at: Stage 1 (Quick-screen) — 7 of 8 gates passed; CAGR is the binding constraint
Fail reason: magnitude
Date: 2026-05-31
Lineage: Direct re-pre-registration of S013 with strategy unchanged and one gate corrected for author arithmetic error. S013's "max single-trade loss ≤ 0.10% of capital" was incompatible with the 1% sizing rule by construction. S014 corrects this to 1.10% (sizing bound + small slippage buffer) and confirms what S013 already showed: the strategy is cut because realized CAGR doesn't clear +5%, full stop.
What we tested
Exactly the S013 strategy: S008 Variant B signal + S012 calm-regime filter (0.85× SPY rv_20d median) + S011 risk-weighted sizing (1% capital max loss per trade) + a -200%-of-credit max-loss stop. Same universe, same period, same friction, same exit-rule priority order. The simulation code is identical to S013's; the trades parquet, the capital path, the per-trade win rate, the Sharpe, the drawdown, the yearly P/L — all identical.
What's different is one number in the gate evaluation: the max-single-trade-loss threshold was 0.10% in S013 and is 1.10% in S014. The threshold was chosen to validate the sizing rule's actual physical bound (1% sizing → up to 1% loss per trade at force-close- with-assignment) plus a small buffer for slippage edge cases. S013's 0.10% threshold was based on incorrect arithmetic about what the stop alone could bound (the stop only triggers on the ~15% of trades that hit the 2× MTM threshold; the other ~85% reach modest losses via force-close, which the sizing rule already bounds).
What we found
7 of 8 gates passed.
| Criterion | We needed | We got | |
|---|---|---|---|
| Portfolio CAGR | ≥ +5% | +4.57% | ✗ |
| Max drawdown | ≤ 25% | 3.4% | ✓ |
| Sharpe (monthly, annualised) | ≥ 0.5 | 1.85 | ✓ |
| Per-trade win rate | ≥ 75% | 82.2% | ✓ |
| Welch p<0.05 AND mean>0 | yes | p=0.0000, +0.88% | ✓ |
| Both halves positive | yes | h1 $129K, h2 $156K | ✓ |
| Final capital > starting | yes | $155,728 vs $100K | ✓ |
| Max single-trade loss ≤ 1.10% capital (corrected) | yes | 0.35% | ✓ |
Comparison with S013:
| Gate | S013 result | S014 result |
|---|---|---|
| CAGR (+5%) | +4.57% FAIL | +4.57% FAIL (identical) |
| Drawdown (≤25%) | 3.4% PASS | 3.4% PASS (identical) |
| Sharpe (≥0.5) | 1.85 PASS | 1.85 PASS (identical) |
| Win rate (≥75%) | 82.2% PASS | 82.2% PASS (identical) |
| Welch | PASS | PASS (identical) |
| Both halves | PASS | PASS (identical) |
| Final > start | PASS | PASS (identical) |
| Max single trade | 0.35% vs 0.10% threshold = FAIL | 0.35% vs 1.10% threshold = PASS |
| Total | 6/8 PASS, CUT on 2 | 7/8 PASS, CUT on 1 (CAGR alone) |
Why this matters / what surprised us
Nothing surprised at the numerical level. This run was specifically designed to confirm that nothing about the strategy was contingent on the broken gate — the deterministic simulation would produce identical numbers, and the only thing that needed validation was that the sizing rule (1% per-trade max loss) actually binds as designed. It does: worst single trade was $353.55 (0.35% of starting capital), well below the corrected 1.10% threshold and below the sizing rule's 1.00% theoretical maximum.
The real surprise is methodological. Pre-registration discipline forced us to honor a known-broken gate in S013's record, then publish S014 as a separate setup just to correct one number. This is exactly the discipline working as intended: gates are frozen, even if the author later realizes one was specced wrong; the correction is a new pre-registration, not a retroactive edit.
The lab record now reads cleanly. A reader of /lab sees:
- S013 = the combined strategy + a pre-registered gate set, one of
which the author later identified as mis-arithmetic'd; the public
record honestly documents both gate failures and the methodology
explanation
- S014 = the same strategy with the gate-arithmetic corrected,
confirming CAGR is the actual binding constraint
This is what pre-registration discipline buys: the audit trail makes the author's mistake visible without letting it contaminate the strategy's read.
The combined strategy is genuinely cut. Whether the gate evaluation is S013's (2 fails) or S014's (1 fail), the strategy does not pass Stage 1. The +4.57% CAGR is the limit of what this configuration can produce; tightening or loosening the surrounding gates doesn't change the underlying number. For Stage 2 work, the implication is: the combined approach is the wrong direction; S011 (sizing alone, +10.7% CAGR) is the stronger Stage-2 candidate.
Filter + stop together cost more in CAGR than they add in safety metrics. S011 alone: CAGR 10.7%, Sharpe 1.67, drawdown 19.1%. S014 (= S013): CAGR 4.57%, Sharpe 1.85, drawdown 3.4%. The Sharpe gain is small (+0.18) and the drawdown gain is large (−15.7pp), but the CAGR cost is severe (−6.15pp). For a real investor with a preference axis, S011's profile dominates unless drawdown is near-existential (which 19% is not for most institutional risk budgets).
What this doesn't tell us yet
-
A re-positioned conservative variant could be its own setup. "Sharpe ≥ 0.5 AND max drawdown ≤ 10%" with CAGR moved to +3% would describe a real product category (conservative-vol-yield). That would be S015 with its own pre-registration if it's worth pursuing. Not in scope for S014.
-
The stop or filter individually might be Stage-2 sensitivities for S011. Stop-loss sweep (-150%, -200%, -300%, no-stop) in Stage 2 would test whether the stop adds incremental Sharpe to S011 WITHOUT the filter (and therefore without the CAGR collapse). Same for filter threshold (0.75, 0.80, 0.85, 0.90, 0.95).
-
A v3 with looser filter (0.90× or 0.95× median) and stop but no risk-weighting might thread the needle — more trades, more dollar P/L, still some risk-control benefit. Would be S015+.
What happens next
S014 is formally cut. S013 stays in the record as-is (its gate failures are an honest part of the lab history). The Stage-2 candidate ranking is now:
- S011 (sizing alone) — strongest CAGR (+10.7%), cleanest pass, Stage-2-ready
- S012 (filter alone, uniform sizing) — strong per-trade EV (+1.19%), even time-stationarity (h1/h2 essentially identical), Stage-2-ready
- ~~S013 / S014 (combined)~~ — over-controlled; CAGR too low
For Stage 2 work, S011 with the stop-loss sensitivity sweep built into the Stage-2 design is the natural next step. S014's finding makes this concrete: the stop should be one of the swept parameters, likely with a wider range (-150%, -200%, -300%) to find the risk-adjusted optimum.
For the specialist — methodology details (click to expand)
Setup (verbatim from spec)
The S013 strategy evaluated against corrected gates where the max-single-trade-loss threshold is anchored to the sizing rule's physical bound (1.10% of starting capital) instead of S013's incorrectly-specified 0.10%, produces the same portfolio-level outcomes as S013 — the strategy is unchanged and the simulation is deterministic.
Test setup
100% identical to S013. The only difference is one numerical constant in the gate evaluation:
# S013 (mis-specified):
("Max single-trade loss ≤ 0.10% of starting capital (stop-binds)",
f"{worst_single_loss_pct_capital:.4%}",
worst_single_loss_pct_capital <= 0.001)
# S014 (corrected):
("Max single-trade loss ≤ 1.10% of starting capital (sizing-rule binds)",
f"{worst_single_loss_pct_capital:.4%}",
worst_single_loss_pct_capital <= 0.011)
Why the S013 gate was wrong (post-mortem on author error)
The pre-registered S013 gate read "max single-trade loss ≤ 0.10% of starting capital". I justified this at pre-registration time with arithmetic that approximated "1% sizing × 200% stop = ~0.03% per- trade max loss" and added headroom. But this arithmetic is wrong: the stop only triggers when MTM reaches 2× opening premium, which happens to roughly 15% of trades. The other ~85% experience modest mark-to-market deterioration that drifts toward the strike without ever hitting the 2× threshold. Those trades reach force-close at day 21 and realize losses up to the sizing rule's bound (~1% of capital). The 0.10% gate could only pass if EVERY losing trade hit the stop, which is impossible by construction.
The correct interpretation of "validate the stop is working" would have been something like "stop fires on ≥ 80% of losing trades" or "median losing trade is bounded by stop". The correct interpretation of "validate the sizing rule is binding" is what S014 uses: "max single-trade loss ≤ 1.10% of starting capital".
Pre-registered gate (FROZEN 2026-05-31, before run)
Same as S013 except the eighth gate is corrected:
portfolio_cagr ≥ +5%
max_drawdown ≤ 25%
sharpe_monthly (ann.) ≥ 0.5
per_trade_win_rate ≥ 75%
welch_p<0.05 AND mean>0 (per-trade EV % notional)
both_halves_positive
final_capital > starting
max_single_trade_loss_pct_capital ≤ 1.10% (corrected; was 0.10% in S013)
Detailed numbers
Identical to S013 at every digit (deterministic simulation): - Trades executed: 7,581 - Final capital: $155,728 - CAGR: +4.57% - Max drawdown: 3.4% - Sharpe: 1.85 - Win rate: 82.2% - Welch p: 0.0000, mean +0.88% - Worst single trade: $353.55 (0.354% of starting capital) - Exit reasons: 58.4% quick_take, 17.5% profit_take, 14.6% stop_loss, 4.8% force_close_loss, 4.7% force_close_win
Verification
Spot-check that S013 and S014 produced bit-for-bit identical
numbers — done by direct comparison of stage1_summary.json
fields. The only difference between the two files is in the
gates array's eighth entry (the corrected gate's name + threshold +
pass flag). All numerical fields are identical.
Artifacts
- Executed trades:
lab/postmortem/put-selling-capitulation-combined-v2/trades_executed.parquet - Capital path:
capital_path.parquet - Summary JSON:
stage1_summary.json - Histogram bins (monthly returns):
chart_data.json - Driver script:
lab/quickkill/put-selling-capitulation-combined-v2/run.py - Pre-registered gates:
lab/setups/gates.md§put-selling-capitulation-combined-v2 - Setup spec:
lab/setups/put-selling-capitulation-combined-v2.md - Antecedent:
lab/postmortem/put-selling-capitulation-combined-v1/kill.md(S013)
Stage 1 ran 2026-05-31. Pre-registered gates frozen before run. This setup exists specifically to correct the author's arithmetic error in S013's pre-registration. The strategy is identical; only one gate threshold was changed (from a known-broken 0.10% bound to a structurally-correct 1.10% bound). Per pre-registration discipline, both S013 and S014 stay in the lab record as separate setups with their own gate sets.