library(readxl)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(xts)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## 
## ######################### Warning from 'xts' package ##########################
## #                                                                             #
## # The dplyr lag() function breaks how base R's lag() function is supposed to  #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or       #
## # source() into this session won't work correctly.                            #
## #                                                                             #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop           #
## # dplyr from breaking base R's lag() function.                                #
## #                                                                             #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning.  #
## #                                                                             #
## ###############################################################################
## 
## Attaching package: 'xts'
## The following objects are masked from 'package:dplyr':
## 
##     first, last
library(tseries)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(dygraphs)
## Warning: package 'dygraphs' was built under R version 4.4.2
library(forecast)
data <- read_excel("~/Semester 3 Muhammad Maulana Zafrani/Metode Peramalan/Data Tertinggi Saham Telkom Indonesia.xlsx")
data
## # A tibble: 98 × 2
##    Date                 high
##    <dttm>              <dbl>
##  1 2024-12-18 00:00:00  2660
##  2 2024-12-17 00:00:00  2650
##  3 2024-12-16 00:00:00  2760
##  4 2024-12-13 00:00:00  2790
##  5 2024-12-12 00:00:00  2850
##  6 2024-12-11 00:00:00  2880
##  7 2024-12-10 00:00:00  2830
##  8 2024-12-09 00:00:00  2770
##  9 2024-12-06 00:00:00  2780
## 10 2024-12-05 00:00:00  2840
## # ℹ 88 more rows
str(data)
## tibble [98 × 2] (S3: tbl_df/tbl/data.frame)
##  $ Date: POSIXct[1:98], format: "2024-12-18" "2024-12-17" ...
##  $ high: num [1:98] 2660 2650 2760 2790 2850 2880 2830 2770 2780 2840 ...
summary(data)
##       Date                             high     
##  Min.   :2024-08-01 00:00:00.00   Min.   :2580  
##  1st Qu.:2024-09-04 06:00:00.00   1st Qu.:2815  
##  Median :2024-10-09 12:00:00.00   Median :2935  
##  Mean   :2024-10-09 10:46:31.83   Mean   :2928  
##  3rd Qu.:2024-11-12 18:00:00.00   3rd Qu.:3048  
##  Max.   :2024-12-18 00:00:00.00   Max.   :3190
colSums(is.na(data))
## Date high 
##    0    0

Eksplorasi Data

# Mengubah kolom Date menjadi indeks
colnames(data) <- c("Date", "High")  # Pastikan nama kolom benar
data$Date <- as.Date(data$Date)
data_xts <- xts(data$High, order.by = data$Date)
data_xts
##            [,1]
## 2024-08-01 2930
## 2024-08-02 2880
## 2024-08-05 2830
## 2024-08-06 2840
## 2024-08-07 2840
## 2024-08-08 2880
## 2024-08-09 2880
## 2024-08-12 2910
## 2024-08-13 2900
## 2024-08-14 2890
## 2024-08-15 2880
## 2024-08-16 2990
## 2024-08-19 2970
## 2024-08-20 3000
## 2024-08-21 3010
## 2024-08-22 2970
## 2024-08-23 3010
## 2024-08-26 2990
## 2024-08-27 3000
## 2024-08-28 3000
## 2024-08-29 3080
## 2024-08-30 3070
## 2024-09-02 3150
## 2024-09-03 3150
## 2024-09-04 3100
## 2024-09-05 3090
## 2024-09-06 3050
## 2024-09-09 3080
## 2024-09-10 3060
## 2024-09-11 3050
## 2024-09-12 3070
## 2024-09-13 3120
## 2024-09-17 3130
## 2024-09-18 3130
## 2024-09-19 3150
## 2024-09-20 3170
## 2024-09-23 3180
## 2024-09-24 3180
## 2024-09-25 3190
## 2024-09-26 3180
## 2024-09-27 3140
## 2024-09-30 3030
## 2024-10-01 3040
## 2024-10-02 2980
## 2024-10-03 2950
## 2024-10-04 2930
## 2024-10-07 2910
## 2024-10-08 2990
## 2024-10-09 3010
## 2024-10-10 2980
## 2024-10-11 3000
## 2024-10-14 2970
## 2024-10-15 2970
## 2024-10-16 3000
## 2024-10-17 3060
## 2024-10-18 3130
## 2024-10-21 3130
## 2024-10-22 3070
## 2024-10-23 2980
## 2024-10-24 2960
## 2024-10-25 2950
## 2024-10-28 2940
## 2024-10-29 2930
## 2024-10-30 2900
## 2024-10-31 2870
## 2024-11-01 2840
## 2024-11-04 2810
## 2024-11-05 2810
## 2024-11-06 2800
## 2024-11-07 2790
## 2024-11-08 2780
## 2024-11-11 2730
## 2024-11-12 2670
## 2024-11-13 2630
## 2024-11-14 2590
## 2024-11-15 2580
## 2024-11-18 2610
## 2024-11-19 2850
## 2024-11-20 2750
## 2024-11-21 2810
## 2024-11-22 2790
## 2024-11-25 2780
## 2024-11-26 2800
## 2024-11-28 2750
## 2024-11-29 2760
## 2024-12-02 2730
## 2024-12-03 2830
## 2024-12-04 2850
## 2024-12-05 2840
## 2024-12-06 2780
## 2024-12-09 2770
## 2024-12-10 2830
## 2024-12-11 2880
## 2024-12-12 2850
## 2024-12-13 2790
## 2024-12-16 2760
## 2024-12-17 2650
## 2024-12-18 2660

Visualisasi Data

# Membuat grafik interaktif
dygraph(data_xts, main = "Pergerakan Nilai High") %>%
  dyAxis("y", label = "Nilai High") %>%
  dyAxis("x", label = "Tanggal") %>%
  dyRangeSelector()

Uji Stasioneritas Data

adf_result <- adf.test(data_xts, alternative = "stationary")
print(adf_result)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  data_xts
## Dickey-Fuller = -2.3016, Lag order = 4, p-value = 0.4518
## alternative hypothesis: stationary
cek_stasioneritas <- function(seri_waktu, tingkat_signifikansi = 0.05) {
  hasil_adf <- adf.test(seri_waktu, alternative = "stationary")
  print(hasil_adf)
  if (hasil_adf$p.value < tingkat_signifikansi) {
    cat("Deret waktu ini stasioner.\n")
  } else {
    cat("Deret waktu ini tidak stasioner.\n")
  }
}

cek_stasioneritas(data_xts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  seri_waktu
## Dickey-Fuller = -2.3016, Lag order = 4, p-value = 0.4518
## alternative hypothesis: stationary
## 
## Deret waktu ini tidak stasioner.

Differencing Data

ts_diff_1 <- diff(data_xts)
ts_diff_1 <- na.omit(ts_diff_1)
plot(ts_diff_1, type = "l", main = "Differenced Time Series", ylab = "Differenced Value", xlab = "Index")

acf(ts_diff_1, main = "Plot ACF")

pacf(ts_diff_1, main = "Plot PACF")

# Membagi Data

train_size <- floor(0.7 * length(data_xts))
train_data <- data_xts[1:train_size]
test_data <- data_xts[(train_size + 1):length(data_xts)]

Model ARIMA

# Mencari kombinasi terbaik p, d, q dengan auto.arima
best_arima_model <- auto.arima(train_data)
print(best_arima_model)
## Series: train_data 
## ARIMA(0,1,0) 
## 
## sigma^2 = 1511:  log likelihood = -340.29
## AIC=682.59   AICc=682.65   BIC=684.79
# Prediksi
forecast_values <- forecast(best_arima_model, h = length(test_data))

# Plot hasil prediksi
plot(forecast_values, main = "Prediksi ARIMA vs Data Asli")

lines(test_data, col = "red")

# Evaluasi Model ARIMA

evaluate_arima_model <- function(train, test, arima_order) {
  model <- tryCatch({
    arima(train, order = arima_order)
  }, error = function(e) {
    return(NULL)
  })
  
  if (!is.null(model)) {
    forecast_values <- forecast(model, h = length(test))
    rmse <- sqrt(mean((forecast_values$mean - test)^2))
    return(rmse)
  } else {
    return(Inf)
  }
}

p_values <- 0:2
d_values <- 0:2
q_values <- 0:2
best_score <- Inf
best_cfg <- NULL

for (p in p_values) {
  for (d in d_values) {
    for (q in q_values) {
      order <- c(p, d, q)
      rmse <- evaluate_arima_model(train_data, test_data, order)
      if (rmse < best_score) {
        best_score <- rmse
        best_cfg <- order
      }
      cat(sprintf("ARIMA(%d, %d, %d) RMSE=%.3f\n", p, d, q, rmse))
    }
  }
}
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(0, 0, 0) RMSE=260.425
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(0, 0, 1) RMSE=256.762
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(0, 0, 2) RMSE=254.395
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(0, 1, 0) RMSE=97.211
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(0, 1, 1) RMSE=97.415
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(0, 1, 2) RMSE=96.204
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(0, 2, 0) RMSE=97.211
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(0, 2, 1) RMSE=147.545
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(0, 2, 2) RMSE=115.124
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(1, 0, 0) RMSE=160.613
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(1, 0, 1) RMSE=176.580
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(1, 0, 2) RMSE=205.834
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(1, 1, 0) RMSE=97.211
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(1, 1, 1) RMSE=95.567
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(1, 1, 2) RMSE=96.314
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(1, 2, 0) RMSE=170.474
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(1, 2, 1) RMSE=100.739
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(1, 2, 2) RMSE=89.513
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(2, 0, 0) RMSE=189.231
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(2, 0, 1) RMSE=218.103
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(2, 0, 2) RMSE=208.126
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(2, 1, 0) RMSE=94.099
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(2, 1, 1) RMSE=94.915
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(2, 1, 2) RMSE=99.647
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(2, 2, 0) RMSE=210.877
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(2, 2, 1) RMSE=89.512
## Warning in mean((forecast_values$mean - test)^2): Incompatible methods
## ("Ops.ts", "Ops.xts") for "-"
## ARIMA(2, 2, 2) RMSE=89.627
cat(sprintf("Best ARIMA(%d, %d, %d) RMSE=%.3f\n", best_cfg[1], best_cfg[2], best_cfg[3], best_score))
## Best ARIMA(2, 2, 1) RMSE=89.512

Prediksi dengan Model Terbaik

final_model <- arima(train_data, order = best_cfg)
forecast_values <- forecast(final_model, h = 9)

# Plot Prediksi
plot(data_xts, main = "Prediksi ARIMA", col = "blue")
lines(forecast_values$mean, col = "red", lty = 2)
legend("topright", legend = c("Data Asli", "Prediksi"), col = c("blue", "red"), lty = c(1, 2))