Chapter 22 — Market Microstructure

"The order book is the market. Everything else is derived from it."


Modern financial markets are electronic matching engines processing millions of events per second. The surface of a market — a single quoted bid and ask price — conceals a layered order book: hundreds or thousands of resting limit orders waiting for execution at various price levels above and below the current mid-price. When a market order arrives, it is matched against the best available limit order on the opposite side, consuming liquidity at that price. If the order is large enough to exhaust the best level, it continues into the next level, and so on — a process called walking the book that generates immediate price impact for large trades.

Understanding this mechanism is essential for any quantitative practitioner. Execution cost is not just the bid-ask spread — it is the full implementation shortfall between the decision price (the mid-price when the decision to trade is made) and the final average execution price, which includes spread, market impact, timing risk, and opportunity cost. For a large asset manager trading in size, these costs can easily exceed $100 million per year; for a high-frequency firm, they determine whether a strategy is profitable at all.

This chapter builds an order book simulator, implements market impact models (the linear Kyle lambda and the empirical square-root model), studies the economics of market making under adverse selection, and implements standard execution benchmarks (VWAP, TWAP, implementation shortfall). These concepts feed directly into Chapter 23's execution algorithms.


22.1 Order Book Fundamentals

module Order_book = struct

  type side = Bid | Ask

  type order = {
    id        : int;
    side      : side;
    price     : float;
    qty       : float;
    timestamp : int64;   (* nanoseconds since epoch *)
  }

  (** Price-time priority order book *)
  module PriceMap = Map.Make(struct
    type t = float * int64
    let compare (p1, t1) (p2, t2) =
      (* Bids: highest price first, then earliest time *)
      let c = compare p2 p1 in
      if c <> 0 then c else Int64.compare t1 t2
  end)

  type t = {
    bids : order PriceMap.t;
    asks : order PriceMap.t;
    last_trade : float option;
  }

  let empty = { bids = PriceMap.empty; asks = PriceMap.empty; last_trade = None }

  let best_bid book =
    if PriceMap.is_empty book.bids then None
    else Some (fst (PriceMap.min_binding book.bids))

  let best_ask book =
    if PriceMap.is_empty book.asks then None
    else Some (fst (PriceMap.min_binding book.asks))

  let spread book =
    match best_bid book, best_ask book with
    | Some (b, _), Some (a, _) -> Some (a -. b)
    | _ -> None

  let mid_price book =
    match best_bid book, best_ask book with
    | Some (b, _), Some (a, _) -> Some ((a +. b) /. 2.0)
    | _ -> None

  (** Level-2 market data: aggregated quantities at each price level *)
  let depth ~book ~side ~levels =
    let m = match side with Bid -> book.bids | Ask -> book.asks in
    let bindings = PriceMap.bindings m in
    List.filteri (fun i _ -> i < levels) bindings
    |> List.map (fun ((price, _), order) -> price, order.qty)

end

22.2 Market Impact

When a large order executes, it moves the price. The Kyle (1985) model gives:

$$\Delta p = \lambda Q, \quad \lambda = \frac{\sigma_u}{2\sigma_z}$$

where $\sigma_u$ is information variance and $\sigma_z$ is noise order flow.

Square-root impact law (empirical):

$$\Delta p = \sigma \cdot \gamma \cdot \sqrt{\frac{Q}{V_{\text{daily}}}}$$

module Market_impact = struct

  (** Square root impact model: η usually ~0.3–0.5 *)
  let price_impact ~vol_daily ~adv ~order_qty ?(eta = 0.4) () =
    vol_daily *. eta *. sqrt (order_qty /. adv)

  (** Permanent vs temporary impact (Almgren-Chriss) *)
  type impact_params = {
    gamma : float;   (* permanent impact coefficient *)
    eta   : float;   (* temporary impact coefficient *)
    sigma : float;   (* asset volatility *)
    adv   : float;   (* average daily volume *)
  }

  let temporary_impact p rate =
    p.eta *. p.sigma *. (rate /. p.adv) ** 0.6   (* empirical power *)

  let permanent_impact p rate =
    p.gamma *. p.sigma *. (rate /. p.adv) ** 0.5

  (** Implementation shortfall cost for an execution trajectory *)
  let implementation_shortfall ~params ~trajectory ~dt =
    let n = Array.length trajectory in
    let total_cost = ref 0.0 in
    for i = 0 to n - 1 do
      let qty   = trajectory.(i) in
      let rate  = qty /. dt in
      let temp  = temporary_impact params rate in
      let perm  = permanent_impact  params rate in
      total_cost := !total_cost +. qty *. (temp +. 0.5 *. perm)
    done;
    !total_cost

end

22.3 Bid-Ask Spread Components

The spread compensates the market maker for:

  1. Inventory risk: adverse price moves while holding position
  2. Adverse selection: informed traders know more than the market maker
  3. Order processing costs: operational costs

Glosten-Milgrom model: the spread is:

$$\text{Spread} = 2\alpha \cdot |V - p|$$

where $\alpha$ is the fraction of informed traders and $V$ is the true value.


22.4 VWAP and TWAP

module Benchmarks = struct

  (** Volume-Weighted Average Price *)
  let vwap ~prices ~volumes =
    let pv = Array.fold_left2 (fun a p v -> a +. p *. v) 0.0 prices volumes in
    let v  = Array.fold_left (+.) 0.0 volumes in
    pv /. v

  (** Time-Weighted Average Price *)
  let twap ~prices ~times =
    let n = Array.length prices in
    let total_time = times.(n - 1) -. times.(0) in
    let sum = ref 0.0 in
    for i = 0 to n - 2 do
      sum := !sum +. prices.(i) *. (times.(i + 1) -. times.(i))
    done;
    !sum /. total_time

  (** Arrival price: mid at time of order submission *)
  let arrival_price ~book = Order_book.mid_price book

  (** Implementation shortfall between arrival and executed VWAP *)
  let impl_shortfall ~side ~arrival ~executed_vwap ~shares =
    let slippage = match side with
      | `Buy  -> executed_vwap -. arrival   (* we pay more *)
      | `Sell -> arrival -. executed_vwap   (* we receive less *)
    in
    slippage *. shares

end

22.5 Chapter Summary

Market microstructure is the physics of financial markets: the study of how prices are formed, how orders are matched, and what determines the cost of trading. This chapter provides the conceptual and computational foundation for the execution algorithms in Chapter 23 and the trading strategies in Chapter 24.

The order book is a priority queue of resting limit orders, sorted by price (best first) and then by time (first-in, first-out within a price level). The bid-ask spread at any moment reflects the cost of immediacy — the premium a market taker pays for the certainty of immediate execution. Market makers stand on both sides of the spread, profiting from the difference but exposed to two risks: inventory risk (the position accumulated from imbalanced order flow may move adversely) and adverse selection risk (informed traders tend to trade when prices are about to move against the market maker).

Market impact is the most practically important concept in microstructure. Kyle's 1985 model derives that price impact is linear in order size, with the Kyle lambda measuring the price change per unit of order flow. The empirical square-root law $\Delta p \approx \sigma \sqrt{Q/V}$ (where $Q$ is the trade size and $V$ is the daily volume) is one of the most robust empirical regularities in finance, holding across asset classes and time periods. Large orders cost more than linear in their size because they reveal information about the trader's intent and consume progressively deeper (worse) levels of the book.

The implementation shortfall framework by Perold (1988) provides the correct accounting of execution cost: the difference between the paper portfolio value (valued at the arrival mid-price) and the actual portfolio value (valued at the execution prices). This decomposes into spread cost, market impact, timing risk, and fees.


Exercises

22.1 Build an in-memory limit order book with add/cancel/match operations. Process 1000 random orders and measure the evolution of the spread.

22.2 Generate an order flow simulation (Poisson arrivals, random bid/ask quantities) and measure realized VWAP vs mid-price. Study how spread varies with volume.

22.3 Implement the Kyle lambda estimation from a time series of trade signs and price changes using OLS. Compare to the theoretical formula.

22.4 Simulate implementation shortfall for a large sell order using the square-root impact model with uniform vs VWAP-schedule execution.


Next: Chapter 23 — Execution Algorithms