x |
Datos móvil |
X1 |
|
X2 |
|
X3 |
x1,x2,x3 |
X4 |
x2,x3,x4 |
X5 |
x3,x4,x5 |
X6 |
x4,x5,x6 |
En R, este procedimiento se puede realizar utilizando la función rollapply, la misma segmenta las observaciones de determinados grupos de tamaño (width = 3), y posteriormente realiza el cálculo indicado en la función que se le brinda de argumento a la función.
library(lubridate)
library(zoo)
x_ej <- zoo(c(3,4,2,8,9,3))
rollapply(data = x_ej, width = 3, FUN = mean)
2 3 4 5
3.000000 4.666667 6.333333 6.666667
También podemos crear nuestras propias funciones para alimentar los procedimientos dentro de la función rollapply:
sum(x)/length(x)
}
rollapply(data = x_ej, width = 3, FUN = mean2)
2 3 4 5
3.000000 4.666667 6.333333 6.666667
Alinear los datos arriba o debajo del vector de datos sobre el cual estamos aplicando la función, además de determinar cuál valor queremos sustituir dentro de las observaciones que quedan sin datos:
media<-rollapply(data = x_ej, width = 3, FUN =
mean2, align = "right", fill=NA)
media2<-rollapply(data = x_ej, width = 3, FUN =
mean2, align = "left", fill=NA)
tabla1
<- cbind(x_ej,media,media2)
tabla1
x_ej media
media2
1 3 NA 3.000000
2 4 NA 4.666667
3 2 3.000000
6.333333
4 8 4.666667
6.666667
5 9 6.333333 NA
6 3
6.666667 NA
x
|
Datos móvil
|
X1
|
.
|
X2
|
.
|
X3
|
x1,x2,x3
|
X4
|
.
|
X5
|
.
|
X6
|
x4,x5,x6
|
media_by <- rollapply(data = x_ej, width = 3, FUN =
mean2, align = "right", fill=NA, by=3)
tabla1 <- cbind(tabla1,media_by)
tabla1
x_ej media
media2 media_by
1 3
NA 3.000000 NA
2 4
NA 4.666667 NA
3 2 3.000000 6.333333 3.000000
4 8 4.666667 6.666667 NA
5 9 6.333333 NA
NA
6 3
6.666667 NA 6.666667
Los valores NA también se pueden completar con información parcial, en este caso se usarán las ventadas disponibles para la estimación. Esto solo es recomendable en algunos procedimientos estadísticos, porque otros están influenciados en la cantidad de observaciones usadas.
x |
Datos móvil |
X1 |
x1 |
X2 |
x1,x2 |
X3 |
x1,x2,x3 |
X4 |
x2,x3,x4 |
X5 |
x3,x4,x5 |
X6 |
x4,x5,x6 |
tabla1 <- cbind(tabla1,media_par)
tabla1
x_ej media media2 media_by media_par
1 3 NA 3.000000 NA 3.000000
2 4 NA 4.666667 NA 3.500000
3 2 3.000000 6.333333 3.000000 3.000000
4 8 4.666667 6.666667 NA 4.666667
5 9 6.333333 NA NA 6.333333
6 3 6.666667 NA 6.666667 6.666667
También se puede modificar el argumento width para modificar el tamaño de la ventana a voluntad y generar ventanas recursivas, es decir, donde el tamaño de la ventana vaya creciendo con cada estimación.
x |
Datos móvil |
X1 |
x1 |
X2 |
x1,x2 |
X3 |
x1,x2,x3 |
X4 |
x1,x2,x3, x4 |
X5 |
x1,x2,x3,x4,x5 |
X6 |
x1,x2,x3,x4,x5,x6 |
mean_re <- rollapply(data = x_ej, width = 1:obs, FUN = mean, align = "right")
tabla1 <- cbind(tabla1,mean_re)
tabla1
x_ej media media2 media_by media_par mean_re
1 3 NA 3.000000 NA 3.000000 3.000000
2 4 NA 4.666667 NA 3.500000 3.500000
3 2 3.000000 6.333333 3.000000 3.000000 3.000000
4 8 4.666667 6.666667 NA 4.666667 4.250000
5 9 6.333333 NA NA 6.333333 5.200000
6 3 6.666667 NA 6.666667 6.666667 4.833333
2. Aplicaciones de la función rollapply a la econometría financiera
2.1. Ventana de volatilidad (ventana móvil)
Usamos la data EuStockMarkets para estos ejemplos. El primero calcula las tasas de variación para estas series (recuerde siempre trabajar con series estacionarias) para posteriormente estimar la volatilidad de la misma en una ventana de datos de 100 días. Es un proceso muy utilizado en la gestión del riesgo para analizar la volatilidad condicional.
data <- EuStockMarkets %>%
data.frame() %>%
mutate(across(is.numeric, ~((./dplyr::lag(.)-1)*100))) %>%
na.omit()
r_data0 <- data[,"DAX"]
vol_t <- rollapply(r_data0, width=100, FUN=sd)
plot(vol_t, type="l")
2.2. Ventana
de volatilidad (ventana recursiva)
***
2.3. Calcular el VaR histórico de un activo
Aquí también podemos obtener la evolución del VaR de determinada serie financiera. Se muestra además la flexibilidad de la función al permitirnos colocar dos argumentos a la vez.
rollapply(data, width, FUN, …, )
plot(r_data0, type="l")
lines(var_dax)
mean(r_data0<var_dax)
[1] 0.01667563
2.4. Correlación histórica entre activos
La función no solo permite incluir más de un argumento de una función, sino que facilita el trabajo con más de una variable. Aquí se muestra como trabajar con varias columnas. Este es necesario cuando quisiéramos ver cuestiones como la evolución histórica de la correlación entre dos series y como vimos anteriormente, cuando necesitamos incluir funciones propias para reservar los datos que vamos obteniendo. Esta función la podemos crear fuera o colocar dentro de la misma función.
corr_t <- rollapply(r_data, width=100, function(x) cor(x[,1],x[,2]), by.column=FALSE)
plot(corr_t, type="l")
2.5. Obtener
el beta histórico de una cartera
Sumamente útil para descomponer el riesgo de un activo e identificar el componente sistémico de su volatilidad, además de identificar fuentes de riesgo y la sensibilidad de la serie a factores puntuales de riesgo. El procedimiento consiste en guardar el coeficiente de regresión de un modelo factorial sencillo, pero note que modificando la función podemos obtener modelos factoriales con mayor cantidad de factores de riesgo.
lm(x[,2] ~ x[,1])[[1]][[2]]
}
Beta <- rollapply(r_data, width=100, by.column = F, beta_sis)
plot(Beta, type="l")
Verifique que se usa el argumento by.column, cuyo valor por default es TRUE, esto para evitar que la función se aplique a cada una de las columnas con las que estamos trabajando. En los casos anteriores, como solo teníamos un vector como argumento de datos, no era necesario preocuparnos por este argumento de la función.
Note que esta función la podemos modificar para obtener más de un resultado de la función con la que estamos interesados. Por ejemplo, podemos estar enterados en recuperar el intercepto y la pendiente del modelo de regresión, o adicionalmente recuperar el R2.
lmr <-lm(x[,2] ~ x[,1])
c(beta=coef(lmr)[[2]], r2=summary(lmr)$r.squared)
}
Beta_r2 <- rollapply(r_data, width=100, by.column = F, beta_sis2)
par(mfrow=c(2,1))
plot(Beta_r2[,1], type="l")
plot(Beta_r2[,2], type="l")
Una alternativa mostrada en data.camp es:
FUN = function(z) coef(lm(y ~ y1 + y12, data = as.data.frame(z))
3. Condiciones de la estimación
3.1. Tamaño
de la ventana
Note que no es trivial elegir el tamaño de la ventana. Pues la sensibilidad al contexto, o inclusive la dinámica de la serie puede cambiar de forma significativa en función del tamaño de la ventana seleccionada.
vol_t <- rollapply(r_data0, width=100, FUN=sd,align = "right", fill=NA)
vol_t500 <- rollapply(r_data0, width=500, FUN=sd,align = "right", fill=NA)
vol_t1000 <- rollapply(r_data0, width=1000, FUN=sd, align = "right", fill=NA)
plot(vol_t, type="l")
lines(vol_t500)
lines(vol_t1000)
3.2. Ventana
recursiva vs. ventana móvil
4. Referencias
Dumitrescu, E.; Hurlin, C.; Pham., V. Backtesting Value-at-Risk: From Dynamic Quantile to Dynamic Binary Tests.
Grothendieck, K. (2020). Rollapply for backtesting the value at risk. stackoverflow.
Grothendieck, K. (2021). Using Rollapply to return both the Coefficient and RSquare. stackoverflow.
Kleiber, C. (2017). Applied Econometrics whith R.
Simaan, M. (2018). Tip of the Month: rollapply.
Wickham., H. (2021). Advanced R. Functionals.