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!