TWAP vs VWAP vs POV Orders Explained
SPY intraday volume curve vs a flat TWAP schedule, June to August 2026series ·
2026-09-28 · 13×4
How far volume falls from the open to the 12:30 half hour, five liquid namestable ·
2026-09-28 · 5×6
What a 10% participation order on AAPL could fill each half hour, August 12, 2026series ·
2026-09-28 · 13×4
SPY: median, lowest and highest share of the day's volume per half hour, June to August 2026series ·
2026-09-28 · 13×4
SPY intraday volume curve vs a flat TWAP schedule, June to August 2026
SPY intraday volume curve vs a flat TWAP schedule, June to August 2026
| et_time | avg_volume_millions | vwap_share_pct | twap_share_pct |
|---|---|---|---|
| 09:30 | 4.61 | 11.01 | 7.69 |
| 10:00 | 3.33 | 7.97 | 7.69 |
| 10:30 | 2.79 | 6.66 | 7.69 |
| 11:00 | 2.47 | 5.89 | 7.69 |
| 11:30 | 2.48 | 5.93 | 7.69 |
| 12:00 | 2.2 | 5.25 | 7.69 |
| 12:30 | 1.97 | 4.7 | 7.69 |
| 13:00 | 2.04 | 4.88 | 7.69 |
| 13:30 | 1.87 | 4.47 | 7.69 |
| 14:00 | 2.28 | 5.45 | 7.69 |
| 14:30 | 2.46 | 5.88 | 7.69 |
| 15:00 | 3.14 | 7.52 | 7.69 |
| 15:30 | 10.21 | 24.39 | 7.69 |
the exact SQL behind every number
WITH bars AS
(
SELECT
toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York')) AS minute_of_day,
toFloat64(volume) AS shares
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2026-06-01 00:00:00', 'UTC')
AND window_start < toDateTime('2026-09-01 00:00:00', 'UTC')
UNION ALL
SELECT
toDate(toTimeZone(sip_timestamp, 'America/New_York')) AS et_date,
959 AS minute_of_day,
toFloat64(maxIf(size, has(conditions, 8))) AS shares
FROM global_markets.stocks_trades
WHERE ticker = 'SPY'
AND sip_timestamp >= toDateTime('2026-06-01 00:00:00', 'UTC')
AND sip_timestamp < toDateTime('2026-09-01 00:00:00', 'UTC')
AND toHour(sip_timestamp, 'America/New_York') IN (13, 16)
AND toMinute(sip_timestamp, 'America/New_York') < 10
GROUP BY et_date
HAVING countIf(has(conditions, 8)) > 0
),
per_bucket AS
(
SELECT
formatDateTime(toDateTime(intDiv(minute_of_day, 30) * 30 * 60, 'UTC'), '%H:%i') AS et_time,
sum(shares) AS bucket_shares,
countDistinct(et_date) AS sessions
FROM bars
WHERE minute_of_day >= 570
AND minute_of_day < 960
GROUP BY et_time
)
SELECT
b.et_time AS et_time,
round(b.bucket_shares / b.sessions / 1e6, 2) AS avg_volume_millions,
round(100 * b.bucket_shares / t.window_shares, 2) AS vwap_share_pct,
round(100 / t.bucket_count, 2) AS twap_share_pct
FROM per_bucket AS b
CROSS JOIN
(
SELECT
sum(bucket_shares) AS window_shares,
count() AS bucket_count
FROM per_bucket
) AS t
ORDER BY et_time
More from this analysisTWAP vs VWAP vs POV Orders Explained
What a 10% participation order on AAPL could fill each half hour, August 12, 2026
series 13×4
→
SPY: median, lowest and highest share of the day's volume per half hour, June to August 2026
series 13×4
→
How far volume falls from the open to the 12:30 half hour, five liquid names
table 5×6
→
Average shares per print, monthly, MSFT and KO
series 90×4
→
See all 3,293 queries →