spy_monthly_trace
Answered against 22 years of US equities and 12 years of US options data and published with the query that produced it. This result is stored as of 2026-10-01, from stocks-with-the-biggest-iv-rv-gap.
| month | implied_vol_pct | realized_vol_pct | gap_pct |
|---|---|---|---|
| 2024-07 | 12.9 | 19.2 | -6.3 |
| 2024-08 | 15 | 13.8 | 1.2 |
| 2024-09 | 13.6 | 11.2 | 2.4 |
| 2024-10 | 16.4 | 11.8 | 4.6 |
| 2024-11 | 13 | 14.1 | -1.1 |
| 2024-12 | 11.6 | 13.9 | -2.3 |
| 2025-01 | 13.9 | 13.2 | 0.7 |
| 2025-02 | 12.7 | 20.7 | -8 |
| 2025-03 | 17.7 | 51.9 | -34.2 |
| 2025-04 | 26.4 | 16.8 | 9.6 |
| 2025-05 | 17.4 | 10.2 | 7.2 |
| 2025-06 | 14.7 | 6.6 | 8.1 |
| 2025-07 | 14.4 | 12 | 2.4 |
| 2025-08 | 12.6 | 7.1 | 5.5 |
| 2025-09 | 11.3 | 13.8 | -2.5 |
| 2025-10 | 15.3 | 15.4 | -0.1 |
| 2025-11 | 15.5 | 8.4 | 7.1 |
| 2025-12 | 12.4 | 10.3 | 2.1 |
| 2026-01 | 13.4 | 13.4 | 0 |
| 2026-02 | 15.3 | 18.2 | -2.9 |
| 2026-03 | 19.4 | 11.6 | 7.8 |
| 2026-04 | 15.6 | 9.7 | 5.9 |
| 2026-05 | 14.7 | 17.7 | -3 |
| 2026-06 | 14.7 | 12.1 | 2.6 |
- Rows × columns
- 24 × 4
- Computed
- Completeness
- No missing values
- Source
- US exchange, SIP and OPRA market data
- Licence
- Strasmore terms · free, no signup
What each column holds
| Column | Type | Range | Notes |
|---|---|---|---|
month |
text | 24 distinct values (2024-07, 2024-08, 2024-09…) | |
implied_vol_pct |
number | 11.3 to 26.4 | percent |
realized_vol_pct |
number | 6.6 to 51.9 | percent |
gap_pct |
number | -34.2 to 9.6 | percent |
Computed from Strasmore's warehouse of US exchange, SIP and OPRA market data. Equity prices are delayed; options greeks and implied volatility are end-of-day. This result is stored, not recomputed on load — it is exactly the numbers that were returned on , and the query below is what returned them.
Run it yourself
This is the exact query behind the result above. Change a ticker, a date or a column and run it against the warehouse — no account, no key. The no-signup tier is smaller than the one this page was computed on; a query that reaches past it comes back saying which plan runs it.
WITH
px AS
(
SELECT
date AS session,
max(toFloat64(close)) AS px
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2024-07-01'
AND date < '2026-08-01'
GROUP BY session
),
iv_rows AS
(
SELECT
g.session AS session,
g.iv AS iv
FROM
(
SELECT
toDate(date) AS session,
toFloat64(strike_price) AS strike,
implied_volatility AS iv
FROM global_markets.options_greeks
WHERE underlying_symbol = 'SPY'
AND date >= '2024-07-01'
AND date < '2026-07-01'
AND lower(toString(option_type)) IN ('c', 'call')
AND days_to_expiry BETWEEN 20 AND 45
AND implied_volatility > 0
) AS g
INNER JOIN px AS p ON p.session = g.session
WHERE abs(g.strike / p.px - 1) < 0.05
),
daily_returns AS
(
SELECT
arrayJoin(arrayMap((a, b) -> (tupleElement(a, 1), log(tupleElement(a, 2) / tupleElement(b, 2))),
arraySlice(series, 2),
arraySlice(series, 1, length(series) - 1))) AS ret
FROM
(
SELECT arraySort(groupArray((session, px))) AS series
FROM px
)
),
realized AS
(
SELECT
toStartOfMonth(tupleElement(ret, 1)) AS rv_month,
round(100 * sqrt(252) * stddevSamp(tupleElement(ret, 2)), 1) AS realized_vol_pct
FROM daily_returns
GROUP BY rv_month
HAVING count() >= 15
),
implied AS
(
SELECT
iv_month,
addMonths(iv_month, 1) AS forward_month,
implied_vol_pct
FROM
(
SELECT
toStartOfMonth(session) AS iv_month,
round(100 * avg(iv), 1) AS implied_vol_pct
FROM iv_rows
GROUP BY iv_month
HAVING countDistinct(session) >= 15
)
)
SELECT
formatDateTime(implied.iv_month, '%Y-%m') AS month,
implied.implied_vol_pct AS implied_vol_pct,
realized.realized_vol_pct AS realized_vol_pct,
round(implied.implied_vol_pct - realized.realized_vol_pct, 1) AS gap_pct
FROM implied
INNER JOIN realized ON realized.rv_month = implied.forward_month
ORDER BY month
Work with this data in your AI assistant
Opens ready to query, with this page's data. Free, no account.