How orders actually fill: the limit order book, the bid–ask spread, and what it really costs to push size through the market.
Weeks 6–8 decided what to hold — W6 target weights, W7 factor exposures, W8 stress tests. But none of it is a position until an order fills. Market microstructure is the mechanism that turns a target weight into a fill: the order book, the counterparties, and the price you pay for immediacy.
Every strategy QR hands over was backtested on closing prices or mids — no spread, no impact, infinite liquidity. Live, the spread is real, your own order moves the price, and the strategy has a capacity: a size beyond which impact eats the edge. Trading inside it is Pillar 4.
By Friday you should be able to:
Reading: Harris, Trading and Exchanges (2003) is the readable canonical text; O'Hara, Market Microstructure Theory (1995) for the models; Almgren & Chriss (2000) for optimal execution; Perold (1988) for implementation shortfall. Bouchaud et al., Trades, Quotes and Prices (2018) for the empirical impact literature.
Most modern equity and futures venues are continuous double auctions built around a limit order book (LOB): every resting order to buy or sell, ranked by price. Buy orders are bids, sell orders asks (offers); the highest bid and lowest ask are the top of book. In US equities the consolidated top across venues is the NBBO (National Best Bid and Offer).
Two orders compete for the same price by price–time priority (price first, then arrival time — FIFO). Some venues use pro-rata matching instead, splitting a fill across resting orders by size. A snapshot for a stock quoting around $50:
| Level | Side | Price | Size (shares) | Cumulative |
|---|---|---|---|---|
| Ask +3 | Sell | 50.06 | 1,200 | 3,100 |
| Ask +2 | Sell | 50.05 | 1,400 | 1,900 |
| Best Ask | Sell | 50.04 | 500 | 500 |
| — mid 50.035 · spread 0.01 (2.0 bps) — | ||||
| Best Bid | Buy | 50.03 | 600 | 600 |
| Bid −2 | Buy | 50.02 | 900 | 1,500 |
| Bid −3 | Buy | 50.01 | 1,500 | 3,000 |
A market order demands immediacy and walks the book: to buy 1,000 shares now you take all 500 at 50.04, then 500 of the 1,400 at 50.05, for a size-weighted fill of 50.045 — 1 bp of half-spread (mid 50.035 → ask 50.04) plus ~1 bp of impact from the second level. A limit order instead joins the book and waits — no spread paid, but no guarantee of a fill.
The spread is the price of immediacy. Three measurements, increasingly honest about what you actually paid. Let \( m_t \) be the mid and \( D=+1 \) for a buy, \( -1 \) for a sell.
\[ m_t=\frac{P^{\text{bid}}_t+P^{\text{ask}}_t}{2}, \qquad s^{\text{quoted}}_t = P^{\text{ask}}_t - P^{\text{bid}}_t \]The quoted spread is what the screen shows — but you rarely trade exactly at the quote, getting price improvement inside it or paying up by walking the book. The effective spread measures realized cost against the mid at the fill:
\[ s^{\text{eff}} = 2\,D\,\bigl(P_{\text{exec}} - m_t\bigr) \qquad\bigl[\text{in bps: } s^{\text{eff}}/m_t \times 10^4\bigr] \]The factor of 2 makes it comparable to the round-trip quoted spread: a fill at the far touch gives \( s^{\text{eff}} = s^{\text{quoted}} \), price improvement less, walking the book more. The realized spread then marks the fill against the mid a short interval \( \Delta \) later (5 min is common):
\[ s^{\text{real}} = 2\,D\,\bigl(P_{\text{exec}} - m_{t+\Delta}\bigr), \qquad \underbrace{s^{\text{eff}}}_{\text{you paid}} = \underbrace{s^{\text{real}}}_{\text{maker kept}} + \underbrace{\bigl(s^{\text{eff}} - s^{\text{real}}\bigr)}_{\text{price impact}} \]That decomposition is the whole game from the maker's side: effective spread is what the taker pays, realized spread is what the maker keeps after the price moves, and the difference is adverse-selection cost — they traded with someone who knew more.
A market maker quotes a two-sided price and earns the spread for standing ready to trade. The classic decomposition (Stoll 1978; Glosten–Milgrom 1985; Ho–Stoll 1981) splits it into three costs:
The fixed, mechanical cost of being in the business — exchange and clearing fees, technology, the minimum tick. Roughly constant per trade; dominant in liquid, low-information names where the other two costs are small.
A maker who buys your sell holds unwanted inventory and bears price risk until they offload it — the wider the spread, the faster they're paid for that exposure. Inventory models (Ho–Stoll, Amihud–Mendelson) have the maker skew quotes to mean-revert the position toward zero.
Some counterparties are informed — they trade because they know something. The maker systematically loses to them and must recoup it from uninformed flow by widening the spread (Glosten–Milgrom). Kyle (1985) formalizes the same force as price impact \( \lambda \): price moves linearly in net order flow.
These three set the floor on your trading cost, and they are not constant. Spreads widen at the open, into the close, around news, and in stress (recall the 2020 liquidity squeeze in W8). Sizing that ignores this assumes a spread that isn't there when you need it.
Every fill has a liquidity provider (the resting limit order — the maker) and a liquidity taker (the marketable order that hits it). Most US equity venues run maker–taker pricing: the taker pays a fee, the maker collects a rebate. A representative tape-A schedule is a taker fee around \$0.0030/share and a maker rebate around \$0.0020–0.0025/share; inverted venues flip the sign to attract takers.
The consequence: posting (joining the book) and crossing (taking) have different all-in costs even before impact — a passive fill can earn the rebate and the half-spread, an aggressive fill pays the half-spread and the access fee. The cost of patience is fill risk: your limit order may never trade, and the price may run (timing risk, below).
Posting is cheap but uncertain; taking is certain but expensive. Every execution decision QT makes is a point on that line — and the right point depends on how much the signal decays while you wait.
The order type is how you express your position on the cost-vs-certainty tension. The essential set:
| Type | Behavior | Use when |
|---|---|---|
| Market | Fills immediately against the book at whatever price it reaches. | Immediacy dominates cost; small size relative to top-of-book depth. |
| Limit | Rests at a stated price or better; may not fill. | Capturing the spread / rebate matters more than certainty of fill. |
| Marketable limit | A limit priced through the book — fills now, but caps the worst price. | You want immediacy but a hard cap on slippage from walking the book. |
| IOC (immediate-or-cancel) | Takes whatever is available right now, cancels the rest. | Sweeping available liquidity without leaving a resting footprint. |
| FOK (fill-or-kill) | All-or-nothing, immediately. | The position only makes sense in full size. |
| Stop / stop-limit | Dormant until a trigger price, then becomes a market / limit order. | Risk exits and breakout entries — not a resting book order until triggered. |
| Pegged | Auto-tracks a reference (mid, bid, or ask) as it moves. | Staying at the touch passively without constant re-quoting. |
| Hidden / iceberg | Displays none / only a slice of true size. | Working large size while minimizing information leakage. |
Crossing the spread is the visible cost. The larger, hidden cost is market impact — your own trading moves the price against you. It splits in two:
Empirically, impact is concave in size — it grows like the square root of the order, not linearly. The widely-used approximation (Almgren et al.; BARRA; Tóth–Bouchaud):
\[ \frac{\Delta P}{P} \;\approx\; Y\,\sigma\,\sqrt{\frac{Q}{V}} \]where \( \sigma \) is daily volatility, \( Q \) the order size, \( V \) average daily volume (ADV), and \( Y \) a constant of order one (\( \approx 0.3\text{–}1 \)). The square root is the key fact: doubling the order doesn't double the cost — 4× the size costs ~2× the impact. The curve below uses \( Y=0.5,\ \sigma=2\% \):
This curve is why capacity exists. A signal worth 40 bps per trade is pure profit at 1% of ADV (~10 bps cost) and underwater at 40% (~63 bps). Tradable size is wherever impact crosses the edge — and the only way past it is to spread the order over time.
How do you score an execution? Perold's (1988) implementation shortfall (IS) compares the paper portfolio — filled instantly and free at the arrival price (the price when you decided to trade) — against the real portfolio you got. Everything that makes reality worse than paper is the shortfall:
\[ \text{IS} = \underbrace{(P_{\text{exec}} - P_{\text{dec}})\,Q_{\text{filled}}\,D}_{\text{execution cost}} \;+\; \underbrace{(P_{\text{end}} - P_{\text{dec}})\,Q_{\text{unfilled}}\,D}_{\text{opportunity cost}} \;+\; \text{fees} \]The first term is the spread and impact you paid on filled shares. The second is the opportunity cost of shares you didn't get because you were too passive and the price ran — what market orders avoid and limit orders incur. IS is the honest, all-in number, and the standard benchmark precisely because it can't be gamed with a flattering reference.
Computing effective spread and IS from a fills table is a few lines:
import pandas as pd
# fills: one row per execution, with the prevailing bid/ask at fill time
fills['mid'] = (fills['bid'] + fills['ask']) / 2
fills['side'] = fills['is_buy'].map({True: 1, False: -1}) # D
# effective spread per fill, in bps (signed by direction)
fills['eff_spread_bps'] = 2 * fills['side'] * (fills['price'] - fills['mid']) \
/ fills['mid'] * 1e4
# implementation shortfall vs the arrival (decision) price, for a buy
arrival = 50.035
exec_vwap = (fills['price'] * fills['qty']).sum() / fills['qty'].sum()
is_bps = (exec_vwap - arrival) / arrival * 1e4
print(f"avg effective spread {fills['eff_spread_bps'].mean():.2f} bps")
print(f"exec VWAP {exec_vwap:.4f} IS {is_bps:.1f} bps vs arrival")
The fix for impact is to slice a parent order into child orders over time. How you slice is the schedule, and each makes a different bet on the impact-vs-timing-risk trade-off — trade fast and pay impact, or trade slow and risk the price drifting away while you wait (Almgren–Chriss formalize this as an efficient frontier).
| Algo | Schedule | Benchmark / goal | Trade-off |
|---|---|---|---|
| TWAP | Equal slices across a fixed clock window. | Time-weighted average price. | Simple, predictable; ignores when volume actually shows up. |
| VWAP | Slices tracking the intraday (U-shaped) volume profile. | Volume-weighted average price. | Blends into natural volume; underperforms if the day's profile is abnormal. |
| POV (participation) | A fixed % of live market volume until done. | Stay a constant fraction of flow. | Self-adjusts to liquidity; completion time is uncertain. |
| Implementation Shortfall | Front-loaded; trades faster when the signal is urgent or vol is low. | Minimize slippage vs the arrival price. | Lowest expected IS; takes more impact up front to cut timing risk. |
The schedule should follow the signal's decay. A fast-decaying alpha (gone by tomorrow) wants an IS / arrival-price algo — pay impact now, because waiting forfeits the trade. A slow, no-urgency rebalance wants VWAP or a low POV — minimize footprint, let timing risk wash out. Matching schedule to decay is the practical core of Pillar 4.