Yield to Maturity for Bond Pricing
Yield to Maturity in Fixed Income
The Yield to Maturity basically poses the following question:
What r or YTM when applied solves to produce a Present Value = $1010.77? The equation can not be solved algebraically so we will have to rely on numerical or grid search techniques like goal seek in Excel. Below we will also employ the bisection technique which is heavily utilized in Finance.
What r or discount rate can be applied so that the present value of coupons and Face equate to the current market price of bond of $1010.77.
More generally, yield to maturity is the discount rate at which the sum of all future cash flows from the bond (coupons and principal) is equal to the current price of the bond. The yield to maturity provides us with an estimate of the internal rate of return for the bond. This can be important for investors when comparing one bond relative to another. Below, we estimate the Yield of Maturity (YTM) of a Bond using Excel Goal Seek and then introduce the Bisection technique to verify results.
VBA code for Bisection Technique when estimating Yield to Maturity
In the video above we estimate yield to maturity using Goal Seek in Excel. We then automate estimate this estimation using the Bisection technique. This same technique is used for estimating Implied Volatility. When there is closed form formula - we arrive at estimate using trial and error. This can be accomplished by using Bisection
' PV of Bond using PV of Annuity
Function PVBm(cpr, r, T, Face, m)
coup = Face * cpr / m
PVBm = (coup * (1 - (1 + r / m) ^ (-T * m)) / (r / m)) + Face * (1 + r / m) ^ (-T * m)
End Function
' YTM of Bond using Bisection
Function PVBmIRR(cpr, T, Face, m, Target)
H = 2
L = 0
Do While (H - L) > 0.0001
If PVBm(cpr, ((H + L) / 2), T, Face, m) > Target Then
L = (H + L) / 2
Else: H = (H + L) / 2
End If
Loop
PVBmIRR = (H + L) / 2
End Function
Yield to Maturity using Interpolation
For exam purposes and quizzes where manual estimation is relied upon students are generally obliged to use interpolation. For completeness, we introduce the interpolation below using the numerical example set out above
More on Bisection
Below, we create a single unified non-referenced VBA function to estimate Yield to maturity.
Function PVBmIRR(cpr, T, Face, m, Target)
Coup = Face * cpr / m
' PVBm = (Coup * (1 - (1 + r / m) ^ (-T * m)) / (r / m)) + Face * (1 + r / m) ^ (-T * m)
H = 2
L = 0
Do While (H - L) > 0.0001
If (Coup * (1 - (1 + ((H + L) / 2) / m) ^ (-T * m)) / (((H + L) / 2) / m)) + Face * (1 + ((H + L) / 2) / m) ^ (-T * m) > Target Then
L = (H + L) / 2
Else: H = (H + L) / 2
End If
Loop
PVBmIRR = (H + L) / 2
End Function
C++ code for Yield to Maturity for Bond using Bisection
#include <cmath>
#include <iostream>
using namespace std;
double PVB(double Face,double cr,double r,int m, double T)
{
// store the value of the bond
double BV=0.;
// add in coupons
int TNC=T*m;
double cpn = (cr/m)*Face;
for(int i=1;i<=TNC; i++)
{
BV = BV + cpn*pow((1+r/m),-i);
}
BV = BV + Face*pow((1+r/m),-T*m);
return BV;
}
// Bisection Algorithm
double BisecYTM(double Face, double cr, double Target, double T, int m, double a, double b) {
const int MaxIter = 50000;
double Tol = 0.0000001;
double midP = 0.0, midCdif;
double lowCdif = Target - PVB(Face, cr,a, m, T);
double highCdif = Target - PVB(Face, cr, b, m, T);
if (lowCdif*highCdif > 0)
return -1;
else
for (int i = 0; i <= MaxIter; i++) {
midP = (a + b) / 2.0;
midCdif = Target - PVB(Face,cr,midP,m,T);
if (abs(midCdif)<Tol) goto LastLine;
else {
if (midCdif>0) b = midP;
else a = midP;
}
}
LastLine:
return midP;
}
int main()
{
double Face = 1000;
double cr = 0.06;
double Target = 1010.91;
double T = 3;
int m = 2;
double a = 0.000001;
double b = 10;
double YTM = BisecYTM(Face,cr,Target,T, m,a,b);
cout << " YTM = " << YTM << " " << endl;
}
Python Code for Yield to Maturity from Jeffrey Liang Repository based on Bernt Odegaard Financial recipes
The python code below comes Jeffrey Liang github. The examples are based on the workings of Bernt Arne Ødegaard. A copy of Financial Recipes you can be found here. We estimate Yield to Maturity.
# https://bit.ly/2R0yRy5
def bonds_price_discrete(times, cashflows, r):
p = 0
for i in range(len(times)):
p += cashflows[i] / np.power((1 + r), times[i])
return p
def bond_yield_to_maturity_discrete(times, cashflows, bondprice):
ACCURACY = 1e-5
MAX_ITERATIONS = 200
bot = 0
top = 1.
while bonds_price_discrete(times, cashflows, top) > bondprice:
top = top * 2
r = .5 * (top + bot)
for _ in range(MAX_ITERATIONS):
diff = bonds_price_discrete(times, cashflows, r) - bondprice
if np.abs(diff) < ACCURACY:
return r
if diff > 0:
bot = r
else:
top = r
r = .5 * (top + bot)
return r
import numpy as np
c = np.array([60, 60, 1060])
t = np.arange(1, 4)
r = .056
b = np.sum(c * (1. / np.power((1 + r), t)))
print('Bond price, 5.6% percent discretely compounded interest = {:.3f}'.format(
bonds_price_discrete(t, c, r)))
print('bond yield to maturity = {:.4f}'.format(bond_yield_to_maturity_discrete(t, c, b)))