我正在尝试计算债券的到期收益率(在 Google Colab (Jupyter) 中工作)。 该问题的数学公式为: 价格 = $1276.76,期数 = 60 [0.5 年] = 30 年,每期付款 = $40,最终付款(面值)= $1000,利率 = r。
我试图通过函数导出“r”。
当寻求对公式和函数进行硬编码的方法时,我发现:
# Yield to maturity
""" Get yield-to-maturity of a bond """
import scipy.optimize as optimize
def bond_ytm(price, par, T, coup, freq=2, guess=0.05):
freq = float(freq)
periods = T*freq
coupon = coup/100.*par/freq
dt = [(i+1)/freq for i in range(int(periods))]
ytm_func = lambda(y): \
sum([coupon/(1+y/freq)**(freq*t) for t in dt]) + \
par/(1+y/freq)**(freq*t) - price
return optimize.newton(ytm_func, guess)
from bond_ytm import bond_ytm
ytm = bond_ytm(95.0428, 100, 1.5, 5.75, 2)
print(ytm)
我收到错误:lambda 行中的“无效语法”,并且在删除它时(为了检查函数本身是否有效)“没有名为“bond_ytm”的模块”,甚至将其保存为与 (. jpynb) python 文件。 我也不理解 lambda 内联函数、dt 数组/for 循环以及 bond_ytm 的调用位置和原因。
这是来自 github 的非常相似的方法,它也没有运行,第二部分使用另一个函数:
https://github.com/jamesmawm/Mastering-Python-for-Finance-source-codes/blob/master/B03898_05_Codes/bond_ytm.py
if __name__ == "__main__":
ytm = bond_ytm(95.0428, 100, 1.5, 5.75, 2)
print ytm
这让我也失去了同样的理解。
这是一个软件包的大型文档,我不知道他们的计算方法,但我可以在其中手动输入期间日期,并允许计算付款(优惠券)日期之间的应计利息。 https://bond-pricing.readthedocs.io/en/latest/#module-bond_pricing.simple_bonds:
>>> bond_yield(settle="2012-04-15", mat="2022-01-01", cpn=8e-2,
... price=94.33, freq=1)
0.08884647275135965
>>> bond_yield(mat=10.25, cpn=8e-2, price=93.37, freq=2)
0.09000591604105035
>>> bond_yield(settle="2012-04-15", mat="2022-01-01", cpn=8e-2,
... price=[93, 94, 95], freq=1)
array([0.09104904, 0.08938905, 0.08775269])
如果你想找到的是内部收益率,有一个 numpy 金融库(需要与
pip
安装)可以找到它。
>>> import numpy_financial as npf
>>> npf.irr([-1276.76] + [40]*60 + [1000])
0.02985264673122634
有很多包可以执行此计算。让我展示一个使用 scipy 中的
fsolve
的解决方案。
你需要 numpy 和 scipy:
import numpy as np
from scipy.optimize import fsolve
您的问题的参数是:
首先,在代码中设置参数。然后将要优化的函数
func
定义为:
代码是:
freq = 2 # frequency of payments = 2 yearly
P = 1000 # par
C = 0.04 * P # coupon payment = coupon rate x principal
T = 30 # time to maturity (years)
price = 1276.76
def func(x, *p):
P, C, T, freq, price = p # unpack the parameters
t = (np.arange(T*freq) + 1) / freq # time vector
return [np.sum((C/freq) / (1+x[0]/freq)**(t*freq)) + P / (1+x[0]/freq)**(T*freq) - price]
p0 = P, C, T, freq, price
root = fsolve(func, [0.06], args=p0) # 0.06 is an initial guess
root
array([0.02655854])
这里,
fsolve
返回优化函数的根,实际上您正在求解产量x(未知数)。
让我们检查一下公式是否返回债券的价格:
y = root[0]
t = (np.arange(T*freq) + 1) / freq
print(np.sum((C/freq) / (1+y/freq)**(t*freq)) + P / (1+y/freq)**(T*freq))
1276.760000000002
哪个是正确的。