I am trying to calculate the yield to maturity for bonds (working in Google Colab (Jupyter)).
The mathematical formulation of the problem is:
with price = $1276.76, number of periods = 60 [0.5 years] = 30 years, payment per period = $40 and final payment(par value) = $1000 and interest rate = r.
Where I am trying to derive the "r" through a function.
When going for an approach with hardcoding the formula and function I found herefore:
# 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)
I get the error: "invalid syntax" in the lambda line and when removing it (in order to check if the function itself works) "no module named 'bond_ytm'" even saving it as extra file in the same directory as (.jpynb) python file. I did also not understand the lambda in-line function, the dt array/for-loop, and where and why the bond_ytm is called from.
Here is a very similar approach form github, which also did not run, using another function for the second part:
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
And which left me with the same missing understanding.
Here is a large documentation to a package, where I can't know their methodology of calculation, but where I can enter the dates of the period manually and which allows for computing accrued interest between the payment (coupon) dates. 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])