3、数据获取与清洗:交易所API对接、WebSocket实时流、数据去重与对齐、时间戳处理

做订单簿预测,第一步不是建模,而是搞定数据。

我见过太多人,模型写得花里胡哨,结果数据源一塌糊涂。回测跑得飞起,实盘一上线就崩。说白了,数据是地基,地基不稳,楼盖得再高也是白搭。

这一章,我们就来聊聊怎么从交易所拿到干净、对齐、可用的订单簿数据。我会把我在实战中踩过的坑、总结的经验,一股脑儿倒出来。

3.1 交易所API对接:REST vs WebSocket

交易所提供两种主要的数据接口:REST API 和 WebSocket。很多人一开始搞混,我简单解释一下。

  • REST API:你主动去问交易所要数据。比如你发一个HTTP请求,交易所给你返回当前订单簿的快照。适合做历史数据回测,或者低频策略。
  • WebSocket:交易所主动把数据推给你。你连上之后,只要订单簿有变化,交易所就实时发给你。适合做高频交易、实时监控。

我个人习惯是:回测用REST,实盘用WebSocket。为什么?因为REST拿到的数据是完整的快照,方便做历史回放。而WebSocket拿到的增量数据,延迟低,适合实时决策。

重要提醒:千万别在实盘里用REST轮询去拿订单簿。我见过有人每100ms发一次请求,结果被交易所封了IP。WebSocket才是实时场景的正确姿势。

3.2 WebSocket实时流:增量更新与快照重建

WebSocket推送的数据,通常是增量数据。什么意思呢?交易所不会每次都把整个订单簿发给你,而是只告诉你「谁变了」。

比如,你收到一条消息:{"asks": [["50000.0", "0.5"]]}。这表示卖一档的价格变成了50000,数量0.5。你需要用这个增量去更新你本地维护的订单簿。

这里有个坑——增量数据可能会丢包。我曾经在实盘里遇到过,网络抖动导致漏掉了几条增量,结果本地的订单簿和交易所的真实状态对不上了。那怎么办?

解决方案是:定期做快照同步。比如每5分钟,或者每1000条增量后,主动用REST API拉一次完整的订单簿快照,覆盖本地数据。这样即使中间丢了包,也能很快纠正回来。

我的小技巧:在本地维护一个「序列号」计数器。每收到一条WebSocket消息,序列号+1。如果发现序列号跳变,说明丢了数据,立即触发快照同步。这个机制帮我避免了好几次数据错乱。

3.3 数据去重与对齐:别让脏数据毁了你的模型

WebSocket数据是实时的,但网络延迟、交易所重传机制,都可能导致你收到重复数据。比如同一条订单簿更新,交易所发了两次。如果你不做去重,模型就会学到「假规律」。

怎么去重?我一般用时间戳 + 消息ID作为唯一键。每条WebSocket消息都带有一个唯一的ID,或者精确到微秒的时间戳。你维护一个集合,记录最近1000条消息的ID。新消息来了,先查一下ID是否在集合里。如果在,直接丢弃。

# 伪代码示例
seen_ids = set()
def on_message(msg):
    msg_id = msg['id']
    if msg_id in seen_ids:
        return  # 重复消息,丢弃
    seen_ids.add(msg_id)
    # 继续处理

数据对齐,是另一个头疼的问题。不同交易所的订单簿,时间戳格式不一样。有的用Unix毫秒,有的用微秒,还有的用字符串。你想想看,如果时间戳不对齐,你拿两个交易所的数据做套利,结果时间差了几十毫秒,那策略就废了。

我的做法是:统一转成Unix毫秒整数。不管交易所给什么格式,进来先转。这样后续做时间序列分析、回测,都不会出问题。

注意:有些交易所的时间戳是「交易所本地时间」,不是UTC。比如币安用的是UTC+0,但有些小交易所可能用本地时间。一定要确认清楚,否则数据对齐会出大问题。我曾经因为这个原因,回测结果和实盘差了整整8个小时。

3.4 时间戳处理:精度与对齐的艺术

时间戳处理,是订单簿数据清洗中最容易被忽视的一环。我见过很多新手,直接把时间戳当字符串存起来,结果做时间序列分析时各种报错。

核心要点就两个:精度对齐

  • 精度:高频交易需要微秒级精度。如果你的时间戳只精确到秒,那同一秒内的订单簿变化你就分不清先后顺序了。我个人建议,至少保留毫秒级精度。
  • 对齐:把不同数据源的时间戳,对齐到同一个时间轴上。比如,你同时订阅了币安和OKX的订单簿,它们的时间戳可能相差几毫秒。你需要用「最近邻对齐」或者「线性插值」的方法,把它们对齐到同一个时间点。

下面是一个简单的时间戳对齐示例:

import pandas as pd

# 假设有两个数据源的时间序列
binance_ts = [1000, 1005, 1010]  # 毫秒
okx_ts = [1002, 1007, 1012]

# 对齐到统一的参考时间轴
ref_ts = [1000, 1005, 1010, 1015]

# 使用pandas的reindex进行最近邻对齐
binance_series = pd.Series([1,2,3], index=binance_ts)
okx_series = pd.Series([4,5,6], index=okx_ts)

binance_aligned = binance_series.reindex(ref_ts, method='nearest')
okx_aligned = okx_series.reindex(ref_ts, method='nearest')

嗯,这里要注意:对齐会引入误差。如果你的数据本身延迟就很大,对齐后的数据可能完全失真。所以,尽量选择延迟低的交易所,并且控制对齐的时间窗口不要太大。

3.5 本章知识体系总览

为了让你更直观地理解本章的内容,我画了一张流程图。它展示了从交易所原始数据到干净、对齐的订单簿数据的完整链路。

订单簿数据获取与清洗流程 交易所数据源 REST API (快照) WebSocket (增量) 快照同步 (定期) 增量更新 + 去重 数据对齐 (时间戳) 干净、对齐的订单簿数据

从这张图你可以看到,整个流程分为两条线:左边是REST API的快照同步,右边是WebSocket的增量更新。两条线最终在「数据对齐」这一步汇合,输出我们需要的干净数据。

实战建议:刚开始做的时候,别追求完美。先用REST API把历史数据拉下来,跑通回测流程。等模型稳定了,再上WebSocket做实时流。一步到位往往容易翻车。

好了,数据获取与清洗这部分就聊到这儿。记住一句话:数据质量决定了模型的天花板。花80%的时间在数据上,20%的时间在模型上,这是值得的。

专注资料整理