Current Blog
How to Model Trading Costs in a Backtest
A useful backtest models the price and execution costs the strategy could have faced when each order was sent.
By alyc
A trading-cost model converts a strategy's theoretical order into a plausible executed result. It should account for explicit fees, the bid and ask spread, price movement caused by the order, delay, and orders that never fill. Applying a flat haircut to final returns can be useful as a first warning, but it cannot show which trades fail when liquidity, size, and order type change.
The correct starting point is the decision record. Store the time the strategy decided, the price it could observe then, the order type and size, the venue or market, the simulated fill time, and the resulting execution price. Costs can then be attached to the same path that produced the position rather than subtracted from the portfolio after the fact.
Separate the parts of trading cost
The SEC's transaction-cost discussion distinguishes commissions, spreads, market impact, and opportunity costs. That distinction is useful in a backtest because each part needs different data and reacts differently to an order.
Commissions and venue fees are explicit charges tied to the executed quantity.
Spread cost is the price paid for crossing from the midpoint to the available bid or ask.
Market impact is the adverse price movement associated with demanding liquidity.
Delay cost reflects price movement between the decision and the fill.
Opportunity cost captures the part of an intended trade that did not execute.
Borrow fees, funding payments, taxes, and financing costs may also belong in the model when the instrument or holding period requires them. They should remain separate fields. A single blended rate hides which assumption changed the result.
Do not treat the bar close as an executable price
A close, midpoint, or last trade is a reference value. It is not automatically the price available for the strategy's full order. The SEC's market-fragmentation release explains that market orders pay an implicit liquidity cost through the effective spread, while limit orders control price but may miss execution.
For a marketable buy order, a simple spread-aware model begins at the ask rather than the midpoint. A sell begins at the bid. Historical quotes are better than a fixed spread because spreads widen and narrow with market conditions. Quote data also needs a timestamp available before the simulated order. The availability-time test for backtests applies to execution inputs as well as strategy features.
Limit orders need a fill rule. Touching the limit price during a bar does not prove that the order filled. Queue position, displayed size, trade direction, and latency can determine whether the order received an execution. If those inputs are unavailable, test a range of fill assumptions and label the result as uncertain.
Make impact respond to order size
A fixed slippage rate assumes that a small order and a large order face the same market response. That is rarely a safe default. At minimum, group trades by order size relative to observed volume and apply higher cost assumptions to the larger groups. A stronger model estimates cost from historical fills or market data for the same instrument, time window, and order style.
Almgren and Chriss model permanent and temporary market impact while balancing expected execution cost against price risk during the execution period. A backtest does not need to reproduce that model in full to use its central lesson. Trading faster can increase impact, while trading more slowly leaves the order exposed to market movement and missed opportunity.
Calibrate impact outside the test period. Estimating a cost curve with the same trades used to judge the strategy can make execution look better than it would have been at the time. Keep the calibration window, instruments, order sizes, and fitting method in the run record.
Measure implementation shortfall
Implementation shortfall compares the value of the intended trade at the decision price with the value produced by executed and unexecuted quantities. It provides one ledger for spread, fees, impact, delay, and missed fills. The SEC notes that this measure begins at the price available when the decision to trade was made.
Record the benchmark price before simulating the order. Then calculate the executed quantity, average fill price, explicit charges, and remaining quantity. For a buy, a higher fill price increases shortfall. For a sell, a lower fill price increases it. An unfilled remainder should not disappear. It remains part of the missed opportunity calculation or stays as an unchanged position.
A data-lineage record should preserve the quote source, fee schedule, fill rule, impact parameters, and code revision used for each run. This makes a cost-model change visible when two otherwise identical backtests disagree.
Worked example: reconcile a $50 gross move to $44 net
Assume an invented 100-unit round trip. The entry midpoint is $50.00 and the exit midpoint is $50.50, so the midpoint-to-midpoint gain is $50.00. The modeled buy fills at the $50.02 ask and the sell at the $50.48 bid. Fill-to-fill profit is 100 × ($50.48 − $50.02) = $46.00. Two $1 commissions leave $44.00.
The reconciliation is $50 gross midpoint gain − $2 entry spread cost − $2 exit spread cost − $2 commissions = $44 net. Do not subtract the $4 spread cost a second time after already using bid/ask fill prices. This simplified example assumes a full fill and no additional impact, delay, financing, or taxes; those exclusions must stay visible.
The separation between explicit charges and implicit execution costs follows the categories in the SEC transaction-cost discussion. The prices and charges above are illustrative assumptions, not a current fee quote.
Run sensitivity tests before accepting the result
Test the strategy under a baseline cost model and several harder conditions. Widen spreads during stressed periods. Increase latency. Reduce fill probability for passive orders. Raise impact for orders that consume a larger share of observed volume. Recalculate turnover, return, drawdown, and trade count after each change.
The output should show where the strategy stops working. A result that survives one average cost assumption but fails under slightly wider spreads does not have a stable execution case. Paper-first testing can compare simulated fills with live market observations before any production authority is considered.
Cost controls should fail closed. If the backtest lacks quotes, fee schedules, or a defensible fill rule, mark execution quality as unverified. Guardrails before execution should prevent a research result from gaining authority when its cost assumptions cannot be reconstructed.
The final review should be possible at the order level. Pick one historical decision and trace its reference price, available liquidity, simulated fill, explicit charges, impact estimate, and unfilled quantity. If any part is missing, the reported return is not yet an executable result.
Editorial note: This article was prepared with AI assistance and checked against the cited sources. No named human review is recorded.




