Nelson-Siegel model using constrOptim.nl() R function
In this post, the non-linear least squares problem is solved by using constrOptim.nl() function from alabama R package. Like the previous posts, Nelson-Siegel model is also used for a testing purpose.
Nelson-Siegel model as a non-linear optimization problem
Nelson-Siegel model is a non-linear least square problem with 4 parameters with some inequality constraints.
\[\begin{align} y(\tau) &= \beta_1 + \beta_2 \left( \frac{1-e^{- \tau \lambda }}{\tau \lambda }\right) \\ &+ \beta_3 \left(\frac{1-e^{- \tau \lambda }}{\tau \lambda }-e^{- \tau \lambda }\right) \end{align}\] \[\begin{align} \beta_1 > 0, \beta_1 + \beta_2 >0, \lambda > 0 \end{align}\]
Here, \(\tau\) is a maturity and \(y(\tau)\) is a continuously compounded spot rate with \(\tau\) maturity. \(\beta_1, \beta_2, \beta_3\) are coefficient parameters and \(\lambda\) is the time decay parameter.
constrOptim.nl() function
After installing alabama R package, constrOptim.nl() function can be used. Its arguments are so straightforward to understand that I just point out two arguments for constraints. The following two arguments denote inequality and equality constraint functions respectively. In particular, unlike nloptr() function, the inequality constraint function (hin) returns a vector of greater than zero constraints. You can easily find their functional form in the R code which will be shown below
# hin : a vector function specifying inequality constraints such that hin[j] > 0 for all j # heq : a vector function specifying equality constraints such that heq[j] = 0 for all j |
For further information about its settings, please see the document (https://www.rdocumentation.org/packages/alabama/versions/2022.4-1/topics/constrOptim.nl).
R code
The following R code is similar to the previous post in that it estimates parameters of Nelson-Siegel model with yield curves at two dates.
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 119 120 121 122 123 | #========================================================# # Quantitative Financial Econometrics & Derivatives # ML/DL using R, Python, Tensorflow by Sang-Heon Lee # # https://shleeai.blogspot.com #--------------------------------------------------------# # Nelson-Siegel using constrOptim.nl function #========================================================# graphics.off(); rm(list = ls()) library(alabama) #----------------------------------------------- # constrOptim.nl objective function #----------------------------------------------- objfunc_co <- function(para, y, m) { beta <- para[1:3]; la <- para[4] C <- cbind( rep(1,length(m)), (1-exp(-la*m))/(la*m), (1-exp(-la*m))/(la*m)-exp(-la*m)) return(sqrt(mean((y - C%*%beta)^2))) } #----------------------------------------------- # constrOptim.nl constraint function ( > : larger ) #----------------------------------------------- # beta0 + beta1 > 0 constfunc_co <- function(para, y, m) { beta <- para[1:3]; la <- para[4] h <- rep(NA, 4) h[1] <- beta[1] # b1 > 0 h[2] <- beta[1]+beta[2] # b1+b2 > 0 h[3] <- la-0.001 # lambda > 0.001 h[4] <- 0.1-la # lambda < 0.1 return(h) } #======================================================= # 1. Read data #======================================================= # b1, b2, b3, lambda for comparisons ns_reg_para_rmse1 <- c( 4.26219396, -4.08609206, -4.90893865, 0.02722607, 0.04883786) ns_reg_para_rmse2 <- c( 4.97628654, -4.75365297, -6.40263059, 0.05046789, 0.04157326) str.zero <- " mat rate1 rate2 3 0.0781 0.0591 6 0.1192 0.0931 9 0.1579 0.1270 12 0.1893 0.1654 24 0.2669 0.3919 36 0.3831 0.8192 48 0.5489 1.3242 60 0.7371 1.7623 72 0.9523 2.1495 84 1.1936 2.4994 96 1.4275 2.7740 108 1.6424 2.9798 120 1.8326 3.1662 144 2.1715 3.4829 180 2.5489 3.7827 240 2.8093 3.9696" df <- read.table(text = str.zero, header=TRUE) m <- df$mat y1 <- df$rate1; y2 <- df$rate2 #============================================================== # 2. constrOptim.nl # : Nonlinear least squares with constraints #============================================================== #--------------------------------------------- # NS estimation with 1st data #--------------------------------------------- y <- y1 x_init <- c(y[16], y[1]-y[16], 2*y[6]-y[1]-y[16], 0.0609) m_coptim <- constrOptim.nl(par = x_init, y = y, m = m, fn = objfunc_co, hin = constfunc_co, control.optim = list(maxit=50000, trace=0, reltol = 1e-16, abstol = 1e-16) , control.outer = list(eps = 1e-16, itmax = 50000, method = "Nelder-Mead", NMinit = TRUE)) ns_coptim_out1 <- c(m_coptim$par, m_coptim$value) #--------------------------------------------- # NS estimation with 2nd data #--------------------------------------------- y <- y2 x_init <- c(y[16], y[1]-y[16], 2*y[6]-y[1]-y[16], 0.0609) m_coptim <- constrOptim.nl(par = x_init, y = y, m = m, fn = objfunc_co, hin = constfunc_co, control.optim = list(maxit=50000, trace=0, reltol = 1e-16, abstol = 1e-16) , control.outer = list(eps = 1e-16, itmax = 50000, method = "Nelder-Mead", NMinit = TRUE)) ns_coptim_out2 <- c(m_coptim$par, m_coptim$value) #======================================================= # 3. Results and Comparisons #======================================================= ns_reg_para_rmse1 ns_coptim_out1 ns_reg_para_rmse2 ns_coptim_out2 | cs |
The following estimation results show that non-linear optimization results from constrOptim.nl() function are nearly similar to the answers.
Using these estimated parameters at two selected dates, two fitted term structure of interest rates can be generated as follows.
Concluding Remarks
This post shows how to use constrOptim.nl() R function to perform non-linear optimization problem with or without equality or inequality constraints. The reason why I introduce this optimization function is that its computation time tends to be a little faster than nloptr() function. \(\blacksquare\)
No comments:
Post a Comment