Public research example — internal demonstration

Volatility Term-Structure Strategy

A transparent SPY allocation example combining a lagged VIX term-structure filter, realized-volatility targeting, leverage limits and explicit turnover costs.

This is not a client case study. It is a deliberately simple strategy, built internally, to demonstrate how a transparent quantitative strategy can be documented and reviewed — not evidence of a validated or profitable trading system.

View the repository on GitHub (opens in a new tab)

Strategy overview

The strategy allocates to SPY using two other public instruments as inputs: the VIX index and the VIX3M index.

It holds SPY only when the lagged VIX3M/VIX term-structure ratio is above 1.0 — a simple regime filter for calmer volatility conditions.

When the regime filter is on, exposure is sized to target 10% annualized volatility, using a 20-trading-day trailing realized-volatility estimate, and capped at a maximum of 2x leverage.

A simplified linear cost of 1 basis point per unit of turnover is charged on every change in exposure.

Timing convention

The causal convention is explicit and unit-tested in the repository:

  • Both signal features — the VIX3M/VIX ratio and realized volatility — are lagged by one trading observation.
  • Exposure on row t is therefore computed from information available only through t-1.
  • That exposure is applied to the row-t close-to-close SPY return.
  • No additional execution shift is used in the published reference implementation.
term_structure_lag[t] = (VIX3M / VIX)[t-1]
realized_vol_lag[t]   = std(SPY returns, 20 days)[t-1] * sqrt(252)
exposure[t]           = 1(term_structure_lag[t] > 1.0)
                        * min(0.10 / realized_vol_lag[t], 2.0)
strategy_return[t]    = exposure[t] * SPY_return[t]
                        - turnover[t] * 1 bp

Snapshot metrics

Sample: 2013-02-01 to 2026-07-17 — 3,384 aligned trading observations.

Strategy vs. SPY buy-and-hold

MetricStrategySPY buy-and-hold
CAGR8.13%14.62%
Annualized volatility10.60%16.86%
Sharpe (0% risk-free rate)0.7910.894
Maximum drawdown-17.17%-33.72%
Total return185.81%525.23%

Additional diagnostics

DiagnosticValue
Annualized active return-6.69%
Information ratio-0.554
Correlation with SPY0.701
Beta to SPY0.441
Average SPY exposure85.1%
Annualized turnover17.15x
Regime on92.6% of observations

Metrics are descriptive history from the committed repository snapshot, not a claim of future performance.

Charts

Line chart of the growth of $1 invested since 2013 in the strategy compared with SPY buy-and-hold, plotted on a logarithmic scale.
Growth of $1
Line chart comparing the strategy drawdown with the SPY buy-and-hold drawdown over time, showing a shallower maximum drawdown for the strategy.
Strategy and SPY drawdowns
Three stacked panels showing the lagged VIX3M/VIX term-structure ratio, the lagged realized-volatility estimate, and the resulting SPY exposure over time.
Lagged term structure, realized volatility and SPY exposure

What this example demonstrates

  • Explicit timing conventions matter: stating exactly what information each row of exposure uses, and when, is what makes a backtest auditable.
  • Volatility targeting can reduce realized volatility and historical drawdown relative to a buy-and-hold benchmark.
  • Lower risk does not automatically imply benchmark outperformance — this example underperformed SPY buy-and-hold on CAGR and total return over the sample.
  • A clear, like-for-like benchmark prevents risk reduction from being mistaken for alpha.
  • Reproducible code, machine-readable metrics and derived data make a result inspectable, rather than asking for trust.

Reproducibility

  • Built and tested with Python 3.12.
  • Pinned top-level dependencies, listed in the repository’s requirements file.
  • A standalone analysis script reproduces the metrics, the derived CSV and all three charts from a single command.
  • Machine-readable metrics are committed alongside the code, together with the exact strategy configuration used.
  • The derived CSV of aligned returns and exposure is committed and bound to the metrics file by a SHA-256 hash, so the snapshot cannot silently drift from the numbers shown here.
  • Synthetic-data unit tests cover feature timing, exposure bounds and cost accounting.
  • A GitHub Actions workflow runs the test suite on every change.

View source on GitHub (opens in a new tab)

Limitations

  • Yahoo Finance is a convenient public data source, not a point-in-time institutional archive — historical observations may be revised.
  • VIX and VIX3M are regime indicators; the strategy does not trade VIX products directly.
  • The backtest does not model bid/ask spreads, market impact, taxes, financing, borrow constraints or intraday execution.
  • The cost model is a simplified, linear cost per unit of turnover.
  • The parameters were chosen for demonstration and are not presented as universally optimal.
  • This is a historical example, not investment advice or a forecast.