4. 数据获取与清洗:银行间市场数据源、Wind/QE接口、数据预处理
做银行间市场流动性分析,第一步就是搞定数据。说实话,这一步卡住了不少人。我见过太多分析师,模型建得漂漂亮亮,结果数据源没选对,或者清洗不到位,最后结论全是错的。今天咱们就把这块硬骨头啃下来。
4.1 银行间市场核心数据源
银行间市场的数据,说白了就三大类:行情数据、交易数据、衍生品数据。每一类都有它特定的获取渠道。
| 数据类别 | 典型指标 | 主要数据源 | 更新频率 |
|---|---|---|---|
| 货币市场 | DR001、DR007、Shibor、R001 | Wind、QE、中国货币网 | 日频 |
| 债券市场 | 国债收益率、信用利差、成交量 | Wind、QE、中债登 | 日频/周频 |
| 衍生品市场 | IRS利率、国债期货、利率互换 | Wind、QE、CFETS | 日频/分钟频 |
| 央行操作 | OMO、MLF、TMLF、SLF | 央行官网、Wind | 事件驱动 |
我个人习惯,把数据源分成「官方源」和「商业源」。官方源比如中国货币网、中债登、上清所,数据最权威,但接口往往不太好用。商业源像Wind、QE,封装得好,但价格不菲。嗯,这里要注意:做量化回测时,尽量用商业源,因为数据连续性更好。
4.2 Wind接口实战
Wind在固收领域,几乎是标配。我用Python调Wind接口已经五六年了,踩过的坑能写本书。先看个最基础的例子:
import pandas as pd
from WindPy import w
# 启动Wind服务
w.start()
# 获取DR007历史数据
dr007 = w.wsd("DR007.IB", "close", "2024-01-01", "2024-12-31", "")
# 返回的是Wind特有的格式,需要转换
df_dr007 = pd.DataFrame(dr007.Data, index=dr007.Fields, columns=dr007.Times).T
# 获取Shibor 3M数据
shibor_3m = w.wsd("SHIBOR3M.IR", "close", "2024-01-01", "2024-12-31", "")
df_shibor = pd.DataFrame(shibor_3m.Data, index=shibor_3m.Fields, columns=shibor_3m.Times).T
print(df_dr007.head())
为什么会这样?因为Wind底层是用C++写的,Python接口只是封装。所以数据格式跟pandas原生习惯不太一样。你想想看,如果每次都要手动转格式,多麻烦。所以我写了个小工具函数:
def wind_to_df(data):
"""将Wind数据转换为标准DataFrame"""
if data.ErrorCode != 0:
print(f"Error: {data.ErrorCode}")
return None
df = pd.DataFrame(data.Data, index=data.Fields, columns=data.Times).T
df.index = pd.to_datetime(df.index)
return df
# 使用示例
df_dr007 = wind_to_df(w.wsd("DR007.IB", "close", "2024-01-01", "2024-12-31", ""))
4.3 QE接口实战
QE是后来崛起的金融数据平台,在债券数据方面有独特优势。尤其是信用债的估值数据,QE比Wind更全。我记得有一次做信用利差分析,Wind上缺了不少AA+级城投债的数据,换成QE就全了。
import qe
# 初始化QE客户端
qe_client = qe.QEClient()
# 获取国债收益率曲线
treasury_yields = qe_client.get_yield_curve(
bond_type="treasury",
start_date="2024-01-01",
end_date="2024-12-31",
tenors=["1Y", "3Y", "5Y", "10Y"]
)
# 获取IRS利率
irs_data = qe_client.get_irs_rate(
currency="CNY",
start_date="2024-01-01",
end_date="2024-12-31",
tenors=["1Y", "5Y"]
)
print(treasury_yields.head())
4.4 数据预处理——避坑指南
数据拿到手,别急着分析。预处理这步,我吃过太多亏了。曾经有一次,因为没处理节假日缺失值,导致流动性指标计算出了大问题,被领导叫去喝茶。从那以后,我总结了一套标准流程:
4.4.1 缺失值处理
银行间市场的数据,节假日必然缺失。还有的时候,某些债券当天没成交,也会缺失。处理方法要分情况:
- 利率类数据(DR、Shibor):用前值填充。因为利率有粘性,不会突然跳变。
- 成交量类数据:用0填充。没成交就是0,别自作聪明插值。
- 收益率曲线数据:用插值法。中债登每天都会发布曲线,但如果你自己算,可以用线性插值。
# 缺失值处理示例
def fill_missing_data(df, method="ffill"):
"""
根据数据类型选择填充方法
method: 'ffill' 前向填充, 'zero' 零填充, 'interpolate' 插值
"""
if method == "ffill":
return df.fillna(method='ffill')
elif method == "zero":
return df.fillna(0)
elif method == "interpolate":
return df.interpolate(method='linear')
else:
raise ValueError("不支持的填充方法")
# 利率数据用前向填充
df_rates_filled = fill_missing_data(df_dr007, "ffill")
# 成交量用零填充
df_volume_filled = fill_missing_data(df_volume, "zero")
4.4.2 异常值检测
银行间市场偶尔会有「乌龙指」或者数据录入错误。比如DR007突然飙到10%,明显不合理。我一般用两种方法:
- 3-sigma法则:超过均值±3倍标准差的数据,标记为异常。
- IQR方法:超过Q1-1.5*IQR或Q3+1.5*IQR的数据,标记为异常。
def detect_outliers_iqr(data, column):
"""用IQR方法检测异常值"""
Q1 = data[column].quantile(0.25)
Q3 = data[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = data[(data[column] < lower_bound) | (data[column] > upper_bound)]
return outliers
# 检测DR007异常值
outliers = detect_outliers_iqr(df_dr007, "close")
print(f"发现 {len(outliers)} 个异常值")
4.4.3 日期对齐与重采样
不同数据源的日期可能不一致。Wind用交易日历,QE用自然日,央行操作又是事件驱动。做分析前,必须统一时间轴。
# 统一到交易日历
def align_to_trading_calendar(df, calendar="CHINA_IB"):
"""
对齐到银行间市场交易日历
calendar: 'CHINA_IB' 银行间, 'CHINA_STOCK' 交易所
"""
from pandas.tseries.offsets import CustomBusinessDay
from pandas.tseries.holiday import AbstractHolidayCalendar
# 这里简化处理,实际需要加载完整的交易日历
trading_days = pd.date_range(start=df.index.min(),
end=df.index.max(),
freq='B') # 仅做示例
df_aligned = df.reindex(trading_days)
return df_aligned
# 重采样到周频
df_weekly = df_dr007.resample('W').mean()
4.5 数据质量检查清单
我每次做完数据清洗,都会过一遍这个清单。你可以直接拿去用:
| 检查项 | 检查方法 | 常见问题 |
|---|---|---|
| 缺失率 | df.isnull().sum() / len(df) | 节假日缺失、数据源中断 |
| 重复值 | df.duplicated().sum() | 接口重复调用、数据合并错误 |
| 边界值 | df.describe() 查看min/max | 负利率、异常高值 |
| 时间连续性 | 检查日期是否连续 | 跳空、停牌日未处理 |
| 跨源一致性 | 对比Wind和QE同指标 | 计算口径不同、四舍五入差异 |
4.6 本章知识体系
下面这张图,是我自己梳理的数据获取与清洗流程。你可以把它当作操作手册:
这张图把整个流程分成了三层。数据源层解决「从哪拿」的问题,清洗层解决「怎么处理」的问题,质量检查层解决「对不对」的问题。我建议你每次做数据准备时,都按这个流程走一遍,能省掉很多返工的麻烦。
好了,数据获取和清洗这块,核心内容就这些。记住一句话:垃圾进,垃圾出。数据质量不过关,后面再漂亮的模型都是白搭。下一章咱们会用到今天清洗好的数据,来做流动性指标的构建和可视化。
公众号:蓝海资料掘金营,微信deep3321