3、明池路由基础:交易所连接、FIX协议入门、订单生命周期

好,咱们进入正题。

明池路由,说白了就是你的订单怎么光明正大地走到交易所去。暗池是黑箱,明池就是透明柜台。你想想看,一个订单从你敲下回车,到最终成交,中间经历了什么?这背后就是交易所连接、FIX协议、还有订单生命周期这三件事。

3.1 交易所连接:不只是TCP长连接

很多人以为连交易所就是开个socket发数据。嗯,没那么简单。

我个人习惯把交易所连接分成三层:

  • 传输层:TCP长连接,心跳保活,断线重连
  • 会话层:登录认证,序列号管理,消息确认
  • 业务层:订单收发,行情订阅,风险控制

我在项目中遇到过最坑的事——某次交易所升级,把心跳间隔从30秒改成了15秒,我们的老代码没跟上,结果每天下午准时断线。排查了三天才发现是心跳超时。

避坑指南:我曾经因为没处理好断线重连的序列号,导致重复下单,被风控部门请去喝茶。记住:重连后一定要做序列号同步。

3.2 FIX协议入门:金融界的HTTP

FIX协议,全称Financial Information eXchange。说白了,就是交易所和交易员之间说好的「黑话」。

一个典型的FIX消息长这样:

8=FIX.4.2|9=78|35=D|49=CLIENT1|56=EXCHANGE|34=1|52=20240101-00:00:00|11=ORD001|55=600519|54=1|38=100|44=200.50|10=123|

看着乱?我拆开给你看:

标签 含义 示例值
8 协议版本 FIX.4.2
35 消息类型 D(新订单)
55 证券代码 600519(茅台)
54 买卖方向 1(买)
38 数量 100股
44 价格 200.50元

你可能会问:为什么不用JSON?因为FIX诞生在90年代,那时候带宽金贵,一个字节都不能浪费。现在虽然带宽不是问题,但FIX已经成为行业标准,改不动了。

个人经验:我建议新手先别急着写FIX解析器。直接用现成的库,比如QuickFIX/C++或者Python的simplefix。自己手写?我曾经干过这事,结果被各种边界条件折磨到怀疑人生。

3.3 订单生命周期:从摇篮到坟墓

一个订单从出生到死亡,大概经历这么几个阶段:

  1. 创建:你填好价格、数量、方向,点击发送
  2. 验证:交易所检查你的账户余额、风控规则
  3. 排队:进入订单簿,等待撮合
  4. 成交:和对手单匹配,部分或全部成交
  5. 撤销:你主动取消,或者交易所帮你取消
  6. 过期:当日有效订单收盘后自动失效

这里有个关键点——订单状态机。我见过太多人把状态机画成一条直线,实际上它是带环的图。

核心要点:订单状态转换必须幂等。同一个成交回报收到两次,不能导致重复成交。我曾经因为没处理好这个,让系统多买了1000股,那叫一个酸爽。

下面这张图,是我自己项目里用的订单状态机,你感受一下:

新建 已确认 部分成交 全部成交 已撤销 已拒绝 确认 部分成交 剩余成交 撤销 拒绝 撤销确认 订单状态机(简化版)

你看,状态之间不是单向的。比如「部分成交」之后,还可以继续成交,也可以撤销剩余部分。我当年第一次画这个图,画成了线性结构,结果上线第一天就出了bug——部分成交后撤销,系统直接崩溃了。

3.4 实战中的那些坑

最后分享几个我踩过的坑:

  • 序列号跳跃:FIX协议要求序列号连续,一旦跳跃,交易所会断开连接。我遇到过因为多线程并发发送导致序列号乱序,被交易所踢下线。
  • 心跳超时:不同交易所的心跳间隔不一样,有的30秒,有的15秒。我建议统一设为10秒,留足余量。
  • 订单重复:网络重传可能导致同一订单发两次。解决方案是每个订单生成唯一ID(ClOrdID),交易所会做去重。
我的习惯:每次上线新交易所,我都会先跑一周的模拟盘。不是不相信文档,是文档经常和实际不一样。你想想看,交易所的文档更新速度,永远赶不上代码改动的速度。

好了,明池路由的基础就这些。记住:连接是骨架,FIX是语言,订单生命周期是灵魂。这三样搞明白了,后面的路由策略才有得玩。


公众号:蓝海资料掘金营,微信deep3321