R : Nelson-Siegel-Svensson (NSS) model with fixed or estimated constant decay parameters

This post implements the period-by-period estimation of the Nelson-Siegel-Svensson yield curve model with fixed or estimated constant decay parameters using R code.



NSS or SV model



The Nelson-Siegel-Svensson (NSS) or Svensson (SV) model (Svensson, 1994) has the following form with positive dacay parameters (\( \lambda_1 > \lambda_2 > 0 \)).
\[\begin{align} y(\tau) &= \beta_1 + \beta_2 \left( \frac{1-e^{- \tau \lambda_1 }}{\tau \lambda_1 }\right) \\ &+ \beta_3 \left(\frac{1-e^{- \tau \lambda_1 }}{\tau \lambda_1 }-e^{- \tau \lambda_1 }\right) \\ &+ \beta_4 \left(\frac{1-e^{- \tau \lambda_2 }}{\tau \lambda_2 }-e^{- \tau \lambda_2 }\right) + \epsilon \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\) or \(\beta_4\) are coefficient parameters.


NSS model with fixed decay parameters


Non-linear optimization for joint estimation of all time-varying parameters is possible, but this estimation reduces the interpretability of yield factors due to parameter instability. Given two decay parameters, coefficients can be easily obtained by using the OLS.

#========================================================#
# Quantitative Financial Econometrics & Derivatives 
# ML/DL using R, Python, Tensorflow by Sang-Heon Lee 
#
# https://shleeai.blogspot.com
#--------------------------------------------------------#
# Period-by-Period Estimation of 
# the Nelson-Siegel-Svensson model 
# with constantly estimated decay parameters
#========================================================#
 
graphics.off()  # clear all graphs
rm(list = ls()) # remove all files from your workspace
 
setwd('D:/SHLEE/blog/R/NSS_two_lambda_opt')
 
# data is located in the following address
# 'https://github.com/Financial-Times/yield-curve-sonification/blob/7d131970377380f118fb9a0e1626f5ed1ecd35ca/yield-curve-monthly-data.csv'
 
yield <- as.matrix(read.csv('yield-curve-monthly-data.csv')[,-1])
mat <- c(13612,  24366084120240360)
 
#===========================================================
# NSS given two lambda
#===========================================================
 
# Svensson factor loading
sv_factor_loading <-function(la, m) {
    return(cbind(
        rep(1,length(m)), 
        (1-exp(-la[1]*m))/(la[1]*m), 
        (1-exp(-la[1]*m))/(la[1]*m)-exp(-la[1]*m),
        (1-exp(-la[2]*m))/(la[2]*m)-exp(-la[2]*m)))
}
 
# fitted yield curve
fit_sv  <- function(beta, la, m)    { 
    return(sv_factor_loading(la, m)%*%beta) 
}
 
# RMSE
rmse_sv <- function(beta, la, y, m) { 
    return(sqrt(mean((y - fit_sv(beta, la, m))^2)))
}
 
# OLS beta given lambda
est_sv_beta_reg_given_la <- function(la, y, m) {
    C    <- sv_factor_loading(la, m)
    beta <- solve(t(C)%*%C)%*%t(C)%*%y; 
    rmse <- rmse_sv(beta, la, y, m)
    return(list(beta=beta, la=la, rmse=rmse))
}
 
# period-by-period Estimation
est_sv_beta_reg_given_la_ts <- function(la, y_all, m) {
    nobs <- nrow(y_all); nmat <- length(m)
    rmse <- rep(NA,nobs)
    beta <- matrix(NA, nobs, 4)
    
    # apply the same two lambda for the whole sample
    la <- matrix(la, nobs, 2, byrow = TRUE)
    
    # period-by-period OLS estimation given lambda
    for(t in 1:nobs) {
        lt <- est_sv_beta_reg_given_la(la[t,],y_all[t,],m)
        beta[t,] <- lt$beta
        rmse[t]  <- lt$rmse
    }
    return(list(beta=beta, la=la, rmse=rmse))
}
 
# Svensson yield factors given lambda
out_sv_given_la <- est_sv_beta_reg_given_la_ts(
    c(1.8/361.8/120), yield, mat)
 
x11(width = 16/2, height = 9/2.3)
matplot(out_sv_given_la$beta, type="l", lty=1, lwd=3)
legend("bottomright", pch = 16, col = 1:4, cex = 0.9,
       bty = "n", horiz=TRUE, legend=c("L","S","C1","C2"))
 
cs


The following figure displays estimated 4 factors but two curvature factors shows somewhat symmetric movements.


NSS model with estimated constant decay parameters


When two decay parameters are estimated, we need to use numerical optimization to find these two parameters by minimizing the average RMSEs of the whole sample.

#===========================================================
# NSS with constantly optimized lambda
#===========================================================
 
la_hi <- 1.8/24
la_m1 <- 1.8/60
la_m2 <- 1.8/96
la_lo <- 1.8/180
 
# reparameterization of lambda
sv_trans <- function(b0) {
    b1 <- b0
    b1[1<- 1/(1+exp(b0[1]))*(la_hi - la_m1) + la_m1
    b1[2<- 1/(1+exp(b0[2]))*(la_m2 - la_lo) + la_lo
    return(b1)
}
 
# objective function 
rmse_sv_reg_given_la <- function(la, y, m) { 
    beta <- est_sv_beta_reg_given_la(la, y, m)$beta
    fit  <- fit_sv(beta, la, m); 
    return(sqrt(mean((y - fit)^2)))
}
 
# objective function to find constant lambda for whole sample
sv_all_objf  <- function(para, y_all, m) {
 
    # set boundaries for lambda
    la  <- sv_trans(para)
 
    # period-by-period estimation given the same lambda
    rmse_sum <- 0
    for(i in 1:nrow(y_all)) {
        y    <- y_all[i,]
        beta <- est_sv_beta_reg_given_la(la, y, m)$beta
        fit  <- fit_sv(beta, la, m)
        rmse_sum <- rmse_sum + sqrt(mean((y - fit)^2))
    }
    return(rmse_sum)
}
 
# optimization
mod <- optim(c(2,-3),
           sv_all_objf, method=c("Nelder-Mead"),
           #control=list(maxit=50000,reltol = 1e-12, trace=2),
           control=list(maxit=50000, trace=2),
           y_all = yield, m = mat)
 
# estimated lambda
est_la <- sv_trans(mod$par); est_la
out_sv_est_la <- est_sv_beta_reg_given_la_ts(est_la, yield, mat)
 
x11(width = 16/2, height = 9/2.3)
matplot(out_sv_est_la$beta, type="l", lty=1, lwd=3)
legend("bottomright", pch = 16, col = 1:4, cex = 0.9,
       bty = "n", horiz=TRUE, legend=c("L","S","C1","C2"))
 
cs


The following figure shows 4 estimated factors, but two curvature factors also show more symmetrical movements than before. This means that two curvature factors are not correctly identified. The NSS model has the advantage of always having a better goodness of fit than the NS model because it adds another curvature factor. However, it has the disadvantage of making the interpretation of the factors more difficult than the NS model, especially when two curvature factors are not correctly identified.


In particular, the factors extracted by the NS or NSS model are often used as explanatory variables in various econometric models because they effectively summarize the term structure of interest rates, but the factors in the NSS model are difficult to interpret and there is a question whether they can be used as explanatory variables because the two curvature factors have similarly large values and opposite signs.

The correlation of two curvature factors is -0.7263771 and it is high even if we consider the independent factor DNSS model. This problem is not easy to solve because it is difficult to find the appropriate constraints.

As mentioned in Diebold et al. (2006), it is difficult to interpret the curvature factor (the first curvature factor in the NSS model) from a macro-yield nexus perspective. Later, Moench (2012) find that The curvature factor is found to carry predictive information both about the future evolution of the yield curve and the macroeconomy and that unexpected increases of the curvature factor precede a flattening of the yield curve and announce a significant decline of output more than 1 year ahead.

However, the second curvature factor in the NSS model is even more difficult to interpret and is understood to serve only to improve the long-term maturity fit. Therefore, there is no economic interpretation of the second curvature factor in the literature.

Therefore, I think that further research on the NSS model is needed to improve factor identification, especially between two curvature factors, and interpretability of these factors using a new approach.


Concluding Remarks


This post implements the Nelson-Siegel-Svensson model with fixed or estimated constant lambda. But it show a tendency of instability of two curvature dynamics.

Reference

Moench, E. (2013), Term structure surprises: the predictive content of curvature, level, and slope, Journal of Applied Econometrics 27-4, 574-602.

Diebold, F. X., G. D. Rudebusch S. B. Aruoba, 2006. The macroeconomy and the yield curve: a dynamic latent factor approach. Journal of Econometrics 131-1, 309–338.

Svensson, L. (1994). Estimating and Interpreting Forward Interest Rates: Sweden 1992 – 1994. Working Paper, National Bureau of Economic Research. \(\blacksquare\)


No comments:

Post a Comment