Back to Nautilus Trader

Rust

docs/concepts/rust.md

1.229.021.8 KB
Original Source

Rust

Nautilus has a complete Rust implementation under the crates/ directory. You can write actors, strategies, run backtests, and trade live without Python. The domain model is shared across all paths, and the v2 PyO3 path runs Python strategies on the Rust engine directly.

:::warning The Rust API is under active development. Method signatures and trait requirements may change between releases. :::

System implementations

Nautilus has three implementations. Understanding where each stands helps you choose the right one for your use case.

  • v1 legacy: Cython/Python classes under nautilus_trader/. Fully featured with the broadest component coverage.
  • v2 Rust: Pure Rust under crates/. Runs without Python.
  • v2 PyO3: Python user-components (actors, strategies) running on the Rust core via PyO3 bindings. Combines Python convenience with Rust engine performance.

Capability matrix

Componentv1 legacy (Cython)v2 Rustv2 PyO3 (Python on Rust)
Strategy
Actor
DataEngine
ExecutionEngine
RiskEngine
BacktestEngine
BacktestNode
LiveNode
OrderEmulator
Matching engine
Portfolio
Accounts
Cache
MessageBus
Data catalog
Indicators
Exec algorithmsTWAPTWAPTWAP
Controller--
Tearsheets--
Config serialization--

Adapters

Adapterv1 legacy (Cython)v2 Rustv2 PyO3
Architect AX
Betfair
Binance
BitMEX
Bybit
Databento
Deribit
dYdX
Hyperliquid
Interactive Brokers--
Kraken
OKX
Polymarket
Sandbox
Tardis

Choosing a path

  • v1 legacy is the most complete today. Use it if you need the Controller, tearsheets, Interactive Brokers, or config serialization.
  • v2 Rust gives native performance without a Python runtime. All core trading functionality is available. Use it for latency-sensitive deployments or teams that prefer a compiled language.
  • v2 PyO3: Python user-components (actors, strategies) run on the Rust core engine with Rust performance for data processing and execution, while keeping the Python authoring experience.

Project setup

The Nautilus crates are published to crates.io. Add them to your Cargo.toml:

toml
[dependencies]
nautilus-backtest = "0.59"
nautilus-common = "0.59"
nautilus-execution = "0.59"
nautilus-model = { version = "0.59", features = ["stubs"] }
nautilus-trading = { version = "0.59", features = ["examples"] }

anyhow = "1"
log = "0.4"

For live trading, add the live crate and the adapter for your venue:

toml
[dependencies]
nautilus-live = "0.59"
nautilus-okx = "0.59"

To track the latest development branch, point all Nautilus dependencies at the same git source to avoid type mismatches between crates.io and git versions:

toml
[dependencies]
nautilus-backtest = { git = "https://github.com/nautechsystems/nautilus_trader.git", branch = "develop" }
nautilus-common = { git = "https://github.com/nautechsystems/nautilus_trader.git", branch = "develop" }
nautilus-execution = { git = "https://github.com/nautechsystems/nautilus_trader.git", branch = "develop" }
nautilus-model = { git = "https://github.com/nautechsystems/nautilus_trader.git", branch = "develop", features = ["stubs"] }
nautilus-trading = { git = "https://github.com/nautechsystems/nautilus_trader.git", branch = "develop", features = ["examples"] }

The minimum supported Rust version (MSRV) is 1.96.0.

Feature flags

FlagCrateEffect
high-precisionnautilus-model16-digit fixed precision (default is 9). Required for crypto.
stubsnautilus-modelTest instrument stubs (audusd_sim, etc.).
examplesnautilus-tradingExample strategies (EmaCross, GridMarketMaker).
streamingnautilus-backtestCatalog‑based data streaming via BacktestNode.
definautilus-modelDeFi data types. Implies high-precision.

:::tip Standard 9-digit precision handles most traditional finance instruments. Enable high-precision for crypto venues where prices can have many decimal places (e.g. 0.00000001). :::

Actors

An actor receives market data, custom data/signals, and system events but does not manage orders. Implement the DataActor trait and use nautilus_actor! to wire your DataActorCore field into the runtime contract. Your type implements or derives Debug; the macro supplies the native runtime wiring. User code normally uses the DataActor facade methods for subscriptions, cache access, and clock access.

Handler methods

Override any handler on the DataActor trait to receive the corresponding data or event. All handlers have default no-op implementations, so you only override what you need.

HandlerReceives
on_startActor started.
on_stopActor stopped.
on_quoteQuoteTick
on_tradeTradeTick
on_barBar
on_book_deltasOrderBookDeltas
on_bookOrderBook (at interval)
on_instrumentInstrumentAny
on_mark_priceMarkPriceUpdate
on_index_priceIndexPriceUpdate
on_funding_rateFundingRateUpdate
on_option_greeksOptionGreeks
on_option_chainOptionChainSlice
on_instrument_statusInstrumentStatus
on_order_filledOrderFilled
on_order_canceledOrderCanceled
on_time_eventTimeEvent

For a step-by-step walkthrough, see the Write an Actor (Rust) how-to guide. For a complete example, see BookImbalanceActor.

Strategies

A strategy extends an actor with order management. Implement DataActor for data handling and use nautilus_strategy! to wire your StrategyCore field into the strategy runtime contract. StrategyCore stores the runtime strategy state; normal strategy logic reaches it through facade methods on self. Runtime registration requires the native wiring generated by the macro, but normal strategy logic uses Strategy methods and the facade methods on self.

Order management

The Strategy trait provides order methods through the facade:

MethodAction
submit_orderSubmit a new order to the venue.
submit_order_listSubmit a list of contingent orders.
modify_orderModify price, quantity, or trigger price.
cancel_orderCancel a specific order.
cancel_ordersCancel a filtered set of orders.
cancel_all_ordersCancel all orders for an instrument.
close_positionClose a position with a market order.
close_all_positionsClose all open positions.

The OrderApi (accessed via self.order()) builds orders and order lists:

  • generate_client_order_id
  • generate_order_list_id
  • market
  • limit
  • stop_market
  • stop_limit
  • market_to_limit
  • market_if_touched
  • limit_if_touched
  • trailing_stop_market
  • trailing_stop_limit
  • bracket
  • create_list

Core wiring macros

Rust actors, strategies, and execution algorithms keep their runtime core as a struct field. The macros tell the traits where that field lives.

MacroCore fieldGenerates
nautilus_actor!(Type)DataActorCoreRuntime wiring.
nautilus_strategy!(Type)StrategyCoreRuntime wiring and Strategy.
nautilus_execution_algorithm!(Type, { ... })ExecutionAlgorithmCoreRuntime wiring and algorithm.

The macros expect a field named core; pass a field name as the second argument when needed. They do not make the actor, strategy, or StrategyCore deref to runtime internals. The execution algorithm macro takes an on_order() implementation block because that method defines the algorithm's required order handling. Normal code uses facade methods such as:

  • actor_id()
  • trader_id()
  • is_registered()
  • config()
  • strategy_id()
  • clock()
  • cache()
  • order()
  • portfolio()

Native traits

Use facade methods by default:

  • actor_id()
  • trader_id()
  • is_registered()
  • config()
  • strategy_id()
  • clock()
  • cache()
  • order()
  • portfolio()

DataActorNative, StrategyNative, and ExecutionAlgorithmNative are for native-only access below that facade. This section documents host integration and explicit latency-sensitive native Rust code, not the portable authoring path.

Authoring pathNative traits?Normal API
Native Rust binaryOnly when neededStrategy and DataActor facades.
Rust launched from PythonOnly when neededSame as native Rust.
Python‑authored componentNoFacades only.
Plug‑in‑compatible codeNoFacades only.

Native traits expose borrowed core state, Rc<RefCell<_>>, and runtime references. Use them when native Rust code intentionally accepts those borrow rules for an explicit latency-sensitive path or host integration. Engine, runtime, registration, PyO3, testkit, and plug-in host code can import DataActorNative, StrategyNative, or ExecutionAlgorithmNative when they need actor-core, strategy-core, or execution-algorithm-core access. Do not use them in ordinary portable actor, strategy, or execution algorithm logic, Python-authored components, or plug-in-compatible code, because those types do not cross those boundaries.

ExecutionAlgorithmCore owns a DataActorCore, but it does not deref to one. Normal execution algorithm logic should use id(), actor_id(), trader_id(), clock(), and cache(). Reach for ExecutionAlgorithmNative only when the code needs native execution-algorithm state.

Choose the smallest native handle and keep each borrow scoped. Use order() for normal strategy order construction. Reach for order_factory() only when native code needs the raw mutable factory borrow.

DataActorNative methods

Native methodReturn shapeUse when
core()&DataActorCoreRead actor internals.
core_mut()&mut DataActorCoreMutate actor internals.
clock_mut()RefMut<'_, dyn Clock>Need a mutable clock borrow.
clock_rc()Rc<RefCell<dyn Clock>>Store or pass the shared clock.
cache_ref()Ref<'_, Cache>Need short live‑cache reads.
cache_rc()Rc<RefCell<Cache>>Mutate, store, or pass cache.

StrategyNative methods

Native methodReturn shapeUse when
strategy_core()&StrategyCoreRead strategy internals.
strategy_core_mut()&mut StrategyCoreMutate strategy internals.
order_factory()RefMut<'_, OrderFactory>Need raw mutable factory borrow.
order_factory_rc()Rc<RefCell<OrderFactory>>Store or pass the factory.
portfolio_rc()Rc<RefCell<Portfolio>>Store or pass the portfolio.

ExecutionAlgorithmNative methods

Native methodReturn shapeUse when
exec_algorithm_core()&ExecutionAlgorithmCoreRead execution algorithm internals.
exec_algorithm_core_mut()&mut ExecutionAlgorithmCoreMutate execution algorithm internals.

For a step-by-step walkthrough, see the Write a Strategy (Rust) how-to guide. For complete examples, see EmaCross and GridMarketMaker.

Running Rust components

Rust strategies and actors can run through three paths. The examples below use strategies, but the same pattern applies to bundled actors via add_actor (pure Rust) and add_builtin_actor (from Python).

Pure Rust

Write your strategy and main function in Rust, then build a standalone binary with cargo build. This path requires no Python runtime.

rust
let strategy = GridMarketMaker::new(config);
node.add_strategy(strategy)?;
node.run().await?;

See Run Live Trading (Rust) for a full walkthrough.

Built-in examples from Python

Pass a type name and config to add_builtin_strategy to register a built-in example strategy from Python. This path exists to single-source the bundled example strategy code across Rust and Python docs, examples, and tests. It is not a first-class extension path for adding native strategies. For custom native components, use pure Rust or plugin loading.

python
from nautilus_trader.core.nautilus_pyo3.trading import GridMarketMakerConfig

config = GridMarketMakerConfig(
    instrument_id=InstrumentId.from_str("BTC-USDT-SWAP.OKX"),
    max_position=Quantity.from_str("10.0"),
    trade_size=Quantity.from_str("0.1"),
    num_levels=5,
    grid_step_bps=15,
)

node.add_builtin_strategy("GridMarketMaker", config)

Built-in strategy configs:

ConfigStrategy
CompositeMarketMakerConfigCompositeMarketMaker
DeltaNeutralVolConfigDeltaNeutralVol
EmaCrossConfigEmaCross
ExecTesterConfigExecTester
GridMarketMakerConfigGridMarketMaker
HurstVpinDirectionalConfigHurstVpinDirectional

add_builtin_actor follows the same bundled-only rule for actors used by examples and tests.

Built-in actor configs (via add_builtin_actor):

ConfigActor
BookImbalanceActorConfigBookImbalanceActor
DataTesterConfigDataTester

Plugin loading

Use add_plugin or LiveNodeConfig.plugins for Rust components built as cdylib crates. The plug-in manifest supplies the component kind, so the host needs only the library path, manifest type name, and instance config.

Backtesting

For annotated walkthroughs of both APIs, see the Run a Backtest (Rust) how-to guide.

BacktestEngine (low-level API)

Construct the engine, add venues and instruments, load data, register strategies, and run. See the full working example:

bash
cargo run -p nautilus-backtest --features examples --example engine-ema-cross

Source: crates/backtest/examples/engine_ema_cross.rs

BacktestNode (high-level API)

Loads data from a ParquetDataCatalog and supports streaming in configurable chunk sizes. Requires the streaming feature on nautilus-backtest. See the full working example:

bash
cargo run -p nautilus-backtest --features examples,streaming --example node-ema-cross

Source: crates/backtest/examples/node_ema_cross.rs

Live trading

For an annotated walkthrough, see the Run Live Trading (Rust) how-to guide.

The LiveNode connects to real venues through adapter clients. The builder pattern configures data and execution clients, then run() starts the async event loop. Each adapter provides its own factory and config types.

AdapterExample
Architect AXcrates/adapters/architect_ax/examples/
Betfaircrates/adapters/betfair/examples/
Binancecrates/adapters/binance/examples/
BitMEXcrates/adapters/bitmex/examples/
Blockchaincrates/adapters/blockchain/examples/
Bybitcrates/adapters/bybit/examples/
Databentocrates/adapters/databento/examples/
Deribitcrates/adapters/deribit/examples/
dYdXcrates/adapters/dydx/examples/
Hyperliquidcrates/adapters/hyperliquid/examples/
Krakencrates/adapters/kraken/examples/
OKXcrates/adapters/okx/examples/
Polymarketcrates/adapters/polymarket/examples/
Sandboxcrates/adapters/sandbox/examples/
Tardiscrates/adapters/tardis/examples/

Most adapters include node_data_tester.rs and node_exec_tester.rs examples. These test data requests, streaming, and order execution against live venues.