El análisis de series de tiempo constituye una herramienta fundamental para comprender la evolución de variables económicas y financieras, permitiendo identificar patrones, evaluar tendencias y realizar pronósticos que apoyan la toma de decisiones estratégicas. En un contexto global altamente dinámico, caracterizado por la digitalización, la interdependencia económica y la volatilidad de los mercados, el estudio del comportamiento histórico de indicadores clave se vuelve esencial para anticipar escenarios futuros y diseñar estrategias eficientes en sectores como las finanzas, el comercio, el mercado laboral y la gestión empresarial.
En este trabajo se analiza la serie temporal correspondiente a los precios de cierre diarios de la acción de Amazon (AMZN), una de las compañías tecnológicas más influyentes del mundo. Los datos fueron obtenidos de Yahoo Finance, una plataforma ampliamente utilizada para la consulta de información financiera en tiempo real. La elección de esta serie resulta relevante tanto a nivel global como nacional debido al impacto de Amazon en el comercio electrónico, la computación en la nube y la economía digital, sectores que han transformado profundamente los modelos de negocio y los patrones de consumo a escala mundial.
El período analizado, comprendido entre 2015 y 2025, incluye eventos económicos significativos como la expansión mundial del comercio digital, el auge de los servicios en la nube, la irrupción de la pandemia de COVID-19 y el posterior ajuste del mercado financiero global. Estos acontecimientos generaron fluctuaciones notables en el comportamiento de la acción de Amazon, convirtiéndola en un caso representativo para estudiar cómo factores macroeconómicos y tecnológicos pueden influir en el valor de activos financieros.
Para el análisis se empleó una metodología basada en técnicas de series de tiempo, comenzando con la caracterización de la variable mediante la identificación de patrones como tendencia, estacionalidad y componentes aleatorios. Posteriormente, se aplicó el modelo ARIMA, el cual combina autorregresión, diferenciación y medias móviles para transformar la serie en estacionaria y modelar la dependencia temporal.
Una serie de tiempo es un conjunto de datos ordenados cronológicamente que representan la evolución de una variable a lo largo del tiempo. Estas observaciones se toman en intervalos de tiempo regulares, como horas, días, meses o años, y se usan para analizar tendencias, patrones (como estacionalidad) o para hacer pronósticos.
Secuencia temporal: Los datos están ordenados en el tiempo, lo que los hace únicos en comparación con otros tipos de datos.
Dependencia temporal: A menudo, los valores de una observación están relacionados con los de observaciones anteriores.
Análisis: Se utilizan para identificar patrones como:
- Tendencia: El movimiento general al alza o a la baja de los datos a largo plazo (ej. el aumento de la temperatura media global).
- Estacionalidad: Variaciones periódicas que ocurren dentro de un período de tiempo fijo y conocido (ej. un aumento de las ventas de helados en verano).
- Ciclos: Oscilaciones alrededor de la tendencia que duran más tiempo y no son de duración fija (ej. ciclos económicos).
- Componente aleatorio o irregular: Movimientos erráticos que no siguen un patrón predecible.
Aplicaciones: Se aplican en diversos campos, como la economía (predecir la inflación), las finanzas (analizar el precio de las acciones) o el medio ambiente (predecir el clima).
Un modelo ARIMA (Media Móvil Integrada Autorregresiva) es un método estadístico de pronóstico que utiliza datos de series temporales para predecir valores futuros. Funciona combinando tres componentes: autoregresión (AR), que usa valores pasados; diferenciación (I), para hacer la serie estacionaria; y medias móviles (MA), que consideran los errores de pronóstico pasados. La meta es comprender patrones en datos históricos y predecir el futuro, especialmente para series no estacionarias.
- AR (Autorregresivo): Predice el valor actual de la serie basándose en sus propios valores pasados (rezagos).
- I (Integrado): Se refiere a la diferenciación de la serie, que se utiliza para eliminar tendencias y hacer que la serie sea estacionaria, es decir, que su media y varianza no cambien con el tiempo.
- MA (Media Móvil): Predice el valor actual basándose en los errores de pronóstico pasados (la diferencia entre los valores reales y los pronósticos anteriores).
Análisis de series temporales: Permite entender la relación entre un punto en el tiempo y los puntos anteriores.
Pronóstico: Se utiliza para predecir valores futuros de la serie, como la demanda de un producto, el precio de una acción o el clima, basándose en datos históricos.
Modelado: Puede explicar una serie temporal en función de sus propios valores pasados y de los errores de pronóstico pasados.
Estacionariedad: Se transforma la serie temporal mediante la diferenciación (el número de veces que se resta el valor anterior del actual) hasta que la media y la varianza se vuelvan constantes a lo largo del tiempo. El número de diferenciaciones es el componente ‘d’.
Identificación de órdenes: Se utilizan los gráficos de autocorrelación (ACF) y autocorrelación parcial (PACF) para determinar los órdenes ‘p’ (autorregresivo) y ‘q’ (media móvil).
Ajuste del modelo: Se ajusta el modelo ARIMA (p, d, q) a los datos. Evaluación: Se verifica si el modelo se ajusta bien a los datos, por ejemplo, analizando los residuos.
Los modelos ARIMA son importantes y útiles en la predicción de series temporales porque pueden identificar y modelar patrones complejos como tendencias y estacionalidad, permitiendo realizar pronósticos precisos a corto plazo en diversos campos como finanzas, economía y meteorología. Su utilidad radica en su flexibilidad para adaptarse a diferentes tipos de datos, su capacidad para explicar el valor futuro basándose en valores pasados y errores anteriores, y su aplicación en la gestión de inventario, personal y recursos hídricos.
- Modelado de patrones complejos: ARIMA puede identificar y describir patrones en los datos históricos, como tendencias (crecimiento o decrecimiento) y estacionalidad (ciclos que se repiten a intervalos regulares), lo que es fundamental para hacer predicciones fiables.
- Realización de pronósticos precisos: Permiten predecir valores futuros con una alta precisión, especialmente en el corto plazo, al basarse en la dependencia de los valores pasados (componente AR) y los errores de predicción pasados (componente MA).
- Adaptabilidad a diferentes datos: Son flexibles y pueden adaptarse a una amplia gama de datos de series temporales, tanto no estacionales como estacionales, lo que los hace útiles en diversas industrias.
- Base para la toma de decisiones: Los pronósticos generados por ARIMA son cruciales para la planificación estratégica en negocios e industrias. Por ejemplo, ayudan a las empresas a gestionar mejor el inventario, el personal y la demanda de los consumidores.
- Análisis de fenómenos naturales: Se utilizan para analizar y pronosticar fenómenos naturales complejos, como los niveles de los ríos, lo que contribuye a la planificación y optimización de la gestión de recursos hídricos, especialmente en el contexto del cambio climático.
- Análisis de datos económicos y financieros: Son ampliamente utilizados para predecir precios de acciones, demanda energética y otros indicadores económicos, proporcionando información procesable para la toma de decisiones.
Amazon es una empresa estadounidense fundada en 1994 por Jeff Bezos, inicialmente como una librería en línea. Con el tiempo se transformó en una de las compañías tecnológicas más grandes del mundo, expandiéndose hacia comercio electrónico, servicios en la nube (AWS), entretenimiento digital, inteligencia artificial y logística global. La empresa comenzó a cotizar en la bolsa NASDAQ el 15 de mayo de 1997, lo que la convierte en una de las compañías tecnológicas con mayor trayectoria en los mercados bursátiles modernos.
Durante el período analizado (2015–2025), como se observa en la Figura 1, Amazon enfrentó múltiples dinámicas que influyeron en el comportamiento de su acción. Entre 2015 y 2019 se presenta una tendencia claramente ascendente, impulsada por el crecimiento sostenido del comercio electrónico, la expansión global de la empresa y la consolidación de Amazon Web Services (AWS), su división de computación en la nube que se convirtió en una de sus principales fuentes de ingresos. Durante esta etapa, el precio de la acción pasó de aproximadamente $20 USD en 2015 a valores superiores a $80–100 USD en 2019, evidenciando un periodo de apreciación constante y estable.
A partir de 2020, la llegada de la pandemia de COVID-19 generó un cambio abrupto en la dinámica del mercado. El confinamiento global impulsó fuertemente la demanda por comercio electrónico, entretenimiento digital y servicios en la nube, sectores donde Amazon es líder. Como resultado, la gráfica muestra un incremento muy pronunciado durante 2020, con un crecimiento acelerado del precio que llevó a la acción a alcanzar máximos históricos a finales de 2021. Esta etapa coincide con la aceleración de la digitalización en hogares y empresas, lo que fortaleció de forma excepcional el desempeño financiero de Amazon.
Figura 1. Evolución del precio de Amazon (2015-2025)
library(quantmod)
library(plotly)
library(dplyr)
serie <- getSymbols('AMZN',src='yahoo',auto.assign=FALSE,
from="2015-01-01", to="2025-01-15")
amazon_df <- data.frame(
Date = index(serie),
Price = as.numeric(serie$AMZN.Close)
)
# Periodos
periodos <- tibble::tribble(
~inicio, ~fin, ~etiqueta, ~color,
"2015-01-01", "2019-12-31", "2015–2019: Crecimiento sostenido", "rgba(46,134,193,0.55)",
"2020-01-01", "2020-12-31", "2020: Salto por COVID-19", "rgba(231,76,60,0.55)",
"2021-01-01", "2021-12-31", "2021: Máximos históricos", "rgba(244,208,63,0.55)",
"2022-01-01", "2022-12-31", "2022: Caída por inflación y tasas", "rgba(155,89,182,0.55)",
"2023-01-01", "2025-01-15", "2023–2025: Recuperación sostenida", "rgba(39,174,96,0.55)"
) %>% mutate(across(c(inicio, fin), as.Date))
# Eventos
eventos <- tibble::tribble(
~fecha, ~descripcion,
"2015-01-05", "Inicio del período analizado",
"2018-08-30", "Amazon supera los $100 USD",
"2020-04-20", "Aceleración por pandemia COVID-19",
"2021-07-08", "Máximo histórico en pandemia",
"2022-12-29", "Mínimo por inflación y tasas FED",
"2024-06-06", "Fin del período analizado"
) %>% mutate(fecha = as.Date(fecha))
eventos <- eventos %>%
left_join(amazon_df, by = c("fecha" = "Date"))
# Franjas para los periodos
shapes_periodos <- lapply(1:nrow(periodos), function(i) {
list(
type = "rect",
x0 = periodos$inicio[i],
x1 = periodos$fin[i],
y0 = 0,
y1 = max(amazon_df$Price, na.rm = TRUE),
fillcolor = periodos$color[i],
opacity = 0.55,
line = list(width = 0)
)
})
# Gráfico
fig <- plot_ly()
# Línea principal
fig <- fig %>% add_lines(
data = amazon_df,
x = ~Date,
y = ~Price,
name = "Precio de cierre",
line = list(color = "black", width = 2),
hoverinfo = "x+y"
)
# Eventos importantes
fig <- fig %>% add_markers(
data = eventos,
x = ~fecha,
y = ~Price,
marker = list(size = 9, color = "red"),
hovertext = ~paste0(
"<b>", descripcion, "</b>",
"<br>Fecha: ", fecha,
"<br>Precio: $", round(Price, 2)
),
hoverinfo = "text",
name = "Eventos"
)
fig <- fig %>% layout(
title = "Evolución del precio de Amazon (2015–2025)",
xaxis = list(title = "Fecha",
tickmode = "array",
tickvals = as.Date(paste0(2015:2025, "-01-01")),
ticktext = as.character(2015:2025)
),
yaxis = list(title = "Precio de cierre (USD)"),
shapes = shapes_periodos,
showlegend = FALSE
)
fig
Sin embargo, se evidencia un retroceso significativo durante 2022, observándose una fuerte caída entre finales de 2021 y finales de 2022. Este comportamiento está asociado a un contexto económico global desfavorable marcado por las fuertes presiones inflacionarias, el aumento agresivo de las tasas de interés por parte de la Reserva Federal de Estados Unidos y los crecientes temores de desaceleración económica. Además, el sector tecnológico en general enfrentó un proceso de ajuste tras el crecimiento extraordinario registrado durante la pandemia, lo que llevó a una corrección en los portafolios de inversión y a una caída generalizada en los mercados bursátiles. Como resultado, la acción de Amazon perdió una parte importante de las ganancias obtenidas en el período pandémico.
A partir de 2023, el precio de la acción muestra una recuperación progresiva, reflejando mejoras en el desempeño financiero de Amazon, la implementación de estrategias de optimización interna y una mayor estabilidad en los mercados tras la volatilidad de 2022. Durante 2023 y 2024, la empresa experimenta una normalización económica acompañada de recortes de costos, ajustes operativos y un aumento en la rentabilidad, factores que contribuyen a restablecer la confianza de los inversionistas.
El precio de la acción presenta un valor promedio de 110.73, lo que indica que, en general, los precios tienden a ubicarse alrededor de este nivel, ver tabla 1. Sin embargo, la mediana es 98,96, un valor considerablemente menor que la media. Esta diferencia evidencia que la distribución del precio está sesgada hacia la derecha, lo que significa que existen valores altos que empujan la media hacia arriba. Esto suele estar asociado a la presencia de valores atípicos o a una cola larga en los precios más elevados.
Tabla 1. Estadística descriptiva.
library(quantmod)
library(fpp2)
library(tseries)
library(knitr)
library(kableExtra)
serie <- getSymbols('AMZN',src='yahoo',auto.assign=FALSE,
from="2015-01-01")
accion <- serie$AMZN.Close
descriptivos <- data.frame(
Estadística = c("Media", "Mediana", "Mínimo",
"Máximo", "Desv. Est.", "IQR"),
Valor = sprintf("%.2f", c(
mean(accion, na.rm = TRUE),
median(accion, na.rm = TRUE),
min(accion, na.rm = TRUE),
max(accion, na.rm = TRUE),
sd(accion, na.rm = TRUE),
IQR(accion, na.rm = TRUE)
))
)
kable(descriptivos,
align = c('l', 'r'),
caption = "Estadísticas Descriptivas") %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE,
position = "left",
font_size = 14
) %>%
column_spec(1, width = "12em", bold = TRUE) %>%
column_spec(2, width = "10em")
| Estadística | Valor |
|---|---|
| Media | 110.95 |
| Mediana | 99.28 |
| Mínimo | 14.35 |
| Máximo | 254.00 |
| Desv. Est. | 61.17 |
| IQR | 112.40 |
Al observar los extremos, el precio mínimo registrado es 14,35, mientras que el máximo alcanza 254, lo cual muestra un rango muy amplio. Esta variabilidad refleja que la acción ha experimentado tanto periodos prolongados de bajos precios como fases de fuerte crecimiento. La desviación estándar, de 61.01, confirma esta elevada dispersión, indicando que los precios se alejan considerablemente del promedio y evidencian una alta volatilidad en la evolución del activo.
Por su parte, el rango intercuartílico (IQR) es 112.23, un valor también elevado. Este indicador mide la dispersión del 50 % central de los datos y su magnitud revela que incluso la parte más representativa de la distribución presenta una gran variabilidad. En conjunto, estas estadísticas indican que el precio de la acción es altamente volátil, presenta asimetrías importantes y contiene valores extremos que influyen notablemente en su estructura distributiva.
Por otra parte, la figura 2 muestra la distribución empírica de los retornos diarios (cuánto cambia el precio de la acción de un día para otro) de la acción de Amazon (AMZN) entre 2015 y 2025. El histograma (en azul) revela la frecuencia de los diferentes valores de retorno, mientras que la densidad empírica (línea roja) y la distribución normal teórica (línea verde) permiten evaluar qué tan similar es el comportamiento real respecto a un modelo normal. Esta comparación es clave para comprender el riesgo, la volatilidad y la presencia de eventos extremos.
Figura 2. Distribución de retornos de Amazon.
library(plotly)
library(moments)
# Calcular retornos logarítmicos
retornos <- diff(log(accion)) %>% na.omit()
df_retornos <- data.frame(retornos = as.numeric(retornos))
# Calcular estadísticos
media_ret <- mean(df_retornos$retornos)
sd_ret <- sd(df_retornos$retornos)
asimetria <- skewness(retornos)
curtosis_valor <- kurtosis(retornos)
exceso_curtosis <- curtosis_valor - 3
# Crear histograma
hist_data <- hist(df_retornos$retornos, breaks = 50, plot = FALSE)
# Crear secuencia para las curvas
x_seq <- seq(min(df_retornos$retornos), max(df_retornos$retornos), length.out = 500)
# Densidad real
density_real <- density(df_retornos$retornos)
# Densidad normal teórica
density_normal <- dnorm(x_seq, mean = media_ret, sd = sd_ret)
# Crear gráfico con plotly
fig <- plot_ly() %>%
# Histograma
add_histogram(
x = df_retornos$retornos,
histnorm = "probability density",
name = "Histograma",
marker = list(
color = 'rgba(70, 130, 180, 0.7)',
line = list(color = 'rgb(25, 25, 25)', width = 1)
),
hovertemplate = paste('<b>Retorno:</b> %{x:.4f}<br>',
'<b>Densidad:</b> %{y:.2f}<br>',
'<extra></extra>')
) %>%
# Curva de densidad real
add_trace(
x = density_real$x,
y = density_real$y,
type = 'scatter',
mode = 'lines',
name = 'Densidad Real',
line = list(color = 'rgb(220, 20, 60)', width = 3),
hovertemplate = paste('<b>Retorno:</b> %{x:.4f}<br>',
'<b>Densidad:</b> %{y:.2f}<br>',
'<extra></extra>')
) %>%
# Curva normal teórica
add_trace(
x = x_seq,
y = density_normal,
type = 'scatter',
mode = 'lines',
name = 'Distribución Normal',
line = list(color = 'rgb(34, 139, 34)', width = 2.5, dash = 'dash'),
hovertemplate = paste('<b>Retorno:</b> %{x:.4f}<br>',
'<b>Densidad Normal:</b> %{y:.2f}<br>',
'<extra></extra>')
) %>%
# Línea vertical en la media
add_segments(
x = media_ret, xend = media_ret,
y = 0, yend = max(density_real$y),
line = list(color = 'rgb(255, 140, 0)', width = 2, dash = 'dot'),
showlegend = TRUE,
name = 'Media',
hovertemplate = paste('<b>Media:</b>', round(media_ret, 5), '<extra></extra>')
) %>%
# Anotaciones con las estadísticas
add_annotations(
x = 1,
y = 1,
xref = "paper",
yref = "paper",
text = paste0(
"<b>Medidas de Forma</b><br>",
"──────────────<br>",
"Asimetría: <b>", round(asimetria, 4), "</b><br>",
"Curtosis: <b>", round(curtosis_valor, 4), "</b><br>",
"Exceso Curtosis: <b>", round(exceso_curtosis, 4), "</b><br><br>",
"<i>",
if(asimetria > 0) "Sesgada a la derecha" else if(asimetria < 0) "Sesgada a la izquierda" else "Simétrica",
"<br>",
if(exceso_curtosis > 0) "Colas pesadas" else if(exceso_curtosis < 0) "Colas ligeras" else "Normal",
"</i>"
),
showarrow = FALSE,
xanchor = "right",
yanchor = "top",
align = "left",
bgcolor = "rgba(255, 255, 255, 0.95)",
bordercolor = "rgb(70, 130, 180)",
borderwidth = 2,
borderpad = 10,
font = list(size = 12, family = "Arial, sans-serif")
) %>%
# Layout del gráfico
layout(
title = list(
text = paste0(
"<b>Distribución de Retornos de AMZN</b><br>",
"<sup>Análisis de Forma y Normalidad</sup>"
),
font = list(size = 18, family = "Arial, sans-serif")
),
xaxis = list(
title = "<b>Retornos</b>",
titlefont = list(size = 14),
showgrid = TRUE,
gridcolor = 'rgba(200, 200, 200, 0.3)',
zeroline = TRUE,
zerolinecolor = 'rgba(0, 0, 0, 0.3)',
tickformat = ".3f"
),
yaxis = list(
title = "<b>Densidad</b>",
titlefont = list(size = 14),
showgrid = TRUE,
gridcolor = 'rgba(200, 200, 200, 0.3)'
),
hovermode = 'x unified',
plot_bgcolor = 'rgba(245, 245, 245, 0.9)',
paper_bgcolor = 'white',
legend = list(
orientation = "h",
x = 0.5,
xanchor = "center",
y = -0.15,
bgcolor = 'rgba(255, 255, 255, 0.8)',
bordercolor = 'rgb(200, 200, 200)',
borderwidth = 1,
font = list(size = 11)
),
margin = list(t = 100, b = 80, l = 80, r = 200)
) %>%
# Configuración de interactividad
config(
displayModeBar = TRUE,
modeBarButtonsToRemove = c('lasso2d', 'select2d'),
displaylogo = FALSE,
toImageButtonOptions = list(
format = 'png',
filename = 'distribucion_retornos_AMZN',
height = 800,
width = 1200,
scale = 2
)
)
fig
En cuanto a la forma de la distribución, la asimetría es 0.1701, indicando una ligera inclinación positiva. Esto significa que los retornos positivos extremos ocurren con una frecuencia apenas mayor que los retornos negativos equivalentes. Aunque la diferencia es pequeña, coincide con el comportamiento de un activo que ha mostrado una tendencia alcista a lo largo del tiempo: la mayoría de los movimientos diarios son pequeños, pero existe una leve propensión a registrar alzas puntuales más pronunciadas.
La curtosis, con un valor de 8.7569, genera un exceso de curtosis de 5.7569, lo cual señala que la distribución es marcadamente leptocúrtica. Esto implica que presenta un pico más alto en el centro y colas pesadas, lo que refleja la existencia de retornos extremos tanto positivos como negativos más frecuentes que los esperados bajo una distribución normal. Este comportamiento es típico de los mercados financieros y es esencial para la gestión del riesgo, ya que sugiere que los movimientos abruptos no son eventos excepcionales, sino relativamente probables.
La comparación visual refuerza esta conclusión: la curva normal teórica (verde) muestra colas más delgadas que las observadas en la distribución empírica (roja), lo cual evidencia que el mercado incorpora una mayor probabilidad de eventos inusuales. Además, la media de los retornos, representada por la línea punteada naranja, se ubica cerca de cero, lo cual es característico de las series de retornos diarios, donde el rendimiento promedio suele ser muy pequeño aunque la acción crezca a largo plazo.
En conjunto, la distribución de los retornos de AMZN evidencia las propiedades típicas de un activo financiero de alta liquidez: ligero sesgo positivo, colas pesadas, alta concentración alrededor de cero y eventos extremos más frecuentes de lo normal. Estos rasgos confirman que, aunque la mayoría de los días los cambios son moderados, existe una probabilidad significativa de experimentar variaciones bruscas.
El proceso de identificación del modelo se realizó utilizando los gráficos de autocorrelación (ACF) y autocorrelación parcial (PACF) ver figura 3 , junto con la función auto.arima() de R, la cual selecciona automáticamente el mejor modelo según los criterios de información AIC, AICc y BIC. El modelo seleccionado fue un ARIMA(0,1,0) con drift, lo que indica que:
- p = 0: no existe un componente autorregresivo significativo.
- d = 1: la serie requiere una diferenciación para lograr estacionariedad, lo
cual coincide con la presencia de tendencia en los datos originales.
- q = 0: no se identificaron componentes de medias móviles necesarios.
Figura 3. Gráficos del ACF y PACF.
library(quantmod)
theme_set(theme_gray(base_size = 3)) # ← letra más pequeña
serie <- getSymbols('AMZN',src='yahoo',auto.assign=FALSE,
from="2015-01-01")
accion<-serie$AMZN.Close
ventana<-window(accion, end = "2024-06-06") # ventana de entrenamiento
ventana2<-window(accion, start = "2024-06-07") # ventana de prueba
miserie<-diff(ventana) %>% na.omit()
library(gridExtra)
grid.arrange(ggAcf(miserie),
ggPacf(miserie),
nrow=1
)
La inclusión del término drift (tendencia estocástica) sugiere
que, aun después de diferenciar, la serie presenta un desplazamiento
sistemático en el tiempo, consistente con la tendencia ascendente
observada en el precio de la acción de Amazon.
El AIC obtenido (10566.01) y el BIC (10577.55) fueron los más bajos entre los modelos evaluados, lo que confirma que ARIMA(0,1,0) con drift es la especificación más adecuada según los criterios de parsimonia y ajuste.
Para determinar el modelo ARIMA más apropiado, se evaluaron dos especificaciones: el Modelo 1, obtenido automáticamente mediante la función auto.arima(), y el Modelo 2, ajustado manualmente como un ARIMA(1,1,0). La comparación se realizó utilizando los criterios de información AIC, AICc y BIC, que permiten seleccionar el modelo que ofrece el mejor equilibrio entre calidad de ajuste y complejidad.
Los resultados obtenidos se pueden observar en la tabla
# Definir ventana de análisis
ventana <- window(accion, end = "2024-06-06")
# Ajustar modelos ARIMA
modelo1 <- Arima(ventana, order = c(0,1,0))
modelo2 <- Arima(ventana, order = c(1,1,0))
modelo3 <- Arima(ventana, order = c(0,1,1))
modelo4 <- Arima(ventana, order = c(1,1,1))
# Comparación de modelos por criterios de información
modelos_info <- tibble::tibble(
Modelo = c("ARIMA(0,1,0) con drift",
"ARIMA(1,1,0)",
"ARIMA(0,1,1)",
"ARIMA(1,1,1)"),
AIC = c(modelo1$aic, modelo2$aic, modelo3$aic, modelo4$aic),
AICc = c(modelo1$aicc, modelo2$aicc, modelo3$aicc, modelo4$aicc),
BIC = c(modelo1$bic, modelo2$bic, modelo3$bic, modelo4$bic)
)
# Mostrar tabla de resultados
knitr::kable(modelos_info,
digits = 2,
align = 'c')
| Modelo | AIC | AICc | BIC |
|---|---|---|---|
| ARIMA(0,1,0) con drift | 10566.42 | 10566.42 | 10572.19 |
| ARIMA(1,1,0) | 10567.38 | 10567.38 | 10578.92 |
| ARIMA(0,1,1) | 10567.35 | 10567.36 | 10578.90 |
| ARIMA(1,1,1) | 10568.65 | 10568.66 | 10585.97 |
El Modelo 1, generado por auto.arima(), presenta valores más bajos de AIC, AICc y BIC en comparación con los otros tres modelos. Según los criterios de información, el modelo con los valores más pequeños es el preferido, ya que proporciona un mejor ajuste sin añadir parámetros innecesarios (principio de parsimonia).
Además, el Modelo 1 incluye un término de drift, lo cual es coherente con la tendencia creciente observada en la serie temporal del precio de Amazon. Este comportamiento es típico de los precios financieros, que suelen seguir un camino aleatorio con deriva.
Por estas razones, el modelo seleccionado como más adecuado para el análisis y pronóstico fue el ARIMA(0,1,0) con drift, recomendado por auto.arima().
La evaluación del modelo ARIMA(0,1,0) con drift se realizó mediante el análisis de residuos utilizando la función checkresiduals() (ver figura 4). Este procedimiento permite comprobar si los errores del modelo cumplen las condiciones fundamentales: independencia, media cero, varianza constante y aproximación a una distribución normal.
Figura 4. Residuos (checkresiduals)
library(quantmod)
library(fpp2)
library(tseries)
library(gridExtra)
library(ggplot2)
# Descargo la serie de interes desde yahoo
serie <- getSymbols('AMZN', src='yahoo', auto.assign=FALSE, from="2015-01-01")
# Seleccionar precio de cierre
accion <- serie$AMZN.Close
# Ventanas de entrenamiento y prueba
ventana <- window(accion, end = "2024-06-06")
ventana2 <- window(accion, start = "2024-06-07")
# Modelo ARIMA
modelo1 <- Arima(ventana, order = c(0,1,0))
# Extraer residuos
residuos <- residuals(modelo1)
# Test de Ljung-Box
ljung_test <- Box.test(residuos, lag=10, type="Ljung-Box")
# --- GRÁFICO 1: Serie temporal de residuos ---
p1 <- autoplot(residuos) +
geom_hline(yintercept = 0, linetype="dashed", color="red", linewidth=0.8) +
labs(title = "Residuos del Modelo ARIMA(0,1,0)",
subtitle = "Serie temporal de los residuos",
y = "Residuos", x = "Tiempo") +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face="bold", size=14, hjust=0.5),
plot.subtitle = element_text(size=11, hjust=0.5, color="gray30"),
panel.grid.minor = element_blank(),
panel.grid.major = element_line(color="gray90"),
plot.background = element_rect(fill="white", color=NA),
panel.background = element_rect(fill="white", color=NA)
)
#GRÁFICO 2: Histograma con curva normal
p2 <- ggplot(data.frame(residuos = as.numeric(residuos)), aes(x=residuos)) +
geom_histogram(aes(y=after_stat(density)), bins=30,
fill="steelblue", color="white", alpha=0.7) +
stat_function(fun = dnorm,
args = list(mean=mean(residuos, na.rm=TRUE),
sd=sd(residuos, na.rm=TRUE)),
color="red", linewidth=1.2, linetype="dashed") +
labs(title = "Distribución de Residuos",
subtitle = "Línea roja: distribución normal teórica",
x = "Residuos", y = "Densidad") +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face="bold", size=14, hjust=0.5),
plot.subtitle = element_text(size=10, hjust=0.5, color="gray30"),
panel.grid.minor = element_blank(),
panel.grid.major = element_line(color="gray90"),
plot.background = element_rect(fill="white", color=NA),
panel.background = element_rect(fill="white", color=NA)
)
#GRÁFICO 3: ACF mejorado
p3 <- ggAcf(residuos, lag.max=24) +
labs(title = "ACF de Residuos",
subtitle = sprintf("Test Ljung-Box: p-value = %.4f", ljung_test$p.value),
y = "ACF", x = "Lag") +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face="bold", size=14, hjust=0.5),
plot.subtitle = element_text(size=10, hjust=0.5,
color=ifelse(ljung_test$p.value > 0.05, "darkgreen", "darkred")),
panel.grid.minor = element_blank(),
panel.grid.major.y = element_line(color="gray90"),
panel.grid.major.x = element_blank(),
plot.background = element_rect(fill="white", color=NA),
panel.background = element_rect(fill="white", color=NA)
)
#GRÁFICO 4: Q-Q Plot
p4 <- ggplot(data.frame(residuos = as.numeric(residuos)), aes(sample=residuos)) +
stat_qq(color="steelblue", size=2, alpha=0.6) +
stat_qq_line(color="red", linewidth=1, linetype="dashed") +
labs(title = "Q-Q Plot",
subtitle = "Comparación con distribución normal",
x = "Cuantiles teóricos", y = "Cuantiles de la muestra") +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face="bold", size=14, hjust=0.5),
plot.subtitle = element_text(size=10, hjust=0.5, color="gray30"),
panel.grid.minor = element_blank(),
panel.grid.major = element_line(color="gray90"),
plot.background = element_rect(fill="white", color=NA),
panel.background = element_rect(fill="white", color=NA)
)
# Combinar todos los gráficos
grid.arrange(p1, p2, p3, p4, ncol=2,
top = grid::textGrob("Diagnóstico de Residuos - ARIMA(0,1,0)",
gp=grid::gpar(fontsize=16, fontface="bold")))
a. Comportamiento temporal de los residuos
En la gráfica superior se observa la evolución de los residuos a lo largo del tiempo. En términos generales, los errores:
Se encuentran alrededor de cero, lo que indica ausencia de sesgo sistemático.
Presentan cierta volatilidad variable en diferentes periodos, especialmente en la parte final de la serie, donde se observa un aumento en la magnitud de los picos.
Aun así, no se identifican patrones visibles ni tendencias persistentes en los residuos, lo cual respalda que la diferenciación aplicada logró eliminar la estructura determinística del precio original.
Este comportamiento es consistente con un proceso cercano a ruido blanco.
b. Análisis de autocorrelación (ACF)
El correlograma ACF muestra que:
La mayoría de los coeficientes se encuentran dentro de las bandas de significancia.
Algunos rezagos, por ejemplo, alrededor del lag 30 sobresalen ligeramente de las bandas, pero no presentan un patrón sistemático ni en forma de decrecimiento o periodicidad.
Esto indica que no hay autocorrelación significativa en los residuos, lo cual sugiere que el modelo ARIMA(0,1,0) capturó adecuadamente la dependencia temporal de la serie.
c. Distribución de los residuos
El histograma muestra la forma de la distribución de los errores comparada con una curva normal teórica. Los resultados evidencian que:
La distribución es aproximadamente simétrica alrededor de cero.
Se observan colas más pesadas que las de una distribución normal, lo cual es característico de series financieras (leptocurtosis).
Aun así, no se aprecian desviaciones extremas que afecten la validez global del modelo.
Este comportamiento indica que los residuos cumplen razonablemente las condiciones de normalidad aproximada necesarias para la inferencia del modelo.
Por lo tanto, el modelo ARIMA(0,1,0) es adecuado para la serie temporal analizada, ya que sus residuos se comportan como ruido blanco, cumpliendo con los supuestos necesarios para un modelo ARIMA bien especificado.
A partir del modelo seleccionado ARIMA(0,1,0) con drift, se generaron cinco pronósticos (h = 5) correspondientes a los días siguientes al periodo de entrenamiento. La siguiente tabla muestra los valores estimados junto con los intervalos de confianza al 95 %:
pronostico <- modelo1 %>%
forecast(h=5, level = 0.95)
tabla_pronostico <- data.frame(
Periodo = 1:5,
Pronostico = round(as.numeric(pronostico$mean), 2),
LimInf = round(as.numeric(pronostico$lower), 2),
LimSup = round(as.numeric(pronostico$upper), 2)
)
colnames(tabla_pronostico) <- c("Periodo", "Pronostico", "Lim Inf", "Lim Sup")
kable(tabla_pronostico, format = "html")
| Periodo | Pronostico | Lim Inf | Lim Sup |
|---|---|---|---|
| 1 | 185 | 180.60 | 189.40 |
| 2 | 185 | 178.78 | 191.22 |
| 3 | 185 | 177.38 | 192.62 |
| 4 | 185 | 176.21 | 193.79 |
| 5 | 185 | 175.17 | 194.83 |
Los valores verdaderos observados posteriormente fueron:
library(knitr)
library(kableExtra)
tabla_ventana2 <- data.frame(
Fecha = as.Date(time(ventana2[1:5])),
ValorReal = round(as.numeric(ventana2[1:5]), 2)
)
colnames(tabla_ventana2) <- c("Fecha", "Valor Real")
kable(tabla_ventana2,
align = c('l', 'r')) %>%
kable_styling(
bootstrap_options = c("striped", "hover"),
full_width = FALSE,
position = "center"
)
| Fecha | Valor Real |
|---|---|
| 2024-06-07 | 184.30 |
| 2024-06-10 | 187.06 |
| 2024-06-11 | 187.23 |
| 2024-06-12 | 186.89 |
| 2024-06-13 | 183.83 |
Estos valores reales se encuentran dentro de los intervalos de confianza estimados por el modelo, lo que confirma que el ARIMA (0,1,0) es capaz de capturar adecuadamente la dinámica general del precio y generar predicciones razonables en el corto plazo.
De manera consistente, en la gráfica de pronóstico (ver figura 5), se observa que los valores futuros siguen una trayectoria ascendente, coherente con la presencia del término drift identificado en el modelo. La línea central del forecast representa la predicción puntual, mientras que las bandas sombreadas corresponden a los intervalos de confianza al 80 % y 95 %, los cuales se ensanchan conforme avanza el horizonte temporal. Este ensanchamiento refleja la incertidumbre creciente inherente a los modelos de series de tiempo, especialmente en series financieras caracterizadas por alta volatilidad.
Figura 5. Gráfico de pronósticos.
library(quantmod)
library(fpp2)
library(ggplot2)
library(tidyverse)
serie <- getSymbols('AMZN', src='yahoo', auto.assign=FALSE, from="2015-01-01")
accion <- serie$AMZN.Close
# Ventanas de entrenamiento y prueba
ventana <- window(accion, end = "2024-06-06")
ventana2 <- window(accion, start = "2024-06-07")
# Modelo ARIMA
modelo1 <- Arima(ventana, order = c(0,1,0))
pronostico <- forecast(modelo1, h=5)
modelo1 %>%
forecast(h=5) %>%
autoplot(include=80) +
scale_fill_manual(values = c("#4A90E2", "#A8D5FF")) +
labs(
title = "Pronóstico ARIMA(0,1,0) - Amazon (AMZN)",
x = "Fecha",
y = "Precio de Cierre (USD)"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face="bold", size=15, hjust=0.5),
plot.subtitle = element_text(size=11, hjust=0.5, color="gray30", margin=margin(b=10)),
axis.title = element_text(face="bold", size=11),
axis.text = element_text(size=10),
legend.position = "right",
legend.title = element_blank(),
legend.text = element_text(size=10),
panel.grid.major = element_line(color="gray85", linewidth=0.4),
panel.grid.minor = element_line(color="gray92", linewidth=0.2),
plot.background = element_rect(fill="white", color=NA),
panel.background = element_rect(fill="white", color=NA)
)
El pronóstico muestra que, bajo la estructura del modelo y la tendencia estimada, el precio de la acción se mantendría en una trayectoria estable o moderadamente creciente, consistente con el comportamiento observado en los últimos años del historial. Aunque el modelo no captura eventos externos ni shocks de mercado, proporciona una estimación estadística válida basada exclusivamente en los patrones internos de la serie.
El análisis de la serie temporal del precio de cierre de la acción de Amazon (AMZN) entre 2015 y 2025 permitió identificar patrones relevantes característicos de los mercados financieros modernos. En primer lugar, se evidenció una evolución marcada por periodos de crecimiento sostenido, un incremento acelerado durante la pandemia de COVID-19, una corrección pronunciada en 2022 y una posterior recuperación. Las estadísticas descriptivas confirmaron la alta volatilidad del activo, así como la presencia de asimetrías y colas pesadas en la distribución de los retornos, rasgos típicos de mercados accionarios con fuerte liquidez y exposición a shocks externos.
En cuanto al modelado, el ARIMA(0,1,0) con drift fue seleccionado como la especificación más adecuada según los criterios AIC, AICc y BIC. El análisis de residuos mostró que los errores se comportan como ruido blanco, sin autocorrelación significativa y con distribución aproximadamente simétrica, aunque con colas pesadas. Esto indica que el modelo captura adecuadamente la estructura temporal básica de la serie y que es estadísticamente válido para realizar pronósticos de corto plazo.
Los pronósticos generados, correspondientes a cinco días posteriores al periodo de entrenamiento, mostraron valores coherentes con la tendencia reciente y se mantuvieron dentro de los intervalos de confianza del 95 %. Esto implica que, aunque el modelo no predice movimientos bruscos, sí ofrece una proyección razonable bajo condiciones normales del mercado. En términos prácticos, estas predicciones pueden servir como referencia para inversionistas o analistas que requieran estimaciones basadas únicamente en el historial de precios, especialmente en horizontes cortos donde los modelos ARIMA suelen ser más fiables.
No obstante, el análisis también presenta limitaciones. En primer lugar, los modelos ARIMA no incorporan información externa, como noticias, decisiones de política monetaria, eventos macroeconómicos o cambios estratégicos de la empresa, factores que pueden generar variaciones abruptas en los precios financieros. Además, la presencia de colas pesadas sugiere que la serie contiene eventos extremos que podrían modelarse mejor mediante enfoques alternativos, que capturan de manera más adecuada la volatilidad condicional. Finalmente, el pronóstico a mayor plazo se vuelve rápidamente impreciso debido al ensanchamiento de los intervalos, característica inherente a los modelos basados en caminatas aleatorias.
Para futuros estudios, se recomienda complementar el enfoque ARIMA con modelos de volatilidad, incorporar variables exógenas relevantes o explorar arquitecturas más complejas como modelos híbridos o redes neuronales recurrentes. Estas mejoras permitirían obtener pronósticos más robustos y profundizar en la comprensión del comportamiento del precio de la acción en escenarios de alta incertidumbre.
DataCamp. (s.f.). ARIMA para la previsión de series temporales: Guía completa. Recuperado de https://www.datacamp.com/es/tutorial/arima
Minitab. (2025). ¿Qué es una serie de tiempo? Minitab Support. https://support.minitab.com/es-mx/minitab/help-and-how-to/statistical-modeling/time-series/supporting-topics/basics/what-is-a-time-series/
Morpher. (2024, 24 de septiembre). ARIMA explicado: cómo el modelo de promedio móvil integrado autorregresivo predice las tendencias del mercado. Morpher. https://www.morpher.com/es/blog/arima-explained