HANDS ON PROGRES UAS TDS 1 NOVA

# ============================================================
#   BAB 4 — HASIL DAN PEMBAHASAN
#   Pemodelan ARIMA dan SARIMA pada Data IDX Kompas 100
# ============================================================
rm(list = ls())
set.seed(42)

library(tseries)   # Uji ADF, Jarque-Bera
## Warning: package 'tseries' was built under R version 4.5.2

## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(forecast)  # ARIMA, SARIMA, auto.arima, forecast()
## Warning: package 'forecast' was built under R version 4.5.2
library(TSA)       # EACF
## Warning: package 'TSA' was built under R version 4.5.3

## Registered S3 methods overwritten by 'TSA':
##   method       from    
##   fitted.Arima forecast
##   plot.Arima   forecast

## 
## Attaching package: 'TSA'

## The following objects are masked from 'package:stats':
## 
##     acf, arima

## The following object is masked from 'package:utils':
## 
##     tar
library(tseries)
# 4.1 Membaca Data
# ============================================================
data_idx <- read.csv(
  "C:/Users/Msi user/Downloads/Tugas Dalam Statistika I/Data Historis IDX Kompas 100 (1).csv",
  sep          = ",",
  header       = TRUE,
  fileEncoding = "UTF-8-BOM"
)

# Bersihkan nama kolom
names(data_idx) <- c("Tanggal", "Terakhir", "Pembukaan",
                     "Tertinggi", "Terendah", "Volume")

# Konversi format tanggal
data_idx$Tanggal <- as.Date(data_idx$Tanggal, format = "%m/%d/%Y")

# Bersihkan kolom numerik — hilangkan titik/koma pemisah ribuan
clean_num <- function(x) {
  x <- gsub("\\.", "", as.character(x))
  x <- gsub(",", ".", x)
  as.numeric(x)
}

data_idx$Terakhir   <- clean_num(data_idx$Terakhir)
data_idx$Pembukaan  <- clean_num(data_idx$Pembukaan)
data_idx$Tertinggi  <- clean_num(data_idx$Tertinggi)
data_idx$Terendah   <- clean_num(data_idx$Terendah)

# Urutkan dari terlama ke terbaru
data_idx <- data_idx[order(data_idx$Tanggal), ]

# Lihat struktur data
str(data_idx)
## 'data.frame':    267 obs. of  7 variables:
##  $ Tanggal  : Date, format: "2019-01-02" "2019-01-03" ...
##  $ Terakhir : num  1349 1322 1313 1296 1301 ...
##  $ Pembukaan: num  1350 1315 1320 1295 1302 ...
##  $ Tertinggi: num  1358 1324 1322 1298 1307 ...
##  $ Terendah : num  1342 1313 1313 1293 1298 ...
##  $ Volume   : chr  "3,21B" "2,22B" "2,29B" "3,19B" ...
##  $ NA       : chr  "0,28%" "1,05%" "-0,21%" "0,53%" ...
head(data_idx)
##        Tanggal Terakhir Pembukaan Tertinggi Terendah Volume   <NA>
## 245 2019-01-02  1349.05   1350.43   1357.63  1342.23  3,21B  0,28%
## 226 2019-01-03  1321.90   1314.92   1323.60  1313.33  2,22B  1,05%
## 206 2019-01-04  1312.76   1320.06   1321.70  1312.76  2,29B -0,21%
## 151 2019-01-07  1295.79   1295.07   1298.24  1292.59  3,19B  0,53%
## 128 2019-01-08  1300.97   1301.88   1306.67  1297.99  3,10B -0,18%
## 85  2019-01-10  1229.02   1236.15   1238.42  1228.84  1,69B -0,69%
tail(data_idx)
##     Tanggal Terakhir Pembukaan Tertinggi Terendah Volume   <NA>
## 254    <NA>  1327.89   1327.93   1332.89  1325.40  5,08B  0,00%
## 255    <NA>  1327.83   1327.55   1328.84  1317.48  4,54B  0,44%
## 256    <NA>  1322.03   1321.26   1329.58  1318.34  5,35B  0,22%
## 257    <NA>  1319.09   1320.50   1322.30  1312.22  6,39B  0,06%
## 258    <NA>  1318.25   1302.42   1318.25  1298.35  5,79B  1,45%
## 259    <NA>  1299.46   1303.62   1305.23  1291.16  4,37B -0,53%
# 4.2 Statistik Deskriptif Harga Penutupan IDX Kompas 100
# ============================================================
cat("======================================================\n")
## ======================================================
cat("   STATISTIK DESKRIPTIF HARGA PENUTUPAN (TERAKHIR)\n")
##    STATISTIK DESKRIPTIF HARGA PENUTUPAN (TERAKHIR)
cat("   IDX KOMPAS 100\n")
##    IDX KOMPAS 100
cat("======================================================\n")
## ======================================================
summary(data_idx$Terakhir)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1161    1251    1278    1275    1304    1349
cat(sprintf("\nJumlah observasi  : %d\n",   nrow(data_idx)))
## 
## Jumlah observasi  : 267
cat(sprintf("Standar deviasi   : %.2f\n",  sd(data_idx$Terakhir, na.rm = TRUE)))
## Standar deviasi   : 37.25
cat(sprintf("Koefisien variasi : %.2f%%\n",
            sd(data_idx$Terakhir, na.rm = TRUE) /
              mean(data_idx$Terakhir, na.rm = TRUE) * 100))
## Koefisien variasi : 2.92%
cat(sprintf("Missing value     : %d\n",    sum(is.na(data_idx$Terakhir))))
## Missing value     : 0
cat(sprintf("Periode           : %s s.d. %s\n",
            format(min(data_idx$Tanggal), "%d %B %Y"),
            format(max(data_idx$Tanggal), "%d %B %Y")))
## Periode           : NA s.d. NA
# 4.3 Membentuk Objek Time Series
# ============================================================
# frequency = 5 (hari kerja per minggu)
data.ts <- ts(
  data_idx$Terakhir,
  frequency = 5
)

cat("\nPanjang data :", length(data.ts), "observasi\n")
## 
## Panjang data : 267 observasi
cat("Frekuensi    :", frequency(data.ts), "hari kerja per minggu\n")
## Frekuensi    : 5 hari kerja per minggu
# 4.4 Visualisasi Data Time Series
# ============================================================
ts.plot(
  data.ts,
  type = "l",
  ylab = "Indeks IDX Kompas 100",
  xlab = "Waktu (Minggu ke-)",
  col  = "#1565C0",
  lwd  = 1.2
)
title(main = "Time Series Plot Indeks IDX Kompas 100\n(Data Harian Hari Kerja)")
abline(h   = mean(data.ts),
       col = "firebrick",
       lty = 2,
       lwd = 1.5)
legend("topleft",
       legend = c("Indeks IDX Kompas 100", "Rata-rata"),
       col    = c("#1565C0", "firebrick"),
       lty    = c(1, 2), lwd = 2, cex = 0.85)

# 4.5 Visualisasi Seasonal Plot
# ============================================================
seasonplot(
  data.ts,
  year.labels = TRUE,
  main        = "Seasonal Plot Indeks IDX Kompas 100\n(Siklus Mingguan — 5 Hari Kerja)",
  ylab        = "Indeks IDX Kompas 100",
  col         = rainbow(ceiling(length(data.ts) / 5)),
  cex         = 0.7
)

# 4.6 Monthplot (Pola Per Hari Kerja dalam Siklus Mingguan)
# ============================================================
monthplot(
  data.ts,
  ylab   = "Indeks IDX Kompas 100",
  col    = "#1565C0",
  main   = "Monthplot Indeks IDX Kompas 100\nper Hari Kerja dalam Siklus Mingguan",
  xlab   = "Hari ke- (1=Senin, 5=Jumat)"
)

# 4.7 Uji Kehomogenan Ragam (Fligner-Killeen)
# ============================================================
# H0: Ragam data homogen
# H1: Ragam data tidak homogen
tahun <- cycle(data.ts)
fligner.test(data_idx$Terakhir ~ tahun)
## 
##  Fligner-Killeen test of homogeneity of variances
## 
## data:  data_idx$Terakhir by tahun
## Fligner-Killeen:med chi-squared = 2.8141, df = 4, p-value = 0.5894
# 4.8 Splitting Data (Training 80% — Testing 20%)
# ============================================================
n <- length(data.ts)

train.ts <- subset(data.ts, start = 1,            end = floor(0.8 * n))
test.ts  <- subset(data.ts, start = floor(0.8 * n) + 1)

cat("\nPanjang data training :", length(train.ts), "observasi\n")
## 
## Panjang data training : 213 observasi
cat("Panjang data testing  :", length(test.ts),  "observasi\n")
## Panjang data testing  : 54 observasi
# 4.9 Visualisasi Data Training dan Testing
# ============================================================
ts.plot(
  train.ts,
  col  = "#1565C0",
  ylab = "Indeks IDX Kompas 100",
  xlab = "Waktu (Minggu ke-)"
)
title(main = "Training Data — Indeks IDX Kompas 100 (80%)")
points(train.ts, pch = 20, col = "#1565C0", cex = 0.3)

ts.plot(
  test.ts,
  col  = "firebrick",
  ylab = "Indeks IDX Kompas 100",
  xlab = "Waktu (Minggu ke-)"
)
title(main = "Testing Data — Indeks IDX Kompas 100 (20%)")
points(test.ts, pch = 20, col = "firebrick", cex = 0.3)

# BAB 4.10 — ARIMA NON-SEASONAL
# ============================================================

# 4.10.1 Plot ACF dan PACF Data Training
acf0 <- acf(
  train.ts,
  main    = "ACF Data Training — IDX Kompas 100",
  lag.max = 40,
  xaxt    = "n",
  col     = "#1565C0"
)
axis(1, at = 0:40 / frequency(train.ts), labels = 0:40)

pacf0 <- pacf(
  train.ts,
  main    = "PACF Data Training — IDX Kompas 100",
  lag.max = 40,
  xaxt    = "n",
  col     = "#1565C0"
)
axis(1, at = 0:40 / frequency(train.ts), labels = 0:40)

# 4.10.2 Differencing Non-Seasonal (d = 1)
# ============================================================
d1 <- diff(train.ts)

ts.plot(
  d1,
  type = "l",
  ylab = "Δ Indeks IDX Kompas 100",
  xlab = "Waktu (Minggu ke-)",
  col  = "#1565C0"
)
title(main = "Plot Differencing Non-Seasonal (d = 1)")

# 4.10.3 Uji ADF — Data Asli dan Setelah Differencing
# ============================================================
cat("======================================================\n")
## ======================================================
cat("  UJI ADF — DATA ASLI (TRAINING)\n")
##   UJI ADF — DATA ASLI (TRAINING)
cat("  H0: Data tidak stasioner (ada unit root)\n")
##   H0: Data tidak stasioner (ada unit root)
cat("  H1: Data stasioner\n")
##   H1: Data stasioner
cat("======================================================\n")
## ======================================================
print(adf.test(train.ts))
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train.ts
## Dickey-Fuller = -3.1187, Lag order = 5, p-value = 0.1069
## alternative hypothesis: stationary
cat("\n======================================================\n")
## 
## ======================================================
cat("  UJI ADF — SETELAH DIFFERENCING d = 1\n")
##   UJI ADF — SETELAH DIFFERENCING d = 1
cat("======================================================\n")
## ======================================================
print(adf.test(d1))
## Warning in adf.test(d1): p-value smaller than printed p-value

## 
##  Augmented Dickey-Fuller Test
## 
## data:  d1
## Dickey-Fuller = -11.031, Lag order = 5, p-value = 0.01
## alternative hypothesis: stationary
# 4.10.4 Plot ACF dan PACF Setelah Differencing d = 1
# ============================================================
acf1 <- acf(
  d1,
  lag.max = 40,
  xaxt    = "n",
  main    = "ACF Setelah Differencing d = 1",
  col     = "#1565C0"
)
axis(1, at = 0:40 / frequency(d1), labels = 0:40)

pacf1 <- pacf(
  d1,
  main    = "PACF Setelah Differencing d = 1",
  lag.max = 40,
  xaxt    = "n",
  col     = "#1565C0"
)
axis(1, at = 0:40 / frequency(d1), labels = 0:40)

# EACF untuk identifikasi kandidat model ARIMA
eacf(d1)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 x x x x x o o x o o o  o  o  o 
## 1 x o x o x o o x x o o  x  o  o 
## 2 x x x x x o o x o o o  x  o  o 
## 3 o x x o x o o x o o o  o  o  o 
## 4 o x x o x x o x o o o  o  o  o 
## 5 x o o x x o o x o o o  o  o  o 
## 6 x o o o x o o o o o o  o  o  o 
## 7 o o o x x o o o o o o  o  o  o
# 4.10.5 Kandidat dan Estimasi Model ARIMA
# ============================================================
# Berdasarkan ACF/PACF/EACF, kandidat model:
KandidatARIMA <- c(
  "ARIMA(0,1,0)",
  "ARIMA(0,1,1)",
  "ARIMA(1,1,0)",
  "ARIMA(1,1,1)",
  "ARIMA(0,1,2)"
)
KandidatARIMA
## [1] "ARIMA(0,1,0)" "ARIMA(0,1,1)" "ARIMA(1,1,0)" "ARIMA(1,1,1)" "ARIMA(0,1,2)"
# Estimasi
model_a1 <- Arima(train.ts, order = c(0,1,0))
model_a2 <- Arima(train.ts, order = c(0,1,1))
model_a3 <- Arima(train.ts, order = c(1,1,0))
model_a4 <- Arima(train.ts, order = c(1,1,1))
model_a5 <- Arima(train.ts, order = c(0,1,2))

# Fungsi AICc
calc_AICc <- function(model, n) {
  k   <- length(model$coef)
  aic <- AIC(model)
  aic + (2 * k * (k + 1)) / (n - k - 1)
}

n_train <- length(train.ts)

compARIMA <- data.frame(
  "Kandidat Model" = KandidatARIMA,
  "Nilai AIC"  = round(c(model_a1$aic, model_a2$aic, model_a3$aic,
                          model_a4$aic, model_a5$aic), 2),
  "Nilai AICc" = round(c(calc_AICc(model_a1, n_train),
                          calc_AICc(model_a2, n_train),
                          calc_AICc(model_a3, n_train),
                          calc_AICc(model_a4, n_train),
                          calc_AICc(model_a5, n_train)), 2),
  "Nilai BIC"  = round(c(model_a1$bic, model_a2$bic, model_a3$bic,
                          model_a4$bic, model_a5$bic), 2),
  check.names = FALSE
)
cat("\n======================================================\n")
## 
## ======================================================
cat("  TABEL PERBANDINGAN KANDIDAT MODEL ARIMA\n")
##   TABEL PERBANDINGAN KANDIDAT MODEL ARIMA
cat("======================================================\n")
## ======================================================
print(compARIMA)
##   Kandidat Model Nilai AIC Nilai AICc Nilai BIC
## 1   ARIMA(0,1,0)   2030.79    2030.79   2034.14
## 2   ARIMA(0,1,1)   2024.74    2024.76   2031.45
## 3   ARIMA(1,1,0)   2028.54    2028.56   2035.26
## 4   ARIMA(1,1,1)   1996.55    1996.61   2006.62
## 5   ARIMA(0,1,2)   2002.10    2002.16   2012.17
# Model ARIMA terbaik (AIC terkecil)
daftar_model_arima <- list(model_a1, model_a2, model_a3, model_a4, model_a5)
model_arima_best   <- daftar_model_arima[[which.min(compARIMA$`Nilai AIC`)]]

cat("\n======================================================\n")
## 
## ======================================================
cat("  MODEL ARIMA TERBAIK\n")
##   MODEL ARIMA TERBAIK
cat("======================================================\n")
## ======================================================
summary(model_arima_best)
## Series: train.ts 
## ARIMA(1,1,1) 
## 
## Coefficients:
##          ar1      ma1
##       0.6004  -0.9792
## s.e.  0.0628   0.0229
## 
## sigma^2 = 700.8:  log likelihood = -995.28
## AIC=1996.55   AICc=1996.67   BIC=2006.62
## 
## Training set error measures:
##                     ME     RMSE      MAE        MPE     MAPE      MASE
## Training set -3.089376 26.28561 18.74572 -0.2831605 1.487336 0.5834066
##                    ACF1
## Training set 0.04001568
# 4.10.6 Diagnostik Residual ARIMA — Uji Ljung-Box
# ============================================================
# H0: Tidak terdapat autokorelasi pada residual
# H1: Terdapat autokorelasi pada residual
lags <- c(5, 10, 15, 20, 25, 30)

hasil_ljungbox_arima <- data.frame(
  Lag       = lags,
  Statistik = NA,
  P_Value   = NA
)

for (i in seq_along(lags)) {
  test <- Box.test(
    residuals(model_arima_best),
    lag   = lags[i],
    type  = "Ljung-Box",
    fitdf = length(model_arima_best$coef)
  )
  hasil_ljungbox_arima$Statistik[i] <- round(test$statistic, 4)
  hasil_ljungbox_arima$P_Value[i]   <- round(test$p.value,   4)
}

cat("\n======================================================\n")
## 
## ======================================================
cat("  UJI LJUNG-BOX RESIDUAL ARIMA\n")
##   UJI LJUNG-BOX RESIDUAL ARIMA
cat("======================================================\n")
## ======================================================
print(hasil_ljungbox_arima)
##   Lag Statistik P_Value
## 1   5   21.2735   1e-04
## 2  10   41.9602   0e+00
## 3  15   50.9899   0e+00
## 4  20   62.0246   0e+00
## 5  25   77.5178   0e+00
## 6  30   85.3373   0e+00
# BAB 4.11 — ARIMA SEASONAL (SARIMA)
# ============================================================

# 4.11.1 Seasonal Differencing s = 5 (siklus mingguan 5 hari kerja)
D1 <- diff(train.ts, 5)

ts.plot(
  D1,
  type = "l",
  ylab = "Seasonal Differencing",
  xlab = "Waktu (Minggu ke-)",
  col  = "#1565C0"
)
title(main = "Plot Seasonal Differencing (D=1, s=5)")

# 4.11.2 Plot ACF Setelah Seasonal Differencing
# ============================================================
acf2 <- acf(
  D1,
  lag.max = 40,
  xaxt    = "n",
  main    = "ACF Setelah Seasonal Differencing (D=1, s=5)",
  col     = "#1565C0"
)
axis(1, at = 0:40 / frequency(D1), labels = 0:40)

# 4.11.3 Differencing Gabungan (d=1, D=1, s=5)
# ============================================================
d1D1 <- diff(D1)

ts.plot(
  d1D1,
  type = "l",
  ylab = "Differencing Gabungan",
  xlab = "Waktu (Minggu ke-)",
  col  = "#1565C0"
)
title(main = "Plot Differencing Gabungan (d=1, D=1, s=5)")

cat("\n======================================================\n")
## 
## ======================================================
cat("  UJI ADF — DIFFERENCING GABUNGAN (d=1, D=1, s=5)\n")
##   UJI ADF — DIFFERENCING GABUNGAN (d=1, D=1, s=5)
cat("======================================================\n")
## ======================================================
print(adf.test(d1D1))
## Warning in adf.test(d1D1): p-value smaller than printed p-value

## 
##  Augmented Dickey-Fuller Test
## 
## data:  d1D1
## Dickey-Fuller = -13.618, Lag order = 5, p-value = 0.01
## alternative hypothesis: stationary
# 4.11.4 Identifikasi Model SARIMA — ACF & PACF Differencing Gabungan
# ============================================================
acf3 <- acf(
  d1D1,
  lag.max = 40,
  xaxt    = "n",
  main    = "ACF Differencing Gabungan (d=1, D=1, s=5)",
  col     = "#1565C0"
)
axis(1, at = 0:40 / frequency(d1D1), labels = 0:40)

pacf3 <- pacf(
  d1D1,
  lag.max = 40,
  xaxt    = "n",
  main    = "PACF Differencing Gabungan (d=1, D=1, s=5)",
  col     = "#1565C0"
)
axis(1, at = 0:40 / frequency(d1D1), labels = 0:40)

# 4.11.5 Identifikasi Komponen Seasonal (Lag Kelipatan s=5)
# ============================================================
acf3_fresh      <- acf(d1D1, lag.max = 40, plot = FALSE)
acf3_fresh$lag  <- acf3_fresh$lag * frequency(d1D1)
acf3.1          <- as.data.frame(cbind(acf3_fresh$acf, acf3_fresh$lag))
names(acf3.1)   <- c("ACF", "Lag")
acf3.2          <- acf3.1[which(acf3.1$Lag %% 5 == 0 & acf3.1$Lag > 0), ]

barplot(
  height    = acf3.2$ACF,
  names.arg = acf3.2$Lag,
  ylab      = "ACF",
  xlab      = "Lag (kelipatan s=5)",
  col       = "#1565C0",
  main      = "ACF pada Lag Musiman (kelipatan s=5)"
)
abline(h = c( 1.96 / sqrt(length(d1D1)),
             -1.96 / sqrt(length(d1D1))),
       col = "red", lty = 2)

pacf3_fresh      <- pacf(d1D1, lag.max = 40, plot = FALSE)
pacf3_fresh$lag  <- pacf3_fresh$lag * frequency(d1D1)
pacf3.1          <- as.data.frame(cbind(pacf3_fresh$acf, pacf3_fresh$lag))
names(pacf3.1)   <- c("PACF", "Lag")
pacf3.2          <- pacf3.1[which(pacf3.1$Lag %% 5 == 0 & pacf3.1$Lag > 0), ]

barplot(
  height    = pacf3.2$PACF,
  names.arg = pacf3.2$Lag,
  ylab      = "PACF",
  xlab      = "Lag (kelipatan s=5)",
  col       = "#1565C0",
  main      = "PACF pada Lag Musiman (kelipatan s=5)"
)
abline(h = c( 1.96 / sqrt(length(d1D1)),
             -1.96 / sqrt(length(d1D1))),
       col = "red", lty = 2)

# EACF
eacf(d1D1)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 x o x x x o o x o o o  o  o  o 
## 1 x o x o x x o x o o o  x  o  o 
## 2 o x o o x x x x o o o  x  o  o 
## 3 x x o o x x x o o o o  o  o  o 
## 4 o x x o x x x o o o o  o  o  o 
## 5 x o x x x x o x o o o  o  o  x 
## 6 x x o o x o o o o o o  o  o  x 
## 7 x o o o x o x x o o o  o  o  o
# 4.12 Kandidat Model SARIMA(p,1,q)(P,1,Q)[5]
# ============================================================
# Berdasarkan ACF, PACF, dan EACF:
#   SARIMA(0,1,0)(0,1,1)[5]
#   SARIMA(0,1,0)(0,1,2)[5]
#   SARIMA(0,1,0)(1,1,1)[5]
#   SARIMA(0,1,1)(0,1,1)[5]
#   SARIMA(0,1,2)(0,1,1)[5]
# 4.13 Estimasi Parameter Model SARIMA
# ============================================================
tmodel1 <- Arima(train.ts, order = c(0,1,0),
                 seasonal = list(order = c(0,1,1), period = 5))
summary(tmodel1)
## Series: train.ts 
## ARIMA(0,1,0)(0,1,1)[5] 
## 
## Coefficients:
##          sma1
##       -1.0000
## s.e.   0.0547
## 
## sigma^2 = 851:  log likelihood = -1000.83
## AIC=2005.67   AICc=2005.72   BIC=2012.33
## 
## Training set error measures:
##                    ME     RMSE      MAE        MPE    MAPE      MASE       ACF1
## Training set 1.141281 28.68893 20.77043 0.06506511 1.64333 0.6464198 -0.1363448
tmodel2 <- Arima(train.ts, order = c(0,1,0),
                 seasonal = list(order = c(0,1,2), period = 5))
summary(tmodel2)
## Series: train.ts 
## ARIMA(0,1,0)(0,1,2)[5] 
## 
## Coefficients:
##          sma1    sma2
##       -1.2864  0.3441
## s.e.   0.0841  0.0881
## 
## sigma^2 = 819:  log likelihood = -993.82
## AIC=1993.64   AICc=1993.75   BIC=2003.63
## 
## Training set error measures:
##                     ME     RMSE      MAE        MPE     MAPE      MASE
## Training set 0.8133128 28.07602 19.95864 0.04074711 1.580567 0.6211552
##                     ACF1
## Training set -0.09155995
tmodel3 <- Arima(train.ts, order = c(0,1,0),
                 seasonal = list(order = c(1,1,1), period = 5))
summary(tmodel3)
## Series: train.ts 
## ARIMA(0,1,0)(1,1,1)[5] 
## 
## Coefficients:
##          sar1     sma1
##       -0.2170  -0.9617
## s.e.   0.0716   0.0478
## 
## sigma^2 = 834.3:  log likelihood = -996.35
## AIC=1998.7   AICc=1998.82   BIC=2008.7
## 
## Training set error measures:
##                     ME     RMSE      MAE        MPE     MAPE     MASE
## Training set 0.9611023 28.33623 20.17099 0.05207033 1.596921 0.627764
##                    ACF1
## Training set -0.1037163
tmodel4 <- Arima(train.ts, order = c(0,1,1),
                 seasonal = list(order = c(0,1,1), period = 5))
summary(tmodel4)
## Series: train.ts 
## ARIMA(0,1,1)(0,1,1)[5] 
## 
## Coefficients:
##           ma1     sma1
##       -0.3241  -1.0000
## s.e.   0.1380   0.0777
## 
## sigma^2 = 821.7:  log likelihood = -996.76
## AIC=1999.52   AICc=1999.64   BIC=2009.52
## 
## Training set error measures:
##                    ME     RMSE      MAE        MPE     MAPE      MASE      ACF1
## Training set 1.426279 28.12194 19.91908 0.08023609 1.575211 0.6199239 0.1085509
tmodel5 <- Arima(train.ts, order = c(0,1,2),
                 seasonal = list(order = c(0,1,1), period = 5))
summary(tmodel5)
## Series: train.ts 
## ARIMA(0,1,2)(0,1,1)[5] 
## 
## Coefficients:
##           ma1      ma2     sma1
##       -0.4254  -0.2904  -1.0000
## s.e.   0.0606   0.0537   0.0514
## 
## sigma^2 = 733.5:  log likelihood = -985.11
## AIC=1978.22   AICc=1978.42   BIC=1991.55
## 
## Training set error measures:
##                   ME     RMSE      MAE        MPE     MAPE      MASE      ACF1
## Training set 1.73389 26.50468 19.14079 0.09888347 1.514077 0.5957018 0.0897656
# 4.14 Pemilihan Model SARIMA Terbaik
# ============================================================
KandidatModelSARIMA <- c(
  "SARIMA(0,1,0)(0,1,1)[5]",
  "SARIMA(0,1,0)(0,1,2)[5]",
  "SARIMA(0,1,0)(1,1,1)[5]",
  "SARIMA(0,1,1)(0,1,1)[5]",
  "SARIMA(0,1,2)(0,1,1)[5]"
)

compmodelSARIMA <- data.frame(
  "Kandidat Model" = KandidatModelSARIMA,
  "Nilai AIC"  = round(c(tmodel1$aic, tmodel2$aic, tmodel3$aic,
                          tmodel4$aic, tmodel5$aic), 2),
  "Nilai AICc" = round(c(tmodel1$aicc, tmodel2$aicc, tmodel3$aicc,
                          tmodel4$aicc, tmodel5$aicc), 2),
  "Nilai BIC"  = round(c(tmodel1$bic, tmodel2$bic, tmodel3$bic,
                          tmodel4$bic, tmodel5$bic), 2),
  check.names = FALSE
)

cat("\n======================================================\n")
## 
## ======================================================
cat("  TABEL PERBANDINGAN KANDIDAT MODEL SARIMA\n")
##   TABEL PERBANDINGAN KANDIDAT MODEL SARIMA
cat("======================================================\n")
## ======================================================
print(compmodelSARIMA)
##            Kandidat Model Nilai AIC Nilai AICc Nilai BIC
## 1 SARIMA(0,1,0)(0,1,1)[5]   2005.67    2005.72   2012.33
## 2 SARIMA(0,1,0)(0,1,2)[5]   1993.64    1993.75   2003.63
## 3 SARIMA(0,1,0)(1,1,1)[5]   1998.70    1998.82   2008.70
## 4 SARIMA(0,1,1)(0,1,1)[5]   1999.52    1999.64   2009.52
## 5 SARIMA(0,1,2)(0,1,1)[5]   1978.22    1978.42   1991.55
# Model terbaik (AIC terkecil)
daftar_sarima  <- list(tmodel1, tmodel2, tmodel3, tmodel4, tmodel5)
idx_terbaik    <- which.min(compmodelSARIMA$`Nilai AIC`)
model_sarima_best <- daftar_sarima[[idx_terbaik]]

cat("\nModel SARIMA terbaik :", KandidatModelSARIMA[idx_terbaik], "\n")
## 
## Model SARIMA terbaik : SARIMA(0,1,2)(0,1,1)[5]
# 4.15 Perbandingan dengan auto.arima
# ============================================================
auto_model <- auto.arima(
  train.ts,
  seasonal      = TRUE,
  stepwise      = TRUE,
  approximation = FALSE,
  D             = 1,
  max.P         = 2,
  max.Q         = 2
)
auto_model
## Series: train.ts 
## ARIMA(1,0,0)(2,1,1)[5] 
## 
## Coefficients:
##          ar1     sar1     sar2     sma1
##       0.6720  -0.2297  -0.1600  -0.9198
## s.e.  0.0575   0.0794   0.0779   0.0389
## 
## sigma^2 = 697.6:  log likelihood = -980.59
## AIC=1971.17   AICc=1971.47   BIC=1987.86
PerbandinganModel <- data.frame(
  Model = c(KandidatModelSARIMA[idx_terbaik], "SARIMA auto.arima"),
  AIC   = c(round(model_sarima_best$aic, 2), round(auto_model$aic, 2))
)
print(PerbandinganModel)
##                     Model     AIC
## 1 SARIMA(0,1,2)(0,1,1)[5] 1978.22
## 2       SARIMA auto.arima 1971.17
cat(sprintf("\nModel dengan AIC terkecil: %s\n",
            PerbandinganModel$Model[which.min(PerbandinganModel$AIC)]))
## 
## Model dengan AIC terkecil: SARIMA auto.arima
# 4.16 Pengujian Signifikansi Parameter Model SARIMA Terbaik
# ============================================================
printstatarima <- function(x, digits = 4, se = TRUE) {
  if (length(x$coef) > 0) {
    cat("\nCoefficients:\n")
    coef <- round(x$coef, digits = digits)
    if (se && nrow(x$var.coef)) {
      ses        <- rep(0, length(coef))
      ses[x$mask]<- round(sqrt(diag(x$var.coef)), digits = digits)
      coef       <- matrix(coef, 1, dimnames = list(NULL, names(coef)))
      coef       <- rbind(coef, s.e. = ses)
      statt      <- coef[1,] / ses
      pval       <- 2 * pt(abs(statt),
                            df         = length(x$residuals) - 1,
                            lower.tail = FALSE)
      coef       <- rbind(coef,
                          t     = round(statt, digits = digits),
                          sign. = round(pval,  digits = digits))
      coef <- t(coef)
    }
    print.default(coef, print.gap = 2)
  }
}

printstatarima(model_sarima_best)
## 
## Coefficients:
##                  s.e.         t  sign.
## ma1   -0.4254  0.0606   -7.0198      0
## ma2   -0.2904  0.0537   -5.4078      0
## sma1  -1.0000  0.0514  -19.4553      0
# 4.17 Diagnostik Residual Model SARIMA Terbaik
# ============================================================
png("diagnostik_sarima.png", width = 1200, height = 900)

tsdisplay(
  residuals(model_sarima_best),
  lag.max = 40,
  main = paste("Diagnostik Residual",
               KandidatModelSARIMA[idx_terbaik]),
  col = "#1565C0"
)

dev.off()
## png 
##   2
# --- Uji Ljung-Box ---
# H0: Tidak terdapat autokorelasi pada residual
# H1: Terdapat autokorelasi pada residual
hasil_ljungbox_sarima <- data.frame(
  Lag       = lags,
  Statistik = NA,
  P_Value   = NA
)
for (i in seq_along(lags)) {
  test <- Box.test(
    residuals(model_sarima_best),
    lag  = lags[i],
    type = "Ljung-Box"
  )
  hasil_ljungbox_sarima$Statistik[i] <- round(test$statistic, 4)
  hasil_ljungbox_sarima$P_Value[i]   <- round(test$p.value,   4)
}
cat("\n======================================================\n")
## 
## ======================================================
cat("  UJI LJUNG-BOX RESIDUAL SARIMA\n")
##   UJI LJUNG-BOX RESIDUAL SARIMA
cat("======================================================\n")
## ======================================================
print(hasil_ljungbox_sarima)
##   Lag Statistik P_Value
## 1   5   27.7527       0
## 2  10   47.1310       0
## 3  15   57.4251       0
## 4  20   69.5300       0
## 5  25   91.0201       0
## 6  30  100.5841       0
# --- Uji Normalitas Jarque-Bera ---
# H0: Residual berdistribusi normal
# H1: Residual tidak berdistribusi normal
cat("\n======================================================\n")
## 
## ======================================================
cat("  UJI JARQUE-BERA RESIDUAL SARIMA\n")
##   UJI JARQUE-BERA RESIDUAL SARIMA
cat("======================================================\n")
## ======================================================
print(jarque.bera.test(residuals(model_sarima_best)))
## 
##  Jarque Bera Test
## 
## data:  residuals(model_sarima_best)
## X-squared = 20.699, df = 2, p-value = 3.201e-05
par(mfrow = c(1,2))
hist(residuals(model_sarima_best),
     main   = paste("Histogram Residual", KandidatModelSARIMA[idx_terbaik]),
     col    = "lightblue", border = "white",
     xlab   = "Residual", breaks = 30)
qqnorm(residuals(model_sarima_best),
       main = paste("QQ-Plot Residual", KandidatModelSARIMA[idx_terbaik]))
qqline(residuals(model_sarima_best), col = "red", lwd = 2)

par(mfrow = c(1,1))
# 4.18 Perbandingan Metrik Evaluasi ARIMA vs SARIMA
# ============================================================
mape_func <- function(actual, predicted) {
  mean(abs((actual - predicted) / actual)) * 100
}

fc_arima  <- forecast(model_arima_best,  h = length(test.ts))
fc_sarima <- forecast(model_sarima_best, h = length(test.ts))

actual <- as.numeric(test.ts)

rmse_a <- round(sqrt(mean((actual - fc_arima$mean)^2)), 4)
mae_a  <- round(mean(abs(actual - fc_arima$mean)), 4)
mape_a <- round(mape_func(actual, as.numeric(fc_arima$mean)), 4)

rmse_s <- round(sqrt(mean((actual - fc_sarima$mean)^2)), 4)
mae_s  <- round(mean(abs(actual - fc_sarima$mean)), 4)
mape_s <- round(mape_func(actual, as.numeric(fc_sarima$mean)), 4)

nama_arima_best  <- KandidatARIMA[which.min(compARIMA$`Nilai AIC`)]
nama_sarima_best <- KandidatModelSARIMA[idx_terbaik]

TabelPerbandingan <- data.frame(
  Model      = c(nama_arima_best, nama_sarima_best),
  RMSE       = c(rmse_a, rmse_s),
  MAE        = c(mae_a,  mae_s),
  "MAPE (%)" = c(mape_a, mape_s),
  AIC        = c(round(AIC(model_arima_best),  2),
                 round(AIC(model_sarima_best), 2)),
  BIC        = c(round(BIC(model_arima_best),  2),
                 round(BIC(model_sarima_best), 2)),
  check.names = FALSE
)

cat("\n======================================================\n")
## 
## ======================================================
cat("  PERBANDINGAN METRIK EVALUASI MODEL\n")
##   PERBANDINGAN METRIK EVALUASI MODEL
cat("======================================================\n")
## ======================================================
print(TabelPerbandingan)
##                     Model     RMSE      MAE MAPE (%)     AIC     BIC
## 1            ARIMA(1,1,1)  59.4622  57.9402   4.4176 1996.55 2006.62
## 2 SARIMA(0,1,2)(0,1,1)[5] 123.9745 119.0504   9.0397 1978.22 1991.55
best_model <- ifelse(rmse_s < rmse_a, nama_sarima_best, nama_arima_best)
cat(sprintf("\n★ Model terbaik berdasarkan RMSE : %s\n", best_model))
## 
## ★ Model terbaik berdasarkan RMSE : ARIMA(1,1,1)
cat("\n--- Akurasi ARIMA ---\n");  accuracy(fc_arima, test.ts)
## 
## --- Akurasi ARIMA ---

##                     ME     RMSE      MAE        MPE     MAPE      MASE
## Training set -3.089376 26.28561 18.74572 -0.2831605 1.487336 0.5834066
## Test set     51.001586 59.46220 57.94024  3.8342172 4.417608 1.8032230
##                    ACF1 Theil's U
## Training set 0.04001568        NA
## Test set     0.76554830  3.443674
cat("\n--- Akurasi SARIMA ---\n"); accuracy(fc_sarima, test.ts)
## 
## --- Akurasi SARIMA ---

##                     ME      RMSE       MAE        MPE     MAPE      MASE
## Training set   1.73389  26.50468  19.14079 0.09888347 1.514077 0.5957018
## Test set     116.73680 123.97449 119.05040 8.84237257 9.039745 3.7051003
##                   ACF1 Theil's U
## Training set 0.0897656        NA
## Test set     0.7936512  7.198688
# 4.19 Visualisasi Forecasting — Validasi Data Testing
# ============================================================
# Plot ARIMA
plot(fc_arima, col = "#1565C0",
     main = paste("Forecasting", nama_arima_best, "— Validasi Data Testing"),
     xlab = "Waktu (Minggu ke-)", ylab = "Indeks IDX Kompas 100",
     shadecols = c("mistyrose", "lightyellow"))
lines(test.ts, col = "darkgreen", lwd = 2)
legend("topleft",
       legend = c("Training", paste("Forecast", nama_arima_best), "Aktual Testing"),
       col    = c("#1565C0", "blue", "darkgreen"),
       lty = 1, lwd = 2, cex = 0.8)

# Plot SARIMA
plot(fc_sarima, col = "#1565C0",
     main = paste("Forecasting", nama_sarima_best, "— Validasi Data Testing"),
     xlab = "Waktu (Minggu ke-)", ylab = "Indeks IDX Kompas 100",
     shadecols = c("thistle1", "lavender"))
lines(test.ts, col = "darkgreen", lwd = 2)
legend("topleft",
       legend = c("Training", paste("Forecast", nama_sarima_best), "Aktual Testing"),
       col    = c("#1565C0", "purple", "darkgreen"),
       lty = 1, lwd = 2, cex = 0.8)

# Overlay Aktual vs ARIMA vs SARIMA
ts.plot(
  test.ts, fc_arima$mean, fc_sarima$mean,
  gpars = list(
    col  = c("darkgreen", "red", "purple"),
    lty  = c(1, 2, 3), lwd = c(2, 1.5, 1.5),
    main = "Overlay: Aktual vs ARIMA vs SARIMA (Periode Testing)\nIndeks IDX Kompas 100",
    ylab = "Indeks IDX Kompas 100", xlab = "Waktu (Minggu ke-)"
  )
)
legend("topleft",
       legend = c("Aktual",
                  sprintf("%s (MAPE = %.2f%%)", nama_arima_best,  mape_a),
                  sprintf("%s (MAPE = %.2f%%)", nama_sarima_best, mape_s)),
       col = c("darkgreen", "red", "purple"),
       lty = c(1, 2, 3), lwd = 2, cex = 0.8)

# 4.20 Tabel dan Visualisasi Hasil Forecasting Model Terbaik
# ============================================================
forecast_terbaik <- cbind(fc_sarima$mean, fc_sarima$lower, fc_sarima$upper)
forecast_terbaik <- as.data.frame(forecast_terbaik)
colnames(forecast_terbaik) <- c("Forecast", "Lo 80", "Lo 95", "Hi 80", "Hi 95")

cat("\nTabel Hasil Forecasting", nama_sarima_best, "(20 baris pertama):\n")
## 
## Tabel Hasil Forecasting SARIMA(0,1,2)(0,1,1)[5] (20 baris pertama):
print(head(round(forecast_terbaik, 2), 20))
##    Forecast   Lo 80   Lo 95   Hi 80   Hi 95
## 1   1191.86 1156.74 1138.15 1226.98 1245.57
## 2   1202.47 1161.96 1140.52 1242.97 1264.42
## 3   1207.02 1165.30 1143.21 1248.74 1270.82
## 4   1202.93 1160.03 1137.32 1245.82 1268.53
## 5   1200.35 1156.31 1133.00 1244.39 1267.71
## 6   1197.02 1151.68 1127.67 1242.36 1266.37
## 7   1200.01 1153.48 1128.85 1246.55 1271.18
## 8   1204.57 1156.92 1131.70 1252.21 1277.43
## 9   1200.48 1151.75 1125.96 1249.20 1274.99
## 10  1197.90 1148.12 1121.77 1247.68 1274.03
## 11  1194.57 1143.58 1116.59 1245.55 1272.54
## 12  1197.56 1145.47 1117.89 1249.66 1277.23
## 13  1202.11 1148.98 1120.85 1255.25 1283.37
## 14  1198.02 1143.88 1115.21 1252.17 1280.83
## 15  1195.45 1140.31 1111.12 1250.59 1279.78
## 16  1192.12 1135.84 1106.05 1248.39 1278.18
## 17  1195.11 1137.79 1107.45 1252.43 1282.78
## 18  1199.66 1141.35 1110.48 1257.97 1288.84
## 19  1195.57 1136.30 1104.92 1254.84 1286.22
## 20  1193.00 1132.78 1100.90 1253.22 1285.09
# Visualisasi
plot(fc_sarima$mean, type = "l", col = "#1565C0", lwd = 2,
     xlab = "Periode", ylab = "Indeks IDX Kompas 100",
     main = paste("Hasil Forecasting", nama_sarima_best,
                  "\npada Data Testing"))
lines(fc_sarima$lower[,2], col = "firebrick", lwd = 1.5, lty = 2)
lines(fc_sarima$upper[,2], col = "darkgreen", lwd = 1.5, lty = 2)
lines(as.numeric(test.ts),  col = "black",    lwd = 1.5)
legend("topleft",
       legend = c("Forecast", "Lower 95%", "Upper 95%", "Aktual"),
       col    = c("#1565C0", "firebrick", "darkgreen", "black"),
       lty    = c(1,2,2,1), lwd = 2, cex = 0.8)

# 4.21 Forecast 1 Minggu ke Depan (5 Hari Kerja)
# ============================================================
fc_future <- forecast(model_sarima_best, h = 5)

plot(
  fc_future,
  col       = "#1565C0",
  fcol      = "purple",
  main      = paste("Peramalan Indeks IDX Kompas 100\n5 Hari Kerja ke Depan —",
                    nama_sarima_best),
  xlab      = "Waktu (Minggu ke-)",
  ylab      = "Indeks IDX Kompas 100",
  shadecols = c("thistle1", "lavender")
)

cat("\nForecast 5 Hari Kerja ke Depan:\n")
## 
## Forecast 5 Hari Kerja ke Depan:
print(round(as.data.frame(fc_future), 2))
##       Point Forecast   Lo 80   Hi 80   Lo 95   Hi 95
## 43.60        1191.86 1156.74 1226.98 1138.15 1245.57
## 43.80        1202.47 1161.96 1242.97 1140.52 1264.42
## 44.00        1207.02 1165.30 1248.74 1143.21 1270.82
## 44.20        1202.93 1160.03 1245.82 1137.32 1268.53
## 44.40        1200.35 1156.31 1244.39 1133.00 1267.71
# 4.22 KAJIAN SIMULASI
# ============================================================

# 4.22.1 Simulasi Data ARIMA(1,1,1)
cat("\n======================================================\n")
## 
## ======================================================
cat("  KAJIAN SIMULASI — ARIMA(1,1,1)\n")
##   KAJIAN SIMULASI — ARIMA(1,1,1)
cat("======================================================\n")
## ======================================================
n      <- 200
phi1   <-  0.5; phi2   <- -0.7
theta1 <- -0.3; theta2 <- -0.5
sd_e   <- sqrt(1.20)

e <- rnorm(n, mean = 0, sd = sd_e)
x <- numeric(n)
for (t in 3:n) {
  x[t] <- phi1*x[t-1] + phi2*x[t-2] +
          e[t] + theta1*e[t-1] + theta2*e[t-2]
}
x_d1     <- cumsum(x)
data_sim <- cumsum(x_d1)

# Hapus 50 data awal (burn-in)
data_trim  <- data_sim[51:200]
n_data     <- length(data_trim)
train_size <- floor(0.8 * n_data)

train_sim <- ts(data_trim[1:train_size])
test_sim  <- ts(data_trim[(train_size+1):n_data], start = train_size + 1)

ts.plot(train_sim, main = "Data Training — Simulasi ARIMA(1,1,1)",
        ylab = "Nilai", xlab = "Waktu", col = "#1565C0")

# ADF
cat("ADF Data Asli Simulasi:\n");   print(adf.test(train_sim))
## ADF Data Asli Simulasi:

## Warning in adf.test(train_sim): p-value greater than printed p-value

## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_sim
## Dickey-Fuller = 0.82052, Lag order = 4, p-value = 0.99
## alternative hypothesis: stationary
train_d1 <- diff(train_sim);        cat("ADF d=1:\n"); print(adf.test(train_d1))
## ADF d=1:

## Warning in adf.test(train_d1): p-value smaller than printed p-value

## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_d1
## Dickey-Fuller = -4.1669, Lag order = 4, p-value = 0.01
## alternative hypothesis: stationary
train_d2 <- diff(train_d1);         cat("ADF d=2:\n"); print(adf.test(train_d2))
## ADF d=2:

## Warning in adf.test(train_d2): p-value smaller than printed p-value

## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_d2
## Dickey-Fuller = -8.2592, Lag order = 4, p-value = 0.01
## alternative hypothesis: stationary
par(mfrow = c(1,2))
acf(train_d2,  main = "ACF Differencing ke-2 — Simulasi ARIMA")
pacf(train_d2, main = "PACF Differencing ke-2 — Simulasi ARIMA")

par(mfrow = c(1,1))
eacf(as.matrix(train_d2))
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 x x x x x o x o o o o  o  o  o 
## 1 x x x x x o o o o o o  o  o  o 
## 2 o x o o o o o o o o o  o  o  o 
## 3 x x o o o o o o o o o  o  o  o 
## 4 x x o x o o o o o o o  o  o  o 
## 5 x x x x o o o o o o o  o  o  o 
## 6 o x x x o o o o o o o  o  o  o 
## 7 x o x o o o o o o o o  o  o  o
# Fitting
model_sim <- forecast::Arima(train_sim, order = c(1,1,1))
cat("\nKoefisien ARIMA(1,1,1):\n"); print(model_sim$coef)
## 
## Koefisien ARIMA(1,1,1):

##       ar1       ma1 
## 0.3130695 0.8299624
result_sim <- data.frame(
  Model = "ARIMA(1,1,1)",
  AIC   = round(AIC(model_sim), 4),
  BIC   = round(BIC(model_sim), 4),
  AICc  = round(calc_AICc(model_sim, length(train_sim)), 4)
)
print(result_sim)
##          Model      AIC      BIC     AICc
## 1 ARIMA(1,1,1) 387.5481 395.8854 387.6506
# Diagnostik
ts.plot(residuals(model_sim), main = "Residual ARIMA(1,1,1) — Simulasi",
        ylab = "Residual", col = "purple")
abline(h = 0, col = "red", lty = 2)

acf(residuals(model_sim), main = "ACF Residual — Simulasi ARIMA")

cat("\nLjung-Box:\n");   print(Box.test(residuals(model_sim), lag=20, type="Ljung-Box"))
## 
## Ljung-Box:

## 
##  Box-Ljung test
## 
## data:  residuals(model_sim)
## X-squared = 50.495, df = 20, p-value = 0.0001881
cat("\nShapiro-Wilk:\n"); print(shapiro.test(residuals(model_sim)))
## 
## Shapiro-Wilk:

## 
##  Shapiro-Wilk normality test
## 
## data:  residuals(model_sim)
## W = 0.99289, p-value = 0.802
par(mfrow = c(1,2))
hist(residuals(model_sim), main = "Histogram Residual Simulasi ARIMA",
     col = "lightblue", border = "black")
qqnorm(residuals(model_sim), main = "QQ Plot Residual Simulasi ARIMA")
qqline(residuals(model_sim), col = "red", lwd = 2)

par(mfrow = c(1,1))
# Perbandingan parameter asli vs estimasi
tabel_param_arima <- data.frame(
  Parameter = c("phi1", "phi2", "theta1", "theta2"),
  Asli      = c(phi1, phi2, theta1, theta2),
  Estimasi  = round(as.numeric(model_sim$coef[1:4]), 4),
  Selisih   = round(abs(c(phi1,phi2,theta1,theta2) -
                        as.numeric(model_sim$coef[1:4])), 4)
)
cat("\n======================================================\n")
## 
## ======================================================
cat("  PARAMETER ASLI vs ESTIMASI — SIMULASI ARIMA\n")
##   PARAMETER ASLI vs ESTIMASI — SIMULASI ARIMA
cat("======================================================\n")
## ======================================================
print(tabel_param_arima)
##   Parameter Asli Estimasi Selisih
## 1      phi1  0.5   0.3131  0.1869
## 2      phi2 -0.7   0.8300  1.5300
## 3    theta1 -0.3       NA      NA
## 4    theta2 -0.5       NA      NA
# ============================================================
# 4.22.2 Simulasi Data SARIMA(1,1,1)(1,1,1)[5]
# ============================================================

sim_sarima_data <- arima.sim(
  model = list(
    order = c(1,1,1),
    seasonal = list(order = c(1,1,1), period = 5),
    ar  = 0.5,
    ma  = -0.3,
    sar = 0.4,
    sma = -0.5
  ),
  n = 300
)

# Hapus 50 data awal (burn-in)
sim_sar_trim <- sim_sarima_data[51:300]

# Training-testing
n_sar <- length(sim_sar_trim)
train_size_sar <- floor(0.8 * n_sar)

train_sar <- ts(
  sim_sar_trim[1:train_size_sar],
  frequency = 5
)

test_sar <- ts(
  sim_sar_trim[(train_size_sar + 1):n_sar],
  frequency = 5
)

# Fitting model SARIMA simulasi
model_sar_sim <- Arima(
  train_sar,
  order = c(1,1,1),
  seasonal = list(order = c(1,1,1), period = 5)
)

summary(model_sar_sim)
## Series: train_sar 
## ARIMA(1,1,1)(1,1,1)[5] 
## 
## Coefficients:
##          ar1      ma1    sar1     sma1
##       0.2929  -0.1403  0.0702  -1.0000
## s.e.  0.4632   0.4796  0.0765   0.0714
## 
## sigma^2 = 0.9404:  log likelihood = -276.17
## AIC=562.34   AICc=562.66   BIC=578.68
## 
## Training set error measures:
##                        ME      RMSE       MAE      MPE     MAPE      MASE
## Training set -0.006569082 0.9451947 0.7347999 9.605673 64.32814 0.3907076
##                     ACF1
## Training set 0.001142119
# Parameter asli
phi1_s   <- 0.5
theta1_s <- -0.3
Phi1_s   <- 0.4
Theta1_s <- -0.5

# Differencing gabungan
D1_sar   <- diff(train_sar, lag = 5)
d1D1_sar <- diff(D1_sar)

ts.plot(d1D1_sar,
        main = "Differencing Gabungan (d=1,D=1) — Simulasi SARIMA",
        ylab = "Δ Nilai", xlab = "Waktu", col = "#1A237E")
abline(h = 0, col = "red", lty = 2)

cat("ADF Differencing Gabungan — Simulasi SARIMA:\n")
## ADF Differencing Gabungan — Simulasi SARIMA:
print(adf.test(d1D1_sar))
## Warning in adf.test(d1D1_sar): p-value smaller than printed p-value

## 
##  Augmented Dickey-Fuller Test
## 
## data:  d1D1_sar
## Dickey-Fuller = -7.9244, Lag order = 5, p-value = 0.01
## alternative hypothesis: stationary
par(mfrow = c(1,2))
acf(d1D1_sar,  lag.max = 40, main = "ACF Diff. Gabungan — Simulasi SARIMA",
    col = "#1A237E", xaxt = "n")
axis(1, at = 0:40/5, labels = 0:40)
pacf(d1D1_sar, lag.max = 40, main = "PACF Diff. Gabungan — Simulasi SARIMA",
     col = "#1A237E", xaxt = "n")
axis(1, at = 0:40/5, labels = 0:40)

par(mfrow = c(1,1))
# Fitting
png("Diagnostik_Residual_SARIMA.png",
    width = 1600,
    height = 1200)

tsdisplay(
  residuals(model_sar_sim),
  lag.max = 40,
  main = "Diagnostik Residual SARIMA(1,1,1)(1,1,1)[5] - Simulasi",
  col = "#00796B"
)

dev.off()
## png 
##   2
# Uji Ljung-Box
cat("\nLjung-Box SARIMA Simulasi:\n")
## 
## Ljung-Box SARIMA Simulasi:
print(Box.test(
  residuals(model_sar_sim),
  lag = 20,
  type = "Ljung-Box"
))
## 
##  Box-Ljung test
## 
## data:  residuals(model_sar_sim)
## X-squared = 11.733, df = 20, p-value = 0.925
# Uji Jarque-Bera
cat("\nJarque-Bera SARIMA Simulasi:\n")
## 
## Jarque-Bera SARIMA Simulasi:
print(jarque.bera.test(residuals(model_sar_sim)))
## 
##  Jarque Bera Test
## 
## data:  residuals(model_sar_sim)
## X-squared = 10.866, df = 2, p-value = 0.004371
tabel_param_sarima <- data.frame(
  Parameter = c("phi1", "theta1", "Phi1", "Theta1"),
  Asli      = c(phi1_s, theta1_s, Phi1_s, Theta1_s),
  Estimasi  = round(c(
    model_sar_sim$coef["ar1"],
    model_sar_sim$coef["ma1"],
    model_sar_sim$coef["sar1"],
    model_sar_sim$coef["sma1"]
  ), 4),
  Selisih = round(abs(
    c(phi1_s, theta1_s, Phi1_s, Theta1_s) -
    c(
      model_sar_sim$coef["ar1"],
      model_sar_sim$coef["ma1"],
      model_sar_sim$coef["sar1"],
      model_sar_sim$coef["sma1"]
    )
  ), 4)
)
#   SELESAI — BAB 4
# ============================================================
cat("\n============================================================\n")
## 
## ============================================================
cat("  BAB 4 SELESAI DIEKSEKUSI\n")
##   BAB 4 SELESAI DIEKSEKUSI
cat("  Model Terbaik ARIMA  :", nama_arima_best,  "\n")
##   Model Terbaik ARIMA  : ARIMA(1,1,1)
cat("  Model Terbaik SARIMA :", nama_sarima_best, "\n")
##   Model Terbaik SARIMA : SARIMA(0,1,2)(0,1,1)[5]
cat("  MAPE ARIMA           :", mape_a, "%\n")
##   MAPE ARIMA           : 4.4176 %
cat("  MAPE SARIMA          :", mape_s, "%\n")
##   MAPE SARIMA          : 9.0397 %
cat("============================================================\n")
## ============================================================