股票实时行情接口的推送消息中如何区分快照和增量?
做股票实时行情接口对接的时候,有个点一开始很容易忽略:推送消息看起来都差不多,但实际含义完全不一样。有的像“完整市场画面”,有的只是“局部变化”。如果这一步没分清,后面不管是做盘口还是做策略回放,数据都会慢慢跑偏。
我刚开始接触这一块的时候,就吃过这个亏。缓存结构写得挺顺,但数据偶尔会“跳一下”,后来才发现问题出在快照和增量混着当成一种数据处理了。
快照和增量到底在表达什么
在股票实时行情接口里,快照和增量其实是两种完全不同的数据逻辑。
快照更像是“整张行情截图”,某一时刻的完整盘口、成交、深度信息都会一次性给你。这种数据的作用很直接,就是让客户端对齐当前真实状态,不依赖历史数据也能直接还原。
增量就不一样了,它只告诉你“哪里变了”。比如某一档价格挂单数量变化,或者某一笔成交更新。它不会重复给全量数据,传输更轻,但对本地状态依赖更强。
简单说就是:
快照:用来初始化当前市场状态
增量:用来持续修正这个状态
如果把这两种混在一起处理,本地盘口基本一定会乱。
消息里一般怎么区分
不同的股票实时行情接口实现方式不完全一样,但大致思路都类似,通常会在字段上做区分。
常见情况大概是这样:
| 类型 | 常见字段 | 含义 |
| 快照 | snapshot / full | 全量盘口数据 |
| 增量 | update / delta | 局部变化数据 |
| 混合 | type 字段区分 | 同一通道不同消息类型 |
有些接口更直接,会在 message 里加一个 type 字段,比如 snapshot 或 update,一眼就能判断。
也有一些不太友好的设计,只能通过结构判断,比如:
快照一定带完整 depth 数组
增量只有部分 price level 更新
这种就需要在代码里多留一点判断空间。
实际处理时的思路
我自己在处理这类数据的时候,会把逻辑拆成两段:一段负责“建立状态”,一段负责“持续修正”。快照来了就直接覆盖本地缓存,不做任何合并操作。因为它本身就是完整数据,再去 merge 反而容易引入脏数据。增量则是在已有缓存基础上做局部更新,比如更新某一档价格的挂单量,或者删除某个失效档位。
这里有个很关键的点:增量不能脱离快照存在,如果系统刚启动还没收到快照,增量直接丢掉是更安全的选择。
代码里的处理方式
以 AllTick API 的 websocket 推送为例,快照和增量可以在同一个连接里通过 type 字段区分。下面是一个比较接近真实工程的写法:
import websocket
import json
cache = {}
def apply_snapshot(data):
symbol = data["symbol"]
cache[symbol] = {
"bids": data["bids"],
"asks": data["asks"]
}
def apply_update(data):
symbol = data["symbol"]
if symbol not in cache:
return
book = cache[symbol]
for bid in data.get("bids", []):
price = bid["price"]
size = bid["size"]
book["bids"][price] = size
for ask in data.get("asks", []):
price = ask["price"]
size = ask["size"]
book["asks"][price] = size
def on_message(ws, message):
data = json.loads(message)
msg_type = data.get("type")
if msg_type == "snapshot":
apply_snapshot(data)
elif msg_type == "update":
apply_update(data)
def on_open(ws):
sub = {
"action": "subscribe",
"symbol": "BTCUSDT",
"type": "depth",
"id": 1
}
ws.send(json.dumps(sub))
ws = websocket.WebSocketApp(
"wss://api.alltick.co/ws",
on_message=on_message,
on_open=on_open
)
ws.run_forever()
这个结构其实很简单:快照负责“搭骨架”,增量负责“补变化”。
容易被忽略的几个细节
做一段时间之后会发现,真正影响稳定性的不是逻辑本身,而是一些细节处理。
一个是快照刷新问题。有些股票实时行情接口会周期性推快照,如果直接覆盖缓存没问题,但如果和增量同时到达,就要注意顺序,否则会出现短暂错乱。
另一个是增量丢失。如果网络不稳定,某些 update 丢掉了,本地状态不会立刻报错,但盘口会慢慢偏离真实情况,这种问题通常要靠下一次快照修正。
还有一个是多 symbol 并发处理,如果缓存没按 symbol 隔离,很容易出现数据串台,这个坑我也踩过一次,排查起来挺费时间。
收口的理解
快照和增量其实不是两个复杂概念,本质上就是“完整状态”和“变化事件”。在股票实时行情接口的设计里,这套模型几乎是标准结构。理解之后再看不同数据源,差别其实只是字段名字不一样。
工程上真正重要的不是解析,而是状态管理:什么时候覆盖,什么时候更新,什么时候丢弃。这几个点理顺之后,行情数据会稳定很多。
本作品采用《CC 协议》,转载必须注明作者和本文链接
关于 LearnKu
推荐文章: