● END OF DAY
SPXcurrent: every source’s date
SPX2026-10-28 VIX2026-10-28 LABELS2026-10-28 FIT2026-10-28 GREEKS2026-10-28 SURFACE2026-10-28 BACKTEST≤2025-03-24 MODELv2 BUILD088fc8d VIEWas of 2026-10-28
SPX7,743.98▲ +0.28% VIX16.91▼ −0.61 VVIX96.61▼ −2.84 9D→6M+5.64contango VIX/VIX3M0.880 RV219.69 VIX−RV21+7.22 VIX 1Y PCTL46th (percentile among the 252 sessions before 2026-10-28) RULER1short gamma2026-10-28 1M ATMF13.40%RR25−4.312026-10-28

C16–C23 corrections — 33 findings, 30 fixed, 3 quantified

Each round as a blameless postmortem: what was wrong, why, how it was found, the fix, the tests that now pin it and what it did to the published result. Most corrections lowered the published result (from −9.1% after C17 to −22.2% after C23); C22 raised it from −26.1% to −21.6%; no round restored a positive return.

64 regression tests cited·27 commits linked·C22 evidence from c22_bridge.csv·C23 from c23_bridge.csv

C22 waterfall · portfolio P&L, one correction at a time

$000s

From −$261K (C21 as published) to −$222K (canonical today, on the C23 record) in 15 cumulative steps; each bar is one correction's effect on portfolio P&L.

C22 bridge: each correction applied in turn ($)
RowCorrectionΔ P&LP&L afterSharpe after
—C21 as published−$261,206
0C21 engine as published−$3,621−$264,827−1.84
1VIX tenors 9/30/93/184d, 365-day year−$524−$265,350−1.84
2Sharpe on excess P&L, rf=0$0−$265,350−1.17
3^IRX gaps: previous print$0−$265,350−1.17
4S3 proxy exit-day P&L + cost−$1,341−$266,692−1.18
5hedge open/unwind costs−$15,252−$281,944−1.25
6premium + hedge financing+$20,542−$261,402−1.15
7expiry settle / roll$0−$261,402−1.15
8open trade in trade log$0−$261,402−1.15
9size off sleeve NAV+$51,921−$209,480−1.33
10real correlation netting+$15,932−$193,548−1.33
11ATM vol = 0.82 × VIX+$107,870−$85,678−0.37
12S3 = short SPX straddle (index leg)−$35,627−$121,305−0.57
13R2 gate = upstream default (adaptive (rolling 80th pct))−$138,841−$260,145−1.28
14PDV spread: 21-day RMS-vol forecast (daily purged refit)+$37,968−$222,177−0.99

Each bar is one correction's effect on portfolio P&L in the order the bridge applies them (each row is cumulative), replayed on the C23-restated VIX record, so the last bar is today’s canonical run; the published C22 run ended at −$216,092 and the C23 table below accounts for the difference. The β step moves it by +$108K (S1C −$414K → −$116K, S1 +$576K → −$508K); the single R2 gate by −$139K.

Published result after each round

C17 to C22 as published at the time; C23 from the stored canonical run.

Published cumulative return by round (%)
RoundCumulative return
C17−9.1%
C18−19.0%
C19−19.0%
C20−19.0%
C21−26.1%
C22−21.6%
C23−22.2%

C16 published no portfolio figure; C19 and C20 left it unchanged; C23 is the stored canonical run, with its intervals and nulls in the inference on Research.

Findings register · every finding, C16–C23

33 findings
Every finding: status, portfolio P&L where a bridge CSV measures it, the tests that pin it
IDRoundFlawStatusPortfolio P&LTestsEntry
C16.1C16PDV look-ahead biasfixed—2C16 finding 1
C16.2C16Circular classifier featurefixed—1C16 finding 2
C16.3C16Retrospective Kelly nettingfixed—1C16 finding 3
C16.4C16S1C data snoopingquantified—0 gapC16 finding 4
C16.5C16S3 arbitrary P&L scalequantified—1C16 finding 5
C17.1C17Classifier never benchmarked against persistencefixed—2C17 finding 1
C17.2C17Margin model documented but not enforcedfixed—1C17 finding 2
C17.3C17S1C had no R2 exitfixed—1C17 finding 3
C17.4C17Dead monthly recalibration; a flat 5% hurdlefixed—1C17 finding 4
C18.1C18Same-day re-entry kept one straddle alivefixed—2C18 finding 1
C19.1C19S2 stop-loss not propagated; dead code; incomplete summaries; data gapsfixed—2C19 finding 1
C20.1C20Archived fits ranked by SPX RMSE with no data-sufficiency checkfixed—2C20 finding 1
C21.1C21^IRX history inside the window was seven synthetic test rowsfixed—2C21 finding 1
C21.2C21First holding day carried no time decayfixed—1C21 finding 2
C21.3C21The bot published classifier output as rule labelsfixed—1C21 finding 3
C22.1C22ATM straddles priced at the VIXfixed+$108K2C22 finding 1
C22.2C22Two R2 gates and a hard-coded VVIX overridefixed−$139K2C22 finding 2
C22.3C22Free hedging, no carry, sizing off $1M, no-op nettingfixed+$73K4C22 finding 3
C22.4C22S3 P&L was a z-score times an assumed 2%fixed−$37K2C22 finding 4
C22.5C22PDV spread compared the 30-day VIX with a 1-day forecastfixed+$38K2C22 finding 5
C22.6C22Sharpe charged cash twicefixedunchanged1C22 finding 6
C22.7C22VIX indices fitted as futures; ATM-call anchors; one-expiry live fitsfixed—3C22 finding 7
C23-D1C23The labels, backtest and calibrator read Yahoo's copies of the VIX index familyfixed−$6K3C23 finding 1
C23-M1C23The σ ≤ 2 box, not the market, sets the headline fitquantified—3C23 finding 2
C23-M2C23Model error was never measured against the bid–ask, and quotes were not screened for static arbitragefixed—3C23 finding 3
C23-S1C23The backtest had no statistical inferencefixed—4C23 finding 4
C23-R1C23Flat rates in the hedger and the Greeks surfacefixed—2C23 finding 5
C23-O1C23A presentation test could lose a captured sessionfixed—2C23 finding 6
C23-O2C23`make reproduce` refitted the calibrations from a deleted scratch pickle and with the wrong optimiserfixed—1C23 finding 7
C23-U1C23The accessibility gate audited retired pages; the Risk page printed 'r = —%'; the ML classifier sat on the Overviewfixed—2C23 finding 8
C23-E1C23`option_chain.year_fraction` raised on an origin with no time in itfixed—1C23 finding 9
C23-E2C23Known advisories in three locked packages on the download and preview pathsfixed—1C23 finding 10
C23-V1C23Published claims that the branch's own artifacts contradicted (independent review of C23)fixed—6C23 finding 11

Portfolio P&L is the sum of the finding's rows in c22_bridge.csv or c23_bridge.csv (mark-to-model; hover for the rows); — where no bridge measures it. A gap is a finding no regression test pins. 30 fixed, 3 quantified (measured and published rather than removed); 1 without a dedicated regression test. The postmortems below keep each finding's root cause, fix, evidence and tests (open a finding, or follow its entry link); the newest round is open.

Cited on: Research

Postmortems

C16

Methodology audit: look-ahead, a circular feature, retrospective sizing

high severity 5 findings 2026-06-11
Detection
Self-audit of the methodology before the result was published.
Components · commits
signals, classifier, sizing · 47e1ffe
Effect on the published result
The published +19% headline was a label-noise artifact.
Finding 1 · fixed PDV look-ahead bias
Root cause
The PDV model was fitted on the full sample, so every backtest year traded a forecast that had seen its own future.
Fix
PDVLinear refitted per backtest year on strictly earlier returns (walk-forward) before it feeds the pdv_iv_spread feature.
Evidence
S1/S1C now trade a causal PDV forecast
Pinned by
test_pdv.py::TestNoLookAhead::test_walk_forward_no_lookahead_poison, test_pdv.py::TestNoLookAhead::test_poison_actually_bites_later
Finding 2 · fixed Circular classifier feature
Root cause
vvix was a training feature while the R2 label is defined as VVIX above a threshold, so 86.2% accuracy partly measured rule recovery.
Fix
vvix removed from the classifier's features; honest accuracy 63.4%.
Evidence
Historical C16 figure: honest accuracy 63.4%; C17 then found it lost to the persistence baseline
Pinned by
test_regime_classifier.py::TestVersionRobustPickle::test_shipped_classifier_is_built_on_the_canonical_gate
Finding 3 · fixed Retrospective Kelly netting
Root cause
Correlation and Sharpe multipliers used same-day P&L to size the same day's positions.
Fix
Multipliers shifted one session and applied to position size in a second simulation pass, so contracts and costs reflect the real size.
Evidence
Ex-ante sizing; no same-day information
Pinned by
test_backtest_accounting.py::TestCorrelationNetting::test_engine_applies_the_overlay_one_session_late
Finding 4 · quantified no test S1C data snooping
Root cause
S1C's direction was chosen after watching S1 fail on 2018–2025; that cannot be undone in code.
Fix
Tested on 2013–2017, a window not used to design it (C17 re-ran it under corrected labels): S1C −$333K; the apparent edge was an artifact.
Evidence
Pseudo-out-of-sample under C17: S1C −$333K — the apparent edge was an artifact
Pinned by
no dedicated regression test (a gap)
Finding 5 · quantified S3 arbitrary P&L scale
Root cause
S3's P&L was an assumed 2% per z-unit (no single-stock options data).
Fix
Sensitivity run at 0.5% / 1% / 2% / 4% per z-unit; C22 replaced the proxy with the index leg (a short SPX straddle).
Evidence
C16 sensitivity run: P&L +$5K…+$52K, win 15–17 of 17 at every scale (before C18, C21 and C22 re-priced every trade and C22 replaced the proxy with the index leg)
Pinned by
test_backtest_accounting.py::TestS3::test_null_test_exposes_the_z_proxy_bias
C17

Red-team: the classifier against a persistence baseline; margin; an unbounded tail

high severity 4 findings 2026-06-11
Detection
Red-team review in the same week as C16.
Components · commits
classifier, risk limits, signals · 8c3ba9b
Effect on the published result
The classifier loses to 'predict yesterday's regime' and was demoted from the trading loop; portfolio −9.1% as published after this round.
Finding 1 · fixed Classifier never benchmarked against persistence
Root cause
Regime labels are same-day observables, so yesterday's label is a no-skill baseline; it scored 90.0% on 2020+ against the classifier's 63.4%.
Fix
ML demoted to research; the backtest trades the lagged deterministic rule labels.
Evidence
63.4% vs 90.0% — the ML added negative value (the C22 retrain on the adaptive gate: 74.9% vs 87.0%; still below the baseline)
Pinned by
test_regime_classifier.py::TestEvaluateClassifier::test_persistence_baseline_reported, test_regime_classifier.py::TestEvaluateClassifier::test_persistence_uses_previous_session_label
Finding 2 · fixed Margin model documented but not enforced
Root cause
MARGIN_RATIO was defined but never applied, so short straddles had unlimited capacity.
Fix
Short straddles capped at nav / (0.20 * K * 100) contracts at entry.
Evidence
Cost model now matches its documentation
Pinned by
test_backtest_engine.py::TestC17Fixes::test_margin_cap_on_short_straddles
Finding 3 · fixed S1C had no R2 exit
Root cause
An open S1C short straddle could ride a VVIX spike for up to 21 days with no stop.
Fix
S1C force-closes when the regime moves into R2, as S1X, S2X and S4 do.
Evidence
Worst-case short-gamma exposure now bounded by the R2 rule
Pinned by
test_signal_engine.py::TestGenerateSignal1Contrarian::test_r2_transition_forces_exit
Finding 4 · fixed Dead monthly recalibration; a flat 5% hurdle
Root cause
The monthly Heston loop never produced a calibration (no pre-2026 options data) and nothing consumed its output; Sharpe used a flat 5%.
Fix
Loop removed; Sharpe and Sortino measured against the per-date ^IRX path (later superseded in C22).
Evidence
Backtest claims now match what the code does
Pinned by
test_backtest_engine.py::TestC17Fixes::test_compute_metrics_accepts_rf_series
C18

Straddles never rolled: one stale-strike position marked past expiry

high severity 1 finding 2026-06-14
Detection
Word-by-word audit of the engine's position series: positions never returned to flat.
Components · commits
backtest engine · 3d52f42
Effect on the published result
Inverted the contrarian thesis: S1 −$1.53M → +$463K, S1C −$97K → −$404K, portfolio −9.1% → −19.0%; S3 unchanged.
Finding 1 · fixed Same-day re-entry kept one straddle alive
Root cause
The state machine re-entered on the day it exited, so the strike was fixed at first entry and the tenor decayed to its 1-day floor: a directional |S - K| bet, not a vol trade. Every P&L figure from C10 to C17 was contaminated.
Fix
A forced flat day so positions roll into fresh 30-day ATM straddles.
Evidence
Inverted the thesis: S1 −$1.53M → +$463K, S1C −$97K → −$404K, portfolio −9.1% → −19.0%; S3 unchanged
Pinned by
test_backtest_accounting.py::TestExpiryRoll::test_rolls_into_fresh_atm_straddles, test_backtest_accounting.py::TestExpiryRoll::test_no_trade_outlives_its_expiry
C19

Signal-engine logic fixes and data-gap repair

low severity 1 finding 2026-06-20
Detection
Follow-up review of the signal state machines after C18.
Components · commits
signals, data · e1cfbd0
Effect on the published result
Cleanup; the canonical numbers did not change.
Finding 1 · fixed S2 stop-loss not propagated; dead code; incomplete summaries; data gaps
Root cause
Stop-loss exits did not reach the S2 position; signal summaries skipped sleeves; market data had gaps.
Fix
Stops propagate to the S2 position, dead code removed, summaries cover every sleeve, gaps repaired.
Evidence
Cleanup — the canonical numbers did not change
Pinned by
test_signal_engine.py::TestGenerateSignal2::test_short_straddle_stopped_when_front_vol_rises, test_signal_engine.py::TestGenerateSignal2::test_long_straddle_stopped_when_front_vol_falls
C20

The calibration selector rewarded broken data

high severity 1 finding 2026-08-04 → 2026-09-05
Detection
The headline fit was traced to a day the VIX feed returned only ^VIX.
Components · commits
calibration, dashboard · 35690a2, 9058371
Effect on the published result
The published 'best calibration' had been the day the VIX feed failed; fits are now gated on at least 3 VIX tenors with provenance recorded.
Finding 1 · fixed Archived fits ranked by SPX RMSE with no data-sufficiency check
Root cause
With one VIX tenor the VIX leg is one point Heston matches exactly, so under-identified joint fits scored best and headlined the site.
Fix
Gate on >= 3 VIX tenors; Feller reported as PASS / BINDING / VIOLATED. C22 went further: the headline is the newest gate-passing fit, never the lowest RMSE.
Evidence
The published “best calibration” had been the day the VIX feed failed
Pinned by
test_joint_calibrator.py::TestCalibrationQualityGate::test_single_vix_tenor_rejected, test_dashboard.py::test_selector_takes_newest_acceptable_fit_not_lowest_rmse
C21

The cash hurdle was a test fixture; straddles marked a day too rich

high severity 3 findings 2026-09-05
Detection
Adversarial audit of the backtest inputs and the daily bot.
Components · commits
backtest engine, data, daily bot · 15b4db5, 90dc851
Effect on the published result
Portfolio −19.0% → −26.1%, Sharpe −1.57 → −1.80, MaxDD −25.9% → −31.5%; S1 +$463K → +$694K, S1C −$404K → −$600K.
Finding 1 · fixed ^IRX history inside the window was seven synthetic test rows
Root cause
test_rates.py wrote np.linspace(0.015, 0.020) into the tracked database and it was forward-filled for five years.
Fix
Real ^IRX history loaded (1,809 rows); the suite now works on a private copy and cannot write the tracked database.
Evidence
Part of the round's combined effect above; the two backtest fixes were not re-run separately
Pinned by
test_c21_audit_fixes.py::TestRiskFreeHurdle::test_metrics_reject_a_stub_rate_series, test_rates.py::TestIsolation::test_database_module_points_at_a_temp_file
Finding 2 · fixed First holding day carried no time decay
Root cause
T_rem was computed from the pre-increment day count, so every mark valued the straddle one day too rich, flattering the short side.
Fix
Time to expiry decays from the first holding day.
Evidence
Part of the round's combined effect above; the two backtest fixes were not re-run separately
Pinned by
test_c21_audit_fixes.py::TestStraddleTimeDecay::test_first_holding_day_decays
Finding 3 · fixed The bot published classifier output as rule labels
Root cause
The daily refresh relabelled regime_labels.parquet with the demoted classifier and refit a frozen option surface.
Fix
The bot writes deterministic rule labels and calibrates on a live chain.
Evidence
The published labels are the rule's again
Pinned by
test_c21_audit_fixes.py::TestRegimeLabelProvenance::test_refresh_labels_with_rule_not_classifier
C22

Full-system audit: pricing at the VIX, free hedging, two R2 gates, a z-score P&L

high severity 7 findings 2026-10-12 → 2026-10-19
Detection
A subsystem-by-subsystem audit (about 270 findings, each reproduced before fixing) after the live calibration failed for a month.
Components · commits
backtest engine, signals, calibration, daily bot · a51eccc
Effect on the published result
Portfolio P&L −$261,206 (C21 as published) → −$216,092 (NAV $783,908), Sharpe −1.80 → −0.88, max drawdown −31.5% → −21.6%, as published in C22; S1 +$693,938 → −$287,644. Its 15-step waterfall is replayed today on the C23-restated VIX record, so it ends at the C23 canonical run.
Finding 1 · fixed ATM straddles priced at the VIX
Root cause
The VIX is a 30-day variance-swap rate that contains the skew premium; straddles were priced and marked at it.
Fix
ATM vol = β × VIX, with β estimated from stored SPX chains.
Evidence
β = 0.82 = mean of 4 DB chains and 1 live capture (0.80–0.84); the first later chain, 2026-10-16, gives 0.70 — the mean over all 9 chains, 0.79, is not in the β grid. C22 bridge row 11: S1 +$576K → −$508K from β alone, before the later C22 steps; at β = 1 under the full C22 configuration (β grid), S1 shows +$2.5M
C22 bridge
row 11 · portfolio P&L +$108K · Sharpe −1.33 → −0.37
Pinned by
test_backtest_accounting.py::TestAtmVol::test_entry_vol_is_beta_times_vix, test_backtest_reproducibility.py::test_default_beta_is_the_estimate_from_the_real_chains
Finding 2 · fixed Two R2 gates and a hard-coded VVIX override
Root cause
Published labels used the adaptive gate while the backtest traded a fixed 100-point VVIX gate, and the signal engine OR-ed a VVIX > 100 override onto any labels.
Fix
One adaptive gate (rolling 252-day 80th percentile of VVIX) everywhere; no override.
Evidence
The backtest traded the fixed gate while the labels used the adaptive one (48% vs 23% of the backtest sessions in R2). C22 bridge row 13: portfolio −$139K
C22 bridge
row 13 · portfolio P&L −$139K · Sharpe −0.57 → −1.28
Pinned by
test_regime_classifier.py::TestR2Gate::test_default_gate_is_adaptive, test_signal_engine.py::TestSignalEngineGenerate::test_default_regimes_are_lagged_canonical_rule_labels
Finding 3 · fixed Free hedging, no carry, sizing off $1M, no-op netting
Root cause
The opening hedge and unwind were free, the book earned no carry, size used $1M instead of the sleeve's NAV, and the netting factor was clipped into a no-op.
Fix
Costs charged once each, premium and hedge financed, size off the running sleeve NAV, real netting.
Evidence
C22 bridge rows 5, 6, 9, 10: −$15K, +$21K, +$52K, +$16K
C22 bridge
rows 5, 6, 9, 10 · portfolio P&L +$73K · Sharpe −1.18 → −1.33
Pinned by
test_backtest_accounting.py::TestHedgeCosts::test_open_rebalance_and_unwind_charged_once_each, test_backtest_accounting.py::TestFinancing::test_trade_financing_matches_formula, test_backtest_accounting.py::TestBookkeeping::test_sizing_and_margin_use_running_sleeve_nav, test_backtest_accounting.py::TestCorrelationNetting::test_legacy_multiplier_could_never_reduce_size
Finding 4 · fixed S3 P&L was a z-score times an assumed 2%
Root cause
The 'survivor' was positive on 99.5% of random-walk null paths: it measured mean reversion of a ratio, not option P&L.
Fix
S3 is the index leg of the dispersion trade (a short SPX straddle) on the same engine, with a timing null test.
Evidence
S3 +$23K (z-units, as published in C21) → +$61K (index leg); timing null test on S3 at base (pass-1) size, before the sizing overlay: p = 0.065 (the C22 200-path null; C23 replaced it with exposure-matched nulls, Finding 4 of C23); positive for β ≥ 0.80 in the sensitivity grid, negative at 0.78
C22 bridge
rows 4, 12 · portfolio P&L −$37K · Sharpe −1.17 → −0.57
Pinned by
test_backtest_accounting.py::TestS3::test_index_leg_is_a_short_spx_straddle, test_backtest_accounting.py::TestS3::test_null_real_statistic_is_the_engines_s3
Finding 5 · fixed PDV spread compared the 30-day VIX with a 1-day forecast
Root cause
The pre-C22 forecast was next-day E|r|, so 'VIX > forecast + 2 vol pts' held on almost every session.
Fix
The spread uses a 21-day RMS-vol forecast refitted daily on labels fully observed at the forecast origin.
Evidence
the pre-C22 σ̂ (a 1-day E|r| forecast) averaged 0.71× the realised RMS vol of the next 21 sessions in the backtest window, so “VIX > σ̂ + 2 vol pts” held on 95% of its 1,816 sessions. C22 bridge row 14: portfolio +$38K
C22 bridge
row 14 · portfolio P&L +$38K · Sharpe −1.28 → −0.99
Pinned by
test_pdv21_wiring.py::TestBacktestEngine::test_canonical_horizon_is_21, test_pdv.py::TestWalkForwardVolForecast::test_no_lookahead_poison
Finding 6 · fixed Sharpe charged cash twice
Root cause
Option P&L on unfunded collateral is already an excess return; subtracting ^IRX again double-counted it.
Fix
Sharpe uses rf = 0 (collateral assumed to earn T-bills), with the T-bill benchmark shown beside it.
Evidence
C22 bridge row 2: Sharpe −1.84 → −1.17 with P&L unchanged
C22 bridge
row 2 · portfolio P&L unchanged · Sharpe −1.84 → −1.17
Pinned by
test_backtest_accounting.py::TestSharpeConvention::test_engine_does_not_charge_tbills_on_excess_pnl
Finding 7 · fixed VIX indices fitted as futures; ATM-call anchors; one-expiry live fits
Root cause
The calibrator fitted spot VIX indices with the futures formula, anchored on adjacent ATM calls only, and the daily bot accepted fits from one SPX expiry (9 options) for a month.
Fix
Spot-index VIX leg, forward-moneyness z-grid anchors with put-wing quotes, and a gate on expiries, options and the put wing.
Evidence
Headline Heston fit replaced; one-expiry fits are rejected by the gate
Pinned by
test_joint_calibrator.py::TestSyntheticMarket::test_vix_index_leg_zero_at_generating_params, test_joint_calibrator.py::TestCalibrationQualityGate::test_single_expiry_rejected, test_joint_calibrator.py::TestCalibrationQualityGate::test_missing_put_wing_rejected
C23

Vendor data, the calibration's identification, spread-unit evidence and statistical inference

high severity 11 findings 2026-10-20 → 2026-10-21
Detection
A reviewer-standard pass over every subsystem in six parallel chains (surface, calibration, statistics, data, UI, engineering), each result measured on the five committed model_version 2 sessions and merged only with the full suite green. An independent adversarial review of the merged branch then confirmed 62 findings; the ones that corrected a published claim are finding 11.
Components · commits
data layer, calibration, surface, statistics, rates, daily bot, dashboard, engineering · c63e515, 2566553, 958be69, 49f5fd0, 1c886e3, ca36d24, 9c486c3, a678e57, e6a92bc, ba360c8, a92308c, 741dfe3, 113efa5, d63b797, 59e73b1, dd4dc01, b69eb45, 1a4ca03
Effect on the published result
Portfolio P&L −$216,092 → −$222,177, Sharpe −0.88 → −0.99 (C23 waterfall, data_store/backtest/c23_bridge.csv: 8 VVIX sessions from Cboe −$6,502; 136 Cboe values +$417); 6 of 4,162 rule labels move; the portfolio Sharpe's 95% bootstrap interval is −1.81 to −0.30. The headline Heston fit is unchanged, now reported with its σ profile and rough Heston beside it. The review round (finding 11) corrected published claims without moving a headline number.
C23 waterfall · the C22 run restated on the Cboe record (c23_bridge.csv)
RowStep (cumulative)Portfolio P&LΔ P&LSharpe
0C22 canonical as published (pre-C23 record)−$216,092−0.879
1same 2-decimal prints restated as Cboe's (|change| <= 0.005)−$216,092$0−0.879
2term-structure rows on NYSE holidays removed−$216,092$0−0.879
3VVIX sessions missing from Yahoo added from Cboe−$222,594−$6,502−0.991
4term-structure values replaced by Cboe's (|change| > 0.005)−$222,177+$417−0.987
Finding 1 (C23-D1) · fixed The labels, backtest and calibrator read Yahoo's copies of the VIX index family
Root cause
Production overlaid Cboe's official closes on vix_daily only; every consumer read vix_term_structure, Yahoo's float32 copies with NULL provenance, NYSE-holiday rows and 8 VVIX sessions missing (forward-filled).
Fix
Cboe's index files are the record (Yahoo only as a provisional same-evening row, replaced when Cboe posts); the database cache re-synced from it; the daily job writes Cboe first and reports cross-source differences above 0.25 index pts.
Evidence
136 term-structure rows replaced (38 by more than 0.25 index pts, 33 of them in the backtest window), 8 VVIX sessions added, 31 holiday rows removed; portfolio −$216,092 → −$222,177 (c23_bridge.csv); labels 2019-08-09, 2020-02-20, 2020-06-11, 2021-05-11 R1 → R2 and 2021-06-09, 2021-07-08 R2 → R1
Pinned by
test_data_layer.py::TestC23RecordCorrection::test_apply_db_removes_holiday_rows_and_installs_the_cboe_values, test_cloud_refresh.py::test_vix_term_structure_is_cboe_primary, test_backtest_reproducibility.py::test_c23_bridge_reproduces_every_row
Finding 2 (C23-M1) · quantified The σ ≤ 2 box, not the market, sets the headline fit
Root cause
σ sits on its 2.0 ceiling in 2 of the 5 model_version 2 fits (2026-03-24, 2026-10-16); the page said 4 of 5 parameters are set by the market without saying what the box costs.
Fix
A σ profile (the joint loss refitted under caps 1 to 10, κ ≤ 60) and Gauss–Newton identifiability are stored per session and shown; the production box is kept (the NN domain, the vomma shock sizing and the gate depend on it) and its cost is published. The review round (C23f) removed the count the σ profile contradicts: κ is interior but moves with the σ cap along a κ–σ ridge (κ 1.2 at σ ≤ 1, 5.0 at the cap, 27.4 freed) and its curvature SE is 19%, so the pages say σ is on its bound and κ is set by the box, not that 4 of 5 parameters are set by the data.
Evidence
2026-10-16: freeing σ gives σ 6.90, κ 27.4, loss −27.7%, out-of-sample RMSE 2.96 → 1.19 vol pts and model VVIX 205 → 113 against the market's 110; on 2026-03-24 the box costs 2.1% of the loss (data_store/calibrations/diagnostics/)
Pinned by
test_identifiability.py::test_sigma_box_rationale_in_config_matches_the_artifacts, test_identifiability.py::test_diagnostics_artifact_is_consistent, test_dashboard.py::test_no_identification_count_where_the_sigma_profile_contradicts_it
Finding 3 (C23-M2) · fixed Model error was never measured against the bid–ask, and quotes were not screened for static arbitrage
Root cause
No per-quote residuals were stored, the calibration chart drew the model only, and nothing screened the stored quotes for static arbitrage.
Fix
A surface package: Cohen–Reisinger–Wang screen and l1 repair on HiGHS, an executable-arbitrage certificate, eSSVI and calendar-ordered SVI surfaces, and one scorecard that scores every model on the calibrator's out-of-sample quotes in half-spreads.
Evidence
Out-of-sample median |model − mid| over the 5 sessions: Heston 4.4–15.6 half-spreads (3.0–12.3% inside the bid–ask); the arbitrage-free SVI surface 0.45–1.98 (32–80% inside); executable static arbitrage on all 5 sessions, 160–629 quotes per session in an executable row (data_store/surface/)
Pinned by
test_surface_arbitrage.py::test_committed_session_screen_counts, test_surface_report.py::test_spread_unit_claims_hold, test_surface_report.py::test_committed_artifacts_match_a_recomputation
Finding 4 (C23-S1) · fixed The backtest had no statistical inference
Root cause
Sharpe ratios and a 200-path S3 null were published without intervals, deflation for the configurations tried since C10, or exposure-matched nulls for every sleeve.
Fix
Stationary-bootstrap intervals, PSR/DSR against a committed trials ledger, Hansen SPA and StepM, CSCV PBO, exposure-matched circular-shift and trade-shuffle nulls for every sleeve, and forecast comparisons (QLIKE, Diebold–Mariano, MCS).
Evidence
Portfolio Sharpe −0.99, 95% CI −1.81 to −0.30; S3 timing p 0.078 against 3,550 circular shifts (Holm over 6 sleeves 0.47); Hansen SPA p 0.65 for the published series against cash; S3's deflated Sharpe ratio is 0.000–0.019 at the ledger's trial counts (N 147–210) and reaches 0.27 only at N 4.6, the eigenvalue participation ratio of the 83 re-run trial series (not a trial count), with the skill-less trial variance; CSCV PBO 0.34 for the 16 configurations of the published portfolio (data_store/backtest/inference/summary.json)
Pinned by
test_stats_inference_report.py::test_headline_is_generated_from_the_stored_numbers, test_stats_inference_report.py::test_bootstrap_rebuilds_exactly_from_the_committed_curve, test_stats_nulls.py::test_circular_null_detects_real_timing_and_not_luck, test_stats_inference_report.py::test_dsr_reports_the_ledger_count_range_beside_the_lenient_bound
Finding 5 (C23-R1) · fixed Flat rates in the hedger and the Greeks surface
Root cause
The C7 hedger hard-coded R = 1.5% ('2020 US Treasury'), and the Greeks surface used one median r and q for every maturity, so its 1-year forward was 0.50% below that expiry's parity forward.
Fix
A daily Treasury zero curve (bills and par yields, look-ahead gated, refused when more than 7 days old) feeds the calibrator's reference, the chain cleaner, the C7 study and per-maturity Greeks carry.
Evidence
C7 cumulative P&L 167.95 → 168.34 index points; Greeks surface 1-year forward 7,931.8 → 7,971.7 (the parity forward); the committed fits recorded ^IRX and are unchanged
Pinned by
test_rate_reference.py::test_c7_uses_the_one_year_zero_rate_at_entry, test_rate_reference.py::test_greeks_carry_reprices_the_parity_forwards_on_the_treasury_curve
Finding 6 (C23-O1) · fixed A presentation test could lose a captured session
Root cause
The daily job committed the chain and the fit only if the dashboard tests passed; a test that pinned a value of the committed data failed on the first new fit, and the 2026-10-19 overnight book (accepted three times) was lost.
Fix
Separate gates: data tests gate the capture commit, artifact tests the derived artifacts, presentation tests only the deploy; CI simulates the bot's next session before merge.
Evidence
No published number moved; the simulated next session (scripts/ci/simulate_next_session.py) found 5 more tests that would have blocked the deploy on the first accepted fit
Pinned by
test_infra_config.py::test_a_presentation_test_cannot_lose_the_captures, test_infra_config.py::test_each_commit_adds_its_own_paths
Finding 7 (C23-O2) · fixed `make reproduce` refitted the calibrations from a deleted scratch pickle and with the wrong optimiser
Root cause
The refit step read each fit's recorded inputs from the scratch copy's pickle, which run_step deletes first, so all five calibration steps failed; with the path right, the default TRF refit would still have missed the committed DE fits by up to 2e-3 relative.
Fix
Each refit reads its inputs from the committed pickle in the checkout and runs the optimiser that made it (DE for every fit committed before C23).
Evidence
make reproduce plus the three --full steps: 14 of 14 artifacts bit for bit (docs/reproduce.md)
Pinned by
test_infra_config.py::test_reproduce_refits_each_fit_from_its_committed_record
Finding 8 (C23-U1) · fixed The accessibility gate audited retired pages; the Risk page printed 'r = —%'; the ML classifier sat on the Overview
Root cause
The CI accessibility gate listed two pages that had become redirects and could not inject axe under the pages' CSP; every page scrolled horizontally at 320 px when the view was a session behind; the Risk banner read one flat carry the per-maturity Greeks no longer had; a demoted research model was on the first screen.
Fix
The gate audits the seven pages and the 404 (the redirects are not pages), with CSP bypassed for the audit context only; status items wrap below 480 px; the Risk page states its r(T), q(T) ranges and the curve; the classifier moved to the Research page.
Evidence
axe-core 4.13.0: 0 violations on the 7 pages and the 404 at 1440 and 390 px in both colour schemes; no horizontal scroll from 320 to 1920 px (docs/engineering.md)
Pinned by
test_dashboard.py::test_risk_provenance_states_the_per_maturity_carry, test_dashboard.py::test_overview_keeps_research_prototypes_off_the_first_screen
Finding 9 (C23-E1) · fixed `option_chain.year_fraction` raised on an origin with no time in it
Root cause
A missing quote_time cell reads as an empty string or a missing value, which the time parser did not accept; making the module pass mypy's strict flags found it.
Fix
An origin with no time counts as the session close.
Evidence
the path raised; it never returned a wrong T
Pinned by
test_properties_iv.py::test_year_fraction_clock
Finding 10 (C23-E2) · fixed Known advisories in three locked packages on the download and preview paths
Root cause
pip-audit 2.10.1 on the lock (2026-10-20): idna 3.11 (CVE-2026-45409), urllib3 2.6.3 (five CVEs), werkzeug 3.1.8 (CVE-2026-102598); none in the numerical stack.
Fix
Floors idna ≥ 3.15, urllib3 ≥ 2.8.0 and werkzeug ≥ 3.1.9 in requirements.txt and a recompiled lock that keeps every numerical pin.
Evidence
requirements-lock.txt pins idna 3.20, urllib3 2.8.0, werkzeug 3.1.9; the committed pickles and bit-exact artifacts are unaffected
Pinned by
test_infra_config.py::test_lock_keeps_the_security_floors
Finding 11 (C23-V1) · fixed Published claims that the branch's own artifacts contradicted (independent review of C23)
Root cause
Claims were checked on the grids that produced them: the 'arbitrage-free' SVI surface was constrained at 241 nodes, the forward ledger was tested on synthetic books that always held the position's expiry, the Risk page's delta grid was labelled from the column name, and the S3 deflated Sharpe ratio was quoted at its most lenient trial count.
Fix
SVI slices are accepted only with refined-grid butterfly and calendar certificates (Durrleman g ≥ 0 and calendar order on a 1e-4 grid over k in [−3, 2], a 1/k grid to |k| = 2,000–3,000 and the |k| → ∞ limits), which also gate the label; the ledger trades and marks on the session's full Cboe book whatever the fit does; the Risk grid shows the OTM option's forward delta; every DSR and PBO is reported with its basis; page copy states only what the data supports.
Evidence
Before: 21 SVI-cal slices with g < 0 between grid nodes (worst −2.58e-5 at k = 0.19 on 2026-10-16) and 35 crossing calendar pairs; after: 0 and 0 in all five sessions, every session's objective equal or lower, the published 0.45–1.98 half-spread range unchanged. The ledger's position expiry was in its book on 3 of 19 sessions; now the full Cboe book (55 expiries). The Risk grid showed +0.99 for a 30%-OTM put; now −0.01. S3's DSR: 0.000–0.019 at the ledger's counts, 0.27 only at N 4.6. 'Every fix made the backtest worse': C22 raised it from −26.1% to −21.6%
Pinned by
test_surface_svi.py::test_butterfly_certificate_finds_the_dip_between_grid_nodes, test_surface_svi.py::test_ordering_certificate_catches_crossings_the_check_grid_missed, test_forward_ledger.py::test_a_book_without_the_expiry_defers_the_close_to_the_next_book_that_has_it, test_dashboard.py::test_risk_delta_grid_is_the_otm_options_forward_delta, test_stats_inference_report.py::test_every_pbo_is_reported_with_its_basis, test_dashboard.py::test_corrections_trend_sentence_agrees_with_the_published_series

Keyboard shortcuts

g o
Overview
g s
Surface
g c
Calibration
g r
Risk
g e
Research
g x
Corrections
g m
Model Risk
?
This list
← → ↑ ↓
Move between heatmap cells

Units, signs and definitions: every term the pages abbreviate, with its formula.