{"slug":"do-stocks-move-as-much-as-options-predict","qid":"ratio_distribution","label":"Where the realized move landed relative to implied","post_title":"Do Stocks Move as Much as Options Predict?","post_url":"/blog/do-stocks-move-as-much-as-options-predict#q-ratio_distribution","columns":["ratio_bucket","event_count","share_pct","cumulative_pct"],"rows":[{"ratio_bucket":"under 0.50x","event_count":33,"share_pct":32,"cumulative_pct":32},{"ratio_bucket":"0.50 to 0.75x","event_count":13,"share_pct":12.6,"cumulative_pct":44.7},{"ratio_bucket":"0.75 to 1.00x","event_count":9,"share_pct":8.7,"cumulative_pct":53.4},{"ratio_bucket":"1.00 to 1.50x","event_count":24,"share_pct":23.3,"cumulative_pct":76.7},{"ratio_bucket":"1.50 to 2.00x","event_count":13,"share_pct":12.6,"cumulative_pct":89.3},{"ratio_bucket":"over 2.00x","event_count":11,"share_pct":10.7,"cumulative_pct":100}],"shape":"ranking","sql":"WITH\nreports AS (\n    SELECT\n        toString(ticker)    AS sym,\n        toDate(filing_date) AS report_date\n    FROM global_markets.stocks_8k_text\n    WHERE ticker IN ('AAPL', 'AMD', 'AMZN', 'AVGO', 'DIS', 'GOOGL', 'JPM', 'KO', 'META', 'MSFT', 'NFLX', 'NVDA', 'ORCL', 'QCOM', 'TSLA', 'WMT')\n      AND filing_date >= '2021-09-01'\n      AND filing_date <  '2026-09-20'\n      AND (items_text ILIKE '%results of operations and financial condition%'\n        OR items_text ILIKE '%item 2.02%')\n    GROUP BY sym, report_date\n),\nsessions AS (\n    SELECT\n        toString(ticker) AS sym,\n        toDate(date)     AS session_date,\n        toFloat64(close) AS px\n    FROM global_markets.stocks_daily_aggs\n    WHERE ticker IN ('AAPL', 'AMD', 'AMZN', 'AVGO', 'DIS', 'GOOGL', 'JPM', 'KO', 'META', 'MSFT', 'NFLX', 'NVDA', 'ORCL', 'QCOM', 'TSLA', 'WMT')\n      AND date >= '2021-08-01'\n      AND date <  '2026-09-27'\n      AND close > 0\n),\nspans AS (\n    SELECT\n        r.sym         AS sym,\n        r.report_date AS report_date,\n        maxIf(s.session_date, s.session_date < r.report_date) AS pre_date,\n        minIf(s.session_date, s.session_date > r.report_date) AS post_date\n    FROM reports AS r\n    INNER JOIN sessions AS s ON s.sym = r.sym\n    WHERE s.session_date >= r.report_date - 8\n      AND s.session_date <= r.report_date + 8\n    GROUP BY r.sym, r.report_date\n    HAVING countIf(s.session_date < r.report_date) > 0\n       AND countIf(s.session_date > r.report_date) > 0\n),\nmoves AS (\n    SELECT\n        sp.sym         AS sym,\n        sp.report_date AS report_date,\n        sp.pre_date    AS pre_date,\n        round(100 * abs(b.px / a.px - 1), 2) AS realized_pct\n    FROM spans AS sp\n    INNER JOIN sessions AS a ON a.sym = sp.sym AND a.session_date = sp.pre_date\n    INNER JOIN sessions AS b ON b.sym = sp.sym AND b.session_date = sp.post_date\n),\ngreeks AS (\n    SELECT\n        toString(underlying_symbol)   AS sym,\n        toDate(date)                  AS pre_date,\n        toDate(expiration_date)       AS expiry,\n        lower(option_type)            AS side,\n        toFloat64(strike_price)       AS strike,\n        toFloat64(option_close)       AS opt_px,\n        toFloat64(underlying_close)   AS spot,\n        toFloat64(implied_volatility) AS iv,\n        toUInt16(days_to_expiry)      AS dte\n    FROM global_markets.options_greeks\n    WHERE underlying_symbol IN ('AAPL', 'AMD', 'AMZN', 'AVGO', 'DIS', 'GOOGL', 'JPM', 'KO', 'META', 'MSFT', 'NFLX', 'NVDA', 'ORCL', 'QCOM', 'TSLA', 'WMT')\n      AND date >= '2021-09-01'\n      AND date <  '2026-09-20'\n      AND iv_converged = 1\n      AND volume > 0\n      AND days_to_expiry BETWEEN 1 AND 45\n      AND underlying_close > 0\n      AND option_close > 0\n      AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.05\n),\nchain AS (\n    SELECT\n        g.sym      AS sym,\n        g.pre_date AS pre_date,\n        g.expiry   AS expiry,\n        g.side     AS side,\n        g.strike   AS strike,\n        g.opt_px   AS opt_px,\n        g.spot     AS spot,\n        g.iv       AS iv,\n        g.dte      AS dte\n    FROM greeks AS g\n    INNER JOIN moves AS m ON m.sym = g.sym AND m.pre_date = g.pre_date\n    WHERE g.expiry > m.report_date\n),\nfront AS (\n    SELECT sym, pre_date, min(expiry) AS expiry\n    FROM chain\n    GROUP BY sym, pre_date\n),\nstraddles AS (\n    SELECT\n        c.sym       AS sym,\n        c.pre_date  AS pre_date,\n        c.strike    AS strike,\n        any(c.spot) AS spot,\n        max(c.dte)  AS dte,\n        avgIf(c.opt_px, c.side IN ('call', 'c')) AS call_px,\n        avgIf(c.opt_px, c.side IN ('put', 'p'))  AS put_px,\n        avg(c.iv)   AS atm_iv\n    FROM chain AS c\n    INNER JOIN front AS f\n        ON f.sym = c.sym AND f.pre_date = c.pre_date AND f.expiry = c.expiry\n    GROUP BY c.sym, c.pre_date, c.strike\n    HAVING countIf(c.side IN ('call', 'c')) > 0\n       AND countIf(c.side IN ('put', 'p')) > 0\n),\nimplied AS (\n    SELECT\n        sym,\n        pre_date,\n        argMin(round(100 * (call_px + put_px) / spot, 2), abs(strike / spot - 1)) AS straddle_pct,\n        argMin(round(100 * atm_iv * sqrt(dte / 365), 2), abs(strike / spot - 1))  AS iv_root_t_pct\n    FROM straddles\n    GROUP BY sym, pre_date\n)\nSELECT\n    bucket                                                           AS ratio_bucket,\n    toUInt32(n)                                                      AS event_count,\n    round(100 * n / sum(n) OVER (), 1)                               AS share_pct,\n    round(100 * sum(n) OVER (ORDER BY sort_key) / sum(n) OVER (), 1) AS cumulative_pct\nFROM\n(\n    SELECT\n        multiIf(r <= 0.50, 1, r <= 0.75, 2, r <= 1.00, 3, r <= 1.50, 4, r <= 2.00, 5, 6) AS sort_key,\n        multiIf(r <= 0.50, 'under 0.50x',\n                r <= 0.75, '0.50 to 0.75x',\n                r <= 1.00, '0.75 to 1.00x',\n                r <= 1.50, '1.00 to 1.50x',\n                r <= 2.00, '1.50 to 2.00x',\n                'over 2.00x') AS bucket,\n        count()               AS n\n    FROM\n    (\n        SELECT m.realized_pct / i.straddle_pct AS r\n        FROM moves AS m\n        INNER JOIN implied AS i ON i.sym = m.sym AND i.pre_date = m.pre_date\n        WHERE i.straddle_pct > 0\n    )\n    GROUP BY sort_key, bucket\n)\nORDER BY sort_key","computed_at":"2026-09-27T16:03:10.589339+00:00","elapsed":0.012357421}