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

This post makes a user-defined R function for Adams and Deventer (1994, revised 2010) maximum smoothness forward curve for the purpose of reusing and performs robustness checks for various initial term structures. We find that every time an initial term structure is changed, our procedure delivers correct output with different shapes of forward curves.

# Maximum Smoothness Forward Rates

This post makes a R function for Adams-Deventer maximum smoothness forward curve based on previous post and performs robustness check for various initial term structures. Output of this post is the following figure describing various maximum smoothness forward rate curves with spot curves.

Details of maximum smoothness forward rate curve and its implementation are explained in the previous two posts below.

### R user-defined function for Maximum Smoothness Forward Rates

For the purpose of reusing, previous post’s R code is structured as the next the user-defined R function. Here, we assume that a yield at time zero is the same as the yield at the shortest maturity.

 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 #========================================================## 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# Robustness Check using a user-defined function#========================================================# graphics.off()  # clear all graphsrm(list = ls()) # remove all files from your workspace # function for Maximum Smoothness Forward Curvefunc_msfc <– function(df.mkt) {        # maturity strings for figure    v.str.mat <– paste0(as.character(df.mkt$mat), “Y”) # number of maturity n <– length(df.mkt$mat)        # add 0-maturity zero rate (assumption)    df <– rbind(c(0, df.mkt$zrc[1]), 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 df$t0 <– 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]) #———————————————— # construction linear system #———————————————— mQ <– mA <– matrix(0, nrow = 5*n, ncol = 5*n) vC <– vB <– rep(0,5*n) # Objective function for(r in 1:n) { mQ[((r–1)*5+1):((r–1)*5+3),((r–1)*5+1):((r–1)*5+3)] <– matrix(with(df[r+1,], c(144/5*dt5, 18*dt4, 8*dt3, 18*dt4, 12*dt3, 6*dt2, 8*dt3, 6*dt2, 4*dt1)),3,3) } # Smoothness Constraints : f, f’, f”, f”’ for (r in 1:4) { for(t in 1:(n–1)) { if(r==1) { temp <– with(df[t+1,], c(t4, t3, t2, t1, t0)) } else if(r==2) { temp <– with(df[t+1,], c(4*t3, 3*t2, 2*t1, t0)) } else if(r==3) { temp <– with(df[t+1,], c(12*t2, 6*t1, 2*t0)) } else if(r==4) { temp <– with(df[t+1,], c(24*t1, 6*t0)) } mA[(r–1)*(n–1)+t,((t–1)*5+1):((t–1)*5+6–r)] <– temp mA[(r–1)*(n–1)+t,((t–0)*5+1):((t–0)*5+6–r)] <– –temp } } # bond price fitting constraints r = 5; for(t in 1:n) { temp <– with(df[t+1,], c(dt5/5,dt4/4,dt3/3,dt2/2,dt1)) mA[(r–1)*(n–1)+t,((t–1)*5+1):((t–0)*5)] <– temp } # additional four constraints r = 5*n–3; c = 5 ; mA[r,c] <– 1 r = 5*n–2; c = 5–1; mA[r,c] <– 1 r = 5*n–1; c = (5*(n–1)+1):(5*(n–1)+4) mA[r,c] <– with(df[n+1,], c(4*t3, 3*t2, 2*t1, t0)) r = 5*n–0; c = (5*(n–1)+1):(5*(n–1)+3) mA[r,c] <– with(df[n+1,], c(12*t2, 6*t1, 2*t0)) # RHS vector vC <– rep(0,5*n) vB <– c(rep(0,4*(n–1)), df$mln[2:(n+1)], df$zrc[1],0,0,0) # concatenation of matrix and vector AA = rbind(cbind(mQ, –t(mA)), cbind(mA, matrix(0,5*n,5*n))) BB = c(–vC, vB) #———————————————— # solve linear system by using inverse matrix #———————————————— XX = solve(AA)%*%BB XX # save and print calibrated parameters for(i in 1:n) { df.mkt[i,c(“a”,“b”,“c”,“d”,“e”)] <– XX[((i–1)*5+1):(i*5)] } df.coef <– df.mkt[,c(“a”,“b”,“c”,“d”,“e”)] #———————————————— # monthly forward rate and spot rate #———————————————— df.mm <– data.frame( mat = seq(0,10,1/12),y = NA, fwd = NA) # which segment df.mm$seg_no <–         apply(df.mm, 1,               function(x) min(which(x[1]<=df.mkt$mat)) ) # ti^n df.mm$t5 <– df.mm$mat^5 df.mm$t4 <– df.mm$mat^4 df.mm$t3 <– df.mm$mat^3 df.mm$t2 <– df.mm$mat^2 df.mm$t1 <– df.mm$mat^1 df.mm$t0 <– 1        nr <– nrow(df.mm) # number of rows        # dti = ti^n-(ti-1)^n    df.mm$dt5 <– c(NA,df.mm$t5[2:nr] – df.mm$t5[1:(nr–1)]) df.mm$dt4 <– c(NA,df.mm$t4[2:nr] – df.mm$t4[1:(nr–1)])    df.mm$dt3 <– c(NA,df.mm$t3[2:nr] – df.mm$t3[1:(nr–1)]) df.mm$dt2 <– c(NA,df.mm$t2[2:nr] – df.mm$t2[1:(nr–1)])    df.mm$dt1 <– c(NA,df.mm$t1[2:nr] – df.mm$t1[1:(nr–1)]) # monthly maximum smoothness forward curve df.mm$fwd[1] <– df.mkt$e[1] # time 0 forward rate df.mm$y[1]   <– df.mkt$e[1] # time 0 yield temp_y_sum <– 0 for(i in 2:nr) { mat <– df.mm$mat[i]        seg_no  <– df.mm$seg_no[i] # which segment v_tn <– df.mm[i,c(“t4”,“t3”,“t2”,“t1”,“t0”)] v_dtn <– df.mm[i,c(“dt5”,“dt4”,“dt3”,“dt2”,“dt1”)] v_abcde <– df.mkt[seg_no, c(“a”,“b”,“c”,“d”,“e”)] # monthly maximum smoothness forward curve df.mm$fwd[i] <– sum(v_abcde*v_tn)                # monthly yield curve        temp_y_sum <– temp_y_sum +            sum(c(1/5,1/4,1/3,1/2,1)*v_abcde*v_dtn)        df.mm$y[i] <– (1/mat)*temp_y_sum } #———————————————— # Draw Graph #———————————————— x11(width=8, height = 6); plot(df.mkt$mat, df.mkt$zrc, col = “red”, cex = 1.5, ylim = c(min(df.mm$fwd)–0.01,max(df.mm$fwd)+0.01), xlab = “Maturity”, ylab = “Interest Rate”, lwd = 10, main = “Monthly Maximum Smoothness Forward Rates and Spot Rates”) text(df.mkt$mat,          df.mkt$zrc+(max(df.mm$fwd)–min(df.mm$fwd))/12, labels=v.str.mat, cex= 1.5) lines(df.mm$mat, df.mm$y , col = “blue” , lwd = 5) lines(df.mm$mat, df.mm$fwd, col = “green”, lwd = 10) legend(“bottomright”, legend=c(“Spot Curve”,“Forward Curve”,“Input Spot Rates”), col=c(“blue”,“green”,“red”), pch = c(15,15,16), border=“white”, box.lty=0, cex=1.5) XX2 <– solve(mA)%*%vB cbind(XX[1🙁5*n)],XX2,XX[1🙁5*n)]–XX2) sum(abs(XX[1🙁5*n)]–XX2)) return(list(mm=df.mm, coef = df.coef))} Colored by Color Scripter cs ### Robustness Check For robustness check, we change a initial term structure a little and draw graph and print coefficients. Since we made a user-defined R code, this job can be done simply by using the following R code.  123456789101112131415161718192021222324 #————————————————# Robustness Check#———————————————— # 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)lt1 <– func_msfc(df.mkt); lt1$coefdf.mkt <– data.frame(    mat = c(0.25,   1,   3,     5,  7,  10),    zrc = c(4.75, 4.5, 5.5,  5.25,  7, 6.5)/100)lt2 <– func_msfc(df.mkt); lt2$coef df.mkt <– data.frame( mat = c(0.25, 1, 3, 5, 7, 8, 10), zrc = c(4.75, 4.5, 5.5, 5.25, 7, 4, 6.5)/100)lt3 <– func_msfc(df.mkt); lt3$coef df.mkt <– data.frame(    mat = c(0.25,   1,   3,  4,   5,  7,  8,  10),    zrc = c(4.75, 4.5, 5.5,  8, 5.25,  7,  4, 6.5)/100)lt4 <– func_msfc(df.mkt); lt4\$coef Colored by Color Scripter cs

Running the above R code for robustness check, we can get the following table of coefficients. As the number of maturity of a initial term structure increases, the number of parameters increases in multiples of 5.

With these estimated coefficients, we can draw the following maximum smoothness forward (green solid line) and spot (blue solid line) curve with each initial term structure (red dot point).

### Concluding Remarks

So far through three posts regarding Adams-Deventer maximum smoothness forward curve, we can understand and implement this powerful model. In particular, we make a user-defined R function for another usages. $$\blacksquare$$