Order types and time in force
The order-type vocabulary traders expect, decomposed into two orthogonal questions the engine asks of every order.
The order state machine tells us when an order can rest, fill, cancel, or expire. Order types constrain how those transitions are selected.
A natural first design is to add a separate matching algorithm and state machine for every named order type offered by the venue. But the core composes a small set of orthogonal price and lifetime policies, and a conditional order cannot affect the live book before its trigger becomes a sequenced fact.
Brokers advertise dozens of order types. Nearly all decompose into two independent questions:
Question 1 — at what price may this trade?
flowchart TB
O["Order arrives"] --> Q{"Price constraint?"}
Q -- "none — take what's there" --> MKT["MARKET: match at best available until filled or book empty"]
Q -- "limit price given" --> LMT["LIMIT: match at limit or better, rest any remainder"]
Q -- "dormant until trigger" --> STP["STOP: inert until last trade touches stop price, then becomes market or limit"]
Question 2 — how long does the order persist? This is time in force (TIF):
| TIF | Meaning | Typical user |
|---|---|---|
| DAY | Live until the close, then auto-expires. | Default for most retail flow. |
| GTC — good till canceled | Persists across days until canceled (venues cap at 30–90 days). | Patient limit orders far from the market. |
| IOC — immediate or cancel | Match whatever is possible right now; cancel the remainder. Never rests. | Algos probing liquidity without showing their hand. |
| FOK — fill or kill | Fill completely right now or cancel entirely. All-or-nothing IOC. | Block traders who can't accept partial fills. |
Book from 1.3 (asks: 200 @ 10.03, 800 @ 10.04). Compare three buys of 900 shares:
- Limit 10.04, DAY: fills 900 (200 + 700), as in lesson 1.3.
- Limit 10.03, IOC: fills 200 @ 10.03; the remaining 700 would rest — but IOC forbids resting, so 700 is canceled instantly.
- Limit 10.03, FOK: the engine first checks whether 900 shares exist at ≤ 10.03. Only 200 do — the entire order cancels. Zero shares trade, and crucially, the check-then-match is atomic inside the single-threaded engine, so no one can slip in between.
The lesson behind the lesson: keep the engine's vocabulary minimal — price constraint, trigger, TIF — and let brokers compose exotic behavior (trailing stops, icebergs, pegged orders) at their edge from these primitives. Every type the core engine understands natively is more state to replicate, snapshot, and reason about in Parts 2 and 3.
A stop sell placed directly on the book can change displayed liquidity before the trigger price trades. A fill-or-kill order that partially fills before cancellation violates its contract just as clearly. Both errors come from confusing policy with ordinary resting state.
Order types = price constraint × time in force. Two small axes, rich vocabulary. IOC/FOK are matching-time policies; stops add a trigger state. Keep the core's type system minimal; compose exotica at the edge.