Introducción

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.

El DataFrame

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:

Descripción del Data Frame: Serie Histórica de GEB (Grupo Energía Bogotá)

Este data frame contiene la evolución mensual de la acción GEB (Grupo Energía Bogotá S.A. ESP), una de las principales empresas del sector de servicios públicos en Colombia. La serie histórica va desde mayo de 2015 hasta abril de 2025, proporcionando información confiable y continua para análisis de tendencias, pronósticos de precios y simulaciones financieras.

Estructura de columnas

Columna Descripción
Fecha Último día hábil de cada mes.
Último Precio de cierre mensual de la acción (COP).
Apertura Precio de apertura del mes.
Máximo Precio más alto registrado durante el mes.
Mínimo Precio más bajo del mes.
Vol. Volumen negociado en el mes (en millones o miles de acciones).
% var. Porcentaje de variación del precio de cierre respecto al mes anterior.
Rendimientos GEB Rendimiento mensual efectivo, calculado como:

\[ \left( \frac{P_t - P_{t-1}}{P_{t-1}} \right) \times 100 \]

Nota: Aunque % var. y Rendimientos EC son muy similares, se incluyen ambas columnas para trazabilidad. En el análisis se toma Rendimientos 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

Observaciones adicionales

  • Las cifras de precios (Último, Apertura, etc.) están en pesos colombianos (COP).
  • El campo Vol. puede estar abreviado (“15,95M”),

Pronóstico

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.

# Cargar las librerías 
library(readxl)
library(forecast)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(ggplot2)
library(dplyr)
## 
## 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
library(smooth)
## Cargando paquete requerido: greybox
## Package "greybox", v2.0.4 loaded.
## This is package "smooth", v4.2.0

Grupo Energía Bogotá (GEB)

Grupo Energía Bogotá (GEB) es una empresa multilatina con más de 128 años de historia, especializada en la transmisión y distribución de energía eléctrica, así como en el transporte y distribución de gas natural. Con operaciones en Colombia, Perú, Brasil y Guatemala, GEB se ha consolidado como un actor clave en el sector energético de América Latina.

# Cargar los datos
library(readxl)
Caso1 <- read_excel("Caso1.xlsx", sheet = "DatoshistoricosGrupoEnergia ")
(Caso1)
Caso1$`Rendimientos GEB` <- as.numeric(Caso1$`Rendimientos GEB`)
# 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 GEB` <- as.numeric(Caso1$`Rendimientos GEB`)

# 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 GEB`, 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 Energia Bogota", # 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 muestra una tendencia clara de aumento o disminución a lo largo del tiempo. Los rendimientos oscilan alrededor de un valor cercano a cero, sin evidencia de un crecimiento sostenido ni un descenso prolongado. Esto sugiere que los valores se mantienen relativamente estables en términos de tendencia a largo plazo.

  • Irregularidad: La serie presenta variaciones impredecibles, con picos y caídas repentinas que no parecen explicarse por los otros componentes. Este comportamiento es común en series de tiempo financieras, donde el mercado responde a eventos inesperados, cambios en la percepción de los inversionistas o factores externos.

  • Estacionalidad: No se observan patrones recurrentes que indiquen estacionalidad clara en la serie. Los picos y valles parecen aparecer en momentos variados, sin repetirse en intervalos específicos como anual, mensual o diario. Esto sugiere que no hay una componente estacional definida que influya en los rendimientos de estas acciones.

  • Ciclicidad: Se pueden notar fluctuaciones a largo plazo, pero no ocurren en intervalos fijos. Estas variaciones pueden estar relacionadas con factores económicos, sociales o del mercado que afectan los rendimientos de Grupo Energía Bogotá. Hay períodos de alta volatilidad seguidos de otros más estables, lo que puede asociarse con dinámicas cíclicas del sector energético o del mercado financiero.

Modelo de Promedios Moviles

#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))

Suavización exponencial

# 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         Jun
## 2025                                                 0.004928441 0.005059199
## 2026 0.004896102 0.004873135 0.004850276 0.004827523                        
##              Jul         Aug         Sep         Oct         Nov         Dec
## 2025 0.005036192 0.005012571 0.004989058 0.004965655 0.004942361 0.004919177
## 2026
# Graficar el pronóstico
plot(f2)

Modelos Indices estacionales

Simple

# 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.0123341303
## 2026  0.0090465264 -0.0003695001 -0.0095514168 -0.0023662357              
##                Jun           Jul           Aug           Sep           Oct
## 2025  0.0151613689  0.0121670257  0.0227213900 -0.0064271089 -0.0011163803
## 2026                                                                      
##                Nov           Dec
## 2025  0.0003588845  0.0082673157
## 2026
# Graficar el pronóstico
plot(f3)

Parcial

# 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.029494643
## 2026  0.012046788 -0.014868247 -0.003258130 -0.012552047             
##               Jun          Jul          Aug          Sep          Oct
## 2025  0.027441759 -0.006020594  0.032081531 -0.007016966  0.016658838
## 2026                                                                 
##               Nov          Dec
## 2025 -0.028232248  0.015210184
## 2026
# Graficar el pronóstico
plot(f4)

Full

# 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.002757159
## 2026  0.004225663  0.002869495 -0.017034362 -0.009385820             
##               Jun          Jul          Aug          Sep          Oct
## 2025  0.017897399  0.010639456  0.005927950 -0.002605119 -0.018959724
## 2026                                                                 
##               Nov          Dec
## 2025  0.002287816  0.009019153
## 2026
# Graficar el pronóstico
plot(f5)

print(f5$mean)
##               Jan          Feb          Mar          Apr          May
## 2025                                                      0.002757159
## 2026  0.004225663  0.002869495 -0.017034362 -0.009385820             
##               Jun          Jul          Aug          Sep          Oct
## 2025  0.017897399  0.010639456  0.005927950 -0.002605119 -0.018959724
## 2026                                                                 
##               Nov          Dec
## 2025  0.002287816  0.009019153
## 2026

l pronóstico mostrado en el gráfico refleja una serie temporal con fluctuaciones moderadas en el período proyectado (2025-2026) en comparación con los datos históricos, los cuales presentan una variabilidad más marcada. La proyección parece mantener una tendencia estable sin cambios abruptos, aunque se identifican ciertos movimientos estacionales.

En el año 2025, los valores comienzan con un crecimiento en junio (0.00276) y julio (0.01064), seguido de una ligera disminución en agosto (0.00593) y una caída en septiembre (-0.00261), alcanzando su punto más bajo en octubre (-0.01896). Sin embargo, en los meses de noviembre y diciembre, la serie recupera valores positivos (0.00229 y 0.00902, respectivamente), lo que podría indicar un efecto estacional.

Para el 2026, los primeros meses presentan valores positivos (enero y febrero), pero en marzo y abril la serie muestra un descenso (-0.01703 y -0.00939), lo que sugiere una posible repetición de patrones observados en el año anterior.

En general, el pronóstico no evidencia una tendencia claramente creciente ni decreciente, sino más bien un comportamiento estable con fluctuaciones que podrían corresponder a patrones estacionales.

Regresiones polinómicas

#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.183357 -0.028657 -0.000081  0.028872  0.186672 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)
## (Intercept)  1.214e-02  1.024e-02   1.186    0.238
## t           -9.046e-05  1.469e-04  -0.616    0.539
## 
## Residual standard error: 0.05575 on 118 degrees of freedom
## Multiple R-squared:  0.003203,   Adjusted R-squared:  -0.005244 
## F-statistic: 0.3792 on 1 and 118 DF,  p-value: 0.5392
g1<-predict.lm(mlineal, h=12)
mcuad=lm(y~t+t2)
summary(mcuad)
## 
## Call:
## lm(formula = y ~ t + t2)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.180744 -0.031513 -0.001003  0.029153  0.182962 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)
## (Intercept)  2.384e-02  1.552e-02   1.536    0.127
## t           -6.658e-04  5.923e-04  -1.124    0.263
## t2           4.754e-06  4.742e-06   1.003    0.318
## 
## Residual standard error: 0.05574 on 117 degrees of freedom
## Multiple R-squared:  0.01169,    Adjusted R-squared:  -0.005199 
## F-statistic: 0.6922 on 2 and 117 DF,  p-value: 0.5025
g2<-predict.lm(mcuad, h=12)
#Grafico sencillo
plot(fechas,y,type="l",col="#828282")
lines(fechas,g1,col="#007bff")
lines(fechas,g2,col="#4c3d19") 

Modelo ARIMA

library(tseries)
adf.test(y)  # Prueba de Dickey-Fuller aumentada
## Warning in adf.test(y): p-value smaller than printed p-value
## 
##  Augmented Dickey-Fuller Test
## 
## data:  y
## Dickey-Fuller = -4.746, 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.746 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.

modelo_arima <- auto.arima(y)
summary(modelo_arima)
## Series: y 
## ARIMA(0,0,0) with zero mean 
## 
## sigma^2 = 0.00311:  log likelihood = 176.11
## AIC=-350.23   AICc=-350.19   BIC=-347.44
## 
## Training set error measures:
##                       ME      RMSE        MAE MPE MAPE      MASE       ACF1
## Training set 0.006670428 0.0557681 0.04047104 100  100 0.7224016 -0.1050653
pronostico <- forecast(modelo_arima, h = 12)  # Pronóstico para 12 meses
plot(pronostico, main = "Pronóstico ARIMA rendimientos Grupo Energia Bogota")

# Si quieres ver los valores del pronóstico:
print(pronostico)
##          Point Forecast      Lo 80     Hi 80      Lo 95     Hi 95
## May 2025              0 -0.0714697 0.0714697 -0.1093035 0.1093035
## Jun 2025              0 -0.0714697 0.0714697 -0.1093035 0.1093035
## Jul 2025              0 -0.0714697 0.0714697 -0.1093035 0.1093035
## Aug 2025              0 -0.0714697 0.0714697 -0.1093035 0.1093035
## Sep 2025              0 -0.0714697 0.0714697 -0.1093035 0.1093035
## Oct 2025              0 -0.0714697 0.0714697 -0.1093035 0.1093035
## Nov 2025              0 -0.0714697 0.0714697 -0.1093035 0.1093035
## Dec 2025              0 -0.0714697 0.0714697 -0.1093035 0.1093035
## Jan 2026              0 -0.0714697 0.0714697 -0.1093035 0.1093035
## Feb 2026              0 -0.0714697 0.0714697 -0.1093035 0.1093035
## Mar 2026              0 -0.0714697 0.0714697 -0.1093035 0.1093035
## Apr 2026              0 -0.0714697 0.0714697 -0.1093035 0.1093035

Análisis de correlación

  y<-(Caso1$`Rendimientos GEB`)
x<-(Caso1$`IPC mensual`)
mcorr<-lm(y~x)
summary(mcorr)
## 
## Call:
## lm(formula = y ~ x)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.177368 -0.029980 -0.002915  0.025645  0.193133 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)
## (Intercept)  0.01229    0.01078   1.141    0.256
## x           -0.09594    0.16204  -0.592    0.555
## 
## Residual standard error: 0.05575 on 118 degrees of freedom
## Multiple R-squared:  0.002962,   Adjusted R-squared:  -0.005487 
## F-statistic: 0.3506 on 1 and 118 DF,  p-value: 0.5549

Este análisis muestra, nuevamente, ausencia de relación lineal significativa entre x e y:

Coeficiente de x: -0.09594, muy cercano a cero, no significativo (p = 0.555).

R² = 0.00296, es decir, x explica solo el 0.3% de la variabilidad en y.

El modelo completo no es significativo (F = 0.3506, p = 0.5549).

Conclusión breve: La relación entre x e y es estadísticamente insignificante y la correlación es prácticamente nula.

# Calcular la correlación de Pearson
correlacion_pearson <- cor(Caso1$`Rendimientos GEB`, 
                           Caso1$`IPC mensual`, 
                           use = "complete.obs", 
                           method = "pearson")
print(paste("Correlación de Pearson:", correlacion_pearson))
## [1] "Correlación de Pearson: -0.054426189596503"

El coeficiente de Pearson -0.0544 indica una correlación negativa muy débil, casi nula.

Esto coincide con el resultado del modelo lineal:

No hay evidencia de una relación lineal significativa entre x e y, ni estadística ni prácticamente.

Conclusión: Las variables están prácticamente no correlacionadas.

Medidas de error de pronóstico

# 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

)
# EJECUTA ESTO AL FINAL
knitr::kable(tabla_errores, caption = "Medidas de error de pronóstico para cada modelo Grupo Energia Bogota")
Medidas de error de pronóstico para cada modelo Grupo Energia Bogota
MAE RMSE MAPE
SMA 0.0415486 0.0571531 Inf
CES 0.0401800 0.0552426 Inf
CES_Estacional 0.0396519 0.0536191 Inf
CES_Parcial 0.0392039 0.0524863 Inf
CES_Full 0.0405749 0.0539362 Inf
Polinomial_Lineal 0.0404181 0.0552790 Inf
Polinomial_Cuadratico 0.0398100 0.0550430 Inf
ARIMA 0.0404710 0.0557681 NaN
# PASO 1: Define la NUEVA función para calcular errores (con sMAPE)
# Asegúrate de que esta sea la función ACTIVA en tu sesión de R
calcular_errores <- function(real, pred) {
  # Aseguramos que no haya NAs en los datos antes de calcular
  valid_indices <- complete.cases(real, pred)
  real_clean <- real[valid_indices]
  pred_clean <- pred[valid_indices]

  # Si después de limpiar no quedan datos válidos, retornamos NA
  if(length(real_clean) == 0) {
      return(data.frame(MAE = NA, RMSE = NA, sMAPE = NA)) # Retorna sMAPE
  }

  mae <- mean(abs(real_clean - pred_clean))
  rmse <- sqrt(mean((real_clean - pred_clean)^2))

  # Calcular sMAPE
  abs_diff <- abs(real_clean - pred_clean)
  sum_abs <- abs(real_clean) + abs(pred_clean)

  # Calculamos el componente de sMAPE, manejando el caso donde sum_abs es 0
  # Si sum_abs es 0 (lo que implica real_clean=0 y pred_clean=0), el componente es 0
  smape_components <- ifelse(sum_abs == 0, 0, 2 * abs_diff / sum_abs)

  # Calculamos la media de los componentes y multiplicamos por 100
  smape <- mean(smape_components) * 100

  return(data.frame(MAE = mae, RMSE = rmse, sMAPE = smape)) # Devuelve sMAPE
}

# PASO 2: Calcula los errores para cada modelo USANDO la función recién definida
# EJECUTA ESTO DESPUÉS de haber definido la función 'calcular_errores' arriba
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 que m4 es CES_Parcial
errores_ces_full <- calcular_errores(y, fitted(m5)) # Asegúrate de que m5 es CES_Full

# Para modelos polinómicos:
errores_lineal <- calcular_errores(y, g1) # Asumo que g1 es el modelo lineal
errores_cuadratico <- calcular_errores(y, g2) # Asumo que g2 es el modelo cuadrático

# Para ARIMA:
errores_arima <- calcular_errores(y, fitted(modelo_arima))


# PASO 3: 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
)

# PASO 4: Muestra la tabla
# EJECUTA ESTO AL FINAL
knitr::kable(tabla_errores, caption = "Medidas de error de pronóstico para cada modelo Grupo Energia Bogota")
Medidas de error de pronóstico para cada modelo Grupo Energia Bogota
MAE RMSE sMAPE
SMA 0.0415486 0.0571531 144.7035
CES 0.0401800 0.0552426 154.3711
CES_Estacional 0.0396519 0.0536191 143.2194
CES_Parcial 0.0392039 0.0524863 135.3245
CES_Full 0.0405749 0.0539362 142.9731
Polinomial_Lineal 0.0404181 0.0552790 157.9905
Polinomial_Cuadratico 0.0398100 0.0550430 160.9661
ARIMA 0.0404710 0.0557681 196.6667

Elección del mejor modelo

# 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) ---"
print(paste("El modelo con el menor RMSE de ajuste es:", mejor_modelo_rmse))
## [1] "El modelo con el menor RMSE de ajuste es: CES_Parcial"
print("Sus medidas de error de ajuste son:")
## [1] "Sus medidas de error de ajuste son:"
print(errores_mejor_rmse)
##                    MAE       RMSE    sMAPE
## CES_Parcial 0.03920393 0.05248632 135.3245
# --- 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_Parcial"
## [1] "Su valor de MAE es: 0.0392"
## [1] "--------------------"
## [1] "El modelo con el menor RMSE es: CES_Parcial"
## [1] "Su valor de RMSE es: 0.0525"
## [1] "--------------------"
## [1] "El modelo con el menor sMAPE es: CES_Parcial"
## [1] "Su valor de sMAPE es: 135.3245"
## [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.

En el análisis de las medidas de error de pronóstico para el Grupo Energía de Bogotá, se observa que el modelo CES_Parcial presenta el mejor desempeño general, con el menor MAE (0.0392), el menor RMSE (0.0525) y el más bajo sMAPE (135.32%), lo que indica una mayor precisión tanto en términos absolutos como relativos. Le siguen de cerca los modelos CES_Estacional y CES_Full, aunque con errores ligeramente superiores. En contraste, el modelo ARIMA muestra el peor resultado en sMAPE (196.67%), lo que sugiere una baja precisión proporcional, a pesar de que sus errores absolutos (MAE y RMSE) son similares a los demás. El modelo SMA también tiene un desempeño inferior, con sMAPE de 144.70%. Por tanto, el modelo CES_Parcial se destaca como la mejor opción para pronosticar esta serie, gracias a su equilibrio entre exactitud y capacidad de capturar patrones relevantes.