1 votos

Problemas para calibrar un modelo Vasicek

He simulado algunos datos según un proceso de Vasicek y luego estoy intentando aplicar un análisis de regresión por mínimos cuadrados ordinarios (MCO) para ver la exactitud de los parámetros del modelo estimado a partir de la estimación. Sin embargo, mis parámetros estimados del modelo no parecen ni siquiera acercarse a lo que deberían ser. He intentado dejar que T sea muy grande, e incluso he simulado 100.000 trayectorias y he estimado el modelo para cada trayectoria, y luego he promediado las estimaciones. Sin embargo, los resultados siguen siendo erróneos. Así que o bien estoy simulando mis datos mal, o la regresión que estoy haciendo es de alguna manera incorrecta. He adjuntado mi código python a continuación, así que si alguien puede echar un vistazo y decirme por qué los parámetros de mi modelo están mal, se lo agradecería mucho.

La forma del modelo que estoy utilizando es:

$$ dr_t = (a - b r_t) dt + \sigma dW.$$

Para estimar los parámetros de mi modelo estoy ajustando una regresión sobre los datos discretos que me da el siguiente modelo:

$$ r_{t+1} - r_{t} = (a - b r_t) \Delta t + \sigma Z_t$$

donde $ Z_t \sim N(0,\Delta t)$ (es decir, media 0, varianza $\Delta t$ ). A partir de esta configuración sé que mi intercepción estimada será $ a\Delta t$ y mi pendiente estimada será $-1 * b \Delta t$ . Por lo tanto, en mi función fit_vasicek_model, hago la transformación necesaria para recuperar "a" y "b".

Aquí está mi código ( he omitido algunas partes que son irrelevantes para esta pregunta )

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import random
import statsmodels.formula.api as smf
import statsmodels.api as sm
import statsmodels.tools as sm_tools

class InterestRateModels:

    def __init__(self, nsim, T, Vas = None):
        self.N = nsim
        self.T = T
        self.dt = 1/T
        self.Vas = Vas

    def sim_vasicek(self, r0, a, b, sigma):
        """
        Inputs:
        -------
        N = number of paths to simulate
        T = number of time steps to take
        r0 = initial (current) short-term rate
        a, b, sigma = parameters of the model

        The Model:
        ----------
        dr_t = (a  b*r_t)*dt +  * dBt

        r_t = short rate
        a = long-run average rate, a in Real Numbers
        b = speed of reversion, b > 0
        sigma = volatility of short rate
        Bt = Gaussian (0 mean, 1 sigma) process

        Returns:
        --------
        Creates an object attribute that is a matrix of simulated short rate paths.
        """
        dt = 1.0/self.T
        X = np.random.normal(0,np.sqrt(dt),size=(self.N,self.T))
        self.Vas = np.zeros((self.N,self.T)); self.Vas[:,0] = r0;
        for i in range(self.N):
            for j in range(1,self.T):
                self.Vas[i,j] = self.Vas[i,j-1] + (a-b*self.Vas[i,j-1]) * dt + sigma * X[i,j]
        return

    def plot_vasicek(self):
        for i in range(self.N):
            plt.plot(self.Vas[i,:])
        return

    def fit_vasicek_model(self, rate_path):
        """
        Inputs:
        -------
        rate_path is a single interest rate path.

        Returns:
        --------
        Parameters of the model (not the regression paraneters, as they get transformed)
        Intercept = a * dt
        Slope = -1 * b * dt (The slope needs to be multiplied by negative 1)
        """

        n = len(rate_path)
        X = rate_path[:n-1]
        y = np.diff(rate_path)
        X = sm_tools.tools.add_constant(X)
        model = sm.OLS(y,X)
        results = model.fit()
        a, b1 = results.params / self.dt
        b = -1 * b1
        return a, b

Así que ahora, cuando creo una instancia y simulo un montón de trayectorias, y luego ajusto el modelo, tengo parámetros para a y b que ni siquiera se acercan a su valor real. Aquí está mi conjetura en cuanto a por qué: Tiene que haber un período lo suficientemente largo (es decir, T es lo suficientemente grande), en relación con el parámetro de reversión, b. Significa que si b es grande, T puede ser pequeño. Si b es pequeño, T debe ser grande.

# nsim=1000, T=30, a=1, b=4 #
rates_sim = InterestRateModels(nsim=1000, T=30)
rates_sim.sim_vasicek(.02, a=1, b=4, sigma=.3)
rates_sim.plot_vasicek()

b_lst = []
a_lst = []
for i in range(rates_sim.N):
    rate_path = rates_sim.Vas[i,:]
    a, b = rates_sim.fit_vasicek_model(rate_path)
    a_lst.append(a)
    b_lst.append(b)

np.mean(b_lst)
Out[273]: 7.0396842314975165

Observa que la media de b es 7,03, no 4. Así que ahora cuando dejo T=1000 esto es lo que veo.

np.mean(b_lst)
Out[275]: 7.538313498938557

Esto sigue siendo un poco fuera de lugar. He mirado el gráfico de las curvas de velocidad y no parecen totalmente estacionarias. Así que dejando que b sea realmente grande (es decir, b=30), incluso para un T=30 más pequeño obtengo el siguiente resultado

np.mean(b_lst)
Out[277]: 31.078385891056488

Esto parece lo que yo esperaría. Entonces, ¿cuál es la regla general para una convergencia razonable? He leído en alguna parte que debemos tener $\mid 1 - b \Delta t \mid <= 1$ aunque cuando $\Delta t = 1/30$ y $b=4$ Esto sigue siendo cierto, pero los resultados son horribles. Gracias por leer esto, y aprecio cualquier ayuda que los filks puedan dar.

1voto

Jacob Jones Puntos 26

Su modelo es:

dr_t = (a - b*r_t)*dt + σ * dBt

Sin embargo, el modelo Vasicek sí lo es:

dr_t = a(b - r_t)*dt + σ * dBt

¿Puedes actualizar la ecuación e intentarlo de nuevo?

Normalmente, a es la velocidad de reversión media y b es el nivel de reversión media

https://en.wikipedia.org/wiki/Vasicek_model

0 votos

Gracias, lo probaré. Aunque, en mi parametrización la media es b/a, así que mi conjetura inicial es que al cambiar cómo simular mis datos sólo estaré cambiando la interpretación de los parámetros de regresión.

0 votos

¿Acabó ayudando esto?

1voto

Rahul Gupta Puntos 145

Consulte este artículo: https://papers.ssrn.com/sol3/papers.cfm?abstract_id=130068

Esto se hace en tiempo discreto, lo que hace que sea más fácil de calibrar en la práctica.

0 votos

Leeré esto a ver si me ayuda. Gracias.

Finanhelp.com

FinanHelp es una comunidad para personas con conocimientos de economía y finanzas, o quiere aprender. Puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X