Simulation and Replay

TL;DR

Use a paper executor to test order and accounting behavior without sending orders to a live venue. Use REPLAY mode to rerun recorded events through your strategy. Always validate with paper before going live.

Paper execution

Paper accounts use the same executor and receipt interfaces as live accounts. The difference is where fills come from: a live executor gets fills from an exchange; a paper executor simulates fills from a configured data source.

device::BoundExecutor paper_;

paper_ = bind<device::BoundExecutor>(paper::Account{
    .id = "paper",
    .balances = {
        {.asset = "USDT", .amount = Notional{100'000}},
        {.asset = "BTC", .amount = Notional{0}},
    },
    .instruments = {
        Instrument::Spot("BTCUSDT", "BTC", "USDT"),
    },
    .simulation = paper::fromBar{
        .topic = "bar://okx/BTCUSDT@1m",
        .latency = time::milliseconds(100),
    },
});

Note

fromBar fills from the configured bar stream — each bar close becomes a fill price. This is a simplified fill model suitable for strategy logic validation. It is not a substitute for exchange queue simulation, which would model individual order matching against a limit order book. Choose the simulation model that matches what you are testing.

Replay mode

sdk::Application({
    .mode = sdk::RuntimeMode::REPLAY,
    .replay = ReplayConfig{.speed = 0.0},
})

speed = 0 processes eligible events without wall-clock pacing. A positive speed maps logical event time to wall time.

Decision tree: Which mode should I use?

What are you trying to do?

Test strategy logic with fake fills?
  → LIVE mode + paper::Account

Run historical data through your strategy?
  → REPLAY mode

Paper trade with real-time market data?
  → LIVE mode + paper::Account

Trade with real money?
  → LIVE mode + venue executor (see live-trading)

Tip

A common workflow: develop in LIVE + paper, replay historical data to validate the strategy across a broader date range, then switch to LIVE + venue executor for production. Each mode catches different classes of bugs.

Runtime controls

Installed replay projects support pause and resume:

aurum pause replay-demo
aurum resume replay-demo

Runtime controls currently operate on the selected local Aurum home and do not accept --server. Use the Forge environment’s operator surface when the instance runs remotely.

Validate before live trading

Confirm at least the following before replacing a paper executor with a live venue executor:

[ ] expected resource keys appear in the runtime catalog
[ ] rejected and partially filled receipts are handled
[ ] balances and positions converge after fills
[ ] replay completes without dropped lossless events
[ ] strategy identity and version are ready for an immutable push

Warning

A strategy that works perfectly in paper can fail in live trading for reasons unrelated to fill accuracy: network latency, exchange rate limits, credential expiration, partial fills at unexpected prices, or venue-specific order rejection rules. Paper validates your strategy logic. It does not validate your operational readiness.

Common mistakes

Treating paper fills as identical to live fills.

fromBar fills every market order at the bar close price. A live venue fills at the prevailing bid/ask, which may be far from the bar close during volatile periods. Paper tells you if your logic is correct; it does not tell you if your execution quality will be good.

Not handling rejected receipts in paper mode.

Even paper executors can reject orders (e.g., insufficient balance). If your strategy only handles accepted and ignores rejected, you may not notice that your paper account ran out of funds.

Using REPLAY speed=0 for real-time-sensitive logic.

speed=0 processes events as fast as the CPU allows. If your strategy has wall-clock-dependent behavior (timeouts, rate limiters), it will behave differently at speed=0 than at speed=1.0. Test at multiple speeds.

Next steps