加密货币api的订单簿增量推送,如何与本地快照合并得到实时深度?

📅 2026/7/3 10:13:13 👁️ 阅读次数 📝 编程学习
加密货币api的订单簿增量推送,如何与本地快照合并得到实时深度?

我做行情分析有一段时间了,发现订单簿的数据其实比我们想象的要复杂。很多人用加密货币api的时候,只拉全量快照或者盯着增量消息,其实都不够。全量快照频繁拉取占用带宽,增量推送如果没有本地快照做基础,又会出现数据不完整的情况。把增量消息和本地快照结合起来,才能得到真正可靠的实时深度。

为什么要合并快照和增量

增量推送的核心是“更新现有状态”,它是基于某个快照的变化。如果直接用增量而没有初始快照,就可能出现深度表不完整的情况。我的做法是先拿一次快照作为初始状态,然后用增量消息去更新本地买卖列表,这样深度表随时都是完整的,延迟也控制得住。

本地快照如何组织

在代码里,我通常把买卖两边用字典保存,价格作为 key,数量作为 value。举个例子:

买/卖

价格

数量

30000

1.5

29950

2.0

30050

0.8

30100

3.0

这样做方便更新:增量消息来了,直接更新对应价格的数量或者删除数量为 0 的价格层。无需遍历整个列表,效率很高。

增量消息的处理方式

增量推送通常包含三种操作:新增、更新、删除。

  • 新增:本地没有的价格层,直接插入字典。

  • 更新:价格层存在,则覆盖数量。

  • 删除:数量为 0 时,删除这个价格层。

有的交易所增量消息会乱序,但大部分都会提供 sequence 或 timestamp 字段,用来保证更新顺序。只要用这个字段校验,基本不会覆盖错数据。

以AllTick API 为例,我在测试时,把增量消息直接合并到本地快照里,代码很简单:

import websocket import json snapshot = {} def on_message(ws, message): data = json.loads(message) for update in data['orders']: price = update['price'] quantity = update['quantity'] side = update['side'] # 'buy' 或 'sell' if quantity == 0: snapshot[side].pop(price, None) else: snapshot.setdefault(side, {})[price] = quantity print(snapshot) ws = websocket.WebSocketApp("wss://api.alltick.co/crypto/orderbook", on_message=on_message) ws.run_forever()

这段代码里,快照保存在本地字典里,增量消息来了直接处理就行。买卖深度一直保持最新。

性能优化建议

如果订单层级多,或者推送频繁,可以考虑两点:

  1. 只处理差异:有些消息更新了但本地没有变化的价格可以忽略,减少无效操作。

  2. 限制深度层数:大多数策略只关注前 20-50 层,更新全部深度没必要,占用资源。

另外,价格最好用 Decimal 或者统一数据类型,避免浮点精度问题,尤其是计算买卖价差时。

校验和稳定性

增量推送方便,但网络抖动可能会丢消息,所以建议定期拉一次全量快照做校验,频率根据交易量和策略决定,一般几秒到几十秒就够。这样可以保证深度表随时可靠。

我的体会

把增量和快照结合,实时深度几乎和交易所保持一致,延迟低又可靠。在可视化或者交易策略中,这种方法比只靠全量快照或者单独增量都稳。对于做行情相关开发的同学来说,理解增量消息和快照的关系,比盯着 API 文档里的参数更重要。