2、数据获取与清洗:多资产数据源介绍
做跨资产关联性分析,第一步就是搞数据。
说实话,这一步最枯燥,但也最重要。数据搞砸了,后面所有模型都是白搭。我个人习惯把数据获取和清洗看作整个量化流程的「地基」——地基不稳,楼盖得再高也得塌。
2.1 多资产数据源:股票、债券、商品、外汇
不同资产类别的数据源,各有各的门道。我一个个说。
股票数据
股票数据相对好拿。A股市场,我个人常用的是Tushare和AkShare。这两个都是Python库,免费版够用,但要注意频率限制。
美股的话,Yahoo Finance(通过yfinance库)是最简单的入口。不过Yahoo的数据偶尔会有缺失,我遇到过几次分红除权后价格没调整的情况,嗯,这里要注意。
债券数据
债券数据就麻烦多了。国内债券市场,中债登和中证登的数据最权威,但基本要付费。我个人习惯用Wind或聚宽的数据接口,虽然也要钱,但数据质量有保障。
国债收益率曲线、信用利差这些,做跨资产分析时经常用到。如果你没有付费数据源,可以用央行官网公布的国债收益率,虽然更新慢一点,但胜在免费。
商品数据
商品期货数据,国内有上期所、大商所、郑商所。我建议直接用tushare.pro或者akshare,它们已经把各个交易所的数据整合好了。
国际商品(黄金、原油、铜),可以用yfinance获取对应的ETF数据。比如黄金看GLD,原油看USO。但要注意,ETF跟踪的是期货价格,不是现货价格,两者有基差。
外汇数据
外汇数据,我推荐yfinance或者forex-python库。主要货币对(EUR/USD、USD/JPY、GBP/USD)的数据比较干净。
做跨资产分析时,外汇数据经常被忽略。但你想,美元强弱会影响商品价格,也会影响新兴市场股市。所以外汇数据一定要纳入。
数据源总结表
| 资产类别 | 推荐数据源 | 注意事项 |
|---|---|---|
| A股 | Tushare, AkShare | 注意复权处理 |
| 美股 | yfinance | 分红除权可能未调整 |
| 债券 | Wind, 聚宽 | 免费数据质量参差不齐 |
| 商品 | tushare.pro, akshare | 期货有换月问题 |
| 外汇 | yfinance, forex-python | 注意点差和交易时间 |
2.2 数据对齐与重采样
不同资产的数据频率不一样。股票是日频,债券可能是周频,外汇是24小时交易。怎么把它们对齐?
说白了,就是统一时间戳。
数据对齐
我一般用Pandas的merge或join方法,按日期做外连接。这样能保留所有数据点,缺失值用NaN填充。
import pandas as pd
# 假设stock_df和bond_df都有'date'列
aligned_df = pd.merge(stock_df, bond_df, on='date', how='outer')
aligned_df = aligned_df.sort_values('date').fillna(method='ffill')
这里有个坑:不同市场的交易日历不一样。A股有春节、国庆长假,美股有感恩节、圣诞节。直接用merge会留下很多NaN。我建议先统一交易日历,比如只保留所有市场都交易的日期。
小技巧:用pd.bdate_range()生成交易日序列,然后对每个资产做重采样,能省不少事。
重采样
重采样就是把高频数据转成低频,或者反过来。做跨资产分析,我通常统一到日频。
# 将5分钟数据重采样为日数据
daily_df = minute_df.resample('D').last()
为什么用last()而不是close?因为外汇市场没有明确的收盘价,我习惯用最后一个交易价格作为当日收盘价。
低频转高频(比如周频转日频)要小心。直接用插值会引入未来信息。我一般用前向填充(ffill),至少不会泄露数据。
2.3 异常值处理
异常值处理,说白了就是「揪出那些不对劲的数据」。
常见的异常值类型
- 价格跳空:比如某股票突然从100元跳到1000元,明显是数据错误
- 收益率极端值:日收益率超过±20%,大概率是异常
- 缺失值:某天数据突然没了,需要处理
检测方法
我常用的方法有三种:
- Z-score法:计算每个数据点与均值的标准差倍数,超过3倍就标记为异常
- IQR法:四分位距法,超出Q1-1.5*IQR或Q3+1.5*IQR的算异常
- 百分比变化法:日收益率超过某个阈值(比如±10%)就标记
def detect_outliers(series, method='zscore', threshold=3):
if method == 'zscore':
z = (series - series.mean()) / series.std()
return z.abs() > threshold
elif method == 'iqr':
Q1 = series.quantile(0.25)
Q3 = series.quantile(0.75)
IQR = Q3 - Q1
return (series < Q1 - 1.5*IQR) | (series > Q3 + 1.5*IQR)
警告:Z-score法对极端值敏感,因为极端值本身会影响均值和标准差。我建议先用IQR法粗筛一遍,再用Z-score法精筛。
处理方式
发现异常值后,怎么处理?
- 删除:如果异常值很少(比如不到1%),直接删掉
- 填充:用前一个交易日的数据填充(
ffill) - 插值:用前后数据做线性插值,但要注意不要引入未来信息
- Winsorize:将异常值替换为阈值(比如用99%分位数替换)
我曾经遇到过一个案例:某债券数据连续三天收益率都是0,明显是数据源出了问题。我查了半天,发现是数据提供商在节假日没有更新数据。最后我用前向填充解决了。
2.4 本章知识体系
下面这张图,是我做跨资产数据清洗时的核心流程。你可以照着这个思路来。
嗯,数据获取与清洗这部分,说白了就是「磨刀不误砍柴工」。我见过太多人急着跑模型,结果数据里一堆坑,最后花几倍时间返工。所以,别急,把这一步做扎实了,后面会顺很多。
核心要点回顾
- 不同资产用不同数据源,注意数据质量和频率
- 数据对齐是跨资产分析的前提,统一交易日历是关键
- 异常值检测用IQR+Z-score组合,处理时优先保留数据完整性
- 清洗后的数据一定要做可视化检查,肉眼看看有没有明显异常