A high-performance limit order book (LOB) simulator and ML backtesting engine built in C++17 with LibTorch integration.
⚠️ Note: This project is under active development. Built for personal LOB research and microstructure experiments. Feel free to fork and adapt!
A fast C++ toolkit for streaming order book data, running ML inference (DeepLOB-style), and backtesting execution strategies with minimal overhead.
Data Flow: CSV → [L2Streamer] → [Ring40] → [TorchModel] → [Trader] → PnL
↓ ↓ ↓ ↓
Parse LOB History Inference Execute
Snapshots Buffer (0.1ms) Orders
┌──────────────────────────────────────────────────────────────────┐
│ LOB-Sim-CPP │
├──────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────┐ ┌──────────┐ ┌────────────┐ │
│ │ L2Streamer │───▶│ Snap │───▶│ Ring40<H> │ │
│ │ (CSV I/O) │ │ (10-lvl) │ │ (H×40 buf) │ │
│ └────────────┘ └──────────┘ └─────┬──────┘ │
│ │ │
│ ┌─────────────────────────────────┘ │
│ ▼ │
│ ┌────────────┐ ┌──────────┐ ┌────────────┐ │
│ │ TorchModel │───▶│ Predict │───▶│ Trader │ │
│ │ (DeepLOB) │ │ -1/0/+1 │ │ (PnL/Pos) │ │
│ └────────────┘ └──────────┘ └────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Utilities │ │
│ │ LOBDay • LatencyQueue • mid() • spread() │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘
| Component | Description |
|---|---|
| L2Streamer | Streams paired orderbook + message CSVs (LOBSTER format) |
| Snap | Compact 10-level LOB snapshot (40 floats: ask/bid price & size) |
| Ring40<H> | Lock-free circular buffer maintaining H×40 contiguous history |
| TorchModel | TorchScript wrapper for DeepLOB inference |
| Trader | Simple market order executor with position & PnL tracking |
| LOBDay | Bulk loader for full-day orderbook data |
Orderbook CSV (10 levels × 4 columns = 40 values per row):
───────────────────────────────────────────────────────────
ask_p1, ask_s1, bid_p1, bid_s1, ask_p2, ask_s2, ...
Message CSV (timestamps):
───────────────────────────────────────────────────────────
timestamp_sec, event_type, order_id, size, price, direction
#include "lob/L2Streamer.hpp"
#include "lob/Ring40.hpp"
#include "lob/Trader.hpp"
#include "lob/TorchModel.hpp"
int main() {
// Stream LOBSTER data
lob::L2Streamer stream("AAPL", "2023-01-03", 10, "data/raw");
lob::Ring40<100> ring; // 100-snapshot history
Trader trader;
TorchModel model("models/deeplob_ts.pt");
lob::Snap snap;
std::uint64_t ts_us;
while (stream.next(snap, ts_us)) {
if (!ring.push(snap)) continue; // warm-up
double mid = 0.5 * (snap.askPrice[0] + snap.bidPrice[0]);
// ML inference → direction prediction
auto [side, prob] = model.infer(ring.contiguous(), 100);
if (prob > 0.8f && side != 0) {
trader.market(mid, side, 100);
}
}
std::cout << "Final PnL: $" << trader.pnl(mid) << std::endl;
}git clone https://github.com/YOUR_USERNAME/lob-sim-cpp.git
cd lob-sim-cpp
mkdir build && cd build
# Point to your LibTorch installation
cmake -DCMAKE_PREFIX_PATH="$HOME/Downloads/libtorch" ..
cmake --build . --config Release- CMake ≥ 3.16
- C++17 compiler (clang++ / g++)
- LibTorch (PyTorch C++ distribution)
# Demo: load and inspect order book data
./demo AAPL 2023-01-03 10
# Backtest: run DeepLOB strategy
./backtest AAPL 2023-01-03 data/raw=== DeepLOB Backtesting System ===
Symbol: AAPL, Date: 2023-01-03, Depth: 10
Opening CSV streamer... ✓ (12ms)
Initializing ring buffer... ✓ (3μs)
Loading ML model... ✓ (847ms)
=== Starting main processing loop ===
Processed: 50000 rows, Rate: 142,857 rows/sec
Processed: 100000 rows, Rate: 138,462 rows/sec
=== Performance Report ===
Total rows processed: 234,521
Processing rate: 140,234 rows/sec
=== Timing Breakdown ===
Avg inference latency: 89 μs
Total trades executed: 1,247
Trade rate: 0.53% of rows
=== Trading Results ===
Final PnL: $2,341.87
lob-sim-cpp/
├── include/
│ └── lob/
│ ├── L2Streamer.hpp # CSV streaming
│ ├── Snap.hpp # LOB snapshot struct
│ ├── Ring40.hpp # Circular history buffer
│ ├── TorchModel.hpp # TorchScript wrapper
│ ├── Trader.hpp # Position & PnL tracker
│ ├── LOBDay.hpp # Bulk day loader
│ ├── LatencyQueue.hpp # Latency simulation
│ └── utils.hpp # mid(), spread(), etc.
├── src/
│ ├── LOBDay.cpp
│ └── main.cpp
├── app/
│ ├── main.cpp # Demo executable
│ ├── backtest.cpp # ML backtest
│ └── deeplob_backtest.cpp # Enhanced backtest
├── models/
│ └── deeplob_ts.pt # TorchScript model
├── data/
│ └── raw/ # LOBSTER CSV files
├── CMakeLists.txt
└── README.md
1. Data Ingestion
CSV → L2Streamer → Snap{askPrice[10], askSize[10], bidPrice[10], bidSize[10]}
│
▼
2. History Buffer (Ring40<100>)
┌─────────────────────────────────────────┐
│ t-99 │ t-98 │ ... │ t-1 │ t-0 │ (head) │ → [100 × 40] float array
└─────────────────────────────────────────┘
3. ML Inference
[100 × 40] → TorchModel(DeepLOB) → softmax → argmax → {-1, 0, +1}
│
4. Execution ▼
side = -1 (sell) │ side = 0 (hold) │ side = +1 (buy)
│ │
└──────────► Trader.market() ◄──────┘
│
▼
Update pos, cash, PnL
| Principle | Implementation |
|---|---|
| Zero-copy where possible | Ring buffer returns pointer to contiguous memory |
| Minimal allocations | Fixed-size arrays, stack allocation in hot path |
| Inference-only ML | Models trained in Python, exported as TorchScript |
| Modular components | Swap data source, model, or execution logic independently |
- LOBSTER CSV streaming
- Ring buffer for ML input
- TorchScript integration
- Basic market order execution
- PnL tracking
- Limit order support
- Latency simulation modes
- Multi-asset support
- Live data feed adapters
- GPU inference optimization
MIT License - see LICENSE for details.
Angelo - GitHub