4. 常见行情协议与数据格式

在Tick增量行情与订单簿重建的工程链路中,协议与数据格式决定了“数据长什么样、以什么节奏到达、解析成本有多高”。同一份市场深度,可能以JSON文本、紧凑二进制、FIX/FAST编码或组播报文的形式出现。理解这些差异,是后续做增量合并、序列号校验和低延迟优化的前提。

核心原理:行情协议的三层结构

任何行情接口都可以拆成三层:传输层(TCP、UDP组播、WebSocket)、编码层(JSON、CSV、二进制、FIX/FAST)、语义层(快照、增量、成交、心跳、重传请求)。传输层决定延迟与可靠性,编码层决定解析开销,语义层决定订单簿如何重建。三者组合出交易所常见的接口形态。

关键判断:增量行情必须能识别“序号”与“更新类型”。没有序列号或更新类型的协议,无法可靠重建订单簿,只能做展示级行情。
行情协议三层结构与数据链路 传输层 TCP / UDP组播 / WebSocket 决定延迟、可靠性、顺序 编码层 JSON / CSV / 二进制 / FIX/FAST 决定解析开销与带宽 语义层 快照 / 增量 / 成交 / 心跳 决定订单簿重建逻辑 交易所行情网关 → 协议编码 → 网络传输 → 客户端解码 → 增量合并 → 订单簿 JSON/CSV 可读、体积大、解析慢 二进制协议 紧凑、快、需schema FIX/FAST 金融标准、模板化 WebSocket/组播 推送、低延迟、多播 图:协议三层结构决定订单簿重建的可行性与性能边界

方法流程:从接口到订单簿的解析路径

以典型交易所增量深度接口为例,处理流程如下:

  1. 建立连接:WebSocket订阅depth频道,或加入UDP组播组并监听端口。
  2. 获取快照:通过REST或快照频道拉取当前订单簿全量,记录快照序号。
  3. 接收增量:持续接收增量消息,每条包含序号、买卖方向、价格、数量、更新类型。
  4. 序号校验:若增量序号与本地序号不连续,触发重连或重新拉取快照。
  5. 合并更新:按价格档位更新数量,数量为0则删除该档。
  6. 输出订单簿:维护买卖两侧有序结构,供策略或风控消费。

不同编码格式的解析差异很大。JSON需要字段名匹配与浮点解析;二进制协议按固定偏移读取;FIX/FAST需要先加载模板再按字段ID解码。下面是一个二进制增量消息的伪代码示例:

// 二进制增量消息:序号(8B) + 方向(1B) + 价格(8B) + 数量(8B)
struct DepthDelta {
    uint64_t seq;
    uint8_t  side;   // 0=bid, 1=ask
    double   price;
    double   qty;    // qty=0 表示删除该档
};

// 解析时按偏移读取,避免逐字段字符串匹配
DepthDelta d;
memcpy(&d.seq, buf + 0, 8);
d.side = buf[8];
memcpy(&d.price, buf + 9, 8);
memcpy(&d.qty, buf + 17, 8);

案例/场景:不同协议在实战中的取舍

协议/格式 典型场景 优点 风险与代价
JSON over WebSocket 零售交易所、快速接入 可读、调试方便、生态成熟 体积大、解析慢、GC压力高
CSV快照 历史回放、批量导入 简单、易存储 无增量语义、需自行对齐序号
二进制协议 期货、专业行情源 紧凑、低延迟、高吞吐 需schema、版本兼容复杂
FIX/FAST 机构级交易与行情 标准化、模板压缩 学习曲线陡、模板维护成本高
UDP组播 交易所直连、低延迟场景 一对多、延迟极低 丢包需重传、顺序需自保
实战建议:先用JSON/WebSocket打通订单簿重建逻辑,再逐步替换为二进制或组播通道。协议可以换,但序号校验、快照对齐、增量合并这三步不能省。

误区/复盘:协议选择中的常见坑

  • 误区一:只看延迟不看可靠性。UDP组播延迟低,但丢包后若无重传或快照恢复机制,订单簿会持续错位。
  • 误区二:忽略序号回绕。部分协议序号为32位,长时间运行会回绕,比较时需用无符号差值而非简单大于。
  • 误区三:快照与增量时间窗不匹配。先拉快照再订阅增量,中间可能丢失更新;正确做法是“先订阅增量、缓存、再拉快照、按序号对齐”。
  • 误区四:JSON浮点直接比较价格。文本解析出的浮点可能存在精度误差,价格档位应使用定点整数或字符串键。
  • 误区五:FIX/FAST模板版本不一致。模板变更后未同步更新,会导致字段错位或解析失败,必须做版本校验。
复盘要点:订单簿重建的稳定性,80%取决于协议语义理解是否准确,而不是代码写得多快。先确认“序号、更新类型、快照对齐方式”三件事,再动手写解析器。