Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

The duration of a floating rate note (FRN) is the remaining time until the first next payment date. Using this fact, a duration of FRN has not been calculated explicitly but has been understood conceptually. Instead of this reasoning, this post tries to calculate it directly based on the numerical differentiation using R code.

We have investigated the properties of a price and duration of FRN and calculated its price in the following previous post

### Price and Duration of FRN

In the previous post, we find that a price of FRN at time $$t$$ is. \begin{align} P_{zero}^{FRN} &= \begin{cases} 1, & \text{payment date} \\ D_{0,\tau} (1+R_{reset}), & \text{otherwise}\\ \end{cases} \\ \\ \tau &= t_{payment}^{1st} – t \end{align} Here $$t_{payment}^{1st}$$ is the first next payment dates after the pricing date ($$t$$). $$D(0,t)$$ denotes a discount factor for a cashflow at time $$t$$.

Duration of FRN is zero right before the reset date and is an interest payment period right after the reset date and is a linearly interpolated year when pricing date is between two consecutive payment dates. Duration of FRN is summarized as follows. \begin{align} D_{zero}^{FRN} = \begin{cases} 0, & \text{payment date} \\ \tau, & \text{otherwise}\\ \end{cases} \end{align}

### Effective Duration

The effective duration is of the follwing form of numerical differentiation. \begin{align} D &= \frac{P_u – P_d}{2 \Delta y \times P_0} \end{align} Here, $$P_0$$ denotes an initial bond price with yield to maturity ($$y$$). $$P_u$$ and $$P_d$$ represent bond prices after downward ($$y-\Delta y$$) and upward ($$y+\Delta y$$) shocks to interest rates (yield to maturity) respectively.

Refer the following post for more details of the effective duration

We intend to use this formula to calculate a FRN duration but how can we apply this YTM change in the framework of FRN pricing? For this matter, we need to generate a zero curve from a parallel shift of the YTM curve.

### Zero curve from Parallel Shift of YTM curve

Unlike the fixed rate bond which can be priced by using the YTM or zero pricing, FRN use zero pricing so that when we apply the numerical differentiation for duration, we need to generate a zero curve from a parallel shift of market yield (YTM or swap rate) curve which consists of market instruments. The following figure shows three zero curves generated from baseline,1 bp upward shifted, and 1 bp downward shifted YTM curves.

Refer the following post for more details of a zero curve bootstrapping

In summary, in duration calculation, a change in the market yield curve means a parallel shift of the market yield curve, not a individual yield change at a specific maturity.

### R code

The following R code implements the above effective duration formula and applies it to the calculation of 3-year FRN’s duration with quarterly frequency, and finally compares it with the actual remaining time between the pricing date and the first next payment date ($$\tau$$) for three cases (pricing date : t=0, 1/12, 2/12).

 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 #========================================================## Quantitative ALM, Financial Econometrics & Derivatives # ML/DL using R, Python, Tensorflow by Sang-Heon Lee ## https://kiandlee.blogspot.com#——————————————————–## Calculate a duration of FRN # using numerical differentiation#========================================================# graphics.off()  # clear all graphsrm(list = ls()) # remove all files from your workspace #——————————————————-# Input#——————————————————-     # continuously compounded zero rate    # zr0 : baseline zero curve    # zru : zero curve generated from 1 bp downward shifted YTM curve    # zrd : zero curve generated from 1 bp upward   shifted YTM curve    str.zero <–“month     zr0          zru            zrd                3    0.006594635    0.006694472    0.006494797                6    0.006819495    0.006919243    0.006719675                9    0.00704844    0.007148193    0.006948601                12    0.00731956    0.007419349    0.007219723                15    0.007630967    0.007730765    0.007531127                18    0.00794161    0.008041417    0.007841763                21    0.008232426    0.008332244    0.008132565                24    0.008522513    0.008622352    0.008422642                27    0.008767559    0.008867411    0.008667681                30    0.009012877    0.009112739    0.008912988                33    0.009257467    0.009357346    0.009157564                36    0.00960459    0.009704503    0.009504658″        df.raw <– read.table(text = str.zero, header = TRUE)     k  <– 4      # interest payment frequency (quarterly)    dr <– 0.0001 # yield change (1 bp)    #——————————————————-# Calculation of Price and Duration of FRN# by using Numerical Differentiation#——————————————————-     for(t in c(0,1,2)) {                # initialize        df <– df.raw                # remaining maturity (monthly)        df$mat <– (df$month – t)/12                # interest period        df$tau <– df$mat        df$tau[2:12] <– df$mat[2:12] – df$mat[1:11] # discount factor df$df0  <– exp(–df$zr0*df$mat)        df$dfu <– exp(–df$zru*df$mat) df$dfd  <– exp(–df$zrd*df$mat)                # forward rate        df$fd0 <– df$zr0        df$fdu <– df$zru        df$fdd <– df$zrd        df$fd0[2:12] <– (1/df$tau[2:12])*(df$df0[1:11]/df$df0[2:12]–1)        df$fdu[2:12] <– (1/df$tau[2:12])*(df$dfu[1:11]/df$dfu[2:12]–1)        df$fdd[2:12] <– (1/df$tau[2:12])*(df$dfd[1:11]/df$dfd[2:12]–1)                        # reset the first coupon rate when pricing date is reset date        # assumption of no reset lag        if(t == 0) { # reset date                    # newly reset the reference index          r0_reset <– 0.00660 # spot rate at spot date          ru_reset <– 0.00660           rd_reset <– 0.00660        }                # forward rates as cash flows        df$cf0 <– df$fd0/k        df$cfu <– df$fdu/k        df$cfd <– df$fdd/k                # set the first coupon rate        df$cf0[1] <– r0_reset/k df$cfu[1] <– ru_reset/k         df$cfd[1] <– rd_reset/k # add nominal principal (1) df$cf0[nrow(df)] <– 1 + df$cf0[nrow(df)] df$cfu[nrow(df)] <– 1 + df$cfu[nrow(df)] df$cfd[nrow(df)] <– 1 + df$cfd[nrow(df)] # FRN price as sum of discounted variable CF P0 <– sum(df$df0*df$cf0) Pd <– sum(df$dfu*df$cfu) Pu <– sum(df$dfd*df\$cfd)                Dr <– (Pu–Pd)/(2*dr)/P0      # Duration            # Print        cat(paste0(“\nResults for FRN (t=”,t,“)\n\n”,                   “Price     = “, P0, “\n”,                   “Duration  = “, Dr, “\n”,                   “time to the first next payment date\n”,                   ”          = “, (3–t)/12, “\n\n”))    }      Colored by Color Scripter cs

From he following output of the above R code, we can find that the duration of FRN for each case is equal to the actual remaining time between the pricing date and the first next payment date ($$\tau$$)

 12345678910111213141516171819202122232425 # Print Results for FRN (t=0) Price     = 0.999999981495524Duration  = 0.249593750056916time to the first next payment date          = 0.25  Results for FRN (t=1) Price     = 1.00054968543389Duration  = 0.166395833356961time to the first next payment date          = 0.166666666666667  Results for FRN (t=2) Price     = 1.00109969154668Duration  = 0.0831979166709382time to the first next payment date          = 0.0833333333333333 Colored by Color Scripter cs

### Concluding Remarks

From this post, we calculate the duration of FRN directly by using numerical differentiation. This intuitive exercise reminds us of fact that a market yield change means a parallel shift of the market yield curve and then this change is translated and spread to a zero curve change. This is plain but easy to overlook. Using this changed zero curve, an effective duration of FRN can be obtained numerically.