Médias móviles

En el análisis de series temporales, el método de medias móviles tiene diversas aplicaciones: así, este método puede sernos útil si queremos calcular la tendencia de una serie temporal sin tener que ajustarnos a una función previa, ofreciendo así una visión suavizada o alisada de una serie, ya que promediando varios valores se elimina parte de los movimientos irregulares de la serie; también puede servirnos para realizar predicciones cuando la tendencia de la serie tiene una media constante.

Veamos qué es una media móvil: se trata, sencillamente de una media aritmética que se caracteriza porque toma un valor para cada momento del tiempo y porque en su cálculo no entran todas las observaciones de la muestra disponible.

Entre los distintos tipos de medias móviles que se pueden construir nos vamos a referir a dos tipos: medias móviles centradas y medias móviles asimétricas. El primer tipo se utiliza para la representación de la tendencia, mientras que el segundo lo aplicaremos para la predicción en modelos con media constante.

Las medias móviles centradas se caracterizan porque el número de observaciones que entran en su cálculo es impar, asignándose cada media móvil a la observación central. Así, una media móvil centrada en \(t\) de longitud \(2n+1\) viene dada por la siguiente expresión:

\[MM(2n+1)_t=\frac{Y_{t-n}+Y_{t-n+1}+\cdots+Y_{t}+Y_{t+n-1}+Y_{t+n}}{2n+1}\]

Como puede observarse, el subíndice asignado a la media móvil, \(t\), es el mismo que el de la observación central,\(Y_t\). Obsérvese también que, por construcción, no se pueden calcular las medias móviles correspondientes a las \(n\) primeras y a las \(n\) últimas observaciones.

Ejemplo

Para el ejemplo vamos a tomar 31 obervaciones de las acciones de Apple entre los días 2021-07-01 y 2021-07-31.

library(tidyquant)
library(TTR)
library(ggplot2)
library(knitr)
AAPL <- tq_get("AAPL", get="stock.prices", from= "2021-07-01", to= "2021-07-31") 
AAPL <- data.frame(AAPL) 
a<-mean(AAPL$close)
sma20 <- SMA(AAPL[c('close')], n=10) 

fecha20<- as.Date(AAPL$date)
precio<-AAPL$close
data<-data.frame(fecha20,precio,sma20)
dataprecio<-data.frame(fecha20,precio)
colnames(dataprecio)<-c("Fecha","Precio de cierre")
#ggplot(data = data,
#       aes(fecha20,y = precio)) +
#  geom_line(color='darkblue')+
#  ggtitle('Precio de una acción') +
#  xlab('Fecha') + 
#  ylab('Precio cierre') 
kable(dataprecio)
Fecha Precio de cierre
2021-07-01 137.27
2021-07-02 139.96
2021-07-06 142.02
2021-07-07 144.57
2021-07-08 143.24
2021-07-09 145.11
2021-07-12 144.50
2021-07-13 145.64
2021-07-14 149.15
2021-07-15 148.48
2021-07-16 146.39
2021-07-19 142.45
2021-07-20 146.15
2021-07-21 145.40
2021-07-22 146.80
2021-07-23 148.56
2021-07-26 148.99
2021-07-27 146.77
2021-07-28 144.98
2021-07-29 145.64
2021-07-30 145.86

vamos a encontrar la media movil centrada, para ello usamos la libreria TTR y con la función SMA

library(vars)

sma20 <- SMA(AAPL[c('close')], n=5) 
dataprecio<-data.frame(fecha20,precio,sma20)
colnames(dataprecio)<-c("Fecha","Precio de cierre","Media Móvil Centrada")
kable(dataprecio)
Fecha Precio de cierre Media Móvil Centrada
2021-07-01 137.27 NA
2021-07-02 139.96 NA
2021-07-06 142.02 NA
2021-07-07 144.57 NA
2021-07-08 143.24 141.412
2021-07-09 145.11 142.980
2021-07-12 144.50 143.888
2021-07-13 145.64 144.612
2021-07-14 149.15 145.528
2021-07-15 148.48 146.576
2021-07-16 146.39 146.832
2021-07-19 142.45 146.422
2021-07-20 146.15 146.524
2021-07-21 145.40 145.774
2021-07-22 146.80 145.438
2021-07-23 148.56 145.872
2021-07-26 148.99 147.180
2021-07-27 146.77 147.304
2021-07-28 144.98 147.220
2021-07-29 145.64 146.988
2021-07-30 145.86 146.448

En un gráfico veremos los datos de mejor manera

library(vars)

ggplot(dataprecio,aes(fecha20,y = precio))+
  geom_line(color="darkblue")+
  geom_line(data = dataprecio,
       aes(fecha20,y = sma20), color='red')+ 
  ggtitle('Precio  de la acción de Apple') +
  xlab('Fecha') + 
  ylab('Precio')

De igual manera podemos hacerlo con los rendimientos de la acción de Apple, esto es

fecha2<-dataprecio$Fecha[2:21]
precio2<-dataprecio$`Precio de cierre`
n<-length(precio2)
rendimiento<-c()
for (i in 1:n) {
  rendimiento[i]<-(precio[i+1]-precio[i])/(precio[i])
}
rendimiento<-na.omit(rendimiento)
smarend <- SMA(rendimiento, n=5) 
dataprend<-data.frame(fecha2,rendimiento,smarend)
colnames(dataprend)<-c("Fecha","Rendimiento","Media Móvil")
kable(dataprend)
Fecha Rendimiento Media Móvil
2021-07-02 0.0195964 NA
2021-07-06 0.0147185 NA
2021-07-07 0.0179552 NA
2021-07-08 -0.0091997 NA
2021-07-09 0.0130550 0.0112251
2021-07-12 -0.0042037 0.0064651
2021-07-13 0.0078893 0.0050992
2021-07-14 0.0241005 0.0063283
2021-07-15 -0.0044921 0.0072698
2021-07-16 -0.0140760 0.0018436
2021-07-19 -0.0269144 -0.0026985
2021-07-20 0.0259740 0.0009184
2021-07-21 -0.0051317 -0.0049280
2021-07-22 0.0096287 -0.0021039
2021-07-23 0.0119891 0.0031091
2021-07-26 0.0028945 0.0090709
2021-07-27 -0.0149003 0.0008960
2021-07-28 -0.0121960 -0.0005168
2021-07-29 0.0045524 -0.0015321
2021-07-30 0.0015106 -0.0036278

En un gráfico veremos los datos de mejor manera

ggplot(dataprend,aes(fecha2,y = rendimiento))+
  geom_line(color="darkblue")+
  geom_line(data = dataprend,
       aes(fecha2,y = smarend), color='red')+
  ggtitle('Rendimiento de la acción de Apple') +
  xlab('Fecha') + 
  ylab('Precio')

Alisado Exponencial Simple

El método del alisado exponencial simple consiste, al igual que en el caso de las medias móviles, en una transformación de la variable original. Si una variable \(Y_t\) es sometida a un proceso de alisado exponencial simple se obtiene como resultado la variable alisada \(S_t\). Teóricamente, la variable alisada\(S_t\) se obtendría según la expresión:

\[S_t=(1-w)Y_t+(1-w)wY_{t-1}+(1-w)w^2Y_{t-2}+\cdots\]

donde \(w\) es un parámetro que toma valores comprendidos entre 0 y 1, y los puntos suspensivos indican que el número de términos de la variable alisada puede ser infinito. La expresión anterior en realidad no es más que una media aritmética ponderada de infinitos valores de \(Y\).

Se denomina alisada ya que suaviza o alisa las oscilaciones que tiene la serie, al obtenerse como una media ponderada de distintos valores. Por otra parte, el calificativo de exponencial se debe a que la ponderación o peso de las observaciones decrece exponencialmente a medida que nos alejamos del momento actual \(t\). Esto quiere decir que las observaciones que están alejadas tienen muy poca incidencia en el valor que toma \(S_t\). Finalmente, el calificativo de simple se aplica para distinguirla de otros casos en que, como veremos más adelante, una variable se somete a una doble operación de alisado.

Una vez que se han visto estos aspectos conceptuales, vamos a proceder a la obtención operativa de la variable alisada, ya que la expresión no es directamente aplicable por contener infinitos términos. Retardando un período en la expresión anterior se tiene que:

\[S_{t-1}=(1-w)Y_{t-1}+(1-w)wY_{t-2}+(1-w)w^2Y_{t-3}+\cdots\]

Multiplicando ambos miembros por \(w\) se obtiene:

\[wS_{t-1}=(1-w)wY_{t-1}+(1-w)w^2Y_{t-2}+(1-w)w^3Y_{t-3}+\cdots\]

Restando \(S_t\) de \(wS_{t-1}\) miembro a miembro y ordenando los términos se tiene que:

\[S_t=\alpha Y_t+(1-\alpha)S_{t-1}\]

donde \(\alpha=1-w\).

Ahora ya sólo nos falta calcular los valores de \(\alpha\) y \(S_0\), parámetros a partir de los cuales resulta sencillo hallar los valores de la variable alisada de manera recursiva, tal que:

\[\begin{align*} S_1&=\alpha Y_1+(1-\alpha)S_0\\ S_2&=\alpha Y_2+(1-\alpha)S_1\\ S_3&=\alpha Y_3+(1-\alpha)S_2\\ & \vdots \end{align*}\]

Al asignar un valor a \(\alpha\) hay que tener en cuenta que un valor pequeño de \(\alpha\) significa que estamos dando mucho peso a las observaciones pasadas a través del término \(S_{t-1}\). Por el contrario, cuando \(\alpha\) es grande se da más importancia a la observación actual de la variable \(Y\). En general, parece que un valor de \(\alpha=0.2\) es apropiado en la mayor parte de los casos. Alternativamente, se puede seleccionar aquel valor de \(\alpha\) para el que se obtenga una Raíz del Error Cuadrático Medio menor en la predicción del período muestral.

Respecto a la asignación de valor a \(S_0\) , se suelen hacer estos supuestos: cuando la serie tiene muchas oscilaciones se toma \(S_0=Y_1\) ; por el contrario, cuando la serie tiene una cierta estabilidad, se hace \(S=\overline{Y}\).

Ejemplo

Tomemos los rendimientos de la acción de Apple como la serie que deseamos suavizar exponencialmente

Y<-na.omit(rendimiento)
ggplot(dataprend,aes(fecha2,y = rendimiento))+
  geom_line(color="darkblue")+
  ggtitle('Rendimiento de la acción de Apple') +
  xlab('Fecha') + 
  ylab('Precio')

como observamos, es una serie que presenta varias occilaciones, entonces tomemos un \(\alpha=0.2\) y \(S=\overline{Y}\)

alpha1<-0.2
S0<-mean(Y)

y construyamos \(S_t=\alpha Y_t+(1-\alpha)S_{t-1}\)

S1<-alpha1*Y[1]+(1-alpha1)*S0
S2<-alpha1*Y[2]+(1-alpha1)*S1
S3<-alpha1*Y[3]+(1-alpha1)*S2
S4<-alpha1*Y[4]+(1-alpha1)*S3

vamos a realizar para todos los datos que tiene el rendimiento

fechaS<-fecha20[2:21]
S0<-mean(Y)
Sv<-c()
S<-rbind(S0,Sv)
m<-length(Y)
for (i in 1:m) {
  S[i+1]<-alpha1* Y[i+1]+(1-alpha1)*S[i]
}
S<-na.omit(S)
dataS<-data.frame(fechaS,rendimiento,S)
colnames(dataS)<-c("Fecha","Rendimiento ","Valores S")
kable(dataS)
Fecha Rendimiento Valores S
2021-07-02 0.0195964 0.0031375
2021-07-06 0.0147185 0.0054537
2021-07-07 0.0179552 0.0079540
2021-07-08 -0.0091997 0.0045233
2021-07-09 0.0130550 0.0062296
2021-07-12 -0.0042037 0.0041429
2021-07-13 0.0078893 0.0048922
2021-07-14 0.0241005 0.0087339
2021-07-15 -0.0044921 0.0060887
2021-07-16 -0.0140760 0.0020557
2021-07-19 -0.0269144 -0.0037383
2021-07-20 0.0259740 0.0022042
2021-07-21 -0.0051317 0.0007370
2021-07-22 0.0096287 0.0025153
2021-07-23 0.0119891 0.0044101
2021-07-26 0.0028945 0.0041070
2021-07-27 -0.0149003 0.0003055
2021-07-28 -0.0121960 -0.0021948
2021-07-29 0.0045524 -0.0008454
2021-07-30 0.0015106 -0.0003742

ahora veamos en un gráfico

ggplot(dataS,aes(fechaS,y = rendimiento))+
  geom_line(color="darkblue")+
  geom_line(aes(fechaS,y = S),color="darkred")+
  ggtitle('Rendimiento de la acción de Apple') +
  xlab('Fecha') + 
  ylab('Precio')