Workflow:Nautechsystems Nautilus trader Backtest with BacktestNode
| Knowledge Sources | |
|---|---|
| Domains | Algorithmic_Trading, Backtesting, Quantitative_Finance |
| Last Updated | 2026-02-10 09:00 GMT |
Overview
End-to-end process for running configuration-driven backtests using the NautilusTrader BacktestNode with data sourced from a ParquetDataCatalog.
Description
This workflow covers the higher-level backtest orchestration pattern using BacktestNode, which accepts declarative configuration objects to define complete backtest scenarios. Unlike the BacktestEngine workflow (which requires programmatic setup), BacktestNode is configuration-driven: venue definitions, data sources, strategy assignments, and engine settings are all specified through serializable config objects. This enables batch execution of multiple backtest scenarios, parameter sweeps, and reproducible experiment tracking. The node sources data from a ParquetDataCatalog, automatically handling data loading, instrument resolution, and engine lifecycle.
Usage
Execute this workflow when you need to run multiple backtest configurations systematically, perform parameter optimization across strategy settings, or when you prefer a declarative configuration approach over programmatic engine setup. This is the preferred approach when data is already stored in a ParquetDataCatalog and you want reproducible, config-driven backtest execution. It is also the pattern used for automated testing and CI/CD pipeline integration.
Execution Steps
Step 1: Prepare the Data Catalog
Ensure historical market data and instrument definitions are stored in a ParquetDataCatalog. The catalog must contain the instruments and data types referenced in the backtest configuration. This step uses the Data Loading and Cataloging workflow to populate the catalog if data is not already available.
Key considerations:
- The catalog path will be referenced in BacktestDataConfig objects
- Instruments must be written to the catalog before data that references them
- Verify data availability for the desired time range and instruments
- The catalog supports multiple data types per instrument (ticks, bars, order book data)
Step 2: Define Venue Configurations
Create BacktestVenueConfig objects for each simulated exchange venue. Each config specifies the venue name, OMS type, account type, base currency, starting balances, and optional book type for order book simulation. These configs are serializable and can be stored/loaded from JSON.
Key considerations:
- BacktestVenueConfig is a declarative representation of engine.add_venue()
- Book type can be set to L2_MBP for order-book-driven backtests
- Multiple venue configs enable cross-exchange backtest scenarios
- Configs are hashable for experiment deduplication
Step 3: Define Data Configurations
Create BacktestDataConfig objects specifying which data to load from the catalog. Each config identifies the catalog path, data class (QuoteTick, TradeTick, Bar, OrderBookDelta), instrument ID, and optional time range filters. For bar data, specify the bar_spec or bar_types parameter.
Key considerations:
- Data configs reference the catalog path and instrument IDs
- Multiple data configs can be combined for multi-instrument or multi-data-type backtests
- Time range filtering is specified via start_time and end_time (as Unix nanoseconds)
- Bar data requires a bar_spec string (e.g., "1-MINUTE-BID") or explicit bar_types list
Step 4: Define Strategy Configurations
Create ImportableStrategyConfig objects that specify the strategy class module path and its configuration parameters. This factory pattern allows the BacktestNode to instantiate strategies from configuration alone, without requiring direct imports of strategy classes.
Key considerations:
- ImportableStrategyConfig uses strategy_path to specify the module and class (e.g., "my_package.strategies:EMACross")
- The config_path specifies the StrategyConfig subclass location
- All strategy parameters are embedded in the config for reproducibility
- Multiple strategy configs enable multi-strategy backtests
Step 5: Assemble and Run BacktestNode
Combine venue configs, data configs, engine config, and strategy configs into a BacktestRunConfig. Pass one or more run configs to the BacktestNode constructor and call node.run(). The node instantiates engines, loads data from the catalog, configures venues and strategies, executes the backtests, and collects results.
Key considerations:
- Multiple BacktestRunConfig objects enable batch execution of scenarios
- The node manages engine lifecycle (creation, execution, disposal) automatically
- Use node.get_engines() after execution to access individual engine results
- Each run config produces an independent BacktestEngine with isolated state
- Configs can be serialized to JSON for experiment versioning
Step 6: Extract and Compare Results
Retrieve the BacktestEngine instances from the completed node to access performance reports, order fills, position history, and portfolio statistics. When running multiple configurations, compare results across scenarios to identify optimal parameters or validate strategy robustness.
Key considerations:
- Each engine's trader provides generate_account_report(), generate_order_fills_report(), and generate_positions_report()
- The PortfolioAnalyzer computes aggregate statistics for each run
- Results can be collected into DataFrames for cross-scenario comparison
- Engine instances remain available until the node is disposed