第二章:日志数据采集——从交易所到本地,一个都不能少
做量化交易,数据就是你的血液。没有数据,策略再好也是纸上谈兵。
我个人习惯把日志数据采集分成三个层次:交易所API、本地文件、实时流。这三个层次,说白了就是「过去、现在、未来」的数据都要抓在手里。你想想看,如果只盯着实时数据,回测怎么做?如果只读本地文件,错过行情怎么办?
2.1 从交易所API获取交易数据
这是最基础的一步。交易所API就像一扇门,你得知道钥匙怎么配。
我在项目中遇到过最坑的事:某次行情波动剧烈,API调用频率没控制好,直接被交易所封了IP。嗯,这里要注意——每个交易所的限频规则都不一样。
核心要点:API鉴权、请求频率控制、数据格式解析
以币安为例,获取K线数据的代码大概长这样:
import requests
import json
# 我个人习惯把API密钥放在环境变量里
api_key = "你的API_KEY"
secret_key = "你的SECRET_KEY"
# 获取BTC/USDT的1小时K线
url = "https://api.binance.com/api/v3/klines"
params = {
"symbol": "BTCUSDT",
"interval": "1h",
"limit": 100
}
response = requests.get(url, params=params)
data = response.json()
# 解析数据:时间戳、开盘价、最高价、最低价、收盘价、成交量
for kline in data:
print(f"时间: {kline[0]}, 开盘: {kline[1]}, 收盘: {kline[4]}")
避坑指南:我曾经因为没处理API返回的异常状态码,导致策略在交易所维护时还在疯狂下单。一定要加try-except!
2.2 本地日志文件读取
本地日志文件,说白了就是你的「交易日记」。每次下单、撤单、成交,都应该留下痕迹。
我建议日志文件采用CSV或JSON格式,按日期分文件存储。为什么?因为单文件太大时,读取速度会慢到你怀疑人生。
| 日志字段 | 说明 | 示例 |
|---|---|---|
| timestamp | 时间戳(毫秒级) | 1712345678000 |
| symbol | 交易对 | BTCUSDT |
| side | 买卖方向 | BUY / SELL |
| price | 成交价格 | 65000.12 |
| quantity | 成交数量 | 0.01 |
读取本地日志,我一般用Pandas,又快又方便:
import pandas as pd
# 读取昨天的交易日志
df = pd.read_csv("logs/trade_2024-04-01.csv")
print(f"共 {len(df)} 条交易记录")
print(df.head())
小技巧:如果日志文件超过100MB,建议用chunksize分块读取,不然内存会爆。我曾经在8GB的机器上硬读2GB的日志文件,结果你懂的...
2.3 实时日志流处理(WebSocket)
实时数据流,是量化交易的「眼睛」。WebSocket比轮询API高效得多——它就像一根水管,数据自己流过来,不用你一次次去拧水龙头。
为什么会这样?因为WebSocket建立一次连接后,服务器会主动推送数据,延迟低、带宽省。
一个典型的WebSocket连接代码:
import websocket
import json
def on_message(ws, message):
data = json.loads(message)
# 实时处理行情数据
print(f"最新价格: {data['p']}")
def on_error(ws, error):
print(f"连接出错: {error}")
def on_close(ws, close_status_code, close_msg):
print("连接关闭")
def on_open(ws):
print("连接成功")
# 订阅BTC/USDT的实时交易数据
subscribe_msg = {
"method": "SUBSCRIBE",
"params": ["btcusdt@trade"],
"id": 1
}
ws.send(json.dumps(subscribe_msg))
# 启动WebSocket连接
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()
注意:WebSocket连接可能会断。我建议加一个自动重连机制,比如每5秒检查一次连接状态,断了就重新连。我曾经因为没做重连,半夜策略断线了都不知道,第二天一看亏了5%...
2.4 三种采集方式的对比
这三种方式各有各的用处,我整理了一张表:
| 采集方式 | 适用场景 | 延迟 | 数据完整性 |
|---|---|---|---|
| 交易所API | 回测、历史数据分析 | 高(秒级) | 完整 |
| 本地日志文件 | 复盘、绩效评估 | 无(离线) | 取决于记录频率 |
| WebSocket实时流 | 实盘交易、监控 | 低(毫秒级) | 实时但不保证历史 |
2.5 知识体系结构图
下面这张图,是我对日志数据采集的整体理解:
你看,三种采集方式最终汇聚到统一的数据仓库。我个人习惯把API数据存一份、本地日志存一份、实时流也存一份——三份数据互相校验,出问题能快速定位。
总结一下:日志数据采集不是简单的「拿到数据就行」。你要考虑数据完整性、实时性、存储效率。我见过太多人只盯着实时流,结果回测时发现历史数据不全,策略评估直接废了。