3、因子数据获取:使用Python获取因子数据、数据清洗与预处理、因子标准化处理
好,咱们进入第三章。说实话,因子数据获取这块,是很多量化新手最容易翻车的地方。我见过太多人策略逻辑写得漂亮,结果数据源一塌糊涂,回测曲线看着完美,实盘一跑就崩。为什么?数据质量不行。
今天我就把我在实战中踩过的坑、总结的经验,一次性给你讲透。咱们从数据获取开始,一步步走到标准化处理。
3.1 数据获取:别让脏数据毁了你的策略
我个人习惯,数据获取分两步走:先确定数据源,再写获取逻辑。
常见的数据源有哪些?
- 免费公开数据:比如Tushare、AKShare、Yahoo Finance。适合个人研究、小规模回测。
- 商业数据库:Wind、Bloomberg、Quandl。机构用得最多,数据质量高,但贵。
- 自建数据库:用InfluxDB或MongoDB存自己清洗过的数据。我团队就是这么干的。
下面是一个用Python获取股票日行情的例子:
import akshare as ak
import pandas as pd
# 获取沪深300成分股日行情
stock_zh_a_hist_df = ak.stock_zh_a_hist(
symbol="000300",
period="daily",
start_date="20200101",
end_date="20231231",
adjust="qfq" # 前复权
)
print(stock_zh_a_hist_df.head())
嗯,这里要注意。很多新手直接拿原始数据就跑因子计算,结果发现收益率算出来是负的。为什么?因为没做复权处理。股票分红、送股都会影响价格连续性。我建议你始终用前复权数据,这样历史收益率才真实。
3.2 数据清洗与预处理:80%的时间花在这里
说实话,因子研究里最耗时的不是建模,而是数据清洗。我在项目中遇到过,一个看起来完美的动量因子,跑出来IC值全是负的。查了两天,发现是某只股票在2015年股灾期间有连续跌停,数据里出现了-20%的日收益率,把整个因子都带偏了。
清洗流程我一般这么走:
- 缺失值处理:先看缺失比例。低于5%的,直接删除或填充。高于30%的,这个因子基本废了。
- 异常值检测:用3σ原则或IQR方法。金融数据里,极端值往往是数据错误,不是真实信号。
- 行业与市值中性化:这个后面会细讲,但清洗阶段就要把行业分类和市值数据准备好。
- 时间对齐:不同频率的数据(日频、月频)要统一时间戳。我习惯用交易日历对齐。
代码示例——缺失值处理:
# 假设df是因子数据,index是日期,columns是股票代码
# 检查缺失比例
missing_ratio = df.isnull().mean()
# 删除缺失超过30%的股票
df = df.loc[:, missing_ratio < 0.3]
# 对剩余缺失值,用行业均值填充
# 假设industry是每只股票的行业标签
for industry in industry.unique():
mask = industry == industry
df.loc[:, mask] = df.loc[:, mask].fillna(
df.loc[:, mask].mean()
)
3.3 因子标准化处理:让不同因子站在同一起跑线
你想想看,市盈率因子取值范围可能是5到100,而换手率因子可能是0.1%到10%。如果不做标准化,你合成多因子时,市盈率会完全主导结果。这显然不合理。
常用的标准化方法有三种:
| 方法 | 公式 | 适用场景 |
|---|---|---|
| Z-score | (x - μ) / σ | 因子近似正态分布时 |
| Min-Max | (x - min) / (max - min) | 因子有明确上下界时 |
| Rank标准化 | 排序后映射到[0,1] | 因子有极端值时,最稳健 |
我个人最常用的是Rank标准化。为什么?金融数据里极端值太多了。Z-score对异常值敏感,一个极端值就能把整个分布拉偏。而Rank标准化只看相对排序,稳健得多。
核心逻辑:因子标准化不是为了改变因子本身的信息,而是为了消除量纲影响。你合成多因子时,每个因子的贡献应该是平等的。
代码示例——Rank标准化:
import numpy as np
from scipy.stats import rankdata
def rank_standardize(series):
"""
对因子序列进行Rank标准化
输出范围:[0, 1]
"""
# 计算排名
ranks = rankdata(series)
# 映射到[0, 1]
normalized = (ranks - 1) / (len(series) - 1)
return normalized
# 应用
df_standardized = df.apply(rank_standardize, axis=1)
嗯,这里有个细节。你注意看,我是按axis=1做的,也就是每个时间截面上对所有股票做标准化。为什么不是按股票做时间序列标准化?因为因子投资的核心是横截面比较——同一时刻,哪些股票因子值高,哪些低。时间序列标准化会破坏这种横截面信息。
3.4 本章知识体系总览
下面这张图,是我自己画的数据处理流程。你跟着这个流程走,基本不会出大问题。
3.5 实战中的几个小技巧
最后,分享几个我这些年总结出来的经验:
- 数据备份:原始数据永远不要直接修改。我习惯把原始数据存一份Parquet格式,清洗后的存另一份。万一洗错了,还能回滚。
- 因子监控:标准化之后,我会定期检查因子的分布。如果某个因子突然变成双峰分布,大概率是数据出了问题。
- 不要过度清洗:有些异常值其实是真实的市场信号。比如2015年股灾时的极端波动,你把它洗掉了,那你的风控因子就失效了。清洗前先问问自己:这个异常值,是数据错误还是市场行为?
好了,数据获取、清洗、标准化这三步走完,你的因子数据基本就准备好了。下一步就是因子测试和组合构建了。记住,数据质量决定了策略的天花板。你花在数据上的每一分钟,都会在回测结果里体现出来。