Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ExchangeSimulator

C++23 License: MIT CI GitHub release

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).

Status

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

Architecture

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

Prerequisites

  • CMake 3.25+
  • A C++23 compiler: MSVC 2022 (17.7+ if you want AddressSanitizer), GCC, or Clang
  • No vcpkg.json manifest is committed, so the following must already be resolvable via CMAKE_PREFIX_PATH or a vcpkg toolchain file:

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.

Building

cmake -S . -B build
cmake --build build

If 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.cmake

This builds the slick-sim executable and, by default, the slick_sim_tests test binary.

Developer options

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)

Configuration

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 the slick::logger levels (trace, debug, info, warn, error, fatal); defaults to info if omitted.
  • exchanges — required. Each key is a venue name (coinbase, hyperliquid); a venue is skipped unless enabled is true (defaults to true if omitted).
    • md_feeds — live market data feeds to subscribe to on the real exchange.
    • order_gateway — the venue-native order-entry endpoint(s) slick-sim serves. Coinbase exposes separate REST and WS ports; Hyperliquid exposes a single REST port plus the upstream base_url used for request signing/proxying and a placeholder default_wallet.
    • md_publisher — the port slick-sim serves 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-sim looks for slick-sim.json in the current directory — which does not match the committed sample's name or location (config/slick_sim.json). Always pass the path explicitly.

Running

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.

Testing

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 build

Continuous integration & releases

ci.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.

Project structure

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

License

MIT

About

Exchange simulator that shadows live exchanges - mirrors real market data into a FIFO matching engine and exposes each venue's own FIX/REST/WS API, so trading clients can test against realistic fills without real capital.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages