Market Microstructure & Data Feeds
Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.
Why Microstructure Matters
From setup to market reality
In Course Overview & Environment Setup, you verified the toolchain, shaped a small project, and practiced the HFT habit of measuring something.
Now we zoom into the world your code will interact with: the exchange.
For high-frequency trading, an algorithm is not just “buy low, sell high.” It must understand:
- Who can trade with whom
- What data arrives from the venue
- What each message means
- Whether data is complete, stale, or out of order
- How prices form at the bid and ask
This lesson gives you the vocabulary and mental model needed before we write faster C++ or reconstruct order books later.

Market Microstructure Map
The market is a matching system
Market microstructure studies how trades actually happen inside a venue.
At a simplified exchange:
Buyers submit bids Sellers submit asks
\ /
\ /
-> Matching engine <-
|
v
Trades + market data
Key actors:
- Exchange / venue: Runs the matching engine.
- Participants: Traders, market makers, brokers, funds.
- Matching engine: Applies rules to pair compatible buy and sell interest.
- Market data feed: Publishes price, quote, trade, and status updates.
For HFT, the feed is your algorithm’s sensory system. If you misread the feed, your strategy may react to a market that no longer exists.

Quotes And Trades
Two messages you must separate
A beginner mistake is treating every market data update as “the price.” In real feeds, you will commonly see different event types.
Two essential ones:
- Quote: An update to available buying/selling interest.
- Trade: A completed transaction.
From the best quote we often compute:
- Bid: Highest visible buy price.
- Ask: Lowest visible sell price.
-
Spread:
ask - bid. -
Mid:
(bid + ask) / 2.
This small C++ example processes a few simplified feed events and logs the evolving best market.
```cpp
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
struct Event {
std::string type; // "QUOTE" or "TRADE"
double bid;
double ask;
double tradePrice;
int tradeQty;
};
int main() {
std::vector<Event> feed = {
{"QUOTE", 100.10, 100.14, 0.0, 0},
{"TRADE", 0.0, 0.0, 100.14, 200},
{"QUOTE", 100.11, 100.15, 0.0, 0},
{"TRADE", 0.0, 0.0, 100.11, 50}
};
double bestBid = 0.0;
double bestAsk = 0.0;
std::cout << std::fixed << std::setprecision(2);
for (const auto& e : feed) {
if (e.type == "QUOTE") {
bestBid = e.bid;
bestAsk = e.ask;
double spread = bestAsk - bestBid;
double mid = (bestBid + bestAsk) / 2.0;
std::cout << "QUOTE bid=" << bestBid
<< " ask=" << bestAsk
<< " spread=" << spread
<< " mid=" << mid << '\n';
} else if (e.type == "TRADE") {
std::cout << "TRADE price=" << e.tradePrice
<< " qty=" << e.tradeQty << '\n';
}
}
return 0;
}
```
Quote Or Trade?
A feed message says: last_price = 42.18, quantity = 300. It reports that a transaction already occurred.
What kind of market data event is this most likely?
Feed Types
Not all feeds show the same world
Market data feeds vary in detail and speed. Common categories:
Top-of-book
Shows only the best bid and best ask.
Best bid: 100.10 x 500
Best ask: 100.12 x 300
Depth-of-book
Shows multiple price levels.
Bid side Ask side
100.10 x 500 100.12 x 300
100.09 x 800 100.13 x 700
100.08 x 600 100.14 x 900
Full order-by-order
Shows individual order additions, modifications, cancellations, and executions.
The more detailed the feed, the more your system must track. Later, in Market Data Handling & Order Book Reconstruction, we will turn these messages into a live book structure.

Sequence Numbers
Completeness matters more than elegance
Market data feeds usually include a sequence number: a monotonically increasing identifier attached to each message.
Why it matters:
- If you receive
101, then102, then103, the stream looks continuous. - If you receive
101, then103, message102may be missing. - If you receive
105, then104, messages may be out of order.
A fast strategy built on incomplete data can make confident but wrong decisions. Your first job as a feed consumer is not prediction — it is integrity checking.
```cpp
#include <iostream>
#include <vector>
int main() {
std::vector<int> sequenceNumbers = {101, 102, 103, 105, 106, 104, 107};
int expected = sequenceNumbers.front();
for (int seq : sequenceNumbers) {
if (seq == expected) {
std::cout << "OK seq=" << seq << '\n';
++expected;
} else if (seq > expected) {
std::cout << "GAP detected: expected " << expected
<< " but received " << seq << '\n';
expected = seq + 1;
} else {
std::cout << "LATE/duplicate seq=" << seq
<< " current expected=" << expected << '\n';
}
}
return 0;
}
```
Gap Detection
Exchanges often attach a monotonically increasing identifier to market data messages so consumers can detect missing or out-of-order updates.
Fill in the blank:
This identifier is commonly called a ____.
Timestamps And Latency
Every event has a time story
A market data message may carry several meaningful times:
- Exchange timestamp: When the venue generated the event.
- Receive timestamp: When your machine observed it.
- Process timestamp: When your code handled it.
Latency is not just one number. You often care about:
exchange event -> network travel -> NIC receive -> application handling
The exact low-level optimization comes later in Low-Latency C++ for HFT and Networking & Kernel Bypass. For now, build the habit of preserving timestamps and measuring delay instead of guessing.
```cpp
#include <chrono>
#include <iostream>
#include <thread>
int main() {
using Clock = std::chrono::steady_clock;
auto receiveTime = Clock::now();
// Simulate application work after receiving a message.
std::this_thread::sleep_for(std::chrono::milliseconds(2));
auto processTime = Clock::now();
auto delayMicros = std::chrono::duration_cast<std::chrono::microseconds>(
processTime - receiveTime
).count();
std::cout << "Simulated receive-to-process delay: "
<< delayMicros << " microseconds\n";
return 0;
}
```
One True Price?
True or false:
In market data, the latest trade price is always the best representation of the current market because it is the most recent transaction.
Feed Mental Model
You are designing the first version of a market data consumer. Before using the data for trading decisions, what should it prioritize?