Build the fill from a quoted midpoint
An order sized at a fraction of typical daily volume can use a scenario rule . This is a modelling choice. Estimate in consistent units, segment by asset and liquidity, and avoid extrapolation far beyond observed sizes. A separate participation limit can cap the shares filled within each bar. Add market movement between decision and arrival when your reference timestamp precedes the simulated execution window.
Update cash by , with set by the brokerage schedule, including per-order minimums and per-share charges if relevant. Choose whether fees apply per fill or to a parent order. For longer-horizon cost models, specify how lasting impact changes subsequent marks and fills.
Reconcile every component on a 5,000-share buy
A buy for 5,000 shares arrives at a $40.00 midpoint, with a $0.04 spread and typical volume of 500,000 shares. With , the impact fraction is . The simulated fill is $40.036. Spread costs $100, impact costs $80, and fees of half a cent per share cost 25 dollars. The total shortfall from the arrival midpoint is $205, or 10.25 basis points of $200,000 reference notional.
On the sell side, check that the same spread and impact assumptions push the fill below the arrival midpoint. Record execution cost as signed quantity times fill price minus midpoint, with the fee added separately. If P&L already uses the fill price, spread and temporary impact have already entered it. Deducting those amounts as a second charge would count them twice. Use the price bridge to explain the result, and use explicit fees for cash deductions that the fill price does not capture.
Implement signed fills and fees
from math import copysign, sqrt
def market_fill(mid, spread, shares, daily_volume, impact_scale=0.004):
impact = impact_scale * sqrt(abs(shares) / daily_volume)
price = mid + copysign(spread / 2 + mid * impact, shares)
commission = max(1.0, 0.005 * abs(shares))
cash_change = -shares * price - commission
shortfall = shares * (price - mid) + commission
return price, cash_change, shortfall
print(market_fill(40.0, 0.04, 5_000, 500_000))This function prices a nonzero order assumed to fill in full. In a simulator, apply it only to the quantity the current execution window can fill.
References and next steps
- QuantConnect, slippage models shows practical fill-model assumptions.
- How to Test Whether a Significant Signal Survives Costs