使用Python求解含大指数的债券到期收益率方程遇阻求助
求解债券YTM:SymPy solve()失效的替代方案
看起来你遇到了SymPy符号求解YTM方程的瓶颈——这很正常,因为债券YTM的方程本质是非线性超越方程,包含大量分数次幂,几乎不存在闭合形式的解析解,SymPy的solve()主要针对有解析解的方程,所以会失效。下面是几个可行的解决思路,附代码示例:
1. 改用SymPy的数值求解工具nsolve()
SymPy提供了nsolve()专门处理数值求解问题,你只需要提供方程、待解变量和一个合理的初始猜测值(YTM通常接近票息率,比如你的票息是4.375%,可以猜0.04)。
首先要确保你的方程是现值总和等于当前价格(你之前的代码只构建了现金流现值之和,需要减去当前价格得到等式0 = expr - price):
from sympy import symbols, nsolve, pow # 定义变量和参数 ytm = symbols('ytm', positive=True) # 约束YTM为正数,提升求解效率 current_price = 98 # 替换为你的实际债券价格 coupon = 4.375 face_value = 100 # 从你的表达式反推现金流时间:初始时间0.2356,每次加0.5,共57期(最后一期是28.7356) initial_exp = 0.235616438356164 periods = 57 # 构建完整的现值表达式(含最后一期票息+面值) expr = coupon / pow((1 + ytm), initial_exp) current_exp = initial_exp for _ in range(1, periods - 1): current_exp += 0.5 expr += coupon / pow((1 + ytm), current_exp) # 最后一期是票息+面值 current_exp += 0.5 expr += (coupon + face_value) / pow((1 + ytm), current_exp) # 构建方程:现值总和 = 当前价格 equation = expr - current_price # 数值求解,初始猜测值设为0.04(4%) ytm_solution = nsolve(equation, ytm, 0.04) print(f"YTM数值解:{ytm_solution.evalf(6)}") # 保留6位小数
2. 用SciPy的数值优化工具(更高效)
如果你的表达式非常复杂,SymPy的nsolve()可能速度较慢,这时可以用SciPy的数值求解函数(比如newton或root),它们处理大规模非线性方程的效率更高:
from scipy.optimize import newton import numpy as np def ytm_residual(ytm, price, coupon, face_value, cashflow_times): # 计算现值总和与当前价格的差值(残差) pv = sum(coupon / np.power(1 + ytm, t) for t in cashflow_times[:-1]) # 最后一期是票息+面值 pv += (coupon + face_value) / np.power(1 + ytm, cashflow_times[-1]) return pv - price # 构建现金流时间列表 cashflow_times = [0.235616438356164 + 0.5*i for i in range(57)] # 参数代入 current_price = 98 coupon = 4.375 face_value = 100 # 初始猜测值(票息率附近) initial_guess = 0.04 # 牛顿法求解 ytm_solution = newton(ytm_residual, initial_guess, args=(current_price, coupon, face_value, cashflow_times)) print(f"YTM数值解:{round(ytm_solution*100, 4)}%") # 转成百分比,保留4位小数
3. 先检查表达式的正确性
从你的输出看,第一个项是104.375*(...),这应该是最后一期的票息(4.375)加面值(100),但你的代码里是单独加100/pow(...),这可能导致表达式错误——确保最后一期的现金流是票息+面值,而不是分开计算,否则会少算一次票息。
关键注意点
- 初始猜测值:YTM的初始猜测一定要接近真实值(比如票息率),否则数值方法可能不收敛或得到错误解。
- 验证解:得到YTM后,代入表达式计算现值总和,看是否和当前价格一致(允许微小误差,因为数值求解有精度限制)。
- 单位一致性:确保所有参数的单位统一(比如YTM是年化收益率,时间以年为单位)。
内容的提问来源于stack exchange,提问作者M. Vlad
相关产品推荐
相关产品推荐

