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. Rather than rebuilding, it reuses the Release-config Windows and Linux binaries ci.yml already built and tested for that exact commit (downloaded from that CI run's artifacts), packages each with its runtime libraries and the sample config, and drafts a GitHub Release with both archives attached. This means the tagged commit must already have a successful ci.yml run on main — tag what you've already merged, not an untested commit. 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