{"slug":"relative-volume-screener-from-the-free-sql-api","qid":"volume_curve","label":"volume_curve","post_title":"relative-volume-screener-from-the-free-sql-api","post_url":"/blog/relative-volume-screener-from-the-free-sql-api#q-volume_curve","columns":["et_time","spy_share_pct","ko_share_pct"],"rows":[{"et_time":"09:30","spy_share_pct":11.5,"ko_share_pct":14.6},{"et_time":"10:00","spy_share_pct":19.8,"ko_share_pct":23.3},{"et_time":"10:30","spy_share_pct":26.7,"ko_share_pct":30.2},{"et_time":"11:00","spy_share_pct":34.8,"ko_share_pct":37.1},{"et_time":"11:30","spy_share_pct":40.6,"ko_share_pct":42.4},{"et_time":"12:00","spy_share_pct":45.3,"ko_share_pct":47.6},{"et_time":"12:30","spy_share_pct":49.5,"ko_share_pct":52.2},{"et_time":"13:00","spy_share_pct":54.2,"ko_share_pct":56.7},{"et_time":"13:30","spy_share_pct":58.1,"ko_share_pct":60.8},{"et_time":"14:00","spy_share_pct":63.2,"ko_share_pct":65.6},{"et_time":"14:30","spy_share_pct":70.2,"ko_share_pct":71.4},{"et_time":"15:00","spy_share_pct":77.6,"ko_share_pct":78.4},{"et_time":"15:30","spy_share_pct":100,"ko_share_pct":100}],"shape":"series","sql":"WITH\n    bars AS (\n        SELECT\n            ticker,\n            toDate(et_ts)                                                        AS session_date,\n            formatDateTime(toStartOfInterval(et_ts, INTERVAL 30 MINUTE), '%H:%i') AS et_time,\n            toHour(et_ts) * 60 + toMinute(et_ts)                                 AS et_min,\n            toFloat64(volume)                                                    AS vol\n        FROM\n        (\n            SELECT\n                ticker,\n                toTimeZone(window_start, 'America/New_York') AS et_ts,\n                volume\n            FROM global_markets.delayed_stocks_minute_aggs\n            WHERE ticker IN ('SPY', 'KO')\n              AND window_start >= toDateTime(today() - 40)\n        )\n    ),\n    slots AS (\n        SELECT\n            ticker,\n            session_date,\n            et_time,\n            min(et_min) AS slot_min,\n            sum(vol)    AS slot_vol\n        FROM bars\n        WHERE et_min >= 570 AND et_min < 960\n        GROUP BY ticker, session_date, et_time\n    ),\n    complete AS (\n        SELECT ticker, session_date\n        FROM slots\n        GROUP BY ticker, session_date\n        HAVING max(slot_min) >= 930\n    ),\n    slot_avg AS (\n        SELECT\n            ticker,\n            et_time,\n            min(slot_min) AS slot_min,\n            avg(slot_vol) AS avg_slot_vol\n        FROM slots\n        WHERE (ticker, session_date) IN (SELECT ticker, session_date FROM complete)\n        GROUP BY ticker, et_time\n    ),\n    cum AS (\n        SELECT\n            ticker,\n            et_time,\n            slot_min,\n            sum(avg_slot_vol) OVER (PARTITION BY ticker ORDER BY slot_min) AS cum_vol,\n            sum(avg_slot_vol) OVER (PARTITION BY ticker)                   AS day_vol\n        FROM slot_avg\n    )\nSELECT\n    et_time,\n    round(100 * maxIf(cum_vol / day_vol, ticker = 'SPY'), 1) AS spy_share_pct,\n    round(100 * maxIf(cum_vol / day_vol, ticker = 'KO'), 1)  AS ko_share_pct\nFROM cum\nGROUP BY et_time\nORDER BY min(slot_min)","computed_at":"2026-09-25T15:03:15.697897+00:00","elapsed":0.469558137}