Market Data Handler and Order Gateway: Initial Implementation
Hands-on goal: design a tiny, practical skeleton that shows how a UDP multicast market-data listener and a TCP/UDP order gateway fit together. We'll simulate both sides so you (a beginner in C++, Python, Java, C, JS) can see the core ideas without needing exchange credentials or NIC tuning yet.
Why this matters (short):
- Market data (multicast) is usually UDP-style: fire-and-forget, no retransmit. If you miss a packet you must detect gaps (sequence numbers) and recover via snapshot or TCP replay.
- Orders (gateway) are typically TCP (or a binary TCP protocol like
OUCH): reliable, ordered, and you must acknowledge and validate. - Building a clean separation helps:
MarketDataHandler(parse, detect gaps, publish) andOrderGateway(validate orders, send, ack).
Core concepts you should walk away with:
- Sequence recovery: maintain
last_seq, detectseq != last_seq + 1. Missing packet -> request replay/snapshot. - Parsing: binary parsing (map bytes to fields) vs text parsing (
FIXtag=valuewith SOH\x01). - Minimal API design: fast-in path for market updates, slightly heavier path for order validation.
ASCII data-flow (simplified)
Exchange multicast (ITCH-like) ---> NIC ---> [MarketDataHandler: parse, seq-check] ---> Strategy ---> [OrderGateway: validate, TCP submit] ---> Exchange TCP
A few notes tailored to your background:
- If you're comfortable in
Python, reimplement the C++ demo inPythonto feel the ergonomic differences (strings, slicing, map ops). ForJava,C, orJSthe same primitives apply: buffer handling + sequence bookkeeping. - For basketball fans: we use symbol
KB24in the demo — change it to your favourite player ticker to make it fun while you learn.
What the included C++ example does (run it in the code pane):
- Simulates two binary multicast packets (big-endian sequence number + fixed 8-byte symbol + price + size).
- Intentionally sends a gap (1001 then 1003) to show gap detection and a simulated recovery trigger.
- Parses a tiny
FIX-like order and prints parsedtag => valuepairs.
Guided challenges (pick one or more):
- Add checksum verification for the
FIXmessage (tag 10) and reject orders with bad checksums. - Simulate a replay server: when a gap is detected, fetch a synthetic snapshot (in C++ or Python) and patch the state.
- Reimplement the multicast parser in Python using
struct.unpackand compare code size and readability. - Replace the simulated packets with a real UDP socket receiver (Linux) and test with a local pcap replay tool like
tcpreplay(only after you understand sandbox/network safety).
Practical tips before you move on:
- Keep the hot path minimal: avoid allocations per packet in production. This demo uses strings/vectors for clarity.
- Validate lengths and fields before trusting values (never trust network input).
- Log sequence gaps and add metrics (counter of gaps, last good seq) — useful when you graduate to profiling with
perf.
Try this next: edit the C++ code to (1) change KB24 to your favorite ticker/player, (2) simulate a second gap, and (3) print how many gaps were detected. Or, reimplement the parse_fix function in Python to compare parsing convenience.
Happy hacking — this small demo is the seed of a real market-data handler and a safe order gateway skeleton. Build on it, then we’ll add sockets, recovery protocols, and latency measurements in later labs.
xxxxxxxxxx}using namespace std;// Simple helpers to simulate incoming binary multicast packets (big-endian)uint32_t read_be32(const vector<uint8_t>& b, size_t off) { return (uint32_t(b[off]) << 24) | (uint32_t(b[off+1]) << 16) | (uint32_t(b[off+2]) << 8) | uint32_t(b[off+3]);}vector<uint8_t> make_packet(uint32_t seq, const string& sym, uint32_t price, uint32_t size) { vector<uint8_t> p; // 4-byte sequence (big-endian) p.push_back((seq >> 24) & 0xFF); p.push_back((seq >> 16) & 0xFF); p.push_back((seq >> 8) & 0xFF); p.push_back(seq & 0xFF); // fixed 8-byte symbol (padded with \0) string s = sym; s.resize(8, '\0'); for (char c : s) p.push_back((uint8_t)c); // 4-byte price and 4-byte size p.push_back((price >> 24) & 0xFF); p.push_back((price >> 16) & 0xFF);

