Core Execution Algorithms (TWAP, VWAP, POV)
Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.
From OMS To Schedules
Why execution algorithms matter
Now that you've built the pieces from Order Management & FIX Integration and Market Data Handling & Order Book Reconstruction, you're ready to answer a practical trading question:
If we need to buy or sell a large quantity, how do we release it into the market without being reckless?
Core execution algorithms turn a parent order into many smaller child orders:
Parent order: Buy 100,000 shares
|
v
Execution algorithm decides timing + size
|
v
Child orders sent through OMS/FIX
In this lesson, we'll focus on three foundational execution styles:
- TWAP: trade evenly through time
- VWAP: trade according to expected volume distribution
- POV: trade as a percentage of observed market volume
These are not alpha strategies. They are execution tools: their job is to complete an order while controlling market impact, timing risk, and operational risk.

Execution Algo Map
Three ways to answer: "how much now?"
Each execution algorithm repeatedly answers one question:
At this moment, how many shares/contracts should we attempt to trade?
TWAP: Time Weighted Average Price
Split quantity across time buckets.
10:00 10:05 10:10 10:15 10:20
|------|------|------|------|
20% 20% 20% 20% 20%
Good when you want simple, predictable execution and do not have strong volume expectations.
VWAP: Volume Weighted Average Price
Split quantity based on expected market volume distribution.
Open Midday Close
High -> Low -> High volume
Good when the benchmark is market VWAP or when volume follows a known intraday curve.
POV: Percentage Of Volume
Trade as a fixed percentage of live market volume.
If market trades 50,000 shares
and POV = 10%
then target child quantity ≈ 5,000 shares
Good when you want to adapt to actual liquidity instead of a fixed clock schedule.

TWAP Scheduler
TWAP: equal slices over time
A TWAP schedule divides the parent quantity across a fixed number of time intervals.
Example:
Buy 10,000 shares over 5 intervals
=> 2,000 shares per interval
In production, TWAP usually has more details:
- minimum order size
- randomization to avoid looking robotic
- price limits
- cancel/replace behavior
- no-trade windows
- remaining quantity cleanup
But the core idea is simple: time drives the schedule.
Below is a small standalone C++ program that creates a basic TWAP schedule.
```cpp
#include <iostream>
#include <vector>
#include <iomanip>
struct Slice {
int interval;
int quantity;
};
std::vector<Slice> make_twap_schedule(int total_quantity, int intervals) {
std::vector<Slice> schedule;
schedule.reserve(intervals);
int base = total_quantity / intervals;
int remainder = total_quantity % intervals;
for (int i = 0; i < intervals; ++i) {
int qty = base + (i < remainder ? 1 : 0);
schedule.push_back({i + 1, qty});
}
return schedule;
}
int main() {
int parent_quantity = 10000;
int intervals = 5;
auto schedule = make_twap_schedule(parent_quantity, intervals);
std::cout << "TWAP schedule for " << parent_quantity
<< " shares over " << intervals << " intervals:\n";
int total = 0;
for (const auto& s : schedule) {
total += s.quantity;
std::cout << "Interval " << s.interval
<< ": send " << s.quantity << " shares\n";
}
std::cout << "Total scheduled: " << total << " shares\n";
return 0;
}
```
Choose The Driver
You need to execute a parent order, and your primary instruction is:
Trade evenly across the next 30 minutes, regardless of short-term volume changes.
Which execution algorithm best matches this instruction?
VWAP Profile
VWAP: follow expected liquidity
A VWAP schedule uses an expected market volume profile.
Many markets have a rough intraday pattern:
Open: high volume
Midday: lower volume
Close: high volume
So a VWAP schedule may trade more near the open and close, and less during quiet periods.
The basic formula is:
child quantity for bucket = parent quantity × expected volume share for bucket
If a bucket is expected to contain 25% of the day's volume, the schedule may allocate about 25% of the parent order to that bucket.
Below is a simplified VWAP allocator using a historical volume profile.
```cpp
#include <iostream>
#include <vector>
#include <cmath>
#include <iomanip>
struct VwapSlice {
int bucket;
double volume_share;
int quantity;
};
std::vector<VwapSlice> make_vwap_schedule(int parent_quantity,
const std::vector<double>& profile) {
std::vector<VwapSlice> schedule;
schedule.reserve(profile.size());
int allocated = 0;
for (std::size_t i = 0; i < profile.size(); ++i) {
int qty;
if (i + 1 == profile.size()) {
qty = parent_quantity - allocated; // fix rounding on final bucket
} else {
qty = static_cast<int>(std::round(parent_quantity * profile[i]));
allocated += qty;
}
schedule.push_back({static_cast<int>(i + 1), profile[i], qty});
}
return schedule;
}
int main() {
int parent_quantity = 100000;
// Example intraday volume profile. Must sum to approximately 1.0.
std::vector<double> profile = {0.18, 0.12, 0.08, 0.07, 0.10, 0.15, 0.30};
auto schedule = make_vwap_schedule(parent_quantity, profile);
std::cout << "VWAP-style schedule:\n";
int total = 0;
for (const auto& s : schedule) {
total += s.quantity;
std::cout << "Bucket " << s.bucket
<< " | expected volume share " << std::fixed << std::setprecision(0)
<< s.volume_share * 100 << "%"
<< " | send " << s.quantity << " shares\n";
}
std::cout << "Total scheduled: " << total << " shares\n";
return 0;
}
```
VWAP Formula
Fill in the blank:
For a simple VWAP schedule:
child quantity = parent quantity × expected ______ share
POV Adapts
POV: trade with live volume
A POV algorithm, also called participation rate, targets a percentage of observed market volume.
Example:
Target POV = 10%
Market trades 8,000 shares in a bucket
Algo targets about 800 shares
Unlike TWAP and basic VWAP, POV does not require a fixed schedule. If the market is active, it can trade more. If the market goes quiet, it slows down.
This makes POV useful when liquidity is uncertain.
Important: a POV scheduler should still obey parent-order limits, price limits, risk checks, and OMS state transitions from the earlier OMS lesson.
```cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
int main() {
int parent_remaining = 20000;
double participation_rate = 0.10; // 10% POV
// Simulated live market volume per time bucket.
std::vector<int> market_volume = {5000, 12000, 3000, 20000, 9000};
std::cout << "POV execution target: "
<< participation_rate * 100 << "% of market volume\n";
for (std::size_t i = 0; i < market_volume.size(); ++i) {
int target = static_cast<int>(market_volume[i] * participation_rate);
int child_qty = std::min(target, parent_remaining);
parent_remaining -= child_qty;
std::cout << "Bucket " << (i + 1)
<< " | market volume " << market_volume[i]
<< " | child target " << child_qty
<< " | remaining " << parent_remaining << "\n";
if (parent_remaining == 0) {
std::cout << "Parent order complete.\n";
break;
}
}
if (parent_remaining > 0) {
std::cout << "Unfilled parent quantity after stream: "
<< parent_remaining << " shares\n";
}
return 0;
}
```
POV Behavior
True or false:
A POV algorithm usually increases its target child quantity when observed market volume increases, assuming the parent order still has remaining quantity.
Execution Guardrails
Schedules are not enough
A schedule says what the algorithm wants to do. A production execution engine must still decide what it is allowed to do.
Common guardrails:
Quantity controls
- Never exceed parent remaining quantity
- Respect minimum and maximum child size
- Prevent duplicate sends after reconnects or retries
Price controls
- Do not cross beyond limit price
- Avoid trading through stale quotes
- Use the reconstructed book from the previous lesson to check current top-of-book conditions
Time controls
- Start and end windows
- Pause windows around auctions or news events
- Cancel outstanding child orders when the schedule changes
State controls
- Only replace/cancel orders in valid OMS states
- Reconcile fills from execution reports
- Stop if risk limits are breached
A useful mental model:
Schedule target -> Risk checks -> OMS state machine -> FIX message -> Exchange
The execution algorithm should be deterministic enough to debug, but flexible enough to adapt to fills, rejects, market data gaps, and partial completion.

Algorithm Comparison
Picking the right baseline
Here's the practical distinction:
Algorithm Main driver Strength Main risk TWAP Clock time Simple and predictable Ignores real liquidity VWAP Expected volume curve Matches volume benchmark Profile may be wrong POV Live market volume Adapts to liquidity May under-trade in quiet marketsHow this fits the course pipeline
You now have a clean bridge from market data and OMS infrastructure into execution logic:
Market data/book -> schedule decision -> risk checks -> OMS/FIX -> fills -> update remaining qty
In the next lesson, we'll move from executing a parent order to providing liquidity with market making. That is a different job: instead of slicing a known parent order, the system continuously manages quotes and inventory.
