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

This post implements Adams and Deventer (1994) approach which generates the best fitting yield curve smoothing with the principle of maximum smoothness forward rate curve. This provides a powerful closed-form solution by which we can sidestep a kinked or zigzag problem of forward rate curve effectively.

# Computing Maximum Smoothness Forward Rate Curve

To ensure a smoothness of the yield curve, the Adam-Deventer method can be used.

• Adams K.J. and D. R. van Deventer (1994), Fitting yield curves and forward rate curves with maximum smoothness, Journal of Fixed Income 4-1, pp. 52-62.
• Imai K. and D. R. van Deventer (1996), Financial Risk Analytics Book
• van Deventer, D. R. (2010), Basic Building Blocks of Yield Curve Smoothing, Part 10: Maximum Smoothness Forward Rates and Related Yields versus Nelson-Siegel (Revised May 8, 2012)
• Lim, K. G. and Q. Xiao (2002), Computing maximum smoothness forward rate curves, Statistics and Computing 12, pp. 275-279.

We use the Deventer (2010) revised methodology, from which we borrow input data also as follows.

 12345678910111213 ——————————————    Maturity   Spot Rate     ZCB Price——————————————       t           r          P(0,t)——————————————     0.25        4.75%          0.9882       1         4.50%          0.9560       3         5.50%          0.8479       5         5.25%          0.7691      10         6.50%          0.5220—————————————— Colored by Color Scripter cs

Using a linear interpolation of the given market zero curve, we can calculate next monthly zero curve and forward curve. As can be seen in figure below, forward rate from linearly interpolated show discontinuity and no smoothness (some forward rates are omitted because they show too large deviations as outliers).

To ensure a smooth yield curve, Adams and Deventer (1994) use maximum smoothness forward rate approach. Their approach delivers a smooth yield curve like the following figure.

### Forward Rate

To evaluate smoothness numerically, Adams and Deventer (1994) calculate the second derivative of forward rate for each segments (intervals between observed maturities), the squared sum of them, and minimize this with some constraints which ensure smoothness of yield curve.

In each forward rate curve segment, each forward rate $$f(t)$$ is assumed to have the following form.
\begin{align} f(t) &= a_i t^4 + b_i t^3 + c_i t^2 + d_i t + e_i \\ \\ &t_{i-1} \lt t \le t_{i}, \quad i=1,2,…,m \end{align}
The subscript i denotes the segment number. In case of the example data, as the number of coefficients are $$25 = 5 \times 5$$, it is desirable to construct 25 constraints.

### Objective Function

The i-th objective function maximizes a smoothness of forward rates, which is an integration of twice differenced forward rates. \begin{align} \int_{t_{i-1}}^{t_i} [f^{”}(t)]^2 dt &= \int_{t_{i-1}}^{t_i} \left[12a_i t^2 + 6 b_i t + 2 c_i \right]^2 dt \\ &= \frac{144}{5} \Delta t_i^5 a_i^2 + 36 \Delta t_i^4 a_i b_i + 12 \Delta t_i^3 b_i^2 \\ &+ 16 \Delta t_i^3 a_i c_i + 12 \Delta t_i^2 b_i c_i + 4 \Delta t_i c_i^2 \end{align}

### Equality Linear Constraints

For $$i=1,2,…,m-1$$, restrictions on continuity of $$f$$, $$f^{‘}$$,$$f^{”}$$ and $$f^{”’}$$ are imposed.

\begin{align} &a_{i+1} t^4 + b_{i+1} t^3 + c_{i+1} t^2 + d_{i+1} t + e_{i+1} \\ &= a_i t^4 + b_i t^3 + c_i t^2 + d_i t + e_i \\ \\ & 4a_{i+1} t^3 + 3b_{i+1} t^2 + 2c_{i+1} t + d_{i+1} \\ &= 4a_i t^3 + 3b_i t^2 + 2c_i t + d_i\\ \\ &12a_{i+1} t^2 + 6b_{i+1} t + 2c_{i+1} = 12a_{i} t^2 + 6b_{i} t + 2c_{i} \\ \\ & 24 a_{i+1} t + 6b_{i+1} = 24a_{i} t + 6 b_{i} \end{align}
For $$i=1,2,…,m$$, a set of integration of forward rates should fit a set of zero coupon bond price.

\begin{align} -log\left[ \frac{P_i}{P_{i-1}}\right] &= \frac{1}{5} a_i (t_i^5 – t_{i-1}^5) + \frac{1}{4} b_i (t_i^4 – t_{i-1}^4) \\ &+ \frac{1}{3} c_i (t_i^3 – t_{i-1}^3) + \frac{1}{2} d_i (t_i^2 – t_{i-1}^2) + e_i (t_i – t_{i-1}) \end{align}
These restrictions can be rewritten more compactly ($$\Delta k_{i+1}= k_{i+1} – k_{i}, \Delta t_i^n= t_i^n – t_{i-1}^n$$). \begin{align} 0 &= \Delta a_{i+1} t^4 + \Delta b_{i+1} t^3 + \Delta c_{i+1} t^2 + \Delta d_{i+1} t + \Delta e_{i+1} \\ 0 &= 4\Delta a_{i+1} t^3 + 3\Delta b_{i+1} t^2 + 2\Delta c_{i+1} t + d\Delta _{i+1} \\ 0 &= 12\Delta a_{i+1} t^2 + 6\Delta b_{i+1} t + 2\Delta c_{i+1} \\ 0 &= 24\Delta a_{i+1} t + 6\Delta b_{i+1} \end{align} \begin{align} -log\left[ \frac{P_i}{P_{i-1}}\right] = \frac{1}{5} a_i \Delta t_i^5 + \frac{1}{4} b_i \Delta t_i^4 + \frac{1}{3} c_i \Delta t_i^3 + \frac{1}{2} d_i \Delta t_i^2 + e_i \Delta t_i \end{align}

From these, we have $$21 = 4 \times 4 + 5$$ constraints and additional 4 constraints are required.

The initial forward rate is assumed to be equal to the observed spot rate or given other rate at time zero. Three remaining constraints are related to the smoothness of forward rate at time 0 and T using the first or second derivative of forward rate.

\begin{align} f(0) = r(0) \\ f^{‘}(0) = 0 \\ f^{‘}(T) = 0 \\ f^{”}(T) = 0 \end{align}
Now we have a problem of 25 unknowns and 25 equations.

### R code

We use optimization to solve for this 25 unknown variables problem using NlcOptim R package which have two main arguments : 1) objective function and 2) constraints function. In particular, constraints function can deal with both linear and non-linear constraints. The following R code estimate 25 coefficients of Adams-Deventer’s maximum smoothness forward rate curve.

 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 #========================================================## Quantitative ALM, Financial Econometrics & Derivatives # ML/DL using R, Python, Tensorflow by Sang-Heon Lee ## https://kiandlee.blogspot.com#——————————————————–## Adams and Deventer Maximum Smoothness Forward Curve# using non-linear optimization#========================================================# graphics.off()  # clear all graphsrm(list = ls()) # remove all files from your workspace library(NlcOptim) # optimization with non-linear constraints # whole calculation processf_calc <– function(x0) {        # number of maturity    n <– length(df.mkt$mat) # add 0-maturity zero rate (assumption) #df <- rbind(c(0, df.mkt$zrc), df.mkt)    df <– rbind(c(0, 0.04), df.mkt)        # discount factor    df$DF <– with(df, exp(–zrc*mat)) # -ln(P(t(i)/t(i-1))) df$mln <– c(NA,–log(df$DF[1:n+1]/df$DF[1:n]))        # ti^n    df$t5 <– df$mat^5    df$t4 <– df$mat^4    df$t3 <– df$mat^3    df$t2 <– df$mat^2    df$t1 <– df$mat^1        # dti = ti^n-(ti-1)^n    df$dt5 <– c(NA,df$t5[1:n+1] – df$t5[1:n]) df$dt4 <– c(NA,df$t4[1:n+1] – df$t4[1:n])    df$dt3 <– c(NA,df$t3[1:n+1] – df$t3[1:n]) df$dt2 <– c(NA,df$t2[1:n+1] – df$t2[1:n])    df$dt1 <– c(NA,df$t1[1:n+1] – df$t1[1:n]) # parameters to be found df$e <– df$d <– df$c <– df$b <– df$a <– c(NA,rep(0,n))     df$a[1:n+1] <– x0[(0*n+1):(1*n)] df$b[1:n+1] <– x0[(1*n+1):(2*n)]    df$c[1:n+1] <– x0[(2*n+1):(3*n)] df$d[1:n+1] <– x0[(3*n+1):(4*n)]    df$e[1:n+1] <– x0[(4*n+1):(5*n)] # difference of coefficients : dki = ki – k(i-1) df$da <– c(NA, df$a[2:n] – df$a[2:n+1], NA)    df$db <– c(NA, df$b[2:n] – df$b[2:n+1], NA) df$dc <– c(NA, df$c[2:n] – df$c[2:n+1], NA)    df$dd <– c(NA, df$d[2:n] – df$d[2:n+1], NA) df$de <– c(NA, df$e[2:n] – df$e[2:n+1], NA)        # forward rate    df$fwd <– NA df$fwd[1:n+1] <– with(df[1:n+1,], a*t4 + b*t3 + c*t2 +d*t1 + e)    df$fwd <– df$e        # linear constraints    df$cmln <– df$cfp3 <– df$cfp2 <– df$cfp1<– df$cfp0<– NA df$cfp0[2:n] <– with(df[2:n,], da*t4 + db*t3 +   dc*t2 +   dd*t1 +   de)    df$cfp1[2:n] <– with(df[2:n,], 4*da*t3 + 3*db*t2 + 2*dc*t1 + dd) df$cfp2[2:n] <– with(df[2:n,],                12*da*t2 + 6*db*t1 + 2*dc)    df$cfp3[2:n] <– with(df[2:n,], 24*da*t1 + 6*db) df$cmln[2:(n+1)] <– with(df[2:(n+1),],                        a*dt5/5 + b*dt4/4 + c*dt3/3 + d*dt2/2 + e*dt1 – mln)        # additional 4 constraint    # initial(0) forward rate(f) = r0, initial f’ = 0    # terminal(T) f’, f” = 0    const_f_0  <– df$e – df$zrc    const_f1_0 <– df$d const_f1_T <– with(df[n+1,], 4*a*t3 + 3*b*t2 + 2*c*t1 + d) const_f2_T <– with(df[n+1,], 12*a*t2 + 6*b*t1 + 2*c) # objective function df$obj <– NA    df$obj[1:n+1] <– with(df[1:n+1,], (144/5)*dt5*a^2 + 36*dt4*a*b + 12*dt3*b^2 + 16*dt3*a*c + 12*dt2*b*c + 4*dt1*c^2) return(list(df.calc = df, fvalue = sum(df$obj[1:n+1]),                const   = c(                    df$cfp0[2:n], df$cfp1[2:n],                    df$cfp2[2:n], df$cfp3[2:n],                    df$cmln[2:(n+1)], const_f_0, const_f1_0, const_f1_T, const_f2_T)))} # objective function for solnlobj <– function(x) { lt.out <– f_calc(x); return(lt.out$fvalue)} # constraint function for solnlcon <– function(x) {    lt.out <– f_calc(x)    return(list(ceq = lt.out$const, c = NULL))} # Input : market zero rate, maturitydf.mkt <– data.frame( mat = c(0.25, 1, 3, 5, 10), zrc = c(4.75, 4.5, 5.5, 5.25, 6.5)/100) x0 <– rep(0.001,25) # initial guesses out <– solnl(x0, objfun = obj, confun = con) # augment df.mkt with calibrated paramtersn <– length(df.mkt$mat) df.mkt$a[1:n] <– out$par[(0*n+1):(1*n)]df.mkt$b[1:n] <– out$par[(1*n+1):(2*n)]df.mkt$c[1:n] <– out$par[(2*n+1):(3*n)]df.mkt$d[1:n] <– out$par[(3*n+1):(4*n)]df.mkt$e[1:n] <– out$par[(4*n+1):(5*n)] df.mkt Colored by Color Scripter cs

Running the above R code, we can obtain calibrated parameters ($$a_i, b_i, c_i, d_i, e_i$$, $$i=1,…,m$$) which characterize the maximum smoothness forward curve.

It is typical to set the time 0 spot rate to the shortest term rate but Deventer (2010) use 4% and we follow this setting.

 1234567 mat    zrc             a            b          c             d           e1  0.25 0.0475  3.7020078185 -3.343981375  0.8481712  1.429488e-16  0.040000002  1.00 0.0450 -0.1354629771  0.493489420 -0.5908803  2.398419e-01  0.025009883  3.00 0.0550  0.0080049880 -0.080382440  0.2699275 -3.340299e-01  0.168477824  5.00 0.0525 -0.0024497294  0.045074169 -0.2946273  7.950796e-01 -0.678354295 10.00 0.0650  0.0002985362 -0.009891143  0.1176126 -5.790532e-01  1.03931172 Colored by Color Scripter cs

Substituting these calibrated parameters into the above equations for forward rate and yield curve, we can draw the next figure. Green line is the maximum smoothness forward rate. we can easily find that this forward rate is continuous and very smooth unlike the forward rate from the linearly interpolated zero rate (yellow line).

### Concluding Remarks

From this post, we have implemented Adams and Deventer’s maximum smoothness forward rate curve. This is a powerful approach for fitting yield curve. But in principle, this problem is solved by closed form solution because it is a quadratic optimization with equality linear constraints. This topic will be covered in the next post. $$\blacksquare$$