数据源与API:获取行业指数数据
做行业轮动分析,第一步就是搞数据。没有数据,再牛的模型也是空中楼阁。
我个人习惯把数据源分成三类:行情数据、宏观数据、另类数据。今天咱们重点聊前两个。
一、三大主流数据源
国内做量化,绕不开这三个平台。我一个个说。
1. Tushare
Tushare 是个人开发者用得最多的免费数据源。它覆盖了股票、基金、期货、宏观等全品类数据。
优点:文档清晰,社区活跃,免费额度够用。
缺点:积分制,高频数据需要付费。另外,接口偶尔会挂。
我在项目中遇到过 Tushare 凌晨数据更新延迟的情况。嗯,建议把数据抓取任务安排在早上8点以后。
核心接口示例:获取申万一级行业指数日线数据
import tushare as ts
# 初始化(需要你的token)
pro = ts.pro_api('your_token_here')
# 获取申万一级行业指数(2024年数据)
df = pro.index_daily(
ts_code='801010.SI', # 申万农林牧渔
start_date='20240101',
end_date='20241231',
fields='trade_date,open,high,low,close,vol'
)
print(df.head())
2. Wind(万得)
Wind 是机构标配。数据质量高,更新及时,但贵。一年几万块的终端费,个人用户基本用不起。
我建议:如果你在机构工作,优先用 Wind。数据清洗的工作量能少一半。
小技巧:Wind 的 Python 接口叫 WindPy,安装后需要先启动 Wind 客户端才能调用。
from WindPy import w
w.start()
# 获取行业指数行情
data = w.wsd(
"801010.SI", # 申万农林牧渔
"open,high,low,close,volume",
"2024-01-01",
"2024-12-31",
"PriceAdj=F" # 不复权
)
print(data.Data)
3. 东方财富(AkShare)
东方财富的数据可以通过 AkShare 库获取。免费,接口丰富,但文档有点乱。
说白了,AkShare 就是爬虫封装。它把东方财富网页上的数据扒下来,整理成 DataFrame。
import akshare as ak
# 获取申万一级行业指数
df = ak.sw_index_daily(
index_code="801010", # 农林牧渔
start_date="20240101",
end_date="20241231"
)
print(df.head())
注意:AkShare 依赖网络请求,如果东方财富改版,接口可能会失效。建议做好异常处理。
二、宏观经济数据获取
行业轮动离不开宏观背景。利率、CPI、PMI、社融数据,这些都是驱动因子。
我个人习惯用 Tushare 的宏观接口,数据全,更新快。
# 获取GDP数据
df_gdp = pro.cn_gdp(
start_q='20200101',
end_q='20241231',
fields='quarter,gdp,gdp_yoy'
)
# 获取CPI数据
df_cpi = pro.cn_cpi(
start_m='202001',
end_m='202412',
fields='month,cpi,cpi_yoy'
)
print(df_gdp.head())
print(df_cpi.head())
你想想看,如果宏观数据滞后两个月,你的行业轮动模型还能准吗?所以数据时效性很重要。
三、数据清洗与预处理
数据拿到手,别急着用。80%的时间其实花在清洗上。
我曾经因为没处理缺失值,导致回测结果异常漂亮——后来发现是数据断层了。嗯,血的教训。
1. 缺失值处理
import pandas as pd
import numpy as np
# 检查缺失值
print(df.isnull().sum())
# 方法一:向前填充(行业指数常用)
df['close'] = df['close'].fillna(method='ffill')
# 方法二:删除缺失行(慎用)
df = df.dropna(subset=['close'])
2. 异常值处理
行业指数很少出现极端异常,但个股数据经常有。我一般用3倍标准差法。
# 3倍标准差法剔除异常
mean = df['close'].mean()
std = df['close'].std()
df = df[(df['close'] > mean - 3*std) & (df['close'] < mean + 3*std)]
3. 日期对齐
不同数据源的日期可能不一致。比如 Tushare 用 '20240101',Wind 用 '2024-01-01'。统一格式是第一步。
# 统一日期格式
df['trade_date'] = pd.to_datetime(df['trade_date'], format='%Y%m%d')
df = df.sort_values('trade_date').reset_index(drop=True)
4. 行业分类映射
行业轮动需要把股票映射到行业。申万一级行业有31个,代码从801010到801890。
| 行业代码 | 行业名称 |
|---|---|
| 801010 | 农林牧渔 |
| 801020 | 采掘 |
| 801030 | 化工 |
| ... | ... |
| 801890 | 综合 |
建议:把行业映射表存成 CSV,每次直接读取,别硬编码。
四、知识体系总览
下面这张图,是我做数据获取时的完整流程。你看一眼就明白了。
五、避坑指南
最后,分享几个我踩过的坑。
- 数据频率不一致:行业指数是日频,宏观数据可能是月频。合并时注意对齐。
- 复权问题:行业指数一般用不复权数据。个股做回测时,记得用后复权。
- 接口限流:Tushare 免费版每分钟最多200次请求。批量获取时,加个 time.sleep(0.5)。
- 数据缓存:每次跑策略都重新拉数据,太慢了。我习惯把原始数据存成 parquet 格式,每天增量更新。
核心原则:数据质量决定策略上限。花80%时间在数据上,20%时间建模,这是值得的。