如何在Sympy中计算内部收益率(IRR)与到期收益率(YTM)?
求解债券到期收益率(YTM)的Python实现方法
问题背景
给定债券参数:面值1000美元,年票息50美元,当前售价900美元,3年后到期,YTM满足方程:
900 = 50/(1+r) + 50/(1+r)² + 50/(1+r)³ + 1000/(1+r)³
以下两种方法均可求解r:
方法一:用Sympy直接求解
Sympy的符号求解器可以直接处理这个非线性方程,步骤如下:
- 导入sympy库并定义符号变量
r - 构建方程表达式
- 调用求解方法后,筛选出合理的正利率解(YTM为正)
代码示例:
import sympy as sp # 定义符号变量 r = sp.symbols('r') # 构建方程:令等式左右差值为0 equation = sp.Eq(900, 50/(1+r) + 50/(1+r)**2 + 50/(1+r)**3 + 1000/(1+r)**3) # 求解方程 solutions = sp.solve(equation, r) # 筛选有效解:实数且为正 valid_r = [sol.evalf() for sol in solutions if sol.is_real and sol > 0] print(f"YTM(r)的值为:{valid_r[0]}")
运行后会得到约0.0891(即8.91%)的结果。
方法二:手动实现牛顿法
如果不想依赖符号计算库,也可以用牛顿迭代法逼近方程的根,思路如下:
- 定义目标函数
f(r):债券理论价格与实际价格的差值,即f(r) = 50/(1+r) + 50/(1+r)² + 1050/(1+r)³ - 900(合并最后一期的票息与面值) - 计算目标函数的导数
f'(r),用于牛顿迭代公式 - 设置初始迭代值(比如0.05,因为票息率为5%,债券折价发行,YTM应高于此值)
- 迭代计算直到结果精度满足要求
代码示例:
def bond_ytm(price, face_value, coupon, years, precision=1e-6, max_iter=100): # 初始猜测值 r = 0.05 for _ in range(max_iter): # 计算当前r对应的债券现值 pv = sum(coupon/(1+r)**t for t in range(1, years+1)) + face_value/(1+r)**years # 计算现值对r的导数 dp_dr = sum(-t*coupon/(1+r)**(t+1) for t in range(1, years+1)) - years*face_value/(1+r)**(years+1) # 牛顿迭代更新r r_new = r - (pv - price)/dp_dr # 检查精度是否达标 if abs(r_new - r) < precision: return r_new r = r_new # 迭代未收敛返回None return None # 代入参数计算 ytm = bond_ytm(900, 1000, 50, 3) print(f"YTM(r)的值为:{ytm:.4f}")
运行结果同样约为0.0891(8.91%)。
内容的提问来源于stack exchange,提问作者Flux
相关产品推荐
相关产品推荐

