{"slug":"local-volatility-vs-implied-volatility","qid":"fwd_curve","label":"Forward volatility embedded in the SPY monthly expiry curve, last week of September 2026","post_title":"Local Volatility vs Implied Volatility","post_url":"/blog/local-volatility-vs-implied-volatility#q-fwd_curve","columns":["expiry_date","expiry_label","spot_iv_pct","forward_iv_pct"],"rows":[{"expiry_date":"2026-11-20","expiry_label":"Nov 20, 2026","spot_iv_pct":14.09,"forward_iv_pct":14.76},{"expiry_date":"2026-12-18","expiry_label":"Dec 18, 2026","spot_iv_pct":14.54,"forward_iv_pct":15.36},{"expiry_date":"2027-01-15","expiry_label":"Jan 15, 2027","spot_iv_pct":14.75,"forward_iv_pct":15.35},{"expiry_date":"2027-03-19","expiry_label":"Mar 19, 2027","spot_iv_pct":15.79,"forward_iv_pct":17.45},{"expiry_date":"2027-09-17","expiry_label":"Sep 17, 2027","spot_iv_pct":17.85,"forward_iv_pct":19.61}],"shape":"series","sql":"SELECT\n    toString(expiration_date)                      AS expiry_date,\n    formatDateTime(expiration_date, '%b %e, %Y')   AS expiry_label,\n    round(iv * 100, 2)                             AS spot_iv_pct,\n    round(sqrt((dte * iv * iv - prev_dte * prev_iv * prev_iv)\n               / (dte - prev_dte)) * 100, 2)       AS forward_iv_pct\nFROM\n(\n    SELECT\n        expiration_date,\n        iv,\n        dte,\n        lagInFrame(iv)  OVER (ORDER BY expiration_date) AS prev_iv,\n        lagInFrame(dte) OVER (ORDER BY expiration_date) AS prev_dte\n    FROM\n    (\n        SELECT\n            expiration_date,\n            avg(toFloat64(implied_volatility)) AS iv,\n            avg(days_to_expiry)                AS dte\n        FROM global_markets.options_greeks\n        WHERE underlying_symbol = 'SPY'\n          AND date >= '2026-09-24'\n          AND date <  '2026-10-01'\n          AND iv_converged = 1\n          AND volume > 0\n          AND underlying_close > 0\n          AND implied_volatility > 0\n          AND days_to_expiry BETWEEN 10 AND 400\n          AND toDayOfWeek(expiration_date) = 5\n          AND toDayOfMonth(expiration_date) BETWEEN 15 AND 21\n          AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) <= 0.01\n        GROUP BY expiration_date\n        HAVING count() >= 20\n    )\n)\nWHERE prev_dte > 0\n  AND dte > prev_dte\n  AND dte * iv * iv > prev_dte * prev_iv * prev_iv\nORDER BY expiration_date","computed_at":"2026-10-09T16:40:46.322233+00:00","elapsed":0.004264299}