4. FIX协议应用类消息详解
各位同学,今天我们来聊聊FIX协议里最核心、最常用的几个应用类消息。说白了,这些消息就是交易系统之间沟通的「语言」。你想想看,一个订单从发出到成交,中间要经历多少步骤?每一步都需要特定的消息来承载信息。
我个人习惯把应用类消息分成两类:指令消息和回报消息。指令消息是你告诉交易所你想干什么,回报消息是交易所告诉你结果是什么。今天要讲的四个消息,正好覆盖了订单的完整生命周期。
核心知识点:NewOrderSingle(新订单)、ExecutionReport(执行报告)、OrderCancelRequest(撤单请求)、OrderCancelReplaceRequest(撤单并改单请求)
4.1 NewOrderSingle(新订单)—— 一切从这里开始
NewOrderSingle,标签35=D,是FIX协议里最基础的消息。你每次下单,本质上就是在组装这条消息。我记得刚入行时,有个老工程师跟我说:「能把NewOrderSingle写好,FIX协议就算入门了。」当时我不信,后来踩了坑才明白——细节决定成败。
这条消息必须包含的字段,我列个表给你看:
| 标签 | 字段名 | 说明 | 示例值 |
|---|---|---|---|
| 11 | ClOrdID | 客户端订单ID,必须唯一 | ORD20240301001 |
| 54 | Side | 买卖方向:1=买,2=卖 | 1 |
| 38 | OrderQty | 订单数量 | 1000 |
| 40 | OrdType | 订单类型:1=市价,2=限价 | 2 |
| 44 | Price | 价格(限价单必填) | 10.50 |
| 55 | Symbol | 股票代码 | 600519 |
我的经验:ClOrdID这个字段,我建议你用「时间戳+自增序列」的方式生成。曾经有个同事直接用随机数,结果重复了,导致订单被拒绝。嗯,这种低级错误咱们得避免。
来看一个完整的NewOrderSingle消息示例:
8=FIX.4.4|9=145|35=D|34=5|49=CLIENT1|52=20240301-10:30:00.000|56=EXCHANGE|
11=ORD20240301001|21=1|38=1000|40=2|44=10.50|54=1|55=600519|60=20240301-10:30:00.000|
10=123|
这里有个细节要注意:标签21(HandlInst),它决定了订单的执行方式。我个人习惯设成1(自动执行),除非你有特殊需求。
4.2 ExecutionReport(执行报告)—— 交易所的回应
ExecutionReport,标签35=8,是交易所给你反馈的消息。说白了,你发出去的每个指令,交易所都会用这条消息告诉你结果。我见过不少新手,只关注新订单,却忽略了执行报告的处理,结果订单状态都搞不清楚。
执行报告里最重要的字段是39(OrdStatus),它告诉你订单当前的状态:
| 状态码 | 含义 | 说明 |
|---|---|---|
| 0 | New | 订单已接收,等待处理 |
| 1 | PartiallyFilled | 部分成交 |
| 2 | Filled | 全部成交 |
| 4 | Canceled | 已撤销 |
| 8 | Rejected | 被拒绝 |
注意:同一个订单可能会收到多条ExecutionReport。比如一个限价单,可能先收到New状态,然后PartiallyFilled,最后Filled。你的系统必须能处理这种「多次回报」的情况。
我曾经在一个项目中,发现系统只处理了Filled状态,忽略了PartiallyFilled。结果呢?订单只成交了一半,系统却以为没成交,又发了一个撤单请求。嗯,那天的对账真是惨不忍睹。
4.3 OrderCancelRequest(撤单请求)—— 后悔药怎么吃
OrderCancelRequest,标签35=F。说白了,就是你想撤销一个还没成交的订单。但注意,不是所有订单都能撤。已经全部成交的订单,你发撤单请求只会被拒绝。
撤单请求必须包含的字段:
- 11(ClOrdID):新的客户端ID,用于标识这次撤单请求
- 41(OrigClOrdID):原始订单的ClOrdID,告诉交易所你要撤哪个单
- 55(Symbol):股票代码,双重确认
来看示例:
8=FIX.4.4|9=120|35=F|34=6|49=CLIENT1|52=20240301-10:31:00.000|56=EXCHANGE|
11=CXL20240301001|41=ORD20240301001|55=600519|
10=456|
这里有个坑:OrigClOrdID必须和原始订单的ClOrdID完全一致。我见过有人把大小写搞混了,结果撤单失败。FIX协议是大小写敏感的,切记。
4.4 OrderCancelReplaceRequest(撤单并改单)—— 更优雅的方式
OrderCancelReplaceRequest,标签35=G。这个功能很实用——你想改订单的价格或数量,不用先撤再发,一条消息搞定。
但要注意,不是所有字段都能改。一般来说,可以改价格(44)和数量(38),但不能改买卖方向(54)和股票代码(55)。
改单请求的关键字段:
- 11(ClOrdID):新的客户端ID
- 41(OrigClOrdID):原始订单的ClOrdID
- 38(OrderQty):新的数量
- 44(Price):新的价格
我的建议:改单操作其实包含两个步骤:先撤单,再发新单。交易所内部是原子操作,但你的系统要做好「改单失败」的准备。我曾经遇到改单请求被拒绝,原始订单却已经被撤销了——嗯,这种边缘情况你得处理。
来看改单示例:
8=FIX.4.4|9=135|35=G|34=7|49=CLIENT1|52=20240301-10:32:00.000|56=EXCHANGE|
11=MOD20240301001|41=ORD20240301001|38=2000|44=10.80|55=600519|
10=789|
4.5 消息交互的完整流程
把这四个消息串起来,就是一个完整的订单生命周期:
- 你发NewOrderSingle,交易所回ExecutionReport(New)
- 订单部分成交,交易所回ExecutionReport(PartiallyFilled)
- 你想改价格,发OrderCancelReplaceRequest
- 交易所处理改单,回ExecutionReport(Canceled)和ExecutionReport(New)
- 最终全部成交,交易所回ExecutionReport(Filled)
你看,每一步都有对应的消息。我个人习惯在系统里维护一个订单状态机,把每个订单的当前状态记录下来。这样不管收到什么消息,都能快速判断是否合法。
核心要点回顾:
- NewOrderSingle(35=D):发新订单,ClOrdID必须唯一
- ExecutionReport(35=8):交易所的反馈,关注OrdStatus
- OrderCancelRequest(35=F):撤单,OrigClOrdID要准确
- OrderCancelReplaceRequest(35=G):改单,注意字段限制
好了,这四种消息就讲到这里。说白了,FIX协议的消息设计很巧妙,每条消息都有明确的职责。你只要理解了它们的交互逻辑,写代码的时候心里就有底了。
公众号:蓝海资料掘金营,微信deep3321