4. 数据模型与数据类型
在 NautilusTrader 中,回测与实盘共用同一套数据模型,这是它区别于许多“回测一套、实盘另一套”框架的核心优势。理解 QuoteTick、TradeTick、Bar、OrderBookDelta 这四类数据的结构、用途与转换关系,是写出可复用策略、避免回测失真和实盘异常的前提。本节从数据模型的设计意图出发,逐层拆解它们的字段、适用场景与相互转换方法。
一、核心原理:为什么需要多种数据类型
市场信息本身是多层次的:最细粒度是订单簿的每一次增删改,其次是逐笔成交与最优买卖报价,再往上是按时间窗口聚合的 K 线。NautilusTrader 用不同的数据类型分别承载这些层次,而不是用单一结构“一把梭”。这样做的原因是:数据精度决定策略能感知到的信息边界。一个只依赖 Bar 的策略无法看到盘口挂单变化,而一个做市策略必须依赖 OrderBookDelta 才能重建订单簿。
所有数据类型都继承自统一的数据基类,携带 instrument_id、ts_event(事件发生时间)和 ts_init(系统初始化时间)等公共字段。理解 ts_event 与 ts_init 的区别非常关键:前者是交易所时间戳,后者是本地接收时间戳,回测中二者通常一致,实盘中二者可能相差数毫秒甚至更多,直接影响延迟敏感策略的表现。
二、四类数据的结构与用途
QuoteTick 表示某一时刻的最优买卖报价,核心字段为 bid_price、ask_price、bid_size、ask_size。它适合做价差监控、盘口强度判断和基于报价的挂单策略。注意 QuoteTick 只反映最优档,不包含深度信息。
TradeTick 表示一笔实际成交,字段包括 price、size 和 aggressor_side(主动方方向)。主动方方向是判断买卖压力的关键:主动买盘推高价格,主动卖盘压低价格。做量价分析和订单流策略时,TradeTick 是基础数据。
Bar 是时间窗口聚合结果,包含 open、high、low、close、volume,并带有 bar_type 描述周期与价格类型(如 EUR/USD.SIM-1-MINUTE-BID-EXTERNAL)。Bar 数据量小、计算快,适合趋势、均值回归等中低频策略。
OrderBookDelta 描述订单簿的增量变化,字段包括 action(ADD/UPDATE/DELETE)、side、price、size 和 order_id。它是重建完整订单簿的唯一途径,适合做市、高频套利和微观结构研究。
| 数据类型 | 核心字段 | 典型用途 | 数据量级 |
|---|---|---|---|
| QuoteTick | bid/ask price & size | 价差监控、报价驱动挂单 | 高 |
| TradeTick | price, size, aggressor_side | 量价分析、订单流 | 高 |
| Bar | OHLCV, bar_type | 趋势、均值回归策略 | 低 |
| OrderBookDelta | action, side, price, size | 做市、高频、微观结构 | 极高 |
三、数据转换方法与实操
NautilusTrader 提供了内置的聚合器,可以把细粒度数据转换为粗粒度数据。最常见的是用 QuoteTick 或 TradeTick 聚合出 Bar。以下代码演示如何配置一个基于 TradeTick 的 1 分钟 Bar 聚合器:
from nautilus_trader.config import BarAggregatorConfig
from nautilus_trader.model.data import BarType, BarAggregation
bar_type = BarType.from_str("EUR/USD.SIM-1-MINUTE-LAST-EXTERNAL")
config = BarAggregatorConfig(
bar_type=bar_type,
aggregation=BarAggregation.MINUTE,
price_type="LAST", # 使用最新成交价
interval=1,
)
# 在策略中订阅 TradeTick 后,聚合器会自动生成 Bar
self.subscribe_trade_ticks(instrument_id)
self.subscribe_bars(bar_type)
反向转换并不总是可行:Bar 无法还原出逐笔成交,QuoteTick 也无法还原完整订单簿。因此数据精度只能向下聚合,不能向上还原。这一点在回测数据选择时至关重要——如果你用 Bar 回测一个依赖盘口深度的策略,结果必然失真。
四、常见误区与复盘
- 误区一:混用 ts_event 与 ts_init。回测中二者常被当作相同值,但实盘中 ts_init 晚于 ts_event。若策略逻辑依赖时间差,回测会低估延迟影响。
- 误区二:认为 Bar 可以替代 Tick。Bar 丢失了窗口内的价格路径,止损触发点、滑点估算都会失真。
- 误区三:忽略 aggressor_side。只看成交价和成交量,会丢失买卖主动方信息,订单流策略无法成立。
- 误区四:OrderBookDelta 不做快照对齐。增量数据必须从某个快照开始重建,否则订单簿状态错误。