{"slug":"stocks-with-the-biggest-iv-rv-gap","qid":"spy_monthly_trace","label":"spy_monthly_trace","post_title":"stocks-with-the-biggest-iv-rv-gap","post_url":"/blog/stocks-with-the-biggest-iv-rv-gap#q-spy_monthly_trace","columns":["month","implied_vol_pct","realized_vol_pct","gap_pct"],"rows":[{"month":"2024-07","implied_vol_pct":12.9,"realized_vol_pct":19.2,"gap_pct":-6.3},{"month":"2024-08","implied_vol_pct":15,"realized_vol_pct":13.8,"gap_pct":1.2},{"month":"2024-09","implied_vol_pct":13.6,"realized_vol_pct":11.2,"gap_pct":2.4},{"month":"2024-10","implied_vol_pct":16.4,"realized_vol_pct":11.8,"gap_pct":4.6},{"month":"2024-11","implied_vol_pct":13,"realized_vol_pct":14.1,"gap_pct":-1.1},{"month":"2024-12","implied_vol_pct":11.6,"realized_vol_pct":13.9,"gap_pct":-2.3},{"month":"2025-01","implied_vol_pct":13.9,"realized_vol_pct":13.2,"gap_pct":0.7},{"month":"2025-02","implied_vol_pct":12.7,"realized_vol_pct":20.7,"gap_pct":-8},{"month":"2025-03","implied_vol_pct":17.7,"realized_vol_pct":51.9,"gap_pct":-34.2},{"month":"2025-04","implied_vol_pct":26.4,"realized_vol_pct":16.8,"gap_pct":9.6},{"month":"2025-05","implied_vol_pct":17.4,"realized_vol_pct":10.2,"gap_pct":7.2},{"month":"2025-06","implied_vol_pct":14.7,"realized_vol_pct":6.6,"gap_pct":8.1},{"month":"2025-07","implied_vol_pct":14.4,"realized_vol_pct":12,"gap_pct":2.4},{"month":"2025-08","implied_vol_pct":12.6,"realized_vol_pct":7.1,"gap_pct":5.5},{"month":"2025-09","implied_vol_pct":11.3,"realized_vol_pct":13.8,"gap_pct":-2.5},{"month":"2025-10","implied_vol_pct":15.3,"realized_vol_pct":15.4,"gap_pct":-0.1},{"month":"2025-11","implied_vol_pct":15.5,"realized_vol_pct":8.4,"gap_pct":7.1},{"month":"2025-12","implied_vol_pct":12.4,"realized_vol_pct":10.3,"gap_pct":2.1},{"month":"2026-01","implied_vol_pct":13.4,"realized_vol_pct":13.4,"gap_pct":0},{"month":"2026-02","implied_vol_pct":15.3,"realized_vol_pct":18.2,"gap_pct":-2.9},{"month":"2026-03","implied_vol_pct":19.4,"realized_vol_pct":11.6,"gap_pct":7.8},{"month":"2026-04","implied_vol_pct":15.6,"realized_vol_pct":9.7,"gap_pct":5.9},{"month":"2026-05","implied_vol_pct":14.7,"realized_vol_pct":17.7,"gap_pct":-3},{"month":"2026-06","implied_vol_pct":14.7,"realized_vol_pct":12.1,"gap_pct":2.6}],"shape":"series","sql":"WITH\n    px AS\n    (\n        SELECT\n            date                  AS session,\n            max(toFloat64(close)) AS px\n        FROM global_markets.stocks_daily_aggs\n        WHERE ticker = 'SPY'\n          AND date >= '2024-07-01'\n          AND date <  '2026-08-01'\n        GROUP BY session\n    ),\n    iv_rows AS\n    (\n        SELECT\n            g.session AS session,\n            g.iv      AS iv\n        FROM\n        (\n            SELECT\n                toDate(date)            AS session,\n                toFloat64(strike_price) AS strike,\n                implied_volatility      AS iv\n            FROM global_markets.options_greeks\n            WHERE underlying_symbol = 'SPY'\n              AND date >= '2024-07-01'\n              AND date <  '2026-07-01'\n              AND lower(toString(option_type)) IN ('c', 'call')\n              AND days_to_expiry BETWEEN 20 AND 45\n              AND implied_volatility > 0\n        ) AS g\n        INNER JOIN px AS p ON p.session = g.session\n        WHERE abs(g.strike / p.px - 1) < 0.05\n    ),\n    daily_returns AS\n    (\n        SELECT\n            arrayJoin(arrayMap((a, b) -> (tupleElement(a, 1), log(tupleElement(a, 2) / tupleElement(b, 2))),\n                               arraySlice(series, 2),\n                               arraySlice(series, 1, length(series) - 1))) AS ret\n        FROM\n        (\n            SELECT arraySort(groupArray((session, px))) AS series\n            FROM px\n        )\n    ),\n    realized AS\n    (\n        SELECT\n            toStartOfMonth(tupleElement(ret, 1))                         AS rv_month,\n            round(100 * sqrt(252) * stddevSamp(tupleElement(ret, 2)), 1) AS realized_vol_pct\n        FROM daily_returns\n        GROUP BY rv_month\n        HAVING count() >= 15\n    ),\n    implied AS\n    (\n        SELECT\n            iv_month,\n            addMonths(iv_month, 1) AS forward_month,\n            implied_vol_pct\n        FROM\n        (\n            SELECT\n                toStartOfMonth(session) AS iv_month,\n                round(100 * avg(iv), 1) AS implied_vol_pct\n            FROM iv_rows\n            GROUP BY iv_month\n            HAVING countDistinct(session) >= 15\n        )\n    )\nSELECT\n    formatDateTime(implied.iv_month, '%Y-%m')                     AS month,\n    implied.implied_vol_pct                                       AS implied_vol_pct,\n    realized.realized_vol_pct                                     AS realized_vol_pct,\n    round(implied.implied_vol_pct - realized.realized_vol_pct, 1) AS gap_pct\nFROM implied\nINNER JOIN realized ON realized.rv_month = implied.forward_month\nORDER BY month","computed_at":"2026-10-01T15:31:10.167530+00:00","elapsed":2.854627076}