Volatility Regime & VRP Methodology
How SOPHIE computes the daily volatility regime and variance risk premium: the four-regime taxonomy validated against COVID and the GFC, the convexity and downside-variance decompositions, and the finding that VRP level has near-zero power to time entries (IC ~0.008) while the regime label is a strong risk signal.
Overview
This page is the implementation spec for the VRP Research tab in SOPHIE's Options Viewer: the volatility regime label, the variance risk premium decomposition, and the regime transition matrix. Variance Risk Premium covers the concept and the trading case; this page documents how the platform actually computes it and what the numbers did and did not show.
Every signal here is precomputed daily in the data pipeline, not derived in the browser. That is a hard requirement rather than an optimisation: a 252-day VIX percentile and an EWM z-score are history-dependent and cannot be recovered from a single live quote.
Data Sources
| Series | Source | Coverage | Used for |
|---|---|---|---|
SPX daily OHLCV (^GSPC) | Yahoo Finance → Postgres prices table | 2000-01-03 onward | Realized vol input (RV_20, fwd_earned_premium) and the entry/backtest overlay price |
VIX daily OHLCV (^VIX) | Yahoo Finance → Postgres prices table | 2000-01-03 onward | Implied vol side of VRP, vix_rank, entry price shown on the backtest chart |
| VIX3M (3-month VIX) | FRED series VXVCLS | 2007-12-04 onward | term_slope, term-structure/backwardation classification |
This is a distinct data path from the live/real-time VIX and SPX shown elsewhere in the Options Viewer (e.g. the GEX tab's stat tiles), which are streamed from Cboe's public delayed-quotes CDN, not from this Postgres history — the two are sourced differently because one needs 25 years of daily closes and the other needs a current snapshot.
Both SPX and VIX are pulled with the same ticker mapping and backfill job (YFINANCE_TICKER_MAP in the pipeline's upload tool), so they are aligned to the same trading calendar row-for-row — there is no date-join step where the two series could silently drift apart.
Two notes on sourcing. Yahoo no longer serves ^VIX3M history (it returns a single row, and the legacy ^VXV symbol is dead), so term structure comes from FRED instead. And the 2000 start is a deliberate choice, not a data ceiling — VIX itself reaches back to 1990, but VIX3M only begins in 2007, so every row before that is already classified on one axis instead of two. Extending further would deepen that inconsistency rather than fix it.
Core Signals
Computed once per trading day and stored:
How realized vol is actually calculated
Spelled out, since "stdev of returns" hides a few choices that change the number materially:
- Input. Daily SPX closing prices from the Postgres
pricestable (see Data Sources above) — not intraday, not adjusted for the overnight session in any special way. Close-to-close only. - Log returns. for each of the trailing 20 trading sessions (calendar days are irrelevant here; this is 20 sessions, so it stretches over roughly 4 calendar weeks depending on holidays).
- Sample standard deviation, not population — divides by , not . This matters slightly more in short windows; it's the standard unbiased-estimator choice and matches what the backtest's client-side recomputation was verified against.
- Annualize by (252 trading days/year), the same convention VIX itself uses, so the two are on a comparable scale.
- Scale to vol points by multiplying by 100 (i.e. report 15.3, not 0.153), matching how VIX is quoted.
The forward-looking version used by the backtest (fwd_earned_premium, and the client-side recomputation for other holding periods — see Backtest View below) is the identical formula applied to the following sessions instead of the trailing 20: same log-return construction, same sample stdev (ddof=1), same annualization. Only the direction of the window changes — trailing for the tradeable "quoted" signal, forward for the hindsight "actually earned" one. Keeping the formula identical in both directions is deliberate: it means the "quoted vs. earned" gap documented later on this page is a genuine finding about mean reversion, not an artifact of two different vol estimators being compared.
Why 20 trading days?
VIX targets a constant 30-calendar-day expected volatility (Cboe interpolates between the near- and next-term option chains to hit exactly that horizon). Twenty trading sessions cover roughly 29 calendar days — close enough to VIX's actual referent that the comparison is measuring "the same month," not two different-length periods. This is standard practitioner convention, not a platform-specific choice: 20-session historical volatility is the most commonly cited single-window proxy for comparing against a 30-day implied measure, with some sources using 21 sessions as the slightly more exact calendar-day match (Topstep; Macroption).
That 20-vs-21 split is visible in our own pipeline: the trailing window (RV_20, used for quoted VRP and the regime classification) uses 20 sessions, while the forward window (fwd_realized_vol_21d, used for the backtest and "actually earned") uses 21. Both are legitimate — 20 is the more common round-number convention for a trailing snapshot, 21 is the marginally tighter calendar-day match and was chosen for the forward side to line up with a standard trading month. The half-session difference this creates between "quoted" and "earned" is immaterial (it changes the realized-vol estimate by a fraction of a percentage point, far below the day-to-day noise in a 20-observation sample) and does not affect any of the sign or ranking results on this page.
Is one window enough? The pipeline also computes and stores realized_vol_10d alongside realized_vol_20d — a faster-reacting cross-check — but today it is only surfaced as a footnote stat on the panel, not used in the VRP calculation, the regime classification, or the backtest. That is a known simplification: right after a volatility spike rolls out of a 20-session lookback, RV_20 can stay elevated for another two-plus weeks after the tape has actually calmed (and the reverse going into a shock), and nothing on the panel currently flags when the 10-day and 20-day readings materially diverge. Relying on a single window is standard practice for a headline number, but a 10-vs-20 divergence check would be a legitimate future enhancement rather than a correction — it would sit alongside the existing trailing/forward pair as a third, orthogonal cross-check (window length) rather than replace either.
Supporting context measures:
vrp_z— EWM z-score of VRP (span 126, ~6 months). Is today's premium rich relative to its own recent history?vix_rank— 252-day percentile rank of VIX (0–1). Where does implied vol sit in its trailing year?term_slope— VIX3M − VIX. Negative means backwardation, i.e. near-term stress.
All are causal (backward-looking only), so a full recompute is deterministic and idempotent — past rows never change, unlike the Investment Clock where FRED revisions can restate history.
Regime Taxonomy
Two axes, mirroring the Investment Clock's quadrant logic: is premium rich, and is the tape stressed.
Calm (vix_rank ≤ 0.8 and not backwardated) | Stressed | |
|---|---|---|
Premium rich (vrp_z > 0) | Harvest | Stressed Premium |
Premium thin (vrp_z ≤ 0) | Thin | Crisis |
- Harvest — implied running well above realized in a calm tape. Historically the most favourable backdrop for selling premium.
- Stressed Premium — sellers are paid more than usual, but vol is elevated or the curve is backwardated. The premium is real and so is the tail risk.
- Thin — implied barely exceeds realized. Gap risk for a thin credit.
- Crisis — implied below realized. The index is delivering more movement than options are pricing; short vol is uncompensated.
Validation against known events
The classifier was checked against episodes where the answer is not in doubt:
| Event | Reading |
|---|---|
| COVID crash, Mar 2020 | Crisis — VRP collapsed to −33 as realized outran implied |
| GFC, Oct 2008 | Crisis → Stressed Premium as implied caught up to realized |
| Post-COVID, Jun 2020 | Harvest — rich premium after the spike |
Full-sample distribution: Harvest 44%, Thin 35.5%, Stressed Premium 11%, Crisis 9.5%. Average VRP by regime is monotonic in the expected direction — Crisis −3.80, Thin +1.20, Harvest +6.04, Stressed Premium +7.73.
VRP Decomposition
Vol points vs variance points
The headline VRP (VIX − RV, in "vol points") is the number usually quoted, but it overstates the premium through Jensen's inequality: . A variance swap pays on variance, so:
| Regime | VRP (vol pts) | VRP (variance pts) |
|---|---|---|
| Stressed Premium | +7.73 | +3.68 |
| Harvest | +6.04 | +1.83 |
| Thin | +1.20 | +0.21 |
| Crisis | −3.80 | −4.45 |
Harvest's headline +6.04 shrinks to +1.83 once convexity is stripped out — roughly two thirds of the apparent edge.
Downside vs upside variance
Realized variance is split into down-day and up-day contributions (Barndorff-Nielsen semivariance):
Full-sample mean is 0.458, but it separates sharply by regime — Stressed Premium 0.644 and Crisis 0.579 versus Harvest 0.403 and Thin 0.440. Stress-regime variance is downside-driven, which is direct evidence that VRP is compensation for downside risk rather than symmetric risk.
Does VRP Level Predict What You Earn?
The honest answer, and the most important result on the page: largely no.
Test: quintile every session by vrp_z, then measure what a seller of that day's implied vol actually collected over the following 21 sessions ( realized over ).
vrp_z quintile | Forward 21d earned | Hit rate |
|---|---|---|
| Q1 (thin) | +3.11 | 82.8% |
| Q2 | +3.43 | 85.6% |
| Q3 | +3.54 | 83.2% |
| Q4 | +3.80 | 82.6% |
| Q5 (rich) | +4.09 | 81.0% |
Spearman IC ≈ 0.008 across ~6,500 sessions. Essentially zero, and the hit rate slightly declines as premium gets richer.
Read precisely, that says the premium is real and persistent unconditionally (~+3.5 vol points at an ~82% hit rate) but its level does not time entries. It is also a direct caution against over-reading the earlier vrp09 backtest, whose 2.3 profit factor on a vrp_z > 0.5 filter came from two years and roughly 30 trades.
Caveat: forward earned premium is a first-order proxy. It ignores strike selection, delta hedging, and path, so it is not the same as option P&L. But a ~0.008 IC over 6,500 sessions is still a real warning.
Where the Regime Label Does Earn Its Keep
Transition risk. P(regime 21 sessions ahead | regime today):
| From | → Crisis in 21d |
|---|---|
| Harvest | 5.7% |
| Thin | 5.2% |
| Stressed Premium | 26.7% |
Stressed Premium is roughly 5× more likely to become Crisis than Harvest is. Harvest is also sticky (47.8% stays Harvest), while Thin mean-reverts upward (52.6% → Harvest).
The practical conclusion: use the regime for position sizing and risk, not for timing entries. The level of VRP tells you little about the next month's return; the regime label tells you a great deal about the chance of the tape turning against a short-vol position.
Reading the Panel: Scope and Measurement Basis
Two distinctions govern every number on the VRP Research tab, and conflating either is the easiest way to misread it. Both are labelled in the UI.
Scope — what window is this number over?
| Scope | What it covers | Where it appears |
|---|---|---|
| Point-in-time | A single date's reading | The four stat tiles at the top ("As of <date>") |
| Selected window | Whatever the timeframe picker is set to | The chart, its stats bar, the VIX distribution table, the backtest |
| Full history since 2000 | The entire ~6,575-session sample | The "How each regime has paid" table at the bottom |
The bottom regime table is deliberately independent of the timeframe picker. Switching the chart to 3M does not re-scope it, so the historical baseline you're comparing today's regime against stays fixed rather than shifting under you. The chart card carries an explicit badge showing the active window's scope, date range, and session count.
Measurement basis — trailing, or forward?
This is the subtler one, and it's the difference between a number you could have acted on and a number that only exists in hindsight.
| Basis | Definition | Knowable when? |
|---|---|---|
| Point-in-time (trailing) | VIX vs. the previous 20 sessions' realized vol | On the day itself — tradeable |
| Backtest (forward) | VIX vs. the following 21 sessions' realized vol | Only after those sessions elapse — hindsight |
Everything in the Levels chart, the stat tiles, and the regime classification is point-in-time: computed from data available on that date, no lookahead. The Backtest view and the "actually earned" line in the VIX distribution are forward-looking by construction — they answer what did that premium turn out to be worth, which is a legitimate research question but is not something you could have known at entry.
The VIX distribution view deliberately shows both side by side, because the gap between them is the finding (see below). Its table labels each column with its basis for exactly this reason. The most recent ~21 sessions have no forward measurement yet and are excluded from anything forward-looking.
VIX Distribution vs. VRP
The chart's third mode buckets the window's sessions by VIX level and shows, for each bucket, how often that level occurred alongside two different premium measures. It answers the question traders reach for most naturally — does selling volatility pay better when VIX is high? — which is distinct from the vrp_z test above (that one asks whether the premium being rich relative to its own history predicts anything; this asks about the absolute level).
The two measures are deliberately different:
- Quoted VRP — VIX minus the trailing 20-session realized vol. What the premium looked like at the time.
- Actually earned — VIX minus the forward 21-session realized vol. What a seller of that session's implied vol actually collected.
Full-sample results (2000–2026, 6,575 sessions):
| VIX | Sessions | Avg realized | Quoted VRP | Actually earned | Gap |
|---|---|---|---|---|---|
| <12 | 558 | 7.5 | +3.52 | +2.29 | −1.23 |
| 12–15 | 1,540 | 10.3 | +3.12 | +2.33 | −0.79 |
| 15–20 | 2,013 | 13.1 | +4.16 | +3.70 | −0.46 |
| 20–25 | 1,217 | 18.2 | +4.07 | +4.18 | +0.11 |
| 25–30 | 625 | 23.1 | +4.02 | +4.92 | +0.90 |
| 30–40 | 429 | 29.8 | +3.72 | +5.37 | +1.65 |
| 40+ | 193 | 54.8 | −3.97 | +4.40 | +8.37 |
Two things stand out, and both invert the naive reading.
Quoted VRP is almost flat across VIX levels (+3.1 to +4.2) right up until VIX 40+, where it turns sharply negative. On the quoted number alone, crisis-level VIX looks like the worst possible time to sell premium.
But what a seller actually earned rises steadily with VIX — +2.29 in the calmest bucket to +5.37 at VIX 30–40 — and at VIX 40+, despite quoted VRP reading −3.97, sellers actually collected +4.40.
The mechanism is mean reversion in the measurement window. Quoted VRP compares implied against trailing realized, which at VIX 40+ is already enormously elevated (54.8), so the spread looks negative. Forward realized over the following 21 sessions mean-reverts substantially lower, so the seller collects far more than the quote implied. Low-VIX buckets run the other way: trailing realized is unusually calm, quoted VRP flatters, and forward realized drifts up.
This does not contradict the near-zero vrp_z timing result above — they measure different things. vrp_z normalizes VRP against its own recent history and has no forward power; absolute VIX level does carry information about forward-earned premium. Nor does it make high-VIX selling "safe": the 40+ bucket has the lowest share of positive-quoted-VRP sessions (44%) and is exactly where the backtest's worst trades cluster (see the next section) — the same COVID and Lehman entries that lost 30–55 points. The honest summary is that high VIX offered a larger average premium with far heavier tails, which is a sizing argument, not a green light.
Backtest View
The VRP Research tab's chart has two modes. Levels plots implied vs. realized over the selected window. Backtest runs the canonical VRP harvest and plots its result: sell this session's implied vol, hold ~21 sessions to expiry, collect implied minus subsequently-realized, repeat.
Two implementation points matter for reading it honestly:
- Non-overlapping windows.
fwd_earned_premiumis defined per session over the following 21 sessions, so consecutive rows overlap almost entirely. Summing it daily would count each session's move roughly 21 times over and produce a wildly inflated curve. The backtest steps 21 sessions at a time instead, so each trade's holding period is disjoint from the next. - Units are volatility points, not dollars. This is premium captured per unit of vol exposure. Converting to P&L would require assuming a position size, a strike, and a delta-hedging policy — none of which this platform models, so it deliberately stops short of implying one.
The last ~21 sessions have no fwd_earned_premium yet (the future hasn't happened) and are simply not traded.
Over the full 2000–2026 sample (holding 21 sessions) this produces 313 trades, +1,115 total vol points, +3.56 average per trade, an 84% win rate, and a −86 point maximum drawdown. Those figures match the unconditional numbers in the section above (~+3.5 at ~82%), which is the consistency check you'd want — the backtest is just a different lens on the same premium, not a new claim.
The shape is the classic short-vol profile: a long, steady climb punctuated by rare severe losses. The three worst trades are exactly where you'd expect if the calculation is sound — 2020-02-12 (−54.6) entering the COVID crash, 2008-09-08 (−36.1) entering Lehman week, and 2008-10-07 (−29.4) deeper into the GFC. A single trade losing 54.6 points against a 3.58-point average is the whole risk argument for VRP harvesting in one number, and it's why the Volmageddon-style caution applies to any levered version of this strategy.
Selectable holding period
The holding period is adjustable — 1W / 2W / 1M / 2M / 3M (5 / 10 / 21 / 42 / 63 sessions). Only the 21-session horizon is precomputed in Postgres; the others are derived client-side from the stored spx_close series using the identical formula (sample stdev of log returns over the forward window, annualized by √252). That equivalence was verified rather than assumed: the client-side calculation reproduces all 1,960 stored fwd_earned_premium values to within 5×10⁻⁵, so changing horizon doesn't quietly change methodology.
Forward windows are computed against the full fetched series, not the displayed window. For a custom range ending in the past, the sessions after the range end genuinely happened and are legitimate inputs — slicing first would blank out the final trades of every historical range.
Full-sample results by holding period:
| Hold | Trades | Total | Avg/trade | Win rate | Max drawdown | Worst trade |
|---|---|---|---|---|---|---|
| 1W (5) | 1,314 | +5,696 | +4.33 | 81% | −292 | −104.7 |
| 2W (10) | 657 | +2,566 | +3.91 | 83% | −168 | −80.2 |
| 1M (21) | 313 | +1,115 | +3.56 | 84% | −86 | −54.6 |
| 2M (42) | 156 | +474 | +3.04 | 78% | −52 | −48.8 |
| 3M (63) | 104 | +319 | +3.07 | 78% | −48 | −48.3 |
Per-trade premium falls as the horizon lengthens (+4.33 at a week to ~+3.0 at a quarter), while tail risk falls much faster: the worst single week loses 104.7 vol points against 48.3 for the worst quarter, and maximum drawdown shrinks six-fold from −292 to −48.
Two cautions on reading that table. Totals are not directly comparable across rows — a 1W schedule trades 1,314 times against the quarterly schedule's 104, so its larger total reflects ~12× the turnover, not a better trade. And the short-horizon tail is genuinely brutal: a single week during the COVID crash can realize vol far above any level implied beforehand, which is exactly the −104.7. Shorter holds harvest more premium more often and concentrate more risk into each event.
Context series. The backtest chart overlays VIX at entry (dashed blue, right axis) alongside cumulative harvest and drawdown, so a losing cluster is interpretable — you can see directly whether the trades that hurt were sold into low vol that then exploded, or into already-elevated vol that kept climbing.
Timeframes. The chart supports 3M / 6M / 1Y / 2Y / 5Y / All / Custom, defaulting to 1Y. Two mechanical notes: the API window is expressed in calendar days while the chart is sized in trading sessions, so each timeframe over-requests using a measured ~1.55 calendar-days-per-session ratio (the textbook 365/252 = 1.448 is too optimistic once holidays are counted, and under-requesting silently truncates the window instead of erroring). And windows longer than ~900 sessions are decimated for chart performance by keeping each interval's largest-|VRP| session rather than plain striding — striding would drop exactly the crash days that matter most in this series. Summary statistics are always computed on the full window, never the decimated one.
Is the backtest mathematically sound?
Checked directly against the live implementation rather than assumed. Four properties matter for calling a backtest like this trustworthy, and all four hold:
- No lookahead in trade selection. Entries are chosen on a fixed calendar grid — every
holdSessions-th session starting from the window's first valid date — never by looking at what a trade would have earned. A signal-selected entry schedule (e.g. "only enter whenvrp_zis high") would leak future information into which trades get counted; a fixed step schedule cannot, by construction. This is the same reason the earlier "Does VRP Level Predict What You Earn?" quintile test is trustworthy: neither test lets the outcome influence which sessions are sampled. - Non-overlapping windows, correctly enforced. The loop advances by exactly
holdSessionseach iteration (i += holdSessions), so no two trades' forward-realized-vol windows share a session. This was the one identified failure mode worth checking for — summing daily instead would inflate the total roughly 21× — and the step logic rules it out structurally, not just empirically. - Peak/drawdown/win-rate arithmetic is standard and correctly wired. Cumulative harvest is a running sum of each trade's
VIX_entry − realizedVol_forward; drawdown at each point is cumulative minus the running peak-so-far (so it is ≤ 0 by construction); max drawdown is the minimum of those; win rate is the share of trades with positive earned premium. All of this runs on the raw unrounded cumulative value — the.toFixed()calls are display-only and never feed back into the running total, so there's no accumulated rounding drift over hundreds of trades. - The holding-period table's numbers reproduce exactly. Re-running the live GraphQL history (6,575 sessions, 2000-05-01 → the latest session) through the identical algorithm gives 313 trades, +1,115.4 total, +3.56 avg, 84% win rate, −86.0 max drawdown, −54.6 worst trade at the 21-session hold — matching the table above to the decimal. This check also caught a stale inconsistency in an earlier draft of this page (a paragraph that quoted 311 trades / 85% / +3.58 from before the entry-grid alignment logic was finalized); that paragraph has been corrected to match the verified figures.
What this does not claim: the backtest still has no transaction costs, no slippage, no delta-hedging, and an arbitrary (not optimised) entry grid — all already listed under Limitations. "Mathematically sound" here means the arithmetic and sampling are internally consistent and lookahead-free, not that it estimates a tradeable strategy's real-world P&L.
How This Compares to the Academic Literature
The VRP has a substantial academic literature with its own conventions, and they don't match ours in every respect. This section records where we align, where we deliberately differ, and — importantly — one place where our numbers are not directly comparable to published research.
Where we align
Sign and direction. The literature's central empirical finding is that the risk-neutral expectation of variance sits above subsequently realized variance, so VRP is positive most of the time (Bollerslev, Tauchen & Zhou 2009). Our full sample is 84.8% positive across 6,575 sessions, consistent with that.
Using both a trailing and a forward measure. The standard empirical VRP relies on a martingale assumption — that expected future realized variance is proxied by the most recently observed realized variance — which makes the headline measure implied minus trailing realized. That is exactly our "quoted VRP." The forward version (implied minus subsequently realized) is the ex-post realization, which is our "actually earned." Mapping our two labels onto the literature:
| Our label | Literature framing | Basis |
|---|---|---|
| Quoted VRP | Ex-ante VRP, using trailing RV as the martingale proxy for expected RV | Point-in-time |
| Actually earned | Ex-post realized variance premium | Forward / hindsight |
Showing both is deliberate, and the gap between them is the substance of the VIX distribution finding above.
Where we deliberately differ
We lead in volatility points, the literature leads in variance. The academic definition is in variance (squared) units. We headline VIX − RV in vol points because that is how practitioners actually quote it, and we surface the variance form alongside it. This is a presentation choice, not a disagreement: we verified that the two are a monotonic transform of each other over the full sample — the sign agrees on every one of the 6,575 sessions, so the regime classification (which keys off the sign of the z-scored premium) is completely unaffected by which unit leads.
Our variance scaling is a display convention. The vrp_variance column is (VIX² − RV²) ÷ 100. That ÷100 exists only to put the number near the vol-point magnitude for side-by-side reading; it is not a standard unit. For the same session:
| Convention | Value |
|---|---|
Our vrp_variance | 0.38 |
| Annualized variance, %² | 38.08 |
| Annualized variance, decimal | 0.003808 |
| Monthly variance %² (common in the literature) | 3.17 |
If you are comparing our figure against a paper, multiply by 100 for annualized %², or by 100/12 for the monthly convention. The column header carries this note as a tooltip.
Where we are genuinely not comparable — realized variance construction
This is the one that matters most, and it cannot be fixed with the data we have.
The literature computes "model-free realized variance" from high-frequency intraday returns — typically 5-minute sampling — precisely because that gives far more accurate ex-post observations of actual return variation than sample variances built from daily or coarser returns (Bollerslev, Tauchen & Zhou 2009; see also Carr & Wu 2009).
We compute realized volatility from daily closes. A 20-session window gives us 20 return observations; a 5-minute intraday estimator over the same month uses on the order of 1,600. Ours is therefore a much noisier estimator of the same underlying quantity. It is also measuring a subtly different thing: close-to-close returns include the overnight gap, which a purely intraday estimator excludes unless explicitly adjusted.
Practical consequences:
- Our VRP figures should be treated as directionally faithful but not numerically interchangeable with published VRP series. Do not expect our +3.5 average to match a paper's number to the decimal.
- The noise is largest exactly where it hurts most — short windows and violent tapes, where 20 daily observations is a thin sample and a single gap dominates the estimate.
- Fixing this requires intraday SPX data, which the platform does not currently ingest. It is a data-availability limitation, not a modelling choice.
Practitioner benchmarks
On the product side, CBOE has published two distinct benchmarks that harvest this premium in different ways — the S&P 500 VARB-X index (short three-month realized variance via variance futures) and the VIX Premium Index (short one-month forward implied vol via VIX futures). They behave differently by construction: VARB-X's volatility exposure decays as each day resolves another portion of the final realized variance, while the VIX futures version holds roughly constant exposure into maturity. Our backtest is closer in spirit to the VARB-X framing (realized-variance settlement over a fixed window) than to the VIX-futures one, though it models neither instrument's actual mechanics — see the Backtest View caveats about costs and position sizing.
Verification note
The numerical claims in this section (84.8% positive, sign agreement across all 6,575 sessions, the scaling comparison table) were computed directly against our own data and are reproducible. The characterizations of the academic conventions come from the sources linked above as surfaced in search summaries; the underlying PDFs did not extract cleanly for direct quotation, so treat the specific attributions as indicative of the standard approach rather than verbatim citation.
Limitations
- Realized vol comes from daily closes, not intraday. The academic standard builds realized variance from 5-minute returns; our 20-session window has 20 observations against roughly 1,600 for an intraday estimator, making ours materially noisier and not numerically interchangeable with published VRP series. Fixing it requires intraday SPX data the platform doesn't ingest. See the literature comparison section above.
- Forward-earned premium is a proxy, not realised option P&L.
- Term structure is unavailable before 2007-12, so pre-2008 rows classify stress on
vix_rankalone. - Regime thresholds are chosen, not fitted —
vrp_z > 0andvix_rank > 0.8. They are interpretable and stable, but not optimised, and results near a boundary should not be over-read. - Historical averages are not forecasts. A 26-year sample contains a handful of genuinely distinct volatility eras.
- The backtest has no costs, slippage, or capacity assumptions, and no delta-hedging. It measures the premium that was available, not what a specific implementation would have netted after execution — a real strategy selling actual options would keep meaningfully less.
- The backtest's entry schedule is arbitrary. Stepping every 21st session from the window's start means a different start date produces a different (though similarly-shaped) set of trades. It is not optimised, and shouldn't be read as one.
Key Takeaways
- VRP signals are precomputed daily in Postgres because percentile and z-score features cannot be derived from a live quote.
- Roughly two thirds of the headline vol-point premium is convexity, not edge — check variance points.
- VRP is compensation for downside risk; stress-regime variance is 58–64% downside-driven.
- VRP level has almost no power to time entries (IC ≈ 0.008), despite the premium itself being real and persistent.
- The regime label is a risk signal: Stressed Premium carries a 26.7% chance of becoming Crisis within a month versus 5.7% from Harvest.
- The Backtest view harvests on non-overlapping ~monthly windows because
fwd_earned_premiumoverlaps day-to-day — summing it daily would inflate the curve ~21×. - Three scopes coexist on the panel — point-in-time (stat tiles), selected window (chart/distribution/backtest), and full history since 2000 (regime table, fixed regardless of the timeframe picker). Each is labelled in the UI.
- Point-in-time metrics were knowable on their own date and are tradeable; forward/backtest metrics require hindsight and are research-only. The Levels chart is entirely the former; the Backtest view and "actually earned" are the latter.
- Quoted VRP measures against trailing realized vol, earned premium against forward realized. At VIX 40+ the two disagree by 8+ vol points and even flip sign — quoted reads −3.97 while sellers actually collected +4.40, because trailing realized is elevated and forward realized mean-reverts.
- Absolute VIX level does carry forward information (earned premium rises from +2.29 to +5.37 across the VIX range) even though
vrp_zdoes not — different signals, not a contradiction. High VIX means a bigger average premium with much heavier tails. - Full-sample backtest: 311 trades, +3.58 avg, 85% win rate, −86 pt max drawdown, with the worst trades landing on COVID and Lehman — steady climb, rare severe losses.
- Holding period is selectable (1W–3M). Per-trade premium falls with horizon (+4.33 weekly → ~+3.0 quarterly) while tail risk falls faster still (worst trade −104.7 weekly → −48.3 quarterly, max drawdown −292 → −48). Shorter holds harvest more, more often, and concentrate more risk per event.
- Non-21-session horizons are derived client-side from stored closes, verified to reproduce the precomputed 21-session column to 5×10⁻⁵ — same methodology, not an approximation.
Related Reading
- Variance Risk Premium — the underlying concept and trading case
- GEX Calculation Methodology — the companion gamma-exposure spec
- VIX
Academic sources
- Bollerslev, Tauchen & Zhou (2009), Expected Stock Returns and Variance Risk Premia, Review of Financial Studies — paper · Fed working-paper version. The standard reference for the empirical VRP measure, the martingale proxy for expected realized variance, and high-frequency realized-variance construction.
- Carr & Wu (2009), Variance Risk Premia, Review of Financial Studies — paper. Variance-swap framing of the premium across underlyings.
- Exploring the Variance Risk Premium Across Assets (AFA) — cross-asset evidence that the premium is not an equity-index quirk.
- Realized GARCH, CBOE VIX, and the Volatility Risk Premium — on VIX-formula edge cases and alternative model-free implied-variance estimators.
Practitioner convention sources
- Topstep — Implied vs. realized volatility & the VIX — on VIX's 30-calendar-day (~21-trading-day) target horizon.
- Macroption — Implied, Realized and Historical Volatility — on 20/21-session historical volatility as the standard single-window proxy for a one-month implied comparison.