第一章:数据获取与清洗——量化交易的基石

做统计套利,说白了就是找两个品种之间的价差规律。但有个前提——你得有干净的数据。我见过太多人策略写得漂亮,一上实盘就崩,十有八九是数据出了问题。这一章,咱们就把数据获取和清洗这件事彻底聊透。

1.1 数据源选择:你的原材料从哪里来?

数据源选不对,后面全白费。我个人习惯把数据源分成两类:交易所直连和第三方数据商。各有各的脾气。

交易所API

直接连交易所,数据最原始、延迟最低。适合做高频或者T+0策略。但坑也不少——

  • 限流问题:交易所不是你家开的,每秒请求次数有限。我曾经在币安上同时跑5个策略,结果被限流了半小时,那叫一个惨。
  • 数据格式不统一:不同交易所的K线字段名都不一样。有的叫open,有的叫o,你得自己映射。
  • 断线重连:WebSocket断了怎么办?我建议写个心跳检测,5秒没收到数据就自动重连。

我的经验:做统计套利,至少要有两个交易所的数据。因为价差策略本质上是吃两个市场之间的定价偏差,单市场数据不够用。

第三方数据商

如果你不想折腾交易所API,找第三方数据商是省心选择。国内常用的有万得、聚宽、Tushare,国外有Quandl、Alpha Vantage。

数据商 优点 缺点
万得 数据全,A股覆盖好 贵,一年几万块
聚宽 免费,有回测平台 数据延迟高,不适合高频
Tushare 开源,社区活跃 需要积分,部分数据收费
Quandl 全球数据,质量高 部分数据要付费

小建议:刚开始做策略,先用免费数据跑通逻辑。等要实盘了,再考虑付费数据。别一上来就花冤枉钱。

1.2 数据清洗流程:脏数据是策略的杀手

数据拿到手,第一件事不是分析,是清洗。我见过有人用未清洗的数据跑回测,年化收益率50%,实盘直接亏20%。为什么?因为数据里有未来函数和幸存者偏差。

去重

同一个时间戳出现两条数据,怎么办?我的做法是:

  • 先按时间戳排序
  • drop_duplicates()去重
  • 保留最后一条(因为可能是修正数据)
import pandas as pd

# 假设df是原始数据
df = df.sort_values('timestamp')
df = df.drop_duplicates(subset='timestamp', keep='last')

对齐

统计套利最怕时间戳对不上。比如A品种是1分钟K线,B品种是5分钟K线,你怎么算价差?

我习惯的做法是:

  • 统一用高频数据的时间戳作为基准
  • 低频数据向前填充(forward fill)
  • 或者用resample重采样到同一频率
# 将两个品种对齐到1分钟
df_a = df_a.resample('1T').last()
df_b = df_b.resample('1T').last()

# 合并
df = pd.concat([df_a, df_b], axis=1)

注意:对齐时千万别用向后填充(backfill),那会引入未来数据。我曾经因为这个坑,回测曲线漂亮得不像话,实盘直接打脸。

填充缺失值

数据缺失是常态。比如节假日、交易所故障、网络波动。怎么处理?

  • 线性插值:适合短期缺失,比如缺了1-2根K线
  • 向前填充:适合非交易时段,比如夜盘休市
  • 直接删除:如果缺失太多,比如连续缺了10根K线,我建议直接删掉那一段
# 线性插值
df = df.interpolate(method='linear')

# 向前填充
df = df.fillna(method='ffill')

# 删除连续缺失超过5行的数据
df = df.dropna(thresh=5)

1.3 数据存储方案:存得好才能用得爽

数据清洗完了,得存起来。选什么格式?我根据场景来定。

CSV:简单但慢

适合小数据量,比如几千条K线。优点是通用,Excel都能打开。缺点是:

  • 读写慢,尤其是几百万条数据
  • 不支持索引,每次都要重新加载
  • 容易损坏,断电就完蛋

HDF5:快但复杂

适合大数据量,比如全市场Tick数据。我常用pandas.HDFStore来存:

import pandas as pd

# 写入
store = pd.HDFStore('data.h5')
store['btc_usdt'] = df
store.close()

# 读取
store = pd.HDFStore('data.h5')
df = store['btc_usdt']
store.close()

我的习惯:HDF5支持压缩,能省不少磁盘空间。我存1年的1分钟K线数据,CSV要2GB,HDF5只要500MB。

数据库:最靠谱的选择

如果你要实盘,我强烈建议用数据库。MySQL、PostgreSQL、InfluxDB都行。好处是:

  • 支持并发读写
  • 数据不会损坏
  • 可以按时间范围查询
import sqlalchemy as sa

# 连接数据库
engine = sa.create_engine('postgresql://user:pass@localhost:5432/trading')

# 写入
df.to_sql('btc_usdt', engine, if_exists='replace')

# 读取
df = pd.read_sql('SELECT * FROM btc_usdt WHERE timestamp > "2024-01-01"', engine)

避坑指南:我曾经用SQLite存数据,结果并发写入时直接锁死。实盘系统千万别用SQLite,至少上PostgreSQL。

知识体系总览

下面这张图,把数据获取与清洗的整个流程串起来了。你照着这个框架走,基本不会出大问题。

数据获取与清洗流程 数据源选择 数据清洗 数据存储 交易所API 第三方数据商 去重 对齐 填充缺失值 CSV HDF5 数据库 核心原则:先清洗,再存储,最后分析 关键点:数据质量决定策略上限 去重 → 对齐 → 填充 → 存储,一步都不能少

嗯,数据获取与清洗这部分,说白了就是打地基。地基不稳,楼盖得再高也得塌。我见过太多人在这上面栽跟头,所以这一章我讲得特别细。你照着做,至少能避开80%的坑。

记住一句话:数据质量决定策略上限。你的策略再牛,数据是脏的,结果就是垃圾进垃圾出。

专注资料整理