A high-performance, low-latency C++ library for managing financial market order books. Optimized for microsecond-level performance in high-frequency trading systems.
- π Blazing Fast: Sub-100ns L2 operations, sub-200ns L3 operations (p99)
- π Dual Market Data: Level 2 (aggregated) and Level 3 (order-by-order) support
- π― Multi-Symbol: Efficient management of thousands of instruments
- π§ Flexible Build: Compiled library (default) or header-only mode
- π§© Protocol Agnostic: Generic design works with any exchange feed
- β‘ Zero Allocations: Object pooling eliminates runtime allocations in hot paths
- π¦ C++23: Leverages modern C++ features (
std::flat_map, concepts, etc.)
All performance targets exceeded by 2-40x:
| Operation | Target | Actual (p99) | Status |
|---|---|---|---|
| L2 Add/Modify/Delete | <100ns | 21-33ns | β 3-5x faster |
| L3 Add/Modify/Delete | <200ns | 59-490ns | β 2-3x faster |
| Best Bid/Ask Query | <10ns | 0.25-0.33ns | β 30-40x faster |
| Observer Notification | <50ns/observer | 2-3ns | β 16-25x faster |
| Memory Footprint (L2) | <1KB/symbol | <1KB | β Meets target |
| Memory Footprint (L3) | <10KB/1000 orders | <10KB | β Meets target |
- C++23 compiler: GCC 14+, Clang 18+, or MSVC 2022+ (17.6+)
- CMake: 3.20 or higher
- Git: For cloning the repository
# Clone the repository
git clone https://github.com/SlickQuant/slick-orderbook.git
cd slick-orderbook
# Build (Release mode)
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build . -j
# Run tests
ctest --output-on-failure
# Install (optional)
sudo cmake --install .#include <slick/orderbook/orderbook.hpp>
#include <iostream>
using namespace slick::orderbook;
int main() {
// Create L2 orderbook for symbol ID 1
OrderBookL2 book(1);
// Add price levels
book.updateLevel(Side::Buy, 10000, 100, 0, 0); // Bid: $100.00, qty 100
book.updateLevel(Side::Buy, 9950, 50, 0, 0); // Bid: $99.50, qty 50
book.updateLevel(Side::Sell, 10050, 75, 0, 0); // Ask: $100.50, qty 75
book.updateLevel(Side::Sell, 10100, 100, 0, 0); // Ask: $101.00, qty 100
// Query top of book
auto tob = book.getTopOfBook();
std::cout << "Best Bid: " << tob.best_bid << " x " << tob.bid_quantity << "\n";
std::cout << "Best Ask: " << tob.best_ask << " x " << tob.ask_quantity << "\n";
std::cout << "Spread: " << tob.spread() << "\n";
std::cout << "Mid Price: " << tob.midPrice() << "\n";
return 0;
}Output:
Best Bid: 10000 x 100
Best Ask: 10050 x 75
Spread: 50
Mid Price: 10025
#include <slick/orderbook/orderbook.hpp>
using namespace slick::orderbook;
int main() {
// Create L3 orderbook for symbol ID 1
OrderBookL3 book(1);
// Add individual orders
book.addOrModifyOrder(1001, Side::Buy, 10000, 100, 0, 0, 0); // Order #1001
book.addOrModifyOrder(1002, Side::Buy, 10000, 50, 0, 1, 0); // Order #1002 (lower priority)
book.addOrModifyOrder(2001, Side::Sell, 10050, 75, 0, 0, 0); // Order #2001
// Modify order quantity
book.addOrModifyOrder(1001, Side::Buy, 10000, 150, 0, 0, 0); // Increase qty to 150
// Execute partial order
book.executeOrder(2001, 25, 0, 0); // Execute 25 of order #2001
// Delete order
book.deleteOrder(1002, 0); // Cancel order #1002
// Query aggregated L2 view
auto bids = book.getLevelsL2(Side::Buy); // std::vector<PriceLevelL2>, best first
auto asks = book.getLevelsL2(Side::Sell);
return 0;
}#include <slick/orderbook/orderbook.hpp>
#include <iostream>
using namespace slick::orderbook;
int main() {
// Create multi-symbol manager
OrderBookManager<OrderBookL2> manager;
// Get or create orderbooks for different symbols
auto* btc_book = manager.getOrCreateOrderBook(1); // BTC
auto* eth_book = manager.getOrCreateOrderBook(2); // ETH
auto* sol_book = manager.getOrCreateOrderBook(3); // SOL
// Update each orderbook
btc_book->updateLevel(Side::Buy, 4500000, 1000, 0, 0); // BTC: $45,000
eth_book->updateLevel(Side::Buy, 250000, 5000, 0, 0); // ETH: $2,500
sol_book->updateLevel(Side::Buy, 10000, 10000, 0, 0); // SOL: $100
// Query all symbols
for (SymbolId symbol_id : manager.getSymbols()) {
auto tob = manager.getOrderBook(symbol_id)->getTopOfBook();
std::cout << "Symbol " << symbol_id << ": Best Bid=" << tob.best_bid << "\n";
}
return 0;
}Lifetime: raw pointers from
getOrCreateOrderBook()/getOrderBook()are invalidated byremoveOrderBook()/clear(), and by move-assigning another manager into this one. If symbols can be removed while other threads use them, usegetOrCreateSharedOrderBook()/getSharedOrderBook(), whosestd::shared_ptrkeeps the orderbook alive after removal.
#include <slick/orderbook/orderbook.hpp>
#include <iostream>
using namespace slick::orderbook;
// Implement observer interface
class MyObserver : public IOrderBookObserver {
public:
void onPriceLevelUpdate(const PriceLevelUpdate& update) override {
std::cout << "Level updated: "
<< (update.side == Side::Buy ? "BID" : "ASK")
<< " @ " << update.price
<< " qty=" << update.quantity << "\n";
}
void onTopOfBookUpdate(const TopOfBook& tob) override {
std::cout << "ToB: " << tob.best_bid
<< " / " << tob.best_ask << "\n";
}
// Other callbacks (onOrderUpdate, onTrade, onSnapshotBegin, onSnapshotEnd)
// default to no-ops; override only what you need.
};
int main() {
OrderBookL2 book(1);
auto observer = std::make_shared<MyObserver>();
// Register observer
book.addObserver(observer);
// Updates will trigger notifications
book.updateLevel(Side::Buy, 10000, 100, 0, 0);
// Output: Level updated: BID @ 10000 qty=100
// ToB: 10000 / 0
return 0;
}- Examples - Usage examples
- Architecture - Design and data structure overview
- Performance Guide - Performance best practices and profiling
- Benchmarks - Performance benchmarking and profiling guides
- FlatMap: Uses
std::flat_map(C++23) for cache-friendly sorted price level storage - Intrusive List: Zero-allocation doubly-linked list for order queues
- Object Pool: Pre-allocated memory eliminates runtime allocations
- Cache Alignment: 64-byte alignment prevents false sharing in multi-symbol scenarios
- Template-Based: No virtual dispatch in hot paths
- Concepts: C++23 concepts for compile-time type checking
- Inline Everything: Aggressive inlining for sub-nanosecond operations
# Build options
-DCMAKE_BUILD_TYPE=Release # Release, Debug, RelWithDebInfo
-DSLICK_ORDERBOOK_HEADER_ONLY=ON # Enable header-only mode (default: OFF)
-DSLICK_ORDERBOOK_BUILD_SHARED=ON # Build shared library (default: OFF)
-DSLICK_ORDERBOOK_BUILD_TESTS=ON # Build tests (default: ON)
-DSLICK_ORDERBOOK_BUILD_BENCHMARKS=ON # Build benchmarks (default: OFF)
-DSLICK_ORDERBOOK_BUILD_EXAMPLES=ON # Build examples (default: ON)
-DSLICK_ORDERBOOK_BUILD_COINBASE_EXAMPLE=ON # Build the Coinbase integration example (default: OFF)
-DSLICK_ORDERBOOK_ENABLE_LTO=OFF # LTO/IPO in Release builds (default: ON)
-DSLICK_ORDERBOOK_ENABLE_NATIVE_ARCH=OFF # -march=native in Release builds, GCC/Clang (default: ON)The Coinbase example is opt-in: it fetches coinbase-advanced-cpp, which requires nlohmann-json,
OpenSSL, Boost.Beast and jwt-cpp to be installed (e.g. via vcpkg) before configuring.
With SLICK_ORDERBOOK_BUILD_SHARED=ON the OrderBookL2/OrderBookL3 classes and the
OrderBookManager<OrderBookL2>/OrderBookManager<OrderBookL3> instantiations are exported
(__declspec(dllexport) on Windows, default visibility elsewhere). Linking slick::orderbook
propagates SLICK_ORDERBOOK_SHARED so consumers import them. On Windows, the DLL must be on
PATH or next to the executable at runtime. The library's SOVERSION is MAJOR.MINOR: ABI
compatibility is only kept within a minor version.
After cmake --install, the package config is installed to <prefix>/lib/cmake/slick-orderbook
(for both compiled and header-only builds). All of the library's install rules belong to the
slick-orderbook component, so cmake --install <build> --component slick-orderbook installs
only this library, without anything fetched dependencies install:
find_package(slick-orderbook 1.1 REQUIRED)
target_link_libraries(your_target PRIVATE slick::orderbook)Version matching follows the ABI policy: a compiled (static or shared) install only satisfies requests
for the same MAJOR.MINOR (find_package(slick-orderbook 1.0) does not accept 1.1.x), while a
header-only install satisfies any lower or equal version with the same major version.
Linking slick::orderbook also applies the required C++23 mode (cxx_std_23) to your_target.
include(FetchContent)
FetchContent_Declare(
slick-orderbook
GIT_REPOSITORY https://github.com/SlickQuant/slick-orderbook.git
GIT_TAG main
)
FetchContent_MakeAvailable(slick-orderbook)
target_link_libraries(your_target PRIVATE slick::orderbook)# In your CMakeLists.txt
add_compile_definitions(SLICK_ORDERBOOK_HEADER_ONLY)
target_include_directories(your_target PRIVATE /path/to/slick-orderbook/include)
target_compile_features(your_target PRIVATE cxx_std_23)
include/slick/orderbook/version.hppis generated by CMake at configure time from theproject(VERSION ...)inCMakeLists.txt; change the version there, not in the header.
# Build and run all tests
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DSLICK_ORDERBOOK_BUILD_TESTS=ON
cmake --build build -j
cd build && ctest --output-on-failure
# Run specific tests (all unit tests are in one GoogleTest executable)
./build/tests/slick_orderbook_tests --gtest_filter='OrderBookL2Test.*'
# With sanitizers
cmake -B build-asan -DCMAKE_CXX_FLAGS="-fsanitize=address -g"
cmake --build build-asan
cd build-asan && ctest# Build benchmarks
cmake -B build -DCMAKE_BUILD_TYPE=Release -DSLICK_ORDERBOOK_BUILD_BENCHMARKS=ON
cmake --build build -j
# Run all benchmarks
cd build/benchmarks
./bench_orderbook_l2
./bench_orderbook_l3
./bench_market_replay
# Run specific benchmark with filter
./bench_orderbook_l2 --benchmark_filter="AddNewLevel/100"
# Output results to JSON
./bench_orderbook_l2 --benchmark_out=results.json --benchmark_out_format=jsonThis project is licensed under the MIT License - see the LICENSE file for details.
- Built with modern C++23 features
- Powered by Google Benchmark for performance testing
- Inspired by high-frequency trading systems and exchange matching engines
- Organization: Slick Quant
- GitHub Issues: For bug reports and feature requests
Made with β‘ by Slick Quant