In [1]:
using Dates, Roots
include("jlFiles/printmat.jl")
include("jlFiles/printTable.jl")
Out[1]:
In [2]:
using Plots
#pyplot(size=(600,400))
gr(size=(480,320))
default(fmt = :svg)
In [3]:
include("jlFiles/BondCalculations.jl")
Out[3]:
The calculations below assume that the yield curve is flat, but that it can shift up or down in parallel. This assumption is similar to the classical literature on duration hedging.
The initial values are indicated by the subscript $_0$ and the values after the interest rate change by the subscript $_1$. It is assumed that the change is very sudden, so the time to the different cash flows is (virtually) the same before and after.
The next cell sets up the cash flow for a liability that pays 0.2 each year for the next 10 years. The value of the liability is calculated at an initial interest rate ($\theta_0$) and at a new interest rate ($\theta_1$).
In [4]:
θ₀ = 0.05 #initial interest rate
θ₁ = 0.03 #interest rate after sudden change
cf = fill(0.2,10) #cash flow of liability
m = 1:10 #time periods of the cash flows
P₀ = BondPrice3(θ₀,cf,m)
P₁ = BondPrice3(θ₁,cf,m)
R = (P₁ - P₀)/P₀
printblue("As θ changes from θ₀=$θ₀ to θ₁=$θ₁:")
xy = [P₀, P₁, R]
printTable(xy,[" "],["P₀";"P₁";"ΔP/P₀"],width=15)
printred("Notice that the liability is worth more at the lower interest rate")
In [5]:
"""
BondDuration(P,cf,m,ytm)
Calculate Macaulays (bond) duration measure.
P: scalar, bond price
cf: scalar or K vector of cash flows
m: K vector of times of cash flows
ytm: scalar, yield to maturity
"""
function BondDuration(P,cf,m,ytm)
cdisc = cf.*m./((1+ytm).^m) #c/(1+y) + 2c/(1+y)^2 + ...
Dmac = sum(cdisc)/P #Macaulays duration
return Dmac
end
Out[5]:
In [6]:
Dmac = BondDuration(P₀,cf,m,θ₀)
printlnPs("Macaulay's duration",Dmac)
Δθ = θ₁ - θ₀
R_approx = -Dmac*Δθ/(1+θ₀)
println("\nExact and approximate relative price change: ")
printlnPs(R,R_approx)
Suppose we are short one bond $L$ (this is the liability), which is worth $P_L$. To hedge that we buy $v$ units of bond $H$. The balance is put on a money market account $M$ to make the initial value of the portfolio zero ($V=0$)
$V=vP_{H}+M-P_{L}$.
Over a short time interval, the change in the portfolio value is
$\Delta V=v\Delta P_{H}-\Delta P_{L}$.
In the cells below, we assume that the yield curve is flat and shifts in parallel. This means that the ytm of both instruments change from one common value ($\theta_0$) to another common value ($\theta_1$).
In [7]:
PL₀ = P₀ #just switching notation: this is the value of the liability
PL₁ = P₁
printblue("Value of liability at different interest rates θ₀ and $θ₁:")
printTable([PL₀,PL₁],[""],["PL₀","PL₁"])
printblue("Macaulay's duration of the liability:")
printlnPs(Dmac)
In [8]:
PH₀ = BondPrice3(θ₀,1,Dmac)
PH₁ = BondPrice3(θ₁,1,Dmac)
v = PL₀/PH₀
ΔV = v*(PH₁-PH₀) - (PL₁-PL₀)
R = ΔV/PL₀
printblue("Hedge bond: a zero coupon bond with m=$(round(Dmac,digits=2)) and face value of 1")
xy = [PL₀,PH₀,v,v*PH₀/PL₀,Dmac,Dmac,R]
printTable(xy,[" "],["PL₀","PH₀","v","v*PH₀/PL₀","Dur(liability)","Dur(hedge)","Return"])
printred("Notice, the duration matching gives a return of $(round(R*100,digits=1))%. Close to zero.")
The "naive" hedging invests the same amount in the hedge bond as the value of the liability, that is, $hP_{H}=P_{L}$ so $v=P_{L}/P_{H}$. This means that the money market account is not used ($M=0$).
The effectiveness of this approach depends on the interest rate sensitivity of the two instruments. In particular, it can be shown that
$\frac{\Delta V}{P_{L}}\approx\left( D_{L}^{M}-D_{H}^{M}\right) \times \frac{\Delta\theta}{1+\theta}$.
If $D_{L}>D_{H}$, and $\Delta\theta<0$ (as in the example below), then we will lose money.
In [9]:
mH = 3 #mH year bill is used as hedge bond
PH₀ = BondPrice3(θ₀,1,mH)
PH₁ = BondPrice3(θ₁,1,mH)
v = PL₀/PH₀
ΔV = v*(PH₁-PH₀) - (PL₁-PL₀)
R = ΔV/PL₀
printblue("Hedge bond: zero coupon bond with m=$mH and face value of 1")
xy = [PL₀,PH₀,v,v*PH₀/PL₀,Dmac,mH,R]
printTable(xy,[" "],["PL₀","PH₀","v","v*PH₀/PL₀","Dur(liability)","Dur(hedge)","Return"])
printred("The naive hedge gives a return of $(round(R*100,digits=1))%, which is a bad hedge")
In [10]:
θ = 0:0.01:0.1 #possible ytm values
(PL,PH) = (fill(NaN,length(θ)),fill(NaN,length(θ)))
for i = 1:length(θ)
PL[i] = BondPrice3(θ[i],cf,m)
PH[i] = BondPrice3(θ[i],1,mH)
end
txt = "In our example, the interest rates \nare $θ₀ (before) and $θ₁ (after)"
plot( θ,[PL v*PH],
linecolor = [:red :green],
linestyle = [:solid :dash],
label = ["liability" "v * hedge bond price"],
title = "Naive hedging",
xlabel = "Interest rate",
ylabel = "Value of position",
annotation = (0.005,1.4,text(txt,8,:left)) )
Out[10]:
When $D_{L}^{M}\neq D_{H}$, we could adjust the hedge ratio $v$ to compensate for the difference in interest rate sensitivity (duration). In particular, we could set
$v =\frac{D_{L}^{M}}{D_{H}^{M}}\times\frac{P_{L}}{P_{H}}$.
The balance $(P_L-hP_H)$ is kept on a money market account ($M$).
It can be shown that this gives an (approximate) hedge.
In [11]:
PH₀ = BondPrice3(θ₀,1,mH)
PH₁ = BondPrice3(θ₁,1,mH)
v = Dmac/mH * PL₀/PH₀
M = PL₀ - v*PH₀ #on money market account
ΔV = v*(PH₁-PH₀) - (PL₁-PL₀)
R = ΔV/PL₀
printblue("Hedge bond: zero coupon bond with m=$mH and face value of 1")
xy = [PL₀,PH₀,v,v*PH₀/PL₀,Dmac,mH,M,R]
printTable(xy,[" "],["PL₀","PH₀","v","v*PH₀/PL₀","Dur(liability)","Dur(hedge)","M","Return"])
printred("Notice, the duration hedging gives a return of $(round(R*100,digits=1))%. Close to zero.")
In [12]:
function BondConvexity(P,cf,m,ytm)
cdisc = cf.*m.*(m.+1)./((1+ytm).^(m.+2))
C = sum(cdisc)/P
return C
end
Out[12]:
In [13]:
C = BondConvexity(P₀,cf,m,θ₀)
printblue("Convexity")
xy = [C;Δθ;0.5*C*Δθ^2]
printTable(xy,[" "],["C";"Δθ";"0.5*C*Δθ^2"])
printred("Compare the magnitude to ΔPH/PH: ",round((PH₁-PH₀)/PH₀,digits=3))
In [ ]: