The Volatility Risk Premium, Measured
The ten deepest 21 session shortfalls, one per calendar monthranking ·
2026-10-16 · 10×4
SPY implied volatility against the realized volatility that followed, by monthseries ·
2026-10-16 · 62×5
Distribution of the 21 session volatility risk premium, in volatility pointsranking ·
2026-10-16 · 6×3
The volatility risk premium by option tenor, each matched to its own realized windowtable ·
2026-10-16 · 4×5
The 21 session premium across strikes, puts and calls, 20 to 45 days to expiryranking ·
2026-10-16 · 7×3
The ten deepest 21 session shortfalls, one per calendar month
The ten deepest 21 session shortfalls, one per calendar month
| label | implied_vol_pct | realized_vol_pct | shortfall_pct |
|---|---|---|---|
| Mar 25, 2025 | 15.56 | 51.28 | 35.72 |
| Apr 1, 2025 | 18.84 | 50.72 | 31.89 |
| Apr 20, 2022 | 17.56 | 35.14 | 17.58 |
| Jul 15, 2024 | 12.14 | 21.29 | 9.14 |
| Mar 30, 2022 | 16.49 | 25.5 | 9.01 |
| Sep 9, 2022 | 20.72 | 28.96 | 8.24 |
| Feb 18, 2025 | 12.48 | 20.51 | 8.03 |
| May 17, 2022 | 24.04 | 31.79 | 7.75 |
| Aug 18, 2022 | 17.81 | 25.49 | 7.68 |
| Feb 9, 2022 | 17.33 | 24.84 | 7.51 |
the exact SQL behind every number
WITH
closes AS
(
SELECT
date,
toFloat64(any(close)) AS px
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2021-06-01'
GROUP BY date
),
daily_returns AS
(
SELECT
date,
pow(log(px / lagInFrame(px) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)), 2) AS r2
FROM closes
),
forward_rv AS
(
SELECT
date,
100 * sqrt(252 * avg(r2) OVER (ORDER BY date ROWS BETWEEN 1 FOLLOWING AND 21 FOLLOWING)) AS rv_pct,
count(r2) OVER (ORDER BY date ROWS BETWEEN 1 FOLLOWING AND 21 FOLLOWING) AS sessions_ahead
FROM daily_returns
WHERE isFinite(r2)
),
implied AS
(
SELECT
date,
100 * avg(toFloat64(implied_volatility)) AS iv_pct
FROM global_markets.options_greeks
WHERE underlying_symbol = 'SPY'
AND iv_converged = 1
AND volume > 0
AND days_to_expiry BETWEEN 20 AND 45
AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.05
AND date >= '2021-08-01'
GROUP BY date
HAVING count() >= 20
),
paired AS
(
SELECT
i.date AS date,
i.iv_pct AS iv_pct,
f.rv_pct AS rv_pct,
i.iv_pct - f.rv_pct AS premium_pct
FROM implied AS i
INNER JOIN forward_rv AS f ON f.date = i.date
WHERE f.sessions_ahead = 21
)
SELECT
formatDateTime(argMin(date, premium_pct), '%b %e, %Y') AS label,
round(argMin(iv_pct, premium_pct), 2) AS implied_vol_pct,
round(argMin(rv_pct, premium_pct), 2) AS realized_vol_pct,
round(-1 * min(premium_pct), 2) AS shortfall_pct
FROM paired
GROUP BY toStartOfMonth(date)
ORDER BY min(premium_pct) ASC
LIMIT 10
More from this analysisThe Volatility Risk Premium, Measured
The 21 session premium across strikes, puts and calls, 20 to 45 days to expiry
ranking 7×3
→
Distribution of the 21 session volatility risk premium, in volatility points
ranking 6×3
→
SPY implied volatility against the realized volatility that followed, by month
series 62×5
→
The volatility risk premium by option tenor, each matched to its own realized window
table 4×5
→
See all 3,293 queries →