第三章:数据获取与清洗——用Python搞定宏观数据
各位同学,欢迎来到第三章。说实话,宏观择时模型里最磨人的不是算法设计,而是数据。我见过太多人模型跑得飞起,结果数据源一换,全盘崩溃。今天咱们就聊聊怎么用Python把宏观数据拿到手,再收拾干净。
3.1 数据源的选择:三个常用库
我个人习惯把数据源分成三类:国际宏观、国内宏观、另类数据。对应的Python库也各有千秋。
| 库名 | 适用场景 | 数据频率 | 我的评价 |
|---|---|---|---|
| pandas-datareader | 美联储、世界银行等国际数据 | 日/周/月 | 稳定,但更新慢 |
| tushare | A股、宏观经济指标 | 日/分钟 | 国内最全,但需要token |
| akshare | 中国宏观、行业数据 | 日/周/月 | 免费,接口多 |
你想想看,做宏观择时,至少需要GDP、CPI、PMI、利率、汇率这几类。我建议你三个库都装上,哪个能拿到就用哪个。
3.2 实战:用pandas-datareader拉美联储数据
先来个最简单的。拉美联储的联邦基金利率,这是宏观择时的核心变量。
import pandas_datareader.data as web
import datetime
start = datetime.datetime(2010, 1, 1)
end = datetime.datetime(2024, 12, 31)
# 联邦基金利率(FRED代码:FEDFUNDS)
fed_rate = web.DataReader('FEDFUNDS', 'fred', start, end)
print(fed_rate.head())
嗯,这里要注意:FRED的代码你得去官网查。我刚开始做的时候,把GDP的代码记成了'GDP',结果拉回来一堆空值。实际上应该是'GDPC1'(实际GDP)。
- FEDFUNDS - 联邦基金利率
- GDPC1 - 实际GDP
- CPIAUCSL - CPI
- UNRATE - 失业率
- DGS10 - 10年期国债收益率
3.3 国内数据:tushare和akshare的配合
做A股择时,国内宏观数据是必须的。tushare需要注册拿token,akshare则直接能用。我一般这样搭配:
import tushare as ts
import akshare as ak
# 设置tushare token(需要去官网申请)
ts.set_token('你的token')
pro = ts.pro_api()
# 获取中国GDP季度数据
gdp_data = pro.cn_gdp(start_q='2010Q1', end_q='2024Q4')
print(gdp_data.head())
# 用akshare获取PMI数据
pmi_data = ak.macro_china_pmi()
print(pmi_data.head())
说实话,tushare的宏观数据接口比较稳定,但免费版有调用次数限制。akshare虽然免费,但偶尔接口会变。我曾经遇到过akshare的PMI接口突然改了字段名,导致模型跑出来全是NaN。所以我的建议是:生产环境用tushare,研究阶段用akshare。
3.4 数据清洗:处理缺失值与异常值
数据拿到手,第一件事就是检查缺失值。宏观数据有个特点:发布频率不统一。GDP是季度数据,CPI是月度数据,利率是日度数据。合并的时候,缺失值就来了。
- 日度数据:用前向填充(ffill)
- 月度数据:用线性插值
- 季度数据:保留原样,不做填充
import pandas as pd
import numpy as np
# 假设我们合并了三个数据源
data = pd.DataFrame({
'fed_rate': fed_rate['FEDFUNDS'],
'gdp': gdp_data['gdp'],
'pmi': pmi_data['PMI']
})
# 检查缺失值
print(data.isnull().sum())
# 处理缺失值
data['fed_rate'] = data['fed_rate'].ffill() # 前向填充
data['pmi'] = data['pmi'].interpolate(method='linear') # 线性插值
# GDP季度数据,不做填充,直接保留NaN
# 处理异常值:用3倍标准差法
def remove_outliers(series, threshold=3):
mean = series.mean()
std = series.std()
return series.where((series - mean).abs() <= threshold * std, np.nan)
data['fed_rate'] = remove_outliers(data['fed_rate'])
为什么要用前向填充?因为宏观数据发布有滞后性。比如今天的利率数据,实际上是昨天的值。前向填充正好模拟了这个逻辑。
3.5 数据对齐:不同频率的合并技巧
不同频率的数据合并,是宏观择时里最头疼的事。我总结了一个通用流程:
# 统一对齐到日度数据
# 1. 将季度数据转换为日度(用前一个值填充)
gdp_daily = data['gdp'].resample('D').ffill()
# 2. 将月度数据转换为日度
pmi_daily = data['pmi'].resample('D').ffill()
# 3. 合并所有数据
aligned_data = pd.concat([data['fed_rate'], gdp_daily, pmi_daily], axis=1)
aligned_data = aligned_data.dropna() # 删除仍然缺失的行
print(aligned_data.head())
你想想看,如果直接用原始频率建模,模型会报错。所以这一步是必须的。我个人习惯把所有数据都对齐到日度,因为择时信号通常是日频调仓。
3.6 本章知识体系
下面这张图是我自己画的,把数据获取与清洗的整个流程串起来了:
说白了,数据获取与清洗就是三个步骤:拿到数据、处理脏数据、对齐频率。每一步都有坑,但踩过之后你就知道怎么避开了。
get_macro_data() 函数,一行代码就能拿到清洗好的数据。
好了,这一章就到这里。数据准备好了,下一章咱们就可以开始搭建择时模型了。记住:数据质量决定模型上限,别在这步偷懒。