数据源与采集:主流交易所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级数据不是杀鸡用牛刀吗?数据频率越高,噪声越大,处理起来也越麻烦。

知识体系结构图

下面这张图,是我总结的数据采集核心逻辑:

数据采集核心逻辑 交易所API WebSocket实时流 RESTful历史数据 订单簿增量更新 K线推送 历史K线 历史成交 Tick / 秒级 / 分钟级 分钟级 / 小时级 / 日级

这张图把数据采集的脉络理清楚了。左边是实时流,右边是历史数据,中间是数据频率的选择。你照着这个框架去搭建数据采集系统,基本不会出错。

总结一下:数据采集是量化交易的基石。选对交易所、用对接口、定好频率,后面的事情就顺了。别在这步省时间,否则后面填坑更痛苦。

蓝海数据掘金营,专注资料整理