{"slug":"historical-volatility-vs-implied-volatility","qid":"iv_vs_rv","label":"SPY: monthly implied volatility against the next month's realized volatility","post_title":"Historical Volatility vs Implied Volatility","post_url":"/blog/historical-volatility-vs-implied-volatility#q-iv_vs_rv","columns":["month","implied_vol_pct","realized_next_month_pct","gap_pct"],"rows":[{"month":"2025-02","implied_vol_pct":14.2,"realized_next_month_pct":20.7,"gap_pct":-6.5},{"month":"2025-03","implied_vol_pct":19,"realized_next_month_pct":51.9,"gap_pct":-32.9},{"month":"2025-04","implied_vol_pct":27.2,"realized_next_month_pct":16.8,"gap_pct":10.4},{"month":"2025-05","implied_vol_pct":18.5,"realized_next_month_pct":10.2,"gap_pct":8.3},{"month":"2025-06","implied_vol_pct":15.9,"realized_next_month_pct":6.6,"gap_pct":9.3},{"month":"2025-07","implied_vol_pct":15,"realized_next_month_pct":12,"gap_pct":3},{"month":"2025-08","implied_vol_pct":13.7,"realized_next_month_pct":7.1,"gap_pct":6.6},{"month":"2025-09","implied_vol_pct":13.3,"realized_next_month_pct":13.8,"gap_pct":-0.5},{"month":"2025-10","implied_vol_pct":15.7,"realized_next_month_pct":15.4,"gap_pct":0.3},{"month":"2025-11","implied_vol_pct":16.7,"realized_next_month_pct":8.4,"gap_pct":8.3},{"month":"2025-12","implied_vol_pct":13.5,"realized_next_month_pct":10.3,"gap_pct":3.2},{"month":"2026-01","implied_vol_pct":14,"realized_next_month_pct":13.4,"gap_pct":0.6},{"month":"2026-02","implied_vol_pct":16.4,"realized_next_month_pct":18.2,"gap_pct":-1.8},{"month":"2026-03","implied_vol_pct":21,"realized_next_month_pct":11.6,"gap_pct":9.4},{"month":"2026-04","implied_vol_pct":17.2,"realized_next_month_pct":9.7,"gap_pct":7.5},{"month":"2026-05","implied_vol_pct":15.4,"realized_next_month_pct":17.7,"gap_pct":-2.3},{"month":"2026-06","implied_vol_pct":15.7,"realized_next_month_pct":12.1,"gap_pct":3.6},{"month":"2026-07","implied_vol_pct":14.8,"realized_next_month_pct":11.6,"gap_pct":3.2}],"shape":"series","sql":"WITH\n    daily AS\n    (\n        SELECT\n            date             AS session_date,\n            toFloat64(close) AS close_px,\n            lagInFrame(toFloat64(close)) OVER\n                (ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_close\n        FROM global_markets.stocks_daily_aggs\n        WHERE ticker = 'SPY'\n          AND date >= today() - 560\n          AND date <  today()\n    ),\n    realized AS\n    (\n        SELECT\n            toStartOfMonth(session_date)                                       AS month_start,\n            round(100 * sqrt(252) * stddevSamp(log(close_px / prev_close)), 1) AS realized_vol_pct\n        FROM daily\n        WHERE prev_close > 0\n        GROUP BY month_start\n        HAVING count() >= 15\n    ),\n    implied AS\n    (\n        SELECT\n            toStartOfMonth(date)                  AS month_start,\n            round(100 * avg(implied_volatility), 1) AS implied_vol_pct\n        FROM global_markets.options_greeks\n        WHERE underlying_symbol = 'SPY'\n          AND date >= today() - 560\n          AND date <  today()\n          AND iv_converged = 1\n          AND volume > 0\n          AND days_to_expiry BETWEEN 20 AND 45\n          AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.05\n        GROUP BY month_start\n        HAVING count() >= 100\n    )\nSELECT\n    formatDateTime(imp.month_start, '%Y-%m')                    AS month,\n    imp.implied_vol_pct                                         AS implied_vol_pct,\n    rea.realized_vol_pct                                        AS realized_next_month_pct,\n    round(imp.implied_vol_pct - rea.realized_vol_pct, 1)        AS gap_pct\nFROM implied AS imp\nINNER JOIN realized AS rea ON rea.month_start = addMonths(imp.month_start, 1)\nORDER BY month","computed_at":"2026-08-22T04:08:18.081802+00:00","elapsed":0.871850936}