This project is a small in-memory exchange simulator intended as a portfolio piece and a base for experimentation.
-
Core matching engine
OrderBookkeeps separate bid/ask maps.- Each price level uses intrusive doubly-linked lists of
OrderNodes to maintain strict price–time priority. - Orders are stored in an
Arenaallocator to avoid per-order heap traffic. - An
unordered_map<OrderId, OrderNode*>index gives O(1) cancel by id.
-
Lock-free queues
SpscRingBuffer<T, N>inutils/ringbuffer.hppis a single-producer / single-consumer lock-free ring buffer.- The backtest uses it to enqueue
OrderEvents into the engine.
-
Timestamps
- All events and trades carry nanosecond-resolution timestamps from
utils/time.hpp(now_ns()).
- All events and trades carry nanosecond-resolution timestamps from
-
Strategy plug-in API
Strategyabstract base class withon_step(...).MarketMakerStrategyimplements a simple symmetric market-making strategy adding bid/ask around a stochastic mid-price.- The API is intended to be extended for VWAP, TWAP, stat-arb, etc.
-
Deterministic backtesting
main.cpploads a small YAML-style config (config.yaml) with fields likesteps,seed,mid_price, etc.- Randomness comes from
std::mt19937_64seeded from config for reproducibility. - The loop records an equity curve and computes PnL, max drawdown, and a simple Sharpe ratio.
You can build this with any C++17 compiler. Example with g++:
g++ -std=c++17 -O3 -I./src \
src/utils/arena.cpp \
src/utils/ringbuffer.cpp \
src/utils/time.cpp \
src/core/types.cpp \
src/core/events.cpp \
src/core/book.cpp \
src/main.cpp \
-o lob_sim