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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:08:02