{"slug":"stop-orders-on-options","qid":"spy_put_daily_moves","label":"spy_put_daily_moves","post_title":"stop-orders-on-options","post_url":"/blog/stop-orders-on-options#q-spy_put_daily_moves","columns":["move_bucket","contract_days","share_pct"],"rows":[{"move_bucket":"under 5%","contract_days":396,"share_pct":16.7},{"move_bucket":"5% to 10%","contract_days":339,"share_pct":14.3},{"move_bucket":"10% to 20%","contract_days":591,"share_pct":25},{"move_bucket":"20% or more","contract_days":1039,"share_pct":43.9}],"shape":"ranking","sql":"WITH daily AS\n(\n    SELECT\n        ticker,\n        date,\n        max(toFloat64(option_close))     AS put_close,\n        max(toFloat64(underlying_close)) AS spy_close,\n        max(toFloat64(strike_price))     AS strike,\n        max(days_to_expiry)              AS dte\n    FROM global_markets.options_greeks\n    WHERE underlying_symbol = 'SPY'\n      AND lower(toString(option_type)) IN ('put', 'p')\n      AND date >= toDate('2026-06-29')\n      AND date <  toDate('2026-08-01')\n      AND days_to_expiry BETWEEN 15 AND 50\n      AND volume > 0\n    GROUP BY ticker, date\n),\nchained AS\n(\n    SELECT\n        date,\n        put_close,\n        spy_close,\n        strike,\n        dte,\n        lagInFrame(put_close, 1) OVER (PARTITION BY ticker ORDER BY date ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS prev_put,\n        lagInFrame(date, 1)      OVER (PARTITION BY ticker ORDER BY date ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS prev_date\n    FROM daily\n),\nmoves AS\n(\n    SELECT abs(100 * (put_close / prev_put - 1)) AS move_pct\n    FROM chained\n    WHERE prev_put > 0\n      AND dateDiff('day', prev_date, date) <= 4\n      AND date >= toDate('2026-07-01')\n      AND dte BETWEEN 20 AND 45\n      AND abs(strike / spy_close - 1) < 0.02\n)\nSELECT\n    multiIf(move_pct < 5,  'under 5%',\n            move_pct < 10, '5% to 10%',\n            move_pct < 20, '10% to 20%',\n                           '20% or more') AS move_bucket,\n    count()                                               AS contract_days,\n    round(100 * count() / (SELECT count() FROM moves), 1) AS share_pct\nFROM moves\nGROUP BY move_bucket\nORDER BY min(move_pct)","computed_at":"2026-09-11T14:31:51.251973+00:00","elapsed":0.005175432}