第三章 因子数据获取:数据源选择与清洗
做因子投资,第一步就是搞数据。这步要是没做好,后面再牛的模型也是白搭。我见过太多人,策略回测漂亮得很,一上实盘就崩——十有八九是数据源头出了问题。
今天咱们就聊聊,数据到底从哪来,怎么拿,拿到手之后怎么处理。嗯,这里要注意,数据获取不是简单的“调个API就完事”,里面的坑多着呢。
3.1 数据源怎么选?
国内主流的数据源,我基本都用过。说白了,没有完美的数据源,只有最适合你的。
| 数据源 | 优势 | 劣势 | 适合人群 |
|---|---|---|---|
| Wind | 数据最全,财务数据清洗到位 | 贵,一年几万块 | 机构、专业团队 |
| Tushare | 免费版够用,社区活跃 | 积分限制,高频数据不全 | 个人研究者、学生 |
| JoinQuant | 回测平台自带数据,方便 | 导出受限,本地化麻烦 | 平台用户 |
| AkShare | 完全免费,接口丰富 | 稳定性一般,需自己清洗 | 预算有限的开发者 |
3.2 股票行情数据获取
行情数据是最基础的。日线、分钟线、Tick级数据,需求不一样,获取方式也不同。
拿日线数据举例,用Tushare的话,代码很简单:
import tushare as ts
# 设置token
ts.set_token('你的token')
pro = ts.pro_api()
# 获取平安银行日线数据
df = pro.daily(ts_code='000001.SZ',
start_date='20230101',
end_date='20231231')
print(df.head())
这里有个坑——复权问题。我曾经在回测时直接用原始价格,结果分红除权后,策略信号全乱了。后来才意识到,因子计算必须用后复权价格。
3.3 财务数据获取
财务数据比行情数据麻烦得多。为什么?因为财报有季节性,而且经常修正。
获取财务数据时,要注意几个关键点:
- 财报发布日期 vs 财报期:要用实际可得的日期,而不是财报所属期
- 数据修正:很多公司会修正前期财报,你得跟踪最新版本
- 行业分类:不同行业的财务指标可比性差,需要标准化
举个例子,获取某股票的利润表:
# 获取利润表数据
income = pro.income(ts_code='000001.SZ',
start_date='20230101',
end_date='20231231',
fields='ts_code,end_date,revenue,profit')
# 注意:这里拿到的end_date是财报截止日
# 实际可用日期要查公告日期
print(income.head())
核心要点:财务数据一定要做“前瞻性处理”。也就是说,你在回测时只能用当时已经公布的财报,不能用未来数据。这个错误我见过太多人犯了。
3.4 宏观经济数据获取
宏观数据对因子策略的影响,很多人低估了。GDP、CPI、PMI、利率,这些都会影响因子表现。
获取宏观数据,我推荐几个渠道:
- 国家统计局:官方数据,最权威,但格式不友好
- Wind宏观数据库:整理好了,直接调用
- FRED(美联储):做全球策略必备
用Tushare获取宏观数据也很方便:
# 获取GDP数据
gdp = pro.cn_gdp(start_q='2020Q1', end_q='2023Q4')
print(gdp)
# 获取CPI数据
cpi = pro.cn_cpi(start_m='202301', end_m='202312')
print(cpi)
3.5 数据清洗与预处理
数据拿到手,别急着用。清洗这步,我一般花掉整个数据流程的60%时间。你想想看,脏数据进去,垃圾结果出来,多冤啊。
清洗的核心步骤:
- 缺失值处理:是填充还是删除?要看情况
- 异常值检测:3倍标准差?还是IQR方法?
- 数据对齐:不同频率的数据要对齐到同一时间轴
- 去极值:因子值太极端会影响后续分析
我常用的清洗代码:
import pandas as pd
import numpy as np
def clean_factor_data(df, factor_col):
"""因子数据清洗函数"""
# 1. 删除全空的行
df = df.dropna(subset=[factor_col], how='all')
# 2. 去极值(MAD方法)
median = df[factor_col].median()
mad = np.abs(df[factor_col] - median).median()
upper = median + 5 * mad
lower = median - 5 * mad
df[factor_col] = df[factor_col].clip(lower, upper)
# 3. 标准化
df[factor_col] = (df[factor_col] - df[factor_col].mean()) / df[factor_col].std()
return df
3.6 本章知识体系
下面这张图,是我自己总结的数据获取全流程。你照着这个框架走,基本不会漏掉关键环节。
这张图把整个数据流程串起来了。从数据源选择,到具体数据类型获取,再到最后的清洗预处理,每一步都环环相扣。你按照这个框架来,至少能避开80%的坑。
最后说一句:数据获取没有捷径。我做了这么多年,最大的体会就是——花在数据上的时间,永远不会白费。你前期把数据搞扎实了,后面的因子分析、策略构建才能站得住脚。