2. 行情数据源接入:交易所行情协议对比与网关架构
高频交易系统的第一道关卡是行情数据源接入。不同交易所采用差异极大的底层传输协议与数据编码方式,直接决定了行情网关的架构设计、延迟指标与运维复杂度。本章从协议对比、网关分层、解码归一化三个维度展开,为后续灰度发布与Serving奠定数据基础。
2.1 交易所行情协议对比(UDP / Multicast / TCP)
主流交易所行情分发协议可归纳为三类:UDP单播、UDP组播(Multicast)、TCP流。下表从传输模型、可靠性、延迟、适用场景四个维度进行对比:
| 对比维度 | UDP 单播 | UDP 组播 (Multicast) | TCP 流 |
|---|---|---|---|
| 传输模型 | 点对点,每个客户端独立数据流 | 一对多,网络层复制数据包 | 点对点,面向连接 |
| 可靠性 | 无内置确认/重传,需应用层补偿 | 无内置确认/重传,依赖FEC或快照补偿 | 内置ACK、重传、顺序保证 |
| 延迟 | 极低(微秒级),无连接开销 | 极低(微秒级),网络层多播效率高 | 较低(毫秒级),连接建立与拥塞控制引入抖动 |
| 适用场景 | 小规模自营、专线直连 | 大规模机构、交易所标准行情分发 | WebSocket行情、历史数据回放、非极速场景 |
| 典型交易所 | 部分DMA接口、ICE | CME、Eurex、LSE、上期所(CFFEX) | Binance、Coinbase、Bybit(WebSocket) |
实战建议:高频场景首选UDP组播。组播模式下,行情网关只需加入一个组播组即可接收全量行情,网络负载与客户端数量解耦。但必须处理丢包补偿——通常采用“快照+增量”双通道机制。
2.2 行情网关架构设计
行情网关是连接交易所原始数据与内部系统的桥梁。一个生产级网关通常包含以下分层:
- 网络接入层:负责UDP/TCP socket管理、组播组加入、连接池维护、心跳检测。
- 协议解析层:按交易所协议规范(如CME MDP 3.0、Eurex EBS、上期所STEP)解析二进制报文。
- 解码与归一化层:将交易所专有字段映射为内部统一行情模型(如Symbol、Bid/Ask、LastPrice、Volume)。
- 分发层:将归一化后的行情通过低延迟通道(共享内存、RDMA、ZeroMQ)推送给交易引擎或缓存层。
下图展示行情网关的典型分层架构与数据流:
延迟关键点:网关内部各层之间必须使用无锁队列或环形缓冲区,避免锁竞争和系统调用。网络接入层与协议解析层通常绑定到独立CPU核心,使用DPDK或AF_XDP绕过内核协议栈。
2.3 数据解码与归一化
不同交易所的行情编码格式差异巨大,解码与归一化是网关中最容易引入延迟和Bug的环节。常见编码格式包括:
- 二进制定长/变长:CME MDP 3.0使用SBE(Simple Binary Encoding),Eurex使用EBS二进制协议。
- 文本/JSON:部分加密货币交易所使用JSON over WebSocket,解析开销较高。
- STEP/FIX:国内期货交易所(上期所、大商所)采用STEP协议,基于FIX标签-值格式。
归一化层需要将上述异构数据映射为统一的内部行情结构体。以下是一个简化的C++归一化结构体示例:
// 内部统一行情结构体(归一化后)
struct UnifiedMarketData {
uint64_t timestamp_ns; // 纳秒级时间戳
uint32_t exchange_id; // 交易所枚举
uint32_t symbol_id; // 内部品种ID
double bid_price; // 买一价
uint64_t bid_volume; // 买一量
double ask_price; // 卖一价
uint64_t ask_volume; // 卖一量
double last_price; // 最新成交价
uint64_t last_volume; // 最新成交量
uint8_t data_flags; // 快照/增量/心跳标志
};
避坑提示:归一化时务必注意字节序(Big-Endian vs Little-Endian)、时间戳精度(秒/毫秒/纳秒)、价格精度(定点数 vs 浮点数)。建议在解码层统一转为纳秒时间戳和双精度浮点,避免后续计算时反复转换。
下图展示从原始交易所报文到归一化结构体的完整解码流程:
2.4 灰度发布对行情接入的影响
在灰度发布场景下,行情网关需要支持多版本并行与流量切换。关键设计点包括:
- 协议版本兼容:交易所可能升级协议(如CME MDP 3.0 → 3.1),灰度期间需同时支持新旧版本解码。
- 归一化字段扩展:新版本可能增加字段(如统计波动率),归一化结构体需预留扩展位或使用动态字段。
- 灰度路由:按交易所、品种或客户端ID将行情流量路由到不同版本的网关实例,实现平滑升级。
灰度实践:建议在归一化层引入版本号字段,并在分发层根据版本号将行情投递到不同的消费队列。这样交易引擎可以按自身灰度策略选择消费新版或旧版行情,实现完全解耦。