TWAP in Python
Time-Weighted Average Price — the average price of an asset calculated at equal time intervals, used to execute large orders with minimal market impact.
Definition
TWAP (Time-Weighted Average Price) is the arithmetic average of prices sampled at fixed, equally-spaced time intervals over a defined execution window, in contrast to VWAP which weights by volume. As an execution algorithm, TWAP divides a large parent order into equal child orders and releases them at uniform time intervals across the execution window, without regard for volume patterns. It is the simplest and most predictable execution algorithm, making it easy to game by sophisticated market participants but appropriate for illiquid markets where volume forecasting is unreliable or when minimizing market impact is less important than deterministic execution timing.
Quantitative Formula
Where is the mid-price (or last traded price) at equally-spaced time interval , and is the total number of sampling intervals over the measurement or execution window. Unlike VWAP, every time period contributes equally regardless of trading volume. A TWAP execution algorithm releases shares at each interval, where is the total order quantity and is the number of time slices.
Why It Matters in Backtesting
In backtesting, the choice between TWAP and VWAP as an execution assumption has significant P&L implications for large institutional strategies. TWAP execution tends to underperform VWAP in trending markets (it buys at evenly-distributed prices rather than concentrating volume in high-liquidity periods) but outperforms in mean-reverting, unpredictable volume environments. The key backtesting discipline is consistency: every strategy backtest must use the same execution benchmark assumption that will be applied in live trading — mixing VWAP assumptions in backtesting with TWAP execution in production is a common and costly methodology error.
Python Implementation
import numpy as np
import pandas as pd
def twap_execution_simulator(price_series: pd.Series, order_quantity: float,
execution_window_bars: int = 30,
start_bar: int = 0,
side: str = "buy") -> dict:
"""
Simulates TWAP execution of a large order across a defined time window.
price_series: Intraday price series (e.g., 1-minute bars).
order_quantity: Total shares/contracts to execute.
execution_window_bars: Number of bars over which to distribute the order.
side: 'buy' or 'sell'.
"""
execution_prices = price_series.iloc[start_bar:start_bar + execution_window_bars]
n_slices = len(execution_prices)
slice_quantity = order_quantity / n_slices
fills = pd.DataFrame({
"bar": range(n_slices),
"price": execution_prices.values,
"quantity": slice_quantity
}, index=execution_prices.index)
twap_benchmark = execution_prices.mean()
avg_fill_price = (fills["price"] * fills["quantity"]).sum() / fills["quantity"].sum()
slippage_bps = ((avg_fill_price - twap_benchmark) / twap_benchmark
* (1 if side == "buy" else -1)) * 10000
return {
"fills": fills,
"twap_benchmark": twap_benchmark,
"average_fill_price": avg_fill_price,
"slippage_vs_twap_bps": slippage_bps,
"total_quantity_executed": fills["quantity"].sum(),
"execution_complete": np.isclose(fills["quantity"].sum(), order_quantity)
}Test this in a live environment
Stop running Jupyter notebooks locally. Paste this TWAP code directly into Valetha's Strategy Lab and run a full historical backtest in seconds.
Open the Python Strategy Lab