1. Resumen

Activo elegido: Exxon Mobil Corporation (XOM), accion negociada en la Bolsa de Nueva York (NYSE), en dolares estadounidenses.

Pregunta de investigacion: ¿Un modelo de series de tiempo nos ayuda a decidir si conviene comprar acciones de XOM durante los proximos tres meses?

Muestra: de 31/01/2015 a 30/09/2026, con 141 observaciones mensuales.

Capital disponible: USD 100,000. Horizonte de cada inversion: 3 meses.

Resultado principal: el modelo seleccionado con la muestra de entrenamiento fue SARIMAX_110_100. Desde la fecha de corte 30/09/2023, la regla lleva a MANTENER EFECTIVO porque el rendimiento previsto a tres meses es -2.04%. Esto es una decision basada en un pronostico, no una rentabilidad asegurada.

2. Fuente y analisis de mercado

Exxon Mobil es una empresa energetica con negocios relacionados con petroleo, gas y productos derivados. Se eligio XOM porque tiene precios historicos disponibles y su actividad esta relacionada economicamente con el mercado del crudo. Cotiza como XOM en la NYSE (Exxon Mobil, 2026).

Utilizamos el cierre ajustado de XOM de Yahoo Finance (quantmod) y el precio mensual del crudo WTI de FRED (serie MCOILWTICO, suministrada por EIA). Los precios de la accion representan USD por accion; el WTI se mide en USD por barril. Si se utiliza cierre ajustado, el precio incorpora ajustes reportados por el proveedor; si se utiliza cierre sin ajustar, pueden no estar reflejados los dividendos y otros eventos (Yahoo Finance, s. f.; EIA, s. f.).

Tres hechos economicos para interpretar la muestra:

  1. En 2020, la pandemia redujo la demanda de petroleo y presiono los precios a la baja (EIA, 2021).
  2. En 2022, la invasion de Ucrania por Rusia genero incertidumbre y fuertes subidas del crudo (EIA, 2022).
  3. En 2023, los recortes de produccion de OPEP+ afectaron la oferta mundial de petroleo (EIA, 2023).

Estos hechos sirven para dar contexto, pero por si solos no prueban que causaron cada cambio en la cotizacion de XOM.

Hipotesis y regla fijadas antes de observar test: compraremos XOM solo si el modelo pronostica una apreciacion superior al 1% en tres meses. Si no supera 1%, dejaremos los USD 100,000 en efectivo. Se supone efectivo con rendimiento 0%, sin comisiones ni impuestos. Compararemos esta regla con comprar y mantener XOM y con conservar efectivo.

3. Base de datos y tratamiento

Se usa frecuencia mensual para reducir ruido de los cambios diarios y tener un ejercicio manejable. En XOM se toma el ultimo cierre ajustado disponible de cada mes. En WTI se utiliza el precio promedio mensual publicado por FRED; no son exactamente la misma forma de agregacion y esa es una limitacion.

knitr::kable(head(base,8), digits=2, caption="Primeras observaciones de la muestra")
Primeras observaciones de la muestra
fecha precio wti
2015-01-31 53.47 47.22
2015-02-28 54.56 50.58
2015-03-31 52.38 47.82
2015-04-30 53.84 54.45
2015-05-31 52.94 59.27
2015-06-30 51.69 59.82
2015-07-31 49.22 50.90
2015-08-31 47.19 42.87
cat("Observaciones:",n_total,"\n")
## Observaciones: 141
cat("Faltantes en base final:",sum(!stats::complete.cases(base)),"\n")
## Faltantes en base final: 0
cat("Meses duplicados:",anyDuplicated(base$fecha),"\n")
## Meses duplicados: 0
ggplot2::ggplot(base,ggplot2::aes(x=fecha,y=precio))+
  ggplot2::geom_line(color="steelblue", linewidth=0.7)+
  ggplot2::labs(title=paste("XOM:", tipo_precio, "mensual"),x="Fecha",y="USD por accion")+
  ggplot2::theme_minimal()

base$retorno_pct <- c(NA,100*diff(log(base$precio)))
ggplot2::ggplot(base,ggplot2::aes(x=fecha,y=retorno_pct))+
  ggplot2::geom_col(fill="gray40")+
  ggplot2::labs(title="Rendimientos logaritmicos mensuales de XOM",
               x="Fecha",y="% mensual")+ggplot2::theme_minimal()

r <- diff(log(base$precio))
estadisticas <- data.frame(
  estadistico=c("Promedio precio (USD)","Mediana precio (USD)",
                "Precio minimo (USD)","Precio maximo (USD)",
                "Retorno mensual promedio (%)", "Volatilidad mensual (%)",
                "Volatilidad anual aproximada (%)"),
  valor=c(mean(base$precio),median(base$precio),min(base$precio),max(base$precio),
          100*mean(r),100*sd(r),100*sd(r)*sqrt(12)))
knitr::kable(estadisticas, digits=2)
estadistico valor
Promedio precio (USD) 73.02
Mediana precio (USD) 56.58
Precio minimo (USD) 25.52
Precio maximo (USD) 167.43
Retorno mensual promedio (%) 0.80
Volatilidad mensual (%) 7.67
Volatilidad anual aproximada (%) 26.57

Interpretacion basica: los precios presentan variaciones con el tiempo. La volatilidad mensual de los rendimientos es aproximadamente 7.67%. En meses con movimientos grandes aumenta la incertidumbre de una inversion. Es importante recordar que el valor pasado no determina el valor futuro.

Transformacion Box-Cox. Evaluamos lambda solo con train. Por claridad economica usamos el logaritmo natural del precio: sus diferencias se parecen a rendimientos.

lambda_estimado <- forecast::BoxCox.lambda(stats::ts(train$precio, frequency=12), method="guerrero")
cat("Lambda Box-Cox estimada en train:",round(lambda_estimado,3),"\n")
## Lambda Box-Cox estimada en train: 1.044
cat("Transformacion elegida: log(precio), equivalente a lambda = 0.\n")
## Transformacion elegida: log(precio), equivalente a lambda = 0.

Interpretacion: una lambda proxima a cero apoya usar logaritmos. Si la lambda observada no se aproxima a cero, mantenemos el logaritmo por comparabilidad de rendimientos e indicamos que no es necesariamente la transformacion optima bajo el criterio Box-Cox.

4. Fundamentacion matematica

AR y MA. Un AR(1) usa la observacion anterior: \(y_t=c+\phi_1 y_{t-1}+\varepsilon_t\). Un MA(1) usa el error anterior: \(y_t=c+\varepsilon_t+\theta_1\varepsilon_{t-1}\).

Operador rezago y diferenciacion. Si \(Ly_t=y_{t-1}\), entonces \((1-L)y_t=y_t-y_{t-1}\). Cuando la serie presenta tendencia, diferenciarla ayuda a trabajar con cambios en lugar de niveles. Para \(d\) diferencias se escribe \((1-L)^dy_t\). Aquí \(y_t=\log(P_t)\), y \(\Delta y_t\) aproxima el rendimiento mensual.

ARIMA(p,d,q). Combinando los componentes anteriores:

\[\underbrace{(1-\phi_1 L-\cdots-\phi_pL^p)}_{AR(p)}(1-L)^d y_t = c+\underbrace{(1+\theta_1L+\cdots+\theta_qL^q)}_{MA(q)}\varepsilon_t.\]

ARIMAX. Incluye una variable externa \(X_t\), en este caso \(\log(WTI_t)\):

\[\phi(L)(1-L)^d[y_t-\beta X_t]=\theta(L)\varepsilon_t.\]

\(\beta\) representa una relacion estadistica condicional, no una prueba de causalidad. Con \(d=1\), se modelan diferencias logaritmicas tanto del precio de XOM como de la variable externa. El WTI puede ayudar porque el mercado de petroleo esta relacionado con el negocio de XOM. Para proyectar ARIMAX tambien necesitamos predecir el WTI, ya que no conocemos su valor futuro.

SARIMAX. Añade patrones estacionales con periodo \(s=12\) para datos mensuales:

\[\Phi(L^{12})\phi(L)(1-L)^d(1-L^{12})^D[y_t-\beta X_t]=\Theta(L^{12})\theta(L)\varepsilon_t.\]

\((p,d,q)(P,D,Q)_{12}\) diferencia la dinamica habitual de la estacional. No se da por hecho que haya estacionalidad: se revisan graficos y ACF/PACF y se estima un candidato estacional para compararlo.

ARCH/GARCH. Si la variabilidad de los errores cambia con el tiempo, se puede trabajar con una varianza condicional:

\[\varepsilon_t=\sigma_t z_t,\qquad \sigma_t^2=\omega+\alpha\varepsilon_{t-1}^2+\beta\sigma_{t-1}^2.\]

En GARCH(1,1), \(\omega>0\), \(\alpha\geq 0\), \(\beta\geq 0\) y, para varianza incondicional finita, usualmente \(\alpha+\beta<1\). Este trabajo se concentra en pronosticar el precio con ARIMA/ARIMAX/SARIMAX; GARCH se plantea como posible extension si aparece heterocedasticidad.

5. Identificacion y calibracion

Dividimos la base cronologicamente en 75% train y 25% test. Esto deja 105 meses para estimar los modelos y 36 meses para comprobarlos. La fecha de corte \(T_0\) es 30/09/2023. Ningun dato de test se utiliza para escoger o calibrar el modelo inicial.

knitr::kable(data.frame(conjunto=c("Train","Test"),
  inicio=c(as.character(min(train$fecha)),as.character(min(test$fecha))),
  final=c(as.character(max(train$fecha)),as.character(max(test$fecha))),
  meses=c(n_train,n_test)))
conjunto inicio final meses
Train 2015-01-31 2023-09-30 105
Test 2023-10-31 2026-09-30 36

Pruebas de estacionariedad: ADF contrasta raiz unitaria (hipotesis nula: no estacionaria). KPSS contrasta estacionariedad (hipotesis nula: estacionaria). Se miran ambas, no solamente una.

pruebas <- data.frame(serie=c("Log-precio","Diferencia de log-precio"),
  p_ADF=c(tseries::adf.test(y_train)$p.value,
          tseries::adf.test(diff(y_train))$p.value),
  p_KPSS=c(tseries::kpss.test(y_train, null="Level")$p.value,
           tseries::kpss.test(diff(y_train),null="Level")$p.value))
knitr::kable(pruebas,digits=4)
serie p_ADF p_KPSS
Log-precio 0.9407 0.0425
Diferencia de log-precio 0.0100 0.1000

Interpretacion: en ADF, un valor p menor que 0.05 favorece rechazar la raiz unitaria; en KPSS, un valor p mayor que 0.05 es compatible con estacionariedad. Por eso probamos ARIMA con \(d=1\). Si los resultados discrepan, es una señal de cautela, no una prueba absoluta.

par(mfrow=c(2,2))
acf(y_train, main="ACF del log-precio",lag.max=24)
pacf(y_train,main="PACF del log-precio",lag.max=24)
acf(diff(y_train),main="ACF del log-retorno",lag.max=24)
pacf(diff(y_train),main="PACF del log-retorno",lag.max=24)

par(mfrow=c(1,1))

Lectura sencilla de ACF/PACF: si aparecen barras fuera de las bandas de referencia, puede existir dependencia en ciertos rezagos. Por eso se prueban manualmente ordenes AR(1), MA(1), ARMA(1,1), versiones con WTI y alternativas estacionales. El periodo 12 se evalua como posibilidad, no se impone como resultado confirmado.

mostrar <- tabla_modelos
mostrar$AICc <- round(mostrar$AICc,2)
mostrar$BIC <- round(mostrar$BIC,2)
mostrar$p_Ljung_Box <- round(mostrar$p_Ljung_Box,4)
knitr::kable(mostrar, caption="Modelos candidatos estimados solo con train")
Modelos candidatos estimados solo con train
modelo AICc BIC parametros p_Ljung_Box residuos_compatibles
ARIMAX_011 ARIMAX_011 -231.83 -221.66 3 0.0179 FALSE
SARIMAX_110_100 SARIMAX_110_100 -231.71 -219.10 4 0.0716 TRUE
ARIMAX_110 ARIMAX_110 -231.63 -221.45 3 0.0104 FALSE
ARIMA_010 ARIMA_010 -223.85 -218.68 1 0.4855 TRUE
ARIMA_011 ARIMA_011 -221.76 -214.07 2 0.4317 TRUE
ARIMA_110 ARIMA_110 -221.76 -214.07 2 0.4297 TRUE
ARIMA_111 ARIMA_111 -219.61 -209.44 3 0.3711 TRUE
SARIMA_011_011 SARIMA_011_011 -166.19 -158.90 2 0.2548 TRUE

Eleccion: se considero el AICc (menor es mejor), el BIC, cuantos parametros se utilizan y si el test de Ljung-Box deja residuos sin autocorrelacion notable. Primero se prefieren modelos con p de Ljung-Box mayor a 0.05 y, entre ellos, el de menor AICc. El resultado fue SARIMAX_110_100. Esta regla fue fijada antes de comprobar los pronosticos en test.

coeficientes <- modelo_final$coef
se_coef <- sqrt(diag(modelo_final$var.coef))
tabla_coef <- data.frame(parametro=names(coeficientes),
                         estimacion=as.numeric(coeficientes),
                         error_estandar=as.numeric(se_coef),
                         p_aprox=2*stats::pnorm(-abs(as.numeric(coeficientes)/se_coef)))
knitr::kable(tabla_coef, digits=4, caption="Coeficientes del modelo elegido")
Coeficientes del modelo elegido
parametro estimacion error_estandar p_aprox
ar1 ar1 -0.1504 0.0995 0.1308
sar1 sar1 -0.1501 0.0983 0.1269
drift drift 0.0051 0.0057 0.3742
logWTI logWTI 0.2103 0.0574 0.0003

Interpretacion: los coeficientes muestran como se relacionan los cambios recientes, los errores pasados y, si aplica, el WTI con el precio de XOM. Un valor p pequeno puede indicar evidencia estadistica, pero no convierte la relacion en causalidad economica.

6. Diagnostico de residuos

Los residuos son la parte que el modelo no logro explicar. Idealmente no deben mostrar un patron temporal claro ni una autocorrelacion importante.

par(mfrow=c(2,2))
plot(res_final,type="l",main="Residuos del modelo",xlab="Mes (train)",ylab="Error")
acf(res_final,main="ACF de residuos",lag.max=24)
hist(res_final,main="Histograma",xlab="Error",col="gray85",border="white")
qqnorm(res_final,main="Grafico Q-Q"); qqline(res_final,col="red")

par(mfrow=c(1,1))
ljung <- stats::Box.test(res_final,lag=18,type="Ljung-Box",
                         fitdf=min(length(modelo_final$coef),10))
e2 <- res_final^2
aux_arch <- lm(e2[-1] ~ e2[-length(e2)])
arch_lm <- (length(e2)-1)*summary(aux_arch)$r.squared
p_arch <- pchisq(arch_lm,df=1,lower.tail=FALSE)
tabla_diag <- data.frame(
  prueba=c("Ljung-Box (autocorrelacion)","Jarque-Bera (normalidad)",
           "ARCH LM aproximada (varianza)") ,
  p_valor=c(ljung$p.value,p_jb,p_arch))
knitr::kable(tabla_diag,digits=4)
prueba p_valor
Ljung-Box (autocorrelacion) 0.0716
Jarque-Bera (normalidad) 0.0000
ARCH LM aproximada (varianza) 0.0010

Interpretaciones sencillas:

7. Train-test y capacidad predictiva

Para evaluar fuera de muestra, pronosticamos el conjunto test sin introducir sus precios en el modelo. La proyeccion del WTI utilizada como regresor tambien parte solo de train, mediante un paseo aleatorio con deriva. Asi evitamos usar un WTI futuro observado que el inversionista no conoceria en \(T_0\).

Compararemos todos los candidatos sobre las mismas fechas. MAE y RMSE estan en USD por accion; MAPE, en porcentaje; MASE compara el MAE con el cambio medio mensual de train. El benchmark naive mantiene el ultimo precio visto.

knitr::kable(tabla_errores,digits=3, caption="Errores fuera de muestra: horizonte test completo")
Errores fuera de muestra: horizonte test completo
modelo MAE RMSE MAPE MASE
6 ARIMAX_011 13.301 15.660 11.174 4.149
5 ARIMAX_110 13.374 15.680 11.257 4.172
4 ARIMA_111 13.511 15.718 11.416 4.215
3 ARIMA_011 13.537 15.726 11.446 4.223
2 ARIMA_110 13.543 15.728 11.453 4.225
1 ARIMA_010 13.594 15.743 11.513 4.241
8 SARIMAX_110_100 11.801 15.805 9.390 3.682
7 SARIMA_011_011 16.124 18.003 14.375 5.030
9 NAIVE 15.575 24.008 11.527 4.859

El menor RMSE del bloque test correspondio a ARIMAX_011. No coincide con el modelo seleccionado en train; esto demuestra que mejor ajuste historico no garantiza mejor pronostico. Se presenta esta comparacion como evaluacion, no como excusa para volver a seleccionar el modelo despues de mirar test.

pr <- pronosticos_test[[nombre_final]]
grafico_test <- data.frame(fecha=test$fecha, real=test$precio,
  modelo=pr$central, li95=pr$li95, ls95=pr$ls95,
  naive=rep(tail(train$precio,1),n_test))
ggplot2::ggplot(grafico_test,ggplot2::aes(x=fecha))+
  ggplot2::geom_ribbon(ggplot2::aes(ymin=li95,ymax=ls95),fill="gray70",alpha=.35)+
  ggplot2::geom_line(ggplot2::aes(y=real,color="Real"),linewidth=.9)+
  ggplot2::geom_line(ggplot2::aes(y=modelo,color="Modelo"),linewidth=.8)+
  ggplot2::geom_line(ggplot2::aes(y=naive,color="Naive"),linetype="dashed")+
  ggplot2::scale_color_manual(values=c("Real"="black","Modelo"="blue","Naive"="gray40"))+
  ggplot2::labs(title="Pronostico fuera de muestra e intervalo del 95%",
               x="Fecha",y="USD por accion",color="Serie")+
  ggplot2::theme_minimal()

Interpretacion: la banda gris muestra valores compatibles con la incertidumbre del modelo, condicionada a la trayectoria proyectada del WTI. Si los precios reales se alejan bastante, el modelo no capturo algun cambio del mercado. No se deben interpretar los intervalos como garantias.

8. Pronostico e inversion

Nuestro corte historico \(T_0\) es 30/09/2023. En ese momento solo conocemos train. La regla se evalua con el precio ajustado de cierre 106.55 USD y un horizonte de tres meses.

resultado_inversion <- data.frame(
  concepto=c("Precio en T0 (USD)","Precio pronosticado a 3 meses (USD)",
             "Retorno pronosticado (%)","Umbral de compra (%)",
             "Capital estrategia al cabo de 3 meses (USD)",
             "Capital comprar y mantener 3 meses (USD)",
             "Capital solo efectivo 3 meses (USD)"),
  resultado=c(precio_corte,tail(pred_corte$central,1),
              100*retorno_previsto,100*umbral_compra,
              capital_real_3m,capital_compra_y_mantener_3m,capital_inicial))
knitr::kable(resultado_inversion,digits=2)
concepto resultado
Precio en T0 (USD) 106.55
Precio pronosticado a 3 meses (USD) 104.37
Retorno pronosticado (%) -2.04
Umbral de compra (%) 1.00
Capital estrategia al cabo de 3 meses (USD) 100000.00
Capital comprar y mantener 3 meses (USD) 85809.02
Capital solo efectivo 3 meses (USD) 100000.00
cat("Decision del modelo:",decision,"\n")
## Decision del modelo: MANTENER EFECTIVO

Interpretacion: la senal es MANTENER EFECTIVO. Es importante evaluar el resultado sin cambiar la regla despues de observar los datos reales. Los valores monetarios son simulados; no representan operaciones realizadas.

Evaluacion de la estrategia por periodos de tres meses

Para dar una comparacion adicional, repetimos el ejercicio trimestralmente en test. En cada fecha se reestima la misma estructura de modelo con datos disponibles hasta ese mes, y se pronostican tres meses nuevos; nunca usamos datos posteriores a la fecha de la decision. Se ignoran las fracciones de mes que queden al final de test.

registro_vista <- registro
registro_vista$retorno_previsto <- round(100*registro$retorno_previsto,2)
registro_vista$retorno_observado <- round(100*registro$retorno_observado,2)
registro_vista$capital <- round(registro$capital,2)
names(registro_vista)[3:5] <- c("Previsto_pct","Decision","Observado_pct")
knitr::kable(registro_vista,caption="Backtest trimestral fuera de muestra")
Backtest trimestral fuera de muestra
fecha_inicio fecha_fin Previsto_pct Decision Observado_pct capital
2023-09-30 2023-12-31 -2.04 Efectivo -14.19 100000.00
2023-12-31 2024-03-31 1.81 Comprar 17.34 117343.77
2024-03-31 2024-06-30 1.03 Comprar -0.16 117157.07
2024-06-30 2024-09-30 1.52 Comprar 2.64 120254.65
2024-09-30 2024-12-31 3.86 Comprar -7.48 111261.62
2024-12-31 2025-03-31 1.05 Comprar 11.55 124111.78
2025-03-31 2025-06-30 1.04 Comprar -8.52 113532.97
2025-06-30 2025-09-30 0.71 Efectivo 5.57 113532.97
2025-09-30 2025-12-31 3.37 Comprar 7.67 122235.56
2025-12-31 2026-03-31 -0.04 Efectivo 41.92 122235.56
2026-03-31 2026-06-30 3.90 Comprar -18.87 99171.74
2026-06-30 2026-09-30 1.60 Comprar 19.81 118817.37
resultados_capital <- data.frame(estrategia=c("Regla de pronostico","Comprar y mantener XOM",
                                             "Siempre efectivo"),
                                 capital_final=c(capital_backtest,capital_buyhold,capital_cash))
resultados_capital$rendimiento_pct <- 100*(resultados_capital$capital_final/capital_inicial-1)
knitr::kable(resultados_capital,digits=2,
             caption="Resultado del mismo periodo y con capital inicial de USD 100000")
Resultado del mismo periodo y con capital inicial de USD 100000
estrategia capital_final rendimiento_pct
Regla de pronostico 118817.4 18.82
Comprar y mantener XOM 152752.3 52.75
Siempre efectivo 100000.0 0.00

Lectura: en este backtest, comprar y mantener XOM igualo o supero a la regla de pronosticos. Esto no demuestra que vaya a ocurrir igual en el futuro. Los resultados cambian si hay comisiones, impuestos o un horizonte distinto.

9. Simulacion

Se simulan 2,000 trayectorias vistas desde \(T_0\) durante exactamente 3 meses, el mismo horizonte de la decision. Las simulaciones usan el modelo entrenado antes de test y, para ARIMAX/SARIMAX, simulan tambien el WTI. Si Jarque-Bera rechaza normalidad, se utiliza bootstrap de residuos; de lo contrario, innovaciones normales ajustadas.

tabla_sim <- data.frame(
  indicador=c("Media precio futuro (USD)","Mediana precio futuro (USD)",
    "Precio futuro p5 (USD)","Precio futuro p50 (USD)",
    "Precio futuro p95 (USD)","Probabilidad precio menor al de entrada (%)",
    "Media capital final (USD)", "Capital final p5 (USD)",
    "Capital final p50 (USD)","Capital final p95 (USD)",
    "Probabilidad de perdida de cartera (%)"),
  valor=c(mean(precio_sim),median(precio_sim),unname(q_precio),
          100*prob_perder_precio, mean(capital_sim), unname(q_capital),
          100*prob_perder_cartera))
knitr::kable(tabla_sim,digits=2)
indicador valor
Media precio futuro (USD) 105.61
Mediana precio futuro (USD) 104.02
Precio futuro p5 (USD) 85.13
Precio futuro p50 (USD) 104.02
Precio futuro p95 (USD) 132.40
Probabilidad precio menor al de entrada (%) 57.10
Media capital final (USD) 100000.00
Capital final p5 (USD) 100000.00
Capital final p50 (USD) 100000.00
Capital final p95 (USD) 100000.00
Probabilidad de perdida de cartera (%) 0.00
ggplot2::ggplot(data.frame(precio=precio_sim),ggplot2::aes(x=precio))+
  ggplot2::geom_histogram(bins=35,fill="gray65",color="white")+
  ggplot2::geom_vline(xintercept=precio_corte,color="red",linetype="dashed")+
  ggplot2::labs(title="Distribucion simulada del precio de XOM a 3 meses",
               x="Precio final (USD)",y="Numero de simulaciones")+
  ggplot2::theme_minimal()

Interpretacion sencilla: segun la simulacion, la probabilidad de que el precio de XOM sea inferior al de entrada es 57.10%. El 90% central de precios simulados se ubica aproximadamente entre USD 85.13 y USD 132.40 (percentiles 5 y 95). La probabilidad simulada de perdida para la cartera segun MANTENER EFECTIVO es 0.00%. Si se decide conservar efectivo y se supone rentabilidad cero, la perdida simulada de la cartera sera cero bajo este supuesto simplificado.

10. Conclusiones y limitaciones

Respuestas a las siete preguntas del enunciado:

  1. Caracteristicas de la serie. Analizamos log-precios mensuales, rendimientos y ACF/PACF. Evaluamos estacionariedad y una posible estacionalidad con periodo 12. La volatilidad historica mensual fue de 7.67%.
  2. Modelo elegido. Fue SARIMAX_110_100 porque, siguiendo la regla prefijada, obtuvo un AICc competitivo y el diagnostico de autocorrelacion residual considerado para la seleccion.
  3. Residuos. No se encontro autocorrelacion importante con Ljung-Box. La normalidad fue rechazada. El diagnostico no garantiza un modelo perfecto.
  4. Capacidad predictiva. El RMSE del modelo elegido en test fue 15.80 USD, frente a 24.01 USD del benchmark naive. Supero a naive en esta metrica.
  5. Estrategia frente a benchmark. En el backtest trimestral, la estrategia termino con USD 118,817.37 y comprar y mantener con USD 152,752.32. Es un resultado historico fuera de muestra, no una promesa.
  6. Simulacion y riesgo. La probabilidad simulada de que el precio termine por debajo del precio inicial fue 57.10%. El precio final se ubico entre USD 85.13 y USD 132.40 para los percentiles 5 y 95.
  7. Limitaciones. Los precios pueden cambiar por noticias, decisiones politicas, resultados empresariales y otros factores que no estan en el modelo. La frecuencia mensual oculta movimientos diarios; la variable WTI tambien se pronostica y contiene incertidumbre; los intervalos condicionales del test no incorporan totalmente esa incertidumbre. Tampoco se incluyen impuestos, costos de transaccion o interes del efectivo. Por eso el modelo no garantiza ganancias.

Conclusion final: el ejercicio permite organizar una decision de inversion con criterios previos y probarla contra resultados que no se usaron en el entrenamiento. El resultado depende del periodo elegido y de los supuestos. Seria util estudiar mas variables y, si aparece volatilidad agrupada, modelos GARCH.

11. Referencias

Referencias en formato APA (comprobar formato y fecha de consulta con el grupo):

Paquetes principales: quantmod (descarga), forecast (modelos/pronosticos/simulacion), tseries (pruebas), zoo (fechas), ggplot2 (graficos), knitr y rmarkdown (informe). El codigo completo esta en el archivo .Rmd, las tablas se exportan a datos/ y las simulaciones utilizan set.seed(1234).

cat("Version de R:",as.character(getRversion()),"\n")
## Version de R: 4.6.1
cat("Paquetes usados y versiones:\n")
## Paquetes usados y versiones:
for (p in paquetes) cat(" - ",p,": ",as.character(utils::packageVersion(p)),"\n",sep="")
##  - quantmod: 0.4.29
##  - forecast: 9.0.2
##  - tseries: 0.10.63
##  - zoo: 1.9.1
##  - ggplot2: 4.0.3
##  - knitr: 1.51
##  - rmarkdown: 2.32

12. Uso de inteligencia artificial como herramienta de apoyo

Durante el desarrollo de este trabajo utilizamos herramientas de inteligencia artificial como apoyo para mejorar y perfeccionar los códigos en R, organizar la estructura del documento y facilitar la conexión directa con Yahoo Finance para obtener los datos históricos necesarios.

Esta herramienta nos permitió encontrar soluciones de programación más eficientes, corregir errores y adaptar los códigos a las necesidades de cada análisis.

El equipo fue responsable de comprender los procedimientos, revisar los resultados obtenidos y desarrollar las interpretaciones y conclusiones del trabajo. La inteligencia artificial se utilizó principalmente como una herramienta de apoyo técnico para facilitar la programación y mejorar el desarrollo del ejercicio.

Consideramos que su uso fue un complemento para nuestro aprendizaje, ya que nos permitió concentrarnos en comprender y aplicar los conceptos de econometría financiera.