A exchange simulator that shadows real exchanges for risk-free strategy testing. For each configured venue, it ingests the exchange's live public market data, mirrors it into a local order book, and exposes that exchange's own FIX/REST/WebSocket order-entry API — so a trading client can connect and trade against the simulator exactly as it would against the real exchange, with fills produced by an in-process FIFO matching engine instead of real capital.
Built in C++23. The executable is slick-sim (CMake project name ExchangeSimulator, currently v0.1.0).
Early-stage, under active development. Two exchanges are implemented today:
| Exchange | Status | Order entry | Market data |
|---|---|---|---|
| Coinbase | Implemented | REST + WebSocket | WebSocket |
| Hyperliquid | Implemented | REST | WebSocket |
| CME | Not implemented — adapter file exists but is empty | — | — |
| Eurex / ICE | Not implemented | — | — |
Each enabled exchange runs its own instance of the pipeline below:
Real exchange live public market data (WS)
(Coinbase, Hyperliquid) ────────────────────────────────────────▶ md_feed
│
│ mirrors the book
▼
orders (REST/WS) Exchange
Trading ───────────────────────────────▶ order_gateway ───▶ (CoinbaseExchange /
client ◀─────────────────────────────── ◀─── HyperliquidExchange)
(orders) order acks / fills / cancels │
│ per instrument
▼
Symbol
OrderBook (L3) + FifoMatchingEngine
│
│ book / trade updates
▼
market_data_publisher
│
│ venue-native market data (WS)
▼
Trading client
(market data)
order_gateway is bidirectional: it receives orders from the client and, via the response_queue fed by MatchingEngine::publishOrderAck/publishOrderExecution/publishOrderModify/publishOrderCancel, sends order acks, fills, modifies, cancels, and rejects back to the same client — independently of the market data path.
Library targets:
| Target | Responsibility |
|---|---|
exchange |
Per-venue orchestration (CoinbaseExchange, HyperliquidExchange) and Symbol, which binds one instrument's order book to a matching engine |
matching_engine |
FIFO price/time-priority matching (FifoMatchingEngine) and order lifecycle notifications (ack, fill, modify, cancel) |
order_gateway |
Venue-native REST/WS order-entry endpoints — receives orders and returns order acks/fills/cancels/rejects to the client — plus an unused generic FIX/SBE/JSON TCP gateway |
market_data_publisher |
Republishes book/trade updates in each venue's own WebSocket wire format |
md_feed |
Ingests each venue's live public market data feed |
common, order_book, utils |
Header-only: shared types (Order, Request, Venue, fixed-point price/qty helpers), OrderBook (wraps the external slick-orderbook L3 book), and misc helpers |
- CMake 3.25+
- A C++23 compiler: MSVC 2022 (17.7+ if you want AddressSanitizer), GCC, or Clang
- No
vcpkg.jsonmanifest is committed, so the following must already be resolvable viaCMAKE_PREFIX_PATHor a vcpkg toolchain file:- QuickFIX
- uWebSockets (
unofficial-uwebsockets) - nlohmann_json
- jwt-cpp
- foonathan_memory
- Boost (
uuidcomponent) - GoogleTest (only needed if building tests, which is on by default)
Everything else — slick-logger, slick-socket, slick-object-pool, slick-orderbook, coinbase-advanced-cpp, hyperliquid-cpp, slick-net — is fetched automatically via CMake FetchContent if not already installed locally.
cmake -S . -B build
cmake --build buildIf find_package can't locate the packages listed above, point CMake at a vcpkg installation:
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=<vcpkg_root>/scripts/buildsystems/vcpkg.cmakeThis builds the slick-sim executable and, by default, the slick_sim_tests test binary.
cmake -S . -B build -DENABLE_ASAN=ON # AddressSanitizer (MSVC needs VS2022 17.7+; auto-disabled otherwise)
cmake -S . -B build -DBUILD_EXCH_SIMULATOR_TESTING=OFF # skip building unit tests (default: ON)slick-sim reads a JSON config file passed on the command line. A sample is checked in at config/slick_sim.json:
{
"log_level": "trace",
"exchanges": {
"coinbase": {
"enabled": true,
"request_queue_size": 16777216,
"response_queue_size": 16777216,
"md_queue_size": 16777216,
"md_feeds": [
{
"type": "coinbase_live_ws"
}
],
"order_gateway": {
"rest": {
"port": 4000
},
"ws": {
"port": 4001
}
},
"md_publisher": {
"port": 5000
}
},
"hyperliquid": {
"enabled": true,
"md_feeds": [
{
"type": "hyperliquid_live_ws",
"base_url": "https://api.hyperliquid.xyz",
}
],
"order_gateway": {
"port": 4002,
"base_url": "https://api.hyperliquid.xyz",
"default_wallet": "0x0000000000000000000000000000000000000001"
},
"md_publisher": {
"port": 5001,
"base_url": "https://api.hyperliquid.xyz"
}
}
}
}log_level— one of theslick::loggerlevels (trace,debug,info,warn,error,fatal); defaults toinfoif omitted.exchanges— required. Each key is a venue name (coinbase,hyperliquid); a venue is skipped unlessenabledistrue(defaults totrueif omitted).md_feeds— live market data feeds to subscribe to on the real exchange.order_gateway— the venue-native order-entry endpoint(s)slick-simserves. Coinbase exposes separate REST and WS ports; Hyperliquid exposes a single REST port plus the upstreambase_urlused for request signing/proxying and a placeholderdefault_wallet.md_publisher— the portslick-simserves its own venue-formatted market data WebSocket on.- Coinbase additionally sets
request_queue_size/response_queue_size/md_queue_size, the capacities of its internal lock-free queues.
Note: if no config path is given on the command line,
slick-simlooks forslick-sim.jsonin the current directory — which does not match the committed sample's name or location (config/slick_sim.json). Always pass the path explicitly.
slick-sim config/slick_sim.json(The built binary's exact path depends on your CMake generator/config, e.g. build/src/sim/slick-sim or build/src/sim/Debug/slick-sim.exe.)
Press Ctrl+C to stop — slick-sim catches SIGINT and shuts every enabled exchange down gracefully before exiting.
Logs:
logs/slick-sim.log— always written.- Console — Debug builds only.
logs/coinbase_data/— raw Coinbase WebSocket capture, written whenever the Coinbase feed is active.
Unit tests are built by default (BUILD_EXCH_SIMULATOR_TESTING=ON) using GoogleTest, covering the matching engine (FIFO matching, self-match prevention, time-in-force), order book operations, message/type conversions, and the Coinbase/Hyperliquid exchange adapters (tests/unit/).
cmake -S . -B build
cmake --build build
ctest --test-dir buildci.yml builds and tests every push/PR to main across Windows and Ubuntu (Debug + Release). macOS is currently excluded — GitHub's Intel (macos-13) runners have very limited hosted capacity and queue indefinitely, and the ARM macos-latest runners can't build quickfix (its vcpkg port excludes arm64-osx). Since there's no vcpkg.json manifest, each job clones and bootstraps vcpkg itself and installs the required ports in classic mode (cached per-OS) before configuring CMake.
release.yml triggers on v* tags: it builds Release binaries for Windows and Linux, packages each with its vcpkg-provided runtime libraries and the sample config, and drafts a GitHub Release with both archives attached. Release notes are pulled from the matching # vX.Y.Z section of the CHANGELOG.md file, if present.
slick-sim/
├── .github/
│ └── workflows/
│ ├── ci.yml # build + test on push/PR (Windows, Ubuntu, macOS)
│ └── release.yml # tag-triggered GitHub Release with Windows binary
├── CHANGELOG.md # per-version notes, consumed by release.yml
├── CMakeLists.txt
├── config/
│ └── slick_sim.json # sample runtime configuration
├── scripts/
│ ├── download_cme_schemas.py # fetches CME SBE schemas (not currently used by the build)
│ └── create_fallback_schema.py
├── src/
│ ├── common/ # shared types: Order, Request, Venue, price/qty helpers (header-only)
│ ├── exchange/ # Exchange base + CoinbaseExchange/HyperliquidExchange, Symbol
│ ├── market_data_publisher/ # venue-native WS market data publishers
│ ├── matching_engine/ # FifoMatchingEngine (FIFO price/time priority)
│ ├── md_feed/ # live market data ingestion (Coinbase, Hyperliquid)
│ ├── order_book/ # OrderBook wrapper around the slick-orderbook L3 book (header-only)
│ ├── order_gateway/ # venue-native REST/WS order entry gateways
│ ├── sim/
│ │ └── main.cpp # slick-sim entry point
│ └── utils/ # order id / timestamp / price helpers (header-only)
├── tests/
│ └── unit/ # GoogleTest suite (slick_sim_tests)
├── LICENSE
└── README.md