Branch: Quant Developer (Quant & Code region, Finance galaxy) · Node QD2.01 · ~18 focused hours · Standard gate ≥ 85% (quiz + code-pack)
Every module before this one in the Quant Developer branch has quietly assumed away a whole layer of reality: QD1.02 builds a signal, QD1.03 backtests it, QD1.04 sizes it into a portfolio, and at every step, the implicit assumption is that when the model says "buy 40,000 shares," 40,000 shares simply appear in the portfolio at the price the model was looking at. They do not. Between "the model decided" and "the position exists" sits an entire discipline most quant curricula skip past in a single paragraph, and skipping it is expensive: a genuinely good signal, sized by a genuinely sound optimizer, can still lose money for a fund whose execution is careless, because every share you trade moves the price against you a little, every basis point of avoidable slippage is edge you generated somewhere else and then handed back, and a backtest that assumes you always transact at the closing print is not testing your strategy, it is testing a strategy that does not exist. This module is the missing layer: the mechanics of the market you actually trade in (the order book, and the menu of order types that interact with it), and the algorithms and mathematics a real desk uses to buy or sell a large position without needlessly paying for the privilege.
Advertisement
Here is the whole module compressed into one sentence you will spend eighteen hours earning the right to believe: the price you saw when you decided to trade is not the price you will get, the gap between them is measurable, decomposable, and partially controllable, and an execution algorithm's entire job is to control what can be controlled and honestly report what cannot. You will learn to read a real limit order book snapshot and know, before you send a single share, roughly what a market order would cost you (walk_the_book, this module's Exercise 2); you will implement the two workhorse scheduling algorithms every trading desk runs thousands of times a day (TWAP and VWAP) and grade each one honestly against its own benchmark; you will learn Andre Perold's Implementation Shortfall framework, which is the single most important idea in this module, because it is the only accounting system that cannot be gamed by simply choosing a flattering benchmark after the fact; you will build a market-impact model from the same square-root law real trading desks calibrate against their own fill history, and use it to answer the very practical question "how big a position can I trade before my own footprint costs more than the trade is worth"; and you will learn to grade any execution (yours or someone else's) the way a real transaction-cost-analysis (TCA) report does. Every exercise in this module runs against LOB-shaped data built from the same schema and the same generative process as this program's own bundled synthetic-lob dataset (app/public/datasets/synthetic-lob.csv), you will meet its real rows directly in Worked Example 1.
One framing to carry through the whole module, because it resolves what would otherwise look like a contradiction: this module does not re-teach the transaction-cost modeling inside a backtesting engine (QD1.03 owns that harness ("defeat unrealistic fills") and will reference this module for the actual cost/impact math rather than re-deriving it), and it does not re-derive the statistics of a random walk or a regression (QM1.01/QM1.03 own that theory; this module uses a random-walk mid-price and a square-root functional form as tools, not as objects of study). What this module owns, and owns completely, is the thing in between: the mechanics of the order book itself, and the algorithms that decide how to turn a portfolio decision into filled shares as cheaply as the market will allow.
Learning objectives
By the end you can:
- Name and distinguish the core order types a trading venue offers (market, limit, marketable-limit, stop, stop-limit, IOC, FOK, GTC/day, iceberg (hidden/reserve), and pegged) and state, for each, what it buys you and what it costs you (certainty of execution vs. certainty of price, and how much of your intent it reveals to the rest of the market).
- Explain price-time priority (FIFO) as the rule that governs a limit order book, and, given a raw snapshot of price/size levels on both sides, compute the best bid, best ask, mid, spread (in price and in basis points), the size-weighted microprice, and the top-of-book order-flow imbalance, using the
synthetic-lobdataset's own schema. - Simulate walking the book: given a resting book and a marketable order, compute the size-weighted average fill price, the number of price levels touched, and the resulting slippage versus the best quoted price, including the case where the order is larger than the book's displayed depth and only partially fills.
- Implement a TWAP (time-weighted average price) scheduler (slicing an order evenly across time buckets with an exact, auditable remainder rule) and benchmark its realized execution against the unweighted TWAP price of the market's own tape.
- Implement a VWAP (volume-weighted average price) scheduler (sizing each time bucket's slice proportionally to a volume profile via the largest-remainder apportionment method) and benchmark its realized execution against the true volume-weighted VWAP price.
- Decompose Implementation Shortfall (Perold, 1988) into its four components (delay cost, execution cost, opportunity cost on any unfilled residual, and explicit fees) and compute the total shortfall in both currency and basis points.
- Model market impact with the practitioner's square-root law, split a modeled impact into its temporary (reverting) and permanent (information-driven) components, and invert the law to answer a capacity question: the maximum participation rate a fixed cost budget can afford.
- Measure execution quality honestly (arrival-price slippage, VWAP slippage, fill rate) and state, for a given trading objective (urgency vs. patience), which benchmark is the fair one and which can be gamed.
- (Copilot Discipline, R10.) Use a coding assistant to accelerate the boilerplate of an execution-algorithm function you have already designed and can compute by hand (never to originate the fill logic or the cost math) and review every generated line for a hallucinated broker/exchange API or a silently wrong sign convention before trusting it.
Prerequisites & connections
Builds on. CS1.01/CS1.02 (Python fundamentals, functions, and clean data structures) are assumed completely, every exercise here is ordinary functions over lists, tuples, and dicts. CS1.05 (Data Structures & Algorithms) is worth having fresh: a real production limit order book is implemented as a price-ordered structure, typically a pair of heaps or balanced trees, one per side, each level itself a FIFO queue of resting orders, and while this module's exercises work with an already-aggregated snapshot (a plain list of (price, size) levels, exactly what you get once you've grouped the synthetic-lob dataset's rows), the "why a heap and not a list" reasoning is a direct application of CS1.05's own material, not a new idea. Nothing from DA1.01–DA2.03 is a hard prerequisite (every graded solution in this module's code pack uses plain Python (math, arithmetic, sorting) precisely so a real desk's execution engine reads no differently whether it's a research notebook or a low-latency production path), though a production implementation of everything you build here would typically vectorize with NumPy/pandas once the by-hand version is understood, exactly this program's working agreement of by-hand before tool.
Feeds forward. QD1.03 (Building a Backtesting Engine) names "unrealistic fills" as one of its four classic pitfalls and requires realistic transaction costs and slippage to defeat it, this module is that cost/impact model; QD1.03 calls forward to it rather than re-deriving the square-root law or Implementation Shortfall itself. QD2.02 (Risk Systems) and QD2.03 (Performance & Attribution) both eventually report a strategy's net-of-cost returns, the "cost" side of that ledger is exactly this module's Implementation Shortfall and market-impact output. QD2.05 (the capstone) will ask you to cost and execute a strategy's trades honestly as one stage of the full pipeline, drawing on every exercise in this module directly. QM1.01 (probability, distributions) and QM1.03 (time-series, Monte Carlo) own the theory of a random walk and of volatility estimation, this module borrows a random-walk mid-price and a volatility number as inputs, never re-deriving why a random walk behaves the way it does; no theory is duplicated in either direction (C-3). Note also what this module is not: the Finance-Plus MS branch (Money & Monetary Systems) covers payment rails, central-bank operations, and monetary plumbing, a different meaning of "market structure" entirely, with zero overlap here.
Your code pack. This module's graded exercises live in QD2.01.json (app/public/code-packs/QD2.01.json, referenced in-app by module id QD2.01), eight Python exercises running live in Pyodide, each with a structured (fill-in-the-blank or choose-the-correct-implementation) offline fallback, so the module is 100% completable with zero runtime if your browser can't load the WASM engine. Exercises 1 and 2 are built directly against the synthetic-lob dataset's schema and generative process; every hidden test that touches a price level carries both an India-flavored (₹) and a US-flavored ($) seeded scenario (the spirit of R6, even where the dataset itself is currency-neutral).
Core teaching content
Why execution is its own discipline: the last-mile problem
A portfolio manager's decision to buy 40,000 shares of a name is, at the instant it is made, a number on a screen, it has no cost yet. The moment that decision starts turning into filled shares, cost begins accruing, in at least three distinct and separable ways. First, the market may simply move between the decision and your first trade, for reasons that have nothing to do with you (news, other flow, the ordinary drift of prices): call this delay cost. Second, your own trading pushes the price against you: a large buy order consumes the cheapest available sellers first and then reaches for progressively more expensive ones, and even a series of smaller orders leaks information that other participants can and do trade on, call this market impact, and it is the one component of cost that is partly yours to manage, because how fast and how visibly you trade changes how much of it you pay. Third, if you don't finish the order, whatever you failed to buy is not free, if the price has moved further away by the time you give up, that unfilled portion has an opportunity cost, exactly as real as a cost you actually paid in cash. An execution algorithm is nothing more than a disciplined answer to "how do I turn this decision into filled shares while controlling the piece of this cost I can control, and reporting the rest honestly." Every remaining section of this module is one piece of that answer, in order: the terrain you're trading on (order types and the book), the tools for measuring your footprint on that terrain (walking the book, impact modeling), the two classic scheduling algorithms (TWAP, VWAP), and the accounting system that ties every piece of cost back to the original decision (Implementation Shortfall) and grades the whole effort afterward (execution-quality measurement).
Order types in the stock market
An order type is the instruction that tells a trading venue how to handle your buy or sell. Most of them trade one certainty against another: how sure you are of the price you get, and how sure you are of being filled at all. A market order secures the fill and gives up the price, and a limit order does the reverse. An analyst needs the vocabulary because execution algorithms such as TWAP and VWAP are schedulers that send a sequence of smaller orders of these types.
5 min read, on its own page
The limit order book: structure, and the synthetic-lob dataset
A limit order book (LOB) is simply every currently resting limit order for one instrument, organized into two sorted ladders, bids (buy limits, sorted best-to-worst as highest price first) and asks (sell limits, sorted best-to-worst as lowest price first), with every order at the same price aggregated into one level. The best bid and best ask together are called the touch; everything behind them is the depth. This program ships a purpose-built synthetic construct for practicing on exactly this structure: synthetic-lob (app/public/datasets/synthetic-lob.csv, referenced by every code-pack exercise in this module that needs LOB-shaped data). Its schema is six columns (snapshot_id, timestamp, side (bid/ask), level (1 through 10, level 1 always best), price, size) covering 300 one-minute snapshots (09:00 through 13:59 on a single synthetic trading day) times 10 levels times 2 sides, 6,000 data rows in total. Per its own manifest entry, it is purely synthetic ("no real-market counterpart possible") built from a seeded geometric random walk for the mid-price (so it is reproducible, not a claim about any real instrument) with a tick size fixed at roughly 5 basis points of the current mid, and level sizes drawn from a wide random range that tends, noisily, to thin out at deeper levels, exactly the lumpy, imperfectly-monotonic depth pattern a real book actually shows, not an idealized smooth one. You will read its real rows directly in Worked Example 1, and every hidden test in this module's code pack that touches LOB-shaped data is built from the identical generative recipe (seeded, so fully reproducible, never read from the file itself: determinism the anti-hardcoding way).
From a snapshot's touch alone, five numbers matter enormously and are cheap to compute (code-pack Exercise 1, lob_touch_stats):
- Mid =
(best_bid + best_ask) / 2, the textbook "fair value," and the number every retail quote display shows you. - Spread =
best_ask − best_bid, and spread in basis points =spread / mid * 10000, the cost of round-tripping a single share right now, and the single most-watched proxy for how liquid and how nervous a market currently is. - Microprice =
(bid_size * best_ask + ask_size * best_bid) / (bid_size + ask_size), a size-weighted mid that leans toward whichever side is currently lighter. The intuition is worth internalizing precisely, because it is easy to get backwards: a heavy resting bid queue relative to the ask signals more buying interest waiting than selling interest, which means the ask side is more likely to be the one consumed next, so the microprice tilts toward the ask price. Symmetrically, a heavy ask queue tilts the microprice toward the bid. When Exercise 1 asks you to compute this on the realsynthetic-lobsnapshot 0 row (bid size 1,272 vs. ask size 4,983 (the ask side much heavier), the microprice lands below the mid, closer to the bid) exactly the signal that the touch is more likely to trade down than up from here. - Order-flow imbalance =
(bid_size − ask_size) / (bid_size + ask_size), bounded in[-1, 1], the same size comparison, expressed as a single signed number rather than folded into a price. Positive means bid-heavy (upward pressure); negative means ask-heavy (downward pressure); the snapshot-0 example above has an imbalance around −0.59.
{
"skill": "Scaffolding a small order-book statistics function you have already designed by hand",
"use": "Once you have worked the mid/spread/microprice/imbalance formulas by hand on paper (Worked Example 1) and know exactly what lob_touch_stats must return, use a coding assistant to draft the first version of the function fast — this is pure, low-judgment boilerplate once the formulas are fixed.",
"tools": ["A coding-focused chat assistant or IDE copilot (Claude, GitHub Copilot, Cursor)", "This module's own hidden-test harness, run locally, as the ground truth for whether the draft is actually correct"],
"prompt": "Write a Python function lob_touch_stats(bids, asks) where bids/asks are lists of (price, size) tuples, best level first. Return a dict with best_bid, best_ask, mid, spread, spread_bps, microprice, and imbalance, using exactly these formulas: <paste the five formulas from the Core section above>. Do not import anything beyond what's needed for basic arithmetic.",
"verify": "Recompute the snapshot-0 numbers from Worked Example 1 BY HAND first (mid ~99.6253, microprice ~99.5958), then run the generated function against those exact inputs and confirm it matches to several decimal places before trusting it on anything else. A subtly wrong microprice — e.g. one that swaps which size weights which price, silently reversing the imbalance's direction — will still return a plausible-looking number in roughly the right range, which is exactly why 'it ran without an error' is not verification.",
"diy": "You must be able to compute mid, spread, microprice, and imbalance by hand on a small example, and correctly reason about WHICH way the microprice leans, before this callout is relevant — Worked Example 1 and code-pack Exercise 1 are exactly that gate.",
"market": "US"
}
Walking the book: costing a marketable order before you send it
The touch price is a real, tradeable price for exactly one thing: a size no larger than what's resting at the best level. Anything larger has to walk the book, consume all of level 1, then all of level 2, and so on, until the order is filled or the book runs out of depth (code-pack Exercise 2, walk_the_book). The size-weighted average price of that walk is always at least as bad as the touch (for a buy, at or above the best ask; for a sell, at or below the best bid), and the gap between the average price and the touch price, the slippage, expressed in basis points, grows with order size relative to depth, and grows faster than linearly once you're deep enough into the book that you're consuming thin, disorganized levels. This is the single most concrete rebuttal to the intuitive but wrong idea that "the quoted price is the price I'll get for any size": the quote is a promise about the best available unit, not a guarantee about your whole order. Worked Example 2 walks a small three-level book by hand; code-pack Exercise 2's hidden tests deliberately include the case where the order size exceeds total displayed depth, which must resolve to a clean partial fill (filled_qty less than the requested size) rather than an error, real markets do not manufacture liquidity that isn't there, and neither should your code pretend they do.
TWAP vs VWAP
TWAP and VWAP are two ways to slice a large order into smaller ones. TWAP (time-weighted average price) sends equal slices in equal time buckets and is graded against the plain average of the market's price. VWAP (volume-weighted average price) sizes each slice to its bucket's share of a volume profile, since trading is heaviest at the open and close, and is graded against the volume-weighted average. A VWAP schedule mirrors the volume that defines its benchmark, so it lands very close to it.
3 min read, on its own page
Implementation shortfall
Implementation shortfall is the total cost of carrying out a trade, measured against the decision price: the price at the moment you decided to trade. Every cost is a deviation from that one fixed anchor, split into delay cost, execution cost, opportunity cost and fees. Analysts use it because TWAP and VWAP benchmarks are computed after the fact, so market moves can flatter or punish the trader, while the decision price can't be moved once the trade is done.
5 min read, on its own page
Square-root law of market impact
The square-root law is the practitioner's rule for the price impact of a large order. Impact in basis points equals k × σ × sqrt(Q / ADV), where σ is daily volatility, Q / ADV is the order's size as a share of average daily volume, and k is a constant a desk fits from its own fills. Because it is a square root, quadrupling the size only doubles the cost, so splitting an order over time is cheaper than trading it all at once.
5 min read, on its own page
Execution quality measurement: grading an algorithm honestly
Putting it together, a real desk's post-trade report (code-pack Exercise 8, execution_quality_report) is a small bundle of numbers, each answering a distinct question, and the discipline is refusing to let any one of them stand in for the whole picture: arrival slippage ((exec_avg_price − arrival_price) / arrival_price × 10000) answers "compared to the price when I actually started trading, did I do well", the Implementation-Shortfall-flavored, hardest-to-game number. VWAP slippage (the identical shape, against the VWAP benchmark instead) answers "did I trade in line with the market's own volume rhythm", useful, but gameable by patient, low-urgency trading exactly as discussed above. Fill rate (exec_qty / total_qty) answers a question neither slippage number can: did the order actually get done, because a beautifully-priced 40% fill of an order you needed complete is not obviously a success. Comparing two different execution algorithms honestly means holding the benchmark and the time period fixed across both, a VWAP algorithm will structurally look better on a VWAP-slippage scorecard and a TWAP algorithm will not be disadvantaged by an arrival-price scorecard just because it's a different algorithm; the fair comparison is always "same order, same market conditions, same benchmark," never "whichever algorithm happens to flatter whichever benchmark you picked."
Fragmentation: one instrument, many books, and what that does to a benchmark
Everything above has assumed one order book. For most liquid instruments that assumption is false. The same US-listed share trades on a dozen or more registered exchanges plus a larger number of alternative venues and internalising broker desks; an Indian share trades on two national exchanges with a shared clearing arrangement. Liquidity for one instrument therefore sits in several books at once, and no single book shows you all of it.
Three things break, and each one breaks a benchmark you have already learned to compute. The touch is no longer a single number: the best bid on one venue and the best offer on another can cross, and the consolidated best quote across venues is a constructed object rather than an observed one, arriving with a latency of its own. Displayed depth understates available size, because a meaningful share of volume never appears on any public book at all, so a book-walk cost estimate computed from one venue's depth is systematically pessimistic about size and optimistic about price. And VWAP becomes ambiguous: a volume-weighted average price computed from one venue's prints is a different number from one computed from the consolidated tape, so an algorithm can beat the first while losing to the second.
The practical rules are short. Say which tape your benchmark came from, in writing, before the trade rather than after. Prefer a benchmark anchored to a decision you made, which is why implementation shortfall survives fragmentation and VWAP comparisons across brokers frequently do not. And when a broker's report shows an unusually good VWAP number, ask which venues went into the denominator before you ask anything else.
High-frequency trading, and latency arbitrage in particular
High-frequency trading is not a strategy. It is a set of strategies that share one property: their profit per unit of risk depends on being faster than someone else, so the capital goes into the path rather than the forecast. Co-located servers, direct exchange feeds rather than the consolidated tape, kernel-bypass networking and field-programmable gate arrays are all purchases of microseconds.
The three families worth distinguishing behave very differently towards your order. Electronic market making posts two-sided quotes and earns the spread, managing inventory continuously; on balance it narrows spreads and it is the reason your small marketable order fills instantly. Statistical arbitrage at short horizons trades relationships between correlated instruments and mostly does not interact with your order at all. Latency arbitrage is the one that does. It works like this: an index future moves on one venue, the constituent shares on another venue have not yet reprinted, and a participant who sees the first move before the second venue's quotes update can trade against a stale quote. The profit comes from a price that was correct a few hundred microseconds ago and is not correct now, and the counterparty is whoever was still resting at that stale price, which on a slow day is a market maker and on a busy one is your algorithm's passive order.
What follows for an execution desk is unglamorous and specific. A passive limit order resting at a stale price is the thing being arbitraged, so during fast moves, cancel rather than hope. Randomise slice timing, because a perfectly even TWAP schedule is a pattern and patterns are detectable. Measure your own adverse selection: mark every passive fill against the mid-price a fixed interval later, and if your passive fills are systematically followed by the price moving against you, you are supplying the other side of exactly this trade. And note the design responses that exist because this is real: speed bumps, frequent batch auctions and randomised matching delays are all deliberate attempts to make the last microsecond stop paying.
Types of market manipulation
Market manipulation covers trading and order behaviour that almost every regulated market prohibits, including front running, spoofing, layering, wash trading and quote stuffing. Each has a tell that shows up in a message log, such as a large order cancelled without filling, or a matched pair with the same owner on both sides. An execution engineer needs to recognise them to avoid building one by accident and to notice when the book is being worked against them.
3 min read, on its own page
Common mistakes & how experts think differently
- "A market order is free, there's no explicit commission." The ticket may be free; the order is not. A market order for any real size pays the spread plus whatever market impact its own size causes as it walks the book, an implicit cost that never appears on a commission statement but is every bit as real, and usually far larger. The expert prices this before sending the order (Exercise 2), never discovers it only in the fill report.
- "VWAP is always the right benchmark, beating VWAP means you traded well." VWAP rewards trading in proportion to the market's own volume rhythm, full stop, it says nothing about whether the underlying decision to trade was urgent or right. A trader with genuinely time-sensitive, information-driven flow who trades patiently to "beat VWAP" may be handing back far more in adverse price movement than they gained in slippage-vs-VWAP; for urgent flow, arrival-price/Implementation-Shortfall is the honest benchmark, and the expert chooses the benchmark based on the nature of the flow, not out of habit.
- "Slicing evenly across time (TWAP) is the safe, neutral default." Evenly-sliced orders are also predictably sliced, a fixed schedule any sufficiently attentive counterparty can detect and trade ahead of, and TWAP additionally ignores the market's real volume rhythm entirely, meaning it often trades disproportionately hard exactly when liquidity is thinnest (the mid-session lull). It is a reasonable default, never an unconditionally safe one.
- "The best bid/ask I see is the price I'll get, for any size." The touch price is a valid, tradeable price for exactly the size resting at that level: nothing more. Any larger order must walk the book, and the average price only gets worse the deeper it has to reach; conflating the quoted price with the achievable price for your actual size is one of the most common and most expensive errors a new trader makes.
- "More visible levels of depth means more liquidity is really there." Displayed size is not a promise, hidden/iceberg orders show only a fraction of their true size, resting orders get cancelled the instant conditions change, and a level that looked deep a second ago can evaporate before your order arrives (a phenomenon sometimes called "fleeting liquidity"). Depth shown on a snapshot is evidence, not a guarantee.
- "Impact cost is one number, and it's permanent." Impact splits cleanly into a temporary piece (pure pressure from consuming the book, which reverts once you stop trading) and a permanent piece (genuine information reaching the price, which does not). Treating all impact as permanent overstates a strategy's true cost of exit; treating all of it as temporary understates how much of your own trading is informative to everyone watching.
- "Faster execution is always better, get it done and reduce risk." Trading faster reduces the timing risk of prices drifting away from you while you wait, but it increases impact cost, because the square-root law penalizes participation rate, the exact trade-off Almgren-Chriss formalizes. There is no universally "safer" speed; the right pace depends on the position's urgency, the instrument's liquidity, and how much timing risk versus impact cost the desk is willing to bear.
- "A backtest that fills every trade at the day's closing price is realistic enough." It silently assumes infinite liquidity at one single print and zero market impact regardless of size, exactly the "unrealistic fills" pitfall QD1.03 is built to defeat, and exactly why that module leans on this module's walk-the-book and impact machinery rather than a closing-price shortcut. A strategy that looks profitable against free, infinite, zero-impact fills can be unprofitable the instant real execution costs are subtracted, and the only way to know which you have is to model the cost honestly before you believe the backtest.
The thread through all eight: an expert never treats a quoted price, a benchmark, or a backtest's fill assumption as free of cost or free of judgment, every one of them is a simplification with a specific, nameable failure mode, and the discipline this module installs is knowing which simplification is safe for which question, and pricing the rest explicitly rather than assuming it away.
Worked examples
Worked example 1: Reading the touch on a real dataset row (US, $)
The very first row of this program's bundled synthetic-lob.csv (snapshot 0, timestamp 2026-06-01T09:00:00) gives the top two levels on each side. Treat this as the opening snapshot of a fictional, illustrative US-listed name, Meridian Robotics Inc. (MRB, NASDAQ, fictional, $), trading around $99.6: bid level 1 = $99.5755 / 1,272 shares, bid level 2 = $99.5257 / 230 shares; ask level 1 = $99.6751 / 4,983 shares, ask level 2 = $99.7249 / 1,449 shares. Every figure below is drawn directly from that real, bundled, seeded file (R3), not invented for this example.
Solution. Step 1: mid and spread. mid = (99.5755 + 99.6751) / 2 = 99.6253. spread = 99.6751 − 99.5755 = 0.0996. In basis points: spread_bps = 0.0996 / 99.6253 × 10000 ≈ 9.997, almost exactly 10bps, consistent with this dataset's own construction (tick size fixed at ~5bps of mid on each side, so the touch spread is always close to 2 ticks ≈ 10bps).
Step 2: microprice. microprice = (1272 × 99.6751 + 4983 × 99.5755) / (1272 + 4983) = (126,787.14 + 496,283.06) / 6255 ≈ 99.5958. Notice this lands below the mid (99.6253) and very close to the bid, because the ask-side size (4,983) is much heavier than the bid-side size (1,272).
Step 3: imbalance and interpretation. imbalance = (1272 − 4983) / (1272 + 4983) = −3711 / 6255 ≈ −0.593. A strongly negative imbalance, consistent with the microprice sitting below mid: the heavy ask queue signals more resting sell interest than buy interest at the touch, so the fair-value estimate leans toward the side more likely to get consumed next, here, the touch is more likely to trade down toward the bid than up toward the ask.
Read it. Three numbers (mid, microprice, imbalance) computed from the exact same four inputs, and each answers a genuinely different question: mid is "the naive midpoint," microprice is "a size-aware fair value," and imbalance is "which way is the pressure pointing, on its own signed scale." This is code-pack Exercise 1.
Worked example 2: Walking the book for a large buy order (India, ₹)
Konkan Textiles Ltd (KTXL, NSE, fictional, ₹) (illustrative and synthetic (R3)) shows a thin ask side: level 1 = ₹1,850.00 / 300 shares, level 2 = ₹1,850.50 / 500 shares, level 3 = ₹1,851.00 / 700 shares. A desk needs to buy 900 shares immediately.
Solution. Step 1: consume level 1. 300 shares available at ₹1,850.00; the order takes all of them. Cost so far: 300 × 1850.00 = ₹5,55,000. Remaining to fill: 900 − 300 = 600.
Step 2: consume level 2. 500 shares available at ₹1,850.50; the order takes all of them (600 > 500, so this level is also fully consumed). Cost: 500 × 1850.50 = ₹9,25,250. Running cost: 5,55,000 + 9,25,250 = ₹14,80,250. Remaining: 600 − 500 = 100.
Step 3: consume part of level 3. Only 100 of the requested 100 remaining are needed, and level 3 has 700 available, so the order takes exactly 100 at ₹1,851.00. Cost: 100 × 1851.00 = ₹1,85,100. Total cost: 14,80,250 + 1,85,100 = ₹16,65,350. All 900 shares filled, 3 levels touched.
Step 4: average price and slippage. avg_price = 16,65,350 / 900 = ₹1,850.3889. Against the best ask of ₹1,850.00, that's (1850.3889 − 1850.00) / 1850.00 × 10000 ≈ 2.10 bps of slippage, a small but entirely real cost that the quoted ₹1,850.00 price never warned you about, purely because the order was larger than what was resting at the touch.
Read it. Every share past the first 300 paid a worse price than the one the screen showed when the order was sent, and the order never even reached the third level's full size, a genuinely deep book (level 3 alone had 700 shares) still leaves slippage on a fill that needed only a fraction of it. This is code-pack Exercise 2.
Worked example 3: TWAP: an even schedule against an uneven tape (US, $)
Cascade Semiconductor Inc. (CSDX, NASDAQ, fictional, $) trades at $100.00, $100.50, $101.00, $100.20, and $99.80 across five one-minute buckets: illustrative, synthetic prices (R3). A desk needs to buy 101 shares total, split via naive TWAP.
Solution. Step 1, the schedule. 101 // 5 = 20, remainder 1, so the first bucket gets one extra share: [21, 20, 20, 20, 20], summing to exactly 101.
Step 2, the TWAP benchmark. The plain, unweighted mean of the five prices: (100.0 + 100.5 + 101.0 + 100.2 + 99.8) / 5 = 501.5 / 5 = $100.30.
Step 3, the realized execution price. Assuming each bucket's slice fills at that bucket's own price (no additional slippage modeled here, that's Exercise 2's job, layered on separately in a real system): notional = 21×100.0 + 20×100.5 + 20×101.0 + 20×100.2 + 20×99.8 = 2100 + 2010 + 2020 + 2004 + 1996 = 10,130. Average execution price = 10,130 / 101 ≈ $100.2970.
Step 4: slippage. (100.2970 − 100.30) / 100.30 × 10000 ≈ −0.296 bps, the execution came in very slightly better than the TWAP benchmark, purely because the extra share landed in bucket 1 ($100.00, one of the cheaper buckets) rather than the more expensive bucket 3 ($101.00).
Read it. Notice that the schedule's convention (remainder to the first buckets) is not perfectly neutral: it happened to help here because bucket 1 was cheap, but it would have hurt if the cheapest price had fallen in the last bucket instead (Practice Problem 5 makes this bite). TWAP's benchmark doesn't care which bucket absorbs the odd share; your realized slippage does. This is code-pack Exercise 3.
Worked example 4: VWAP: matching the volume profile (India, ₹)
Deccan Motors Ltd (DECM, NSE, fictional, ₹) trades at ₹1,850.00, ₹1,852.00, ₹1,849.00, and ₹1,851.50 across four buckets, with a classic U-shaped volume profile, heavy at the open and close, light in the middle: volumes 400, 150, 150, 300 (illustrative, synthetic, R3). A desk needs to buy 101 shares.
Solution. Step 1, the exact proportional shares. Total volume = 400+150+150+300 = 1000. Exact allocation: 101 × 400/1000 = 40.4, 101 × 150/1000 = 15.15 (twice), 101 × 300/1000 = 30.3.
Step 2: floor and remainder. Floors: [40, 15, 15, 30], summing to 100, one share short of 101. Fractional remainders: [0.4, 0.15, 0.15, 0.3]. The single leftover share goes to the largest remainder, bucket 0 (0.4), giving the final schedule [41, 15, 15, 30], summing to exactly 101.
Step 3, the VWAP benchmark. (1850.00×400 + 1852.00×150 + 1849.00×150 + 1851.50×300) / 1000 = (740,000 + 277,800 + 277,350 + 555,450) / 1000 = 1,850,600 / 1000 = ₹1,850.60.
Step 4: realized execution and slippage. Notional = 41×1850.00 + 15×1852.00 + 15×1849.00 + 30×1851.50 = 75,850 + 27,780 + 27,735 + 55,545 = 186,910. Average execution = 186,910 / 101 ≈ ₹1,850.5941. Slippage: (1850.5941 − 1850.60) / 1850.60 × 10000 ≈ −0.032 bps, essentially flat.
Read it. That tiny residual slippage is not luck; it's the entire point of VWAP scheduling. Because the schedule was built to mirror the exact volume profile that defines the benchmark, the only gap left between your execution and VWAP is the small, unavoidable rounding the largest-remainder method has to do to keep every bucket an integer number of shares. This is code-pack Exercise 4.
Worked example 5: Implementation Shortfall, fully decomposed (US, $)
A portfolio manager decides to buy 10,000 shares at a decision price of $50.00. By the time the order reaches the trading desk, the price has drifted to an arrival price of $50.10. The desk fills 8,000 shares at an average execution price of $50.25, but the order is cancelled with 2,000 shares unfilled; by then the price has moved to $50.40. Explicit commissions total $150.
Solution. Step 1: delay cost. (arrival_price − decision_price) × total_qty = (50.10 − 50.00) × 10,000 = $1,000, pure drift before any trading began; this cost exists regardless of how well the desk trades afterward.
Step 2: execution cost. (exec_avg_price − arrival_price) × executed_qty = (50.25 − 50.10) × 8,000 = $1,200, the actual cost of trading, relative to the price when trading started.
Step 3: opportunity cost. (cancel_price − decision_price) × (total_qty − executed_qty) = (50.40 − 50.00) × 2,000 = $800, the 2,000 shares never bought are marked, relative to the original decision price, at the price the position ended up at; had they been bought, this $800 of "missed" appreciation would instead have been captured.
Step 4: total, and basis points. Total cost = 1,000 + 1,200 + 800 + 150 = $3,150. As basis points of the original decision notional: 3,150 / (50.00 × 10,000) × 10000 = 3,150 / 500,000 × 10000 = 63.0 bps.
Read it. Three genuinely different phenomena (pure market drift, the actual mechanics of trading, and the cost of simply not finishing) land in one comparable unit (basis points of decision notional), each traceable back to the single decision price that started the clock. No later benchmark choice can make any of these three numbers look better or worse after the fact; that immunity to hindsight is Implementation Shortfall's entire reason for existing. This is code-pack Exercise 5.
Worked example 6: Market impact and capacity (illustrative, bps-neutral)
A desk calibrates its impact model with k = 0.8 and estimates the instrument's daily volatility at σ = 250 bps. It wants to know the impact of trading 16% of ADV, what happens if size quadruples to 64%, and (separately) the largest position it could trade if its cost budget for the day is capped at 60bps.
Solution. Step 1: impact at 16% participation. total_impact_bps = k × σ × sqrt(p) = 0.8 × 250 × sqrt(0.16) = 0.8 × 250 × 0.4 = 80 bps. With the default 50/50 permanent/temporary split, that's 40bps permanent (information that will not revert) and 40bps temporary (pressure that will).
Step 2: impact at 4× the size. 0.8 × 250 × sqrt(0.64) = 0.8 × 250 × 0.8 = 160 bps, exactly double the 80bps from Step 1, even though the size quadrupled. This is the square-root law's whole point: sqrt(4) = 2, not 4, cost grows far slower than size.
Step 3: inverting for capacity. Solve 60 = 0.8 × 250 × sqrt(p) for p: divide both sides by 0.8 × 250 = 200, giving sqrt(p) = 60 / 200 = 0.3; square both sides: p = 0.09, i.e. 9% of ADV is the largest position this desk can trade without exceeding its 60bps budget.
Read it. The same three numbers (k, σ, and participation) answer two different practical questions depending on which variable you solve for: "what will this cost me" (Steps 1–2) and "how big can I go before it costs too much" (Step 3), and the second is nothing more than algebra run backwards on the first. This is code-pack Exercises 6 and 7.
Practice set
Work each problem fully before reading its solution. All figures are illustrative/synthetic (R3) unless stated otherwise; numeric answers to about ±2% unless an exact integer is required.
P1 (guided). Spread in basis points. Best bid = $249.90, best ask = $250.10. Compute the mid, the spread, and the spread in basis points.
Solution. mid = (249.90 + 250.10) / 2 = $250.00. spread = 250.10 − 249.90 = $0.20. spread_bps = 0.20 / 250.00 × 10000 = 8.0 bps.
P2 (guided). Microprice direction. Best bid = $99.90 (size 800), best ask = $100.10 (size 200). Compute the microprice and state, in one sentence, why it lands where it does relative to the $100.00 mid.
Solution. microprice = (800 × 100.10 + 200 × 99.90) / (800 + 200) = (80,080 + 19,980) / 1000 = 100,060 / 1000 = $100.06. It lands above the $100.00 mid, toward the ask, because the heavier size sits on the bid (800 vs. 200), signaling more buying interest than selling interest, so the fair-value estimate leans toward the side (the ask) more likely to get consumed next.
P3 (guided). Walking a two-level book. Asks: level 1 = $20.00/100 shares, level 2 = $20.05/200 shares. A buy order for 250 shares arrives. Compute the filled quantity, average price, and slippage in bps.
Solution. Level 1 fills all 100 at $20.00 (cost $2,000); remaining 150 fills from level 2 at $20.05 (cost $3,007.50). Filled = 250, total cost = $5,007.50, avg_price = 5,007.50 / 250 = $20.03. Slippage: (20.03 − 20.00) / 20.00 × 10000 = 15.0 bps.
P4. TWAP schedule with a larger remainder. Split 23 shares across 4 buckets using this module's remainder rule. What's the schedule?
Solution. 23 // 4 = 5, remainder 3, the first 3 buckets get one extra share each: [6, 6, 6, 5] (sums to 23).
P5. The remainder rule is not perfectly neutral. Prices across 4 buckets: $10, $12, $11, $9. Split a 19-share TWAP order (19 // 4 = 4, remainder 3, so buckets 0–2 get 5 each and bucket 3 gets 4). Compute the TWAP benchmark, the realized execution price, and the slippage in bps, and explain in one sentence why the sign makes sense given which bucket absorbed fewer shares.
Solution. Benchmark (unweighted mean): (10+12+11+9)/4 = $10.50. Schedule [5,5,5,4]; notional = 5×10 + 5×12 + 5×11 + 4×9 = 50+60+55+36 = 201; avg_execution = 201/19 ≈ $10.5789. Slippage: (10.5789 − 10.50)/10.50 × 10000 ≈ 75.2 bps, a real cost. The sign makes sense because bucket 3, the cheapest price ($9), was the one bucket that got fewer shares (4 instead of 5), the naive "remainder to the first buckets" convention happened to underweight the cheapest opportunity this time, overpaying relative to the flat benchmark.
P6. VWAP with an exactly-divisible volume profile. Prices $40.00, $41.00, $39.50 across 3 buckets; volumes 100, 700, 200 (total 1,000); order size 50 shares. Compute the schedule, the VWAP benchmark, the realized execution price, and the slippage.
Solution. Exact proportional shares: 50×100/1000=5.0, 50×700/1000=35.0, 50×200/1000=10.0, every one already a whole number, so the schedule is simply [5, 35, 10] with zero remainder to distribute. VWAP benchmark: (40.00×100 + 41.00×700 + 39.50×200)/1000 = (4,000+28,700+7,900)/1000 = $40.60. Realized execution: (5×40.00+35×41.00+10×39.50)/50 = (200+1,435+395)/50 = 2,030/50 = $40.60: identical to the benchmark. Slippage is exactly 0.0 bps: when the proportional allocation happens to divide evenly, there is no rounding residual left at all, and the VWAP scheduler's execution price and its own benchmark become the same number.
P7. VWAP's tie-break rule, made concrete. Prices $10 and $20 across 2 buckets, volumes 1 and 1 (a perfect 50/50 split), order size 3 shares. What's the schedule, and which rule decided it?
Solution. Exact shares: 3×1/2 = 1.5 for each bucket, an exact tie. Floors are [1, 1], summing to 2, leaving 1 share to distribute; both buckets have the identical 0.5 fractional remainder, so the tie-break rule applies: the earlier (lower-index) bucket wins. Final schedule: [2, 1].
P8. Implementation Shortfall, small numbers. Decision price $50.00, arrival price $50.10, execution price $50.25, cancel price $50.40, total order 100 shares, 80 filled, fees $1.50. Compute all four cost components and the total.
Solution. Delay: (50.10−50.00)×100 = $10.00. Execution: (50.25−50.10)×80 = $12.00. Opportunity: (50.40−50.00)×(100−80) = 0.40×20 = $8.00. Total: 10.00+12.00+8.00+1.50 = $31.50, and in bps, 31.50/(50.00×100)×10000 = 63.0 bps (notice this matches Worked Example 5's 63bps exactly, because every input here is simply Worked Example 5's numbers scaled down by 100×, and basis points are scale-invariant).
P9. Fully filled, India ₹. Decision ₹1,800.00, arrival ₹1,802.00, execution ₹1,805.00, cancel price irrelevant since the order fills completely (500 of 500 shares), fees ₹200. Compute the total cost and confirm the opportunity-cost term.
Solution. Opportunity cost is exactly ₹0 (nothing unfilled). Delay: (1802−1800)×500 = ₹1,000. Execution: (1805−1802)×500 = ₹1,500. Total: 1,000+1,500+0+200 = ₹2,700; in bps, 2,700/(1,800×500)×10000 = 30.0 bps.
P10. Square-root law, doubling. k=1.0, daily vol 100bps. Compute the impact at 5% participation and at 10% participation (double), and state the exact ratio between them.
Solution. At 5%: 1.0×100×sqrt(0.05) ≈ 22.36 bps. At 10%: 1.0×100×sqrt(0.10) ≈ 31.62 bps. Ratio: 31.62/22.36 ≈ 1.414 = sqrt(2), doubling participation multiplies impact by sqrt(2), not by 2, the square-root law's signature.
P11. Capacity inversion. Impact budget 40bps, daily vol 200bps, k=1.0. What's the maximum participation rate?
Solution. p = (40/(1.0×200))² = (0.20)² = 0.04: 4% of ADV.
P12. Execution quality, both benchmarks. Arrival price $300.00, VWAP benchmark $299.70, execution price $300.30, 900 of 1,000 shares filled. Compute arrival slippage, VWAP slippage, fill rate, and whether the trade beat VWAP.
Solution. Arrival slippage: (300.30−300.00)/300.00×10000 = 10.0 bps (a cost vs. arrival). VWAP slippage: (300.30−299.70)/299.70×10000 ≈ 20.02 bps (also a cost: paid above the VWAP benchmark). Fill rate: 900/1000 = 0.90. beat_vwap is False, since VWAP slippage is positive, not ≤ 0.
P13. Partial fill exceeding total depth. Three ask levels of $75.00/50, $75.05/50, $75.10/50 (150 shares total depth); a buy order for 200 shares arrives. What fills, and what's the average price?
Solution. All 150 shares fill (every level fully consumed); 50 shares of the 200 requested are never filled, a partial fill, not an error. Average price: since all three levels carry equal size, the average is simply the plain mean of the three prices: (75.00+75.05+75.10)/3 = 75.05.
P14. TWAP with a single bucket. Split a 500-share order across exactly 1 bucket at $42.00. What's the schedule, the benchmark, and the slippage?
Solution. With one bucket there's nothing to split: schedule [500]. The benchmark is trivially that one price, $42.00, and the realized execution price is also $42.00: slippage is exactly 0.0 bps. (A degenerate case worth checking precisely because "does my code handle exactly one bucket" is a common off-by-one trap.)
P15. Impact split with a non-default permanent fraction. k=1.0, daily vol 150bps, participation 9%, permanent_fraction=0.3. Compute total, permanent, and temporary impact.
Solution. Total: 1.0×150×sqrt(0.09) = 1.0×150×0.3 = 45.0 bps. Permanent: 45.0×0.3 = 13.5 bps. Temporary: 45.0−13.5 = 31.5 bps.
P16. The VWAP-beating boundary. Execution price exactly equals the VWAP benchmark ($500.00 both). Is this trade recorded as having "beaten" VWAP?
Solution. VWAP slippage is exactly 0.0 bps, and the rule is beat_vwap = vwap_slippage_bps ≤ 0, the boundary is inclusive, so yes, an execution price exactly equal to the benchmark counts as beating (or at minimum, matching) VWAP, not failing to.
P17. Sort the invoice from the slippage. A fund executes a ₹40,00,000 buy. Its report lists: brokerage ₹1,200; exchange transaction charges and goods-and-services tax ₹340; securities transaction tax ₹4,000; the market drifted 8 bps between the decision and the moment the order reached the desk; the average fill came in 26 bps above the arrival price; and 6% of the order never filled, with the price at the close of the horizon 15 bps above the decision price. Classify every line as explicit or implicit, assign each to its shortfall bucket, and state which single line a commission negotiation could reduce.
Solution. Explicit, all landing in Fees: brokerage ₹1,200, exchange charges and tax ₹340, securities transaction tax ₹4,000, a total of ₹5,540, which on ₹40,00,000 is 13.85 bps. Implicit, one per bucket: the 8 bps of pre-execution drift is delay cost; the 26 bps against arrival is execution cost, and it is where the spread and the impact both sit; the unfilled 6% marked at 15 bps above decision is opportunity cost, contributing 0.06 × 15 = 0.90 bps of the total. Total shortfall is 8 + 26 × 0.94 + 0.90 + 13.85 = 47.19 bps, noting that execution cost applies only to the 94% actually executed. A commission negotiation reaches the brokerage line alone, ₹1,200 of 3.00 bps, because the statutory levies are set by circular and every other line is a market outcome rather than a price on a rate card. Halving the brokerage saves 1.5 bps against a 33.34 bps implicit bill, which is the argument for spending the negotiating effort on scheduling instead.
P18. Read the message log. A participant posts 5,000 at ₹250.05, 5,000 at ₹250.00 and 5,000 at ₹249.95 between 0.050 s and 0.054 s, sells 800 at ₹250.25 at 0.210 s, and cancels all 15,000 at 0.240 s with no fills on the bid. Compute the four surveillance measurements, name the pattern, and give the strongest innocent explanation plus the one additional field that would settle it.
Solution. Fill rate on the posted side: 0 of 15,000, zero per cent. Quoted-to-traded ratio: 15,000 / 800 = 18.75. Time on book: 0.240 − 0.050 = 190 milliseconds. Side asymmetry: all posted size was on the buy side and the only execution was a sell. The pattern is layering, spoofing given structure by stacking three successive price levels to manufacture apparent depth on one side while trading on the other. The strongest innocent explanation is genuine market making: a two-sided liquidity provider cancels constantly, quotes in size it does not expect to fill, and routinely trades on the opposite side to its resting quotes, so every individual measurement here has a legitimate version. What would settle it is the participant's own resting size on the offer over the same window. A market maker was quoting both sides; this log shows a single side posted and pulled. Add that field to the surveillance extract and the two explanations separate cleanly, which is the general shape of the job: no single ratio proves intent, and the right response to an alert is to name the additional field that discriminates rather than to argue about the threshold.
Applied mini-project
Run a full trade lifecycle: schedule it, cost it, and grade it.
You will take one hypothetical 5,000-share buy order through the entire pipeline this module builds, end to end, using your own worked (or code-pack-verified) functions.
Do this, in order:
- Set the scene. Choose one market (India ₹ or US $) and invent a decision price, an arrival price a short time later, and a small 5-bucket volume profile with realistic-looking U-shape volumes (heavier at the ends). State every number you're using up front, this is illustrative/synthetic data (R3), and it should read that way.
- Schedule it two ways. Compute the TWAP schedule (even split, remainder rule) and the VWAP schedule (largest-remainder apportionment against your volume profile) for the same 5,000 shares across your 5 buckets. Show both schedules and confirm each sums to exactly 5,000.
- Cost the walk. Pick ONE bucket and build a small 3–4 level order book for it (rising ask prices, plausible sizes). Walk the book for that bucket's slice under BOTH schedules and report the average fill price and slippage in bps for each.
- Decompose Implementation Shortfall. Using your decision price, arrival price, one overall execution average price (you may use either schedule's blended result), and a plausible cancel price for whatever, if anything, you choose to leave unfilled, compute all four IS components and the total in bps.
- Model the impact and the capacity ceiling. Pick a plausible
kand daily volatility, compute the modeled impact (temporary/permanent split) at your order's actual participation rate, and separately compute the maximum participation rate a 50bps cost budget would allow. - Grade it. Using your realized numbers, compute arrival slippage, VWAP slippage, and fill rate, and state in one paragraph which of TWAP or VWAP would have been the more defensible choice for THIS specific order, given the urgency you assigned it in Step 1.
Deliverable and self-check. One short write-up with all six steps' numbers shown (not just final answers), your market/currency stated once at the top, and a two-to-three sentence honest reflection on which single number in the whole exercise would most change a portfolio manager's opinion of your execution. Score yourself, 2 points each: (a) every number traced to an assumption you stated, none silently invented mid-calculation; (b) both schedules sum exactly to 5,000; (c) the book-walk step shows the actual level-by-level consumption, not just a final average; (d) Implementation Shortfall's four components are shown separately before being summed; (e) the final grading paragraph explicitly connects the urgency you assigned in Step 1 to the benchmark choice you defend in Step 6. Pass at 8/10, with no zero on any item.
Rubric note. There is no single "correct" numeric answer to this project, it is graded on internal consistency (do your own numbers, run through your own formulas, actually agree with each other) and honesty of assumptions (R3: every synthetic number is labeled as such), not on hitting a specific target.
Reading & resources
Everything below is an anchor to verify against and learn from, never a source to copy a number from directly into real trading decisions. Free unless marked; level tags reflect the ramp from intuition to full mechanism.
The anchor text:
- Larry Harris, Trading and Exchanges: Market Microstructure for Practitioners (Oxford University Press). [Paid] [Beginner–Advanced], the standard reference for this entire module: order types, priority rules, and the practitioner's view of execution quality, cover to cover.
The classic papers (the primary literature this module draws its models from):
- André Perold, "The Implementation Shortfall: Paper Versus Reality," Journal of Portfolio Management, 1988. [Paid, widely summarized free] [Advanced], the original decomposition behind Exercise 5.
- Robert Almgren & Neil Chriss, "Optimal Execution of Portfolio Transactions," Journal of Risk, 2000/2001 (freely available via SSRN/arXiv mirrors). [Free] [Advanced], the formal temporary-vs-permanent, cost-vs-timing-risk optimization this module's impact split simplifies from.
- Albert S. Kyle, "Continuous Auctions and Insider Trading," Econometrica, 1985. [Paid, widely available via university course pages] [Advanced], the original linear price-impact model ("Kyle's lambda"), the historical predecessor to the square-root law used here.
Primary-source order-type and market-structure documentation:
- NSE (National Stock Exchange of India): order-type and market-segment documentation. [Free] [Beginner], the India primary anchor (R6) for order types and priority rules as actually implemented.
- U.S. SEC / FINRA. Regulation NMS overview and order-type guidance; individual exchange (NYSE, Nasdaq) rulebooks for order-type specifics. [Free] [Beginner–Advanced], the US primary anchor (R6).
Practitioner-level overviews (perishable-but-useful; treat exact current numbers as dated):
- Rishi K. Narang, Inside the Black Box: A Simple Guide to Quantitative and High Frequency Trading. [Paid] [Intermediate], an accessible practitioner's tour of execution algorithms and market microstructure alongside the rest of the quant stack.
- Any reputable, current TWAP/VWAP explainer from a broker's or exchange's own execution-services documentation. [Free] [Beginner] (as of 2026-07, check current; execution-service marketing pages change often, use them for intuition only, never as a citation for a number).
Cross-links, not duplicated here: QM1.01/QM1.03 (Finance-Plus) for the probability/random-walk/volatility-estimation theory this module borrows as inputs; CS1.05 for the heap/priority-queue data structures a real LOB implementation is built on; QD1.03 for how this module's cost model plugs into a full backtesting engine's fill logic.
Do this, not just read: open app/public/datasets/synthetic-lob.csv yourself, pick any snapshot other than the one used in Worked Example 1, and hand-compute its mid, spread, microprice, and imbalance before checking your work against code-pack Exercise 1, five minutes with the actual bundled rows will teach you more about the microprice's direction than any amount of re-reading the formula.
Teach it back & journal
Feynman prompt. Explain to a colleague who has only ever seen a single "current price" on a stock-tracking app why that one number hides an entire cost structure: walk them through the difference between the touch price and the price a 50,000-share order would actually achieve, then explain why "beating VWAP" is not the same thing as "trading well" for an urgent order. If your colleague can, unprompted, predict that a market order for a large size will get progressively worse fills the deeper it reaches into the book, and explain why using the words "walk the book", you have installed this module's central mechanism.
Journal prompt. Pick any single number from this module's Mastery Check or Practice Set that surprised you, a slippage figure that was bigger than you expected, a schedule where the remainder landed somewhere non-obvious, an impact ratio that didn't scale the way intuition suggested. Write a short paragraph on why your intuition was off, and what the correct mental model is now. Then answer honestly: if you were handed a real portfolio manager's order tomorrow, which single number from this module, arrival slippage, the square-root law's capacity ceiling, or Implementation Shortfall's four-part decomposition, would you reach for FIRST to decide how to trade it, and why that one over the other two?
This module's flashcards and mastery quiz are wired into the app: see the node's Quiz and Reviews.