数据获取与清洗:数据源选择、清洗流程与复权处理
做量化回测,第一步就是搞数据。这一步要是没做好,后面所有策略都是空中楼阁。我见过太多人,策略写得花里胡哨,结果一跑回测,发现数据里藏着各种坑——停牌没处理、复权搞错了、甚至日期对不上。嗯,今天我们就来聊聊数据获取与清洗这件事。
数据源选择:三大主流工具对比
国内做量化,常用的数据源就那么几个。我个人习惯用 tushare 和 akshare 搭配着来。为什么?因为没有一个数据源是完美的,你想想看,免费的东西总得有点取舍。
| 数据源 | 特点 | 适合场景 | 我踩过的坑 |
|---|---|---|---|
| tushare | 数据全面,但需要积分 | 专业回测、研究 | 积分不够时,日频数据都拿不全 |
| akshare | 免费、接口丰富 | 快速验证、小规模策略 | 偶尔数据更新延迟,得加重试机制 |
| baostock | 稳定、无需注册 | 入门学习、简单回测 | 数据维度少,没有财务指标 |
数据清洗流程:从原始数据到可用数据
数据拿到手,第一件事不是分析,而是清洗。我曾经有一次,从 tushare 拉了5年的日线数据,直接丢进回测引擎,结果收益率曲线漂亮得不像话。后来一查,原来是数据里混了退市整理期的股票,收益率被虚高了。从那以后,我养成了固定的清洗流程。
清洗流程说白了就三步:
- 格式统一:把日期转成 datetime 类型,把价格列转成 float,把代码统一成 6 位字符串。
- 异常值过滤:剔除涨跌幅超过 20% 的(A股有涨跌停限制),剔除成交量小于 0 的。
- 缺失值处理:这个我们单独说。
核心原则: 宁可数据少,不要数据脏。一条错误数据可能让你的回测结果完全失真。
缺失值处理:别让空值毁了你的策略
为什么会缺失?停牌、新股上市、退市、数据源本身就没提供。处理方式有几种,我按推荐程度排个序:
- 向前填充(ffill):用上一个交易日的值填充。适合价格数据,因为停牌期间价格不变。
- 直接删除:如果缺失比例小于 5%,直接删掉那几行。简单粗暴,但有效。
- 插值法:用前后值做线性插值。适合成交量这种连续数据。
- 千万别用均值填充:我见过有人用整个月的均价填充缺失的日价格,结果回测出来策略在停牌日疯狂交易——这明显是错的。
# 我常用的缺失值处理代码
import pandas as pd
def clean_missing(df):
# 先看缺失比例
missing_ratio = df.isnull().sum() / len(df)
print(f"缺失比例:{missing_ratio}")
# 价格列用向前填充
price_cols = ['open', 'high', 'low', 'close']
df[price_cols] = df[price_cols].ffill()
# 成交量用插值
df['volume'] = df['volume'].interpolate(method='linear')
# 如果还有缺失,直接删除
df = df.dropna()
return df
复权数据处理:前复权还是后复权?
这个问题,我当年纠结了很久。说白了,复权就是为了消除分红送股对价格的影响。你想想看,一只股票今天10块钱,明天10送10,价格变成5块。如果不复权,你的回测会以为股价腰斩了,但实际上你的资产没变。
两种复权方式的区别:
| 复权方式 | 原理 | 适合场景 |
|---|---|---|
| 前复权 | 调整历史价格,让价格连续 | 技术分析、看K线形态 |
| 后复权 | 调整当前价格,保持历史真实 | 计算真实收益率 |
我个人习惯用后复权做回测。为什么?因为后复权保留了历史价格的真实值,计算收益率时更准确。前复权虽然看起来K线连续,但会改变历史价格,导致你算出来的收益率和实际有偏差。
后复权价格 = 实际价格 × 复权因子
前复权价格 = 实际价格 / 当前复权因子 × 历史复权因子
# 用 tushare 获取复权数据的示例
import tushare as ts
# 获取复权因子
df_factor = ts.adj_factor(ts_code='000001.SZ')
# 获取日线数据(未复权)
df_daily = ts.daily(ts_code='000001.SZ', start_date='20230101', end_date='20231231')
# 合并并计算后复权价格
df = df_daily.merge(df_factor, on='trade_date')
df['close_adj'] = df['close'] * df['adj_factor']
知识体系总览
下面这张图,是我自己总结的数据获取与清洗的完整流程。你可以把它当成一个检查清单,每次做回测前过一遍。
嗯,数据获取与清洗这部分,说白了就是「磨刀不误砍柴工」。我见过太多人急着跑策略,结果被数据坑得怀疑人生。你花1小时把数据弄干净,后面能省10小时排查问题的时间。
最后提醒一句:每次拿到新数据,先画个图看看。价格曲线有没有断点?成交量有没有异常?一眼就能看出来。别问我怎么知道的——我曾经用了一周时间调试一个策略,最后发现是数据里多了一行空值。