For the complete documentation index, see llms.txt. This page is also available as Markdown.

Order Book

Every market on the Exchange clears through one mechanism: a central limit order book. Traders who are willing to wait post limit orders that rest in the book, forming visible liquidity at discrete price levels; traders who want immediacy send orders that cross the spread and consume that liquidity. The book's contract is price-time priority — a better price always trades first, and at equal prices the earlier order trades first — which rewards the makers who quote tightest and earliest, and gives every taker the best available execution the book can offer.

Because makers commit first, every trade prints at the maker's quoted price: a taker willing to pay more than the best ask still pays only the ask. Around this core, the book layers execution guarantees that protect both sides — fill-or-kill orders that refuse partial execution, post-only orders that refuse to take liquidity, an opt-in self-trade prevention regime, and a server-enforced slippage cap that halts a market order the moment its running average price would drift too far from the mid-price it saw at submission.

The fill event is a fan-in of resting depth, availability, and self-trade decrements, and each fill feeds back into both the depth it consumes and the running VWAP that bounds the next fill.

The fill event is a fan-in of resting depth, availability, and self-trade decrements, and each fill feeds back into both the depth it consumes and the running VWAP that bounds the next fill.

Setting

A market is described by parameters: the tick size δ\delta (minimum price increment), the lot size \ell (minimum quantity increment), and minimum and maximum order sizes. The state is a pair of price-level maps — bids and asks — each holding a first-in-first-out queue of resting orders per price, together with the derived best bid PbP_b and best ask PaP_a. The admissible region for an incoming order requires a strictly positive, tick-aligned limit price and a lot-aligned quantity within the market's size bounds; orders outside it are rejected before touching the book.

Symbol
Name
Description
Units
Domain

qq

quantity

Order quantity in base units of the asset.

base units

(0, ∞)

qfq_f

filled_qty

Cumulative quantity of the order already filled.

base units

[0, ∞)

\ell

lot_size

Market lot size; order quantities must be integer multiples of it (a zero lot size disables the check).

base units

[0, ∞)

δ\delta

tick_size

Minimum price increment of the market. A non-positive tick disables alignment entirely (the raw price passes the check).

USDX per base unit

[0, ∞)

PlimP_{lim}

limit_price

Limit price of a resting or incoming limit order; must be strictly positive and tick-aligned.

USDX per base unit

(0, ∞)

PbP_b

best_bid

Highest resting bid price; undefined when the bid side is empty.

USDX per base unit

(0, ∞)

PaP_a

best_ask

Lowest resting ask price; undefined when the ask side is empty.

USDX per base unit

(0, ∞)

PmidP_{mid}

mid_price

Arithmetic midpoint of the best bid and best ask; the reference price captured once at market-order submission for the slippage cap.

USDX per base unit

(0, ∞)

β\beta

max_slippage_bps

Taker-supplied slippage cap on a market order, in basis points of the mid-price; absent means no cap.

basis points

[0, ∞)

qtq_t

taker_remaining

Unfilled quantity remaining on the incoming (taker) order at the moment it meets a maker.

base units

(0, ∞)

qmq_m

maker_remaining

Unfilled quantity remaining on the resting (maker) order at the front of the queue.

base units

(0, ∞)

PmkP_{mk}

maker_price

Limit price of the resting maker order; every fill prints at this price.

USDX per base unit

(0, ∞)

qq^{\star}

fill_qty

Quantity exchanged in a single fill between the taker and the front maker.

base units

(0, ∞)

PP^{\star}

fill_price

Price of a single fill — always the maker's limit price.

USDX per base unit

(0, ∞)

QavailQ_{avail}

available_qty

Total resting quantity on the opposing side at prices satisfying the taker's limit — the pre-match liquidity visible to a fill-or-kill check.

base units

[0, ∞)

VkV_k

running_notional

Cumulative notional of the fills accepted so far in the current market-order walk.

USDX

[0, ∞)

QkQ_k

running_filled

Cumulative quantity of the fills accepted so far in the current market-order walk.

base units

[0, ∞)

VV

notional

Total notional accumulated by a hypothetical walk of the opposing side in price-time priority.

USDX

(0, ∞)

qreqq_{req}

requested_qty

Quantity requested by a hypothetical market order in a VWAP preview.

base units

(0, ∞)

The mechanism

Admissibility

Before an order can touch the book, its quantity must be an exact multiple of the market's lot size \ell, and must lie within the market's minimum and maximum order sizes. Quantization keeps every resting queue and every fill expressible in whole lots, so partial fills never strand dust below the tradable increment. A zero lot size disables the multiplicity check.

qmod=0(B.1)q \bmod \ell = 0 \tag{B.1}

A limit price must be strictly positive and an exact multiple of the tick size δ\delta. Positivity is checked separately because zero is tick-aligned for every tick size — without the strict guard, a market booted before its first oracle print could accumulate zero-priced resting orders and print zero-priced trades. A non-positive tick size disables the alignment check but never the positivity one.

Plim>0andPlimmodδ=0(B.2)P_{lim} > 0 \quad\text{and}\quad P_{lim} \bmod \delta = 0 \tag{B.2}

Book state

When both sides of the book are populated, the mid-price is the arithmetic midpoint of the best bid and best ask. It is the book's instantaneous consensus price and the reference captured once at submission for the market-order slippage cap (B.8). When either side is empty the mid-price is undefined, and a market order carrying a slippage cap is rejected outright rather than executed against an unpriced book.

Pmid=Pb+Pa2(B.3)P_{mid} = \frac{P_b + P_a}{2} \tag{B.3}

Matching

A fill-or-kill order executes only if the book can satisfy it entirely; otherwise it cancels without touching the book. Before matching, the engine sums the resting quantity QavailQ_{avail} on the opposing side across every price level satisfying the taker's limit, and admits the order to the matching loop only when that sum covers the full request. A rejected fill-or-kill order records an expiry cancellation and generates no fills.

QavailqwhereQavail=levels P satisfyingthe taker limit  orders at P(qqf)(B.4)Q_{avail} \ge q \quad\text{where}\quad Q_{avail} = \sum_{\substack{\text{levels } P \text{ satisfying} \\ \text{the taker limit}}} \; \sum_{\text{orders at } P} (q - q_f) \tag{B.4}

The matching loop walks the opposing side of the book from the best price inward, and within each price level from the oldest order forward — price-time priority. Each encounter between the taker and the front maker exchanges exactly the smaller of the two remaining quantities: the maker cannot give more than it has resting, and the taker cannot take more than it still needs. A fully consumed maker leaves the book; a fully satisfied taker ends the walk.

q=min(qt,  qm)(B.5)q^{\star} = \min\left(q_t,\; q_m\right) \tag{B.5}

Every fill prints at the maker's limit price, not the taker's. The maker committed capital first at a stated price, and the taker who crosses receives that price even when willing to trade at a worse one — the price improvement accrues entirely to the taker. Together with (B.5) this fully determines each fill: a buy taker therefore never pays above its limit, and a sell taker never receives below it.

P=Pmk(B.6)P^{\star} = P_{mk} \tag{B.6}

Self-trade prevention

Self-trade prevention is opt-in and fires per encountered same-account maker, not once at order entry. In cancel-newest mode the taker cancels immediately; in cancel-oldest mode the maker cancels and the taker keeps walking. In decrement-and-cancel mode both orders shrink by the quantity they would have exchanged — the same minimum as (B.5) — but as a reduction of order size rather than a fill, so no trade is recorded. The smaller side is cancelled and the larger continues with reduced quantity; when both sides are equal, both cancel.

Δstp=min(qt,  qm)(B.7)\Delta_{stp} = \min\left(q_t,\; q_m\right) \tag{B.7}

Market-order slippage cap

A market order may carry a slippage cap β\beta in basis points. At submission the engine captures the mid-price (B.3) once and converts the cap into an absolute half-band around it; the running average execution price must remain within [Pmidh,  Pmid+h][P_{mid} - h,\; P_{mid} + h] for the walk to continue. If either side of the book is empty at submission the mid-price does not exist and the capped order is rejected with insufficient liquidity rather than executed unbounded.

h=Pmidβ104(B.8)h = P_{mid} \cdot \frac{\beta}{10^4} \tag{B.8}

As a capped market order walks the book, the engine evaluates, before accepting each candidate fill, the volume-weighted average price the order would have after that fill. If the prospective average would leave the band defined by (B.8), the fill is refused, the walk halts, and the remainder cancels with a slippage-cap reason — fills already accepted stand. The check is per-fill on the cumulative average, not per-level on the marginal price, so a deep sweep is halted exactly when its blended cost breaches the cap. The cap applies only to market orders; on limit orders it is silently ignored, since limit-or-better execution makes it meaningless.

Pˉk+1=Vk+qPQk+q,Pmidh    Pˉk+1    Pmid+h(B.9)\bar{P}_{k+1} = \frac{V_k + q^{\star} P^{\star}}{Q_k + q^{\star}}, \qquad P_{mid} - h \;\le\; \bar{P}_{k+1} \;\le\; P_{mid} + h \tag{B.9}

Execution preview

The book also answers a read-only question: at what average price would a hypothetical market order of size qreqq_{req} execute right now? The preview walks the opposing side in the same price-time order as live matching, accumulating notional VV until the request is covered, and returns the volume-weighted average. If resting liquidity cannot cover the request — or the requested quantity is non-positive — the preview returns no price rather than a partial estimate. Self-trade prevention and slippage caps are deliberately not applied here; they are concerns of the live submission path.

Pˉ=Vqreq,V=walked fillsqP(B.10)\bar{P} = \frac{V}{q_{req}}, \qquad V = \sum_{\text{walked fills}} q^{\star} P^{\star} \tag{B.10}

Invariants

  • The book is never crossed: whenever both sides are non-empty, Pb<PaP_b < P_a. Why it holds: An incoming limit order matches against every opposing level its price crosses before any remainder rests, so a resting bid at or above a resting ask cannot coexist — one would have consumed the other at submission. Post-only orders that would cross are rejected outright, and cancellations only remove orders, which cannot create a crossing.

  • No overfill: for every order, cumulative filled quantity never exceeds order quantity, i.e. qfqq_f \le q; equivalently the sum of fill quantities equals at most the taker's quantity ((B.5)). Why it holds: Every fill quantity is min(qt,qm)\min(q_t, q_m) of the two remaining quantities, so each fill reduces both remainders by a non-negative amount that cannot exceed either. The loop terminates the moment the taker's remainder reaches zero, so filled quantity is a monotone sum bounded by the original quantity.

  • Limit-or-better execution: every fill of a buy taker satisfies PPlimP^{\star} \le P_{lim} and of a sell taker PPlimP^{\star} \ge P_{lim} ((B.6)). Why it holds: The matching loop selects a maker level only if it satisfies the taker's limit — asks at or below a buy limit, bids at or above a sell limit — and every fill prints at that maker price. Levels beyond the limit terminate the walk before generating fills.

  • Index-book consistency: the order index contains exactly the identifiers of orders resting in the book, and every resting order has strictly positive remaining quantity. Why it holds: Every mutation path — insertion, cancellation, fill consumption, self-trade removal, and restore — updates the index and the price-level queues together in the same operation. Makers are removed from both the moment their remaining quantity reaches zero, and emptied price levels are deleted, so no zero-quantity order or dangling index entry survives any operation.

  • Slippage-cap monotonicity: for the same book and order, a larger cap β\beta never fills less quantity than a smaller one ((B.8), (B.9)). Why it holds: The fills accepted before the first band breach are identical for both caps, since the walk order and the running VWAP sequence do not depend on the cap. A wider band can only move the first breach later in that fixed sequence, so the accepted prefix — and hence the filled quantity — is weakly larger. This is pinned by the property test p021_slippage_cap_monotonic.

Worked example

Consider a market with tick size δ=0.5\delta = 0.5 and lot size =0.001\ell = 0.001, and three resting asks from distinct accounts: 1 unit at 100,000100{,}000, 1 unit at 101,000101{,}000, and 1 unit at 102,000102{,}000. A market buy for 2.52.5 units walks the levels in price priority. At the first level (B.5) gives q=min(2.5,1)=1q^{\star} = \min(2.5, 1) = 1 at fill price P=100,000P^{\star} = 100{,}000 per (B.6); the second level fills another unit at 101,000101{,}000; at the third the taker's remainder is 0.50.5, so q=min(0.5,1)=0.5q^{\star} = \min(0.5, 1) = 0.5 at 102,000102{,}000. The taker fully fills with notional V=1100,000+1101,000+0.5102,000=252,000V = 1 \cdot 100{,}000 + 1 \cdot 101{,}000 + 0.5 \cdot 102{,}000 = 252{,}000, an average price of 252,000/2.5=100,800252{,}000 / 2.5 = 100{,}800 per (B.10), and the third maker rests with 0.50.5 units remaining.

Now add a slippage cap. With a bid resting at 99,00099{,}000 and the best ask at 100,000100{,}000, the submission-time mid-price is Pmid=(99,000+100,000)/2=99,500P_{mid} = (99{,}000 + 100{,}000)/2 = 99{,}500 per (B.3). A market buy carrying β=50\beta = 50 basis points gets a half-band h=99,50050/104=497.5h = 99{,}500 \cdot 50 / 10^4 = 497.5 per (B.8), so the running VWAP must stay at or below 99,997.599{,}997.5. The very first candidate fill at 100,000100{,}000 would set the cumulative VWAP to 100,000>99,997.5100{,}000 > 99{,}997.5 per (B.9), so the fill is refused and the order cancels with a slippage-cap reason and zero fills — exactly the behavior pinned by the Rust test suite.

Finally, self-trade prevention in decrement-and-cancel mode: an account with 11 unit resting sends a 0.40.4-unit crossing order against itself. Per (B.7) both orders shrink by Δstp=min(0.4,1)=0.4\Delta_{stp} = \min(0.4, 1) = 0.4 with no fill recorded; the taker (the smaller side) cancels, and the maker continues resting with 10.4=0.61 - 0.4 = 0.6 units.

Analysis

Sensitivity

Elasticities ε = (∂y/∂x)·(x/y), computed numerically from the verified expressions at each worked-example point. |ε| > 1 means the output moves more than proportionally with that input.

Expression
Input
Elasticity ε

tick_alignment

limit_price

0

tick_alignment

tick_size

0

mid_price

best_ask

0.5025

mid_price

best_bid

0.4975

fok_availability

available_qty

0

fok_availability

quantity

0

fill_quantity

taker_remaining

1

fill_quantity

maker_remaining

0

fill_price

maker_price

1

stp_decrement

taker_remaining

1

stp_decrement

maker_remaining

0

slippage_span

mid_price

1

slippage_span

max_slippage_bps

1

running_vwap

running_filled

-0.8

running_vwap

running_notional

0.7976

running_vwap

fill_price

0.2024

running_vwap

fill_qty

0.002381

vwap_estimate

notional

1

vwap_estimate

requested_qty

-1

Sensitivity tornado — Fill quantity
Sensitivity tornado — Slippage half-band
Sensitivity tornado — Running VWAP cap check

Response curves

The absolute price band a capped market order may traverse grows linearly in the basis-point cap, scaled by the submission-time mid-price held constant per series.

The absolute price band a capped market order may traverse grows linearly in the basis-point cap, scaled by the submission-time mid-price held constant per series.

Each fill exchanges the minimum of the two remaining quantities: below the maker's size the taker binds, above it the maker binds (regions marked for the 1.0-unit maker).

Each fill exchanges the minimum of the two remaining quantities: below the maker's size the taker binds, above it the maker binds (regions marked for the 1.0-unit maker).

With two units already filled at an average of 100,500, the cumulative VWAP climbs toward the third level's price as more of it is consumed; the worked example's 0.5-unit fill lands at 100,800.

With two units already filled at an average of 100,500, the cumulative VWAP climbs toward the third level's price as more of it is consumed; the worked example's 0.5-unit fill lands at 100,800.

References

Last updated