数据源排查:交易所WebSocket/Feed延迟、数据丢包与重连机制、多源数据对齐

做订单簿重建,第一步不是写代码,而是搞清楚你的数据到底从哪来、怎么来、来的时候有没有「偷工减料」。我见过太多团队,花了几周时间调算法,最后发现是数据源本身就有问题——白忙一场。

说白了,数据源就是整个系统的地基。地基歪了,上面盖多漂亮的房子都没用。这一节,咱们就聊聊怎么排查数据源的问题。

交易所WebSocket/Feed延迟

先说说延迟。交易所的行情数据,通常通过两种方式推送:WebSocket 和 专用数据 Feed(比如 FIX/ITCH 协议)。

WebSocket 方便,但延迟相对高一些。专用 Feed 快,但接入成本也高。我个人习惯,做高频策略必须用专用 Feed,做中低频的话 WebSocket 也够用。

但不管用哪种,延迟都是绕不开的坎。你想想看,你的订单簿重建速度再快,如果数据本身就已经晚了 10 毫秒,那重建出来的订单簿也是「过去时」。

怎么排查延迟?我一般分三步走:

  1. 本地打时间戳:数据一到达就立刻打上本地时间戳,跟交易所的时间戳做对比。
  2. 观察延迟波动:延迟稳定不可怕,可怕的是忽高忽低。波动大说明网络或者交易所本身有问题。
  3. 对比不同数据源:用两个独立的数据源互相验证,看同一笔交易的到达时间差。

关键指标:对于高频交易,WebSocket 延迟通常要求在 1-5 毫秒以内,专用 Feed 要求在 100 微秒以内。如果超过这个范围,你的订单簿重建基本就是「看图说话」了。

数据丢包与重连机制

丢包,这才是真正的噩梦。我在项目中遇到过好几次,订单簿重建到一半,突然发现中间少了几笔交易。结果呢?整个订单簿的价差、深度全错了。

为什么会丢包?原因很多:网络拥堵、交易所限流、WebSocket 连接不稳定……但不管什么原因,你的系统必须能感知到丢包,并且有能力恢复。

这里我分享一个我自己用的重连机制设计思路:

# 伪代码:带序列号检测的 WebSocket 重连
class OrderBookFeed:
    def __init__(self):
        self.last_seq = 0
        self.reconnect_attempts = 0
        self.max_attempts = 5

    def on_message(self, msg):
        current_seq = msg['sequence']
        if current_seq != self.last_seq + 1:
            # 检测到丢包
            self.request_snapshot()  # 请求全量快照
            self.rebuild_orderbook()
        self.last_seq = current_seq

    def on_disconnect(self):
        while self.reconnect_attempts < self.max_attempts:
            if self.try_reconnect():
                self.request_snapshot()
                break
            time.sleep(2 ** self.reconnect_attempts)  # 指数退避
            self.reconnect_attempts += 1

嗯,这里要注意:重连之后一定要请求全量快照,不能只靠增量数据恢复。我曾经吃过这个亏——重连后只补了增量,结果订单簿一直对不上,排查了整整两天才发现是快照没更新。

避坑指南:我曾经遇到过一个交易所,它的 WebSocket 在重连后不会主动推送全量快照,需要你手动请求。如果你没做这个逻辑,那重连后的所有数据都是「空中楼阁」。

多源数据对齐

做量化交易,尤其是做套利策略,经常需要同时接入多个交易所的数据。这时候问题就来了:每个交易所的时间戳不一样,序列号格式不一样,甚至数据推送的节奏都不一样。怎么对齐?

我个人的做法是:统一时间基准。所有数据到达后,立刻打上本地 NTP 同步的时间戳。然后以这个本地时间戳为基准,做数据对齐。

具体来说,分三步:

  1. 时间戳归一化:把各个交易所的时间戳统一转换成 UTC 纳秒级。
  2. 序列号映射:建立不同交易所之间的序列号映射关系,方便交叉验证。
  3. 延迟补偿:根据历史延迟数据,对每个数据源做动态延迟补偿。

小技巧:我习惯在数据对齐时,额外记录一个「置信度」字段。如果某个数据源的延迟波动大,置信度就低,后续策略可以降低它的权重。

下面这张图,是我自己总结的多源数据对齐流程,你可以参考一下:

多源数据对齐流程 交易所A WebSocket 交易所B 专用Feed 交易所C WebSocket 步骤1:本地NTP时间戳打标(统一时间基准) 步骤2:延迟检测与丢包识别(序列号连续性检查) 步骤3:多源数据对齐输出(带置信度标记)

最后说一句:数据源排查这件事,没有捷径。你得一条一条消息去对,一个时间戳一个时间戳去验证。但只要你把这个基础打牢了,后面的订单簿重建就会顺风顺水。

总结:数据源排查的核心就三件事——延迟要稳、丢包要补、多源要对。这三件事做好了,你的订单簿重建就成功了一半。

专注资料整理