-
Return and Variance 7
-
Lecture1.1
-
Lecture1.2
-
Lecture1.3
-
Lecture1.4
-
Lecture1.5
-
Lecture1.6
-
Lecture1.7
-
-
Solving Equations 5
-
Lecture2.1
-
Lecture2.2
-
Lecture2.3
-
Lecture2.4
-
Lecture2.5
-
-
Capital Allocation Line 6
-
Lecture3.1
-
Lecture3.2
-
Lecture3.3
-
Lecture3.4
-
Lecture3.5
-
Lecture3.6
-
-
Diversification 3
-
Lecture4.1
-
Lecture4.2
-
Lecture4.3
-
-
Investment Sets 3
-
Lecture5.1
-
Lecture5.2
-
Lecture5.3
-
-
Portfolios 7
-
Lecture6.1
-
Lecture6.2
-
Lecture6.3
-
Lecture6.4
-
Lecture6.5
-
Lecture6.6
-
Lecture6.7
-
-
Capital and Security Market Lines 3
-
Lecture7.1
-
Lecture7.2
-
Lecture7.3
-
-
Arbitrage 3
-
Lecture8.1
-
Lecture8.2
-
Lecture8.3
-
-
Dividend Discount Model 2
-
Lecture9.1
-
Lecture9.2
-
-
Fixed Income 4
-
Lecture10.1
-
Lecture10.2
-
Lecture10.3
-
Lecture10.4
-
-
Duration and Immunization 4
-
Lecture11.1
-
Lecture11.2
-
Lecture11.3
-
Lecture11.4
-
Duration Part 2
Solution
def duration(couponRate,periods,r):
flows = [couponRate]*periods
flows[-1]+=1
periodsAr = list(range(1,periods+1))
pv = [x/(1+r)**y for x,y in zip(flows,periodsAr)]
price = sum(pv)
weights = [x/price for x in pv]
duration = sum([x*y for x,y in zip(periodsAr,weights)])
return duration
duration(.05,3,.08)
Duration is the same regardless of face value, only coupon rate, periods and r matter.
We say that our flows are couponRate for each period, until the last (-1) period where we add 1 to represent the full face value we receive.
Now, let’s investigate how a changing coupon rate effects the duration.
import matplotlib.pyplot as plt
couponRate = [x/100 for x in range(0,21)]
durationAr = [duration(x,3,.08) for x in couponRate]
plt.plot(couponRate,durationAr)
plt.xlabel("Coupon Rate")
plt.ylabel("Duration")
plt.title("Duration vs. Coupon Rate")
plt.show()
At a 0% coupon rate, the duration equals the period of the bond because all of the weight is in the single payment at the end. As the coupon rate rises, the duration lowers because the weight becomes more equally spread.
How does r change the duration?
import matplotlib.pyplot as plt
r = [x/100 for x in range(0,21)]
durationAr = [duration(.05,3,x) for x in r]
plt.plot(couponRate,durationAr)
plt.xlabel("Discount Rate")
plt.ylabel("Duration")
plt.title("Duration vs. Discount Rate")
plt.show()
As the interest rate goes up, the duration lowers because the present value of later payments are discounted more heavily.
Duration also has an interesting application to risk. If we know duration, we can approximate percentage change in a bond price for a change in r.
Equation
%ΔP = Percentage Change in Price
D = Duration
%Δr = Change (not percentage change) in r
Let’s see how close the approximation is.
def bondValue(r,fv,year,cr):
final_pay = fv/(1+r)**year
coupon_payment = (fv*cr)
annuity_value = coupon_payment*(1-(1+r)**(-year))/r
return annuity_value+final_pay
p1 = bondValue(.08,1000,3,.05)
p2 = bondValue(.082,1000,3,.05)
print(p1)
print(p2)
print((p2-p1)/p1)
d = duration(.05,3,.08)
print(-d/(1.08)*.002)
Not too bad!
The term d/(1+r) is also known as modified duration, another duration term.