数据准备与清洗:数据源选择、对齐与复权、缺失值与异常值处理、存储方案
做量化回测,最怕什么?
不是策略亏钱,而是数据有问题。我见过太多人,策略回测曲线漂亮得像艺术品,一上实盘就崩。查到最后,十有八九是数据埋了雷。今天咱们就把这块硬骨头啃下来。
数据源选择:日线、分钟线还是Tick?
选什么粒度,取决于你的策略频率。别一上来就搞Tick数据,那玩意儿存储成本高,处理也慢。
- 日线:适合中长线策略,持仓几天到几周。数据量小,处理快。我个人的习惯是,做因子测试先用日线,跑通了再降级验证。
- 分钟线:适合日内策略或中高频交易。1分钟、5分钟最常见。注意,不同交易所的分钟线生成规则不一样,有的用最后成交价,有的用加权平均。
- Tick数据:逐笔成交或逐笔挂单。适合高频策略。但坑也多——比如交易所的Tick流偶尔会断,或者出现重复数据。
数据对齐与复权处理
数据对齐,说白了就是让不同时间序列的数据站在同一起跑线上。比如你有沪深300的日线,又有中证500的日线,它们的交易日可能不完全重合。这时候就需要对齐。
我常用的对齐方法是:以主力合约或基准指数的交易日为锚点,其他数据按时间戳左连接。缺失的交易日直接填充前值或删除。
复权处理,这是个老生常谈但总有人踩坑的问题。
- 前复权:调整历史价格,让价格连续。适合技术分析,因为K线图看起来平滑。
- 后复权:调整当前价格,保持历史真实价格。适合计算真实收益率。
我个人强烈建议:回测时用后复权,实盘时用前复权。为什么?回测要算真实盈亏,后复权能保留分红送股的影响。实盘看盘时,前复权的K线更直观。
缺失值处理
数据缺失是常态。原因很多:停牌、节假日、数据源漏了。处理方式取决于缺失比例和策略需求。
| 缺失比例 | 推荐处理方式 | 适用场景 |
|---|---|---|
| < 5% | 前向填充(ffill)或插值 | 大多数策略 |
| 5% - 20% | 删除该时间段或使用模型填充 | 对数据完整性要求高的策略 |
| > 20% | 直接剔除该标的 | 避免引入偏差 |
我个人的经验是:先用pandas的isnull().sum()快速扫描,如果缺失集中在某几天,大概率是数据源问题,直接补全或重拉数据。如果缺失分散,用前向填充最稳妥。
# 快速处理缺失值示例
import pandas as pd
df = pd.read_hdf('data.h5')
# 检查缺失
print(df.isnull().sum())
# 前向填充
df.fillna(method='ffill', inplace=True)
# 如果还有缺失,用中位数填充
df.fillna(df.median(), inplace=True)
异常值检测
异常值比缺失值更隐蔽。比如某只股票突然涨了100倍,你以为是发现了妖股,其实是数据录入错误。
常用的检测方法:
- 3σ原则:超过均值±3倍标准差的值视为异常。适合正态分布的数据。
- IQR方法:四分位距法。超过Q1-1.5IQR或Q3+1.5IQR的值视为异常。更稳健,不受极端值影响。
- 业务规则:比如涨跌幅超过20%的日线数据,大概率是异常。这个最实用。
# IQR方法检测异常值
Q1 = df['close'].quantile(0.25)
Q3 = df['close'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = df[(df['close'] < lower_bound) | (df['close'] > upper_bound)]
print(f'发现 {len(outliers)} 个异常值')
数据存储方案:HDF5 vs Parquet
数据存哪里?怎么存?直接影响回测速度和磁盘占用。
| 特性 | HDF5 | Parquet |
|---|---|---|
| 读取速度 | 快(列式存储) | 更快(压缩率高) |
| 压缩率 | 中等 | 高(通常节省50%以上空间) |
| 兼容性 | Python生态好 | 跨语言支持好 |
| 适合场景 | 单机回测、小规模数据 | 分布式、大规模数据 |
我个人偏好:日常回测用HDF5,因为pandas直接支持,读写方便。如果数据量超过10GB,或者需要跟其他语言交互,我会转成Parquet。
# HDF5存储示例
df.to_hdf('data.h5', key='daily', mode='w')
# Parquet存储示例
df.to_parquet('data.parquet', compression='snappy')
compression='snappy',速度和压缩比最均衡。别用gzip,解压太慢。
知识体系总览
下面这张图,概括了数据准备与清洗的核心流程。你想想看,从数据源到最终可用的回测数据,每一步都不能省。
说白了,数据准备就是给策略打好地基。地基不稳,楼盖得再高也得塌。我每次开始一个新策略,都会花至少30%的时间在数据清洗上。别嫌麻烦,这步省了,后面全是坑。