第二章 核心协议基础:FIX协议详解、二进制协议对比、RESTful API在交易中的应用
各位同学,今天我们来聊聊交易接口的“通用语言”。做量化交易这些年,我最大的感触就是:接口协议选得好,后面少踩一半坑。这一章,咱们就把FIX、二进制协议、RESTful API这三兄弟掰开揉碎了讲清楚。
2.1 FIX协议:金融界的“普通话”
FIX协议,全称Financial Information eXchange。说白了,它就是金融行业里约定俗成的消息格式标准。我2015年刚入行时,对接的第一家券商就是用的FIX 4.4版本。那时候觉得这玩意儿真啰嗦,一个订单要写一堆标签。后来才发现,正是这种“啰嗦”保证了跨系统的兼容性。
2.1.1 核心结构
FIX消息由三部分组成:
- 头(Header):包含消息类型、发送方、序列号等元信息
- 体(Body):具体的业务数据,比如订单价格、数量
- 尾(Trailer):校验和,保证消息完整性
举个例子,一个简单的限价买入订单长这样:
8=FIX.4.4|9=78|35=D|49=CLIENT1|56=BROKER1|34=1|52=20240101-00:00:00|11=ORD001|21=1|55=600519.SH|54=1|38=100|40=2|44=150.00|10=123|
嗯,这里要注意:每个字段用“|”分隔(实际是SOH字符,0x01)。标签号是固定的,比如35代表消息类型,D就是新订单。我刚开始写解析器时,经常把标签顺序搞反,结果券商那边一直报错。后来养成了习惯:先校验头,再解析体,最后算校验和。
2.1.2 会话层与业务层
FIX协议分两层:
- 会话层:负责登录、心跳、重连、序列号管理。这部分是“管道”
- 业务层:负责订单、成交、行情。这部分是“水”
我个人习惯把会话层单独封装成一个模块。为什么?因为业务层变化快,会话层相对稳定。你想想看,交易所改个订单字段,你只需要改业务层,会话层不用动。我在一个项目中见过有人把两者混在一起写,结果每次升级都像在拆炸弹。
避坑指南:我曾经在对接港交所时,忽略了FIX会话层的序列号校验。结果网络闪断后重连,序列号对不上,交易所直接拒绝所有消息。后来我加了个本地序列号缓存,每次重连前先同步,问题才解决。
2.2 二进制协议:速度与激情的选择
FIX虽然通用,但有个硬伤——慢。一个订单消息可能有几百字节,其中一半是标签名。对于高频交易来说,这简直是灾难。于是,二进制协议应运而生。
2.2.1 为什么快?
二进制协议的核心思想:去掉标签,固定位置。比如,消息的前4个字节是消息长度,接着2个字节是消息类型,再接着8个字节是价格……解析器直接按偏移量读取,不需要字符串匹配。
我做过一个对比测试:同样100万笔订单,FIX解析耗时约1.2秒,二进制协议只要0.3秒。差距就在这里。
2.2.2 常见二进制协议
| 协议名称 | 特点 | 典型场景 |
|---|---|---|
| FIX/FAST | 基于FIX的压缩版,用模板减少冗余 | 行情数据、批量订单 |
| SBE(Simple Binary Encoding) | 固定偏移,零拷贝解析 | 高频交易、FPGA加速 |
| Protobuf | Google出品,灵活但性能略逊 | 内部系统通信 |
| 自定义二进制 | 交易所自研,通常最快 | CTP、XTP等国内柜台 |
我个人最常用的是SBE。为什么?因为它支持零拷贝。什么意思?就是网卡收到数据后,CPU可以直接从内存缓冲区读取字段,不需要复制数据。这对延迟敏感的交易系统来说,简直是福音。
小技巧:如果你要设计二进制协议,记住一条原则:固定长度字段放前面,变长字段放后面。这样解析器可以快速跳过固定部分,按需读取变长部分。
2.3 RESTful API:慢但友好的“万金油”
说到RESTful API,很多做高频的同学会嗤之以鼻:“太慢了,毫秒级延迟,谁用啊?”但我想说,存在即合理。RESTful API在以下场景中非常实用:
- 查询历史成交、持仓、资金
- 管理订单(撤单、改单)
- 非实时行情获取
- 账户风控设置
2.3.1 设计要点
一个标准的交易RESTful API通常包含:
- POST /order:提交订单
- DELETE /order/{id}:撤单
- GET /order/{id}:查询订单状态
- GET /account:查询账户信息
嗯,这里要注意:RESTful API的幂等性设计。我曾经遇到过一个问题:网络超时后,客户端重试,结果同一个订单被提交了两次。后来我要求所有POST请求必须带一个唯一的幂等键(Idempotency-Key),服务端根据这个键去重。从此再也没出过双单问题。
2.3.2 性能优化
虽然RESTful API天生慢,但我们可以优化:
- 连接池:复用HTTP连接,避免三次握手
- 压缩:启用gzip压缩,减少传输量
- 缓存:对不频繁变动的数据(如合约信息)做本地缓存
- 异步回调:用Webhook替代轮询
我见过一个团队,把RESTful API的查询延迟从200ms优化到了20ms。怎么做到的?就是用了连接池+本地缓存。说白了,大部分查询请求都是重复的,没必要每次都去交易所拉数据。
警告:千万不要用RESTful API做高频交易的下单通道。我见过有人用Python requests库每秒发1000个订单,结果网关直接把他IP封了。RESTful API适合管理类操作,交易类操作请用FIX或二进制协议。
2.4 三种协议的对比与选择
好了,三种协议都讲完了。我们来做个对比:
| 维度 | FIX协议 | 二进制协议 | RESTful API |
|---|---|---|---|
| 延迟 | 中等(微秒级) | 低(纳秒级) | 高(毫秒级) |
| 可读性 | 高(文本协议) | 低(需要解码) | 高(JSON/XML) |
| 兼容性 | 高(行业标准) | 低(需双方约定) | 高(HTTP标准) |
| 开发成本 | 中(有现成库) | 高(需自研) | 低(框架成熟) |
| 适用场景 | 订单路由、行情分发 | 高频交易、FPGA | 查询、管理、风控 |
我个人建议:不要只用一种协议。一个成熟的交易系统,应该是FIX做订单路由,二进制协议做高频通道,RESTful API做管理后台。各取所长,才是正道。
2.5 本章知识体系图
下面这张图,是我自己画的三种协议的关系和选择逻辑。你仔细看看,应该能理解为什么我说“没有银弹”。
你看,这张图把三种协议的应用场景和选择逻辑都串起来了。说白了,没有最好的协议,只有最合适的组合。我在设计跨市场交易系统时,通常会先画这样一张图,然后根据每个市场的特点,决定用哪种协议。
好了,这一章的内容就到这里。记住:协议是工具,不是目的。你的目标是让交易系统稳定、快速、可维护。选对协议,事半功倍。
公众号:蓝海资料掘金营,微信deep3321