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 (
FIX
tag=value
with 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 inPython
to feel the ergonomic differences (strings, slicing, map ops). ForJava
,C
, orJS
the same primitives apply: buffer handling + sequence bookkeeping. - For basketball fans: we use symbol
KB24
in 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 => value
pairs.
Guided challenges (pick one or more):
- Add checksum verification for the
FIX
message (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.unpack
and 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);