数据源与采集:主流交易所API对比
做量化交易,第一步就是搞定数据。没有数据,什么策略都是空中楼阁。今天咱们聊聊主流交易所的API怎么选、怎么用。
我个人习惯把数据采集分成两条线:一条是WebSocket实时流,用来做高频策略;另一条是RESTful接口,用来拉历史数据做回测。两条线缺一不可。
主流交易所API对比
目前市场上最主流的三个交易所:Binance、OKX、Coinbase。我三个都用过,各有各的脾气。
| 特性 | Binance | OKX | Coinbase |
|---|---|---|---|
| WebSocket稳定性 | ★★★★★ | ★★★★☆ | ★★★☆☆ |
| RESTful限频 | 1200次/分钟 | 600次/分钟 | 300次/分钟 |
| 订单簿深度 | 5000档 | 400档 | 100档 |
| 数据格式 | JSON | JSON | JSON |
| 文档质量 | 优秀 | 良好 | 一般 |
你看这个表,Binance在各方面都领先。但别急着选,我遇到过一个问题:Binance的WebSocket偶尔会断连,而且它不会主动重连。嗯,这里要注意,你必须自己写心跳检测和重连逻辑。
我的建议:如果你做高频策略,首选Binance。如果做中低频,OKX也够用。Coinbase的API限制太多,我一般只用来做参考。
WebSocket实时流订阅
WebSocket是实时数据的命脉。说白了,它就是一条长连接,交易所不断往你这边推数据。
我以Binance为例,订阅订单簿的代码长这样:
import websocket
import json
def on_message(ws, message):
data = json.loads(message)
# 处理订单簿增量更新
print(f"收到更新: {data['bids'][:2]}")
def on_error(ws, error):
print(f"连接异常: {error}")
def on_close(ws, close_status_code, close_msg):
print("连接关闭,准备重连...")
def on_open(ws):
# 订阅BTCUSDT的深度流
subscribe_msg = {
"method": "SUBSCRIBE",
"params": ["btcusdt@depth20@100ms"],
"id": 1
}
ws.send(json.dumps(subscribe_msg))
websocket.enableTrace(False)
ws = websocket.WebSocketApp(
"wss://stream.binance.com:9443/ws",
on_open=on_open,
on_message=on_message,
on_error=on_error,
on_close=on_close
)
ws.run_forever()
避坑指南:我曾经在项目里忘了处理重连逻辑,结果凌晨三点数据断了,策略还在傻傻地跑。第二天一看,亏了2%。从那以后,我每次写WebSocket代码,第一件事就是写重连。
为什么会这样?因为交易所的WebSocket服务器不是100%可靠的。网络抖动、服务器维护、甚至你本地IP变更,都可能导致连接断开。所以,重连机制是必须的。
RESTful历史数据拉取
回测需要历史数据,这时候就得用RESTful接口了。Binance的RESTful接口设计得很清晰,我直接上代码:
import requests
import pandas as pd
def fetch_klines(symbol, interval, limit=1000):
url = "https://api.binance.com/api/v3/klines"
params = {
"symbol": symbol,
"interval": interval,
"limit": limit
}
resp = requests.get(url, params=params)
data = resp.json()
# 解析成DataFrame
df = pd.DataFrame(data, columns=[
"open_time", "open", "high", "low", "close", "volume",
"close_time", "quote_volume", "count", "taker_buy_vol",
"taker_buy_quote_vol", "ignore"
])
df["open_time"] = pd.to_datetime(df["open_time"], unit="ms")
return df
# 拉取BTCUSDT最近1000根1分钟K线
df = fetch_klines("BTCUSDT", "1m")
print(df.head())
这里有个坑:Binance的RESTful接口有频率限制。你拉得太快,会被封IP。我一般会在请求之间加个0.1秒的延迟,稳得很。
注意:历史数据拉取时,一定要检查数据完整性。我曾经拉过一批数据,中间缺了3根K线,回测结果完全失真。建议拉完数据后,用时间戳检查是否有空缺。
数据频率选择
数据频率怎么选?这取决于你的策略类型。
- Tick级数据:每笔交易都记录。适合做高频做市商、套利策略。数据量巨大,一天可能几百万条。
- 秒级数据:每秒一个快照。适合做中高频策略,比如秒级动量。数据量适中,一天几十万条。
- 分钟级数据:每分钟一根K线。适合做趋势跟踪、均值回归。数据量小,一天1440条。
我个人习惯:做回测用分钟级,做实盘用秒级。Tick级数据太贵了,而且存储成本高。除非你资金量很大,否则没必要。
你想想看,如果你做的是日频策略,用Tick级数据不是杀鸡用牛刀吗?数据频率越高,噪声越大,处理起来也越麻烦。
知识体系结构图
下面这张图,是我总结的数据采集核心逻辑:
这张图把数据采集的脉络理清楚了。左边是实时流,右边是历史数据,中间是数据频率的选择。你照着这个框架去搭建数据采集系统,基本不会出错。
总结一下:数据采集是量化交易的基石。选对交易所、用对接口、定好频率,后面的事情就顺了。别在这步省时间,否则后面填坑更痛苦。