Observatory Signal

Vix Term Structure

vix_term_structure/validation

Signal Data

MetricValue
VerdictCONFIRMED
p-value3.1168470629526914e-07

Description

VIX/VIX3M ratio (term structure slope) -> SPY forward returns. Backwardation = contrarian buy signal.

Additional Data

{
  "signal": "vix_term_structure",
  "data_source": "VIX: FRED/CBOE, VIX3M: CBOE CDN, SPY: cache",
  "data_range": "2010-01-04 to 2026-04-01",
  "n_observations": 4086,
  "regime_counts": {
    "contango (<0.90)": 2394,
    "normal (0.90-1.00)": 1371,
    "mild_backwardation (1.00-1.10)": 252,
    "severe_backwardation (>=1.10)": 69
  },
  "regime_analysis": {
    "5d": {
      "severe_backwardation": {
        "n": 69,
        "mean_fwd_return": -0.24271255393285068,
        "median_fwd_return": 1.2268023063401188,
        "mean_non_regime": 0.28242836669056676,
        "hit_rate": 0.6376811594202898,
        "base_rate": 0.6102666334413157,
        "hit_rate_lift": 0.02741452597897409,
        "mann_whitney_p": 0.1428612321381877,
        "cohens_d": -0.23502990755639297
      },
      "mild_backwardation": {
        "n": 250,
        "mean_fwd_return": 1.1435027927214332,
        "median_fwd_return": 1.478410802220381,
        "mean_non_regime": 0.2167959736762837,
        "hit_rate": 0.628,
        "base_rate": 0.6096033402922756,
        "hit_rate_lift": 0.018396659707724416,
        "mann_whitney_p": 6.964656298365433e-08,
        "cohens_d": 0.41662723074237096
      },
      "contango": {
        "n": 2394,
        "mean_fwd_return": 0.20213665949171203,
        "median_fwd_return": 0.35455251390630593,
        "mean_non_regime": 0.3748357265904732,
        "hit_rate": 0.6123642439431913,
        "base_rate": 0.6084123222748815,
        "hit_rate_lift": 0.003951921668309821,
        "mann_whitney_p": 4.3634121997525185e-07,
        "cohens_d": -0.07731301896945228
      }
    },
    "10d": {
      "severe_backwardation": {
        "n": 69,
        "mean_fwd_return": -0.25763969002567355,
        "median_fwd_return": 2.8302788350691515,
        "mean_non_regime": 0.5588778669877462,
        "hit_rate": 0.6231884057971014,
        "base_rate": 0.6459580838323353,
        "hit_rate_lift": -0.022769678035233887,
        "mann_whitney_p": 0.016637263181044384,
        "cohens_d": -0.27076781444054876
      },
      "mild_backwardation": {
        "n": 247,
        "mean_fwd_return": 1.8803545957909167,
        "median_fwd_return": 2.6156063631434847,
        "mean_non_regime": 0.45894458671403643,
        "hit_rate": 0.7004048582995951,
        "base_rate": 0.6420365535248042,
        "hit_rate_lift": 0.058368304774790936,
        "mann_whitney_p": 7.563158727194138e-12,
        "cohens_d": 0.47407529826868144
      },
      "contango": {
        "n": 2394,
        "mean_fwd_return": 0.3955064131966495,
        "median_fwd_return": 0.6586572289509718,
        "mean_non_regime": 0.757791443305013,
        "hit_rate": 0.6482873851294904,
        "base_rate": 0.6417112299465241,
        "hit_rate_lift": 0.006576155182966281,
        "mann_whitney_p": 8.381425830049526e-14,
        "cohens_d": -0.12027560144911734
      }
    },
    "20d": {
      "severe_backwardation": {
        "n": 69,
        "mean_fwd_return": 2.1392964265995147,
        "median_fwd_return": 3.9176316742676818,
        "mean_non_regime": 1.0890462526489866,
        "hit_rate": 0.7101449275362319,
        "base_rate": 0.6838419209604802,
        "hit_rate_lift": 0.026303006575751686,
        "mann_whitney_p": 0.0001295096320377815,
        "cohens_d": 0.25210648065666635
      },
      "mild_backwardation": {
        "n": 244,
        "mean_fwd_return": 2.997919554517669,
        "median_fwd_return": 2.830115191021619,
        "mean_non_regime": 0.9861695004508771,
        "hit_rate": 0.7090163934426229,
        "base_rate": 0.6827099136803557,
        "hit_rate_lift": 0.026306479762267188,
        "mann_whitney_p": 6.6247619438144674e-09,
        "cohens_d": 0.4858567264563621
      },
      "contango": {
        "n": 2394,
        "mean_fwd_return": 0.7572665811327841,
        "median_fwd_return": 1.2893747140304441,
        "mean_non_regime": 1.6071262261172319,
        "hit_rate": 0.6649958228905597,
        "base_rate": 0.7118947997609085,
        "hit_rate_lift": -0.04689897687034883,
        "mann_whitney_p": 2.1343426394580037e-21,
        "cohens_d": -0.20493041077927002
      }
    },
    "60d": {
      "severe_backwardation": {
        "n": 69,
        "mean_fwd_return": 9.685929503339628,
        "median_fwd_return": 9.086435075428028,
        "mean_non_regime": 3.2531907886737335,
        "hit_rate": 0.8115942028985508,
        "base_rate": 0.7642748863062152,
        "hit_rate_lift": 0.04731931659233557,
        "mann_whitney_p": 3.1168470629526914e-07,
        "cohens_d": 1.0051720339606067
      },
      "mild_backwardation": {
        "n": 243,
        "mean_fwd_return": 6.4593873913174145,
        "median_fwd_return": 6.130250192869212,
        "mean_non_regime": 3.164594910468007,
        "hit_rate": 0.8189300411522634,
        "base_rate": 0.7616279069767442,
        "hit_rate_lift": 0.057302134175519215,
        "mann_whitney_p": 6.572745964725088e-11,
        "cohens_d": 0.514329566842459
      },
      "contango": {
        "n": 2370,
        "mean_fwd_return": 2.355998372974157,
        "median_fwd_return": 3.466727351972544,
        "mean_non_regime": 4.804310279633264,
        "hit_rate": 0.7341772151898734,
        "base_rate": 0.8092939046469523,
        "hit_rate_lift": -0.07511668945707883,
        "mann_whitney_p": 6.567462181796813e-34,
        "cohens_d": -0.38614647699009574
      }
    }
  },
  "vix_spike_analysis": {
    "5d": {
      "n": 311,
      "mean_fwd_return": 0.5283463977764598,
      "median_fwd_return": 0.7911451857876273,
      "mean_non_regime": 0.25253835576754136,
      "hit_rate": 0.6495176848874598,
      "base_rate": 0.607531158843808,
      "hit_rate_lift": 0.04198652604365172,
      "mann_whitney_p": 0.0007479983952638884,
      "cohens_d": 0.1234490532156312
    },
    "10d": {
      "n": 311,
      "mean_fwd_return": 0.7926127250018374,
      "median_fwd_return": 1.6869758025643335,
      "mean_non_regime": 0.5246157182154924,
      "hit_rate": 0.6559485530546624,
      "base_rate": 0.6447158789166224,
      "hit_rate_lift": 0.011232674138039966,
      "mann_whitney_p": 8.499695948981876e-05,
      "cohens_d": 0.08884181103412175
    },
    "20d": {
      "n": 309,
      "mean_fwd_return": 1.5629047559243092,
      "median_fwd_return": 2.4645378541891176,
      "mean_non_regime": 1.0693668978034598,
      "hit_rate": 0.7055016181229773,
      "base_rate": 0.682543906333156,
      "hit_rate_lift": 0.02295771178982131,
      "mann_whitney_p": 0.0005243595463639858,
      "cohens_d": 0.11846648401040091
    }
  },
  "n_events": 69,
  "key_stats": {
    "severe_backwardation_20d_mean": 2.1392964265995147,
    "severe_backwardation_20d_p": 0.0001295096320377815,
    "severe_backwardation_20d_d": 0.25210648065666635,
    "severe_backwardation_20d_hit_rate": 0.7101449275362319,
    "severe_backwardation_20d_base_rate": 0.6838419209604802,
    "vix_spike_20d_mean": 1.5629047559243092,
    "vix_spike_20d_p": 0.0005243595463639858
  },
  "current_signal": {
    "date": "2026-04-01",
    "vix": 24.54,
    "vix3m": 24.86,
    "ratio": 0.9871279163314561,
    "regime": "NORMAL",
    "signal": "NEUTRAL"
  },
  "caveats": [
    "VIX/VIX3M overlap period: 2009-present (~4000 observations)",
    "Severe backwardation events cluster during crisis periods (2008, 2020, 2022) \u2014 survivorship/look-ahead bias risk",
    "VIX3M not interpolated \u2014 only CBOE trading days included",
    "Contrarian signal: backwardation events co-occur with macro dislocations; forward returns reflect mean-reversion, not predictive edge",
    "VIX3M data from CBOE CDN starts 2009; analysis limited to 2009-2026",
    "Multiple horizon testing without Bonferroni correction \u2014 p-values should be interpreted cautiously",
    "DA crisis clustering test passed: 34.8% of events are in COVID window only (GFC predates VIX3M, RATE_SHOCK produced zero triggers); non-crisis events (n=45 days, ~11 independent) show mean 60d +8.5%, hit rate 84.4%, MW p<0.0001"
  ],
  "da_crisis_clustering": {
    "verdict": "DA_PASSED",
    "run_at": "2026-04-06T09:50:34.913869+00:00",
    "total_events": 69,
    "crisis_events_n": 24,
    "crisis_events_pct": 34.8,
    "crisis_breakdown": {
      "GFC": 0,
      "COVID": 24,
      "RATE_SHOCK": 0
    },
    "crisis_mean_60d": 11.979,
    "crisis_hit_rate": 0.75,
    "non_crisis_events_n": 45,
    "non_crisis_independent_n": 11,
    "non_crisis_mean_60d": 8.463,
    "non_crisis_median_60d": 8.991,
    "non_crisis_hit_rate": 0.8444,
    "non_crisis_mw_p": 1e-05,
    "baseline_mean_60d": 3.267,
    "moderate_backwardation_non_crisis": {
      "n": 40,
      "mean_60d": 7.487,
      "hit_rate": 0.875,
      "mw_p": 5.7e-05
    },
    "verdict_reason": "Non-crisis events (n=45 days, ~11 independent) show mean 60d return of 8.5% (hit rate 84.4%, MW p=0.000). Signal holds outside crisis windows \u2014 not purely crisis-driven.",
    "key_finding": "Crisis clustering DA PASSED. Only COVID cluster present (GFC predates VIX3M data, 2022 rate shock produced zero severe-backwardation events). Non-crisis signal is stronger on hit rate (84% vs 75%) though slightly lower mean (8.5% vs 12.0%). Moderate backwardation (1.05-1.10) outside crises also strong: n=40, mean=7.5%, hit rate=87.5%, p=0.0001."
  }
}

Signal identifier: vix_term_structure/validation