Calculation of Key Rate Durations using R code

This post explains how to calculate the key rate durations (KRD). Ho (1992) introduces KRD to measure non-parallel movements of the yield curve that the existing duration measures can not describe as these are defined under the assumption of a parallel shift of the yield curve.


Key Rate Duration using R code



Ho (1992) introduced the concept of the key rate duration (hereafter KRD), which is a new measure of interest rate risk exposure. KRD is a vector of the price sensitivity of a bond to each key rate change. The sum of the key rate durations is identical to the effective duration. The sum of the product of key rate durations and each yield changes in key rates (with negative sign) is the bond price change due to the non-parallel shift of the yield curve.



Key Rate Shifts


Unlike the traditional effective duration, KRD is calculated not from a par yield curve but from a zero curve (spot rate) so that the bump and reprice are performed on selected spot rates (key rates). In other words, individual effective durations are calculated by shift of each spot rate at each key maturity and the sum of them is the KRD.

Formally, ith key rate shift is defined to be zero shift for maturities shorter than (i-1)th key rate and longer than (i+1)th key rate. Interestingly, the shift between these two adjacent key rates is defined by the linear interpolation with the peak at the ith key rate.

Calculation of Key Rate Duration using R code

As can be seen in the above figure, yellow colored maturity is assumed to be the selected maturities of key rates. Ho (1992) suggests the size of shift as 10 bp but we use 1%(=100bp) simply for illustration purpose. A shift of one key rate by 1% affects its neighborhood of that key rate with linear interpolation. Rates outside the range of selected key maturities are set simply by the nearest key rate.

In particular, the light blue colored line (bottom) illustrates the shifts at all maturities, which resulted from 60M key rate's change. In this case, all the key rates except 60M are not affected but two adjacent rates at 54M and 66M are affected linearly.

The ith shifted yield curve is the sum of the initial yield curve (blue colored solid line) and its shifts at all maturities, which resulted from the change of ith key rate. When we add up all shifted changes together on the initial yield curve, we can get the parallel shifted curve (red colored solid line).


Key Rate Durations


By shifting each key rates, we can get N shifted zero curves (N is the number of key rates). Using these N shifted zero curves, each effective duration (\(KRD_i, i=1,...,N \)) is calculated with the initial zero curve.

\[\begin{align} KRD_i = \frac{P_{i,down} - P_{i,up}}{2 \times P_0 \times \Delta s(t_i)} \end{align}\]
Here, \(P_{i,down}\) and \(P_{i,up}\) are bond prices with up and down shifts to ith key rate respectively and \(s(t_i)\) is a spot rate at time \(t_i\).

The percent change in bond price given a shift in ith key rate is calculated as follows.

\[\begin{align} \frac{\Delta P_i}{P} = -KRD_i \times \Delta s(t_i) \end{align}\]
By definition, the sum of KRDs is the effective duration of a bond.

\[\begin{align} D = \sum_{i=1}^N KRD_i \end{align}\]
The shift of the yield curve can be approximated by the sum of all the key rate shifts.

\[\begin{align} \frac{\Delta P}{P} = - \sum_{i=1}^N KRD_i \times \Delta s(t_i) \end{align}\]

Key Rate Shifts in R code


As will be shown in R code, it is worth noting that a vector of shifts due to a key rate movement is appended horizontally with the name of its key rates as follows.

Calculation of Key Rate Duration using R code

Therefore, each shifted zero curve can be calculated by simply summing the initial zero curve and the corresponding shift vector.


R code


R code below implements the above explanations. After calculating we compare the sum of key rate durations with the traditional effective duration. When we use not 0.01 (1%) but 0.0001 (1bp) as a small change in a key rate, two duration measures are nearly the same in the perspective of numerical calculation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#========================================================#
# Quantitative Financial Econometrics & Derivatives 
# ML/DL using R, Python, Tensorflow by Sang-Heon Lee 
#
# https://shleeai.blogspot.com
#--------------------------------------------------------#
# Key Rate Durations
#========================================================#
 
graphics.off(); rm(list = ls())
 
#=======================================================
# read data
#=======================================================
str.zero <- "matm zero
             12    0.022
             24    0.030
             36    0.040
             48    0.046
             60    0.050
             72    0.052
             84    0.053
             96    0.053
            108    0.053
            120    0.054"
 
df <- read.table(text = str.zero, header = TRUE)
 
v.key_matm <- df$matm # maturities for key rates
nkey       <- length(v.key_matm)
 
# linear interpolation of zero rates
f_interpol <- approxfun(df$matm, df$zero, rule = 2)
 
# fill rates between key rates by 6M tenor
matm = seq(6,120,6)
df.sa <- data.frame(matm = matm)
nobs <- length(matm)
 
df.sa$zero <- f_interpol(matm)
 
# 10Y YTM
YTM10 <- 0.0527780789520333
CPN10 <- YTM10 # 10Y coupon = par yield rate
 
 
#=======================================================
# read data
#=======================================================
 
# rate shift : 0.0001 is preferable
dr = 0.0001
 
# make a table of dr for each key rates
for(n in 1:nkey) {
    df.sa <- cbind(df.sa, NA)
    colnames(df.sa)[2+n] <- as.character(v.key_matm[n])
    
    key_matm <- v.key_matm[n]
    
    # set dr to the same key maturity
    # set  0 to other key rates
    # set NA to rates between key rates
    for(i in 1:nobs) {
        
        matmi <- df.sa$matm[i]
        
        if(matmi == key_matm) {
            df.sa[i,2+n] <- dr
        } else if (matmi %in% v.key_matm){
            df.sa[i,2+n] <- 0
        }
    }
    
    # rates between key rates is linearly interpolated
    f_interpol <- approxfun(matm, df.sa[,2+n], rule = 2, na.rm = TRUE)
    df.sa[,2+n] <- f_interpol(matm)
}
 
# p0
zero <- df.sa$zero
P0 <- sum((YTM10/2)/(1+zero/2)^(matm/6)) + 
           1/(1+zero[nobs]/2)^(matm[nobs]/6)
 
# all the key rate shifts
zerou <- zero + rowSums(df.sa[,1:nkey+2])
zerod <- zero - rowSums(df.sa[,1:nkey+2])
 
# effective duration : traditional
Pu <- sum((YTM10/2)/(1+zerou/2)^(matm/6)) + 
      1/(1+zerou[nobs]/2)^(matm[nobs]/6)
Pd <- sum((YTM10/2)/(1+zerod/2)^(matm/6)) + 
      1/(1+zerod[nobs]/2)^(matm[nobs]/6)
ED <- (Pd - Pu)/(2*P0*dr)
 
# Key rate duations
df.KRD <- data.frame(matm = df$matm, ED = NA)
for(n in 1:nkey) {
    
    # key rate shifts
    zerou <- zero + df.sa[,2+n]
    zerod <- zero - df.sa[,2+n]
    
    # effective duration : KRD
    Pu <- sum((YTM10/2)/(1+zerou/2)^(matm/6)) + 
          1/(1+zerou[nobs]/2)^(matm[nobs]/6)
    Pd <- sum((YTM10/2)/(1+zerod/2)^(matm/6)) + 
          1/(1+zerod[nobs]/2)^(matm[nobs]/6)
    
    df.KRD[n,2]  <- (Pd - Pu)/(2*P0*dr)
}
df.KRD
 
# check if sum of KRDs is equal to effective duration
dr
sum(df.KRD$ED)
ED
 
cs


Running this R code, we can get the following results which show that calculation of key rate durations is proper when we use 1bp as the size of shift. Of course, it depends on which problem is investigated.

Calculation of Key Rate Duration using R code


Concluding Remarks


In this post we implemented the key rate durations which is invented by Ho (1992). This can be used in the case of the non-parallel shifts of yield curve and has broad application: replicating portfolio of option embedded bonds, managing fixed-income portfolio, analyzing complex interest rate contingent claims, and so on.


Reference


Ho, T.S.Y. (1992), "Key Rate Durations: Measures of Interest Rate Risks," The Journal of Fixed Income 2-2, pp.29-44. \(\blacksquare\)


No comments:

Post a Comment