El presente informe tiene como objetivo brindar un análisis cuantitativo para apoyar decisiones de inversión en el mercado bursátil colombiano, enfocado en cuatro segmentos estratégicos: petrolero, financiero, industrial y de servicios. El análisis se desarrolla en el marco del índice MSCI COLCAP, utilizando como referencia una acción representativa por cada sector.
Para ello, se emplean herramientas estadísticas y de analítica de datos, fundamentadas en métodos de pronóstico y teoría de la decisión. Los cálculos se basan en datos mensuales de precios de acciones y del Índice de Precios al Consumidor (IPC), lo cual permite establecer escenarios económicos realistas: favorables, estables y en declive, basados en niveles de inflación.
Se aplican diferentes modelos de pronóstico como promedios móviles, suavización exponencial, regresiones polinómicas y modelos ARIMA, con el fin de estimar los rendimientos esperados por acción bajo cada condición económica. Además, se calculan medidas de error para evaluar la precisión de los modelos.
El análisis se complementa con la construcción de un árbol de decisión, el cálculo del valor esperado (EV) por segmento y la realización de simulaciones de Monte Carlo, lo cual permite estimar el comportamiento futuro del portafolio bajo incertidumbre.
El resultado de este informe permitirá al inversionista, que dispone de $100 millones de pesos colombianos, tomar decisiones estratégicas con base en métricas cuantitativas, evaluando no solo el rendimiento potencial, sino también el riesgo asociado a cada alternativa.
Para el desarrollo del presente estudio, se construyeron 7 datas frames consolidados con información mensual desde mayo de 2015 hasta abril de 2025, el cual constituye la base del análisis cuantitativo; Estos datos fueron obtenidos de las siguientes pagínas web:
Investing.com: es una plataforma de mercados financieros que proporciona datos en tiempo real, cotizaciones, gráficos, herramientas financieras, noticias de última hora y análisis de 250 mercados del mundo a través de sus 44 ediciones internacionales.
datosmacro.expansion.com: es un sitio web que reúne en un solo lugar todos los datos macroeconómicos. Ofrece información sobre el PIB, la inflación, ratings, deuda, hipotecas, paro, prima de riesgo, salarios, divisas y más, de forma sencilla de consultar. El objetivo es proporcionar una visión global de la situación económica en cada momento y en cada país.
Gracias a los datos obtenidos de estas páginas, creamos los siguientes conjunto de datos:
Este data frame presenta la información mensual histórica de la acción ARG (Grupo Argos S.A.), empresa clave del sector industrial colombiano. La serie abarca desde mayo de 2015 hasta abril de 2025, proporcionando una base sólida para el análisis de tendencias, pronósticos, simulaciones de retorno y evaluación de escenarios económicos.
Columna | Descripción |
---|---|
Fecha |
Último día hábil de cada mes. |
Último |
Precio de cierre de la acción al finalizar el mes (COP). |
Apertura |
Precio de apertura del mes. |
Máximo |
Precio más alto alcanzado durante el mes. |
Mínimo |
Precio más bajo registrado en el mes. |
Vol. |
Volumen mensual negociado (en millones o miles de acciones). |
% var. |
Variación porcentual mensual del precio de cierre respecto al mes anterior. |
Rendimientos ARG |
Rendimiento mensual calculado como: |
\[ \left( \frac{P_t - P_{t-1}}{P_{t-1}} \right) \times 100 \]
Nota: Aunque
% var.
yRendimientos EC
son muy similares, se incluyen ambas columnas para trazabilidad. En el análisis se tomaRendimientos EC
como la fuente oficial de retorno mensual; ya que la columna% var.
es la columna que por defecto se descargo de la página web
Vol.
(Volumen) necesita transformación para su
uso en cálculos (formato abreviado como “5,05M”).Vamos a pronosticar los precios de cierre de las acciones seleccionadas utilizando diferentes métodos estadísticos y de series temporales. Para ello, se aplicaran técnicas como promedios móviles, suavización exponencial, análisis de índices estacionales, regresiones polinómicas, análisis de correlación y modelos ARIMA. Después de obtener las predicciones con cada método, se calculan las medidas de error de pronóstico (como MAE, RMSE, MAPE, etc.) para evaluar y comparar la precisión de cada técnica en cada acción.
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
##
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
## Cargando paquete requerido: greybox
## Package "greybox", v2.0.4 loaded.
## This is package "smooth", v4.2.0
Grupo Argos es uno de los conglomerados empresariales más importantes de Colombia, con un enfoque estratégico en infraestructura. Es una holding de inversiones con presencia en los sectores de cemento, energía y concesiones viales y aeroportuarias. Su sede principal está en Medellín y tiene operaciones en América Latina y Estados Unidos.
# Cargar los datos
library(readxl)
Caso1 <- read_excel("Caso1.xlsx", sheet = "DatoshistoricosGrupoArgos")
(Caso1)
# Detectar año y mes de inicio
fecha_inicio <- min(Caso1$Fecha, na.rm = TRUE)
anio_inicio <- as.numeric(format(fecha_inicio, "%Y"))
mes_inicio <- as.numeric(format(fecha_inicio, "%m"))
# Convertir la columna Ultimo a numérica (aunque ya vimos que tiene 120 validos, no está de más ser explícito)
Caso1$`Rendimientos ARG` <- as.numeric(Caso1$`Rendimientos ARG`)
# Crear las series temporales con fecha correcta
# Asegúrate de que los datos estén ordenados por fecha si read_excel no lo garantiza
# Caso1 <- Caso1[order(Caso1$Fecha),] # Esto podría ser necesario si los datos no están ya ordenados
y <- ts(Caso1$`Rendimientos ARG`, frequency = 12, start = c(anio_inicio, mes_inicio))
# Fechas para graficar (aunque ts.plot puede manejar el eje x temporalmente)
# La variable 'fechas' no es estrictamente necesaria para ts.plot, pero puede ser util para otras graficas
fechas <- seq(as.Date(fecha_inicio), length.out = length(y), by = "months")
# Graficar con título, ejes y color
ts.plot(y,
main = "Gráfico historico de los rendimientos de las acciones de Grupo Argos", # Título del gráfico
xlab = "Fecha", # Nombre del eje X
ylab = "Rendimientos", # Nombre del eje Y
col = "blue" # Color de la línea (puedes cambiar "blue" por otro color)
)
Se puede hacer el siguiente análisis de la serie de tiempo:
Tendencia: : La serie no presenta una tendencia clara de crecimiento o descenso sostenido. En lugar de ello, se mantiene relativamente estable, con fluctuaciones que giran en torno a un valor central. No hay evidencia de un incremento o disminución sostenida en el tiempo.
Irregularidad: Se detectan variaciones aleatorias y cambios bruscos en los rendimientos sin un patrón definido. Estos picos y caídas repentinas reflejan la presencia de ruido en la serie, lo que puede estar influenciado por eventos inesperados o factores externos.
Estacionalidad: No se identifican patrones recurrentes en intervalos fijos como ciclos anuales o mensuales. Los picos y valles no parecen repetirse de manera consistente en momentos específicos, lo que sugiere una baja estacionalidad.
Ciclicidad: Existen fluctuaciones a largo plazo sin periodicidad fija. Se observan periodos de alta volatilidad, como en 2018 y 2020, seguidos por fases de menor variabilidad. Estas oscilaciones pueden estar relacionadas con fenómenos económicos, sociales o externos al mercado.
#Modelos de suavizamiento
#Modelo de promedios móviles
m1 <- sma(y, order = 12) # Especificamos el tamaño de la ventana a 12
f1 <- forecast(m1, h = 12) # Pronosticamos los próximos 12 meses
plot(forecast(m1))
# Ajustar el modelo de suavización exponencial simple
m2 <- ces(y, seasonality = "none") # No especificamos h aquí, ces ajustará el mejor modelo SES
# Definir cuántos períodos quieres pronosticar hacia el futuro (h) - DEBES ELEGIR UN NÚMERO
periodos_pronostico_ses <- 12 # Ejemplo: pronosticar los próximos 12 meses
# Generar el pronóstico usando la función forecast()
f2 <- forecast(m2, h = periodos_pronostico_ses) # Especificamos h aquí
# Imprimir el resumen del pronóstico
print(f2)
## Jan Feb Mar Apr May
## 2025 -1.119965e-02
## 2026 -1.076564e-04 -1.032720e-04 -9.906616e-05 -9.503162e-05
## Jun Jul Aug Sep Oct
## 2025 -3.109341e-05 -1.393144e-04 -1.325217e-04 -1.271361e-04 -1.219583e-04
## 2026
## Nov Dec
## 2025 -1.169914e-04 -1.122269e-04
## 2026
# Ajustar el modelo de suavización exponencial con estacionalidad simple
m3 <- ces(y, seasonality = "simple") # ces ajustará el mejor modelo SES con estacionalidad
# Definir cuántos períodos quieres pronosticar hacia el futuro (h) - DEBES ELEGIR UN NÚMERO
periodos_pronostico_ses_s <- 12 # Ejemplo: pronosticar los próximos 12 meses (ajusta este valor)
# Generar el pronóstico usando la función forecast()
f3 <- forecast(m3, h = periodos_pronostico_ses_s) # Especificamos h aquí
# Imprimir el resumen del pronóstico
print(f3)
## Jan Feb Mar Apr May
## 2025 -0.010264528
## 2026 0.001712582 -0.011509383 0.034417143 -0.028644767
## Jun Jul Aug Sep Oct
## 2025 0.006744420 -0.016636837 0.018479810 0.045781874 0.013767965
## 2026
## Nov Dec
## 2025 0.013951614 0.005360677
## 2026
# Ajustar el modelo de suavización exponencial con estacionalidad parcial
m4 <- ces(y, seasonality = "partial") # ces ajustará el mejor modelo con estacionalidad parcial
# Definir cuántos períodos quieres pronosticar hacia el futuro (h)
periodos_pronostico_ces_p <- 12 # Pronosticamos los próximos 12 meses
# Generar el pronóstico usando la función forecast()
f4 <- forecast(m4, h = periodos_pronostico_ces_p) # Especificamos h aquí
# Imprimir el resumen del pronóstico
print(f4)
## Jan Feb Mar Apr May
## 2025 -0.041917994
## 2026 -0.003673710 -0.026686108 0.036389665 -0.030962608
## Jun Jul Aug Sep Oct
## 2025 -0.006985121 -0.038722142 0.034421113 0.059345414 0.019156936
## 2026
## Nov Dec
## 2025 0.001244631 -0.010479856
## 2026
# Ajustar el modelo de suavización exponencial con estacionalidad completa
m5 <- ces(y, seasonality = "full") # ces ajustará el mejor modelo con estacionalidad completa (Holt-Winters similar)
# Definir cuántos períodos quieres pronosticar hacia el futuro (h)
periodos_pronostico_ces_f <- 12 # Pronosticamos los próximos 12 meses
# Generar el pronóstico usando la función forecast()
f5 <- forecast(m5, h = periodos_pronostico_ces_f) # Especificamos h aquí
# Imprimir el resumen del pronóstico
print(f5)
## Jan Feb Mar Apr May
## 2025 -0.036446611
## 2026 -0.002272794 -0.021858308 0.025305569 -0.020970125
## Jun Jul Aug Sep Oct
## 2025 -0.004013020 -0.028926519 0.028322797 0.044532318 0.011516315
## 2026
## Nov Dec
## 2025 0.001016955 -0.010198384
## 2026
## Jan Feb Mar Apr May
## 2025 -0.036446611
## 2026 -0.002272794 -0.021858308 0.025305569 -0.020970125
## Jun Jul Aug Sep Oct
## 2025 -0.004013020 -0.028926519 0.028322797 0.044532318 0.011516315
## 2026
## Nov Dec
## 2025 0.001016955 -0.010198384
## 2026
El pronóstico mostrado en el gráfico presenta una tendencia estable, sin indicios claros de crecimiento o decrecimiento sostenido. La serie histórica exhibe una alta variabilidad con fluctuaciones pronunciadas alrededor de la media, mientras que el pronóstico muestra cambios más moderados.
No se identifican patrones estacionales evidentes en los datos históricos ni en la proyección, aunque en el pronóstico se observan leves variaciones mensuales. En particular, los valores de julio y septiembre de 2025 muestran incrementos notables, mientras que enero y mayo de 2025 presentan reducciones más marcadas. Este comportamiento podría estar reflejando ajustes derivados del modelo CES (full) utilizado.
En términos de posibles desviaciones, el pronóstico parece menos volátil que los datos históricos, lo que sugiere una expectativa de estabilidad en el comportamiento futuro de la serie. No se detectan anomalías relevantes en la proyección, y los valores previstos se mantienen dentro de un rango similar al comportamiento histórico, aunque con menor amplitud de oscilaciones.
#Modelos polinomicos y
T=length(y)
t = seq(1:T)
t2 = t^2
t3 = t^3
t4 = t^4
t5 = t^5
t6 = t^6
t7 = t^7
t8 = t^8
mlineal=lm(y~t)
summary(mlineal)
##
## Call:
## lm(formula = y ~ t)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.256301 -0.047654 0.008281 0.045956 0.180718
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.0213733 0.0151077 1.415 0.160
## t -0.0002737 0.0002167 -1.263 0.209
##
## Residual standard error: 0.08223 on 118 degrees of freedom
## Multiple R-squared: 0.01334, Adjusted R-squared: 0.004976
## F-statistic: 1.595 on 1 and 118 DF, p-value: 0.2091
##
## Call:
## lm(formula = y ~ t + t2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.244030 -0.043926 -0.000537 0.042590 0.188694
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.654e-02 2.279e-02 2.042 0.0434 *
## t -1.511e-03 8.695e-04 -1.738 0.0848 .
## t2 1.023e-05 6.961e-06 1.469 0.1444
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.08183 on 117 degrees of freedom
## Multiple R-squared: 0.03122, Adjusted R-squared: 0.01466
## F-statistic: 1.885 on 2 and 117 DF, p-value: 0.1564
#Grafico sencillo
plot(fechas,y,type="l",col="#828282")
lines(fechas,g1,col="#007bff")
lines(fechas,g2,col="#4c3d19")
## Warning in adf.test(y): p-value smaller than printed p-value
##
## Augmented Dickey-Fuller Test
##
## data: y
## Dickey-Fuller = -4.7348, Lag order = 4, p-value = 0.01
## alternative hypothesis: stationary
El Augmented Dickey-Fuller (ADF) Test evalúa si una serie temporal es estacionaria. En este caso, el estadístico Dickey-Fuller es -4.7348 y el p-value es 0.01, lo que indica que hay suficiente evidencia para rechazar la hipótesis nula de no estacionariedad. Es decir, la serie y se considera estacionaria, lo que implica que sus propiedades estadísticas, como la media y la varianza, se mantienen constantes en el tiempo.
## Series: y
## ARIMA(0,0,0) with zero mean
##
## sigma^2 = 0.006762: log likelihood = 129.51
## AIC=-257.02 AICc=-256.99 BIC=-254.23
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 0.004814813 0.08223401 0.06210902 100 100 0.668147 0.1000086
pronostico <- forecast(modelo_arima, h = 12) # Pronóstico para 12 meses
plot(pronostico, main = "Pronóstico ARIMA rendimientos Grupo Argos")
## Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
## May 2025 0 -0.1053871 0.1053871 -0.1611757 0.1611757
## Jun 2025 0 -0.1053871 0.1053871 -0.1611757 0.1611757
## Jul 2025 0 -0.1053871 0.1053871 -0.1611757 0.1611757
## Aug 2025 0 -0.1053871 0.1053871 -0.1611757 0.1611757
## Sep 2025 0 -0.1053871 0.1053871 -0.1611757 0.1611757
## Oct 2025 0 -0.1053871 0.1053871 -0.1611757 0.1611757
## Nov 2025 0 -0.1053871 0.1053871 -0.1611757 0.1611757
## Dec 2025 0 -0.1053871 0.1053871 -0.1611757 0.1611757
## Jan 2026 0 -0.1053871 0.1053871 -0.1611757 0.1611757
## Feb 2026 0 -0.1053871 0.1053871 -0.1611757 0.1611757
## Mar 2026 0 -0.1053871 0.1053871 -0.1611757 0.1611757
## Apr 2026 0 -0.1053871 0.1053871 -0.1611757 0.1611757
##
## Call:
## lm(formula = y ~ x)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.254715 -0.043762 0.008411 0.043471 0.186908
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.0005387 0.0159945 0.034 0.973
## x 0.0729497 0.2405132 0.303 0.762
##
## Residual standard error: 0.08275 on 118 degrees of freedom
## Multiple R-squared: 0.000779, Adjusted R-squared: -0.007689
## F-statistic: 0.092 on 1 and 118 DF, p-value: 0.7622
Esta correlación refleja nuevamente una ausencia total de relación lineal significativa entre x e y:
Coeficiente de x: 0.07295, muy bajo y no significativo (p = 0.762).
R² = 0.00078, es decir, x explica menos del 0.1% de la variabilidad en y.
El modelo global no es significativo (F = 0.092, p = 0.7622).
Conclusión breve: No hay relación lineal entre las variables; están prácticamente no correlacionadas.
# Calcular la correlación de Pearson
correlacion_pearson <- cor(Caso1$`Rendimientos ARG`,
Caso1$`IPC mensual`,
use = "complete.obs",
method = "pearson")
print(paste("Correlación de Pearson:", correlacion_pearson))
## [1] "Correlación de Pearson: 0.0279109264953522"
El coeficiente de Pearson 0.0279 indica una correlación positiva extremadamente débil, prácticamente inexistente.
Esto confirma los resultados del modelo lineal:
No hay relación lineal significativa entre x e y.
La asociación es tan débil que puede considerarse irrelevante tanto estadística como prácticamente.
Conclusión: Las variables son prácticamente independientes.
# Función para calcular las medidas de error
calcular_errores <- function(real, pred) {
mae <- mean(abs(real - pred))
rmse <- sqrt(mean((real - pred)^2))
mape <- mean(abs((real - pred)/real)) * 100
return(data.frame(MAE = mae, RMSE = rmse, MAPE = mape))
}
# Para cada modelo, usa los valores ajustados (fitted) o predichos (forecast)
# Ejemplo para SMA:
errores_sma <- calcular_errores(y, fitted(m1))
errores_ces <- calcular_errores(y, fitted(m2))
errores_ces_estacional <- calcular_errores(y, fitted(m3))
errores_ces_parcial <- calcular_errores(y, fitted(m4))
errores_ces_full <- calcular_errores(y, fitted(m5))
# Para modelos polinómicos:
errores_lineal <- calcular_errores(y, g1)
errores_cuadratico <- calcular_errores(y, g2)
# Para ARIMA:
errores_arima <- calcular_errores(y, fitted(modelo_arima))
# Mostrar todos los resultados en una tabla
tabla_errores <- rbind(
SMA = errores_sma,
CES = errores_ces,
CES_Estacional = errores_ces_estacional,
CES_Parcial = errores_ces_parcial,
CES_Full = errores_ces_full,
Polinomial_Lineal = errores_lineal,
Polinomial_Cuadratico = errores_cuadratico,
ARIMA = errores_arima
)
knitr::kable(tabla_errores, caption = "Medidas de error de pronóstico para cada modelo Grupo Argos")
MAE | RMSE | MAPE | |
---|---|---|---|
SMA | 0.0645758 | 0.0854368 | Inf |
CES | 0.0617069 | 0.0817707 | Inf |
CES_Estacional | 0.0613146 | 0.0798699 | Inf |
CES_Parcial | 0.0609478 | 0.0769798 | Inf |
CES_Full | 0.0600139 | 0.0767810 | Inf |
Polinomial_Lineal | 0.0611590 | 0.0815436 | Inf |
Polinomial_Cuadratico | 0.0602611 | 0.0808014 | Inf |
ARIMA | 0.0621090 | 0.0822340 | NaN |
# Para cada modelo, usa los valores ajustados (fitted) o predichos (forecast)
# EJECUTA ESTO DESPUÉS de definir la función 'calcular_errores' de nuevo
errores_sma <- calcular_errores(y, fitted(m1))
errores_ces <- calcular_errores(y, fitted(m2))
errores_ces_estacional <- calcular_errores(y, fitted(m3))
errores_ces_parcial <- calcular_errores(y, fitted(m4)) # Asegúrate de usar m4 si este es CES_Parcial
errores_ces_full <- calcular_errores(y, fitted(m5)) # Asegúrate de usar m5 si este es CES_Full
# Para modelos polinómicos:
errores_lineal <- calcular_errores(y, g1) # Asumo que g1 y g2 son los fitted/predichos
errores_cuadratico <- calcular_errores(y, g2) # Asumo que g1 y g2 son los fitted/predichos
# Para ARIMA:
errores_arima <- calcular_errores(y, fitted(modelo_arima))
# Mostrar todos los resultados en una tabla
# EJECUTA ESTO DESPUÉS de calcular todos los data.frames errores_*
tabla_errores <- rbind(
SMA = errores_sma,
CES = errores_ces,
CES_Estacional = errores_ces_estacional,
CES_Parcial = errores_ces_parcial,
CES_Full = errores_ces_full,
Polinomial_Lineal = errores_lineal,
Polinomial_Cuadratico = errores_cuadratico,
ARIMA = errores_arima
)
Al usar sMAPE, la columna de error porcentual debería mostrar valores
numéricos comparables en lugar de Inf
o NaN
,
lo que te permitirá incluir esa métrica en tu análisis de cuál modelo es
mejor.
# EJECUTA ESTO AL FINAL
knitr::kable(tabla_errores, caption = "Medidas de error de pronóstico para cada modelo Grupo Argos")
MAE | RMSE | MAPE | |
---|---|---|---|
SMA | 0.0645758 | 0.0854368 | Inf |
CES | 0.0617069 | 0.0817707 | Inf |
CES_Estacional | 0.0613146 | 0.0798699 | Inf |
CES_Parcial | 0.0609478 | 0.0769798 | Inf |
CES_Full | 0.0600139 | 0.0767810 | Inf |
Polinomial_Lineal | 0.0611590 | 0.0815436 | Inf |
Polinomial_Cuadratico | 0.0602611 | 0.0808014 | Inf |
ARIMA | 0.0621090 | 0.0822340 | NaN |
# Encontrar el índice (número de fila) del modelo con el menor valor en la columna 'RMSE'
indice_mejor_rmse <- which.min(tabla_errores$RMSE)
# Usar ese índice para obtener el nombre del modelo (el nombre de la fila)
mejor_modelo_rmse <- rownames(tabla_errores)[indice_mejor_rmse]
# Obtener todas las medidas de error para ese modelo en particular
errores_mejor_rmse <- tabla_errores[indice_mejor_rmse, ]
print("--- Mejor Modelo según RMSE (Errores de Ajuste) ---")
## [1] "--- Mejor Modelo según RMSE (Errores de Ajuste) ---"
## [1] "El modelo con el menor RMSE de ajuste es: CES_Full"
## [1] "Sus medidas de error de ajuste son:"
## MAE RMSE MAPE
## CES_Full 0.06001389 0.076781 Inf
# --- Elección del mejor modelo por cada métrica ---
# Asumimos que tabla_errores es tu data.frame con modelos como nombres de fila
# y métricas (RMSE, R2, MAE, etc.) como columnas.
# Para este ejemplo, asumimos que un valor MENOR es mejor para todas las métricas,
# excepto quizás R2 donde un valor MAYOR es mejor.
print("--- Análisis de Modelos por Métrica ---")
## [1] "--- Análisis de Modelos por Métrica ---"
# Obtener los nombres de las métricas (nombres de columna)
metricas <- colnames(tabla_errores)
# Iterar sobre cada métrica
for (metrica in metricas) {
# Determinar si un valor menor es mejor (generalmente cierto para errores)
# o si un valor mayor es mejor (como para R-squared).
# Puedes añadir lógica aquí si tienes métricas específicas que maximizar.
# Por defecto, asumimos que menor es mejor.
menor_es_mejor <- TRUE
if (metrica == "R2" || metrica == "R-squared") { # Ejemplo: R2 es mejor cuanto mayor
menor_es_mejor <- FALSE
}
if (menor_es_mejor) {
# Encontrar el índice (número de fila) del modelo con el menor valor en la métrica actual
indice_mejor_metrica <- which.min(tabla_errores[[metrica]])
criterio_mejor <- "menor"
} else {
# Encontrar el índice (número de fila) del modelo con el mayor valor en la métrica actual
indice_mejor_metrica <- which.max(tabla_errores[[metrica]])
criterio_mejor <- "mayor"
}
# Usar ese índice para obtener el nombre del modelo
mejor_modelo_metrica <- rownames(tabla_errores)[indice_mejor_metrica]
# Obtener el valor de la métrica para ese modelo
valor_mejor_metrica <- tabla_errores[indice_mejor_metrica, metrica]
# Imprimir el resultado para la métrica actual
print(paste0("El modelo con el ", criterio_mejor, " ", metrica, " es: ", mejor_modelo_metrica))
print(paste0("Su valor de ", metrica, " es: ", round(valor_mejor_metrica, 4))) # Redondeamos para mejor visualización
print("--------------------") # Separador para cada métrica
}
## [1] "El modelo con el menor MAE es: CES_Full"
## [1] "Su valor de MAE es: 0.06"
## [1] "--------------------"
## [1] "El modelo con el menor RMSE es: CES_Full"
## [1] "Su valor de RMSE es: 0.0768"
## [1] "--------------------"
## [1] "El modelo con el menor MAPE es: SMA"
## [1] "Su valor de MAPE es: Inf"
## [1] "--------------------"
# Nota: Este código identifica el mejor modelo PARA CADA MÉTRICA INDIVIDUALMENTE.
# No elige un único "mejor modelo general" si diferentes métricas apuntan a modelos distintos.
# Si necesitas una decisión final basada en múltiples métricas, podrías considerar
# alguna forma de puntuación o ranking combinado.
El modelo CES_Full es el mejor en términos de precisión de ajuste según los indicadores de error. Su desempeño se evalúa mediante métricas clave:
MAE (Error Medio Absoluto): 0.0600, indicando una desviación baja en las predicciones.
RMSE (Raíz del Error Cuadrático Medio): 0.0768, lo que confirma que el modelo reduce los errores extremos con eficacia.
sMAPE (Error Medio Absoluto Porcentual Simétrico): 145.6141, reflejando su capacidad de ajuste en términos de porcentaje de desviación respecto a los valores reales.
La ventaja del CES_Full radica en su habilidad para capturar patrones estacionales y de tendencia sin generar fluctuaciones innecesarias. Su baja varianza en errores sugiere que el modelo es estable y confiable para la proyección futura. Además, comparado con otras opciones, logra minimizar el impacto de posibles anomalías en los datos históricos, proporcionando una estimación más robusta.