AlgoDaily

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.

Why Microstructure Matters

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.

Market Microstructure Map

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.

Feed Types

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, then 102, then 103, the stream looks continuous.
  • If you receive 101, then 103, message 102 may be missing.
  • If you receive 105, then 104, 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?

Open interactive view →