Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Matching Engine (Mini Exchange)

Simple, single-threaded limit order book in C++ with price-time priority. It keeps bids/asks in memory, supports limit and market orders, partial fills, cancel/replace by order id, IOC/GTC time-in-force, and emits trades when orders match.

submit returns a SubmitResult:

  • accepted: whether the order passed validation and entered matching.
  • reject_reason: why an order was rejected (NONE for accepted orders).
  • trades: trades generated by that submission.

Validation currently rejects:

  • duplicate order ids already resting in the book,
  • non-positive price,
  • non-positive quantity,
  • market orders when the opposite book has no liquidity,
  • replace requests for unknown order ids.

Prices are represented internally as integer ticks (PriceTicks) to avoid floating-point precision errors. Use price_to_ticks(...) when constructing orders and ticks_to_price(...) only when formatting output.

Layout

  • src/ core matching engine and book code.
  • tests/ assertions for matching, partial fills, cancel behavior, and safety validation.

Build and run

cmake -S . -B build
cmake --build build
./build/matching_engine_app

Replay mode:

./build/matching_engine_app replay tests/data/replay_basic.csv
./build/matching_engine_app replay tests/data/replay_basic.csv /tmp/trades.csv

Replay mode parses CSV rows, sorts them deterministically by (ts_ns, seq, original_file_order), replays them through the engine APIs, and prints a summary.

TWAP backtest mode (Piece 1):

./build/matching_engine_app backtest_twap tests/data/backtest_twap_basic.csv BUY 6 3

VWAP backtest mode:

./build/matching_engine_app backtest_vwap tests/data/backtest_twap_basic.csv BUY 6 3

Compare TWAP vs VWAP:

./build/matching_engine_app backtest_compare tests/data/backtest_twap_basic.csv BUY 6 3

Batch experiment mode:

./build/matching_engine_app backtest_batch tests/data/backtest_batch_requests.csv
./build/matching_engine_app backtest_batch tests/data/backtest_batch_requests.csv /tmp/backtest_runs.csv /tmp/backtest_summary.csv

Batch request CSV schema:

  • Header: dataset,side,qty,slices,strategy
  • dataset: replay CSV path (for example tests/data/backtest_vwap_profile.csv)
  • side: BUY or SELL
  • qty: positive integer parent quantity
  • slices: positive integer number of schedule buckets
  • strategy: TWAP or VWAP

Default batch outputs:

  • results/backtest_runs.csv: per-run metrics and status.
  • results/backtest_summary.csv: aggregated strategy stats (mean/p50/p95) and paired TWAP-VWAP deltas.

Backtest modes replay the market CSV, inject market child orders on either a TWAP or VWAP schedule, and print execution metrics:

  • fill quantity/rate,
  • arrival benchmark and average fill price,
  • implementation shortfall (bps),
  • participation rate against replay market volume.

VWAP sizing is proportional to replayed market trade volume per time bucket. If replayed market volume is zero, VWAP falls back to equal TWAP sizing. Time buckets with zero allocated VWAP quantity are shown as SKIPPED child slices in the output.

Results Snapshot

Reproducible from:

./build/matching_engine_app backtest_batch tests/data/backtest_batch_requests.csv

Using the current tests/data/backtest_batch_requests.csv scenarios:

  • Mean shortfall:
    • TWAP: 17.6200 bps
    • VWAP: 17.1450 bps
    • TWAP - VWAP: +0.4750 bps (VWAP lower on average in this sample)
  • Tail shortfall (p95):
    • TWAP: 27.4750 bps
    • VWAP: 19.7145 bps
  • Fill rate:
    • TWAP: 1.0000
    • VWAP: 1.0000

Example regime-dependent result from results/backtest_runs.csv:

  • backtest_vwap_profile.csv: TWAP=28.57 bps vs VWAP=14.29 bps
  • backtest_twap_basic.csv: TWAP=6.67 bps vs VWAP=20.00 bps

This demonstrates the intended research workflow: compare execution policies by scenario, not just by global average.

Limitations

  • VWAP sizing currently uses replayed realized market volume (look-ahead), so it is for offline benchmarking and strategy comparison, not live execution deployment as-is.

Time-in-force behavior:

  • GTC: leftover quantity rests in the book.
  • IOC: leftover quantity is canceled immediately.

Order type behavior:

  • LIMIT: matches only at limit price or better.
  • MARKET: matches immediately against best opposite prices and never rests leftover quantity.

Replace behavior:

  • Same price and quantity decrease (or unchanged quantity): keeps queue priority.
  • Price change or quantity increase: loses queue priority (effectively cancel + new submit).

Market data API behavior:

  • top_of_book(): returns optional best bid/ask levels with aggregated quantity at each best price.
  • depth(n_levels): returns top n_levels aggregated levels for bids and asks.
  • event_log() and events_since(seq_num): provide sequenced incremental events (ADD, TRADE, CANCEL, REPLACE).

Replay CSV schema:

  • Header must be exactly:
    • ts_ns,seq,action,order_id,side,type,price,qty,tif,new_price,new_qty,notes
  • action=NEW: requires side, type, qty; price required for LIMIT, blank for MARKET.
  • action=CANCEL: requires order_id.
  • action=REPLACE: requires order_id, new_price, new_qty.
  • Parsing errors include line numbers and stop replay.

Run tests

ctest --test-dir build --output-on-failure

License

MIT. See LICENSE.

About

Deterministic C++ matching engine with price-time priority, CSV market replay, and TWAP/VWAP backtests with TCA metrics.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages