## ============================================================
## UAS ANALISIS RUNTUN WAKTU TERAPAN — STUDI KASUS 1
## Volatilitas return harian saham ITMG dengan model ARCH/GARCH
## ============================================================
# install.packages(c("quantmod","tseries","FinTS","rugarch",
#                    "PerformanceAnalytics","forecast"))
library(quantmod)
## Loading required package: xts
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## Loading required package: TTR
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(tseries)
library(FinTS)                 # ArchTest
library(rugarch)
## Loading required package: parallel
library(PerformanceAnalytics)  # skewness, kurtosis
## 
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
## 
##     legend
# Harga penutupan harian ITMG (Bursa Efek Indonesia), via Yahoo Finance
KODE_SAHAM <- "ITMG.JK"
getSymbols(KODE_SAHAM, src = "yahoo",
           from = "2021-01-01", to = "2026-09-01", auto.assign = TRUE)
## Warning: ITMG.JK contains missing values. Some functions will not work if
## objects contain missing values in the middle of the series. Consider using
## na.omit(), na.approx(), na.fill(), etc to remove or replace them.
## [1] "ITMG.JK"
harga <- na.omit(Cl(get(KODE_SAHAM)))
names(harga) <- "Close"

# --- Cadangan jika tidak ada internet: baca dari CSV ---
# df <- read.csv("data_ITMG.csv"); df$Date <- as.Date(df$Date)
# harga <- xts(df$Close, order.by = df$Date); names(harga) <- "Close"

plot(harga, main = "Harga Penutupan Saham ITMG")

return_log <- na.omit(diff(log(harga)))
names(return_log) <- "Return"
length(return_log)
## [1] 1363
plot(return_log, main = "Return Log Harian ITMG")

summary(as.numeric(return_log))
##       Min.    1st Qu.     Median       Mean    3rd Qu.       Max. 
## -0.1118781 -0.0098787  0.0000000  0.0004742  0.0100503  0.1489084
sd(return_log)
## [1] 0.02201398
skewness(return_log)
## [1] 0.3290638
kurtosis(return_log)          # EXCESS kurtosis (> 0 berarti fat tail)
## [1] 4.463372
jarque.bera.test(return_log)
## 
##  Jarque Bera Test
## 
## data:  return_log
## X-squared = 1156, df = 2, p-value < 2.2e-16
adf.test(return_log)
## Warning in adf.test(return_log): p-value smaller than printed p-value
## 
##  Augmented Dickey-Fuller Test
## 
## data:  return_log
## Dickey-Fuller = -10.087, Lag order = 11, p-value = 0.01
## alternative hypothesis: stationary
pp.test(return_log)
## Warning in pp.test(return_log): p-value smaller than printed p-value
## 
##  Phillips-Perron Unit Root Test
## 
## data:  return_log
## Dickey-Fuller Z(alpha) = -1382.4, Truncation lag parameter = 7, p-value
## = 0.01
## alternative hypothesis: stationary
acf(return_log, main = "ACF Return")

pacf(return_log, main = "PACF Return")

model_mean <- tryCatch({
  library(forecast)
  auto.arima(return_log, max.d = 0, seasonal = FALSE)
}, error = function(e) arima(return_log, order = c(0, 0, 0)))
## 
## Attaching package: 'forecast'
## The following object is masked from 'package:FinTS':
## 
##     Acf
model_mean
## Series: return_log 
## ARIMA(0,0,0) with zero mean 
## 
## sigma^2 = 0.0004845:  log likelihood = 3267.48
## AIC=-6532.97   AICc=-6532.97   BIC=-6527.75
resid_mean <- residuals(model_mean)
acf(as.numeric(resid_mean)^2, main = "ACF Residual Kuadrat")

ArchTest(resid_mean, lags = 12)      # H0: tidak ada efek ARCH
## 
##  ARCH LM-test; Null hypothesis: no ARCH effects
## 
## data:  resid_mean
## Chi-squared = 61.236, df = 12, p-value = 1.342e-08
## ============================================================
## 7. TRIAL AND ERROR SPESIFIKASI MODEL
## ============================================================
coba_model <- function(nama, vmodel, order, arma = c(0, 0), dist = "std",
                       submodel = NULL, archm = FALSE) {
  vm <- list(model = vmodel, garchOrder = order)
  if (!is.null(submodel)) vm$submodel <- submodel
  spec <- ugarchspec(
    variance.model = vm,
    mean.model = list(armaOrder = arma, include.mean = TRUE,
                      archm = archm, archpow = 1),
    distribution.model = dist)
  fit <- tryCatch(ugarchfit(spec, data = return_log, solver = "hybrid"),
                  error = function(e) NULL)
  arma_txt <- paste0("(", arma[1], ",", arma[2], ")")
  if (is.null(fit) || convergence(fit) != 0) {
    return(data.frame(Model = nama, ARMA = arma_txt, Dist = dist,
                      LogLik = NA, AIC = NA, BIC = NA, Persistensi = NA,
                      Param_tdk_sig = "gagal konvergen",
                      LB_z2_p = NA, ARCHLM_p = NA, Layak = FALSE))
  }
  ic <- infocriteria(fit)
  mc <- fit@fit$matcoef
  par_cek <- rownames(mc)[!grepl("^(mu|ar[0-9]+|ma[0-9]+|shape|skew)$", rownames(mc))]
  tdk_sig <- par_cek[which(!(mc[par_cek, 4] <= 0.05))]
  z    <- as.numeric(residuals(fit, standardize = TRUE))
  lb   <- Box.test(z^2, lag = 12, type = "Ljung-Box")$p.value
  alm  <- ArchTest(z, lags = 12)$p.value
  pers <- persistence(fit)
  # Layak: parameter varians (kecuali omega) signifikan, residual bersih
  # dari efek ARCH, persistensi < 1 (kecuali IGARCH)
  layak <- length(setdiff(tdk_sig, "omega")) == 0 &&
           lb > 0.05 && alm > 0.05 && (pers < 1 || vmodel == "iGARCH")
  data.frame(Model = nama, ARMA = arma_txt, Dist = dist,
             LogLik = round(likelihood(fit), 2),
             AIC = round(ic[1], 4), BIC = round(ic[2], 4),
             Persistensi = round(pers, 4),
             Param_tdk_sig = ifelse(length(tdk_sig) == 0, "-", paste(tdk_sig, collapse = ",")),
             LB_z2_p = round(lb, 4), ARCHLM_p = round(alm, 4),
             Layak = layak)
}

spesifikasi <- list(
  "ARCH(1)"        = list("sGARCH",   c(1, 0)),
  "ARCH(2)"        = list("sGARCH",   c(2, 0)),
  "ARCH(3)"        = list("sGARCH",   c(3, 0)),
  "GARCH(1,1)"     = list("sGARCH",   c(1, 1)),
  "GARCH(1,2)"     = list("sGARCH",   c(1, 2)),
  "GARCH(2,1)"     = list("sGARCH",   c(2, 1)),
  "GARCH(2,2)"     = list("sGARCH",   c(2, 2)),
  "GARCH-M(1,1)"   = list("sGARCH",   c(1, 1), archm = TRUE),
  "IGARCH(1,1)"    = list("iGARCH",   c(1, 1)),
  "EGARCH(1,1)"    = list("eGARCH",   c(1, 1)),
  "EGARCH(1,2)"    = list("eGARCH",   c(1, 2)),
  "EGARCH(2,1)"    = list("eGARCH",   c(2, 1)),
  "EGARCH-M(1,1)"  = list("eGARCH",   c(1, 1), archm = TRUE),
  "GJR-GARCH(1,1)" = list("gjrGARCH", c(1, 1)),
  "GJR-GARCH(2,1)" = list("gjrGARCH", c(2, 1)),
  "TGARCH(1,1)"    = list("fGARCH",   c(1, 1), submodel = "TGARCH"))

coba_dari_nama <- function(nama, arma = c(0, 0), dist = "std") {
  s <- spesifikasi[[nama]]
  coba_model(nama, s[[1]], s[[2]], arma = arma, dist = dist,
             submodel = s$submodel, archm = isTRUE(s$archm))
}

## Tahap 1 — jenis model & orde (mean konstanta, Student-t)
tahap1 <- do.call(rbind, lapply(names(spesifikasi), coba_dari_nama))
tahap1 <- tahap1[order(tahap1$AIC), ]
print(tahap1, row.names = FALSE)
##           Model  ARMA Dist  LogLik     AIC     BIC Persistensi
##     EGARCH(1,1) (0,0)  std 3506.10 -5.1359 -5.1129      0.9898
##     EGARCH(1,2) (0,0)  std 3506.74 -5.1353 -5.1085      0.9874
##     EGARCH(2,1) (0,0)  std 3507.61 -5.1352 -5.1045      0.9917
##   EGARCH-M(1,1) (0,0)  std 3506.53 -5.1350 -5.1082      0.9884
##     TGARCH(1,1) (0,0)  std 3504.10 -5.1329 -5.1100      0.9911
##  GJR-GARCH(1,1) (0,0)  std 3500.00 -5.1269 -5.1040      0.9990
##  GJR-GARCH(2,1) (0,0)  std 3501.50 -5.1262 -5.0956      0.9990
##     IGARCH(1,1) (0,0)  std 3495.09 -5.1227 -5.1073      1.0000
##      GARCH(1,1) (0,0)  std 3495.06 -5.1211 -5.1020      0.9990
##    GARCH-M(1,1) (0,0)  std 3495.60 -5.1205 -5.0975      0.9990
##      GARCH(1,2) (0,0)  std 3495.40 -5.1202 -5.0972      0.9990
##      GARCH(2,1) (0,0)  std 3495.29 -5.1200 -5.0970      0.9990
##      GARCH(2,2) (0,0)  std 3495.40 -5.1187 -5.0919      0.9990
##         ARCH(3) (0,0)  std 3448.70 -5.0517 -5.0287      0.9374
##         ARCH(2) (0,0)  std 3442.66 -5.0443 -5.0251      0.8763
##         ARCH(1) (0,0)  std 3426.80 -5.0224 -5.0071      0.6502
##                      Param_tdk_sig LB_z2_p ARCHLM_p Layak
##                                  -  0.4291   0.4243  TRUE
##                                  -  0.4362   0.4268  TRUE
##               alpha1,alpha2,gamma2  0.3047   0.3069 FALSE
##                              archm  0.4489   0.4431 FALSE
##                              omega  0.5266   0.5261  TRUE
##                              omega  0.2894   0.2739  TRUE
##  omega,alpha1,alpha2,gamma1,gamma2  0.2325   0.2284 FALSE
##                              omega  0.5193   0.5201  TRUE
##                              omega  0.5176   0.5186  TRUE
##                        archm,omega  0.5315   0.5317 FALSE
##                        omega,beta2  0.5250   0.5274 FALSE
##                omega,alpha1,alpha2  0.5181   0.5193 FALSE
##          omega,alpha1,alpha2,beta2  0.5250   0.5274 FALSE
##                                  -  0.0029   0.0022 FALSE
##                                  -  0.0000   0.0001 FALSE
##                                  -  0.0000   0.0000 FALSE
## Tahap 2 — distribusi error untuk 3 model layak terbaik
kandidat <- head(tahap1[tahap1$Layak, ], 3)
if (nrow(kandidat) == 0) kandidat <- head(tahap1, 3)
tahap2 <- do.call(rbind, lapply(kandidat$Model, function(m)
  do.call(rbind, lapply(c("norm", "std", "sstd", "ged"), function(d)
    coba_dari_nama(m, dist = d)))))
tahap2 <- tahap2[order(tahap2$AIC), ]
print(tahap2, row.names = FALSE)
##        Model  ARMA Dist  LogLik     AIC     BIC Persistensi Param_tdk_sig
##  EGARCH(1,1) (0,0)  ged 3507.09 -5.1373 -5.1144      0.9905  omega,gamma1
##  EGARCH(1,2) (0,0)  ged 3507.97 -5.1371 -5.1104      0.9877         omega
##  EGARCH(1,1) (0,0)  std 3506.10 -5.1359 -5.1129      0.9898             -
##  EGARCH(1,2) (0,0)  std 3506.74 -5.1353 -5.1085      0.9874             -
##  TGARCH(1,1) (0,0)  ged 3505.50 -5.1350 -5.1120      0.9914         omega
##  EGARCH(1,1) (0,0) sstd 3506.45 -5.1349 -5.1081      0.9894             -
##  EGARCH(1,2) (0,0) sstd 3507.11 -5.1344 -5.1038      0.9869             -
##  TGARCH(1,1) (0,0)  std 3504.10 -5.1329 -5.1100      0.9911         omega
##  TGARCH(1,1) (0,0) sstd 3504.46 -5.1320 -5.1052      0.9910         omega
##  EGARCH(1,2) (0,0) norm 3428.88 -5.0226 -4.9996      0.9881         omega
##  EGARCH(1,1) (0,0) norm 3426.50 -5.0205 -5.0014      0.9909             -
##  TGARCH(1,1) (0,0) norm 3424.45 -5.0175 -4.9984      0.9990             -
##  LB_z2_p ARCHLM_p Layak
##   0.3933   0.3817 FALSE
##   0.4086   0.3922  TRUE
##   0.4291   0.4243  TRUE
##   0.4362   0.4268  TRUE
##   0.4798   0.4726  TRUE
##   0.4345   0.4310  TRUE
##   0.4404   0.4321  TRUE
##   0.5266   0.5261  TRUE
##   0.5292   0.5296  TRUE
##   0.3962   0.3748  TRUE
##   0.3733   0.3563  TRUE
##   0.4333   0.4196  TRUE
## Tahap 3 — mean model ARMA untuk kombinasi layak terbaik tahap 2
terbaik2 <- head(tahap2[tahap2$Layak, ], 1)
if (nrow(terbaik2) == 0) terbaik2 <- head(tahap2, 1)
tahap3 <- do.call(rbind, lapply(list(c(0, 0), c(1, 0), c(0, 1), c(1, 1)), function(a)
  coba_dari_nama(terbaik2$Model, arma = a, dist = terbaik2$Dist)))
tahap3 <- tahap3[order(tahap3$AIC), ]
print(tahap3, row.names = FALSE)
##        Model  ARMA Dist  LogLik     AIC     BIC Persistensi Param_tdk_sig
##  EGARCH(1,2) (1,0)  ged 3509.02 -5.1372 -5.1066      0.9873         omega
##  EGARCH(1,2) (0,1)  ged 3508.99 -5.1372 -5.1066      0.9873         omega
##  EGARCH(1,2) (0,0)  ged 3507.97 -5.1371 -5.1104      0.9877         omega
##  EGARCH(1,2) (1,1)  ged 3509.16 -5.1360 -5.1015      0.9872         omega
##  LB_z2_p ARCHLM_p Layak
##   0.4273   0.4077  TRUE
##   0.4268   0.4072  TRUE
##   0.4086   0.3922  TRUE
##   0.4197   0.4020  TRUE
## Rekap seluruh percobaan
semua <- unique(rbind(tahap1, tahap2, tahap3))
semua <- semua[order(!semua$Layak, semua$AIC), ]
print(semua, row.names = FALSE)
##           Model  ARMA Dist  LogLik     AIC     BIC Persistensi
##     EGARCH(1,2) (1,0)  ged 3509.02 -5.1372 -5.1066      0.9873
##     EGARCH(1,2) (0,1)  ged 3508.99 -5.1372 -5.1066      0.9873
##     EGARCH(1,2) (0,0)  ged 3507.97 -5.1371 -5.1104      0.9877
##     EGARCH(1,2) (1,1)  ged 3509.16 -5.1360 -5.1015      0.9872
##     EGARCH(1,1) (0,0)  std 3506.10 -5.1359 -5.1129      0.9898
##     EGARCH(1,2) (0,0)  std 3506.74 -5.1353 -5.1085      0.9874
##     TGARCH(1,1) (0,0)  ged 3505.50 -5.1350 -5.1120      0.9914
##     EGARCH(1,1) (0,0) sstd 3506.45 -5.1349 -5.1081      0.9894
##     EGARCH(1,2) (0,0) sstd 3507.11 -5.1344 -5.1038      0.9869
##     TGARCH(1,1) (0,0)  std 3504.10 -5.1329 -5.1100      0.9911
##     TGARCH(1,1) (0,0) sstd 3504.46 -5.1320 -5.1052      0.9910
##  GJR-GARCH(1,1) (0,0)  std 3500.00 -5.1269 -5.1040      0.9990
##     IGARCH(1,1) (0,0)  std 3495.09 -5.1227 -5.1073      1.0000
##      GARCH(1,1) (0,0)  std 3495.06 -5.1211 -5.1020      0.9990
##     EGARCH(1,2) (0,0) norm 3428.88 -5.0226 -4.9996      0.9881
##     EGARCH(1,1) (0,0) norm 3426.50 -5.0205 -5.0014      0.9909
##     TGARCH(1,1) (0,0) norm 3424.45 -5.0175 -4.9984      0.9990
##     EGARCH(1,1) (0,0)  ged 3507.09 -5.1373 -5.1144      0.9905
##     EGARCH(2,1) (0,0)  std 3507.61 -5.1352 -5.1045      0.9917
##   EGARCH-M(1,1) (0,0)  std 3506.53 -5.1350 -5.1082      0.9884
##  GJR-GARCH(2,1) (0,0)  std 3501.50 -5.1262 -5.0956      0.9990
##    GARCH-M(1,1) (0,0)  std 3495.60 -5.1205 -5.0975      0.9990
##      GARCH(1,2) (0,0)  std 3495.40 -5.1202 -5.0972      0.9990
##      GARCH(2,1) (0,0)  std 3495.29 -5.1200 -5.0970      0.9990
##      GARCH(2,2) (0,0)  std 3495.40 -5.1187 -5.0919      0.9990
##         ARCH(3) (0,0)  std 3448.70 -5.0517 -5.0287      0.9374
##         ARCH(2) (0,0)  std 3442.66 -5.0443 -5.0251      0.8763
##         ARCH(1) (0,0)  std 3426.80 -5.0224 -5.0071      0.6502
##                      Param_tdk_sig LB_z2_p ARCHLM_p Layak
##                              omega  0.4273   0.4077  TRUE
##                              omega  0.4268   0.4072  TRUE
##                              omega  0.4086   0.3922  TRUE
##                              omega  0.4197   0.4020  TRUE
##                                  -  0.4291   0.4243  TRUE
##                                  -  0.4362   0.4268  TRUE
##                              omega  0.4798   0.4726  TRUE
##                                  -  0.4345   0.4310  TRUE
##                                  -  0.4404   0.4321  TRUE
##                              omega  0.5266   0.5261  TRUE
##                              omega  0.5292   0.5296  TRUE
##                              omega  0.2894   0.2739  TRUE
##                              omega  0.5193   0.5201  TRUE
##                              omega  0.5176   0.5186  TRUE
##                              omega  0.3962   0.3748  TRUE
##                                  -  0.3733   0.3563  TRUE
##                                  -  0.4333   0.4196  TRUE
##                       omega,gamma1  0.3933   0.3817 FALSE
##               alpha1,alpha2,gamma2  0.3047   0.3069 FALSE
##                              archm  0.4489   0.4431 FALSE
##  omega,alpha1,alpha2,gamma1,gamma2  0.2325   0.2284 FALSE
##                        archm,omega  0.5315   0.5317 FALSE
##                        omega,beta2  0.5250   0.5274 FALSE
##                omega,alpha1,alpha2  0.5181   0.5193 FALSE
##          omega,alpha1,alpha2,beta2  0.5250   0.5274 FALSE
##                                  -  0.0029   0.0022 FALSE
##                                  -  0.0000   0.0001 FALSE
##                                  -  0.0000   0.0000 FALSE
## ============================================================
## 8. MODEL TERPILIH: EGARCH(1,1), Student-t, mean konstanta
## ============================================================
# Dasar pemilihan: model layak dengan BIC terkecil, seluruh parameter
# signifikan, selisih AIC dengan model ber-AIC terkecil < 2 (skala total),
# dan uji LR menolak tambahan orde (lihat di bawah).
spec_terbaik <- ugarchspec(
  variance.model = list(model = "eGARCH", garchOrder = c(1, 1)),
  mean.model     = list(armaOrder = c(0, 0), include.mean = TRUE),
  distribution.model = "std")
model_terbaik <- ugarchfit(spec_terbaik, data = return_log, solver = "hybrid")
model_terbaik
## 
## *---------------------------------*
## *          GARCH Model Fit        *
## *---------------------------------*
## 
## Conditional Variance Dynamics    
## -----------------------------------
## GARCH Model  : eGARCH(1,1)
## Mean Model   : ARFIMA(0,0,0)
## Distribution : std 
## 
## Optimal Parameters
## ------------------------------------
##         Estimate  Std. Error  t value Pr(>|t|)
## mu      0.000539    0.000380   1.4162 0.156727
## omega  -0.079796    0.009286  -8.5935 0.000000
## alpha1  0.046223    0.017175   2.6913 0.007117
## beta1   0.989760    0.001418 698.1868 0.000000
## gamma1  0.160712    0.018735   8.5779 0.000000
## shape   3.794807    0.420207   9.0308 0.000000
## 
## Robust Standard Errors:
##         Estimate  Std. Error  t value Pr(>|t|)
## mu      0.000539    0.000370   1.4549 0.145685
## omega  -0.079796    0.016234  -4.9155 0.000001
## alpha1  0.046223    0.020372   2.2690 0.023269
## beta1   0.989760    0.002038 485.6377 0.000000
## gamma1  0.160712    0.019282   8.3348 0.000000
## shape   3.794807    0.413841   9.1697 0.000000
## 
## LogLikelihood : 3506.096 
## 
## Information Criteria
## ------------------------------------
##                     
## Akaike       -5.1359
## Bayes        -5.1129
## Shibata      -5.1359
## Hannan-Quinn -5.1273
## 
## Weighted Ljung-Box Test on Standardized Residuals
## ------------------------------------
##                         statistic p-value
## Lag[1]                    0.09786  0.7544
## Lag[2*(p+q)+(p+q)-1][2]   0.28434  0.8045
## Lag[4*(p+q)+(p+q)-1][5]   1.91209  0.6393
## d.o.f=0
## H0 : No serial correlation
## 
## Weighted Ljung-Box Test on Standardized Squared Residuals
## ------------------------------------
##                         statistic p-value
## Lag[1]                     0.4897  0.4841
## Lag[2*(p+q)+(p+q)-1][5]    1.6173  0.7110
## Lag[4*(p+q)+(p+q)-1][9]    3.4699  0.6795
## d.o.f=2
## 
## Weighted ARCH LM Tests
## ------------------------------------
##             Statistic Shape Scale P-Value
## ARCH Lag[3]    0.8847 0.500 2.000  0.3469
## ARCH Lag[5]    1.8854 1.440 1.667  0.4971
## ARCH Lag[7]    2.8033 2.315 1.543  0.5514
## 
## Nyblom stability test
## ------------------------------------
## Joint Statistic:  1.9132
## Individual Statistics:              
## mu     0.03921
## omega  0.41886
## alpha1 0.71538
## beta1  0.39108
## gamma1 0.46362
## shape  0.22102
## 
## 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           1.5094 0.1314    
## Negative Sign Bias  0.9280 0.3536    
## Positive Sign Bias  0.3323 0.7397    
## Joint Effect        2.4746 0.4799    
## 
## 
## Adjusted Pearson Goodness-of-Fit Test:
## ------------------------------------
##   group statistic p-value(g-1)
## 1    20     17.53       0.5541
## 2    30     28.42       0.4954
## 3    40     43.28       0.2936
## 4    50     36.74       0.9016
## 
## 
## Elapsed time : 0.287107
# Uji likelihood ratio: EGARCH(1,2) vs EGARCH(1,1), keduanya Student-t
fit_e12 <- ugarchfit(ugarchspec(
  variance.model = list(model = "eGARCH", garchOrder = c(1, 2)),
  mean.model     = list(armaOrder = c(0, 0), include.mean = TRUE),
  distribution.model = "std"), data = return_log, solver = "hybrid")
LR <- 2 * (likelihood(fit_e12) - likelihood(model_terbaik))
c(LR = LR, p_value = 1 - pchisq(LR, df = 1))
##        LR   p_value 
## 1.2812604 0.2576648
# Selisih AIC skala total terhadap model layak ber-AIC terkecil
n_obs <- length(return_log)
(semua$AIC[semua$Layak][1] - infocriteria(model_terbaik)[1]) * n_obs   # |nilai| < 2 -> setara
## [1] -1.811155
resid_std <- residuals(model_terbaik, standardize = TRUE)
Box.test(resid_std,   lag = 12, type = "Ljung-Box")
## 
##  Box-Ljung test
## 
## data:  resid_std
## X-squared = 15.783, df = 12, p-value = 0.2014
Box.test(resid_std^2, lag = 12, type = "Ljung-Box")
## 
##  Box-Ljung test
## 
## data:  resid_std^2
## X-squared = 12.208, df = 12, p-value = 0.4291
ArchTest(resid_std, lags = 12)
## 
##  ARCH LM-test; Null hypothesis: no ARCH effects
## 
## data:  resid_std
## Chi-squared = 12.269, df = 12, p-value = 0.4243
signbias(model_terbaik)
##                      t-value      prob sig
## Sign Bias          1.5093632 0.1314386    
## Negative Sign Bias 0.9279730 0.3535865    
## Positive Sign Bias 0.3322576 0.7397460    
## Joint Effect       2.4746365 0.4798923
nyblom(model_terbaik)
## $IndividualStat
##              [,1]
## mu     0.03921336
## omega  0.41885730
## alpha1 0.71538248
## beta1  0.39108187
## gamma1 0.46362332
## shape  0.22101987
## 
## $JointStat
## [1] 1.913167
## 
## $IndividualCritical
##   10%    5%    1% 
## 0.353 0.470 0.748 
## 
## $JointCritical
##  10%   5%   1% 
## 1.49 1.68 2.12
ni <- newsimpact(model_terbaik)
plot(ni$zx, ni$zy, type = "l", lwd = 2,
     xlab = "Guncangan (z)", ylab = "Varians bersyarat",
     main = "News Impact Curve - EGARCH(1,1)")
abline(v = 0, lty = 2)

# Kurva lebih tinggi di sisi kanan -> guncangan positif menaikkan
# volatilitas lebih besar (inverse leverage effect)
sigma_t <- sigma(model_terbaik)
plot(sigma_t, main = "Volatilitas Kondisional (Conditional SD)")

forecast_vol <- ugarchforecast(model_terbaik, n.ahead = 20)
sigma(forecast_vol)
##      2026-08-31
## T+1  0.01596296
## T+2  0.01600246
## T+3  0.01604165
## T+4  0.01608054
## T+5  0.01611912
## T+6  0.01615740
## T+7  0.01619537
## T+8  0.01623304
## T+9  0.01627042
## T+10 0.01630749
## T+11 0.01634427
## T+12 0.01638076
## T+13 0.01641695
## T+14 0.01645285
## T+15 0.01648846
## T+16 0.01652378
## T+17 0.01655881
## T+18 0.01659356
## T+19 0.01662802
## T+20 0.01666220
plot(forecast_vol, which = 3)

coef(model_terbaik)
##            mu         omega        alpha1         beta1        gamma1 
##  0.0005386905 -0.0797955852  0.0462228653  0.9897596471  0.1607120291 
##         shape 
##  3.7948065787
persistence(model_terbaik)   # untuk EGARCH = beta1
## [1] 0.9897596
halflife(model_terbaik)      # hari perdagangan
## [1] 67.34065
b <- coef(model_terbaik)
sqrt(exp(b["omega"] / (1 - b["beta1"])))   # volatilitas harian jangka panjang (aprox.)
##      omega 
## 0.02032031