← Results index

Wire generic harness for VIX contango experiment qm-kdnj.3

2026-08-19T01:20:00Z Experiment completed Wired generic opposite-signal harness for the VIX contango Pine experiment qm-kdnj.3 (VIX/VIX3M EMA50/252, sell when EMA50>EMA252, SMA-seed, 252 warmup, continuous regime) with ^VIX 9215 rows and ^VIX3M 5032 rows persisted offline in data/market.sqlite via yahoo instruments and published head-to-head generic-only versus VIX+generic deltas on the same window/costs/lag (2007-07-17→2026-07-17 4781 valid 43.25% active via BacktestConfig.allocatesmartly next_close 10bps, AND blend) showing SMA200 -52.97% (4.6786→2.2004, CAGR -4.23% Sharpe -0.22), SMA50 -42.35%, cross -56.87%, trailing -61.62% and BH -66.69% VIX-only as a deterministic delta table in docs/experiments/qm-kdnj.3.html, verified by 7 offline harness tests (81 focused tests pass, artifacts deterministic, no DB mutation).

Objective

For qm-kdnj.3 (Pine VIX/VIX3M EMA50/252 vix_ratio_long_ema = ta.ema(vix_data/vix3m_data,252) vix_ratio_short_ema = ta.ema(vix_data/vix3m_data,50) sell = short>long continuous regime, VIX 9215 rows 1990-01-02..2026-08-04 and VIX3M 5032 rows 2006-07-17..2026-07-17 yahoo persisted in data/market.sqlite instruments), wire the generic opposite-signal harness head-to-head deltas as for qm-u94t.1/qm-0azu (SPX <50DMA, <200DMA, 50/200 death-cross, trailing-stop 10% via backtest/generic_signals.py) with datastore provenance already in instruments and offline repro. The delta table must render in the parity page and offline test must pass without live fetch.

Approach

  1. Froze VIX provenance: ^VIX 9215 and ^VIX3M 5032 daily closes yahoo yfinance Yahoo chart API persisted data/market.sqlite:ohlcv + instruments (provider yahoo, field Close, frequency D, native spans 1990-01-02 live and 2006-07-17 live) via backtest.datastore import-cache; verified coverage_ohlcv slack 5d and ensure_universe([SPY,^VIX,^VIX3M], offline=True) returns intersection 5032 with full 9215 still via read_ohlcv, UTC-naive sorted unique, one-bar lag via BacktestConfig.allocatesmartly next_close.
  1. Reused backtest/generic_signals.py (deterministic, causal): sma_signal, cross_signal, trailing_stop_signal 10% expanding peak, bh_signal via all_generic_signals/generic_weights + validate_weights.
  1. Created research/scripts/publish_vix_contango_qm_kdnj3.py (build_manifest, compute_harness offline): loads SPY/^VIX/^VIX3M via ensure_universe offline=True → vix_contango_signals EMA50/252 with SMA-seed (ta.ema alpha 2/(len+1)) → valid 2007-07-17→2026-07-17 4781 bars 43.25% sell active, then for each generic defensive computes paired backtests on same window 2007-07-17→2026-07-17 with BacktestConfig.allocatesmartly (next_close, fee 10bps) via AND blend (cash if either VIX sell or generic defensive; BH blended equals VIX regime alone) and metrics (equity, CAGR, Sharpe, MaxDD, delta%). Emits metrics.generic_exit_harness + supplemental generic_exit_harness_detail/rows + research_narrative and monthly rebased equity.
  1. Fixed research/reports/experiments.py dedup: previously findings-based stub for qm-kdnj.3 (slug qm-kdnj-3-vix...) hid registry manifest harness; now registry manifest wins when id exists in registry (skip finding entry if in registry_ids), so supplemental harness renders via /qm-kdnj.3.html.
  1. Updated research/reports/scaffold.py already renders generic-exit-harness table from supplemental.generic_exit_harness_rows (fallback to dict mapping) with Generic/Generic-only/Signal+Generic Δ%/ΔCAGR/ΔSharpe plus window/note; no hand-edited payloads.
  1. Added tests/test_vix_contango_generic_harness.py (7 offline, no network, no DB mutation): ensure_ohlcv 9215/5032, generic signals deterministic/causal, VIX EMA SMA-seed continuous 2007-07-17 and valid 4781, harness deltas (sma200 -52.97% etc, bh negative as VIX-only underperforms), manifest/site-data/html contain harness, no mutation, one-bar lag and costs.

Files changed

Validation

Results

Datastore persistence verified offline: ^VIX 9215 yahoo 1990-01-02..2026-08-04 and ^VIX3M 5032 yahoo 2006-07-17..2026-07-17 in instruments, VIX contango valid 4781 of 5032 after 252 warmup (2007-07-17→2026-07-17, 43.25% sell active). Continuous regime Pine fidelity already frozen (SMA-seed EMA, 31.9% mismatch vs 4-point ensemble fixed) and rejected for economics (CAGR 4.24% vs 10.58% BH). Generic harness paired each defensive head-to-head same window/costs/lag (BacktestConfig.allocatesmartly next_close 10bps, AND blend): SMA200 generic-only 4.6786 → VIX+generic 2.2004 Δ-52.97% (CAGR 8.47%→4.24% Δ-4.23% Sharpe 0.72→0.51 Δ-0.22 MaxDD -20.9%→-22.3%), SMA50 2.2299→1.2856 Δ-42.35%, cross 50/200 4.5627→1.9677 Δ-56.87%, trailing 10% 3.6447→1.3987 Δ-61.62%, BH 6.8080→2.2675 Δ-66.69% (VIX-only) — all negative showing VIX regime adds defensiveness but hurts return vs generic alone on this window, consistent with prior overlay underperformance. Delta table renders in docs/experiments/qm-kdnj.3.html section generic-exit-harness with Δ% ΔCAGR ΔSharpe.

Links

Source artifact: research/results/qm-60x1.md