What this answers¶
39 asked the owner to decide on two rules, citing the 2009–2026 proxy Tier-1 table¶
(2026-09-27-vrp-threshold-characterisation-tables.md):
- Transition lockout. On the proxy, transition days (53%) realised better than settled days.
- VRP sign. Within calm-contango,
vrp-(premium selling blocked) realised better thanvrp+(allowed).
48 asked whether either survives on canonical SPY ATM IV30, the measure the 1 Nov¶
cutover (#18) would put on the VRP axis. Short answer: neither finding survives. On the same 2022–2026 days, (1) is not established under either measure, and (2) reverses: on canonical IV30 the VRP sign is informative in the direction the mapping assumes.
Nothing here changes mapping_version, regime_config.json or any rule. Those decisions
belong to #18 / #15 / #39.
Method¶
- Days: every FRED trading day with VIX + VIX3M that also has a canonical IV30 value: 1,184 days, 2022-01-03 → 2026-09-22. Both variants use exactly these days.
- Variants: only the VRP axis differs.
proxy: VRP = VIX/100 −forecast_rv30(production today)canonical: VRP = chain-inverted SPY ATM IV30 −forecast_rv30(backtest/out/iv30-spy-chain-inverted-2022-2026.csv, the 2026-09-30 arbiter series)canonical-svi: the same, from the SVI surface (robustness; same chains)- Labels come from production's pure functions (
band_vix,band_term,step_hysteresis, the HAR functions viareplay.har_payload), composed inbacktest/replay_variants.py. Fidelity is checked: the proxy variant was compared with productionmain()(viareplay.replay) on all 7 label fields for all 1,184 days. 0 mismatches. The run refuses to write anything on a single mismatch. - Outcome, per variant, on that variant's own measure:
vrp_realised = iv_t − rv_fwd_30(forward 30-trading-day realised vol on SPY closes). It is joined in a separate pass, as in Tier 1. - Uncertainty: 30-day forward windows overlap, so row counts overstate the evidence. Both contrasts carry 95% moving-block bootstrap intervals (block = 30 trading days, 2,000 resamples, seed 48).
- Consistency check: the VRP sign differs between the variants on 483/1,182 = 40.9% of labelled days, against 40.7% in the 2026-09-30 measurement. Different code paths agree.
Results¶
The two contrasts¶
| variant | contrast | n (a / b) | mean diff | 95% CI | hit-rate diff | 95% CI |
|---|---|---|---|---|---|---|
| proxy | transition − settled | 743 / 412 | −0.0045 | [−0.0226, +0.0102] | −4.3 pp | [−14.8, +4.4] |
| proxy | calm-contango: vrp− minus vrp+ | 282 / 440 | −0.0125 | [−0.0245, +0.0007] | +1.2 pp | [−8.1, +14.1] |
| canonical | transition − settled | 551 / 604 | −0.0005 | [−0.0269, +0.0187] | +0.2 pp | [−14.9, +13.9] |
| canonical | calm-contango: vrp− minus vrp+ | 637 / 85 | −0.0139 | [−0.0253, −0.0021] | −16.8 pp | [−29.4, −2.9] |
| canonical-svi | transition − settled | 565 / 589 | −0.0015 | [−0.0270, +0.0172] | +1.0 pp | [−13.6, +14.5] |
| canonical-svi | calm-contango: vrp− minus vrp+ | 633 / 88 | −0.0135 | [−0.0258, −0.0018] | −13.7 pp | [−29.0, +2.7] |
Calm-contango by VRP sign¶
| variant | label | n | mean | hit rate | worst |
|---|---|---|---|---|---|
| proxy | calm-contango-vrp+ |
440 | 0.0369 | 0.882 | −0.2458 |
| proxy | calm-contango-vrp- |
282 | 0.0244 | 0.894 | −0.2622 |
| canonical | calm-contango-vrp+ |
85 | 0.0200 | 0.882 | −0.1500 |
| canonical | calm-contango-vrp- |
637 | 0.0061 | 0.714 | −0.2814 |
On the proxy over these years, hit rate within calm-contango-vrp+ rises with ex-ante VRP
(0.843 at [0,1) → 0.972 at [3,4)). That is the opposite of the 2009–2026 table, where it fell.
Lockout: share of labelled days in transition¶
| variant | 2022 | 2023 | 2024 | 2025 | 2026 (to 09-22) | all | confirmed-label changes | VRP-sign changes |
|---|---|---|---|---|---|---|---|---|
| proxy | 75.3% | 59.2% | 69.0% | 70.6% | 34.3% | 63.3% | 156 | 164 |
| canonical | 72.9% | 39.2% | 32.1% | 38.7% | 52.5% | 46.8% | 112 | 144 |
Full per-label, per-bucket and SVI tables: 2026-10-04-tier1-canonical-iv30-tables.md.
What this means for the open decisions¶
#39: both findings were artifacts of window and measure, not robust evidence.
- Transition lockout: on 2022–2026 there is no established difference between transition and settled days under either measure (all four intervals straddle 0 widely). The 2009–2026 proxy result does not reproduce here. The lockout is neither supported nor refuted by Tier 1; there is no evidence to remove it on.
- VRP sign: the "
vrp-beatsvrp+" inversion does not hold on these years even on the proxy, and on canonical IV30 it reverses.vrp+realises better on mean (interval excludes 0, chain and SVI) and on hit rate (excludes 0 on chain; marginal on SVI). On the measure the cutover adopts, the sign axis carries information in the direction the mapping assumes. Option (a) in #39, dropping the sign from the label, is not supported.
#18 (cutover): two consequences to weigh, beyond the known −2.6 pt level shift.
- Premium-selling eligibility becomes rare. Canonical
calm-contango-vrp+occurred on 85 of 722 calm-contango days (~18/year), against 440 on the proxy. Its realisation is better per day, but the book would be eligible to sell premium far less often. - Lockout falls overall (63% → 47%) but rises in the current regime. 2026 is 52.5% on canonical vs 34.3% on the proxy, because canonical VRP sits near zero and flips (34 sign changes in 2026 vs 9). That matches what the live gate showed 09-22 → 10-01.
#15 (θ): canonical calm-contango-vrp+ mean realisation is +2.0 vol pts before costs
(median +2.2), and all canonical regimes together average +0.7. That is close to the
"< ~1 vol pt after costs is not worth it" line in the 10-03 strategy note. Any θ on the
canonical measure has very little room.
Limitations¶
- Short window. ~4.7 years, one hiking cycle, one bear market (2022). The
calm-contango-vrp+canonical cell is 85 days ≈ 3 non-overlapping 30-day windows of independent information. The bootstrap interval is the honest statement of that, and it is wide. - Overlapping outcomes. Read
nas an upper bound. - Entry richness, not P&L.
iv − rv_fwdis not the P&L of any traded structure; Tier 2 is still blocked. - Partly mechanical. The label's VRP and the outcome share
iv_t. That's the definition of VRP, and identical in both variants, so the comparison is fair. But some of any sign effect is the HAR forecast's skill at predicting realised vol. - One underlying, one canonical source (SVI is the same chains, not an independent check).
- Hysteresis starts empty on 2022-01-03 in both variants.
Inputs (committed, PR #51 review fix)¶
The canonical series are committed under backtest/data/ so the canonical half can be re-derived from the repo:
| file | sha256 (as committed, LF line endings) |
|---|---|
iv30-spy-chain-inverted-2022-2026.csv |
7a5411ebe7654040f5a6eb9a6afcce07704cf93871ca9f99550e5d3096d800d5 |
iv30-spy-svi-2022-2026.csv |
ca93b252047cef26f16da0c8deb029f8b1b530c7460351df5aa8ecfed84f8cb5 |
Hashes are of the committed bytes. .gitattributes normalises text to LF, and the 09-30 originals were CRLF (sha256 79c751af… / 0591422e…); the CSV values are identical. A fresh checkout of this branch reproduces every number in this receipt exactly (contrasts-48.json compared byte-for-byte as JSON).
Produced 2026-09-30 by backtest/iv30_from_chain.py / iv30_from_svi.py from the VolSurfAE store (data/odifs/volsurfae.duckdb, SVI parquet), which is not on hermes. Regenerating the CSVs needs that store; re-deriving every table from the CSVs does not. Use an interpreter with numpy (on hermes: /usr/bin/python3). The fidelity replay's runtime varies by host, from about 1 min to about 8 min.
Source audit (2026-10-05, #53)¶
The committed chain CSV was regenerated from its source, the VolSurfAE store (ai-rig.local:~/src/VolSurfAE/data/odifs/volsurfae.duckdb, opened read-only), with the committed backtest/iv30_from_chain.py unchanged except for a private output path.
- 1,182 of 1,189 dates byte-identical across all 6 columns. 7 dates differ by at most 0.136 vol pts, each on one expiry of an unchanged expiry pair, consistent with source quotes revised after 2026-09-30. No date is missing from either side.
- Every result in this receipt is unchanged on the regenerated series: same days, the same 483 sign flips, and the same n, means and 95% intervals for all four proxy and canonical contrasts. The only change is canonical calm-contango
vrp− minus vrp+mean −0.0139 → −0.0138 (interval unchanged). - The committed CSV is kept as-is, since it is the artifact this receipt describes. A regeneration's sha256 will differ from the one recorded above wherever the store has revised a row.
- The store extends the series past this receipt (through 2026-10-02 at the time of the audit), which is what the #18 same-date level check (#58) uses.
Reproduce¶
cd backtest
# needs cache/fred_vix_vix3m.csv, cache/spy_closes.json (hermes, 2026-09-27)
python3 characterise_canonical.py --boot 2000
python3 test_backtest.py
Writes out/characterisation-48-canonical.md, out/contrasts-48.json and
out/features-48-{proxy,canonical,canonical-svi}.jsonl. Runtime about 70 s.