Backtesting
Backtester – Concepts
The Backtester is the orchestrator of the entire system. It does not contain trading logic, feature logic, or execution logic. Its sole responsibility is to coordinate the interaction between data, strategy, portfolio, and execution in a strictly ordered loop.
The backtester defines when things happen, never how they happen.
Core Responsibility
At every timestamp, the backtester enforces the following invariant order:
- Observe market state
- Ask strategy for new orders
- Ask portfolio for exit orders
- Execute orders
- Mark portfolio to market
No step is optional. No step is reordered.
High-level Control Flow
flowchart LR
DL[StgDataLoader] --> MGD[MarketGraphData]
MGD --> STG[Strategy]
MGD --> PF[Portfolio]
STG --> EO[Entry Orders]
PF --> XO[Exit Orders]
XO --> ORD[Order Queue]
EO --> ORD
ORD --> PF
PF --> MTM[Mark to Market]
Event-driven View
sequenceDiagram
participant D as StgDataLoader
participant B as Backtester
participant S as Strategy
participant P as Portfolio
participant E as ExecutionModel
D->>B: MarketGraphData(t)
B->>S: forward(MarketGraphData)
S-->>B: entry_orders
B->>P: get_exit_orders(MarketGraphData)
P-->>B: exit_orders
B->>P: on_order(exit_orders)
P->>E: fill_order(...)
E-->>P: filled exits
B->>P: on_order(entry_orders)
P->>E: fill_order(...)
E-->>P: filled entries
B->>P: mark_to_market(MarketGraphData)
Ordering Guarantees (Critical)
Exit Orders Before Entry Orders
Exit orders are always executed before new entry orders:
all_orders = exit_orders + entry_orders
This guarantees:
- cash from exits is available for new entries
- no artificial
NegativeCashError - deterministic capital reuse
This is a design rule, not an optimization.
What the Backtester Does NOT Do
The Backtester deliberately avoids:
- feature computation
- trading decisions
- order sizing
- execution modeling
- portfolio accounting
All such logic is delegated to specialized modules.
Determinism & Reproducibility
Given:
- a deterministic
StgDataLoader - a deterministic
Strategy - a deterministic
ExecutionModel
The backtest result is fully reproducible.
The Backtester itself introduces no randomness.
Mental Model
Think of the Backtester as a clock-driven state machine:
- Time advances via
StgDataLoader - Decisions come from
Strategy - State lives in
Portfolio - Reality is simulated by
ExecutionModel
The backtester only keeps time moving.
Summary
- Backtester is a coordinator, not a logic holder
- Enforces strict ordering per timestamp
- Guarantees exit-before-entry execution
- Preserves determinism and replayability
This separation is intentional and foundational to the system.