Mostrando entradas con la etiqueta garch. Mostrar todas las entradas
Mostrando entradas con la etiqueta garch. Mostrar todas las entradas

8 ago 2023

Midiendo la volatilidad en las series económicas/financiera (ejemplos en R)

La volatilidad de las series financieras y económicas es un momento (característica) indispensable para caracterizar cualquier serie. Usualmente esta mide el nivel de fluctuaciones de una serie alrededor de una medida de referencia, por lo general, la media. Por lo que, una mayor varianza generalmente esta asociada a mayor incertidumbre de los datos. En aplicaciones puntuales, indican que la volatilidad del retorno de un activo financiero se asocia con su precio; la volatilidad del tipo de cambio se asocia al uso de instrumentos de cobertura por parte de los agentes del mercado; la volatilidad de la inflación resta capacidad de pronósticos por los interesados; igual mayor incertidumbre en la actividad económica puede llevar a las instituciones financieras a tomar mayores precauciones frente a posibles eventos adversos, incidiendo inclusive en posibles caídas del consumo… En todos los casos, la volatilidad tiene una incidencia directa sobre las decisiones económicas y las características de las series.

En este marco y entendiendo que la incertidumbre alrededor de la serie es una condición latente (no observable), surgen diferentes alternativas para su medición. La primera de estas alternativas corresponde a la volatilidad incondicional de la serie estacionaria[1]. La estacionariedad de la serie suele aproximarse a partir de la primera diferencia logarítmica, que en finanzas se les llaman retornos.

library(dplyr)
data("EuStockMarkets")
 
dln_dax <- EuStockMarkets |>
  as.data.frame() |>
  mutate(DAX_Return = log(DAX) - log(dplyr::lag(DAX))) |>
  select(DAX_Return)
 
sd(dln_dax$DAX_Return, na.rm = TRUE)
[1] 0.01030084

Volatilidad incondicional

A partir de la varianza de la primera diferencia logarítmica de la serie hemos obtenido la desviación estándar incondicional como primera aproximación de la volatilidad de la serie en cuestión. Ahora bien, una simple inspección del grafico de esta serie (1ra diferencia logarítmica), nos lleva aprecios que el grado de las fluctuaciones de las series respecto al nivel de referencia tiende a cambiar en el tiempo.

library(ggplot2)
ggplot(df, aes(x = time(EuStockMarkets), y = DAX_Return)) +
  geom_line() +
  labs(x = "Fecha", y = "Log-Retorno DAX", title = "Log-Retornos Diarios de DAX") +
  theme_minimal()  


Si estimáramos la varianza en dos lugares distintos de nuestra muestra de datos, obtendríamos valores diferentes.

 sd(dln_dax$DAX_Return[15:150], na.rm = TRUE)
sd(dln_dax$DAX_Return[900:1000], na.rm = TRUE)

Bajo estas condiciones, ha sido ampliamente documentado en la literatura que esta media suele enfrentar inconvenientes asociados a:

i.                    Considera la volatilidad como un fenómeno estable en el tiempo.

ii.                  Reconoce como volatilidad cambios de nivel en la serie o presencia de tendencias.

iii.                No reconoce que parte de las fluctuaciones de una serie podrían ser anticiparles (en caso de serlo no se entiende como volatilidad).

iv.                 Es una medida que mira hacia el pasa.

Ventana de volatilidad

Estas debilidades han llevado a considerar algunas medias alternativas de volatilidad. La primera de estas medidas es la media móvil. Esta consiste en seleccionar una ventana temporal (por ejemplo 20 observaciones) e ir calculando la volatilidad en cada ventana temporal, de forma tal, que se obtenga una medida de la volatilidad histórica. Por ejemplo: tomamos las primeras 20 observaciones, luego tomamos de la observación 2:21, 3:22, … hasta recorrer toda la muestra. Esto permite obtener un vector de volatilidades.

library(zoo)
window_size <- 66
r_dax <- dln_dax$DAX_Return[-1]
volatility_window <- rollapply(r_dax, width = window_size,
                               FUN = sd, align = "right", fill = NA)
 
dln_dax$H_vent_vol <-  c(NA,volatility_window)

Note como ahora se esta considerando la volatilidad como un momento cambiante en el tiempo:

ggplot(dln_dax, aes(x = time(EuStockMarkets), y = H_vent_vol)) +
  geom_line() +
  geom_hline(yintercept = sd(dln_dax$DAX_Return, na.rm = TRUE),
                    col = "red", linetype = "dashed") +
  theme_minimal()


Ponderación exponencial

Sin embargo, las ventanas de volatilidad también suelen presentar debilidades importantes asociadas a que no es trivial seleccionar la amplitud deseada de la ventana de estimación, en el sentido de que ventanas muy pequeñas sueles ser bastante sensible al nuevo dato observados, mientras que al usar ventanas más grandes la serie tiende a suavizarse. Por tanto, la amplitud de la ventana dependerá de cual entendamos modela mejor las características de las series. Otra debilidad es que pondera por igual todas las observaciones de nuestra base, cuando entendemos que los valores recientes guardan mayor cantidad de información. Ambas debilidades son enfrentadas por un modelo de exponenciación exponencial, que permite brindar mayor ponderación a las observaciones recientes, además salta el problema de la selección de ventana.

tobs <- length(r_dax)
varEWMA<- var(r_dax, na.rm=TRUE);
lambda<-0.94
 
for (t in 2:(tobs + 1)) {
  varEWMA[t]<-lambda*varEWMA[t-1]+(1-lambda)*(r_dax[t-1]^2)
  #no consideramos la primera obs
}
 
dln_dax$H_Ewma <- sqrt(varEWMA)
 
dln_dax %>%
  select(starts_with("H_")) |>
  mutate(fecha= time(EuStockMarkets)) |>
  pivot_longer(cols = -fecha, names_to = "variable", values_to = "valor") |>
  ggplot(aes(x = fecha, y = valor, color = variable)) +
  geom_line() +
  theme_minimal()


Modelos GARCH

Adicional a las alternativas anteriores, buscando modelar regularidades empíricas observadas alrededor de las seréis económicas y financieras, se han agregado los modelos GARCH, estos modelos son una generalización de los modelos ARCH y permiten modelar temas como reversión a la media. Capacidad para modelar patrones de volatilidad a largo plazo: Los modelos GARCH son más adecuados para modelar patrones de volatilidad a largo plazo, lo que significa que pueden adaptarse mejor a la evolución de la volatilidad en el tiempo. En R, el paquete rugarch permite estimar este tipo de modelos.

library(rugarch)
spec <- ugarchspec(variance.model = list(model = "sGARCH",
                                         garchOrder = c(1, 1)))
 
fit <- ugarchfit(spec, data = r_dax)
volatility <- sigma(fit)
 
dln_dax$H_garch <- c(NA, volatility[,1])
 
dln_dax %>%
  select(starts_with("H_")) |>
  mutate(fecha= time(EuStockMarkets)) |>
  pivot_longer(cols = -fecha, names_to = "variable", values_to = "valor") |>
  ggplot(aes(x = fecha, y = valor, color = variable)) +
  geom_line() +
  theme_minimal()


Modelos ARMA-GARCH no gaussiano

Extensiones del modelo GARCH han permitido incorporar no normalidades (por ejemplo, usando distribución t, que permite incorporar colas más pesas que indican que los eventos extremos se hacen más posibles); asimetrías en la respuesta en volatilidad (modelos gjr-garch que indican que las noticias positivas/negativas tendrán un efecto diferenciados; o modelar conjuntamente correlaciones en el nivel de la serie estacionaria, mediante los conocidos arma-garch.

spec <- ugarchspec(variance.model = list(model = "gjrGARCH",
                                         garchOrder = c(1, 1)),
                   mean.model = list(armaOrder = c(1, 1)),
                   distribution.model = "std")
 
fit2 <- ugarchfit(spec, data = r_dax)
volatility2 <- sigma(fit2)
 
 
dln_dax$H_gjr_t <- c(NA, volatility2[,1])
 
dln_dax %>%
  select(starts_with("H_")) |>
  mutate(fecha= time(EuStockMarkets)) |>
  pivot_longer(cols = -fecha, names_to = "variable", values_to = "valor") |>
  ggplot(aes(x = fecha, y = valor, color = variable)) +
  geom_line() +
  theme_minimal() +
  gghighlight(variable=="H_gjr_t")  


Bayesian Inference for Stochastic Volatility

Finalmente, otras alternativas de los modelos de volatilidad provienen de los modelos de volatilidad estocástica.

library(stochvol)
 
res <- svsample(r_dax, priormu = c(-10, 1), priorphi = c(20, 1.1), priorsigma = .1)
summary(res, showlatent = FALSE)
 
dln_dax$H_stoc_v <- c(NA, res$summary$sd[,"mean"])
 
dln_dax %>%
  select(starts_with("H_")) |>
  mutate(fecha= time(EuStockMarkets)) |>
  pivot_longer(cols = -fecha, names_to = "variable", values_to = "valor") |>
  ggplot(aes(x = fecha, y = valor, color = variable)) +
  geom_line() +
  theme_minimal() +
  gghighlight(variable %in% c("H_gjr_t","H_stoc_v"))




[1] Recuerde que el uso de momentos solo se justifica en casos donde la serie estimada sea estacionaria. Por ende, al medir la volatilidad de una serie temporal, debemos testear previamente el orden de integración de la serie, pasa saber si necesitamos realizar alguna transformación previa antes de estimar la volatilidad.

14 mar 2023

Rollapply sobre múltiples series en R

En la siguiente entrada se usan diversas estrategias GARCH para obtener diferentes series de volatilidad. El tema es que estas series presentan mucho ruido en su evolución histórica y se proponen promedios móviles de cada una para una representación con menos ruidos. El ejemplo se realiza usando tidyverse. [ver entrada anterior donde se explica cómo preparar las series de volatilidad (es decir, hasta el punto donde se colocan los gráficos): http://betaeconomia.blogspot.com/2022/07/modelos-garch-sobre-multiples-series.html].

dataVol %>%
  mutate(fecha = 1:nrow(dataVol)) %>%
  as.data.frame() %>%
  pivot_longer(!fecha, names_to = "var", values_to = "value") %>%
  ggplot(aes(x = fecha, y = value)) +
  geom_line(aes(color = var))+
  facet_wrap(~var, scales='free_y', ncol = 2) +
  theme_classic()+
  theme(legend.position = "none",
        axis.ticks = element_line(colour = "grey70", size = 0.2),
        strip.background = element_blank()) +
  scale_colour_grey(start = 0.1,end = 0.1)
 
 

Ahora, antes de graficar las volatilidades se crea una variable que representa los promedios de cada serie particular. Esto se hace para disimular el ruido [Aquí se explica en detalle como se usa la función: https://betaeconomia.blogspot.com/2022/04/aplicaciones-de-la-funcion-rollaplay-de.html].

dataVol %>%
  mutate(fecha = 1:nrow(dataVol)) %>%
  as.data.frame() %>%
  pivot_longer(!fecha, names_to = "var", values_to = "value") %>%
  group_by(var) %>%
  mutate(value2 = rollapply(data = value, width = 22, FUN = mean, fill=NA, align = "right", partial = T)) %>%
  ggplot(aes(x = fecha, y = value2)) +
  geom_line(aes(color = var))+
  facet_wrap(~var, scales='free_y', ncol = 2) +
  theme_classic()+
  theme(legend.position = "none",
        axis.ticks = element_line(colour = "grey70", size = 0.2),
        strip.background = element_blank()) +
  scale_colour_grey(start = 0.1,end = 0.1)



27 jul 2022

4 Curso de Econometría Aplicada en R

Parte I. Introducción a la Economettría
Curso 1. Regresión y naturaleza del análisis econométrico
Clase 1. Naturaleza del modelo Econometríco
Clase 2. Repaso de inferencia estadística
Clase 3. Modelo de regresión
Clase 4. Modelo de regresión múltiple
Clase 5. Modelo de regresión en R

Curso 2. Análisis del modelo de regresión y econometría aplicada
Clase 6. Test de hipótesis 
Clase 7. Inferencia sobre el modelo de regresión en R
Clase 8. Formas funcionales y variables discretas
Clase 9. Formas funcionales en R
Clase 10. Selección de modelos en R

Parte II. Microeconometría y datos de Panel
Curso 3. Microeconometría y datos de panal
Clase 1. Causalidad estadística
Clase 2. Endogeneidad y variables instrumentales
Clase 3. Modelos de probabilidad
Clase 4. Panel estatico 

Parte III. Econometría Financiera y de Series Temporales
Curso 4. Econometría financiera en R
Clase 1. Modelos ARIMA en R
Clase 2. Modelos de volatilidad (GARCH en R)
Clase 3. Modelos factoriales y riesgo sistémico 
Clase 4. Valor en riesgo (VaR)
Clase 5. Vectores autoregresivos (VAR)


1 jul 2022

Modelos GARCH sobre múltiples series financieras

 En la siguiente entrada vamos a estimar un modelo de volatilidad condicional para cada una de las variables contenidas en una base de datos, independientemente al numero de variables. Para tal ejemplo usamos la data EuStockMarkets que continente algunos índices financieros. Primero revisamos hemos importado los datos correctamente y realizamos un análisis descriptivo. En este caso no lo hacemos, pero recuerde siempre verificar temas como cambios estructurales, datos perdidos, distribución de los datos, ….

library(dplyr)
library(tibble)
library(fGarch)
library(ggplot2)
library(stargazer)
library(tidyr)

head(EuStockMarkets)
Time Series:
Start = c(1991, 130)
End = c(1991, 135)
Frequency = 260
             DAX    SMI    CAC   FTSE
1991.496 1628.75 1678.1 1772.8 2443.6
1991.500 1613.63 1688.5 1750.5 2460.2
1991.504 1606.51 1678.6 1718.0 2448.2
1991.508 1621.04 1684.1 1708.1 2470.4
1991.512 1618.16 1686.6 1723.1 2484.7
1991.515 1610.61 1671.6 1714.3 2466.8

Posteriormente usamos la función across para obtener la variación de cada serie. Es importante precisar que un análisis formal requeriría un test de estacionariedad sobre las series.  

data_returns <- EuStockMarkets %>%
  as.tibble() %>%
  mutate(
    across(everything(),
           ~((./dplyr::lag(.)-1)*100)
    )) %>%
  na.omit()
 
head(data_returns)
# A tibble: 6 × 4
     DAX    SMI    CAC   F+TSE
   <dbl>  <dbl>  <dbl>  <dbl>
1 -0.928  0.620 -1.26   0.679
2 -0.441 -0.586 -1.86  -0.488
3  0.904  0.328 -0.576  0.907
4 -0.178  0.148  0.878  0.579
5 -0.467 -0.889 -0.511 -0.720
6  1.25   0.676  1.18   0.855

Ahora, guardamos en una lista el modelo GARCH(1,1) correspondiente a cada una de las columnas de mi base de datos. Cada modelo se guarda en una lista dado que permite posteriormente recuperar todos los elementos de la salida de la función garchFit.

models0 <- list()
 
for (i in 1:ncol(data_returns)){
  models0[[i]] <- garchFit( ~  garch(1, 1), trace = F, data = data_returns[,i])
}
 
El commando stargazer nos permite obtener una tabla con los coeficientes asociado a cada variable.
stargazer(models0, type="text")
===========================================================
                              Dependent variable:         
                    ---------------------------------------
                        [         [         [         [   
                       (1)       (2)       (3)       (4)  
-----------------------------------------------------------
mu                  0.070***  0.106***   0.049**  0.052***
                     (0.021)   (0.020)   (0.025)   (0.017)
                                                          
omega               0.044***  0.120***   0.081**   0.009* 
                     (0.012)   (0.024)   (0.037)   (0.005)
                                                           
alpha1              0.068***  0.127***  0.051***  0.046***
                     (0.015)   (0.024)   (0.015)   (0.012)
                                                          
beta1               0.891***  0.735***  0.882***  0.941***
                     (0.023)   (0.043)   (0.042)   (0.018)
                                                          
-----------------------------------------------------------
Observations          1,859     1,859     1,859     1,859 
Log Likelihood      2,587.920 2,412.241 2,788.477 2,136.479
Akaike Inf. Crit.     2.789     2.600     3.004     2.303 
Bayesian Inf. Crit.   2.800     2.611     3.016     2.315 
===========================================================
Note:                           *p<0.1; **p<0.05; ***p<0.01

Otra opción es recuperar la volatilidad histórica asociada a cada modelo. Para esto utilizamos la función vectorizada lapply que nos permite repetir una operación/función, para cada uno de los elementos de una lista, generando una lista de vectores de volatilidades que convertimos en una matriz a partir de la función do.call.

 vols_models <- lapply(models0, function(x) x@sigma.t)
dataVol <- data.frame(do.call(cbind, vols_models))
colnames(dataVol) <- colnames(EuStockMarkets)
 
dataVol %>%  head()
 
        DAX       SMI      CAC      FTSE
1 1.0281714 0.9246996 1.102485 0.7967414
2 1.0265176 0.8843931 1.114000 0.7901069
3 1.0004172 0.8695389 1.167243 0.7807891
4 0.9915619 0.8258928 1.141444 0.7849713
5 0.9614558 0.7884808 1.125005 0.7754941
6 0.9420005 0.8386133 1.101589 0.7760277

 A partir de estas series de volatilidades, podemos obtener una representación gráfica de las series de volatilidades:

dataVol %>%
  mutate(fecha = 1:nrow(dataVol)) %>%
  as.data.frame() %>%
  pivot_longer(!fecha, names_to = "var", values_to = "value") %>%
     ggplot(aes(x = fecha, y = value)) +
     geom_line(aes(color = var))+
     facet_wrap(~var, scales='free_y', ncol = 2) +
     theme_classic()+
  theme(legend.position = "none",
        axis.ticks = element_line(colour = "grey70", size = 0.2),
        strip.background = element_blank()) +
  scale_colour_grey(start = 0.1,end = 0.1)

Estimación del modelo HP mediante máxima verosimilitud

El filtro de Hodrick–Prescott (HP) se utiliza ampliamente para descomponer una serie macroeconómica en un componente cíclico y transitorio. ...