A common approach that can be used to fit the interest rates for different maturities given a set of key-rates is linear interpolation. However a more flexible approach, often used by central banks, is to calibrate the parameters of a model and then to use it to recover the interest rate for any time to maturity. In Equation 1 we present a modified version of the original Nelson-Siegel model, called Nelson-Siegel-Svennson model, in which are introduced two additional parameters, \(\beta_3\) and \(\tau_2\), in order to have more flexibility.
Under this model we can interpret the first two parameters \(\beta_0\) and \(\beta_1\) in the following way:
\(\beta_0\): can be interpreted as the long term interest rate,
\(\beta_0 + \beta_1\): can be interpreted as instantaneous short term interest rate.
In order to have this constraints valid we will need to perform a constraint optimization problem in which the function to optimize is given by the mean square error of the fitted value with respect to the real values (over discrete maturities \((T_a, ....T_b)\)):
where \(\alpha = 0.01\). is an arbitrary threshold level that establish the accuracy of the constraint. To a lower threshold correspond a better fit, however if we set it to low we may not reach a set of parameters that satisfy it.
In order to find the optimal parameters, it is necessary to solve a minimization problem starting from a set of 6 parameters, in general arbitrary or randomly generated. In this case, the following algorithm was implemented:
Fix \(\beta_0\) and \(\beta_1\) both equal to \(\frac{h(0,t_1)}{2}\), in such a way the initial parameters respect the constraint in Equation 5.
Perform the minimization problem in Equation 4 subject the constraints.
# euribor 2022-11-16y <-c(1.1091, 1.6094, 1.7661, 1.8521, 1.881)# times to maturities in yearstau <-c(1, 5, 10, 20, 30)# calibrate parameters fit <-fit_nelson_siegel(term_structure = y/100, tau = tau, params =NULL, threshold =0.01)# create a fitting function with optimal parameters ns <-nelson_siegel(fit$optim_params[[1]])# fitted yields under Nelson-Siegel y_pred <-ns(tau)*100library(ggplot2)ggplot()+geom_line(aes(tau, y))+geom_point(aes(tau, y), color ="red")+geom_line(aes(tau, y_pred), linetype="dashed", color="red")+theme_bw()
Note that it is always a good practice to rescale the rates/yield in the interval \([0,1]\). To see the potential problems generated by expressing the data on a percentage scale. We do not rescale the yield, letting them expressed in percentage. As shown in the following plot this causes fitting issues on the red curve.
Show the code
# calibrate parameters fit <-fit_nelson_siegel(term_structure = y, tau = tau, params =NULL, threshold =0.01)# create a fitting function with optimal parameters ns <-nelson_siegel(fit$optim_params[[1]])# fitted yields under Nelson-Siegel y_pred <-ns(tau)ggplot()+geom_line(aes(tau, y))+geom_point(aes(tau, y), color ="red")+geom_line(aes(tau, y_pred), linetype="dashed", color="red")+theme_bw()