TWAP vs VWAP vs POV Orders Explained
TWAP vs VWAP vs POV orders: how each execution algorithm slices a trade, why VWAP front loads around the open, and what a 10% POV order does at lunch.
TWAP vs VWAP vs POV orders is a choice between three clocks. Each is an execution algorithm that breaks one large parent order into a stream of small child orders; the difference between them is the schedule those child orders follow. TWAP (time-weighted average price) slices evenly across a time window. VWAP (volume-weighted average price) slices in proportion to the volume a stock usually trades through the day. POV (percentage of volume) follows the volume that actually prints, at a participation rate you choose. All three are judged against the arrival price, the quote at the moment you decided to trade.
Why slice an order at all?
A market order for more shares than the quote is showing walks up the order book, and the average fill lands above the price you saw. That gap is market impact. Slicing spreads the order across time, and each child order is small enough to trade near the quote. The cost is timing risk: the longer the order takes, the further the price can drift before the last share fills.
Implementation shortfall captures both sides: the average fill minus the arrival price, times the shares filled, plus the cost of any shares that never filled. A fast algorithm carries little timing risk and heavy impact; a slow one the reverse. Arrival price is a harder benchmark than VWAP: it is fixed the moment the order is sent, and it charges for every cent the stock moves while the algorithm waits for volume.
What is a TWAP order?
A TWAP order divides the parent quantity evenly across the window you specify. Buy 1,300 shares between 9:30 a.m. and 4:00 p.m. ET and the algorithm aims for roughly 100 shares in each of the thirteen half hours. Most implementations randomise the timing and size of each child so the pattern is harder to spot, but the average rate is flat.
The strength is predictability: you know how much will be done by any given time. The weakness is that it ignores the shape of the trading day. Volume in US stocks follows a U-curve, heavy at the open and the close and thin around lunch, and a flat schedule takes the same slice out of the quiet lunch hour that it takes from the busy open.
What is a VWAP order?
A VWAP order slices in proportion to the expected volume curve, trading more when the market usually trades more. The algorithm carries a profile of what fraction of a normal day's volume prints in each interval, and it releases child orders on that profile. The aim is an average fill close to the day's volume-weighted average price, the benchmark explained in what VWAP is and how it is calculated. The panel below draws that profile for SPY over June through August 2026 in half-hour buckets, next to the flat share a TWAP schedule would assign to the same thirteen buckets.
| et_time | avg_volume_millions | vwap_share_pct | twap_share_pct |
|---|---|---|---|
| 09:30 | 4.61 | 11.37 | 7.69 |
| 10:00 | 3.33 | 8.22 | 7.69 |
| 10:30 | 2.79 | 6.88 | 7.69 |
| 11:00 | 2.47 | 6.08 | 7.69 |
| 11:30 | 2.48 | 6.12 | 7.69 |
| 12:00 | 2.2 | 5.42 | 7.69 |
| 12:30 | 1.97 | 4.85 | 7.69 |
| 13:00 | 2.04 | 5.04 | 7.69 |
| 13:30 | 1.87 | 4.61 | 7.69 |
| 14:00 | 2.28 | 5.63 | 7.69 |
| 14:30 | 2.46 | 6.07 | 7.69 |
| 15:00 | 3.14 | 7.76 | 7.69 |
| 15:30 | 8.9 | 21.96 | 7.69 |
The exact SQL behind every number
WITH bars AS
(
SELECT
toTimeZone(window_start, 'America/New_York') AS et,
toHour(et) * 60 + toMinute(et) AS minute_of_day,
toDate(et) AS et_date,
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')
),
per_bucket AS
(
SELECT
formatDateTime(toStartOfInterval(et, INTERVAL 30 MINUTE), '%H:%i', 'America/New_York') 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_timeThe opening half hour carried 11.37% of SPY's regular-session volume across the window and the final half hour 21.96%; the 12:30 p.m. half hour carried 4.85%. A TWAP schedule hands each of the thirteen half hours the same 7.69%. A VWAP schedule front-loads and back-loads its child orders to match the curve, while TWAP trades through the lunch trough at the same pace it trades the open. The trough itself is the subject of why trading volume dies at midday.
What is a POV (percentage of volume) order?
A POV order, labelled "participate" or "percent of volume" on some platforms, carries no schedule. You set a participation rate, say 10%, and the algorithm watches the tape and keeps its fills near that fraction of everything that trades. In its pure form there is no end time, only a rate. Here is what a 10% participation order on AAPL would have been allowed to fill, half hour by half hour, on Wednesday, August 12, 2026; the fill column is one tenth of the volume that printed in each bucket.
| et_time | aapl_volume_millions | pov_child_fill_k_shares | share_of_total_pct |
|---|---|---|---|
| 09:30 | 3.82 | 382 | 12.4 |
| 10:00 | 2.8 | 280 | 9.1 |
| 10:30 | 2.5 | 250 | 8.1 |
| 11:00 | 2.35 | 235 | 7.6 |
| 11:30 | 1.96 | 196 | 6.3 |
| 12:00 | 1.62 | 162 | 5.2 |
| 12:30 | 1.37 | 137 | 4.4 |
| 13:00 | 1.22 | 122 | 3.9 |
| 13:30 | 1.6 | 160 | 5.2 |
| 14:00 | 1.51 | 151 | 4.9 |
| 14:30 | 2.73 | 273 | 8.8 |
| 15:00 | 1.93 | 193 | 6.2 |
| 15:30 | 5.49 | 549 | 17.8 |
The exact SQL behind every number
WITH bars AS
(
SELECT
toTimeZone(window_start, 'America/New_York') AS et,
toHour(et) * 60 + toMinute(et) AS minute_of_day,
toFloat64(volume) AS shares
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'AAPL'
AND window_start >= toDateTime('2026-08-12 00:00:00', 'America/New_York')
AND window_start < toDateTime('2026-08-13 00:00:00', 'America/New_York')
),
buckets AS
(
SELECT
formatDateTime(toStartOfInterval(et, INTERVAL 30 MINUTE), '%H:%i', 'America/New_York') AS et_time,
sum(shares) AS bucket_shares
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 / 1e6, 2) AS aapl_volume_millions,
toUInt32(round(b.bucket_shares * 0.10 / 1e3)) AS pov_child_fill_k_shares,
round(100 * b.bucket_shares / t.day_shares, 1) AS share_of_total_pct
FROM buckets AS b
CROSS JOIN
(
SELECT sum(bucket_shares) AS day_shares
FROM buckets
) AS t
ORDER BY et_timeIn the opening half hour the order could have filled about 382 thousand shares, one tenth of the 3.82 million that traded. In the 12:30 p.m. half hour the allowance was about 137 thousand shares, and in the closing half hour 549 thousand. The market's own volume set the pace.
What does a 10% POV order do when volume dries up at lunch?
It slows in step with the tape, and a trader with a deadline feels it. The panel below sizes the lunch dip for five liquid names over the same window: the ratio of opening half hour volume to 12:30 p.m. half hour volume, and how many shares a 10% participation order could have filled in that lunch half hour on an average session.
| ticker | opening_share_pct | lunch_share_pct | closing_share_pct | open_to_lunch_ratio | pov_lunch_fill_k_shares |
|---|---|---|---|---|---|
| MSFT | 18 | 5.4 | 14.5 | 3.4 | 145 |
| KO | 15.6 | 4.8 | 19.7 | 3.3 | 56 |
| NVDA | 17.5 | 5.5 | 12.4 | 3.2 | 586 |
| AAPL | 16.3 | 5.5 | 15.7 | 3 | 210 |
| SPY | 11.4 | 4.9 | 22 | 2.3 | 197 |
The exact SQL behind every number
WITH bars AS
(
SELECT
ticker,
toTimeZone(window_start, 'America/New_York') AS et,
toHour(et) * 60 + toMinute(et) AS minute_of_day,
toDate(et) AS et_date,
toFloat64(volume) AS shares
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'AAPL', 'MSFT', 'NVDA', 'KO')
AND window_start >= toDateTime('2026-06-01 00:00:00', 'UTC')
AND window_start < toDateTime('2026-09-01 00:00:00', 'UTC')
)
SELECT
ticker,
round(100 * sumIf(shares, minute_of_day < 600) / sum(shares), 1) AS opening_share_pct,
round(100 * sumIf(shares, minute_of_day >= 750 AND minute_of_day < 780) / sum(shares), 1) AS lunch_share_pct,
round(100 * sumIf(shares, minute_of_day >= 930) / sum(shares), 1) AS closing_share_pct,
round(sumIf(shares, minute_of_day < 600)
/ sumIf(shares, minute_of_day >= 750 AND minute_of_day < 780), 1) AS open_to_lunch_ratio,
toUInt32(round(0.10 * sumIf(shares, minute_of_day >= 750 AND minute_of_day < 780)
/ countDistinct(et_date) / 1e3)) AS pov_lunch_fill_k_shares
FROM bars
WHERE minute_of_day >= 570
AND minute_of_day < 960
GROUP BY ticker
HAVING sumIf(shares, minute_of_day >= 750 AND minute_of_day < 780) > 0
ORDER BY open_to_lunch_ratio DESCMSFT shows the steepest drop, with an opening half hour that carried 3.4 times the volume of its 12:30 p.m. half hour; SPY is the flattest of the five at 2.3 times. The ratio is above one for every name. A 10% participation order on SPY could have filled about 197 thousand shares in an average lunch half hour.
A POV order with a "must complete by" time has to abandon its rate near the deadline and catch up with larger child orders into the close, the very impact it was meant to avoid. Many platforms cap the rate, often between a quarter and a half of volume; above that, an order stops following the market and starts being the market.
TWAP vs VWAP vs POV: when each is the wrong tool
TWAP on a news day. A scheduled release, an 8:30 a.m. economic print or a 2:00 p.m. Fed statement, bunches volume and price movement around a known clock time. A flat schedule trades the same slice through the burst and into the quiet that follows, and the fills on either side can sit far apart.
VWAP when you are the volume. The historical curve describes days on which your order was absent. In a stock that trades 200,000 shares a day, a 50,000-share VWAP order is a quarter of the day, and the profile it follows is a forecast of a market that stops existing once the order starts.
POV on an illiquid name. Participation is only as fast as the tape, and on a thin stock the tape barely moves. A 10% order might fill a few hundred shares an hour and still be the most persistent buyer on the screen.
What does "best efforts" mean on a broker's VWAP order?
It means the algorithm targets the day's VWAP without guaranteeing it. One reason is already on the charts above: the schedule is built from an expected curve, and each day's realised curve differs from it. The other reason is mechanical: the child orders are ordinary limit orders underneath, sometimes midpoint peg orders or iceberg orders that display only part of their size, and a limit price on the parent can leave a portion unfilled when the stock runs away. The panel below measures that gap for each SPY half hour in the same window: the median share of the day's volume next to the lowest and highest share any single session recorded.
| et_time | median_share_pct | lowest_share_pct | highest_share_pct |
|---|---|---|---|
| 09:30 | 11.51 | 6.34 | 17.14 |
| 10:00 | 7.9 | 4.55 | 13.14 |
| 10:30 | 6.79 | 3.25 | 14.21 |
| 11:00 | 5.94 | 2.89 | 11.67 |
| 11:30 | 5.53 | 2.6 | 23.55 |
| 12:00 | 5.06 | 1.8 | 10.68 |
| 12:30 | 4.3 | 2.03 | 12.03 |
| 13:00 | 4.75 | 2.63 | 8.85 |
| 13:30 | 4.25 | 2.51 | 11.9 |
| 14:00 | 5.4 | 3.1 | 11.98 |
| 14:30 | 5.42 | 3.85 | 12.79 |
| 15:00 | 7.6 | 4.06 | 13.06 |
| 15:30 | 21.32 | 14.21 | 36.6 |
The exact SQL behind every number
WITH bars AS
(
SELECT
toTimeZone(window_start, 'America/New_York') AS et,
toHour(et) * 60 + toMinute(et) AS minute_of_day,
toDate(et) AS et_date,
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')
),
per_bucket AS
(
SELECT
et_date,
formatDateTime(toStartOfInterval(et, INTERVAL 30 MINUTE), '%H:%i', 'America/New_York') AS et_time,
sum(shares) AS bucket_shares
FROM bars
WHERE minute_of_day >= 570
AND minute_of_day < 960
GROUP BY et_date, et_time
),
per_day AS
(
SELECT
et_date,
sum(bucket_shares) AS day_shares
FROM per_bucket
GROUP BY et_date
)
SELECT
b.et_time AS et_time,
round(100 * quantileDeterministic(0.5)(b.bucket_shares / d.day_shares, toYYYYMMDD(b.et_date)), 2) AS median_share_pct,
round(100 * min(b.bucket_shares / d.day_shares), 2) AS lowest_share_pct,
round(100 * max(b.bucket_shares / d.day_shares), 2) AS highest_share_pct
FROM per_bucket AS b
INNER JOIN per_day AS d ON d.et_date = b.et_date
GROUP BY et_time
ORDER BY et_timeAcross the window's sessions the opening half hour ranged from 6.34% to 17.14% of the day's volume, around a median of 11.51%. The closing half hour ran from 14.21% to 36.6%, against a median of 21.32%. On that heaviest close, a VWAP algorithm scheduled to the median finished most of its order before the bulk of the day's volume arrived, and the day's VWAP settled wherever those late prints did. An anchored VWAP, started at the moment of the decision, is how traders check a fill against the volume that arrived afterwards.
FAQ
Is TWAP or VWAP better for a small order?
For an order that is a tiny fraction of the day's volume, both fill close to their benchmarks and the difference is small. As the order grows relative to what the stock trades, TWAP's flat schedule takes a larger share of the lunch hour and VWAP's leans on the open and the close.
What is arrival price?
Arrival price is the market price, usually the midpoint of the bid and ask, at the moment an order is submitted. Implementation shortfall is the gap between that price and the average fill, plus the cost of any shares left unfilled.
Can a VWAP order guarantee the VWAP price?
No. A VWAP algorithm schedules child orders on an expected volume curve, and the day's actual volume and prices differ from the forecast. The "best efforts" language in a broker's order description says exactly that: the order targets VWAP and does not promise it.
Every panel here ships with the exact SQL beneath it. To draw the curve for another ticker or size a participation order against a real session, ask in plain English on the Strasmore terminal.