6.2.6Backtesting Frameworks

Learn about slippage assumptions

2,694 words12 min readdifficulty · medium

What is Slippage?

WHY it exists: Markets are not infinitely liquid. Large orders consume available liquidity at each price level, forcing subsequent fills at worse prices. Even small orders face the bid-ask spread—a guaranteed minimum slippage.

HOW it manifests: You decide to buy when price is 50.00(midmarket).Bythetimeyourorderarrives,theaskis50.00 (mid-market). By the time your order arrives, the ask is 50.05. You get filled at 50.05.Slippage=50.05. Slippage = 0.05 = 10 basis points.

Deriving Slippage Models from First Principles

1. Fixed Slippage Model

Assumption: Every trade pays a constant slippage ss (in basis points or absolute dollars).

Derivation:

  • Expected fill price when buying: Pfill=Pdecision×(1+s)P_{\text{fill}} = P_{\text{decision}} \times (1 + s)
  • Expected fill price when selling: Pfill=Pdecision×(1s)P_{\text{fill}} = P_{\text{decision}} \times (1 - s)

WHY this form? It's the simplest model: assumes average market conditions and ignores volatility, order size, and liquidity variations.

Example: Buy 100 shares at 50,50, s = 0.001$ (10 bps)

  • Expected fill: 50×1.001=50.0550 \times 1.001 = 50.05
  • Slippage cost: 100 \times 50 \times 0.001 = \5$

Why this step? Multiplying by price converts basis points to dollars. The absolute value Q|Q| ensures slippage is always a cost, never a gain. Watch the conversion: 5 bps is 0.00050.0005 (not 0.0050.005)—a factor-of-10 slip here silently inflates your costs tenfold.

2. Volume-Dependent Slippage Model

Assumption: Larger orders relative to average volume experience worse slippage.

Derivation from market microstructure:

  • The order book has depth DiD_i at each price level PiP_i
  • Your order QQ walks up the book, consuming liquidity
  • Average fill price is the volume-weighted average of levels consumed

For a market order of size QQ in a market with average volume VV: Market ImpactQV\text{Market Impact} \propto \sqrt{\frac{Q}{V}}

WHY the square root? This is the empirical "square-root law" of market impact, documented across many later microstructure studies (e.g., Almgren, Toth, Bouchaud). Note: Kyle's original 1985 lambda model implies linear impact (ΔP=λQ\Delta P = \lambda \cdot Q); the Q/V\sqrt{Q/V} scaling is an empirical regularity observed in real trade data, not a direct consequence of Kyle's model. Intuitively, the square root captures diminishing marginal impact—informed traders splitting orders can't extract unlimited profit.

Example: α=0.1\alpha = 0.1, Q=1000Q = 1000, V=100,000V = 100{,}000

  • s=0.1×1000/100000=0.1×0.1=0.01=100s = 0.1 \times \sqrt{1000/100000} = 0.1 \times 0.1 = 0.01 = 100 bps
  • On a 50stock:slippagecost=50 stock: slippage cost = 1000 \times 50 \times 0.01 = $500$

Why this step? The square root captures diminishing returns—doubling order size doesn't double impact. Dividing by volume normalizes across different liquidity regimes.

3. Volatility-Adjusted Slippage

Assumption: High volatility → prices move faster → more slippage.

Derivation:

  • During latency τ\tau (time to execution), price follows random walk with volatility σ\sigma
  • Expected price move: ΔPστ\Delta P \sim \sigma \sqrt{\tau}
  • Worst-case (directional): ΔP=στ\Delta P = \sigma \sqrt{\tau} against you

Unit convention for τ\tau: Since σ\sigma is annualized, τ\tau must be expressed as a fraction of a year. Examples:

  • Half a trading day: τ=0.52520.001980.002\tau = \dfrac{0.5}{252} \approx 0.00198 \approx 0.002 years
  • One full trading day: τ=12520.003970.004\tau = \dfrac{1}{252} \approx 0.00397 \approx 0.004 years
  • A few seconds of latency: τ\tau is essentially 00 on this scale, so intraday HFT models often use per-second volatility instead.

Example (half-day latency): σ=0.30\sigma = 0.30 (30% annual), τ=0.5/2520.002\tau = 0.5/252 \approx 0.002 years

  • svol=0.5×0.30×0.002=0.5×0.30×0.04470.0067=67s_{\text{vol}} = 0.5 \times 0.30 \times \sqrt{0.002} = 0.5 \times 0.30 \times 0.0447 \approx 0.0067 = 67 bps

Why this step? We use τ\sqrt{\tau} because price diffusion scales with square root of time (Brownian motion). The factor kk acknowledges you won't always get hit by the worst-case move.

4. Combined Slippage Model

Real-world: All effects occur together.

stotal=sfixed+αQV+kστs_{\text{total}} = s_{\text{fixed}} + \alpha \sqrt{\frac{Q}{V}} + k \sigma \sqrt{\tau}

Example: Trade 500 shares, V=50,000V = 50{,}000, σ=0.25\sigma = 0.25, τ=0.001\tau = 0.001 years (~a quarter trading day)

  • Fixed: sfixed=0.0005=5s_{\text{fixed}} = 0.0005 = 5 bps
  • Volume: 0.1×500/50000=0.1×0.1=0.01=1000.1 \times \sqrt{500/50000} = 0.1 \times 0.1 = 0.01 = 100 bps
  • Volatility: 0.5×0.25×0.001=0.5×0.25×0.03160.00395=39.50.5 \times 0.25 \times \sqrt{0.001} = 0.5 \times 0.25 \times 0.0316 \approx 0.00395 = 39.5 bps
  • Total: 0.0145=144.5\approx 0.0145 = 144.5 bps

Why this step? Note carefully: the volume term 0.010.01 equals 1%=1001\% = 100 bps (since 1%=1001\% = 100 bps, and 0.01=100×0.00010.01 = 100 \times 0.0001), not 10 bps. A 500-share order that is 1% of daily volume already generates significant impact—another reminder to keep bps conversions straight (1 bp=0.00011 \text{ bp} = 0.0001).

Implementing Slippage in a Backtest

Step-by-step:

  1. Choose your model based on strategy frequency:

    • High-frequency (seconds): use volatility + volume model
    • Medium-frequency (minutes-hours): use volume + fixed
    • Low-frequency (daily+): fixed slippage often sufficient
  2. Calibrate parameters from real execution data:

    • Measure actual fill prices vs. decision prices over 100+ trades
    • Fit ss, α\alpha, kk to minimize error
    • If no real data: use conservative estimates (10-20 bps for retail, 2-5 bps for institutional)
  3. Apply on every trade:

    # Pseudocode for backtest engine
    def execute_order(decision_price, quantity, volume, volatility):
        s_fixed = 0.0005  # 5 bps  (recall: 1 bp = 0.0001)
        s_volume = 0.1 * sqrt(abs(quantity) / volume)
        s_volatility = 0.5 * volatility * sqrt(latency_in_years)
        total_slippage = s_fixed + s_volume + s_volatility
     
        if quantity > 0:  # Buy
            fill_price = decision_price * (1 + total_slippage)
        else:  # Sell
            fill_price = decision_price * (1 - total_slippage)
     
        return fill_price

Why this structure? Slippage is directional—always hurts you. Buys get worse fills (higher price), sells get worse fills (lower price).

Recall Explain to a 12-Year-Old

Imagine you're at a lemonade stand that posts prices every minute. You see "Lemonade: 1"anddecidetobuy.Butbythetimeyouwalkupandhandoveryourdollar,thesignchangesto"1" and decide to buy. But by the time you walk up and hand over your dollar, the sign changes to "1.10" because five other kids bought first and now there's less lemonade left. You have to pay $1.10 because you already committed. That extra 10¢ is slippage.

Big buyers have it worse: if you want 10 lemonades and the stand only has 3 at 1,thenext3cost1, the next 3 cost 1.20, and the last 4 cost 1.50.Youraveragepriceiswayhigherthantheposted1.50. Your average price is way higher than the posted 1. That's market impact.

In stock trading, this happens thousands of times. If you forget to account for it when testing your strategy, your backtest thinks you're making money, but in real life, you're paying extra on every trade. It's like forgetting to count the delivery fee when budgeting for pizza!

Connections

  • Transaction costs and their impact – slippage is one component of total transaction costs
  • Realistic order execution modeling – extends slippage with partial fills and fill probability
  • Market microstructure basics – order book dynamics explain why slippage exists
  • Look-ahead bias – ignoring slippage is a form of look-ahead bias (assumes perfect execution)
  • Position sizing – slippage costs scale with position size, affecting optimal sizing

#flashcards/stock-market

What is slippage in trading?
The difference between the expected price of a trade (decision price) and the actual execution price, caused by market impact, latency, liquidity constraints, and bid-ask spread.
What are the four main sources of slippage?
(1) Market impact – your order moves price against you, (2) Latency – price changes between decision and execution, (3) Liquidity constraints – insufficient volume at target price, (4) Spread crossing – paying ask/receiving bid.
What is 1 basis point as a decimal, and what is 5 bps?
1 bp = 0.0001 (one hundredth of a percent). So 5 bps = 0.0005, NOT 0.005. A misplaced zero inflates costs by 10×.
Is the √(Q/V) market-impact law derived from Kyle's 1985 model?
No. Kyle's original lambda model implies LINEAR impact (ΔP = λ·Q). The square-root law is an empirical regularity found in later microstructure studies (Almgren, Toth, Bouchaud), not a consequence of Kyle's model.
What is the minimum slippage you pay even on small orders?
Half the bid-ask spread, because market orders always cross the spread (buy at ask, sell at bid). This is never zero in real markets.
Fixed slippage formula for total cost?
Slippage Cost = |Q| × P × s, where Q is quantity, P is decision price, s is slippage rate (e.g., 0.001 for 10 bps). Absolute value ensures slippage is always a cost.
Why does volatility increase slippage?
During execution latency τ, price follows a random walk with volatility σ. Expected adverse price move scales as σ√τ (Brownian motion). Higher volatility → larger price changes while your order is in flight.
Why must τ be expressed in years in the volatility slippage formula?
Because σ is annualized. To keep units consistent, τ must be a fraction of a year: e.g., half a trading day = 0.5/252 ≈ 0.002 years, one trading day = 1/252 ≈ 0.004 years.
Combined slippage model formula?
s_total = s_fixed + α√(Q/V) + kσ√τ, where s_fixed is base slippage, α is impact coefficient, Q/V is order-to-volume ratio, σ is volatility, τ is latency in years.
Why do backtests dramatically overestimate returns when ignoring slippage?
High-turnover strategies pay slippage on every round-trip (buy + sell). With 50 trades/year at 10 bps per side, total cost is 50 × 20 bps = 1000 bps = 10% annual drag. This can eliminate most or all alpha.
What is the "adverse selection" problem with limit orders?
Limit orders tend to fill when the price moves against you (adverse selection) and miss when the price moves in your favor. You can't model them as "zero slippage" – you need to account for fill probability and opportunity cost of missed fills.
Why is using average volatility for slippage modeling a mistake?
Volatility clusters – it spikes during earnings, news, market stress. Slippage is worst exactly when volatility is highest. Using 30-day average underestimates slippage during critical high-volatility periods. Use recent realized volatility instead.

Concept Map

is

causes

arises from

arises from

arises from

arises from

modeled by

modeled by

assumes

cost formula

derived from

square-root law

drives

guarantees

Slippage

Gap between expected and actual price

Backtest overconfidence

Market impact

Latency

Liquidity constraints

Spread crossing

Fixed slippage model

Volume-dependent model

Constant rate s in bps

Qty x Price x s

Market microstructure

Impact scales with sqrt Q over V

Minimum slippage per trade

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Dekho, slippage ka simple funda ye hai ki jab tum backtest me strategy chalate ho, tumhara code bolta hai "buy at 100"paraslimarketmetumkabhibilkul100" — par asli market me tum kabhi bilkul 100 pe fill nahi hote, tum $100.15 pe fill hote ho. Ye chota sa 15 cent ka difference chota lagta hai, par jab tum hazaaron trades karte ho, to ye chota tax milke tumhari profitable strategy ko loss-making bana deta hai. Isiliye slippage ko ignore karna sabse khatarnaak galti hai — tumhe lagta hai strategy jeet rahi hai, par real trading me ye har trade pe paisa kha jaata hai.

Ab slippage aata kahan se hai? Char main reasons hain — market impact (tumhara bada order khud price ko against move kara deta hai), latency (decision aur execution ke beech price hil jaati hai), liquidity constraint (tumhare target price pe itna volume hi nahi hota), aur spread crossing (buy karte waqt ask pay karo, sell karte waqt bid milega). Isko model karne ke liye do main tarike hain: Fixed slippage jisme har trade pe constant rate s lagta hai (jaise 10 bps = 0.001), aur Volume-dependent slippage jisme bada order zyada slippage khaata hai. Yahan ek zaroori cheez — square-root law: impact √(Q/V) ke proportion me badhta hai, matlab order double karne se impact double nahi hota, uss se kam badhta hai. Ye diminishing returns ka concept real trade data se observe hua hai.

Kyun matter karta hai ye tumhare liye? Kyunki ek realistic backtest wahi hai jo slippage ko sahi se add kare. Ek chhoti si mistake — jaise 5 bps ko 0.0005 ki jagah 0.005 likh dena — tumhare cost ko 10 guna galat bana deti hai aur tumhara pura analysis jhooth ho jaata hai. Toh jab bhi tum apna strategy test karo, hamesha realistic slippage assumption daalo, taaki paper pe jo profit dikh raha hai wo real trading me bhi tikke. Warna overconfidence me tum real paise se loss maar loge.

Test yourself — Backtesting Frameworks