3. 数据获取与清洗:数据源选择与清洗流程
做因子择时,第一步就是搞定数据。我见过太多人策略写得漂亮,结果数据源没选对,回测全是噪音。今天咱们就把这块掰开揉碎了讲。
3.1 数据源选择:选对工具,事半功倍
我个人习惯把数据源分成三类:专业终端、开源库、量化平台。各有各的脾气,咱们一个个说。
3.1.1 Wind(万得)
Wind 是机构标配。数据全、更新快、接口稳定。但贵,一年几万块。适合机构用户。
优点:财务数据、行业分类、一致预期,这些因子数据 Wind 最全。
缺点:贵,而且本地安装,远程调用麻烦。
我建议:如果你在机构工作,直接上 Wind。个人做研究,可以先跳过。
3.1.2 Tushare
Tushare 是开源界的良心。免费版够用,Pro 版也不贵。数据覆盖 A 股、基金、期货。
优点:上手快,文档清晰,社区活跃。
缺点:免费版有调用次数限制,高频数据不太行。
避坑指南:我曾经用 Tushare 拉日线数据,没注意积分限制,跑到一半被限流了。建议先注册 Pro 版,花点积分买基础权限。
3.1.3 聚宽(JoinQuant)
聚宽是量化平台,也提供数据接口。本地和云端都能用。
优点:数据与回测平台无缝对接,因子计算方便。
缺点:本地版数据更新有延迟,财务数据不如 Wind 细。
我个人经验:做因子择时回测,我常用聚宽的数据做初步验证,再用 Wind 做最终确认。
3.1.4 数据源对比
| 数据源 | 费用 | 数据覆盖 | 更新速度 | 适合场景 |
|---|---|---|---|---|
| Wind | 高(年费数万) | 全市场 | 实时 | 机构、生产环境 |
| Tushare | 低(免费/积分) | A股为主 | T+1 | 个人研究、回测 |
| 聚宽 | 中(免费/付费) | A股+期货 | T+1 | 策略开发、回测 |
3.2 数据清洗流程:脏数据是策略的毒药
数据拿到手,别急着算因子。先洗一遍。我见过有人用未清洗的数据跑出漂亮曲线,实盘直接崩了。为什么?因为异常值在回测里是「神」,在实盘里是「鬼」。
3.2.1 去极值
因子数据里经常有极端值。比如某只股票一天涨了 20%,这可能是数据错误,也可能是真实事件。但不管怎样,它会严重扭曲你的统计结果。
常用方法:MAD(中位数绝对偏差)法、百分位法。
我个人习惯:用 MAD 法,稳健性更好。百分位法容易把正常值也切掉。
# MAD 去极值示例
import numpy as np
def winsorize_mad(data, n=5):
median = np.median(data)
mad = np.median(np.abs(data - median))
upper = median + n * mad
lower = median - n * mad
return np.clip(data, lower, upper)
3.2.2 标准化
不同因子的量纲不一样。比如市盈率是几十倍,换手率是百分之几。不标准化,你没法比较它们。
常用方法:Z-score 标准化、Min-Max 归一化。
我建议:因子择时用 Z-score。因为它保留了数据的分布形态,而且对异常值不敏感(前提是去极值做干净了)。
# Z-score 标准化
def standardize_zscore(data):
mean = np.mean(data)
std = np.std(data)
return (data - mean) / std
3.2.3 中性化
中性化是为了剔除市场、行业、市值等系统性因素的影响。说白了,就是让因子「纯净」一点。
举个例子:你发现小市值股票涨得好,但这不是因子本身的能力,而是市值风格在起作用。中性化之后,你才能看到因子真正的选股能力。
常用方法:回归残差法。把因子对市值、行业做回归,取残差作为中性化后的因子。
# 市值中性化示例(简化版)
import statsmodels.api as sm
def neutralize_factor(factor, market_cap, industry_dummies):
X = pd.concat([market_cap, industry_dummies], axis=1)
X = sm.add_constant(X)
model = sm.OLS(factor, X).fit()
residual = model.resid
return residual
3.3 数据清洗流程图
下面这张图是我自己总结的清洗流程。每次做因子研究,我都按这个步骤走一遍。
3.4 避坑指南
- 数据对齐:不同数据源的日期格式可能不同。我建议统一用 YYYY-MM-DD 格式,避免解析错误。
- 复权处理:做因子择时,一定要用后复权数据。前复权会引入未来信息,回测会失真。
- 缺失值处理:不要直接 dropna。有些因子天然有缺失(比如次新股没有历史数据)。我习惯用行业均值填充,或者用前向填充。
- 数据缓存:每次跑回测都从数据源拉数据,太慢了。我建议第一次拉完后存成本地 parquet 文件,后续直接读本地。
好了,数据获取和清洗就讲到这里。记住:干净的数据是策略的基石。下一章咱们聊聊因子计算的具体方法。