第二章:数据准备——数据源选择、清洗与对齐

做多因子模型,说白了就是跟数据打交道。我见过太多人,策略逻辑写得天花乱坠,结果一跑回测就崩——十有八九是数据出了问题。这一章,咱们就把数据准备这块硬骨头啃下来。

2.1 数据源怎么选?tushare vs akshare

国内做量化,绕不开两个库:tushare 和 akshare。我个人习惯是两者搭配着用,但各有侧重。

对比项 tushare akshare
数据质量 较高,经过校验 中等,部分接口不稳定
获取难度 需要积分(部分免费) 完全免费,但接口多
速度 较快,有缓存机制 依赖源网站,有时慢
适用场景 核心因子计算 辅助数据、实时行情

我在项目中遇到过这样的情况:用 akshare 拉某只股票的复权数据,结果某天突然多了一根大阴线。后来一查,是源网站数据更新延迟导致的。所以我的建议是——核心因子用 tushare,辅助数据用 akshare。

小技巧: 如果你刚开始做研究,可以先从 akshare 入手,零成本试错。等策略成型了,再切换到 tushare 做正式回测。

2.2 数据清洗——脏数据是最大的敌人

数据清洗听着枯燥,但你不做,模型就会给你颜色看。我总结了三步走:

  1. 去重:同一个交易日出现两条数据,保留最新的那条。
  2. 补缺失:停牌日的数据用前值填充,别用0。
  3. 去异常:涨跌幅超过±20%的,大概率是数据错误。

嗯,这里要注意一点:停牌日的处理。我曾经犯过一个错,直接把停牌日的收益率设为0,结果回测曲线漂亮得不像话——因为停牌期间没有亏损。后来才发现,这是典型的未来函数。

警告: 千万不要用未来数据填充缺失值!比如用后一天的收盘价来补前一天的缺失,这等于作弊。

2.3 数据对齐——让所有因子站在同一起跑线

多因子模型里,不同因子的更新频率可能不一样。比如市盈率每天更新,但财报数据每季度才更新一次。如果不做对齐,你可能会用到未来数据。

我的做法是:统一使用「交易日历」作为时间轴。所有因子数据,都对齐到每个交易日的收盘时刻。

# 伪代码示例:数据对齐
import pandas as pd

# 假设 trade_dates 是交易日列表
trade_dates = pd.date_range('2023-01-01', '2023-12-31', freq='B')

# 市盈率数据(日频)
pe = pe.reindex(trade_dates, method='ffill')

# 财报数据(季频)
eps = eps.reindex(trade_dates, method='ffill')

你想想看,如果财报数据在发布前就被用上了,那回测结果能信吗?所以对齐这一步,再怎么小心都不为过。

2.4 防止未来函数——量化界的「作弊器」

未来函数,说白了就是你在回测时用到了「当时还不知道」的信息。比如用今天的收盘价去预测今天的涨跌,这明显是作弊。

我遇到过最隐蔽的未来函数是:用 tushare 的复权因子时,没注意它是「后复权」。后复权会把未来的分红也算进去,导致历史价格被修改。这样一来,你的策略看起来能精准抄底——其实是因为数据被「未来」调整过了。

核心原则: 回测时,只能使用「截至当前时刻」已知的数据。任何需要未来信息才能计算的数据,都是未来函数。

怎么防?我的经验是:

  • 用前复权数据,而不是后复权
  • 因子计算时,确保只用到历史数据
  • 回测框架里加一个「数据时间戳」校验

2.5 本章知识体系图

下面这张图,帮你理清数据准备的整个流程:

数据准备核心流程 数据源选择 tushare / akshare 数据清洗 去重 / 补缺失 / 去异常 数据对齐 统一交易日历 防止未来函数(贯穿始终) 数据质量 = 策略生命线 每一步出错,回测结果都可能失真

这张图里,数据源、清洗、对齐是三个主要步骤,而防止未来函数是贯穿始终的红线。我每次搭建新模型,都会把这张图打印出来贴在显示器边上——提醒自己别在数据上偷懒。

我的习惯: 每次拉完数据,先随机抽10只股票,手动核对几天的数据。虽然麻烦,但能发现很多自动化检查漏掉的问题。

好了,数据准备这块就聊到这儿。记住一句话:数据干净了,策略才靠谱。下一章咱们开始讲因子计算,到时候你会感谢今天认真清洗数据的自己。


公众号:蓝海资料掘金营,微信deep3321