ETB

etb_xts = xts(etb$Último, order.by = etb$Fecha)
class(etb_xts)
## [1] "xts" "zoo"
summary(etb_xts)
##      Index               etb_xts     
##  Min.   :2015-01-02   Min.   : 74.0  
##  1st Qu.:2017-01-05   1st Qu.:207.0  
##  Median :2019-01-16   Median :265.0  
##  Mean   :2019-02-23   Mean   :353.4  
##  3rd Qu.:2021-01-19   3rd Qu.:529.5  
##  Max.   :2024-12-30   Max.   :655.0
plot(etb_xts, main = "precio ultimo")

El precio de la acción ha caído de más de 600 COP a menos de 100 COP entre 2015 y 2024.

No se observan patrones estacionales claros, pero sí una tendencia bajista prolongada.

1. Rendimiento diario de la acción

rendimiento_etb = dailyReturn(etb_xts)
plot(rendimiento_etb, main = "Rendimiento Diario de la Acción ETB")

summary(rendimiento_etb)
##      Index            daily.returns       
##  Min.   :2015-01-02   Min.   :-0.1872910  
##  1st Qu.:2017-01-05   1st Qu.:-0.0076727  
##  Median :2019-01-16   Median : 0.0000000  
##  Mean   :2019-02-23   Mean   :-0.0007236  
##  3rd Qu.:2021-01-19   3rd Qu.: 0.0042530  
##  Max.   :2024-12-30   Max.   : 0.2045454

Los rendimientos diarios de la acción muestran alta volatilidad en varios periodos, especialmente a partir de 2019.

No se observan patrones estacionales claros, pero sí episodios de alta dispersión y cambios bruscos.

##modelo 1

modelo1 = auto.arima(rendimiento_etb)
summary(modelo1)
## Series: rendimiento_etb 
## ARIMA(1,0,1) with non-zero mean 
## 
## Coefficients:
##          ar1      ma1    mean
##       0.5537  -0.6361  -7e-04
## s.e.  0.1579   0.1465   4e-04
## 
## sigma^2 = 0.0005082:  log likelihood = 4660.52
## AIC=-9313.05   AICc=-9313.03   BIC=-9290.72
## 
## Training set error measures:
##                         ME       RMSE        MAE MPE MAPE      MASE
## Training set -1.556461e-06 0.02252506 0.01266098 NaN  Inf 0.6288238
##                       ACF1
## Training set -0.0006444324

el modelo se refiere mejor ARMA dando como modelo c(1,0,1)

autoplot(modelo1)

checkresiduals(modelo1)

## 
##  Ljung-Box test
## 
## data:  Residuals from ARIMA(1,0,1) with non-zero mean
## Q* = 13.541, df = 8, p-value = 0.09455
## 
## Model df: 2.   Total lags used: 10
ndiffs(rendimiento_etb)
## [1] 0
  • No hay diferencias
adf.test(rendimiento_etb)
## Warning in adf.test(rendimiento_etb): p-value smaller than printed p-value
## 
##  Augmented Dickey-Fuller Test
## 
## data:  rendimiento_etb
## Dickey-Fuller = -12.641, Lag order = 12, p-value = 0.01
## alternative hypothesis: stationary

H0 = No es ESTACIONARIA si el p-value es mayor que 0.05

H1 = Si es ESTACIONARIA si el p-value es menor que 0.05

conclusión:

  • es estacionaria p-value = 0.01

  • El mejor modelo según auto.arima() es ARIMA(1,0,1)

  • La prueba ADF confirma que la serie es estacionaria (p-value = 0.01 < 0.05).

2. ¿Hay efectos ARCH?

Generamos el modelo ARCH a un rezago

modeloarch1 = ArchTest(rendimiento_etb, lags = 1, demean = T) # lags son los rezagos
modeloarch1
## 
##  ARCH LM-test; Null hypothesis: no ARCH effects
## 
## data:  rendimiento_etb
## Chi-squared = 37.317, df = 1, p-value = 1.004e-09

H0 = No hay efectos ARCH si el p-value es mayor que 0.05

H1 = Si hay efectos ARCH si el p-value es menor que 0.05

conclución:

  • SI hay efectos ARCH con rezogo no hay evidencia significativa de heterocedasticidad condicional

  • SI existe volatilidad

3. Determinar si hay heterocedasticidad

calcular los resuduales al cuadrado de nuestro modelo ARMA(0,0,0)

esto para conocer si hay heterocedastica

Errores_cuadrado = resid(modelo1)^2
plot(Errores_cuadrado, main = "Errores_cuadrado")

Los errores al cuadrado presentan picos aislados, indicando presencia de heterocedasticidad.

Se observa mayor concentración de volatilidad en periodos recientes.

Box.test(Errores_cuadrado, lag = 5, type = "Ljung-Box")
## 
##  Box-Ljung test
## 
## data:  Errores_cuadrado
## X-squared = 131.28, df = 5, p-value < 2.2e-16
  • Los errores al cuadrado muestran autocorrelación.

Se hace una regresión con los residuales al cuadrado rezagados esto para observar si nos enfrentamos a un modelo ARCH o no

Regresion1 = dynlm(Errores_cuadrado ~ L(Errores_cuadrado,1))

summary(Regresion1)
## 
## Time series regression with "ts" data:
## Start = 2, End = 1963
## 
## Call:
## dynlm(formula = Errores_cuadrado ~ L(Errores_cuadrado, 1))
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.005613 -0.000440 -0.000421 -0.000198  0.041316 
## 
## Coefficients:
##                         Estimate Std. Error t value Pr(>|t|)    
## (Intercept)            4.395e-04  4.738e-05   9.277  < 2e-16 ***
## L(Errores_cuadrado, 1) 1.342e-01  2.238e-02   5.995 2.42e-09 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.002037 on 1960 degrees of freedom
## Multiple R-squared:  0.018,  Adjusted R-squared:  0.0175 
## F-statistic: 35.93 on 1 and 1960 DF,  p-value: 2.423e-09

H0 = No hay efectos ARCH si el p-value es mayor que 0.05

H1 = Si hay efectos ARCH si el p-value es menor que 0.05

conclución:

  • hay efectos ARCH con un rezogo

Se revisa la autocorrelación y autocorrelación parcial

autoplot(acf(Errores_cuadrado, lag.max = 2434, ylim = c(-0.5,1))) +
  labs(title = "Autocorrelación parcial de los errores al cuadrado") +
  xlab("Rezagos") +
  ylab("Autocorrelación parcial")

4. Generar el modelo GARCH

  • Modelo ARMA (1,0,1) <—– modelo efectivo
ugarch1 = ugarchspec(mean.model = list(armaOrder = c(1,1)))
#resumen
ugarch1
## 
## *---------------------------------*
## *       GARCH Model Spec          *
## *---------------------------------*
## 
## Conditional Variance Dynamics    
## ------------------------------------
## GARCH Model      : sGARCH(1,1)
## Variance Targeting   : FALSE 
## 
## Conditional Mean Dynamics
## ------------------------------------
## Mean Model       : ARFIMA(1,0,1)
## Include Mean     : TRUE 
## GARCH-in-Mean        : FALSE 
## 
## Conditional Distribution
## ------------------------------------
## Distribution :  norm 
## Includes Skew    :  FALSE 
## Includes Shape   :  FALSE 
## Includes Lambda  :  FALSE
ugfit1 = ugarchfit(spec = ugarch1, data = rendimiento_etb)
ugfit1
## 
## *---------------------------------*
## *          GARCH Model Fit        *
## *---------------------------------*
## 
## Conditional Variance Dynamics    
## -----------------------------------
## GARCH Model  : sGARCH(1,1)
## Mean Model   : ARFIMA(1,0,1)
## Distribution : norm 
## 
## Optimal Parameters
## ------------------------------------
##         Estimate  Std. Error   t value Pr(>|t|)
## mu     -0.000232    0.000302  -0.76824 0.442344
## ar1     0.399401    0.148799   2.68417 0.007271
## ma1    -0.528564    0.137248  -3.85115 0.000118
## omega   0.000017    0.000001  15.90677 0.000000
## alpha1  0.087185    0.009319   9.35575 0.000000
## beta1   0.877250    0.006880 127.51616 0.000000
## 
## Robust Standard Errors:
##         Estimate  Std. Error  t value Pr(>|t|)
## mu     -0.000232    0.000328 -0.70694 0.479601
## ar1     0.399401    0.159490  2.50423 0.012272
## ma1    -0.528564    0.143537 -3.68242 0.000231
## omega   0.000017    0.000003  6.28222 0.000000
## alpha1  0.087185    0.032067  2.71880 0.006552
## beta1   0.877250    0.023247 37.73625 0.000000
## 
## LogLikelihood : 4995.698 
## 
## Information Criteria
## ------------------------------------
##                     
## Akaike       -5.0837
## Bayes        -5.0667
## Shibata      -5.0838
## Hannan-Quinn -5.0775
## 
## Weighted Ljung-Box Test on Standardized Residuals
## ------------------------------------
##                         statistic p-value
## Lag[1]                      1.756  0.1851
## Lag[2*(p+q)+(p+q)-1][5]     2.189  0.9114
## Lag[4*(p+q)+(p+q)-1][9]     4.089  0.6700
## d.o.f=2
## H0 : No serial correlation
## 
## Weighted Ljung-Box Test on Standardized Squared Residuals
## ------------------------------------
##                         statistic p-value
## Lag[1]                   0.004787  0.9448
## Lag[2*(p+q)+(p+q)-1][5]  0.409989  0.9706
## Lag[4*(p+q)+(p+q)-1][9]  0.585002  0.9974
## d.o.f=2
## 
## Weighted ARCH LM Tests
## ------------------------------------
##             Statistic Shape Scale P-Value
## ARCH Lag[3]    0.1709 0.500 2.000  0.6793
## ARCH Lag[5]    0.3131 1.440 1.667  0.9368
## ARCH Lag[7]    0.3644 2.315 1.543  0.9890
## 
## Nyblom stability test
## ------------------------------------
## Joint Statistic:  3.7494
## Individual Statistics:              
## mu     0.54541
## ar1    0.35556
## ma1    0.43519
## omega  0.22269
## alpha1 0.20417
## beta1  0.05814
## 
## 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           0.3371 0.7361    
## Negative Sign Bias  0.2364 0.8132    
## Positive Sign Bias  0.8038 0.4216    
## Joint Effect        0.7313 0.8658    
## 
## 
## Adjusted Pearson Goodness-of-Fit Test:
## ------------------------------------
##   group statistic p-value(g-1)
## 1    20      1096   1.359e-220
## 2    30      1280   4.671e-251
## 3    40      1396   1.018e-267
## 4    50      1477   4.860e-277
## 
## 
## Elapsed time : 0.3137732
# ver coeficientes
ugfit1@fit$coef
##            mu           ar1           ma1         omega        alpha1 
## -0.0002321637  0.3994007903 -0.5285642053  0.0000168269  0.0871849976 
##         beta1 
##  0.8772504338
#imprimir varianza
ug_var1 = ugfit1@fit$var
autoplot(ts(ug_var1))

# residuales
ug_resid1 = (ugfit1@fit$residuals)^2
autoplot(ts(ug_resid1))

Conclusiones del Modelo GARCH

  • El modelo GARCH(1,1) estimado tiene un coeficiente β₁ ≈ 0.877, lo que indica alta persistencia en la volatilidad.

  • El coeficiente α₁ ≈ 0.087 sugiere que los shocks recientes afectan la varianza condicional, pero su impacto es moderado.

  • La serie de varianzas condicionales muestra picos de volatilidad concentrados en ciertos periodos, como se observa en el gráfico de varianza.

  • Los residuos estandarizados presentan baja autocorrelación, validando un buen ajuste del modelo.

  • Las pruebas de Ljung-Box y ARCH LM confirman la ausencia de correlación serial y heterocedasticidad remanente en los residuos.

5. Pronostico

# pronostico 
ug_forecast1 = ugarchforecast(ugfit1, n.ahead = 30)
ug_forecast1
## 
## *------------------------------------*
## *       GARCH Model Forecast         *
## *------------------------------------*
## Model: sGARCH
## Horizon: 30
## Roll Steps: 0
## Out of Sample: 0
## 
## 0-roll forecast [T0=2024-12-30]:
##          Series   Sigma
## T+1  -0.0002958 0.01284
## T+2  -0.0002576 0.01326
## T+3  -0.0002423 0.01365
## T+4  -0.0002362 0.01402
## T+5  -0.0002338 0.01437
## T+6  -0.0002328 0.01469
## T+7  -0.0002324 0.01500
## T+8  -0.0002323 0.01529
## T+9  -0.0002322 0.01557
## T+10 -0.0002322 0.01583
## T+11 -0.0002322 0.01608
## T+12 -0.0002322 0.01631
## T+13 -0.0002322 0.01654
## T+14 -0.0002322 0.01675
## T+15 -0.0002322 0.01695
## T+16 -0.0002322 0.01715
## T+17 -0.0002322 0.01733
## T+18 -0.0002322 0.01751
## T+19 -0.0002322 0.01768
## T+20 -0.0002322 0.01784
## T+21 -0.0002322 0.01799
## T+22 -0.0002322 0.01814
## T+23 -0.0002322 0.01828
## T+24 -0.0002322 0.01841
## T+25 -0.0002322 0.01854
## T+26 -0.0002322 0.01867
## T+27 -0.0002322 0.01878
## T+28 -0.0002322 0.01890
## T+29 -0.0002322 0.01901
## T+30 -0.0002322 0.01911
# Último precio observado (ejemplo, debes reemplazar con el valor real)
P_t <- etb$Último[nrow(etb)]

# Pronósticos de rendimiento
R_forecasts <- c(0.0006389, 0.0006389, 0.0006389, 0.0006389, 0.0006389)



# Conclusiones Finales:
pronosticar_precios_garch <- function(ultimo_precio, rendimiento_pronosticado, horizonte = 30) {
  # Validar inputs
  if(horizonte < 1) stop("El horizonte debe ser ≥ 1")
  if(length(rendimiento_pronosticado) == 0) stop("Se requiere al menos un valor de rendimiento")
  
  # Vector de precios pronosticados
  precios_pronosticados <- numeric(horizonte)
  
  # Usar el primer valor de rendimiento para todos los períodos (modelo constante)
  r <- rendimiento_pronosticado[1]
  
  # Calcular precios recursivamente
  precios_pronosticados[1] <- ultimo_precio * (1 + r)
  for(i in 2:horizonte) {
    precios_pronosticados[i] <- precios_pronosticados[i-1] * (1 + r)
  }
  
  # Crear data frame con resultados
  resultados <- data.frame(
    Periodo = paste0("T+", 1:horizonte),
    Precio = precios_pronosticados,
    Rendimiento_Acumulado = (precios_pronosticados/ultimo_precio - 1) * 100
  )
  
  return(resultados)
}

# Uso de la función con tus datos:
resultados <- pronosticar_precios_garch(
  ultimo_precio = etb$Último[nrow(etb)],
  rendimiento_pronosticado = 0.0006389,  # Valor de tu pronóstico GARCH
  horizonte = 30
)

# Ver resultados
print(resultados)
##    Periodo   Precio Rendimiento_Acumulado
## 1      T+1 507.3239             0.0638900
## 2      T+2 507.6481             0.1278208
## 3      T+3 507.9724             0.1917925
## 4      T+4 508.2969             0.2558050
## 5      T+5 508.6217             0.3198585
## 6      T+6 508.9466             0.3839528
## 7      T+7 509.2718             0.4480881
## 8      T+8 509.5972             0.5122644
## 9      T+9 509.9228             0.5764817
## 10    T+10 510.2486             0.6407400
## 11    T+11 510.5745             0.7050394
## 12    T+12 510.9008             0.7693798
## 13    T+13 511.2272             0.8337614
## 14    T+14 511.5538             0.8981841
## 15    T+15 511.8806             0.9626479
## 16    T+16 512.2077             1.0271530
## 17    T+17 512.5349             1.0916992
## 18    T+18 512.8624             1.1562867
## 19    T+19 513.1900             1.2209154
## 20    T+20 513.5179             1.2855855
## 21    T+21 513.8460             1.3502968
## 22    T+22 514.1743             1.4150495
## 23    T+23 514.5028             1.4798436
## 24    T+24 514.8315             1.5446791
## 25    T+25 515.1604             1.6095560
## 26    T+26 515.4896             1.6744743
## 27    T+27 515.8189             1.7394342
## 28    T+28 516.1485             1.8044355
## 29    T+29 516.4783             1.8694783
## 30    T+30 516.8082             1.9345627

sobre los rendimientos

  • Comportamiento: Los rendimientos muestran una media cercana a cero (0.000639) con volatilidad variable

  • Estacionariedad: Confirmada por la prueba ADF (p-value=0.01)

  • Autocorrelación: El modelo ARIMA(0,0,0) sugiere que no hay estructura lineal en los rendimientos

  • El modelo GARCH estimado mostró alta persistencia (β₁ ≈ 1), pero con un impacto casi nulo de shocks recientes (α₁ ≈ 0).

Efectos ARCH/GARCH

Presencia de heterocedasticidad:

  • Prueba ARCH altamente significativa (p-value < 2.2e-16)

  • Autocorrelación en errores al cuadrado (Ljung-Box p-value < 2.2e-16)

  • Regresión de errores cuadrados muestra dependencia significativa (β=0.294, p<2e-16)

Modelo GARCH Estimado

σ²ₜ = 7.32e-06 + 0.0787ε²ₜ₋₁ + 0.904σ²ₜ₋₁

  • Alta persistencia en volatilidad (β₁=0.904)

  • Los shocks recientes tienen impacto moderado (α₁=0.0787)

  • La suma α₁+β₁ ≈ 0.983 (<1) indica proceso estacionario pero con alta memoria

Pronósticos

Rendimientos: Constantes en ~0.0006389 (0.06389% diario)

Precios proyectados:

T+1: 23,655.1

T+5: 23,715.61 (+0.26% en 5 días)

T+30: 24,097.33 (+1.87% en 30 días)

  • Clustering de volatilidad: Los períodos de alta volatilidad tienden a agruparse temporalmente

  • Persistencia: La volatilidad muestra memoria de largo plazo (β₁ cercano a 1)

Conclusiones Finales

Sobre los Rendimientos

  • Comportamiento: Los rendimientos diarios muestran una media cercana a cero (-0.000232) con volatilidad variable a lo largo del tiempo.

  • Estacionariedad: Confirmada por la prueba ADF (p-value < 0.05), indicando que los rendimientos son estacionarios.

  • Autocorrelación: El modelo ARFIMA(1,0,1) ajustado sugiere la existencia de una débil estructura temporal en los rendimientos.

  • El modelo GARCH(1,1) estimado mostró alta persistencia en la volatilidad (β₁ ≈ 0.877) y un impacto moderado de los shocks recientes (α₁ ≈ 0.087).

Efectos ARCH/GARCH

Presencia de heterocedasticidad:

  • La prueba ARCH detectó heterocedasticidad (p-value < 0.05).

  • La autocorrelación de los errores al cuadrado fue significativa, confirmando variabilidad en la volatilidad.

  • La regresión de errores cuadrados mostró dependencia significativa, indicando efectos ARCH en la serie.

Modelo GARCH Estimado

La varianza condicional sigue la siguiente forma:

\[ \sigma^2_t = 1.68 \times 10^{-5} + 0.087 \epsilon^2_{t-1} + 0.877 \sigma^2_{t-1} \]

  • Alta persistencia en la volatilidad (β₁ = 0.877).

  • Impacto moderado de shocks recientes (α₁ = 0.087).

  • La suma α₁ + β₁ ≈ 0.964 (menor a 1), indicando un proceso estacionario pero con larga memoria en la volatilidad.

Pronósticos

  • Rendimientos esperados: Constantes alrededor de -0.000232 (-0.0232% diario).

  • Clustering de Volatilidad: Los períodos de alta volatilidad tienden a agruparse.

  • Persistencia: La volatilidad muestra memoria de largo plazo debido al alto valor de β₁.