Most backtests I get sent use one slippage number for everything. Ten basis points, maybe five if the author is feeling optimistic, applied flat across every fill in the equity curve. It looks responsible. It is a small deduction, it makes the returns a little worse, so it feels like conservatism. The problem is that a flat number is not conservative on the assets that actually matter. It is wildly optimistic on the thin ones and slightly pessimistic on the deep ones, and the strategy that looks great in aggregate is usually surviving on the thin ones. That is the trap I want to talk about.
Why a flat number is the wrong shape
Slippage is not a fixed tax. It is a function of how much you are trying to trade relative to how much liquidity is sitting there to absorb it. When you send a market order, you eat the book. You take the best offer, then the next one, then the next, until your order is filled, and your average fill price is the volume-weighted walk down that ladder. On a deep book, a normal-sized order barely moves off the top level. On a thin one, the same dollar size chews through ten price levels and you get filled at a number that would have embarrassed you if you had seen it on the screen first.
So the real variable is participation. A ten thousand dollar order into BTC is a rounding error against the resting depth. The same ten thousand into some small-cap altcoin might be a meaningful fraction of everything quoted within a percent of mid. A flat slippage number treats those two fills as identical, and they are not remotely identical. This is exactly why a strategy can post a clean backtest and then bleed the moment it goes live: the edge was real, but it was smaller than the cost of getting in and out at the size the backtest assumed.
The depth-based model, when you have snapshots
If you have historical order book snapshots, you can model the fill honestly. For each simulated trade, take the book snapshot at that timestamp, then walk it. Start at the best price on the side you are taking, consume the quantity available at each level, and keep a running total of cost and filled size until your order quantity is met. Divide total cost by total size and you have your realized average price. The difference between that and the mid at the moment of the order is your slippage, and it falls out of the data instead of being a guess.
A few things I have learned doing this. Snapshots are heavy, so most people store them at intervals rather than full tick-by-tick, and you have to accept that the book you are walking is a few hundred milliseconds stale relative to when the fill would really have happened. That is usually fine for anything holding longer than a few minutes and not fine for anything scalping. Also, walk both sides. Buying and selling the same asset can cost different amounts because books are not symmetric, and one side is often thinner than the other, especially right after a move.
The volume-participation proxy, when you do not
Most people testing on daily or hourly bars do not have book snapshots. That is fine, you can still do far better than a flat number using a participation proxy. The idea is to make slippage a function of your order size relative to the volume that traded on that bar.
The mental model is a square-root shape. Impact does not scale linearly with size, it scales roughly with the square root of the fraction of bar volume you represent. A rule of thumb I use to sketch it: pick a coefficient, multiply it by the square root of (your order size divided by bar volume), and add that to your baseline spread cost. So the slippage for a given fill is something like a fixed spread component plus an impact component that grows with the square root of your participation rate. When your order is a tiny fraction of the bar, the impact term is near zero and you are basically paying the spread. When your order is a large fraction of the bar, the impact term dominates and it grows fast.
The coefficient is where the calibration lives. You do not need it to be perfect. You need it to be roughly right per asset, because the whole point is that it is different per asset. If you have even a handful of your own real fills, back out what coefficient would have reproduced them and use that. If you have nothing, start pessimistic and loosen it only when reality proves you can.
Tier your assets by liquidity
Here is the practical piece. Do not calibrate one model and apply it everywhere. Group the assets you test into tiers and give each tier its own parameters. Something like:
- Deep majors like BTC and ETH: tight spread assumption, small impact coefficient, participation almost never bites at retail size.
- Liquid large-caps: wider spread, moderate coefficient, watch participation once orders get into the mid five figures.
- Mid-cap alts: meaningfully wider spread, larger coefficient, and assume the book is thin on at least one side.
- Thin or newly listed names: treat them as hostile. Big spread, big coefficient, and a hard cap on the fraction of bar volume you will let a single order represent.
That last point matters more than the exact numbers. Put a ceiling on participation, say you refuse to simulate an order larger than some fraction of the bar's volume, and if a signal wants more, either split it across bars or reject it. A backtest with no participation ceiling will happily fill a position size that no real book could have absorbed, and it will report that fill at a price that never existed.
The failure mode this catches
The one I see most often: a strategy shows a strong edge across a basket, you dig in, and the returns are concentrated in a few thin altcoins. On those names the modeled edge per trade is a couple of percent, which sounds robust until you price the real cost of trading them at size, and the real cost is also a couple of percent. The edge and the slippage are the same number. It survived on BTC in the aggregate stats because BTC is cheap to trade, so the blended result looked fine, but the actual money was supposedly being made where you can least afford the execution.
The tiered model exposes that immediately. Re-run with per-asset slippage and the thin-name contribution collapses, and you are left looking at whether the edge on the deep assets alone is worth trading. Usually it is smaller than you hoped and more real than what you started with. When we build execution and backtesting tooling at Blockcircle, that per-asset honesty is the part I care about most, because a curve that assumes free fills is just a story.
You do not need this to be elaborate. A spread term plus a square-root impact term, a coefficient calibrated per liquidity tier, and a hard participation cap on the thin stuff will get you most of the way. The goal is not a perfect fill simulator. It is to stop lying to yourself about the assets where lying is cheapest and costs the most.