Market Microstructure: Order Books & Execution Mechanics › The Order Book

Michael BrenndoerferJanuary 9, 202610 min read
Quantitative FinanceAll chapters
Part 12 of 15Market Making and High-Frequency Trading
Chapter 67Market Microstructure: Order Books & Execution Mechanics › The Order Book
Reading section 2 of 13 · The Order Book · 10 minSection 2 of 13 · 10 min

Book contents

Section 2 of 13 · 10 min read

Market Microstructure: Order Books & Execution Mechanics › The Order BookOne section · Sections in this chapter2 / 13 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

The order book is the central mechanism through which modern electronic markets operate. It's a real-time record of all outstanding buy and sell orders for a security, organized by price level and arrival time.

Structure of the Order Book

Before diving into the technical definition, it helps to understand what problem the order book solves. In any market, buyers and sellers rarely arrive at exactly the same moment with perfectly matching quantities and prices. Someone who wants to sell 500 shares right now may not find a buyer willing to take exactly 500 shares at that exact instant. The order book solves this coordination problem by serving as a persistent record of trading interest, allowing buyers and sellers to express their willingness to trade at specific prices and wait for counterparties to arrive.

Order Book

An order book is a list of all outstanding limit orders to buy (bids) and sell (asks/offers) a security organized by price level. It represents the current supply and demand for immediate execution at each price point.

The order book has two sides: the bid side contains all buy orders, and the ask side (or offer side) contains all sell orders. Orders on each side are sorted by price, with the most aggressive prices at the top. The highest bid is called the best bid, and the lowest ask is called the best ask (or best offer). The difference between these two prices is the bid-ask spread.

To quantify the key features of the order book, we define two fundamental measures that traders constantly monitor. The spread captures the cost of trading immediately, while the midprice provides a reference point for the security's theoretical fair value. These quantities are defined mathematically as follows:

S=Pa−PbM=Pa+Pb2\begin{aligned} S &= P_a - P_b \\ M &= \frac{P_a + P_b}{2} \end{aligned}

Let us examine each component of these formulas to understand their economic meaning:

  • PaP_a: best ask price (lowest price to buy). This represents the minimum price at which someone in the market is currently willing to sell. If you want to buy immediately, this is the price you will pay.
  • PbP_b: best bid price (highest price to sell). This represents the maximum price at which someone is currently willing to buy. If you want to sell immediately, this is the price you will receive.
  • SS: bid-ask spread, representing the cost of immediacy. The spread is always non-negative in a properly functioning market, since the best ask must be at least as high as the best bid (otherwise orders would immediately cross and execute). A narrow spread indicates a liquid market where trading is cheap, while a wide spread suggests illiquidity or uncertainty.
  • MM: midprice, representing the theoretical fair value. The midprice sits exactly halfway between the best bid and ask, and we often use it as a reference point for the "true" price of the security. However, the midprice is not an executable price; it is a convenient benchmark.
In[2]:
Code
from dataclasses import dataclass
from enum import Enum


# Define order side
class Side(Enum):
    BID = "bid"
    ASK = "ask"


@dataclass
class Order:
    """Represents a single order in the order book."""

    order_id: int
    side: Side
    price: float
    quantity: int
    timestamp: float  # seconds since epoch

    def __repr__(self):
        return f"Order({self.order_id}, {self.side.value}, ${self.price:.2f}, {self.quantity} shares)"

Let's create a simple order book class that captures the essential mechanics:

In[3]:
Code
from collections import defaultdict
from dataclasses import dataclass
from enum import Enum
from typing import List, Optional, Tuple


# Re-import/define Side and Order for this cell
class Side(Enum):
    BID = "bid"
    ASK = "ask"


@dataclass
class Order:
    """Represents a single order in the order book."""

    order_id: int
    side: Side
    price: float
    quantity: int
    timestamp: float

    def __repr__(self):
        return f"Order({self.order_id}, {self.side.value}, ${self.price:.2f}, {self.quantity} shares)"


class OrderBook:
    """A simple limit order book implementation."""

    def __init__(self, ticker: str):
        self.ticker = ticker
        self.bids = defaultdict(list)  # price -> list of orders
        self.asks = defaultdict(list)  # price -> list of orders
        self.order_id_counter = 0
        self.current_time = 0.0

    def add_limit_order(self, side: Side, price: float, quantity: int) -> Order:
        """Add a limit order to the book."""
        self.order_id_counter += 1
        order = Order(
            order_id=self.order_id_counter,
            side=side,
            price=price,
            quantity=quantity,
            timestamp=self.current_time,
        )

        if side == Side.BID:
            self.bids[price].append(order)
        else:
            self.asks[price].append(order)

        self.current_time += 0.001  # increment time
        return order

    def get_best_bid(self) -> Optional[float]:
        """Return the highest bid price."""
        if not self.bids:
            return None
        return max(self.bids.keys())

    def get_best_ask(self) -> Optional[float]:
        """Return the lowest ask price."""
        if not self.asks:
            return None
        return min(self.asks.keys())

    def get_spread(self) -> Optional[float]:
        """Return the bid-ask spread."""
        best_bid = self.get_best_bid()
        best_ask = self.get_best_ask()
        if best_bid is None or best_ask is None:
            return None
        return best_ask - best_bid

    def get_midprice(self) -> Optional[float]:
        """Return the midpoint between best bid and ask."""
        best_bid = self.get_best_bid()
        best_ask = self.get_best_ask()
        if best_bid is None or best_ask is None:
            return None
        return (best_bid + best_ask) / 2

    def get_depth_at_price(self, side: Side, price: float) -> int:
        """Return total quantity at a given price level."""
        orders = self.bids[price] if side == Side.BID else self.asks[price]
        return sum(o.quantity for o in orders)

    def get_book_snapshot(self, levels: int = 5) -> Tuple[List, List]:
        """Return top N levels of bids and asks."""
        bid_prices = sorted(self.bids.keys(), reverse=True)[:levels]
        ask_prices = sorted(self.asks.keys())[:levels]

        bid_levels = [
            (p, self.get_depth_at_price(Side.BID, p)) for p in bid_prices
        ]
        ask_levels = [
            (p, self.get_depth_at_price(Side.ASK, p)) for p in ask_prices
        ]

        return bid_levels, ask_levels

Now let's populate an order book with some sample orders and visualize it:

In[4]:
Code
import numpy as np

# Create an order book for a hypothetical stock
book = OrderBook("XYZ")

# Add bid orders (buyers)
np.random.seed(42)
for price in [99.90, 99.85, 99.80, 99.75, 99.70]:
    for _ in range(np.random.randint(2, 6)):
        qty = np.random.randint(100, 1000)
        book.add_limit_order(Side.BID, price, qty)

# Add ask orders (sellers)
for price in [100.00, 100.05, 100.10, 100.15, 100.20]:
    for _ in range(np.random.randint(2, 6)):
        qty = np.random.randint(100, 1000)
        book.add_limit_order(Side.ASK, price, qty)

# Get the snapshot
bid_levels, ask_levels = book.get_book_snapshot(levels=5)
Out[5]:
Console
Order Book for XYZ
==================================================
Best Bid: $99.90
Best Ask: $100.00
Spread: $0.10
Midprice: $99.95

Top 5 Bid Levels:
  $99.90: 2,071 shares
  $99.85: 2,421 shares
  $99.80: 1,647 shares
  $99.75: 3,133 shares
  $99.70: 1,547 shares

Top 5 Ask Levels:
  $100.00: 1,152 shares
  $100.05: 972 shares
  $100.10: 2,155 shares
  $100.15: 732 shares
  $100.20: 3,037 shares

The order book reveals several key pieces of information. The spread of $0.10 represents the cost of immediacy: if you want to buy immediately, you pay the ask ($100.00), but if you're willing to wait, you could place a bid at $99.90. The depth at each level shows how much liquidity is available before the price moves to the next level.

Visualizing Order Book Depth

A depth chart provides an intuitive visualization of the order book, showing cumulative volume at each price level:

Out[7]:
Visualization
Step chart with bid depth on the left and ask depth on the right, separated by a shaded bid-ask spread.
Cumulative depth of the simulated limit order book. Bid-side and ask-side step curves show available volume at each price level, while the shaded gap marks the bid-ask spread.

The depth chart shows how much buying power exists at each price level below the current price (bids) and how much selling pressure exists above (asks). The steeper the curve, the more liquidity is concentrated near the best prices. Shallow curves indicate thin markets where even modest order sizes can move prices significantly.