Pacote Nelson-Siegel-Svensson

Pacote Nelson-Siegel-Svensson

Modelo Nelson-Siegel-Svensson Dinâmico Utilizando o Filtro de Kalman

Este pacote implementa os modelos Dinâmicos de Nelson-Siegel-Svensson (DNSS) com filtro de Kalman em Python. O principal objetivo desse pacote é facilitar o trabalho do pesquisador ao otimizar, ajustar e prever a curva de juros em uma única etapa (Fonte).

Abaixo, vamos reproduzir um exemplo utilizando uma base de dados dos EUA entre Janeiro/1972 e Dezembro/2000, com maturidades entre 3 e 120 meses.

O vetor de parâmetros iniciais (param) segue da seguinte forma:

\( \log(\lambda) \): logaritmo do parâmetro de decaimento,

\(\Sigma_\varepsilon^{1/2}\): raiz quadrada da matriz de variância da equação de observação (diagonal),

\(\Phi \): matriz de parâmetro dos fatores nível, inclinação e curvatura (para o modelo DNS),

\(\Sigma_\eta^{1/2} \): decomposição de Cholesky da matriz de variância da equação de medida.

Lembrando que os parâmetros iniciais utilizados nesse exemplo foram calculados utilizando o modelo em dois estágios (Fonte) .

from Dynamic_Nelson_Siegel_Svensson_Kalman_Filter import kalman
import numpy as np
import pandas as pd

url = 'https://www.dropbox.com/s/inpnlugzkddp42q/bonds.csv?dl=1' # US Yield Curve 1972 - 2000
df = pd.read_csv(url,sep=';',index_col=0)

frct = False # 'False' porque não queremos fazer previsão.
ahead = 0 # Se previsão for 'TRUE', definir números de previsões a frente (em meses) 
lik = True # 'True' porque vamos fazer a otimização dos parâmetros.
mty =  np.array([3,6,9,12,15,18,21,24,30,36,48,60,72,84,96,108,120]) # maturidades em meses
model = 'NS' # 'S' para Svensson.

param = np.array([-2.798522, # log of 0.0609
0.14170940,0.07289485,0.11492339,0.11120008,0.09055795,0.07672075,0.07222108,0.07076431,0.07012891,0.07267366,0.10624206,0.09029621,0.10374527,0.09801215,0.09122014,0.11794190,0.13354418, # Sigma_varepsilon^{1/2}
0.99010443,0.02496842,-0.002294319, # phi
-0.02812401,0.94256154, 0.028699387, # phi
0.05178493,0.01247332, 0.788078795, # phi
8.345444,-1.572442,0.2029919,  # mu
0.3408764,-0.07882772,-0.21351036, # Sigma_eta^{1/2}
0.62661018,-0.00425989, # Sigma_eta^{1/2}
1.08802059]) # Sigma_eta^{1/2}

kalman(param = param,Y = df, lik = lik, frct = frct, ahead = ahead, mty = mty, model = model)
-2281.5860793152

Agora vamos fazer a otimização numérica do modelo.

from scipy import optimize

optimize.minimize(fun = kalman, x0 = param, args = (df,lik,frct,ahead,mty,model),method = 'L-BFGS-B', bounds = None,options={'disp':True})

Após alguns minutos (dependendo do seu computador, poderá levar entre 20 e 40 minutos), o resultado final deverá ser o seguinte:

...
 CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH
 fun: -3184.551029683603
 ...
 success: True
 x: array([-2.55419095,  0.2682528 ,  0.07550792,  0.09029396,  0.10450556,
 0.09915572,  0.08648558,  0.07862346,  0.07209206,  0.07267585,
 0.07909973,  0.10295337,  0.09260472,  0.10041753,  0.1117615 ,
 0.10696698,  0.15069579,  0.17277911,  0.99437232,  0.02861622,
-0.02214779, -0.02886483,  0.93904762,  0.03963317,  0.02540488,
 0.02288304,  0.84151308,  7.99042415, -1.46634099, -0.43379175,
 0.30276472, -0.02340832,  0.0488872 ,  0.61858155,  0.01026079,
 0.89411573])

Os parâmetros foram otimizados, houve convergência na otimização. Após esse resultado, seria interessante pegar os parâmetros ótimos e usá-los para fazer previsão...

Até a próxima!