A C++ matching engine implementation that demonstrates how to handle the 500ΞΌs+ latency differences between redundant market data feeds and the 100x jitter spikes that occur during market volatility - problems that cost trading firms millions in missed opportunities.
Real-world challenge: Major exchanges like Nasdaq and CME publish duplicate A/B feeds where:
- Feed latency differences exceed 500ΞΌs (enough to lose every trade)
- Jitter increases 100-1000x during volatility (50ΞΌs β 50ms)
- 17% of trades are now modified within 1 millisecond
- Wrong feed selection negates millions in infrastructure investment
This project demonstrates practical solutions to these exact problems.
- C++20 - Modern C++ for high-performance, zero-cost abstractions
- CMake 3.20+ - Build system and dependency management
- Conan 2.0 - C++ package manager for dependencies
- ASIO (standalone) - Asynchronous I/O for networking
- ZeroMQ - High-performance messaging library
- Protocol Buffers - Efficient binary serialization
- tcpdump/libpcap - Packet capture for latency analysis
- Intel TBB - Threading Building Blocks for parallel algorithms
- Boost.Intrusive - Zero-allocation intrusive containers
- SPSC/MPMC Queues - Lock-free queues for order flow
- Prometheus C++ Client - Metrics collection
- Grafana - Real-time dashboards
- spdlog - High-performance logging
- Google Test - Unit testing framework
- Google Benchmark - Microbenchmarking
- Catch2 - BDD-style testing
- Docker - Containerization
- docker-compose - Multi-container orchestration
- Valgrind/Perf - Performance profiling
- GDB - Debugging
| Metric | Target | Stretch Goal |
|---|---|---|
| Order Processing Latency | < 1 ΞΌs | < 500 ns |
| Throughput | 1M orders/sec | 5M orders/sec |
| Market Data Distribution | < 10 ΞΌs | < 5 ΞΌs |
| Memory Usage | < 1 GB | < 500 MB |
| Jitter (99th percentile) | < 100 ΞΌs | < 10 ΞΌs |
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β Order Entry ββββββΆβ Matching Engine ββββββΆβ Market Data β
β Gateway β β Core β β Distribution β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β β β
β β ββββΆ Feed A (50ΞΌs base)
β β β
βΌ βΌ ββββΆ Feed B (150ΞΌs base)
βββββββββββββββββββ βββββββββββββββββββ β
β Order Queue β β Order Book β βΌ
β (Lock-free) β β (Price-Time) β βββββββββββββββββββ
βββββββββββββββββββ βββββββββββββββββββ β Arbitrage Detectorβ
βββββββββββββββββββ
- Normal Market: 50-100ΞΌs latency with Β±10ΞΌs jitter
- Volatility Spike: 1-10ms latency with Β±1ms jitter (100x increase!)
- Implementation: Realistic jitter injection based on market conditions
- Problem: 500ΞΌs+ difference between "redundant" feeds
- Solution: Dynamic feed selection with latency tracking
- Measurement: Real-time arbitrage opportunity detection
- Challenge: 100x message rate spikes during announcements
- Solution: Adaptive buffering without adding base latency
- Demo: Configurable burst injection with performance monitoring
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y \
build-essential \
cmake \
ninja-build \
libboost-all-dev \
libzmq3-dev \
protobuf-compiler \
libprotobuf-dev \
libtbb-dev
# Install Conan
pip install conan# Clone repository
git clone https://github.com/yourusername/matchingengine.git
cd matchingengine
# Create build directory
mkdir build && cd build
# Configure with CMake
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..
# Build
ninja
# Run tests
ctest --output-on-failure
# Run the matching engine
./bin/matching_engine --symbols AAPL,GOOGL,MSFT --order-rate 1000000# Build and run with Docker Compose
docker-compose up --build
# Access monitoring dashboards
# Grafana: http://localhost:3000 (admin/admin)
# Prometheus: http://localhost:9090matchingengine/
βββ CMakeLists.txt # Root CMake configuration
βββ conanfile.txt # Conan dependencies
βββ docker-compose.yml # Container orchestration
βββ Dockerfile # Container definition
βββ README.md # This file
βββ benchmarks/ # Performance benchmarks
β βββ orderbook_bench.cpp
β βββ latency_bench.cpp
βββ cmake/ # CMake modules
β βββ FindTBB.cmake
βββ config/ # Configuration files
β βββ prometheus.yml
β βββ grafana/
βββ docs/ # Documentation
β βββ architecture.md
β βββ performance.md
βββ include/ # Public headers
β βββ core/
β β βββ order.hpp
β β βββ orderbook.hpp
β β βββ matching_engine.hpp
β βββ network/
β β βββ feed_handler.hpp
β β βββ market_data.hpp
β βββ utils/
β βββ lockfree_queue.hpp
β βββ time_utils.hpp
βββ src/ # Implementation files
β βββ core/
β βββ network/
β βββ monitoring/
β βββ main.cpp
βββ tests/ # Unit tests
β βββ test_orderbook.cpp
β βββ test_latency.cpp
β βββ test_feed_arbitrage.cpp
βββ scripts/ # Utility scripts
βββ generate_orders.py
βββ analyze_latency.py
Normal Conditions:
Order Receipt β Gateway: 50 ns (Β±5 ns)
Gateway β Queue: 20 ns (Β±2 ns)
Queue β Matching: 30 ns (Β±3 ns)
Matching β Execution: 100 ns (Β±10 ns)
Execution β Market Data: 50 ns (Β±5 ns)
Market Data β Network: 200 ns (Β±20 ns)
βββββββββββββββββββββββββββββββββββββββββββββββββ
Total: 450 ns (Β±45 ns)
During Volatility (Fed Announcement):
Order Receipt β Gateway: 500 ns (Β±200 ns)
Gateway β Queue: 200 ns (Β±100 ns)
Queue β Matching: 5000 ns (Β±2000 ns)
Matching β Execution: 10000 ns (Β±5000 ns)
Execution β Market Data: 5000 ns (Β±2000 ns)
Market Data β Network: 20000 ns (Β±10000 ns)
βββββββββββββββββββββββββββββββββββββββββββββββββ
Total: 40700 ns (Β±19300 ns)
12:00:00.000000 - Normal Trading
Feed A: 52ΞΌs latency (Β±8ΞΌs jitter)
Feed B: 148ΞΌs latency (Β±12ΞΌs jitter)
Arbitrage Window: 96ΞΌs
12:30:00.000000 - Economic Data Release
Feed A: 2,847ΞΌs latency (Β±892ΞΌs jitter)
Feed B: 156ΞΌs latency (Β±45ΞΌs jitter)
Arbitrage Window: 2,691ΞΌs (Feed B now faster!)
- Order book correctness under concurrent access
- Jitter injection validation
- Feed arbitrage detection accuracy
- End-to-end latency measurement with hardware timestamps
- A/B feed synchronization verification
- Burst handling without packet loss
- Sustained 1M orders/second for 60 seconds
- Latency percentiles during burst injection
- Memory usage under extreme load
- Random feed latency flips
- Sudden 1000x jitter increase
- Packet loss simulation
- CME Finding: Internal latency varies 100x between products
- Nasdaq Data: B-feed consistently 500ΞΌs+ behind A-feed
- Industry Stats: 17% of DAX futures modified within 1ms (2024)
- "We lost $2M in one day from listening to the wrong feed" - Anonymous Trader
- "Jitter prediction is worth more than raw speed" - HFT Developer
- "Most firms don't even measure feed arbitrage" - Exchange Engineer
MIT License - See LICENSE file for details
- Inspired by real incidents at CME, Nasdaq, and Eurex
- Based on techniques from Jane Street, Jump Trading, and Citadel
- Data from Databento's analysis of exchange feed behavior
Note: This is a simplified educational implementation. Production trading systems require additional features like risk management, regulatory compliance, and fault tolerance.