4. 订单路由核心消息

在FIX协议订单路由链路中,真正承载“下单、撤单、改单、查单”四类核心动作的消息只有四条:NewOrderSingle(D)、OrderCancelRequest(F)、OrderCancelReplaceRequest(G)、OrderStatusRequest(H)。它们分别对应交易生命周期中的创建、终止、修改与查询四个关键节点。理解这四条消息的字段语义与使用边界,是构建稳定路由层的基础。

核心记忆口诀:D 建仓、F 撤单、G 改单、H 查单。四者共享 ClOrdID、OrderID、Symbol、Side 等关键字段,但触发条件与必填字段差异显著。

一、核心原理:四条消息在订单生命周期中的位置

订单从进入路由系统到最终终结,会经历“新建→可能修改→可能撤销→状态确认”的路径。NewOrderSingle 是唯一能创建订单的消息;OrderCancelReplaceRequest 在修改价格或数量的同时保留原订单的“血缘”;OrderCancelRequest 只做终止;OrderStatusRequest 不改变订单状态,仅拉取当前快照。四者并非并列关系,而是围绕同一订单实体在不同阶段被调用。

订单生命周期与四条核心消息的触发位置 新建 已报/部分成交 修改 终结/查询 NewOrderSingle MsgType = D OrderStatusRequest MsgType = H OrderCancelReplace MsgType = G OrderCancelRequest MsgType = F D 创建订单 → G 在原订单上修改 → F 终止订单 → H 随时查询状态

二、字段含义与使用场景对照

四条消息的字段设计遵循“最小必要”原则:D 需要完整订单要素,F 只需定位原订单,G 需要定位原订单并给出新参数,H 只需定位原订单。下表列出各消息的关键字段与典型场景。

消息 MsgType 关键必填字段 典型使用场景
NewOrderSingle D ClOrdID、Symbol、Side、OrdType、Price、OrderQty、TransactTime 策略首次发出买入/卖出指令,路由层向交易所或上游通道新建订单
OrderCancelRequest F OrigClOrdID、ClOrdID、Symbol、Side、TransactTime 行情反转或策略信号消失,需要立即撤销未成交的挂单
OrderCancelReplaceRequest G OrigClOrdID、ClOrdID、Symbol、Side、OrdType、Price、OrderQty 追价、改量、调整止损价,在不丢失订单优先级的前提下修改订单
OrderStatusRequest H ClOrdID 或 OrderID、Symbol、Side 回报延迟、断线重连后确认订单是否仍在交易所、是否已成交

三、方法流程:一次完整的改单与查单操作

以“追价改单”为例,策略先发出 D 建立订单,随后行情上涨,需要将买价从 10.00 改为 10.05。此时不能重新发 D,而应发 G,并在 OrigClOrdID 中填入原订单的 ClOrdID。交易所收到 G 后,会先撤销原订单再以新价格重新挂单,但对外仍视为同一订单的修改。若改单后回报迟迟未到,可发 H 查询当前状态。

# 原始下单(D)
8=FIX.4.4|35=D|11=ORD-20240520-001|55=600519|54=1|40=2|44=10.00|38=1000|60=20240520-09:30:00|

# 追价改单(G)
8=FIX.4.4|35=G|41=ORD-20240520-001|11=ORD-20240520-002|55=600519|54=1|40=2|44=10.05|38=1000|60=20240520-09:31:12|

# 状态查询(H)
8=FIX.4.4|35=H|11=ORD-20240520-002|55=600519|54=1|
注意:G 消息中的 ClOrdID 必须是新的唯一值,而 OrigClOrdID 指向被修改的原订单。若两者混淆,交易所会拒绝改单并返回 OrdRejReason。

四、误区与复盘:四条消息的常见踩坑点

  • 用 D 代替 G 改单:重新发 D 会创建新订单,原订单仍然挂在市场上,导致重复下单和仓位翻倍。
  • F 与 G 的 OrigClOrdID 缺失:撤单和改单必须携带 OrigClOrdID,否则交易所无法定位原订单,直接拒单。
  • H 被当作主动撤单:OrderStatusRequest 只查询状态,不改变订单,误用会导致该撤的订单未撤。
  • ClOrdID 重复:四条消息的 ClOrdID 在同一会话中必须唯一,重复会被视为重复请求而拒绝。
  • 忽略 TransactTime:部分交易所要求 D、F、G 必须携带精确到毫秒的 TransactTime,缺失会导致时间校验失败。
复盘建议:在路由层为每条消息建立字段校验清单,重点检查 OrigClOrdID 是否存在、ClOrdID 是否唯一、Symbol 与 Side 是否与原订单一致。任何一项不匹配,都应在发送前拦截,而不是等交易所拒单后再补救。

掌握这四条消息的字段语义与调用边界后,订单路由层就能在“建、撤、改、查”四个动作上做到精准可控。实际开发中,建议将四条消息的构造逻辑封装为独立方法,并在日志中完整记录 MsgType、ClOrdID、OrigClOrdID 与 TransactTime,以便在回报异常时快速定位是消息构造问题还是通道问题。