架构
欢迎来到 NautilusTrader 的架构概览。
本指南深入探讨支撑平台的基础原理、结构和设计。无论您是开发者、系统架构师,还是只是对 NautilusTrader 的内部工作原理感兴趣,本节涵盖:
- 驱动决策并塑造系统演进的设计理念
- 提供整个系统框架鸟瞰图的总体系统架构
- 框架如何组织以促进模块化和可维护性
- 确保可读性和可扩展性的代码结构
- 组件组织和交互的详细分析,以了解不同部分如何通信和协作
- 最后,对性能、可靠性和健壮性至关重要的实现技术
在整个文档中,术语*"Nautilus 系统边界"*指的是单个 Nautilus 节点(也称为"交易者实例")运行时内的操作。
设计理念
NautilusTrader 采用的主要架构技术和设计模式包括:
- 领域驱动设计 (DDD)
- 事件驱动架构
- 消息传递模式(发布/订阅、请求/响应、点对点)
- 端口和适配器
- 仅崩溃设计
这些技术被用来帮助实现某些架构质量属性。
质量属性
架构决策通常是竞争优先级之间的权衡。以下是在做出设计和架构决策时考虑的一些最重要的质量属性列表,大致按"权重"排序:
- 可靠性
- 性能
- 模块化
- 可测试性
- 可维护性
- 可部署性
系统架构
NautilusTrader 代码库实际上既是用于组合交易系统的框架,也是一组可以在各种环境上下文中运行的默认系统实现。
核心架构组件
NautilusTrader 的核心架构基于以下主要组件:
1. 交易节点 (Trading Node)
- 系统的主要入口点和协调器
- 管理所有其他组件的生命周期
- 提供统一的配置和控制接口
2. 消息总线 (Message Bus)
- 系统内所有通信的中央枢纽
- 实现发布/订阅和请求/响应模式
- 确保组件之间的松耦合
3. 数据引擎 (Data Engine)
- 处理所有市场数据的接收和分发
- 管理数据订阅和缓存
- 提供统一的数据访问接口
4. 执行引擎 (Execution Engine)
- 处理所有交易执行相关操作
- 管理订单生命周期
- 与交易所适配器交互
5. 风险引擎 (Risk Engine)
- 实时风险监控和控制
- 预交易和后交易风险检查
- 头寸和资金管理
6. 策略引擎 (Strategy Engine)
- 管理交易策略的执行
- 提供策略生命周期管理
- 处理策略间的协调
架构图
┌─────────────────────────────────────────────────────────────────┐
│ Trading Node │
├─────────────────────────────────────────────────────────────────┤
│ Message Bus │
├─────────────────┬─────────────────┬─────────────────┬───────────┤
│ Data Engine │ Execution Engine│ Risk Engine │ Strategy │
│ │ │ │ Engine │
├─────────────────┼─────────────────┼─────────────────┼───────────┤
│ Data Cache │ Order Cache │ Risk Manager │ Portfolio │
│ │ │ │ Manager │
├─────────────────┴─────────────────┴─────────────────┴───────────┤
│ Adapters │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │
│ │ Binance │ │ Bybit │ │ IB │ │ ... │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └───────────┘ │
└─────────────────────────────────────────────────────────────────┘
Core Components
The platform is built around several key components that work together to provide a comprehensive trading system:
NautilusKernel
The central orchestration 组件 responsible for:
- Initializing and managing all system components.
- Configuring the messaging infrastructure.
- Maintaining 环境-specific behaviors.
- Coordinating shared resources and lifecycle management.
- Providing a unified entry point for system operations.
MessageBus
The backbone of inter-组件 communication, implementing:
- Publish/Subscribe patterns: For broadcasting events and data to multiple consumers.
- Request/Response communication: For operations requiring acknowledgment.
- Command/Event messaging: For triggering actions and notifying state changes.
- Optional state persistence: Using Redis for durability and restart capabilities.
缓存
高性能 in-内存 存储 system that:
- Stores 金融工具, accounts, 订单, 头寸, and more.
- Provides performant fetching capabilities for trading components.
- Maintains consist state across the system.
- Supports both read and write operations with optimized access patterns.
DataEngine
Processes and routes market 数据 throughout the system:
- Handles multiple 数据 types (quotes, trades, bars, order books, custom 数据, and more).
- Routes 数据 to appropriate consumers based on subscriptions.
- Manages 数据 flow from external sources to internal components.
ExecutionEngine
Manages order lifecycle and 执行:
- Routes trading commands to the appropriate adapter clients.
- Tracks order and position states.
- Coordinates with 风险管理 systems.
- Handles 执行 报告 and fills from venues.
- Handles reconciliation of external 执行 state.
RiskEngine
Provides comprehensive 风险管理:
- Pre-trade risk checks and 验证.
- Position and exposure 监控.
- 实时 risk calculations.
- Configurable risk rules and limits.
环境 Contexts
An 环境 context in NautilusTrader defines the type of 数据 and trading venue you are working with. Understanding these contexts is crucial for effective 回测, 开发, and 实时交易.
Here are the available environments you can work with:
Backtest
: Historical data with simulated venues.Sandbox
: Real-time data with simulated venues.Live
: Real-time data with live venues (paper trading or real accounts).
Common Core
The platform has been designed to share as much common code between backtest, sandbox and 实时交易 systems as possible.
This is formalized in the system
subpackage, where you will find the NautilusKernel
class,
providing a common core system 'kernel'.
The ports and 适配器 architectural style enables modular components to be integrated into the core system, providing various hooks for user-defined or custom 组件 implementations.
数据 and 执行 Flow Patterns
Understanding how 数据 and 执行 flow through the system is crucial for effective use of the platform:
数据 Flow Pattern
- External Data Ingestion: Market data enters via venue-specific
DataClient
adapters where it is normalized. - Data Processing: The
DataEngine
handles data processing for internal components. - Caching: Processed data is stored in the high-performance
Cache
for fast access. - Event Publishing: Data events are published to the
MessageBus
. - Consumer Delivery: Subscribed components (Actors, Strategies) receive relevant data events.
执行 Flow Pattern
- Command Generation: User strategies create trading commands.
- Command Publishing: Commands are sent through the
MessageBus
. - Risk Validation: The
RiskEngine
validates trading commands against configured risk rules. - Execution Routing: The
ExecutionEngine
routes commands to appropriate venues. - External Submission: The
ExecutionClient
submits orders to external trading venues. - Event Flow Back: Order events (fills, cancellations) flow back through the system.
- State Updates: Portfolio and position states are updated based on execution events.
组件 State Management
All components follow a finite state machine pattern with well-defined states:
- PRE_INITIALIZED: Component is created but not yet wired up to the system.
- READY: Component is configured and wired up, but not yet running.
- RUNNING: Component is actively processing messages and performing operations.
- STOPPED: Component has been gracefully stopped and is no longer processing.
- DEGRADED: Component is running but with reduced functionality due to errors.
- FAULTED: Component has encountered a critical error and cannot continue.
- DISPOSED: Component has been cleaned up and resources have been released.
Messaging
To facilitate modularity and loose coupling, an extremely efficient MessageBus
passes messages (数据, commands and events) between components.
From a high level architectural view, it's important to understand that the platform has been designed to run efficiently on a single thread, for both 回测 and 实时交易. Much research and 测试 resulted in arriving at this design, as it was found the overhead of context switching between threads didn't actually result in improved 性能.
When considering the logic of how your algo trading will work within the system boundary, you can expect each 组件 to consume messages in a deterministic synchronous way (similar to the actor model).
Of interest is the LMAX exchange 架构, which achieves award winning 性能 running on a single thread. You can read about their disruptor pattern based architecture in this interesting article by Martin Fowler.
框架 organization
The codebase is organized with a layering of abstraction levels, and generally grouped into logical subpackages of cohesive 核心概念. You can navigate to the 文档 for each of these subpackages from the left nav menu.
Core / low-Level
core
: Constants, functions and low-level components used throughout the framework.common
: Common parts for assembling the frameworks various components.network
: Low-level base components for networking clients.serialization
: Serialization base components and serializer implementations.model
: Defines a rich trading domain model.
Components
accounting
: Different account types and account management machinery.adapters
: Integration adapters for the platform including brokers and exchanges.analysis
: Components relating to trading performance statistics and analysis.cache
: Provides common caching infrastructure.data
: The data stack and data tooling for the platform.execution
: The execution stack for the platform.indicators
: A set of efficient indicators and analyzers.persistence
: Data storage, cataloging and retrieval, mainly to support backtesting.portfolio
: Portfolio management functionality.risk
: Risk specific components and tooling.trading
: Trading domain specific components and tooling.
System implementations
backtest
: Backtesting componentry as well as a backtest engine and node implementations.live
: Live engine and client implementations as well as a node for live trading.system
: The core system kernel common betweenbacktest
,sandbox
,live
environment contexts.
Code structure
The foundation of the codebase is the crates
directory, containing a collection of core Rust crates including a C foreign function 接口 (FFI) generated by cbindgen
.
The bulk of the 生产 code resides in the nautilus_trader
directory, which contains a collection of Python/Cython subpackages and modules.
Python bindings for the Rust core are provided by statically linking the Rust libraries to the C 扩展 modules generated by Cython at compile time (effectively extending the CPython API).
Dependency flow
┌─────────────────────────┐
│ │
│ │
│ nautilus_trader │
│ │
│ Python / Cython │
│ │
│ │
└────────────┬────────────┘
C API │
│
│
│
C API ▼
┌─────────────────────────┐
│ │
│ │
│ nautilus_core │
│ │
│ Rust │
│ │
│ │
└─────────────────────────┘
Both Rust and Cython are build 依赖. The binary wheels produced from a build do not require Rust or Cython to be installed at runtime.
Type safety
The design of the platform prioritizes software correctness and safety at the highest level.
The Rust codebase in nautilus_core
is always type safe and 内存 safe as guaranteed by the rustc
compiler,
and so is correct by construction (unless explicitly marked unsafe
, see the Rust section of the Developer Guide).
Cython provides type safety at the C level at both compile time, and runtime:
If you pass an argument with an invalid type to a Cython implemented 模块 with typed parameters,
then you will receive a TypeError
at runtime.
If a function or method's parameter is not explicitly typed to accept None
, passing None
as an
argument will result in a ValueError
at runtime.
The above exceptions are not explicitly documented to prevent excessive bloating of the docstrings.
Errors and exceptions
Every attempt has been made to accurately document the possible exceptions which can be raised from NautilusTrader code, and the conditions which will trigger them.
There may be other undocumented exceptions which can be raised by Pythons standard 库, or from third party 库 依赖.
Processes and threads
For optimal 性能 and to prevent potential issues related to Python's 内存 model and equality, it is highly recommended to run each trader instance in a separate process.