Brokerage Slippage in Python
The difference between the expected execution price of a trade and the actual price at which it is filled, eroding real-world strategy returns.
Definition
Brokerage Slippage is the aggregate of all transaction costs that separate a theoretical backtest from live trading reality. It encompasses three distinct components: the bid-ask spread (the cost of immediacy), market impact (the price movement caused by your own order in the order book), and commission fees. Slippage is not constant — it scales with order size relative to market liquidity, is dramatically higher in illiquid assets or at market open/close, and spikes during volatility events. Strategies that appear highly profitable in frictionless backtests frequently become breakeven or loss-making once realistic slippage is applied.
Quantitative Formula
Where is the actual execution price, is the theoretical price at which the signal was generated (typically prior close or VWAP), and is for long entries (higher fill price is worse) and for short entries. Total slippage cost per trade is expressed in basis points (bps): .
Why It Matters in Backtesting
A high-frequency mean-reversion strategy generating 0.05% per trade with a theoretical Sharpe of 3.2 may generate zero alpha after 0.03% per-side slippage and 0.01% commission — costs that are perfectly normal in institutional execution. In backtesting, slippage must be modeled as a function of liquidity (ADV — Average Daily Volume), with larger orders receiving exponentially worse fills. Any backtest that uses exact close prices for execution without applying at minimum 5–15 basis points of round-trip slippage is producing fiction rather than analysis.
Python Implementation
import numpy as np
import pandas as pd
def apply_realistic_slippage(signals: pd.Series, prices: pd.DataFrame,
commission_bps: float = 5.0,
spread_bps: float = 3.0,
market_impact_factor: float = 0.1) -> dict:
"""
Applies a realistic 3-component slippage model to a signal series.
signals: +1 (long), -1 (short), 0 (flat) for each period.
prices: DataFrame with 'Close', 'Volume', 'ADV_20' (20-day avg daily volume).
commission_bps: Round-trip commission in basis points.
spread_bps: Half-spread cost per side in basis points.
market_impact_factor: Scales market impact with order size vs ADV.
"""
trades = signals.diff().fillna(0).abs() # 1 where position changes
# Market impact: larger trades relative to ADV create more impact
order_size_ratio = 1.0 # Assume fixed 1% of ADV; adjust per strategy
market_impact_bps = market_impact_factor * order_size_ratio * np.sqrt(
prices.get("ADV_20", pd.Series(1, index=prices.index)) /
prices.get("Volume", pd.Series(1, index=prices.index))
) * 10000
total_slippage_bps = trades * (commission_bps + spread_bps + market_impact_bps)
slippage_as_return = -total_slippage_bps / 10000
return {
"slippage_series_bps": total_slippage_bps,
"slippage_as_return": slippage_as_return,
"total_cost_bps": total_slippage_bps.sum(),
"avg_cost_per_trade_bps": total_slippage_bps[trades > 0].mean(),
"total_trades": int(trades.sum()),
"annualized_drag": slippage_as_return.sum() * (252 / len(signals))
}Test this in a live environment
Stop running Jupyter notebooks locally. Paste this Brokerage Slippage code directly into Valetha's Strategy Lab and run a full historical backtest in seconds.
Open the Python Strategy Lab