Analizando los retornos de una acción en R
Intro
En este tutorial vamos a cubrir lo siguiente:
Cómo calcular retornos diarios de una acción
Cómo analizar visualmente los retornos diarios de una acción
Cómo calcular y visualizar retornos en otros periodos
1 Retornos de una acción
El retorno de una acción es la ganancia o pérdida de valor porcentual durante un periodo específico. Existen 2 maneras de calcular este retorno: el retorno aritmético (también llamado discreto) y el retorno logarítimco (también llamado continuo).
El retorno aritmético se calcula de la siguiente manera:
valor_final / valor_inicial - 1
e.g. $105 / $100 - 1 = 5.00% de retorno
El retorno logarítmico se calcula de la siguiente manera:
log(valor_final / valor inicial)
e.g. log($105 / $100) = 4.88% de retorno
Para variaciones pequeñas, el retorno aritmético es prácticamente igual que el logarítmico, pero a manera que crece este retorno también crece la diferencia entre ambas maneras de calcularlos.
Los retornos logarítmicos son muy usados en aplicaciones académicas por que permiten simplificar un poco el análisis (principalmente porque son aditivos a través del tiempo). Sin embargo, seguramente estás más familiarizado con retornos aritméticos así que en este tutorial usaremos estos para nuestro análisis.
1.1 Cálculo de retornos aritméticos diarios
Para este tutorial, analizaré las características de riesgo y retorno de la acción de CEMEX para los últimos 10 años. En Yahoo Finance, el ticker de CEMEX es CEMEXCPO.MX:
Así que para cargar los precios usaremos los siguientes comandos en R:
library(quantmod)
getSymbols("CEMEXCPO.MX", from = "2011-10-15")
Verán la siguiente advertencia en su consola:
Lo que quantmod nos está advirtiendo es que hay valores que faltan en nuestra serie de tiempo. Primero, extraigamos sólo la columna de precios ajustados de CEMEX y guardémoslos en la variable cemex y después veamos para que fechas faltan datos con los siguientes comandos:
cemex <- Ad(CEMEXCPO.MX)
which(is.na(cemex))
Y podemos ver que el elemento 296 es el culpable. Pero, ¿qué elemento es este? Usemos el siguiente comando para ver la fecha exacta de la que estamos hablando:
index(cemex)[which(is.na(cemex))]
La fecha es: “2012-12-24”, Navidad del 2012. Es esperado que para esta fecha no haya datos puesto que es un día festivo. Así que lo único que tenemos que hacer es deshacernos de esta observación para evitar problemas en el futuro con el siguiente comando:
cemex <- na.omit(cemex)
Pueden verificar que ahora ya no hay datos faltantes en nuestra serie de tiempo y podemos continuar.
1.1.1 Usando nuestra propia función
Vamos a utilizar esta oportunidad para practicar crear nuestras propias funciones en R. Para calcular retornos aritméticos tenemos que hacer la siguiente operación:
r(t) = precio(t) / precio(t - 1) - 1
para todo t en el periodo t = 2 .. n
donde n es el número total de observaciones
y r(t) = NA para t = 1
Para esto podemos usar la siguiente función:
retornos_aritmeticos <- function(time_series) {
return(time_series / lag(time_series, k = 1) - 1)
}
Lo único que estamos haciendo es dividir nuestra serie de tiempo entre la misma serie de tiempo desfasada 1 lugar usando lag( ) (recuerda usar “?<función>” si quieres leer más sobre como usar alguna función en específico). El resultado de nuestra función es el siguiente:
Podemos comprobar que, efectivamente, 3.728543 / 3.451213 - 1 = 0.080357. Así que nuestro cálculo está correcto y concluímos que el 18 de octubre de 2011 la acción de CEMEX tuvo un retorno de 8.04%.
1.1.2 Usando quantmod
Todo lo anterior no es necesario si ya estamos usando el paquete quantmod. Podemos usar la función dailyReturn( ) y calcular estos retornos con el siguiente comando:
cemex_returns <- dailyReturn(cemex, leading = FALSE)
Y podemos verificar que es igual a los retornos que calculamos con nuestra función:
Otra manera de comprobar es usando el siguiente comando:
(sum(na.omit(cemex_returns == retornos_aritmeticos(cemex))) / (length(cemex_returns) - 1)) * 100
Este comando nos dice que porcentaje de nuestros retornos calculados son exactamente iguales a los de la función de quantmod, y te puedes dar cuenta que son el 100%. Analiza con detenimiento la línea y trata de encontrar una manera alternativa de medir lo mismo.
1.2 Analizando retornos diarios
Ahora que ya calculamos los retornos de la acción, podemos empezar a analizarlos. Lo más importante que queremos determinar es la distribución de estos retornos para saber si pudiéramos predecirlos en el futuro (esto lo veremos en un tutorial posterior). Comparemos la gráfica de precios y la de retornos:
par(mfrow = c(1,2))
plot(cemex, main = "Precios")
plot(cemex_returns, main = "Retornos")
La primer línea del comando anterior, par(mfrow = c(1, 2)), me permite crear una ventana de 1 renglón y 2 columnas para poder graficar dos variables una al lado de la otra. Los siguientes 2 comandos plot( ) que haga serán la primera y segunda gráfica en mi ventana, respectivamente.
Podemos ver que los precios de la acción no son una serie de tiempo estacionaria, puesto que tienen tendencia y varianza variables a lo largo del tiempo. La serie de tiempo de retornos, por otra parte, parece tener medias y varianza más estables a través del tiempo, por lo que sería más factible predecir su movimiento futuro. Todavía no podemos concluir nada a ciencia cierta, así que sigamos analizando los retornos.
Tenemos 4 herramientas principales para analizar gráficamente estos retornos:
Histogramas: nos permiten analizar la distribución de los datos
Diagramas de caja: nos permite identificar valores atípicos
Gráficas de autocorrelación: nos ayuda para identificar patrones repetitivos
Gráficas Q-Q: nos ayuda a determinar si la muestra que tenemos se asemeja a una distribución normal
Podemos generar todas estas 4 gráficas en la misma ventana usando el comando que vimos anteriormente:
cemex_returns <- na.omit(cemex_returns)
par(mfrow = c(2, 2))
hist(cemex_returns, probability = TRUE, ylim = c(0, 25))
lines(density(cemex_returns), col = "red")
boxplot(cemex_returns, main = "Boxplot of cemex_returns")
acf(cemex_returns)
qqnorm(cemex_returns)
qqline(cemex_returns, col = "red")
Del histograma y la función de densidad podemos ver que hay skewness positivo en nuestra muestra. Por la amplitud de las colas de nuestra distribución podemos suponer que también existe exceso de curtosis en nuestra muestra. Nuestra gráfica de caja muestra una gran cantidad de valores atípicos, tanto positivos como negativos aunque tienden más a ser positivos. Nuestra gráfica de autocorrelación no muestra ninguna relación significativa, al menos con los primeros 30 valores inmediatos anteriores. Por último, la gráfica Q-Q nos confirma que nuestra muestra está muy distante de ser similar a una distribución normal.
En tutoriales posteriores vamos a ver cómo utilizar esta información para definir que modelo predictivo pudieramos utilizar y cómo implementarlo en R.
1.3 Cálculo y visualización de retornos anuales
Vamos a hacer un pequeño intermedio antes de continuar y aprovechar para crear algunas gráficas en R. Ahora queremos saber cuáles han sido los retornos anuales de CEMEX y presentarlos en una gráfica. El retorno del 2011 lo vamos a ignorar puesto que nuestra serie de tiempo empieza en octubre de ese año y no sería relevante comparar ese periodo de 2 meses y medio cuando el resto serán de todo el año. El del 2021 sí lo vamos a incluir aunque el año no haya concluído para ver como vamos hasta ahora. Este periodo tiene un nombre especial en finanzas: YTD (siglas de year to date).
Para calcular retornos anuales, usaremos la siguiente función de quantmod:
cemex_ann_returns <- annualReturn(cemex, leading = FALSE)
Y podemos visualizarlos en una gráfica de barras:
barplot(cemex_ann_returns)
Está bien… pero no me convence del todo. Empecemos por quitar el primer retorno que decidimos ignorar y ponerle un título a nuestra gráfica:
barplot(na.omit(cemex_ann_returns), main = “Retornos anuales de CEMEX”)
Un poco mejor, pero sigue sin parecer suficiente. Pongamos los valores encima de cada barra:
plt <- barplot(na.omit(cemex_ann_returns), main = "Retornos anuales de CEMEX")
text(x = plt, y = na.omit(cemex_ann_returns) + .05, labels = as.character(round(na.omit(cemex_ann_returns), 2)))
Ya casi tenemos una gráfica decente. Ahora sólo tenemos que ajustar nuestros ejes por que dos años no muestran su valor en la gráfica (2012 y 2016) y los años de retorno negativo se empalmó el valor con la gráfica. Usemos mejor los siguientes comandos:
plotted_data <- na.omit(cemex_ann_returns)
plt <- barplot(plotted_data, main = "Retornos anuales de CEMEX", ylim = c(-.5, 1))
text(x = plt,
y = ifelse(plotted_data < 0, plotted_data - .05, plotted_data + .05),
labels = as.character(round(plotted_data, 2)))
Esto ya se ve mucho mejor. Si prefieres que los números estén todos en el eje x, puedes hacer lo siguiente:
plotted_data <- na.omit(cemex_ann_returns)
plt <- barplot(plotted_data, main = "Retornos anuales de CEMEX", ylim = c(-.5, 1))
text(x = plt,
y = ifelse(plotted_data < 0, .05, -.05),
labels = as.character(round(plotted_data, 2)))
Modifícala ahora tú cómo prefieras. Puedes ponerle nombres a los ejes, ponerle un subtítulo a la gráfica, cambiar el color de las barras, etc.
Esto es todo por hoy. Ahora tienen herramientas para visualizar y calcular los retornos de una acción en R. En el siguiente tutorial les mostraré cómo calcular métricas de riesgo como varianza, desviación estandar y beta. Hasta el próximo tutorial!