Interpretación:
[Escribir aquí una breve introducción sobre la metodología Box-Jenkins y la variable analizada: tipo de cambio USD/JPY.]
# Abre explorador de archivos para seleccionar el Excel
ruta_excel <- file.choose()
df <- read_excel(ruta_excel)
# Renombrar columnas
colnames(df) <- c("fecha", "precio")
# Convertir fecha y ordenar de más antiguo a más reciente
df$fecha <- as.Date(df$fecha)
df <- df[order(df$fecha), ]
df <- df[!is.na(df$precio), ]
# Crear objeto xts
P <- xts(df$precio, order.by = df$fecha)
colnames(P) <- "JPY.Open"
# Retornos logarítmicos
r <- diff(log(P))
r <- na.omit(r)
r_pct <- 100 * r
cat("Observaciones (precio):", nrow(P), "\n")## Observaciones (precio): 522
## Período: 2024-03-18 a 2026-03-17
##
## Estadísticas básicas de los retornos:
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## -0.0233568 -0.0032917 0.0004155 0.0001258 0.0035946 0.0199993
Interpretación:
[Describir brevemente la base de datos: período, frecuencia, número de observaciones y variable utilizada.]
La metodología Box-Jenkins inicia con el análisis visual de la serie y sus funciones de autocorrelación para determinar si la serie es estacionaria y seleccionar los órdenes iniciales del modelo ARIMA(p, d, q).
op <- par(no.readonly = TRUE)
par(mfrow = c(2,1), mar = c(3,4,3,2))
plot(P,
type = "l", col = "#2C3E50", lwd = 1.2,
main = "USD/JPY — Precio en Niveles",
xlab = "", ylab = "JPY por USD")
grid(col = "lightgray", lty = "dotted")
plot(r_pct,
type = "l", col = "#E74C3C", lwd = 0.8,
main = "USD/JPY — Retornos Logarítmicos Diarios (%)",
xlab = "", ylab = "Retorno (%)")
abline(h = 0, lty = 2, col = "gray50")
grid(col = "lightgray", lty = "dotted")Interpretación:
[Describir el comportamiento visual de la serie en niveles (tendencia, varianza) y de los retornos (estacionariedad aparente, clustering de volatilidad).]
op <- par(no.readonly = TRUE)
par(mfrow = c(1,2), mar = c(4,4,3,2))
acf(as.numeric(P),
lag.max = 40,
main = "ACF — Precio en Niveles",
col = "#2C3E50")
pacf(as.numeric(P),
lag.max = 40,
main = "PACF — Precio en Niveles",
col = "#2C3E50")Interpretación:
[Analizar si la ACF decae lentamente (señal de no estacionariedad / raíz unitaria) o rápidamente (estacionariedad).]
op <- par(no.readonly = TRUE)
par(mfrow = c(1,2), mar = c(4,4,3,2))
acf(as.numeric(r),
lag.max = 40,
main = "ACF — Retornos Log",
col = "#27AE60")
pacf(as.numeric(r),
lag.max = 40,
main = "PACF — Retornos Log",
col = "#27AE60")Interpretación:
[Analizar el patrón de la ACF y PACF de los retornos para identificar posibles órdenes AR(p) y MA(q). Indicar si los retornos parecen estacionarios en media.]
La prueba ADF contrasta:
Regla: Se rechaza \(H_0\) si el estadístico es más negativo que el valor crítico.
## === ADF — Precio en Niveles ===
##
## Augmented Dickey-Fuller Test
##
## data: as.numeric(P)
## Dickey-Fuller = -1.8319, Lag order = 8, p-value = 0.6495
## alternative hypothesis: stationary
##
## === ADF urca — Precio con drift ===
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression drift
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.4965 -0.5302 0.0776 0.5520 2.8178
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.439999 1.311035 1.861 0.0633 .
## z.lag.1 -0.016021 0.008658 -1.850 0.0649 .
## z.diff.lag1 -0.011018 0.044872 -0.246 0.8061
## z.diff.lag2 0.062390 0.044756 1.394 0.1639
## z.diff.lag3 -0.016521 0.044844 -0.368 0.7127
## z.diff.lag4 -0.032834 0.044852 -0.732 0.4645
## z.diff.lag5 -0.029079 0.044876 -0.648 0.5173
## z.diff.lag6 0.013096 0.044847 0.292 0.7704
## z.diff.lag7 0.051179 0.044784 1.143 0.2537
## z.diff.lag8 0.025898 0.044811 0.578 0.5636
## z.diff.lag9 -0.052731 0.044650 -1.181 0.2382
## z.diff.lag10 0.062302 0.044692 1.394 0.1639
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.9419 on 499 degrees of freedom
## Multiple R-squared: 0.02229, Adjusted R-squared: 0.0007376
## F-statistic: 1.034 on 11 and 499 DF, p-value: 0.4144
##
##
## Value of test-statistic is: -1.8503 1.7802
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.43 -2.86 -2.57
## phi1 6.43 4.59 3.78
Interpretación:
[Indicar si se rechaza o no H0 y concluir si la serie de precios es estacionaria o tiene raíz unitaria.]
## === ADF — Retornos Logarítmicos ===
##
## Augmented Dickey-Fuller Test
##
## data: as.numeric(r)
## Dickey-Fuller = -7.9279, Lag order = 8, p-value = 0.01
## alternative hypothesis: stationary
##
## === ADF urca — Retornos con drift ===
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression drift
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.0233819 -0.0032929 0.0004574 0.0037562 0.0192855
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.0000936 0.0002788 0.336 0.737
## z.lag.1 -1.0070154 0.1533322 -6.568 1.29e-10 ***
## z.diff.lag1 -0.0154155 0.1463515 -0.105 0.916
## z.diff.lag2 0.0381276 0.1380828 0.276 0.783
## z.diff.lag3 0.0106605 0.1303366 0.082 0.935
## z.diff.lag4 -0.0364939 0.1218032 -0.300 0.765
## z.diff.lag5 -0.0751476 0.1118879 -0.672 0.502
## z.diff.lag6 -0.0639676 0.1008631 -0.634 0.526
## z.diff.lag7 -0.0217516 0.0892912 -0.244 0.808
## z.diff.lag8 -0.0088784 0.0772262 -0.115 0.909
## z.diff.lag9 -0.0762417 0.0639340 -1.193 0.234
## z.diff.lag10 -0.0201322 0.0448597 -0.449 0.654
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.006289 on 498 degrees of freedom
## Multiple R-squared: 0.5204, Adjusted R-squared: 0.5098
## F-statistic: 49.13 on 11 and 498 DF, p-value: < 2.2e-16
##
##
## Value of test-statistic is: -6.5675 21.5665
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.43 -2.86 -2.57
## phi1 6.43 4.59 3.78
Interpretación:
[Concluir si los retornos son estacionarios y determinar el orden de integración d para el modelo ARIMA.]
La prueba de Ljung-Box evalúa si existe autocorrelación conjunta hasta el rezago \(h\):
## === Ljung-Box — Retornos (lag = 20) ===
##
## Box-Ljung test
##
## data: as.numeric(r)
## X-squared = 18.249, df = 20, p-value = 0.571
##
## === Ljung-Box — Retornos² / Efecto ARCH (lag = 20) ===
##
## Box-Ljung test
##
## data: as.numeric(r)^2
## X-squared = 38.93, df = 20, p-value = 0.006801
Interpretación:
[Indicar si existe autocorrelación en los retornos (justifica ARIMA) y si existe efecto ARCH en los retornos al cuadrado (justifica GARCH).]
Con base en los patrones de ACF y PACF se proponen y estiman modelos ARIMA candidatos.
## === ARIMA automático — criterio BIC ===
fit_bic <- auto.arima(as.numeric(r),
seasonal = FALSE,
ic = "bic",
stepwise = FALSE,
approximation = FALSE)
summary(fit_bic)## Series: as.numeric(r)
## ARIMA(0,0,0) with zero mean
##
## sigma^2 = 3.876e-05: log likelihood = 1906.91
## AIC=-3811.83 AICc=-3811.82 BIC=-3807.57
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 0.0001257654 0.006225865 0.004666557 100 100 0.687792 -0.02334172
## === ARIMA automático — criterio AIC ===
fit_aic <- auto.arima(as.numeric(r),
seasonal = FALSE,
ic = "aic",
stepwise = FALSE,
approximation = FALSE)
summary(fit_aic)## Series: as.numeric(r)
## ARIMA(0,0,0) with zero mean
##
## sigma^2 = 3.876e-05: log likelihood = 1906.91
## AIC=-3811.83 AICc=-3811.82 BIC=-3807.57
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 0.0001257654 0.006225865 0.004666557 100 100 0.687792 -0.02334172
fit_100 <- Arima(r, order = c(1,0,0))
fit_001 <- Arima(r, order = c(0,0,1))
fit_101 <- Arima(r, order = c(1,0,1))
tabla_modelos <- data.frame(
Modelo = c("ARIMA(1,0,0)", "ARIMA(0,0,1)", "ARIMA(1,0,1)"),
AIC = round(c(AIC(fit_100), AIC(fit_001), AIC(fit_101)), 2),
BIC = round(c(BIC(fit_100), BIC(fit_001), BIC(fit_101)), 2),
LogLik = round(c(as.numeric(logLik(fit_100)),
as.numeric(logLik(fit_001)),
as.numeric(logLik(fit_101))), 2)
)
cat("=== Comparación de modelos candidatos ===\n\n")## === Comparación de modelos candidatos ===
## Modelo AIC BIC LogLik
## 1 ARIMA(1,0,0) -3808.32 -3795.56 1907.16
## 2 ARIMA(0,0,1) -3808.30 -3795.53 1907.15
## 3 ARIMA(1,0,1) -3807.45 -3790.43 1907.73
##
## Nota: Menor AIC/BIC indica mejor ajuste
Interpretación:
[Comparar los modelos según AIC y BIC. Indicar cuál modelo es preferido y por qué. Discutir si los coeficientes son estadísticamente significativos.]
Una vez estimado el modelo, se verifica que los residuales sean ruido blanco: media cero, varianza constante y sin autocorrelación.
op <- par(no.readonly = TRUE)
par(mfrow = c(1,2), mar = c(4,4,3,2))
acf(as.numeric(res),
lag.max = 35,
main = "ACF — Residuales del Modelo",
col = "#2980B9")
pacf(as.numeric(res),
lag.max = 35,
main = "PACF — Residuales del Modelo",
col = "#2980B9")Interpretación:
[Verificar si la ACF y PACF de los residuales muestran barras dentro de las bandas de confianza. Si es así, los residuales son ruido blanco en media.]
## === Ljung-Box — Residuales en media (lag = 20) ===
##
## Box-Ljung test
##
## data: as.numeric(res)
## X-squared = 18.211, df = 20, p-value = 0.5735
##
## === Ljung-Box — Residuales² / Efecto ARCH (lag = 20) ===
##
## Box-Ljung test
##
## data: as.numeric(res)^2
## X-squared = 40.245, df = 20, p-value = 0.004651
Interpretación:
[Si p-valor > 0.05 en residuales: modelo adecuado en media. Si p-valor < 0.05 en residuales²: existe efecto ARCH, justifica GARCH.]
op <- par(no.readonly = TRUE)
par(mfrow = c(1,2), mar = c(4,4,3,2))
acf(as.numeric(res)^2,
lag.max = 35,
main = "ACF — Residuales² (Volatilidad)",
col = "#E67E22")
pacf(as.numeric(res)^2,
lag.max = 35,
main = "PACF — Residuales² (Volatilidad)",
col = "#E67E22")Interpretación:
[Si hay barras significativas y persistentes en la ACF de residuales², confirma clustering de volatilidad y justifica pasar a un modelo GARCH.]
tabla_diag <- data.frame(
Prueba = c(
"Ljung-Box Retornos (media)",
"Ljung-Box Retornos² (ARCH)",
"Ljung-Box Residuales (media)",
"Ljung-Box Residuales² (ARCH)"
),
Estadístico = round(c(
lb_r$statistic,
lb_r2$statistic,
lb_res$statistic,
lb_res2$statistic
), 3),
p_valor = round(c(
lb_r$p.value,
lb_r2$p.value,
lb_res$p.value,
lb_res2$p.value
), 4),
Decision = c(
ifelse(lb_r$p.value < 0.05, "Rechaza H0", "No rechaza H0"),
ifelse(lb_r2$p.value < 0.05, "Rechaza H0", "No rechaza H0"),
ifelse(lb_res$p.value < 0.05, "Rechaza H0", "No rechaza H0"),
ifelse(lb_res2$p.value< 0.05, "Rechaza H0", "No rechaza H0")
)
)
print(tabla_diag, row.names = FALSE)## Prueba Estadístico p_valor Decision
## Ljung-Box Retornos (media) 18.249 0.5710 No rechaza H0
## Ljung-Box Retornos² (ARCH) 38.930 0.0068 Rechaza H0
## Ljung-Box Residuales (media) 18.211 0.5735 No rechaza H0
## Ljung-Box Residuales² (ARCH) 40.245 0.0047 Rechaza H0
Interpretación:
[Resumir el diagnóstico completo: si la media está bien especificada y si se requiere modelar la varianza condicional con GARCH.]
Dado que los residuales al cuadrado presentan autocorrelación, los modelos ARIMA son insuficientes para capturar la dinámica de la varianza. Se estima un modelo GARCH(1,1):
\[r_t = \mu + \varphi_1 r_{t-1} + \varepsilon_t\] \[\sigma_t^2 = \omega + \alpha_1 \varepsilon_{t-1}^2 + \beta_1 \sigma_{t-1}^2\] \[\varepsilon_t = \sigma_t z_t, \quad z_t \sim t_\nu\]
r_vec <- as.numeric(na.omit(r))
spec_garch <- ugarchspec(
variance.model = list(model = "sGARCH", garchOrder = c(1,1)),
mean.model = list(armaOrder = c(1,0), include.mean = TRUE),
distribution.model = "std"
)
fit_garch <- ugarchfit(spec = spec_garch, data = r_vec)
show(fit_garch)##
## *---------------------------------*
## * GARCH Model Fit *
## *---------------------------------*
##
## Conditional Variance Dynamics
## -----------------------------------
## GARCH Model : sGARCH(1,1)
## Mean Model : ARFIMA(1,0,0)
## Distribution : std
##
## Optimal Parameters
## ------------------------------------
## Estimate Std. Error t value Pr(>|t|)
## mu 0.000460 0.000221 2.07776 0.037731
## ar1 -0.047556 0.044702 -1.06385 0.287398
## omega 0.000003 0.000008 0.32606 0.744379
## alpha1 0.116144 0.041745 2.78219 0.005399
## beta1 0.827840 0.120427 6.87422 0.000000
## shape 5.150662 1.884037 2.73384 0.006260
##
## Robust Standard Errors:
## Estimate Std. Error t value Pr(>|t|)
## mu 0.000460 0.000268 1.717041 0.085972
## ar1 -0.047556 0.041558 -1.144327 0.252488
## omega 0.000003 0.000091 0.029546 0.976429
## alpha1 0.116144 0.055115 2.107279 0.035093
## beta1 0.827840 1.252632 0.660880 0.508689
## shape 5.150662 16.150952 0.318908 0.749797
##
## LogLikelihood : 1932.802
##
## Information Criteria
## ------------------------------------
##
## Akaike -7.3966
## Bayes -7.3475
## Shibata -7.3968
## Hannan-Quinn -7.3774
##
## Weighted Ljung-Box Test on Standardized Residuals
## ------------------------------------
## statistic p-value
## Lag[1] 0.05318 0.8176
## Lag[2*(p+q)+(p+q)-1][2] 0.29329 0.9947
## Lag[4*(p+q)+(p+q)-1][5] 0.80696 0.9715
## d.o.f=1
## H0 : No serial correlation
##
## Weighted Ljung-Box Test on Standardized Squared Residuals
## ------------------------------------
## statistic p-value
## Lag[1] 0.4229 0.5155
## Lag[2*(p+q)+(p+q)-1][5] 0.6425 0.9336
## Lag[4*(p+q)+(p+q)-1][9] 2.5172 0.8352
## d.o.f=2
##
## Weighted ARCH LM Tests
## ------------------------------------
## Statistic Shape Scale P-Value
## ARCH Lag[3] 0.01502 0.500 2.000 0.9025
## ARCH Lag[5] 0.41621 1.440 1.667 0.9080
## ARCH Lag[7] 2.47644 2.315 1.543 0.6173
##
## Nyblom stability test
## ------------------------------------
## Joint Statistic: 7.3817
## Individual Statistics:
## mu 0.11878
## ar1 0.07995
## omega 0.32955
## alpha1 0.18294
## beta1 0.19032
## shape 0.26733
##
## Asymptotic Critical Values (10% 5% 1%)
## Joint Statistic: 1.49 1.68 2.12
## Individual Statistic: 0.35 0.47 0.75
##
## Sign Bias Test
## ------------------------------------
## t-value prob sig
## Sign Bias 1.1922 0.2337
## Negative Sign Bias 0.4103 0.6818
## Positive Sign Bias 1.1090 0.2680
## Joint Effect 2.8917 0.4086
##
##
## Adjusted Pearson Goodness-of-Fit Test:
## ------------------------------------
## group statistic p-value(g-1)
## 1 20 14.16 0.7741
## 2 30 24.12 0.7228
## 3 40 41.69 0.3547
## 4 50 49.54 0.4517
##
##
## Elapsed time : 0.3373079
Interpretación:
[Interpretar los parámetros: omega (varianza de largo plazo), alpha1 (impacto de noticias/shocks), beta1 (persistencia de la volatilidad), shape (grados de libertad t-Student). Indicar significancia estadística de cada uno.]
coef_g <- coef(fit_garch)
alpha1 <- coef_g["alpha1"]
beta1 <- coef_g["beta1"]
pers <- alpha1 + beta1
cat("alpha1:", round(alpha1, 6), "\n")## alpha1: 0.116144
## beta1 : 0.82784
## Persistencia (alpha + beta): 0.943984
Interpretación:
[Comentar el nivel de persistencia: si alpha + beta es cercano a 1, la volatilidad es muy persistente. Relacionar con el comportamiento de divisas.]
res_std <- residuals(fit_garch, standardize = TRUE)
res_std2 <- res_std^2
cat("=== Ljung-Box — Residuales estandarizados (media) ===\n")## === Ljung-Box — Residuales estandarizados (media) ===
##
## Box-Ljung test
##
## data: as.numeric(res_std)
## X-squared = 12.527, df = 20, p-value = 0.8967
##
## === Ljung-Box — Residuales estandarizados² (varianza) ===
##
## Box-Ljung test
##
## data: as.numeric(res_std2)
## X-squared = 9.3679, df = 20, p-value = 0.9782
Interpretación:
[Si ambos p-valores > 0.05, el modelo GARCH es adecuado: capturó tanto la dinámica de la media como la de la varianza condicional.]
sigma_t <- sigma(fit_garch)
fechas <- index(r)
op <- par(no.readonly = TRUE)
par(mfrow = c(2,1), mar = c(3,4,3,2))
plot(fechas, as.numeric(r_pct),
type = "l", col = "#7F8C8D", lwd = 0.7,
main = "Retornos Diarios USD/JPY (%)",
xlab = "", ylab = "Retorno (%)")
abline(h = 0, lty = 2, col = "gray40")
grid(col = "lightgray", lty = "dotted")
plot(fechas, sigma_t * 100,
type = "l", col = "#C0392B", lwd = 1.2,
main = "Volatilidad Condicional Estimada — GARCH(1,1)",
xlab = "", ylab = "Volatilidad (%)")
grid(col = "lightgray", lty = "dotted")Interpretación:
[Identificar períodos de alta y baja volatilidad en la serie. Relacionar los picos de volatilidad con eventos económicos o geopolíticos relevantes (ej. COVID-19, crisis financieras, decisiones de política monetaria del Banco de Japón).]
[Escribir las conclusiones del análisis siguiendo los 4 pasos de Box-Jenkins:
1. Identificación: ¿La serie es estacionaria? ¿Qué indica la ACF/PACF? 2. Estimación: ¿Qué modelo ARIMA fue seleccionado? ¿Son significativos los coeficientes? 3. Diagnóstico: ¿Los residuales son ruido blanco? ¿Hay efecto ARCH? 4. Extensión GARCH: ¿El modelo captura adecuadamente la volatilidad condicional?]
Informe elaborado con R Markdown — Pontificia Universidad Javeriana Cali | Programa Finanzas