Tier 1 on canonical IV30 vs the proxy, same days (#48)
Days: 1184 (2022-01-03 .. 2026-09-22). Scored (label + forward outcome): proxy 1155, canonical 1155. VRP sign differs between the two on 483/1182 labelled days (40.9%).
Labels: production's pure functions, composed in backtest/replay_variants.py; the proxy variant matches production main() on every field of every day (0 mismatches over 1184 days, checked before this was written).
Outcome on each variant's own measure: vrp_realised = iv_t - rv_fwd_30.
The two contrasts #39 turns on
95% moving-block bootstrap intervals, block = 30 trading days, 2000 resamples, seed 48. An interval that straddles 0 means the sign of the difference is not established on this sample.
| 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 pp, +4.4 pp] |
| proxy |
calm-contango: vrp- minus vrp+ |
282 / 440 |
-0.0125 |
[-0.0245, +0.0007] |
+1.2 pp |
[-8.1 pp, +14.1 pp] |
| canonical |
transition - settled |
551 / 604 |
-0.0005 |
[-0.0269, +0.0187] |
+0.2 pp |
[-14.9 pp, +13.9 pp] |
| canonical |
calm-contango: vrp- minus vrp+ |
637 / 85 |
-0.0139 |
[-0.0253, -0.0021] |
-16.8 pp |
[-29.4 pp, -2.9 pp] |
| canonical-svi |
transition - settled |
565 / 589 |
-0.0015 |
[-0.0270, +0.0172] |
+1.0 pp |
[-13.6 pp, +14.5 pp] |
| canonical-svi |
calm-contango: vrp- minus vrp+ |
633 / 88 |
-0.0135 |
[-0.0258, -0.0018] |
-13.7 pp |
[-29.0 pp, +2.7 pp] |
Churn: how often the gate is locked out
| variant |
year |
labelled days |
in transition |
share |
confirmed-label changes |
VRP-sign changes |
| proxy |
2022 |
251 |
189 |
75.3% |
36 |
48 |
| proxy |
2023 |
250 |
148 |
59.2% |
34 |
32 |
| proxy |
2024 |
252 |
174 |
69.0% |
37 |
45 |
| proxy |
2025 |
248 |
175 |
70.6% |
38 |
30 |
| proxy |
2026 |
181 |
62 |
34.3% |
11 |
9 |
| proxy |
all |
1182 |
748 |
63.3% |
156 |
164 |
| canonical |
2022 |
251 |
183 |
72.9% |
38 |
52 |
| canonical |
2023 |
250 |
98 |
39.2% |
22 |
14 |
| canonical |
2024 |
252 |
81 |
32.1% |
14 |
18 |
| canonical |
2025 |
248 |
96 |
38.7% |
20 |
26 |
| canonical |
2026 |
181 |
95 |
52.5% |
18 |
34 |
| canonical |
all |
1182 |
553 |
46.8% |
112 |
144 |
Tables — proxy
Transition vs settled (proxy)
| group |
n |
mean |
median |
p10 |
p25 |
p75 |
p90 |
hit rate |
worst |
settled |
412 |
0.0362 |
0.0401 |
-0.0141 |
0.0231 |
0.0566 |
0.0742 |
0.876 |
-0.113 |
transition |
743 |
0.0317 |
0.0397 |
-0.0264 |
0.0114 |
0.0676 |
0.094 |
0.833 |
-0.2622 |
By raw label (proxy)
| group |
n |
mean |
median |
p10 |
p25 |
p75 |
p90 |
hit rate |
worst |
calm-contango-vrp+ |
440 |
0.0369 |
0.0428 |
-0.0116 |
0.0247 |
0.061 |
0.0765 |
0.882 |
-0.2458 |
calm-contango-vrp- |
282 |
0.0244 |
0.0309 |
-0.0009 |
0.0157 |
0.0438 |
0.0556 |
0.894 |
-0.2622 |
calm-flat-vrp+ |
38 |
0.005 |
0.0407 |
-0.2244 |
-0.0216 |
0.0717 |
0.0766 |
0.658 |
-0.2377 |
calm-flat-vrp- ⚠ thin |
2 |
0.0121 |
0.0121 |
-0.0227 |
-0.0227 |
0.0469 |
0.0469 |
0.5 |
-0.0227 |
normal-backwardation-vrp+ ⚠ thin |
4 |
-0.0159 |
-0.0188 |
-0.1678 |
-0.1568 |
0.1419 |
0.1419 |
0.5 |
-0.1678 |
normal-contango-vrp+ |
123 |
0.0278 |
0.0345 |
-0.0412 |
-0.0161 |
0.0779 |
0.0934 |
0.683 |
-0.0991 |
normal-contango-vrp- |
63 |
0.0198 |
0.0359 |
-0.0568 |
0.0049 |
0.0493 |
0.0525 |
0.794 |
-0.117 |
normal-flat-vrp+ |
123 |
0.0383 |
0.0796 |
-0.1949 |
0.0136 |
0.0995 |
0.1174 |
0.821 |
-0.2303 |
normal-flat-vrp- ⚠ thin |
19 |
0.0561 |
0.0573 |
0.0024 |
0.0142 |
0.099 |
0.1138 |
0.947 |
-0.0015 |
stressed-backwardation-vrp+ ⚠ thin |
7 |
0.1077 |
0.1475 |
-0.1137 |
0.0779 |
0.1589 |
0.2343 |
0.857 |
-0.1137 |
stressed-backwardation-vrp- ⚠ thin |
3 |
0.1538 |
0.1569 |
0.1335 |
0.1335 |
0.171 |
0.171 |
1.0 |
0.1335 |
stressed-contango-vrp+ ⚠ thin |
1 |
-0.007 |
-0.007 |
-0.007 |
-0.007 |
-0.007 |
-0.007 |
0.0 |
-0.007 |
stressed-contango-vrp- ⚠ thin |
1 |
0.0339 |
0.0339 |
0.0339 |
0.0339 |
0.0339 |
0.0339 |
1.0 |
0.0339 |
stressed-flat-vrp+ |
45 |
0.0695 |
0.0649 |
0.0137 |
0.0345 |
0.0987 |
0.1177 |
1.0 |
0.0069 |
stressed-flat-vrp- ⚠ thin |
4 |
0.0887 |
0.1015 |
0.0112 |
0.0976 |
0.1404 |
0.1404 |
1.0 |
0.0112 |
calm-contango-vrp+ by ex-ante VRP bucket (proxy)
| group |
n |
mean |
median |
p10 |
p25 |
p75 |
p90 |
hit rate |
worst |
[0, 1) |
172 |
0.0283 |
0.0364 |
-0.0384 |
0.0166 |
0.0593 |
0.0726 |
0.843 |
-0.2458 |
[1, 2) |
117 |
0.0399 |
0.0423 |
-0.0019 |
0.0269 |
0.0586 |
0.0798 |
0.889 |
-0.0457 |
[2, 3) |
90 |
0.0391 |
0.0425 |
-0.0064 |
0.0247 |
0.057 |
0.0762 |
0.889 |
-0.0863 |
[3, 4) |
36 |
0.0553 |
0.0593 |
0.0285 |
0.0352 |
0.0775 |
0.0882 |
0.972 |
-0.0005 |
[4, 6) ⚠ thin |
25 |
0.0481 |
0.0565 |
0.0206 |
0.0379 |
0.0681 |
0.0705 |
0.96 |
-0.113 |
Tables — canonical
Transition vs settled (canonical)
| group |
n |
mean |
median |
p10 |
p25 |
p75 |
p90 |
hit rate |
worst |
settled |
604 |
0.0073 |
0.011 |
-0.0453 |
-0.004 |
0.0294 |
0.0447 |
0.704 |
-0.1414 |
transition |
551 |
0.0068 |
0.0249 |
-0.0646 |
-0.0087 |
0.048 |
0.0663 |
0.706 |
-0.2814 |
By raw label (canonical)
| group |
n |
mean |
median |
p10 |
p25 |
p75 |
p90 |
hit rate |
worst |
calm-contango-vrp+ |
85 |
0.02 |
0.0222 |
-0.0036 |
0.0069 |
0.0353 |
0.0418 |
0.882 |
-0.15 |
calm-contango-vrp- |
637 |
0.0061 |
0.0124 |
-0.0473 |
-0.0026 |
0.0294 |
0.0445 |
0.714 |
-0.2814 |
calm-flat-vrp+ |
30 |
-0.0036 |
0.0314 |
-0.1379 |
-0.0227 |
0.0452 |
0.055 |
0.733 |
-0.2743 |
calm-flat-vrp- ⚠ thin |
10 |
-0.0644 |
-0.0377 |
-0.2561 |
-0.0523 |
-0.0154 |
0.0441 |
0.2 |
-0.259 |
normal-backwardation-vrp+ ⚠ thin |
4 |
-0.0726 |
-0.0731 |
-0.1978 |
-0.1966 |
0.0535 |
0.0535 |
0.5 |
-0.1978 |
normal-contango-vrp+ |
61 |
0.0313 |
0.0435 |
-0.0423 |
0.009 |
0.0608 |
0.0754 |
0.787 |
-0.0988 |
normal-contango-vrp- |
125 |
-0.0145 |
-0.0051 |
-0.1007 |
-0.051 |
0.0315 |
0.0451 |
0.48 |
-0.1414 |
normal-flat-vrp+ |
96 |
0.009 |
0.0444 |
-0.2225 |
0.0048 |
0.0708 |
0.0824 |
0.771 |
-0.2579 |
normal-flat-vrp- |
46 |
0.0101 |
0.0338 |
-0.0308 |
-0.0181 |
0.0608 |
0.0712 |
0.63 |
-0.2519 |
stressed-backwardation-vrp+ ⚠ thin |
7 |
0.0415 |
0.0556 |
-0.1544 |
0.0029 |
0.1147 |
0.1445 |
0.857 |
-0.1544 |
stressed-backwardation-vrp- ⚠ thin |
3 |
0.1114 |
0.1196 |
0.0927 |
0.0927 |
0.1218 |
0.1218 |
1.0 |
0.0927 |
stressed-contango-vrp- ⚠ thin |
2 |
-0.0189 |
-0.0189 |
-0.0476 |
-0.0476 |
0.0098 |
0.0098 |
0.5 |
-0.0476 |
stressed-flat-vrp+ |
36 |
0.0332 |
0.0332 |
-0.0178 |
0.0171 |
0.0611 |
0.0725 |
0.778 |
-0.0372 |
stressed-flat-vrp- ⚠ thin |
13 |
0.0314 |
0.051 |
-0.0292 |
-0.0236 |
0.0664 |
0.0807 |
0.692 |
-0.0384 |
calm-contango-vrp+ by ex-ante VRP bucket (canonical)
| group |
n |
mean |
median |
p10 |
p25 |
p75 |
p90 |
hit rate |
worst |
[0, 1) |
49 |
0.0165 |
0.017 |
-0.0067 |
0.0027 |
0.0341 |
0.0456 |
0.857 |
-0.15 |
[1, 2) |
32 |
0.0251 |
0.0267 |
0.0032 |
0.0143 |
0.0385 |
0.0416 |
0.906 |
-0.0153 |
[2, 3) ⚠ thin |
4 |
0.0224 |
0.0256 |
0.0033 |
0.0194 |
0.035 |
0.035 |
1.0 |
0.0033 |
Robustness — canonical from the SVI surface instead of chain inversion
Transition vs settled (canonical-svi)
| group |
n |
mean |
median |
p10 |
p25 |
p75 |
p90 |
hit rate |
worst |
settled |
589 |
0.0078 |
0.0126 |
-0.0486 |
-0.0046 |
0.031 |
0.0453 |
0.699 |
-0.1422 |
transition |
565 |
0.0063 |
0.0233 |
-0.0609 |
-0.0071 |
0.0447 |
0.0649 |
0.71 |
-0.2824 |
calm-contango by VRP sign (canonical-svi)
| group |
n |
mean |
median |
p10 |
p25 |
p75 |
p90 |
hit rate |
worst |
calm-contango-vrp+ |
88 |
0.0201 |
0.0231 |
-0.0046 |
0.005 |
0.0355 |
0.0532 |
0.852 |
-0.1492 |
calm-contango-vrp- |
633 |
0.0066 |
0.0138 |
-0.0463 |
-0.0021 |
0.0302 |
0.0446 |
0.716 |
-0.2824 |
Limitations — these bound every number above
- Short window. 2022-01-03 .. 2026-09-22 is ~4.7 years, one rate-hiking
cycle and one bear market (2022). The 2009-2026 proxy tables in the 09-27
receipt are not comparable row-for-row; the proxy rows HERE, on the same days,
are the like-for-like baseline.
- Overlapping outcomes. Each day's outcome shares up to 29 of its 30 forward
days with its neighbours. Read
n as an upper bound; the block-bootstrap
intervals are the honest uncertainty for the two contrasts.
- Outcome is entry richness, not P&L.
vrp_realised = iv_t - rv_fwd_30 says
whether implied exceeded what was realised. It is not the P&L of any traded
structure; that needs Tier 2 (historical chains through the EV engine).
- One underlying. SPY only; no cross-sectional evidence.
- Canonical series provenance. Chain-inverted SPY ATM IV30 from EOD chains
(backtest/iv30_from_chain.py, r = 10Y TNX, a known tenor mismatch whose ATM
effect is small once the forward is parity-implied). The SVI series is shown as
a robustness check, not as a second independent source (same chains).
- Hysteresis starts empty on 2022-01-03 in both variants, so the first few
days bootstrap a confirmation. Identical across variants, so it cannot favour
either.