如何基于债券数据拟合Vasicek模型参数?现有代码结果异常求修正
Vasicek模型债券拟合问题排查与修复
核心错误点
- 数据映射错误:你提供的期限数组
years长度为6,价格数组pric长度为7,且首元素设为0不符合金融逻辑:零息债券0时刻到期价格应为面值1,且价格和期限需要一一对应。 - 模型输入错误:Vasicek是短期利率模型,输入变量应为即期利率,你直接把债券价格当作利率
r代入模型计算,完全不符合模型定义。 - 离散化逻辑错误:Vasicek的SDE离散形式需要考虑时间间隔
Δt,你忽略了非均匀期限的间隔差异,也没有使用正确的转移分布公式,仅用简单差分计算误差项。 - 优化逻辑错误:你构造的对数似然函数需要最大化,但你使用了
least_squares最小二乘优化器,且初始参数[10,10,10]远超出合理范围,导致优化结果偏离正确值。
正确实现方案
实现步骤
- 从债券价格计算对应期限的即期利率
- 计算相邻期限的时间间隔
Δt - 基于Vasicek精确离散形式的正态转移分布构造对数似然函数
- 带参数约束最小化负对数似然求解最优参数
完整代码
import numpy as np import scipy.optimize as opt # 数据预处理:修正价格与期限对应关系 years = np.array([1, 2, 3, 4, 7, 10]) # 去掉原价格数组的错误首元素0,对应6个期限的债券价格 bond_prices = np.array([.93, .85, .78, .65, .55, .42]) # 零息债券即期利率计算公式:r(T) = -ln(P(T))/T r = -np.log(bond_prices) / years # 计算相邻观测的时间间隔 dt = np.diff(years) r_prev = r[:-1] r_next = r[1:] def neg_log_likelihood(params): a, b, sigma = params # 避免参数为负导致计算异常 if a <= 1e-6 or sigma <= 1e-6: return 1e10 # Vasicek精确转移分布的均值和方差 exp_a_dt = np.exp(-a * dt) mean = r_prev * exp_a_dt + b * (1 - exp_a_dt) var = sigma**2 * (1 - np.exp(-2*a*dt)) / (2*a) # 计算对数似然,忽略不影响优化结果的常数项 ll = -0.5 * np.sum(np.log(var) + (r_next - mean)**2 / var) # 返回负对数似然用于最小化 return -ll # 合理初始参数:a=0.1(均值回复速度), b=0.05(长期利率5%), sigma=0.01(波动率1%) init_params = [0.1, 0.05, 0.01] # 参数约束:a>0, b>0, sigma>0 bounds = [(1e-6, None), (1e-6, None), (1e-6, None)] # 优化求解 result = opt.minimize(neg_log_likelihood, init_params, bounds=bounds) # 输出拟合结果 a_opt, b_opt, sigma_opt = result.x print(f"拟合得到Vasicek参数:") print(f"均值回复速度a = {a_opt:.4f}") print(f"长期平均利率b = {b_opt:.4f}") print(f"波动率sigma = {sigma_opt:.4f}")
内容的提问来源于stack exchange,提问作者ElonMuskofBadIdeas
相关产品推荐
相关产品推荐

