第二章 数据基础与准备:金融数据来源与清洗
做量化研究,有一句话我特别认同:垃圾进,垃圾出。你因子逻辑再漂亮,回测框架再牛,数据源头是脏的,结果就是废的。这一章,我们就来聊聊数据那些事儿。
核心观点:因子研究80%的时间花在数据准备上,20%花在因子构建和检验上。别嫌烦,这是基本功。
2.1 金融数据来源:你该选哪个?
国内主流的数据源,我接触过三个:Wind、Tushare、聚宽。各有各的脾气。
| 数据源 | 特点 | 适合人群 | 成本 |
|---|---|---|---|
| Wind | 数据最全、最权威,API稳定,但贵 | 机构、专业团队 | 高(年费数万) |
| Tushare | 开源免费,社区活跃,但数据质量参差 | 个人、小团队、学习 | 低(积分制) |
| 聚宽 | 平台化,数据+回测一体,方便但封闭 | 策略开发、快速验证 | 中(有免费额度) |
我个人习惯是:机构用Wind,个人用Tushare。聚宽适合快速跑通逻辑,但真要搭因子库,还是得自己拉数据。
小技巧:如果你用Tushare,记得申请token后先缓存到本地。我刚开始用的时候,每次跑脚本都重新拉,结果被限流了……后来改成每天盘后拉一次存CSV,省心多了。
2.2 数据清洗:去极值与缺失值处理
数据拉下来,第一件事不是算因子,而是洗数据。脏数据主要有两类:极值和缺失值。
2.4.1 去极值:别让异常值带偏你
什么叫极值?比如某只股票某天涨了1000%,或者市盈率突然变成负数。这些数据点会严重扭曲你的因子分布。
常用的方法有三种:
- MAD法(中位数绝对偏差):稳健,适合非正态分布。我常用这个。
- 百分位法:直接砍掉上下1%或5%的数据。简单粗暴。
- 标准差法:超过3倍标准差就干掉。适合正态分布的数据。
举个例子,用MAD法去极值:
import numpy as np
def winsorize_mad(series, n=5):
median = np.median(series)
mad = np.median(np.abs(series - median))
upper = median + n * mad
lower = median - n * mad
return np.clip(series, lower, upper)
# 使用
factor_values = [1.2, 1.5, 1.3, 100.0, 1.4, 1.1, 1.6]
cleaned = winsorize_mad(factor_values)
print(cleaned) # 100.0 会被压缩到合理范围
注意:去极值不是删除数据,而是把极端值拉到边界。我曾经见过有人直接删掉异常值,结果导致时间序列不连续,回测时出现跳空——那叫一个惨。
2.4.2 缺失值处理:别让NaN毁了你的因子
金融数据缺失太常见了。停牌、新股上市、数据源没更新……都会产生NaN。
我的处理原则是:
- 时间序列数据:用前向填充(ffill)或插值。比如停牌日,用前一交易日的数据。
- 截面数据:用行业均值填充。比如某只股票的市盈率缺失,用同行业其他股票的均值补上。
- 实在补不了的:直接删除该样本。但要注意,删除比例不能太高,超过5%就要警惕了。
代码示例:
import pandas as pd
# 前向填充
df['factor'] = df['factor'].ffill()
# 行业均值填充
df['factor'] = df.groupby('industry')['factor'].transform(
lambda x: x.fillna(x.mean())
)
避坑指南:我曾经用ffill填充停牌数据,结果忘了处理复牌当天的跳空。因子值连续几天不变,复牌后突然变回真实值,导致因子信号出现假突破。后来我加了一个判断:如果连续填充超过5天,就标记为缺失,重新处理。
2.3 数据对齐与频率统一
因子数据、价格数据、财务数据,它们的频率可能不一样。日频、周频、月频,甚至分钟频。直接拿来用,时间戳对不上,结果就是错位。
举个例子:你要算一个基于月频财务数据的因子,但价格数据是日频的。如果不做对齐,你可能会用上个月的财务数据去预测下个月的收益——这属于未来函数,回测里看着漂亮,实盘就完蛋。
我的做法是:
- 统一时间戳:把所有数据都对齐到交易日历。非交易日的数据要么填充,要么删除。
- 频率降采样:高频数据向低频对齐。比如日频数据转周频,取每周最后一个交易日的数据。
- 频率升采样:低频数据向高频对齐。比如月频财务数据,在当月所有交易日重复使用。
代码示例:
# 日频数据转周频
df_weekly = df_daily.resample('W').last()
# 月频数据填充到日频
df_daily['factor'] = df_monthly.reindex(df_daily.index, method='ffill')
重要:对齐时一定要考虑滞后性。财务数据通常在财报发布后才能用,不能直接用财报截止日的数据。我一般会在财报发布日之后的下一个交易日才开始使用该数据。
2.4 本章知识体系
下面这张图,帮你理清数据准备的全流程:
嗯,数据准备这块,说白了就是耐心活。你想想看,因子库搭得再好,数据源头是脏的,后面所有工作都是白费。我见过太多人花几个月搭因子库,结果回测漂亮、实盘拉胯,一查原因——数据对齐没做好,用了未来数据。
所以,这一章的内容,值得你反复看、反复练。数据干净了,你的因子研究才算真正开始。