Skip to content

backtest: implement event-driven ReplayEngine#11

Merged
marwinsteiner merged 3 commits intomainfrom
phase-4/replay-engine
Feb 22, 2026
Merged

backtest: implement event-driven ReplayEngine#11
marwinsteiner merged 3 commits intomainfrom
phase-4/replay-engine

Conversation

@marwinsteiner
Copy link
Copy Markdown
Owner

Summary

Implements the event-driven historical replay engine (src/sysls/backtest/replay.py) for Phase 4 backtesting:

  • ReplayEngine creates a sandboxed environment (SimulatedClock, EventBus, OMS, PaperVenue) and feeds historical data through the full live stack for realistic simulation
  • Strategies receive events through the standard on_market_data lifecycle, identical to live execution
  • Routes strategy-originated orders through OMS → PaperVenue for simulated fills
  • Advances SimulatedClock with each data point; drains event queue between bars for deterministic replay
  • Computes mark-to-market equity curve with realized + unrealized PnL
  • Returns numpy arrays and trade logs compatible with metrics.py (Junior-1's module)
  • Supports multi-instrument interleaved data, configurable commission rates

Key integrations

  • sysls.core.bus.EventBus — event dispatch
  • sysls.core.clock.SimulatedClock — time advancement
  • sysls.core.events.BarEvent / TradeEvent — data events
  • sysls.execution.oms.OrderManagementSystem — order processing
  • sysls.execution.paper.PaperVenue — simulated fills
  • sysls.strategy.base.Strategy, StrategyContext — strategy lifecycle

Files

  • src/sysls/backtest/__init__.py — package init
  • src/sysls/backtest/replay.py — ReplayEngine (340 lines)
  • tests/backtest/__init__.py — test package init
  • tests/backtest/test_replay.py — 37 tests (733 lines)

Test coverage

37 tests covering: validation, do-nothing strategy, buy-once, buy-and-sell round-trips, strategy lifecycle, params, multi-instrument, commissions, equity curve accuracy, helper functions. 6 test strategy implementations.

Full suite: 551 passed, 10 skipped (existing Windows arcticdb skips). Ruff clean.

Test plan

  • All 37 replay tests pass
  • Full suite (551 tests) passes — no regressions
  • ruff check clean
  • ruff format clean
  • Integration test: strategy receives data → generates orders → gets fills → equity computed
  • Multi-instrument interleaved data works correctly
  • Realized and unrealized PnL computed accurately

Create src/sysls/backtest/ and tests/backtest/ packages with
__init__.py files for the Phase 4 backtesting engine.
Implements the event-driven historical replay engine that creates a
sandboxed environment (SimulatedClock, EventBus, OMS, PaperVenue)
and feeds historical data through the full live stack:

- ReplayEngine class: constructor with initial_capital and commission_rate
- _ns_to_datetime helper: nanosecond epoch to UTC datetime conversion
- _build_event_stream: converts instrument DataFrames to sorted events
  using bars_to_events/trades_to_events from data.normalize
- _compute_equity: mark-to-market portfolio valuation with realized
  and unrealized PnL tracking
- async run(): full lifecycle orchestration
  - Wires strategy to bus (MarketDataEvent, FillEvent, PositionEvent)
  - Routes strategy OrderSubmitted events through OMS for execution
  - Advances SimulatedClock with each data point
  - Drains event queue between bars for deterministic simulation
  - Collects equity curve, trade log, final positions
  - Returns dict with numpy arrays compatible with metrics.py
37 tests covering:
- Constructor: default and custom initial_capital, commission_rate
- Validation: empty data, invalid data_type
- Do-nothing strategy: result dict keys, equity curve shape,
  unchanged equity, no trades/positions, numpy array types
- Buy-once strategy: single trade, trade details, position state,
  unrealized PnL in equity
- Buy-and-sell strategy: round-trip trades, positive/negative
  realized PnL, flat position after close
- Strategy lifecycle: on_start/on_stop, market data count
- Strategy params: forwarded correctly, default empty dict
- Multi-instrument: interleaved data, multiple positions
- Commission: zero and nonzero rates
- Equity curve: starts at initial capital, tracks unrealized PnL
- Helpers: _ns_to_datetime, _build_event_stream sorting

Test strategies: DoNothing, BuyOnce, BuyAndSell, LifecycleTracking,
ParamStrategy, MultiInstrumentStrategy.
@marwinsteiner marwinsteiner merged commit 4d8907e into main Feb 22, 2026
1 check passed
@marwinsteiner marwinsteiner deleted the phase-4/replay-engine branch February 22, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant