Everything in this course meets in one place: high-frequency trading. A modern market-making firm runs Bayes updates on every fill, prices with expected values, sizes with variance, trusts the law of large numbers to turn tiny edges into steady profits, and does all of it in microseconds.
What high-frequency trading is
High-frequency trading (HFT) means automated strategies that make decisions and send orders in microseconds, hold positions for seconds or less, and trade enormous numbers of times a day. Most of it falls into three families:
- Market making: continuously quoting bids and asks and earning the spread (lessons 17–19, at machine speed).
- Arbitrage: keeping related prices in line: the same stock on different exchanges, an ETF against its basket, a future against the underlying.
- Short-term signals: predicting the next few ticks from the order book itself.
The limit order book
Every exchange keeps a limit order book: all resting buy orders (bids) and sell orders (asks), sorted by price. The highest bid and lowest ask are the best bid and offer; the gap between them is the spread; the quantity at each price is the depth.
- A limit order that doesn’t cross the spread rests in the book and adds liquidity (a maker).
- A market order (or a crossing limit) removes liquidity (a taker): it fills against the best level, and if that runs out, the next one. That is called walking the book.
- Most exchanges use price–time priority: at the same price, the order that arrived first fills first. Your queue position is worth money, and being fast is how you get a good one.
Reading the book: imbalance and the microprice
The plain mid is . But if 900 lots are bid and only 100 offered, the next trade is more likely to lift the ask. The microprice weights each side by the size on the other side:
With , , and , the microprice is : very close to the ask. Order-book imbalance is one of the best-known short-horizon signals in HFT research.
The economics of a market maker
Each time a market maker buys at the bid and later sells at the ask, it earns the spread. Per fill, the expected profit is roughly
The adverse-selection term is Bayes’ theorem from lesson 1: being filled is evidence that the trader on the other side knew something. Edges are tiny, often a fraction of a cent per share, and noise per trade is large. They become a business only because of the law of large numbers (lesson 6): with millions of fills, total PnL’s mean grows like while its noise grows like .
Why speed matters
Speed isn’t about trading more often for its own sake. It buys three things:
- Queue position. At a given price the first order in line gets filled first, and fills at the front of the queue carry less adverse selection.
- Not getting picked off. When the market moves, a quote that is now stale is free money for whoever hits it first. A market maker must cancel faster than others can trade against it.
- Arbitrage. When prices diverge across venues, only the first trader to see both and act captures the difference.
The path from market data arriving to an order leaving is called tick-to-trade: receive the packet, decode it, update the book, decide, run risk checks, and send. Firms shrink it with colocation (servers in the exchange’s data centre), kernel-bypass networking, carefully written C++, and FPGAs that do the whole loop in hardware.
The physics limit
Nothing is faster than light. In glass fibre light slows to about , roughly km/s, so every kilometre of fibre costs about :
Air has , which is why firms built chains of microwave towers between Chicago (futures) and the New Jersey data centres (stocks): a straighter path through air shaves milliseconds off fibre, and milliseconds are thousands of FPGA decisions.
In code
import numpy as np
def microprice(bid, ask, bid_size, ask_size):
return (bid * ask_size + ask * bid_size) / (bid_size + ask_size)
print(microprice(99.99, 100.01, 900, 100)) # 100.008: leans towards the ask
# Light in fibre and in air between Chicago and New Jersey (about 1,150 km straight line)
c = 299_792.458 # km/s
d = 1_150
print(f"air: {d / c * 1e3:.2f} ms") # ≈ 3.84 ms
print(f"fibre: {d * 1.47 / c * 1e3:.2f} ms") # ≈ 5.64 ms on a straight line; real routes are longer
# Tiny edge, many trades: the law of large numbers at work
rng = np.random.default_rng(21)
edge, noise = 0.0005, 0.05 # dollars per share per fill
for n in (1_000, 10_000, 100_000): # fills per day
daily = rng.normal(n * edge, np.sqrt(n) * noise, size=100_000)
print(n, f"share of losing days: {np.mean(daily < 0):.3f}") # ≈ 0.38, 0.16, 0.001
Check yourself
A market maker quotes 99.99 @ 100.01 and earns no rebates or fees. On average the price moves 0.6 cents against it after each fill. What is its expected profit per fill?