You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python实现仿射模型从债券数据提取纯通胀预期及风险因子

用Python基于仿射模型提取纯通胀预期的实操指南

先理清楚核心逻辑

  • 盈亏平衡通胀(BEI)= 名义债券收益率 - TIPS实际收益率,但BEI里不止纯通胀预期,还混了通胀风险溢价和凸性调整项
  • 仿射模型是线性动态模型,天生适合处理债券收益率这类时间序列,新手可以先从简化版的线性近似入手,不用一开始就搞复杂的卡尔曼滤波

第一步:数据准备

你需要两类核心数据:

  • 同期限的名义债券收益率和实际收益率(比如1Y、2Y…10Y的月度数据)
  • 可选:CPI同比数据,用来验证结果
    用pandas导入数据的示例代码:
import pandas as pd
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt

# 假设你的数据是csv格式,列包含date、nominal_1y到nominal_10y、real_1y到real_10y、cpi_yoy
data = pd.read_csv("bond_data.csv", parse_dates=["date"], index_col="date")
# 处理缺失值,新手直接删或者插值都行
data = data.dropna()

第二步:先算出盈亏平衡通胀(BEI)

先把基础的BEI算出来,这是后续拆分的起点:

# 循环计算各期限BEI
for tenor in ["1y", "2y", "3y", "5y", "10y"]:
    data[f"bei_{tenor}"] = data[f"nominal_{tenor}"] - data[f"real_{tenor}"]

第三步:用简化版仿射模型拆分纯通胀预期、风险溢价和凸性

严格的仿射模型需要估计动态参数,但新手可以先用线性回归近似实现核心拆分逻辑:

1. 定义状态变量

选几个能解释通胀预期的核心变量:

  • 滞后一期的CPI同比(代表通胀惯性)
  • 长期名义收益率(代表货币政策预期)
  • 长期实际收益率(代表经济基本面)

2. 拟合模型并拆分

以10Y期限为例,代码如下:

# 构造回归用的自变量
data["inflation_lag"] = data["cpi_yoy"].shift(1)
X = sm.add_constant(data[["inflation_lag", "nominal_10y", "real_10y"]])
# 去掉移位产生的缺失值
X = X.dropna()
y = data["bei_10y"].loc[X.index]

# 拟合OLS模型,这里的拟合值就是我们要的纯通胀预期,残差就是风险溢价+凸性项
model = sm.OLS(y, X)
results = model.fit()

# 把结果存回数据框
data["pure_inflation_exp_10y"] = results.predict(X)
data["risk_premium_convexity_10y"] = y - results.predict(X)

3. 扩展到多期限

如果要处理所有期限,直接循环就行:

# 初始化字典存各期限结果
pure_exp = {}
risk_premium = {}

for tenor in ["1y", "2y", "3y", "5y", "10y"]:
    y = data[f"bei_{tenor}"].loc[X.index]
    # 拟合模型
    res = sm.OLS(y, X).fit()
    # 存结果
    pure_exp[tenor] = res.predict(X)
    risk_premium[tenor] = y - res.predict(X)

# 合并到主数据框
for tenor in pure_exp:
    data[f"pure_inflation_exp_{tenor}"] = pure_exp[tenor]
    data[f"risk_premium_convexity_{tenor}"] = risk_premium[tenor]

第四步:更精准的凸性调整(可选)

如果想单独拆分凸性项,可以用债券凸性公式计算:

# 计算各期限收益率的滚动方差(用6个月窗口)
window = 6
for tenor in ["1y", "2y", "3y", "5y", "10y"]:
    # 名义收益率方差
    nom_var = data[f"nominal_{tenor}"].rolling(window).var()
    # 实际收益率方差
    real_var = data[f"real_{tenor}"].rolling(window).var()
    # 凸性调整 = 0.5*(名义方差 - 实际方差)*期限^2(期限转成年数)
    tenor_years = int(tenor[:-1])
    data[f"convexity_{tenor}"] = 0.5 * (nom_var - real_var) * (tenor_years ** 2)
    # 单独的风险溢价 = 之前的残差 - 凸性调整
    data[f"inflation_risk_premium_{tenor}"] = data[f"risk_premium_convexity_{tenor}"] - data[f"convexity_{tenor}"]

第五步:可视化验证结果

把结果画出来,看看拆分是否合理:

plt.figure(figsize=(12, 6))
data["pure_inflation_exp_10y"].plot(label="10Y纯通胀预期")
data["bei_10y"].plot(label="10Y盈亏平衡通胀")
data["inflation_risk_premium_10y"].plot(label="10Y通胀风险溢价")
plt.legend()
plt.title("纯通胀预期、BEI与通胀风险溢价对比")
plt.show()

新手注意事项

  • 数据一定要对齐:名义和实际收益率的期限、时间维度必须严格匹配,否则结果完全没用
  • 如果要做严格的仿射模型(比如无套利NS模型),可以用statsmodels的状态空间模型或者filterpy的卡尔曼滤波,但先把简化版搞懂再进阶
  • 回归结果要检查显著性,比如看results.summary()里的P值,确保自变量确实能解释BEI

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 07:15:25