← Catálogo
· Capítulo 11
T11_mST_Script_EvaluacionPredicciones.R
# ══════════════════════════════════════════════════
# T11 · Series Temporales — Evaluación y Combinación de Predicciones
# Abre primero mSeriesTemporales.Rproj en RStudio
# ══════════════════════════════════════════════════
library(tidyverse)
library(forecast)
pausa <- function(msg = "\n [Pulsa ENTER para continuar...]") {
if (interactive()) { cat(msg); invisible(readline()) }
}
set.seed(2026)
# ── 1. MASE: EJEMPLO SOBRE UNA SERIE SIMULADA ─────
y <- ts(50 + cumsum(rnorm(150, mean = 0.2, sd = 1)) + 3 * sin(2 * pi * (1:150) / 12), frequency = 12)
naive_err <- diff(y, lag = 12)
mae_naive <- mean(abs(naive_err))
m_ets_sim <- ets(y)
mase_ets <- mean(abs(residuals(m_ets_sim))) / mae_naive
cat(sprintf("MAE naive estacional = %.3f | MASE del ETS ajustado = %.3f\n", mae_naive, mase_ets))
pausa()
# ── 2. VALIDACION CRUZADA TEMPORAL (tsCV) ─────────
f_ets <- function(x, h) forecast(ets(x), h = h)
f_naive_est <- function(x, h) snaive(x, h = h)
e_ets <- tsCV(y, f_ets, h = 1, window = 60)
e_naive <- tsCV(y, f_naive_est, h = 1, window = 60)
rmse <- function(e) sqrt(mean(e^2, na.rm = TRUE))
cat(sprintf("RMSE (rolling-origin): ETS=%.3f naive estacional=%.3f\n", rmse(e_ets), rmse(e_naive)))
pausa()
# ── 3. CONTRASTE DE DIEBOLD-MARIANO ───────────────
comun <- !is.na(e_ets) & !is.na(e_naive)
dm <- dm.test(e_ets[comun], e_naive[comun], h = 1, power = 2)
cat(sprintf("DM ETS vs naive: estadistico=%.3f p-valor=%.4f\n", dm$statistic, dm$p.value))
cat(ifelse(dm$p.value < 0.05,
"-> El ETS predice significativamente mejor que el naive estacional.\n",
"-> No hay evidencia suficiente de que el ETS supere al naive estacional.\n"))
pausa()
# ── 4. COMBINACION DE PREDICCIONES: PESO OPTIMO BATES-GRANGER ─
f_holt <- function(x, h) forecast::holt(x, h = h)
e_holt <- tsCV(y, f_holt, h = 1, window = 60)
comun2 <- !is.na(e_ets) & !is.na(e_holt)
idx <- which(comun2)
mitad <- floor(length(idx) / 2)
idx1 <- idx[1:mitad]; idx2 <- idx[(mitad + 1):length(idx)]
s1 <- sd(e_ets[idx1]); s2 <- sd(e_holt[idx1]); rho <- cor(e_ets[idx1], e_holt[idx1])
w_star <- (s2^2 - rho * s1 * s2) / (s1^2 + s2^2 - 2 * rho * s1 * s2)
cat(sprintf("Peso optimo (ETS) = %.3f | sigma_ets=%.3f sigma_holt=%.3f rho=%.3f\n", w_star, s1, s2, rho))
actual <- as.numeric(y)
fc_ets <- actual - as.numeric(e_ets)
fc_holt <- actual - as.numeric(e_holt)
e_opt <- actual[idx2] - (w_star * fc_ets[idx2] + (1 - w_star) * fc_holt[idx2])
e_eq <- actual[idx2] - (0.5 * fc_ets[idx2] + 0.5 * fc_holt[idx2])
cat(sprintf("RMSE fuera de muestra: ETS solo=%.3f Holt solo=%.3f Combo optimo=%.3f Combo igual=%.3f\n",
rmse(e_ets[idx2]), rmse(e_holt[idx2]), rmse(e_opt), rmse(e_eq)))
# === FIN Script T11 — Evaluación y Combinación de Predicciones ===