Quant developer HFT course · Module 9: Trading systems
From market data to a trading decision
The question
Sketch how a market-data update becomes an order inside your system: threads, queues, what the strategy sees, and how you would test it.
Two designs
One thread does everything. The thread that receives the packet decodes it, updates the book, runs the strategy and, if the strategy decides to trade, runs risk checks and sends the order, all before reading the next packet. There are no queues and no handoffs; tick-to-trade is the sum of the stages' compute time. This is the fastest design for one strategy on one feed, and it is common for the most latency-sensitive paths. Its limits: one slow strategy delays the feed, and only one core's worth of work fits.
A pipeline of threads. A feed-handler thread maintains books and publishes; strategy threads consume; a gateway thread sends. Each handoff is a shared-memory ring between cores (Module 4), adding tens to a few hundred nanoseconds, in exchange for isolation and scale: many strategies on one feed, slow components unable to stall fast ones.
Many systems combine them: the fastest strategy runs inline in the feed thread, others downstream.
What the strategy receives
- Events: every book change, in order, as normalised records (add, delete, trade, level change). Needed by strategies that react to specific events, such as a trade or a change at the top of book, and by anything that keeps its own derived state.
- State: the current book, or the current top of book per instrument, read when needed. Through a seqlock per instrument (Module 4), any thread can read a consistent latest state without slowing the writer. Suits pricing, risk and slower strategies.
Many strategies want both: an event to wake them up and the consistent state of several instruments to decide with. A useful property is that the state a strategy reads is consistent with the event it is reacting to; a sequence number on both allows the check.
Batches and consistency
Exchanges often send several related messages in one packet: a large order trading through several levels produces a trade and several level changes. A strategy that runs after the first message sees a book that is mid-update. Feed handlers therefore mark the end of each packet or each logical event, and strategies act on complete updates. Getting this wrong produces trades on books that never existed.
Stale data
Every book carries a status: live, stale (gap detected, recovering), or closed. Strategies must check it before trading, and must also notice silence: a feed that stops sending is indistinguishable from a quiet market without heartbeats and timeouts. Many systems pull a strategy's quotes automatically when its inputs go stale.
Testing: deterministic replay
Recorded market data (every packet with its hardware receive timestamp) is the foundation of testing. Replaying a day through the same code path must produce exactly the same decisions every time. That requires:
- Time comes from the data. The strategy reads the current time from the event's timestamp or a clock interface that replay can drive, never directly from the system clock.
- No dependence on thread timing. With a pipeline, replay either runs the stages in a single thread in sequence order or records and replays the interleavings.
- No hidden nondeterminism: unordered map iteration, uninitialised memory, random numbers without fixed seeds.
With determinism, a bug seen in production can be reproduced exactly from the recording, and every change can be tested against months of history before release. Interviewers often ask how you would test a trading system; this is the answer they hope to hear.
Check yourself
Question 1 of 3
What is the main advantage of running the strategy inline on the feed-handler thread?
Each handoff between cores costs at least a cache-line transfer. Inline execution removes them, at the cost of coupling the strategy to the feed.
Question 2 of 3
A packet contains a trade and three level changes from one aggressive order. Why should the strategy wait for the end of the packet before acting?
Acting on an intermediate state means trading on a book that never existed. Feed handlers mark the end of each logical update.
Question 3 of 3
What is needed for a recorded day to replay into identical decisions?
Determinism comes from controlling every input, including time, and removing sources of variation between runs.
In the interview
Say your own answer out loud first, then open the one we would give.
How does market data get to your strategy?
Either inline, with the feed-handler thread running the strategy and sending orders itself, which is fastest, or through shared-memory rings to strategy threads, which isolates and scales at the cost of a handoff per stage. Strategies get ordered events for reacting and a consistent latest state, often seqlock-protected, for deciding, with book status flags and end-of-update markers.
How would you test a trading strategy's code?
By deterministic replay of recorded market data through the production code path: time driven by the data, no thread-timing dependence, no hidden nondeterminism. The same recording always yields the same decisions, so production issues can be reproduced and every change checked against history, alongside unit tests of each component.
What should a strategy do when its market data goes stale?
Stop trading on it: pull or freeze its quotes, refuse new orders on affected instruments, and wait for the feed handler to report the book live again. Staleness includes silence, detected with heartbeats and timeouts, not only explicit gaps.