ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

NautilusTrader 订单提交事件 OrderSubmitted 完全指南:状态机、字段解析与策略处理

NautilusTrader 订单提交事件 OrderSubmitted 完全指南:状态机、字段解析与策略处理 NautilusTrader 订单提交事件 OrderSubmitted 完全指南状态机、字段解析与策略处理【免费下载链接】nautilus_traderProduction-grade Rust-native trading engine with deterministic event-driven architecture项目地址: https://gitcode.com/GitHub_Trending/na/nautilus_traderOrderSubmitted是 NautilusTrader 事件驱动执行管道中连接本地订单状态与交易所反馈的关键节点——它标志着系统已将订单正式发送至交易场所正处于等待交易所确认acknowledgement的在途in-flight状态。本文围绕该事件深入讲解其触发时机、状态迁移、字段语义、策略侧处理方法并结合仓库 Rust 源码事件模型定义、撮合引擎生成逻辑与 Python 类型桩trading 类型桩验证其底层实现帮助读者在回测与实盘场景中正确使用on_order_submitted处理器。事件语义什么叫做订单已提交根据官方事件文档OrderSubmitted表示系统已将订单提交给交易场所trading venue这一动作。它的完整处理链路是ExecutionEngine执行引擎将事件应用到订单对象上更新Cache缓存中的订单状态通过MessageBus消息总线将事件发布给订阅方包括策略。该事件触发的时机是系统向交易场所发出订单、并等待交易所回执确认的这段时间。换言之此刻订单已离开本地准备区进入交易所的受理队列但尚未得到交易所已受理且有效的答复那是OrderAccepted的职责。Rust 源码中该事件模型的文档注释与此完全一致crates/model/src/events/order/submitted.rs#L36-L38Represents an event where an order has been submitted by the system to the trading venue.从状态机角度OrderStatus::Submitted在 enums.rs 中被定义为The order was submitted by the Nautilus system to the external service or trading venue (awaiting acknowledgement).并且有一处极易被忽略但非常重要的语义细节Submitted属于在途状态而非生效working状态。源码在is_open()的注释中特别提醒crates/model/src/enums.rs#L1338-L1343is_open()用于判断订单在交易所是否处于生效挂单状态它显式排除了Submitted当对账reconciliation时交易所把某个挂单报告映射为Submitted如果只用is_open()过滤会静默丢失该订单必须使用is_open() || is_inflight()的组合判断。这是OrderSubmitted区别于OrderAccepted的核心前者是单向已发出、未确认后者才是交易所的正式受理确认。状态迁移INITIALIZED / RELEASED - SUBMITTED文档给出的典型迁移路径为INITIALIZED / RELEASED - SUBMITTED结合 Events 索引文档 中的完整订单事件状态流表格可以看到OrderSubmitted在整个订单生命周期中处于第一道对外关口事件主要状态迁移处理器OrderInitialized创建/物化订单on_order_initializedOrderDeniedInitialized - Deniedon_order_deniedOrderEmulatedInitialized - Emulatedon_order_emulatedOrderReleasedEmulated - Releasedon_order_releasedOrderSubmittedInitialized/Released - Submittedon_order_submittedOrderAcceptedSubmitted - Acceptedon_order_acceptedOrderRejectedSubmitted - Rejectedon_order_rejected.........从这张表可以看出两条进入Submitted的路径对应两种交易模式直接提交订单在本地初始化INITIALIZED后直接提交至交易所模拟emulation后提交订单先进入OrderEmulator组件被模拟EMULATED释放RELEASED后再提交至交易所。而Submitted之后的去向则由交易所决定可能是OrderAccepted受理成功、OrderRejected被拒也可能因网络或场所问题一直停留在该状态等待超时处理。引擎中事件的实际生成位置在回测/撮合场景中OrderSubmitted由MatchingEngine撮合引擎生成。源码中generate_order_submitted方法crates/execution/src/matching_engine/mod.rs#L6381-L6394清晰地展示了事件的构造过程fn generate_order_submitted(self, order: OrderAny, account_id: AccountId) { let ts_now self.clock.borrow().timestamp_ns(); let event OrderEventAny::Submitted(OrderSubmitted::new( order.trader_id(), order.strategy_id(), order.instrument_id(), order.client_order_id(), account_id, UUID4::new(), ts_now, ts_now, )); self.dispatch_order_event(event); }可以看到ts_event与ts_init在生成时均取当前时钟的纳秒时间戳ts_nowevent_id使用UUID4::new()实时生成事件经dispatch_order_event进入执行管道随后被应用到订单、写入Cache并发布到MessageBus。在撮合引擎处理新订单提交流程中generate_order_submitted与generate_order_accepted连续被调用matching_engine/mod.rs#L2751-L2752即撮合场景下提交后立刻受理而在实盘环境中两个事件之间的间隔取决于交易所网络往返时延。另外注意 order_manager/manager.rs 的说明对于订单管理器order manager而言OrderSubmitted这类事件是 no-op空操作真正驱动订单状态机的是OrderManager层的其他处理逻辑。字段解析在公共字段之外OrderSubmitted 还携带什么OrderSubmitted继承所有 Python 订单事件共有的字段详见 Events 索引文档字段说明trader_idTrader 实例标识符strategy_id与该订单关联的策略标识符instrument_id该订单的合约/标的标识符client_order_id客户端分配的订单标识符event_id事件唯一标识符ts_event事件发生时的 UNIX 纳秒时间戳ts_init事件初始化时的 UNIX 纳秒时间戳causation_id导致该事件的源事件或报告如已知在此之上OrderSubmitted类型专属字段只有一个字段Python 类型是否必需/默认值说明account_idAccountId必需与该订单关联的账户account_id用于将订单归属到具体交易账户从而支持多账户场景下账户维度的对账、风险与持仓核算。这一点在 Rust 结构体定义中得到印证crates/model/src/events/order/submitted.rs#L49-L69OrderSubmitted除公共字段外仅含account_id: AccountId一个业务字段。与其他订单事件的字段对比一个值得注意的对比是OrderSubmitted没有venue_order_id交易所订单号。原因是显而易见的——事件发生时订单刚被送出、交易所尚未回执自然还不存在交易所分配的订单标识符。这一点在 Events 索引文档 中有明确说明venue_order_id、account_id、reconciliation等字段只出现在暴露它们的 Python 事件类上。例如OrderAccepted会新增venue_order_idOrderFilled会新增last_qty、last_px、trade_id与commission。Rust 侧的OrderEventtrait 实现也印证了这一设计submitted.rs#L280-L286venue_order_id()返回None而account_id()返回Some(self.account_id)。策略处理on_order_submitted 处理器在策略中读取该事件的推荐写法来自官方文档示例def on_order_submitted(self, event: OrderSubmitted) - None: self.log.info(fOrder {event.client_order_id} submitted ({event.account_id}))在策略回调签名层面Python 类型桩文件python/nautilus_trader/trading/init.pyi#L447给出了on_order_submitted的准确签名def on_order_submitted(self, event: model.OrderSubmitted) - None: ...处理器分发顺序根据 Events 索引文档 的分发规则当订单事件到达策略时系统按固定顺序调用处理器具体处理器如on_order_submitted先执行聚合处理器on_order_event接收所有订单事件后执行。这意味着你既可以在单个事件粒度上处理也可以在所有订单事件的聚合层面统一处理两者可以并存。例如若要在策略中对所有订单事件做统一日志或监控def on_order_event(self, event: OrderEvent) - None: # 所有订单事件都会经过这里包括 OrderSubmitted self.log.info(fOrder event: {event})处理器中能做什么、不能做什么基于事件语义可以给出如下实践建议适合做记录订单提交日志与时间戳ts_event基于account_id做账户维度分流启动提交超时监控若一段时间内未收到OrderAccepted/OrderRejected可视为提交异常不适合做依赖venue_order_id此时尚不存在将Submitted当作已在交易所生效来触发后续逻辑——状态机要求等到OrderAccepted才表示受理成功。从源码结构看OrderSubmitted在OrderEventtrait 中大量字段访问器如order_type()、price()、quantity()、venue_order_id()等均返回Nonesubmitted.rs#L140-L294说明该事件是轻量的纯状态通告事件不携带价格、数量、成交信息等业务载荷字段语义高度聚焦于订单已送出 归属账户。序列化与持久化OrderSubmitted实现了完整的 Rust 序列化支持结构体上标注了Serialize/Deserialize派生submitted.rs#L39-L40并带有#[serde(tag type)]标签使序列化 JSON 中包含type: OrderSubmitted字段便于多态反序列化。仓库中的单元测试验证了 JSON 序列化-反序列化往返一致性submitted.rs#L338-L346let json serde_json::to_string(original).unwrap(); let deserialized: OrderSubmitted serde_json::from_str(json).unwrap(); assert_eq!(original, deserialized);这意味着该事件可安全地落入事件溯源event sourcing存储或消息队列用于回放重建订单状态。此外序列化 schema 定义位于 crates/serialization/schemas/capnp/events/order.capnpCapn Proto 编码同样覆盖该事件类型。Debug与Display输出格式也值得注意submitted.rs#L117-L129Display紧凑格式为OrderSubmitted(instrument_id..., client_order_id..., account_id..., ts_event...)与日志中常见的OrderAccepted、OrderFilled等事件的格式风格一致便于统一解析。与相邻事件的关系理解OrderSubmitted最好的方式是在事件序列中定位它。一次成功的直接下单流程其事件链大致为OrderInitialized - OrderSubmitted - OrderAccepted - OrderFilled可能伴随 PartiallyFilledOrderInitialized订单在 Nautilus 系统内被实例化本地状态OrderSubmitted订单被送出至交易所本文主题在途等待确认OrderAccepted交易所确认收到且有效进入 working 状态开始具备venue_order_idOrderRejected交易所拒绝与Accepted二选一OrderFilled成交后续事件。若涉及模拟交易则链为OrderInitialized - OrderEmulated - OrderReleased - OrderSubmitted - ...。值得再次强调状态语义差异详见 enums.rs 中 is_open 注释Submitted处于 in-flight 状态、不视为 working因此在任何过滤工作订单的逻辑中如对账、风控扫描、撤单检查务必使用is_open() || is_inflight()组合而不是单独调用is_open()。相关指南Events事件分类、分发机制与公共订单事件字段Orders订单类型与完整状态机含部分成交、外部单、触发单等附加迁移Positions持仓生命周期与 PnL 核算Execution执行流程与风险检查Strategies策略中各处理器的实现方式Architecture数据流与执行流模式。小结OrderSubmitted是 NautilusTrader 订单状态机中连接本地系统与外部交易场所的第一道关口语义上代表已送出、待确认。它只携带account_id一个专属字段配合公共事件字段即可完成账户归属与状态通告策略侧通过on_order_submitted或聚合的on_order_event处理该事件适合做提交日志、超时监控等轻量逻辑而不应把它误当作交易所受理确认。无论是回测中的撮合引擎生成matching_engine/mod.rs#L6381还是实盘中的执行客户端回执这一事件都遵循相同的语义提交 ≠ 受理Submitted之后才是Accepted或Rejected。【免费下载链接】nautilus_traderProduction-grade Rust-native trading engine with deterministic event-driven architecture项目地址: https://gitcode.com/GitHub_Trending/na/nautilus_trader创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进