第二十五讲:订单簿数据源——主流交易所API、数据格式与数据清洗
做量化交易,数据就是你的弹药。订单簿数据更是重中之重。
我个人习惯把订单簿比作市场的「心电图」——每一笔挂单、撤单、成交,都是市场情绪的跳动。今天咱们就聊聊,怎么从交易所拿到这些数据,怎么读懂它们,以及怎么把脏数据洗干净。
一、主流交易所API概览
先说说我常用的几个交易所。说实话,每个交易所的API设计思路都不一样,踩过的坑也不少。
| 交易所 | REST API | WebSocket | 限频规则 |
|---|---|---|---|
| Binance | GET /api/v3/depth | wss://stream.binance.com:9443/ws | 1200次/分钟 |
| OKX | GET /api/v5/market/books | wss://ws.okx.com:8443/ws/v5/public | 20次/秒 |
| Bybit | GET /v5/market/orderbook | wss://stream.bybit.com/v5/public/linear | 50次/秒 |
嗯,这里要注意:Binance的限频虽然看着宽松,但它的深度快照有大小限制。我记得有一次做高频策略,拉100档深度,结果被限频了——后来才发现,Binance的深度数据分「快照」和「增量」两种模式。
二、数据格式解析
订单簿数据长什么样?说白了就是两个列表:买单(bids)和卖单(asks)。每个列表里是一堆价格-数量对。
举个例子,Binance返回的原始数据是这样的:
{
"lastUpdateId": 1027024,
"bids": [
["0.0024", "10"], // 价格,数量
["0.0023", "20"]
],
"asks": [
["0.0026", "15"],
["0.0027", "25"]
]
}
你想想看,这个结构其实很直观。但坑在哪里?
- 价格和数量都是字符串——不是浮点数!我刚开始做的时候直接当float处理,结果精度丢失,亏了一笔小钱。
- 排序规则:买单按价格降序(价高者优先),卖单按价格升序(价低者优先)。
- 更新ID:这个字段很重要,用来判断数据是否连续。
核心要点:订单簿数据分为「快照」和「增量」两种。快照是全量数据,增量是变化数据。做实时策略时,必须把两者结合起来。
三、数据清洗实战
数据清洗,说白了就是「去伪存真」。我在项目中遇到过不少奇葩数据,比如价格为零、数量为负、时间戳乱跳……
下面是我常用的清洗流程:
- 去重:同一个价格点出现多次,只保留最新一条。
- 过滤异常:价格小于等于0、数量小于等于0的直接扔掉。
- 排序校验:检查买单是否降序、卖单是否升序。
- 时间戳对齐:不同交易所的时间戳格式不同,统一转成毫秒级Unix时间戳。
来看一段Python代码,这是我常用的清洗函数:
def clean_orderbook(raw_data):
"""
清洗订单簿数据
raw_data: 交易所返回的原始字典
"""
cleaned = {
'bids': [],
'asks': [],
'timestamp': int(time.time() * 1000)
}
# 清洗买单
for price_str, qty_str in raw_data.get('bids', []):
price = float(price_str)
qty = float(qty_str)
if price > 0 and qty > 0:
cleaned['bids'].append([price, qty])
# 清洗卖单
for price_str, qty_str in raw_data.get('asks', []):
price = float(price_str)
qty = float(qty_str)
if price > 0 and qty > 0:
cleaned['asks'].append([price, qty])
# 排序校验
cleaned['bids'].sort(key=lambda x: x[0], reverse=True)
cleaned['asks'].sort(key=lambda x: x[0])
return cleaned
避坑指南:我曾经遇到过某个交易所的WebSocket推送数据,价格字段里居然混入了空格和换行符。后来我加了一层strip()处理,才彻底解决。
四、知识体系图
下面这张图,是我对订单簿数据源整个流程的理解。从交易所API到清洗后的可用数据,每一步都有讲究。
五、实战中的注意事项
最后,分享几个我踩过的坑:
- WebSocket断线重连:别指望连接永远稳定。我建议每次重连后,先拉一次快照,再订阅增量更新。
- 数据延迟:不同交易所的延迟不一样。Binance的WebSocket延迟通常在10-50ms,OKX稍高一些。做套利策略时,这个差异必须考虑进去。
- 存储策略:全量数据存起来太占空间。我个人习惯只存增量数据,需要时再重建快照。
小技巧:如果你用Python做数据清洗,推荐用decimal.Decimal代替float处理价格。虽然慢一点,但精度有保障。尤其是做高频策略时,小数点后第8位的差异都可能影响盈亏。
嗯,关于订单簿数据源,今天就聊到这儿。数据清洗这块,说白了就是「慢工出细活」。你花在清洗上的每一分钟,都会在后续的策略回测和实盘交易中回报给你。