1. Lógica detrás de la función
La función crea una ventana móvil sobre la cual va
calculando algo (mediante una función) y posteriormente podemos obtener información
histórica sobre ese cálculo. Imaginemos que todos los días calculáramos la varianza
del precio del arroz, si lo hacemos todos los días y vamos guardando este
precio, terminaremos teniendo una serie promedio de precios del arroz. Ahora,
si tenemos información de 10 años necesitamos repetir esta operación para cada día
dentro de la muestra de datos, es aquí donde surge la importancia de esta función.
Supongamos, tenemos el vector x=(x1,x2,x3,x4,x5),
podemos obtener un promedio móvil usando una ventada de tres días. Note que la
ventana de datos móvil que va utilizando el programa va dejando una observación
detrás y tomando la observación siguiente (en caso de solo ir tomando una observación
adicional, partiendo siempre desde la primera observación, se llaman datos
recursivos). Los datos vacios pueden omitirse o quedar como NA.
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(dplyr)
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:
mean2 = function(x){
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
También
podemos realizar el cálculo a partir de x grupos no superpuesto. En otras
palabras, calcular nuestro promedio cada x
cantidad de observaciones utilizando el argumento by
dentro de la función.
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
|
media_par
<- rollapply(data = x_ej, width = 3, FUN = mean, fill=NA, align =
"right", partial = T)
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
|
obs<-length(x_ej)
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.
plot(EuStockMarkets)
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, …, )
var_dax <- rollapply(r_data0, 100, quantile, probs
= 0.01, align = "right")
plot(r_data0, type="l")
lines(var_dax)
#backtesting
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.
r_data <- data[,c(1,2)]
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.
beta_sis = function(x){
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.
beta_sis2 = function(x){
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.
#diferentes ventanas de estimation
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
DataCamp. 2022. rollapply: Apply Rolling Functions.
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.