En esta ocasión vamos a trabajar con unos de los tipos de gráficos más interesantes y más conocidos en la macroeconomía, las finanzas y el trading: Los gráfico de series de tiempo. Estos son esencialmente útiles cuando queremos graficar valores, variaciones, rezagos, etc, durante ciertos periodos de tiempo, los cuales generalmente son bastante amplios ya que se quiere tener una perspectiva sobre lo que estamos graficando en cuestión. Se que esta será una de tus entradas favoritas, ya que no solo veremos una gran cantidad de gráficos y paquetes, si no que también veremos formas muy diversas de personalizarlos. ¡Comencemos!
Antes de iniciar con el primer tipo de gráfico, es importante señalar que para este caso necesitamos datos de series de tiempo, como la cotización de una acción, el PIB, etc. La mayoría de las bases de datos que tenemos por default en R no nos sirven, por lo que en este caso vamos a obtener datos de Yahoo Finance con la librería quantmod
. En entradas futuras profundizaré sobre la obtención de datos con paquetes como ese o mediante el uso de API Keys, pero por el momento me importa más que aprendas cómo graficar los para series de tiempo.
Primero que nada, cargaré los paquetes que usaré para esta entrada:
library(quantmod)
library(dplyr)
library(ggplot2)
library(dygraphs)
library(modeltime)
library(scales)
library(echarts4r)
library(viridis)
Este es el gráfico más común y recurrente cuando nos referimos a series de tiempo, ya que nos muestra la evolución de una serie de datos a lo largo de múltiples periodos. La forma más sencilla de hacerlo es mediante un ggplot, pero primero vamos a obtener los datos. Trabajaremos con el índice S&P 500, el índice NASDAQ y el índice Dow Jones. Para obtener la información de los precios al cierre, que son los que nos interesan, iremos a la página de Yahoo Finance y buscaremos el índice que nos interesa, después solo debemos copiar la clave que se encuentra entre paréntesis junto al nombre, es decir, la que se encuentra marcada a continuación:
Bien, ya que copiamos la clave solamente debemos usar la siguiente función para obtener los índices:
# Obteniendo datos de Yahoo Finance
getSymbols(Symbols = c("^GSPC", "^IXIC", "^DJI"),
src = "yahoo",
index.class = "POSIXct",
from = "2012-01-01",
to = Sys.Date())
## [1] "^GSPC" "^IXIC" "^DJI"
Nótese que utilicé la función Sys.Date()
para que me de la fecha actual que esté registrada en mi computadora.
Ahora, el objeto que nos devuelve la función getSymbols()
es una matriz, por lo que las fechas no tienen un título y no se pueden usar para graficar los datos, por lo que vamos a convertir cada índice en un data frame y agregar el vector de fechas de la siguiente manera:
# Para el S&P 500
SP500 <- as.data.frame(GSPC)
SP500$date <- time(GSPC)
# Para el NASDAQ
NASDAQ <- as.data.frame(IXIC)
NASDAQ$date <- time(IXIC)
# Para el Dow Jones
DJones <- as.data.frame(DJI)
DJones$date <- time(DJI)
Bien, ahora ya tenemos la información que necesitamos y podemos trabajar con ella para hacer gráficos de series de tiempo. Todos los datos tienen la misma estructura, por lo que podemos visualizar uno de ellos para que puedas ver lo que estaré trabajando a continuación:
# Visualizando índice S&P 500
head(SP500)
## GSPC.Open GSPC.High GSPC.Low GSPC.Close GSPC.Volume GSPC.Adjusted
## 2012-01-03 1258.86 1284.62 1258.86 1277.06 3943710000 1277.06
## 2012-01-04 1277.03 1278.73 1268.10 1277.30 3592580000 1277.30
## 2012-01-05 1277.30 1283.05 1265.26 1281.06 4315950000 1281.06
## 2012-01-06 1280.93 1281.84 1273.34 1277.81 3656830000 1277.81
## 2012-01-09 1277.83 1281.99 1274.55 1280.70 3371600000 1280.70
## 2012-01-10 1280.77 1296.46 1280.77 1292.08 4221960000 1292.08
## date
## 2012-01-03 2012-01-03
## 2012-01-04 2012-01-04
## 2012-01-05 2012-01-05
## 2012-01-06 2012-01-06
## 2012-01-09 2012-01-09
## 2012-01-10 2012-01-10
Este es el gráfico más sencillo que podemos hacer para representar una serie de tiempo, ya que nos está indicando la evolución que ha tenido un indicador a los largo de un cierto periodo. Para éstos gráficos es recomendable poner anotaciones en aquellos datos atípicos que podamos encontrar, para entender mejor la evolución que ha tenido el indicador en cuestión.
Vamos a graficar el índice S&P 500 para ver su evolución a lo largo del tiempo:
SP500 %>%
e_charts(date) %>%
e_line(GSPC.Close, name = "Precio al cierre") %>%
e_theme("chalk") %>%
e_color("red") %>%
e_tooltip(trigger = "axis") %>%
e_title("Índice S&P 500 (histórico)") %>%
e_axis_labels(x = "Fecha", y = "Precio")
De igual forma podríamos hacer el gráfico con ggplot2
, obteniendo algo bastante similar, aunque el código es un poco más largo. Vamos a ello:
SP500 %>%
ggplot( aes( x = date, y = GSPC.Close) ) +
geom_line(size = 0.5, color = "Darkblue") +
theme_bw() +
theme(legend.position = "none") +
theme(legend.title = element_blank()) +
guides(col = guide_legend(nrow = 1, byrow = TRUE)) +
xlab("Periodo") +
ylab("Precio al cierre")+
theme(plot.title = element_text(size = 11, face = "bold", hjust = 0)) +
theme(plot.subtitle = element_text(size = 10, hjust = 0)) +
theme(plot.caption = element_text(size = 10, hjust = 0)) +
theme(plot.margin = unit(c(1,1,1,1), "cm")) +
labs(
title = "Índice S&P 500 (histórico).",
subtitle = "Cifras en dólares",
caption = "Fuente: Elaboración propia con datos de Yahoo Finance \nNotas: Espero que te ayude este ejercicio."
) +
# Finalmente, agregamos comas a los precios
scale_y_continuous(labels = comma)
Es recomendable agregar comas a los precios cuando tenemos valores muy grandes, ya que así se hacen más agradables a la lectura. Para hacer eso en ggplot2
tenemos que usar la función scale_y_continuous(labels = comma)
del paquete scales
.
Ahora, si trabajas con macroeconomía es posible que utilices éstos gráficos para presentarlos, por lo que podría darle un formato al estilo Bloomberg. Vamos a utilizar la paleta de colores del paquete viridis
, ya que nos dará una mejor visualización de los datos para aquellos picos en los precios, además de incluir un fondo negro, un cuadriculado punteado y otra fuente. Vamos a ello:
# gráfico al estilo bloomberg
SP500 %>%
ggplot( aes(x=date, y=GSPC.Close, colour=GSPC.Close)) + geom_line(size = 0.4) +
scale_color_viridis() +
ggtitle("Índice S&P 500 (histórico)") +
labs(subtitle = "Cifras en dólares",
caption = "Jorge Hernández | Espero que te sirva este ejercicio") +
xlab("Fecha") +
ylab("Precio") +
# Para cambiar a color negro el fondo
theme(legend.position = 'None',
plot.background = element_rect(fill = "#000000", color = NA),
panel.background = element_rect(fill = "#000000"),
# Para cambiar el color de la letra
title = element_text(color = "#abc1d3", face = "bold"),
# Para puntear la cuadrícula del fondo
panel.grid.major.x = element_line(size = 0.3,
linetype = 'dashed',
colour = "#3f4d58"),
panel.grid.minor.x = element_line(size = 0.3,
linetype = 'dashed',
colour = "#3f4d58"),
panel.grid.major.y = element_line(size = 0.3,
linetype = 'dashed',
colour = "#3f4d58"),
panel.grid.minor.y = element_line(size = 0.3,
linetype = 'dashed',
colour = "#3f4d58"),
# Para cambiar la fuente de las letras del titulo, ejes y pie de página
axis.title.y = element_text(color = "#ffffff", face = "bold", family = "mono"),
axis.title.x = element_text(color = "#ffffff", face = "bold", family = "mono"),
axis.text.x = element_text(color = "#ffffff", family = "mono"),
axis.text.y = element_text(color = "#ffffff", family = "mono"),
plot.margin=unit(c(1,1,1,1),"cm")) +
scale_y_continuous(labels = comma)
Ahora, vamos a hacer lo mismo para los otros dos índices, tal que:
# gráfico de Dow Jones
DJones %>%
ggplot( aes(x=date, y=DJI.Close, colour=DJI.Close)) + geom_line(size = 0.4) +
scale_color_viridis() +
ggtitle("Índice Dow Jones (histórico)") +
labs(subtitle = "Cifras en dólares",
caption = "Jorge Hernández | Espero que te sirva este ejercicio") +
xlab("Fecha") +
ylab("Precio") +
# Para cambiar a color negro el fondo
theme(legend.position = 'None',
plot.background = element_rect(fill = "#000000", color = NA),
panel.background = element_rect(fill = "#000000"),
# Para cambiar el color de la letra
title = element_text(color = "#abc1d3", face = "bold"),
# Para puntear la cuadrícula del fondo
panel.grid.major.x = element_line(size = 0.3,
linetype = 'dashed',
colour = "#3f4d58"),
panel.grid.minor.x = element_line(size = 0.3,
linetype = 'dashed',
colour = "#3f4d58"),
panel.grid.major.y = element_line(size = 0.3,
linetype = 'dashed',
colour = "#3f4d58"),
panel.grid.minor.y = element_line(size = 0.3,
linetype = 'dashed',
colour = "#3f4d58"),
# Para cambiar la fuente de las letras del titulo, ejes y pie de página
axis.title.y = element_text(color = "#ffffff", face = "bold", family = "mono"),
axis.title.x = element_text(color = "#ffffff", face = "bold", family = "mono"),
axis.text.x = element_text(color = "#ffffff", family = "mono"),
axis.text.y = element_text(color = "#ffffff", family = "mono"),
plot.margin=unit(c(1,1,1,1),"cm")) +
scale_y_continuous(labels = comma)
# gráfico del NASDAQ
NASDAQ %>%
ggplot( aes(x=date, y=IXIC.Close, colour=IXIC.Close)) + geom_line(size = 0.4) +
scale_color_viridis() +
ggtitle("Índice NASDAQ (histórico)") +
labs(subtitle = "Cifras en dólares",
caption = "Jorge Hernández | Espero que te sirva este ejercicio") +
xlab("Fecha") +
ylab("Precio") +
# Para cambiar a color negro el fondo
theme(legend.position = 'None',
plot.background = element_rect(fill = "#000000", color = NA),
panel.background = element_rect(fill = "#000000"),
# Para cambiar el color de la letra
title = element_text(color = "#abc1d3", face = "bold"),
# Para puntear la cuadrícula del fondo
panel.grid.major.x = element_line(size = 0.3,
linetype = 'dashed',
colour = "#3f4d58"),
panel.grid.minor.x = element_line(size = 0.3,
linetype = 'dashed',
colour = "#3f4d58"),
panel.grid.major.y = element_line(size = 0.3,
linetype = 'dashed',
colour = "#3f4d58"),
panel.grid.minor.y = element_line(size = 0.3,
linetype = 'dashed',
colour = "#3f4d58"),
# Para cambiar la fuente de las letras del titulo, ejes y pie de página
axis.title.y = element_text(color = "#ffffff", face = "bold", family = "mono"),
axis.title.x = element_text(color = "#ffffff", face = "bold", family = "mono"),
axis.text.x = element_text(color = "#ffffff", family = "mono"),
axis.text.y = element_text(color = "#ffffff", family = "mono"),
plot.margin=unit(c(1,1,1,1),"cm")) +
scale_y_continuous(labels = comma)
Existen paquetes especializados para series de tiempo, como es el caso de dygraphs
, el cual nos pide un objeto de clase xts
, lo que de hecho nos arroja por default la función getsymbols
que usamos al principio para poder obtener las series que necesitabamos. Para hacer este gráfico basta con indicar la serie que necesitamos de nuestro objeto original (Ojo: no el objeto que transformamos a data frame, sino el que obtuvimos para obtener la serie de Yahoo Finance).
Vamos a graficar los datos de la siguiente manera:
# Para el S&P 500
dygraph(GSPC$GSPC.Close, main = "Índice S&P 500: Evolución") %>%
dyOptions(stackedGraph = FALSE) %>%
dyRangeSelector(height = 20)
# Para el Dow Jones
dygraph(DJI$DJI.Close, main = "Índice Dow Jones: Evolución") %>%
dyOptions(stackedGraph = FALSE) %>%
dyRangeSelector(height = 20)
# Para el NASDAQ
dygraph(IXIC$IXIC.Close, main = "Índice NASDAQ: Evolución") %>%
dyOptions(stackedGraph = FALSE) %>%
dyRangeSelector(height = 20)
Estos son útiles cuando no tenemos una gran cantidad de datos, de hecho ya lo mencioné en una entrada anterior. Es común ver que las barras se utilizan para datos de cuentas nacionales, como aquellos que se obtienen de manera trimestral, ya que nos muestran una evolución para pocos datos. Para este ejercicio vamos a utilizar datos de la FRED (la Reserva Federal de Estados Unidos), los cuales se pueden obtener de la misma manera que con los datos de Yahoo Finance, copiando el código de la serie que se encuentra entre paréntesis.
Primero que nada, vamos a obtener la serie:
# Obteniendo datos de la FRED
getSymbols.FRED("GDP",env=globalenv())
## [1] "GDP"
Y ahora los transformamos a un data frame que incluya las fechas, tal que:
GDPUS <- as.data.frame(GDP)
GDPUS$date <- time(GDP)
Bien, ahora podemos graficar los datos de la siguiente manera:
# Gráfico del PIB de USA
GDPUS %>%
e_charts(date) %>%
e_bar(GDP) %>%
e_color("#c44f4f") %>%
e_tooltip(trigger = "axis") %>%
e_title("Producto interno bruto de USA") %>%
e_axis_labels(x = "Fecha", y = "GDP")
El gráfico no es tan agradable a la vista, ya que tenemos una enorme cantidad de datos, por lo que podríamos simplemente obtener los últimos 30 datos para una mejor visualización de la siguiente manera:
# Filtrando datos
top_30 <-GDPUS %>%
top_n(30)
Ahora volvemos a graficar la información:
# Gráfico del PIB de USA
top_30 %>%
e_charts(date) %>%
e_bar(GDP) %>%
e_color("#c44f4f") %>%
e_tooltip(trigger = "axis") %>%
e_title("Producto interno bruto de USA") %>%
e_axis_labels(x = "Fecha", y = "GDP")
Ahora si, ya tenemos un gráfico mucho más agradable a la vista y fácilmente interpretable.
Estos sirven para conocer la tendencia de largo plazo de los datos que tenemos, aunque solo se debe considerar usarlos cuando tenemos una serie de tiempo con un componente estacional (con muchos picos y caídas que sean periódicas en el tiempo). Ya tengo un ejercicio hecho al respecto, por lo que no es necesario replicarlo aquí. Te dejo el link del ejercicio original justo aquí
Estos suelen ser utilizados principalmente cuando queremos trabajar diversas series a la vez y queremos ver la diferencia existente entre cada una de ellas. Para este ejercicio podríamos crear un data frame que incluya los datos de los tres índices usados al principio, para ver la diferencia entre ellos. Vamos a ello:
# Creamos las variables individuales
Fecha <- SP500$date
Precio_sp <- SP500$GSPC.Close
Precio_nas <- NASDAQ$IXIC.Close
Precio_djo <- DJones$DJI.Close
# Creamos el data frame
Indices <- data.frame(Fecha, Precio_sp, Precio_nas, Precio_djo)
# Visualizamos los datos
head(Indices)
## Fecha Precio_sp Precio_nas Precio_djo
## 1 2012-01-03 1277.06 2648.72 12397.38
## 2 2012-01-04 1277.30 2648.36 12418.42
## 3 2012-01-05 1281.06 2669.86 12415.70
## 4 2012-01-06 1277.81 2674.22 12359.92
## 5 2012-01-09 1280.70 2676.56 12392.69
## 6 2012-01-10 1292.08 2702.50 12462.47
Antes de pasar al gráfico voy a reducir el número de observaciones, ya que se haría demasiado pesado.
Indices_red <- Indices %>%
top_n(500)
Bien, ahora pasamos a graficar las series respectivamente:
Indices_red %>%
e_charts(Fecha) %>%
e_area(Precio_sp) %>%
e_area(Precio_djo) %>%
e_area(Precio_nas) %>%
e_theme("chalk") %>%
e_tooltip(trigger = "axis") %>%
e_title("Comparación") %>%
e_axis_labels(x = "Fecha", y = "Precio")
Gracias a este tipo de gráficos se puede tener una visualización mucho más clara de los datos y la diferencia que hay entre ellos, por lo que los podemos comparar de mejor manera.
Probablemente ya conozcas este tipo de gráficos, debido a que en páginas de trading y anuncios sobre inversiones suelen utilizarlos. Estos nos indican más información que la que nos da un gráfico común de linea, barra o área. Básicamente, estos cuando tenemos una vela verde significa que el precio se incrementó, si la vela es roja significa que el precio disminuyó. La línea sobre la vela índica el precio máximo de una observación, mienstras que la línea por debajo indica el precio mínimo. La parte baja de la vela verde indica el precio de apertura y la parte de arriba indica el precio de cierre, mientras que en las velas rojas es lo mismo pero de manera inversa.
Vamos a hacer un gráfico de éstos con los índicadores que ya tenemos transformados en data frames, pero para ello debemos hacer una pequeña transformación a los datos, tal que:
SP500$date <- row.names(SP500)
NASDAQ$date <- row.names(NASDAQ)
DJones$date <- row.names(DJones)
# Para el S&P 500
SP500 %>%
e_charts(date) %>%
e_candle(GSPC.Open, GSPC.Close, GSPC.Low, GSPC.High, name = "S&P 500") %>%
e_tooltip(trigger = "axis") %>%
e_title("Índice S&P 500 (histórico)") %>%
e_axis_labels(x = "Fecha", y = "Precio") %>%
e_datazoom(type = "slider")
# Para el NASDAQ
NASDAQ %>%
e_charts(date) %>%
e_candle(IXIC.Open, IXIC.Close, IXIC.Low, IXIC.High, name = "NASDAQ") %>%
e_tooltip(trigger = "axis") %>%
e_title("Índice NASDAQ (histórico)") %>%
e_axis_labels(x = "Fecha", y = "Precio") %>%
e_datazoom(type = "slider")
# Para el Dow Jones
DJones %>%
e_charts(date) %>%
e_candle(DJI.Open, DJI.Close, DJI.Low, DJI.High, name = "Dow Jones") %>%
e_tooltip(trigger = "axis") %>%
e_title("Índice Dow Jones (histórico)") %>%
e_axis_labels(x = "Fecha", y = "Precio") %>%
e_datazoom(type = "slider")
Estos son básicamente una forma de visualizar información por fechas como si se tratase de un calendario ordenado por una paleta de colores, la cual nos indica los periodos donde hubo valores mayores. Estos son útiles cuando tenemos datos que tienden a variar alrededor de un cierto rango, por ejemplo, muertos diarios de COVID.
Podríamos crear una serie de datos ficticios para mostrar como se vería un gráfico de este tipo. Vamos a ello:
# Creamos el data frame con datos ficticios
fechas_fic <- seq.Date(as.Date("2018-01-01"), as.Date("2019-12-31"), by = "day")
valores <- rnorm(length(fechas_fic), 20, 6)
base_fic <- data.frame(fechas_fic, valores)
Ahora que tenemos los datos, ya podemos crear el gráfico de la siguiente manera:
# Gráfico de calendario
base_fic %>%
e_charts(fechas_fic) %>%
e_calendar(range = "2018") %>%
e_heatmap(valores, coord_system = "calendar") %>%
e_visual_map(max = 30) %>%
e_tooltip() %>%
e_title("Ejemplo de gráfico de calendario")
Estos simplemente se encargan de medir la volatilidad de una serie temporal, es decir, las tasas tasas de cambio que tenemos en la información observada. Entre mayor sea la variación que tenemos de un periodo a otro entonces podemos decir que la volatilidad es mayor, por lo que la línea del gráfico será más grande. Vamos a un ejemplo de ello:
Primero que nada, debemos crear una serie con diferencias para graficar los datos, la cual debe tener estructura de serie de tiempo. Vamos a usar los datos del S&P 500 para el ejercicio. Ahora, al crear la base con las diferencias se pierde un valor inicial, por lo que debemos quitar ese valor para las fechas, tal que:
# Pasamos los datos a serie de tiempo
ts_sp500 <- ts(SP500$GSPC.Close, frequency = 365, start = 2012)
# Creamos la serie en diferencias
diff_sp500 <- diff(ts_sp500, base = exp(1),
lag = 1,
differences = 1)
# Creamos un vector de fechas
fecha_ts <- SP500$date[2:2326]
# Creamos el data frame
base_diff <- data.frame(fecha_ts, diff_sp500)
Ahora, ya podemos graficar los datos de la siguiente manera:
base_diff %>%
e_charts(fecha_ts) %>%
e_line(diff_sp500, name = "Cambio observado") %>%
e_theme("chalk") %>%
e_color("#de3428") %>%
e_tooltip(trigger = "axis") %>%
e_title("Gráfico de sismógrafo") %>%
e_axis_labels(x = "Fecha", y = "Valor")
Éstos gráficos son utilizados cuando hacemos un modelo econométrico o de series de tiempo y queremos visualizar, basados en la proyección que hicimos, cómo cambiará la serie en el futuro. Son útiles para darse una idea sobre lo que veremos. Para éste tipo de gráficos necesitamos necesariamente hacer un modelo, pero esto lo veremos en la sección de series de tiempo en las semanas póximas, ya que es necesario entender toda la teoría detrás de, por ejemplo, un modelo ARIMA, por lo que por ahora me limitaré a mostrarte cómo se ve uno de estos gráficos.
El artículo Exploring echarts4r nos muestra un gráfico de éste estilo, el cual te dejo a continuación:
Este es otro tipo de gráficos de área, solo que aquí se da prioridad a la proporción entre las series sobre el valor individual que hay entre cada una de ellas. podríamos hacer un ejercicio con los datos del índice Dow Jones, para ver si la proporción entre el precio máximo y el mínimo es muy similar o muy diferente. Vamos a ello:
# Creamos el gráfico de río
DJones %>%
e_charts(date) %>%
e_river(DJI.High, name = "Máximo") %>%
e_river(DJI.Close, name = "Cierre") %>%
e_river(DJI.Low, name = "Mínimo") %>%
e_tooltip(trigger = "axis")
Como vemos, prácticamente los diferentes precios observados durante un día para una serie son muy similares entre ellos, por lo que para este caso no valdría la pena hacer un gráfico de rio.
¡Muchas gracias por leerme! Sería de gran ayuda que compartieras ésta entrada con quien creas que pueda serle útil. Me ayudaría mucho que ésto llegue a más gente.
[1] Urias, H. Q., & Salvador, B. R. P. (2014). Estadística para ingeniería y ciencias. Grupo Editorial Patria.
[2] Wickham, H., Chang, W., & Wickham, M. H. (2016). Package ‘ggplot2’. Create Elegant Data Visualisations Using the Grammar of Graphics. Version, 2(1), 1-189.
[3] Kuan, J. (2015). Learning Highcharts 4. Packt Publishing Ltd.
[4] Bivand, R. S., Pebesma, E. J., Gomez-Rubio, V., & Pebesma, E. J. (2013). Applied spatial data analysis with R (Vol. 2). New York: Springer.
[5] Smith, A. (2018). Visual Vocabulary. 4 de marzo de 2020, de Financial Times. Sitio web: https://github.com/ft-interactive/chart-doctor/tree/master/visual-vocabulary
[6] Coene, J. (2017). Graphs. 26 de febrero de 2021, de echarts4r Sitio web: https://echarts4r.john-coene.com/articles/map.html
[7] Simmering, P. (2020). Exploring echarts4r. 31 de marzo de 2021, de Rpubs Sitio web: https://rpubs.com/paul_simmering/echarts