Implementation:Nautechsystems Nautilus trader BacktestEngine Run
| Field | Value |
|---|---|
| sources | https://github.com/nautechsystems/nautilus_trader , https://nautilustrader.io/docs/ |
| domains | backtesting, event-driven simulation, execution |
| last_updated | 2026-02-10 12:00 GMT |
Overview
Concrete tool for executing an event-driven historical simulation provided by NautilusTrader.
Description
The run method on BacktestEngine initiates the main backtest loop. It validates that data has been sorted, resolves start/end boundaries, initializes accounts and the kernel on the first invocation, fast-forwards the data iterator to the start timestamp, and enters the core loop. The loop advances the simulated TestClock to each data event's timestamp, routes the event to the appropriate SimulatedExchange handler (quote tick, trade tick, bar, order book delta, instrument status, etc.), dispatches through the data engine for strategy callbacks, processes exchange execution messages, and interleaves deferred timer event handlers. When streaming is False (default), the method also calls end() to stop all sub-engines, flush remaining messages, and log post-run statistics.
Usage
Call engine.run() after all venues, instruments, data, and strategies have been added. Use start/end to restrict the simulation window. Use streaming=True for memory-efficient processing of datasets larger than RAM.
Code Reference
- Source location:
nautilus_trader/backtest/engine.pyx, lines 1295--1663 - Signature:
def run(
self,
start: datetime | str | int | None = None,
end: datetime | str | int | None = None,
run_config_id: str | None = None,
streaming: bool = False,
) -> None
- Import:
from nautilus_trader.backtest.engine import BacktestEngine
I/O Contract
Inputs:
| Parameter | Type | Required | Description |
|---|---|---|---|
start |
str | int | None | No | UTC start time. If None, uses the first data event's timestamp.
|
end |
str | int | None | No | UTC end time. If None, uses the last data event's timestamp.
|
run_config_id |
None | No | Tokenized BacktestRunConfig ID for tracking/reporting.
|
streaming |
bool |
No | If True, the engine does not call end() after the loop, allowing additional data batches. Default False.
|
Outputs / Side Effects:
| Output | Type | Description |
|---|---|---|
| None (return) | None |
Method mutates engine state in place. |
| Simulation state | side effect | Accounts, positions, orders, and portfolio are updated as the simulation processes each event. |
| Strategy callbacks | side effect | Strategies receive on_start, on_data, on_event, and on_stop callbacks in chronological order.
|
| Post-run stats | side effect | When streaming=False, the engine stops all sub-engines and logs performance statistics.
|
Raises:
| Exception | Condition |
|---|---|
ValueError |
No data has been added, or start >= end.
|
RuntimeError |
Data was added with sort=False but sort_data() was not called.
|
Usage Examples
Running a basic backtest:
from nautilus_trader.backtest.engine import BacktestEngine
engine = BacktestEngine()
# ... add venues, instruments, data, strategies ...
engine.run()
Running with a specific time window:
engine.run(
start="2024-01-01",
end="2024-06-30",
)
Streaming mode for large datasets:
# Batch 1
engine.add_data(batch_1_data)
engine.add_strategy(strategy)
engine.run(streaming=True)
# Clear and load next batch
engine.clear_data()
engine.add_data(batch_2_data)
engine.run(streaming=True)
# Final batch
engine.clear_data()
engine.add_data(batch_3_data)
engine.run(streaming=False) # or engine.end()
Retrieving results after a run:
engine.run()
result = engine.get_result()
print(f"Total orders: {result.total_orders}")
print(f"Total positions: {result.total_positions}")
print(f"Elapsed time: {result.elapsed_time}s")