Simulación de un modelo DCC-GARCH(1,1)
Dado que ya se tiene un conjunto dado de parámetros correctamente definidos para el modelo DCC-GARCH, los residuos estandarizados $\varepsilon_{t-1}$ se recuperan de los modelos GARCH univariantes y se introducen en la estructura DCC para obtener su dinámica de correlación simulada. La simulación de un modelo DCC-GARCH puede definirse en 3 pasos generales:
-
Simular la dinámica GARCH univariante utilizando un algoritmo de filtro para parámetros predefinidos y recuperar los residuos estandarizados. A continuación, construya una función general que simule $d$ Modelos GARCH con diferentes conjuntos de parámetros (o el mismo conjunto de parámetros).
-
Utilice los residuos estandarizados de (1) para simular la dinámica del DCC y recuperar la estructura de correlación. A partir de la construcción, sabemos que $\varepsilon_{t-1} \overset{iid}{\sim} N(0,1)$ y así se puede simular la dinámica DCC y sacar la correlación sin el componente GARCH.
-
Recuperar la matriz de covarianza a través de las varianzas univariantes y la estructura de correlación mediante la siguiente fórmula, $\Sigma_t=D_t^{1/2}R_t D_t^{1/2}$ con $D_t = diag(\sigma_{i,t}^2)$
A lo largo de la respuesta, el código se escribirá en R
. Además, el código no estará optimizado.
1. Simulación de múltiples modelos GARCH univariantes
Formalmente, definamos los rendimientos (degradados) en un entorno univariante,
\begin{equation} r_t = \sigma_t \epsilon_t \iff \frac{r_t}{\sigma_t} = \epsilon_t, \end{equation}
donde $\epsilon_t \overset{iid}{\sim}N(0,1)$ son los residuos estandarizados univariantes. Esto implica además que $r_t \sim N(0, \sigma_t^2)$ que utilizaremos en la simulación. La dinámica de la varianza de los rendimientos univariantes sigue un GARCH(1,1) de la forma:
\begin{equation} \sigma^2_t = \omega + \alpha r_{t-1}^2 + \beta \sigma^2_{t-1}. \end{equation}
La forma de simular un modelo GARCH la iniciamos con un muestreo $r_1 \sim N(0,\sigma^2_1)$ , donde $\sigma^2_1 = \frac{\omega}{1-\alpha - \beta}$ es la varianza incondicional. Después, actualizamos recusivamente la dinámica de la varianza y simulamos los rendimientos utilizando el rnorm()
función.
La función se presenta a continuación con el nombre GARCHSim
y ha sido ampliamente comentado. Para facilitar la implementación, construimos una función ( GARCHmultisim
) que realiza múltiples simulaciones en una sola llamada a la función. Aquí, la variable de parámetros ( params
) será un $d \times 3$ matriz con $d$ que denota la cantidad de modelos GARCH a simular. La función produce una lista de dos matrices con dimensiones $sims \times d$ donde uno contiene los residuos estandarizados y el otro contiene la varianza.
2 + 3. Simulación de la estructura DCC mediante residuos estandarizados
La construcción del algoritmo del filtro para la estructura DCC es, más o menos, el mismo procedimiento que con el modelo GARCH. Tenemos que actualizar $Q_t$ para cada punto de tiempo y luego reconstruir la matriz de correlación siguiendo $R_t = \tilde{Q}_t^{-1/2} Q_t \tilde{Q}_t^{-1/2}$ con $\tilde{Q_t}$ que contiene los elementos diagonales de $Q_t$ . Entonces podemos reconstruir la matriz de covarianza, $\Sigma_t$ utilizando la relación del punto 3.
Además, modelamos $Q_t$ siguiendo una estructura tipo GARCH(1,1) en la que imponemos la estacionariedad débil (es decir. $a+b<1$ ) para garantizar que $Q_t$ es positiva definida e implica que $R_t$ es positiva definida: \begin{equation*} Q_t = \bar{Q} (1-a-b) + a (\eta_{t-1}\eta_{t-1}^\intercal) + b Q_{t-1}, \end{equation*}
donde $\bar{Q}$ es la matriz de covarianza incondicional de los residuos estandarizados multivariantes $\eta_t$ . Podemos recuperar ambos parámetros de la siguiente manera
\begin{align*} \bar{Q} &= \frac{1}{T} \sum_{t=1}^{T} \eta_t \eta_t^\intercal\\ \eta_t &= D_t^{-\frac{1}{2}} r_t \sim N(0, R_t), \end{align*} que utilizaremos en nuestro procedimiento de simulación. La función se ha denominado DCCsim
y se encuentra al final del fragmento de código.
Ilustración gráfica
He proporcionado una ilustración gráfica de un modelo DCC-GARCH(1,1) bivariado simulado con parámetros arbitrarios dados por:
$$\omega_{1}=0.02, \quad \alpha_1 = 0.08, \quad \beta_1 = 0.89, \quad \omega_{2}=0.02, \quad \alpha_2 = 0.05, \quad \beta_2 = 0.94, \quad a=0.1, \quad b=0.89,$$
con $\omega_i, \: \alpha_i, \: \beta_i$ para $i=1,2$ siendo los parámetros del primer y segundo proceso GARCH, que también se representan a continuación en rojo y verde respectivamente.
Algunos comentarios
-
La estructura de correlación en el modelo DCC depende de los residuos de los modelos GARCH. Esencialmente, los modelos GARCH univariantes no captan la estructura de dependencia y, por tanto, estará contenida en los residuos. Sin embargo, los residuos siguen una distribución gaussiana estándar univariante (y son iid ), por lo que no tiene ninguna estructura de correlación. Esto implica que la correlación incondicional tiende a cero cuando $sims \rightarrow \infty$ .
-
También se pueden simular variantes normales multivariantes con correlaciones dinámicas en el modelo DCC, donde las correlaciones se estiman a partir de las comillas bursátiles del mundo real ( es decir, puede utilizar la función mvrnorm en R con una matriz de covarianza cambiante, basada en diferentes correlaciones ), o puede intentar utilizar distribuciones alternativas para los residuos.
-
El modelo de correlación condicional constante (CCC) se recupera reconstruyendo la matriz de covarianza ( DCC_COVAR
) donde se sustituye acor
con la correlación incondicional, mQ
.
-
Cualquier extensión en los modelos GARCH univariantes es válida debido a la separación de las dinámicas de correlación y volatilidad.
La implementación anterior proporciona un marco de simulación básico. En consecuencia, podría haber formas más eficientes de construir correlaciones simuladas realistas dentro de la estructura DCC o formas completamente alternativas de simular este modelo. Espero que esto al menos le proporcione una idea a usted y a los futuros lectores .
Apéndice del código
El código se presenta a continuación.
# Univariate GARCH simulation
GARCHSim <- function(omega, alpha, beta, sims) {
#sims (integer): Number of simulations performed.
## initialize the vector of simulated returns and variances
ret = numeric(sims)
sigma2 = numeric(sims)
## initialize the variance at time t = 1 with the unconditional variance.
sigma2[1] = omega/(1.0 - alpha - beta)
## sample the first observations
ret[1] = rnorm(1, mean = 0, sd = sqrt(sigma2[1]))
## loop over sims.
for (t in 2:sims) {
#update volatility
sigma2[t] = omega + alpha * ret[t - 1]^2 + beta * sigma2[t - 1]
# sample new observarion
ret[t] = rnorm(1, mean = 0, sd = sqrt(sigma2[t]))
}
## we return a list with three components: the sampled returns, the variance,
## and the standardized residuals.
lOut = list()
lOut[["ret"]] = ret
lOut[["sigma2"]] = sigma2
# gives standardized residuals for demeaned returns.
lOut[["stdres"]] = ret/sqrt(sigma2)
return(lOut)
}
# Multiple simulations of the GARCH model.
GARCHmultisim <- function(params, sims){
multisim_res <- matrix(0L, nrow=sims, ncol = nrow(params))
multisim_sigma <- matrix(0L, nrow=sims, ncol = nrow(params))
# rows in parameter matrix determines amount of garch simulations.
for(i in 1:nrow(params)){
# matrix() transforms it into a vector.
multisim_res[, i] <- matrix(GARCHSim(params[i,1], params[i,2], params[i,3], sims)[["stdres"]])
multisim_sigma[, i] <- matrix(GARCHSim(params[i,1], params[i,2], params[i,3], sims)[["sigma2"]])
}
lOut = list()
lOut[["res"]] = multisim_res
lOut[["sigma"]] = multisim_sigma
return(lOut)
}
# Simulation for the Dynamic Conditional Correlations (DCC).
DCCsim <- function(GARCH_params, a, b, sims){
stdres <- GARCHmultisim(GARCH_params, sims)[["res"]]
Gsigs <- GARCHmultisim(GARCH_params, sims)[["sigma"]]
mQ = cor(stdres)
iN = ncol(stdres)
iT = nrow(stdres)
# initialize the array for the correlations
aCor = array(0, dim = c(iN, iN, iT))
# initialize the array for the Q matrices
aQ = array(0, dim = c(iN, iN, iT))
## initialization at the unconditional cor
aCor[,, 1] = mQ
aQ[,,1] = mQ
# main loop
for (t in 2:iT) {
# update the Q matrix
aQ[,, t] = mQ * (1 - a - b) + a * t(stdres[t - 1, , drop = FALSE]) %*%
stdres[t - 1, , drop = FALSE] + b * aQ[,,t - 1]
## Compute the correlation as Q_tilde^{-1/2} Q Q_tilde^{-1/2}
aCor[,, t] = diag(sqrt(1/diag(aQ[,, t]))) %*% aQ[,, t] %*%
diag(sqrt(1/diag(aQ[,, t])))
}
#Getting univariate variance matrix D_t:
msigma <- array(0L, dim = c(ncol(Gsigs), ncol(Gsigs), nrow(Gsigs)))
for(i in 1:ncol(Gsigs)){
msigma[i, i, ] <- Gsigs[, i]
}
# constructing the covariance matrix
DCC_COVAR <- array(0, dim = c(ncol(Gsigs), ncol(Gsigs), nrow(Gsigs)))
DCC_returns <- matrix(0, nrow = nrow(Gsigs), ncol = ncol(Gsigs))
for(i in 1:sims){
DCC_COVAR[,,i] <- msigma[,,i]^0.5 %*% aCor[,,i] %*% msigma[,,i]^0.5
# Getting returns:
DCC_returns[i,] <- mvrnorm(1, rep(0,ncol(Gsigs)), DCC_COVAR[,,i])
}
lOut = list()
# correlations
lOut[["aCor"]] = aCor
# univariate variances
lOut[["Gsigs"]] = Gsigs
# covariances
lOut[["DCC_COVAR"]] = DCC_COVAR
# returns
lOut[["DCC_returns"]] = DCC_returns
return(lOut)
}
```