Alan De Vaney.
All case studies
2026Sole engineerC++23 · memory-mapped storage · C ABI · CMake

C++ trading engine

I built a C++23 trading engine with explicit boundaries around market data and order execution. The engineering work centers on preserving state across restarts and keeping replay behavior consistent.

Independent engine. Production orders run through a gated Python REST executor. The C++ live order path remains gated.

Problem
Restarting a trading process meant recomputing every indicator and losing track of orders already at the exchange.
Engineering decision
Built a C++23 engine with a persistent indicator cache and order-journal recovery. A versioned C ABI lets strategy plugins share the same interface across replay and exchange integrations.
Result
Persistent state and recovery after a restart
Measured evidence
6 recovery scenarios passed, September 22, 2026
My role
Sole engineer, independent systems project
Source access
Private repository
In this case study Features and engineering details

What it does

Persistent indicators
Memory-mapped storage saves calculation progress for the next run.
Order recovery
Journal replay rebuilds local order state before exchange reconciliation.
Strategy plugins
A versioned C ABI checks compatibility when a strategy library loads.
Replay adapters
An interchangeable clock and market interfaces support historical replay.

Walkthrough

Earlier simulator and charting interface. The current C++23 engine is described below. This footage does not demonstrate live execution or the current recovery tests.

Give replay and exchange integrations the same boundaries

Market data and order execution sit behind explicit interfaces, with an interchangeable clock for replay. This lets a strategy use the same interface against historical data and exchange adapters. Strategy plugins load through a versioned C ABI, which makes compatibility checks explicit at the library boundary.

Orders cross threads through a single-producer, single-consumer ring. The repository has a Kraken integration and a separate Python REST execution path. Production orders have run through the Python REST executor since July 2026, and it carries its own fail-closed consent gate, a durable intent ledger with stable references, and its own interlock tests. The C++ live order path stays behind an arming ladder and has never been armed on the production box.

Recover state after an interruption

The indicator cache stores calculation progress in memory-mapped files. On restart, it can resume from the stored input position instead of recalculating the entire history.

Order recovery replays a journal into a fresh order-management system. Reconciliation compares local orders with the exchange's state, including fills that occurred during downtime and orders the exchange no longer reports.

A missing order is not enough evidence to cancel it locally. The recovery tests check that uncertain exchange state does not invent a fill. They also check that an order filled in part and then cancelled keeps both its fill history and its final cancelled status.

Tests exercise those recovery cases and reopen persisted stores after writes. That verifies restart behavior. It does not simulate a physical power failure. Sanitizer builds check memory errors and data races.

Profile the bottleneck

In an earlier simulator, allocation on the ingestion path limited how much history a backtest could process. Linux profiling directed the work toward container sizing and ownership. Preallocating storage and moving data instead of copying it removed that bottleneck. Pooling database connections reduced repeated setup work.

The changes allowed longer backtests without the same allocation bottleneck.

Build on exchange-integration experience

The project began with open-source contributions to zenbot in 2016. Merged pull requests #28 corrected the altcoin pair graph and #34 added Poloniex USDT pairs.

Subsequent versions added a C++ feed handler with gap detection and backfilling, followed by a backtesting simulator with an order book and charting interface. That work informed the boundaries in the current engine. The current engine is the fourth iteration since 2017 and carries 45 architecture decision records as of September 22, 2026.

Verification / September 22, 2026

6 recovery scenarios passed

  • Reopened persistent stores and resumed indicator calculations from saved progress.
  • Replayed order journals and reconciled exchange-state differences after downtime. Checked strategy plugin compatibility.

Local tests of storage and recovery. Live exchange execution and power-loss behavior were not tested.

Source revision d3b59ea