Pendugaan Parameter, Diagnostik Model, dan Peramalan

Angga Fathan Rofiqy

16 October, 2023

Kode di Hide dalam default, untuk menampilkan kode, klik Code .

#                      -=( Install & Load Package Function )=-
install_load <- function (package1, ...)  {   

   # convert arguments to vector
   packages <- c(package1, ...)

   # start loop to determine if each package is installed
   for(package in packages){

       # if package is installed locally, load
       if(package %in% rownames(installed.packages()))
          do.call('library', list(package))

       # if package is not installed locally, download, then load
       else {
          install.packages(package)
          do.call("library", list(package))
       }
   } 
}
path <- function(){
  gsub  ( "\\\\",  "/",  readClipboard ()  )
}
#Copy path, Panggil function di console
#Copy r path, paste ke var yang diinginkan
#Export chart
export.chart <- "C:/Users/Fathan/Documents/Obsidian Vault/2. Kuliah/Smt 5/6. Metode Peramalan Deret Waktu/@Proj/STA1341-MPDW/Pertemuan 67/Chart"

1 Tentang Data

Dataset yang saya gunakan merupakan koleksi data harga saham historis periode Juli 2018 hingga Juli 2023 dari beberapa raksasa teknologi paling berpengaruh di dunia: Microsoft, Apple, Amazon, Nvidia, Google, Netflix, dan Meta (sebelumnya dikenal sebagai Facebook). Dataset ini menjadi sumber daya berharga bagi analis keuangan, ilmuwan data, dan penggemar pasar saham yang ingin menganalisis dan memahami tren harga perusahaan-perusahaan terkemuka di industri ini.

Dataset ini memilki data :

  1. Open: yakni Harga saham pada awal periode perdagangan tertentu. Ini adalah harga saham pertama pada hari perdagangan tersebut.
  2. High: Harga tertinggi yang saham capai selama periode perdagangan tersebut. Ini mencerminkan harga tertinggi yang pembeli bersedia bayar selama hari tersebut.
  3. Low: Harga terendah yang saham capai selama periode perdagangan tersebut. Ini mencerminkan harga terendah yang penjual bersedia terima selama hari tersebut.
  4. Close: Harga saham pada akhir periode perdagangan tertentu. Ini adalah harga saham terakhir pada hari perdagangan tersebut.
  5. Adj Close (Adjusted Close): Harga penutup yang telah disesuaikan untuk memperhitungkan perubahan seperti pembagian saham atau dividen. Ini adalah harga penutup yang paling relevan untuk analisis jangka panjang, karena mencerminkan harga saham yang sebenarnya setelah penyesuaian.
  6. Volume: Volume perdagangan saham selama periode tertentu. Ini mencerminkan jumlah saham yang diperdagangkan selama hari perdagangan tersebut.

Karena tugas kali ini hanya menggunakan satu peubah dan satu kategori saja. Maka kali ini saya akan menggunakan peubah Adj Close (Adjusted Close) .Karena Adj Close Adalah peubah yang paling sesuai untuk dianalisis dibandingkan peubah lainnya. Untuk pemilihan data sahamnya, saya ingin mengeksplorasi terlebih dahulu.

1.1 Data Preparation

1.1.1 Import Data

install_load('rio')
raw.data <- import("https://raw.githubusercontent.com/Zen-Rofiqy/STA1341-MPDW/main/Data/MAANG%20Stock%20Prices.csv")

1.1.2 Data Checking

Cek Tipe data.

str(raw.data)
## 'data.frame':    8812 obs. of  8 variables:
##  $ Name     : chr  "AMZN" "AMZN" "AMZN" "AMZN" ...
##  $ Date     : chr  "7/30/18" "7/31/18" "8/1/18" "8/2/18" ...
##  $ Open     : chr  "91.366501" "89.324501" "89.199997" "89.438499" ...
##  $ High     : chr  "91.474998" "90.091499" "89.921997" "91.828003" ...
##  $ Low      : chr  "88.301003" "86.966003" "88.801003" "89.300003" ...
##  $ Close    : chr  "88.960999" "88.872002" "89.858498" "91.716499" ...
##  $ Adj Close: chr  "88.960999" "88.872002" "89.858498" "91.716499" ...
##  $ Volume   : chr  "131246000" "114774000" "83062000" "87094000" ...

Semua data Karakter, harus diubah.

Cek Data kosong.

sum(is.na(raw.data))
## [1] 0

Tidak ada data kosong.

1.1.3 Penyesuaian Tipe Data

Semua tipe data masih berupa character. Harus diubah menjadi tipe data yang sesuai.

install_load('dplyr')
data <- raw.data %>%  
  mutate(
    Date = as.Date(raw.data[, 2], format = "%m/%d/%y"), #Mengubah menjadi Date 
    across(3:ncol(raw.data), as.numeric)                #Mengubah menjadi Numerik
  )
str(data)
## 'data.frame':    8812 obs. of  8 variables:
##  $ Name     : chr  "AMZN" "AMZN" "AMZN" "AMZN" ...
##  $ Date     : Date, format: "2018-07-30" "2018-07-31" ...
##  $ Open     : num  91.4 89.3 89.2 89.4 91.9 ...
##  $ High     : num  91.5 90.1 89.9 91.8 92.1 ...
##  $ Low      : num  88.3 87 88.8 89.3 91.1 ...
##  $ Close    : num  89 88.9 89.9 91.7 91.2 ...
##  $ Adj Close: num  89 88.9 89.9 91.7 91.2 ...
##  $ Volume   : num  1.31e+08 1.15e+08 8.31e+07 8.71e+07 6.92e+07 ...

1.1.4 Rechecking Data 

Cek kembali data kosong.

cat('Banyaknya Data Kosong', sum(is.na(data)))
## Banyaknya Data Kosong 42

Melihat baris, kolom mana data yang kosong.

# Mencari indeks baris dan kolom yang mengandung NA
na.idx <- which(is.na(data), arr.ind = TRUE)

# Menampilkan data raw dengan baris dan kolom yang mengandung NA
install_load('DT')
## Warning: package 'DT' was built under R version 4.2.3
datatable(raw.data[                        # Subsetting
                unique(na.idx[, 1]),   # Vektor indeks baris yang mengandung NA
                unique(na.idx[, 2])  ] # Vektor indeks kolom yang mengandung NA
          )  

Ternyata pada baris tersebut ada data karakter text yang merupakan label dari tiap kolomnya. Sehingga ketika diubah ke numerik akan menjadi NA. Maka saya akan menghapus baris tersebut.

1.1.5 Data Cleaned

data <- data %>%
  filter(!row_number() %in% unique(na.idx[, 1]))
datatable(data, filter = 'top', 
          options = list(pageLength = 5))

1.2 Pemilihan Variabel Saham

install_load('ggplot2','extrafont')
# font_import(); loadfonts() #Run ini sekali aja
theme.ts <- list(
  theme(legend.position = "none",
        axis.text.x = element_text(hjust = 1, 
                                   margin = margin(b = 10, t=20)),
        axis.text.y = element_text(vjust = 0.5, face = "bold", 
                                   margin = margin(l = 20, r = 20)),
        plot.title = element_text(hjust = 0.5, face = "bold"),
        text = element_text(size = 30),
        plot.subtitle = element_text(hjust = 0.5),
        panel.background = element_rect(fill = 'transparent'),
        plot.background = element_rect(fill='transparent', color=NA),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        axis.line = element_line(linewidth = 1, colour = "black"))
        )
theme.ts1 <- list(
  theme(legend.position = "none",
        axis.text.x = element_text(hjust = 1, 
                                   margin = margin(b = 10, t=20)),
        axis.text.y = element_text(vjust = 0.5, face = "bold", 
                                   margin = margin(l = 50, r = 20)),
        plot.title = element_text(hjust = 0.5, face = "bold"),
        text = element_text(size = 30),
        plot.subtitle = element_text(hjust = 0.5),
        panel.background = element_rect(fill = 'transparent'),
        plot.background = element_rect(fill='transparent', color=NA),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        axis.line = element_line(linewidth = 1, colour = "black"))
        )

1.2.1 Time Series MAANG

Melihat keseluruhan Time Series data saham.

install_load('viridis','ggrepel')
#Plot
chart <-
ggplot(data, aes(x=Date, y=`Adj Close`, color=Name, alpha=Name)) + #Data
  geom_line(aes(color=Name), linewidth=1.5) + #Timeseries
  #Color
  scale_color_manual(values = c(NVDA="green4", NFLX="red4", MSFT="steelblue3",
                                META="royalblue4", AAPL="lightskyblue4",
                                GOOG="yellow3", AMZN="orange2") ) +
  scale_alpha_manual(values = c("NVDA" = .25, "NFLX" = .25, "MSFT" = .25, 
                                "META" = .25, "AAPL" = .25, "GOOG" = .25, 
                                "AMZN" = 1)) +
  theme.ts + #THeme
  labs(x = "\nPeriode (Tahun)", y='Harga Saham (USD)',
       title = "Time Series MAANG",
       subtitle = "Seperti apa sih pola deret waktu saham MAANG?\n") +
  # Label / legend
  geom_text_repel(
    data=data[data$Date == max(data$Date),], #Posisi di ujung data
    aes(color = Name, label = Name), #Warna garis & label saham
    size = 8, #Ukuran text
    nudge_x = 80, #Posisi Text (kanan 50)
    hjust = 0, #Ujung
    segment.size = 1,               #Ukuran garis
    segment.alpha = .75,             #transparasi garis
    segment.linetype = "dotted",    #Time garis
    box.padding = .4, #Biar label saham nggak dempetan
    segment.curvature = -0.1, #biar garis mulus
    segment.ncp = 8, 
    segment.angle = 60 
  ) +
  #Axis
    coord_cartesian(clip = "off"
  ) +
    scale_x_date( #Sumbu x
    date_breaks = "1 year",  # Menampilkan label setiap tahun
    date_labels = "%Y",  # Format label tahun
    limits = c(as.Date("2018-07-30"), as.Date("2023-12-28"))
    #Tampilin lebih dari 20023-07-28 agar label saham bisa masuk
  ) +
    scale_y_continuous( #Sumbu y
    labels = scales::dollar_format(prefix = "$") #tambahin dolar
  ) +
    annotate( #Buat nandain batas data
    "text", x = as.Date("2023-7-28"), y = 50, 
    label = "28 Juli", size=6
  ) +
  geom_vline( #Buat garis batas data
    xintercept = as.numeric(as.Date("2023-07-28")), 
             linetype = "dotted", color = "red")
chart

#Export Chart
ggsave("01_Time Series MAANG.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 23)

Jika dilihat dari tahun 2019-2022, semua saham cenderung memiliki pola trend naik. Lalu dari 2021-2023 polanya cenderung trend turun. Untuk tugas praktikum kali ini, saya hanya akan menggunakan rentang tahun 2022-2023 dengan tren cenderung turun. Agar pengerjaannya tidak terlalu sulit, karena masih tahap awal pembelajaran.

Ada yang menarik perhatian saya. Kenapa dulu Pendiri Amazon, Jeff Bezos yang pernah menjadi orang terkaya di dunia pada tahun 2017 lalu, harga saham sekarang tidak setinggi yang saya kira?. Oleh karena itu saya memutuskan untuk menggunakan data saham Amazon untuk praktikum kali ini.

amzn <- data %>%
  select(1, 2, 7) %>%  # Memilih kolom 1, 2, dan 7
  filter(Name == "AMZN", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(amzn) <- NULL
str(amzn)
## 'data.frame':    394 obs. of  3 variables:
##  $ Name     : chr  "AMZN" "AMZN" "AMZN" "AMZN" ...
##  $ Date     : Date, format: "2022-01-03" "2022-01-04" ...
##  $ Adj Close: num  170 168 164 163 163 ...
datatable(amzn)

Mengubah Ajd Close Menjadi Time series.

amzn.ts <- ts(amzn[,3])

Ringkasan Data Ajd CLose.

summary(amzn.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   81.82  102.01  115.77  119.81  134.88  170.40

1.2.2 Time Series Amazon

min_value <- min(amzn$`Adj Close`)
min_date <- amzn$Date[which.min(amzn$`Adj Close`)]
percentage <- (which.min(amzn$`Adj Close`) / nrow(amzn)) * 100

chart <-
ggplot(amzn, aes(x=Date, y=`Adj Close`)) + 
  geom_line(aes(color=Name), linewidth=2) +
  scale_color_manual(values = c("orange2")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Amazon",
       subtitle = "Seperti apa sih pola deret waktu saham Amazon?\n") +
  theme(legend.position = "none") +
  theme.ts1 + 
  geom_vline(xintercept = as.numeric(min_date), 
             linetype = "dotted", color = "cyan4", linewidth = 1.5) +
  geom_text(aes(x = min_date-1*40, y = max(`Adj Close`)/1.59, label = 
                  paste0("Titik Potong\n","(",round(percentage, 2), "%)",
                         "   ",min_date)), 
            vjust = -1.5, hjust = 0, size = 7, color = "cyan4") 
chart

#Export Chart
ggsave("02_Time Series Amazon.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Berdasarkan chart data deret waktu diatas, terlihat bahwa data cenderung memiliki trend naik dan turun dengan titik potong di tanggal 20222-12-28. Namun titik potongnya masih jauh dari angka \(80\%\). Sehingga tidak akan dijadikan acuan untuk pemisahan data training dan testing.

Pembagian Data Training Dan Test.

#membagi 80% data latih (training) dan 20% data uji (testing)
training <- amzn[1: round(nrow(amzn) *80/100),]
testing <- amzn[round(nrow(amzn) *80/100): nrow(amzn),]
train.ts <- ts(training[,3])
test.ts <- ts(testing[,3])
chart <-
ggplot() + 
  geom_line(data = training, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Latih")) +
  geom_line(data = testing, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Uji")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Amazon",
       subtitle = "Pembagian Data Training dan Test\n") +
  theme(legend.position = "none") +
  scale_colour_manual(name="Keterangan:", 
                      breaks = c("Data Latih", "Data Uji"),
                      values = c("orange", "cyan4")) + theme.ts1
chart

#Export Chart
ggsave("02_TSA_train-test.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)

Berdasarkan plot data deret waktu pada data training, terlihat bahwa data cenderung memiliki trend yang turun dan cenderung tidak bergerak pada nilai tengah tertentu. Hal ini mengindikasikan bahwa data tidak stasioner dalam rataan. Pada plot data uji, terlihat bahwa data cenderung memiliki trend yang naik dan cenderung tidak bergerak pada nilai tengah tertentu. Hal ini mengindikasikan bahwa data uji tidak stasioner dalam rataan.

library(ggplot2)
library(tsibble)
library(tseries)

2 Uji Stasioner Data

2.1 Plot ACF

acf(train.ts)

Berdasarkan plot ACF, terlihat bahwa plot ACF data train menurun secara perlahan (tails of slowly). Hal ini juga menjadi indikasi bahwa data tidak stasioner dalam rataan dan tidak membentuk gelombang sinus.

2.2 Uji ADF

tseries::adf.test(train.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train.ts
## Dickey-Fuller = -2.6387, Lag order = 6, p-value = 0.3071
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.3071\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa data tidak stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga ketidakstasioneran model kedepannya harus ditangani.

2.3 Plot Box-Cox

install_load('MASS')
## 
## Attaching package: 'MASS'
## The following object is masked from 'package:dplyr':
## 
##     select
index <- seq(1:nrow(amzn))
bc = boxcox(amzn.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda <- bc$x[which.max(bc$y)]
#SK
sk <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk), "\n Batas Bawah :", max(sk) )
##  Lambda : 0.21 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : -0.33 
##  Batas Bawah : 0.74

Gambar di atas menunjukkan nilai rounded value (\(\lambda\)) optimum sebesar \(0.21\) dan pada selang kepercayaan \(95\%\) nilai memiliki batas bawah \(0\) dan batas atas \(0.74\). Selang tersebut tidak memuat nilai satu sehingga dapat dikatakan bahwa data saham amazon tidak stasioner dalam ragam.

2.4 Penanganan Ketidakstasioneran Data

train.diff <- diff(train.ts, differences = 1) 
plot.ts(train.diff, lty=1, xlab="Periode (Tahun)", col = "orange", lwd = 3.5,
        ylab="Saham Harga penutup", 
        main="Plot Difference Saham Amazon")

Berdasarkan plot data deret waktu, terlihat bahwa data sudah stasioner dalam rataan ditandai dengan data bergerak pada nilai tengah tertentu (tidak terdapat trend ataupun musiman pada data).

3 Uji Ulang

3.1 Plot ACF

acf(train.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cuts off pada lag ke 13. Sejalan dengan penanganannya, data sudah stasioner dalam rataan dan ketidakstasioneran data telah berhasil tertangani.

3.2 Uji ADF

tseries::adf.test(train.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train.diff
## Dickey-Fuller = -6.515, Lag order = 6, p-value = 0.01
## alternative hypothesis: stationary

\(H_0\) : Data tidak stasioner dalam rataan

\(H_1\) : Data stasioner dalam rataan

Berdasarkan uji ADF tersebut, didapat p-value sebesar \(0.01\) yang lebih kecil dari taraf nyata \(5\%\) sehingga tolak \(H_0\) atau data stasioner dalam rataan. Hal ini sesuai dengan hasil eksplorasi menggunakan plot time series dan plot ACF, sehingga dalam hal ini ketidakstasioneran data sudah berhasil ditangani dan dapat dilanjutkan ke pemodelan.

4 Identifikasi Model

4.1 Plot ACF

acf(train.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cenderung cuts off pada lag ke 13.

4.2 PACF

pacf(train.diff)

Berdasarkan plot tersebut, terlihat bahwa plot PACF cenderung cuts off pada lag ke 13 dan 15.

4.3 Plot EACF

install_load('TSA')
eacf(train.diff)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  x  o 
## 1 x o o o o o o o o o o  o  x  o 
## 2 o x o o o o o o o o o  o  o  o 
## 3 x x x o o o o o o o o  o  o  o 
## 4 x x x x o o o o o o o  o  o  o 
## 5 x x o x o o o o o o o  o  o  o 
## 6 x o o x o x o o o o o  o  o  o 
## 7 x o x x o x o o o o o  o  o  o

Identifikasi model menggunakan plot EACF dilakukan dengan melihat titik sudut kiri segitiga pada pola segitiga nol atas (pola mariks segitiga bawah).

Dalam hal ini model tentatif yang terbentuk adalah ARIMA(0,1,1), ARIMA(1,1,1), ARIMA(2,1,2), ARIMA(3,1,3), dst..

5 Pendugaan Parameter Model Tentatif

5.1 Menggunakan Function

Keterangan parameter function :

  • data = data Time Series baik yang sudah di .diff maupun belum

  • p_max = ordo maksimal dari AR

  • d = ordo I

  • q_max = ordo maksimal dari MA

  • alpha = alpha

install_load('forecast')

# Fungsi untuk menghitung model ARIMA dan menganalisis parameter
analyze_ARIMA_models <- function(data, p_max, d, q_max, alpha=0.05) {
  best_model <- NULL
  best_aic <- Inf
  eacf_result <- eacf(data)
  models <- data.frame(Model = character(0), 
                       AIC = numeric(0), 
                       Signif = character(0), 
                       Keterangan = character(0))
  
  for (p in 0:p_max) {
    for (q in 1:q_max) {
      if (!is.na(eacf_result$symbol[p + 1, q + 1]) && 
          !is.na(eacf_result$symbol[p + 1, q + 2]) && 
          !is.na(eacf_result$symbol[p + 2, q + 2])) {
        if (eacf_result$symbol[p + 1, q + 1] == "o" && 
            eacf_result$symbol[p + 1, q + 2] == "o" && 
            eacf_result$symbol[p + 2, q + 2] == "o") {
      
          model <- Arima(data, order = c(p, d, q), method = "ML")
          aic <- AIC(model)
          
          # Mendapatkan nilai coef dari model
          coeftest_result <- lmtest::coeftest(model)
          
          # jika lebih kecil dari alpha, maka signifikan
          significant_params <- 
            rownames(coeftest_result)[coeftest_result[, "Pr(>|z|)"] < alpha]  
          
          # jika lebih besar dari alpha, maka tidak signifikan
          non_significant_params <- 
            rownames(coeftest_result)[coeftest_result[, "Pr(>|z|)"] > alpha]  
          
          # Keterangan signifikansi
          if (length(significant_params) == 0) {
            keterangan <- "Semua parameter tidak signifikan"
          } else if (length(significant_params) == nrow(coeftest_result)) {
            keterangan <- "Semua parameter signifikan"
          } else {
            keterangan <- paste("Parameter yang tidak signifikan adalah", 
                                paste(non_significant_params, collapse = ", "))
          }
          
          models <- rbind(models, 
                    data.frame(Model = paste("ARIMA(", p, ",", d, ",", q, ")", 
                                             sep = ""), 
                               AIC = aic, 
                               Signif = paste(significant_params, collapse = ", "), 
                               Keterangan = keterangan))
          
            if (aic < best_aic) {
              best_model <- model
              best_aic <- aic
          }
        }
      }
    }
  }
  
  cat("\nModel ARIMA dengan AIC terkecil:\n")
  print(best_model)

  datatable(models, filter = 'top', 
          options = list(pageLength = 5))
}

# Contoh penggunaan fungsi dengan p_max = 3, q_max = 3
analyze_ARIMA_models(train.diff, p_max = 6, d = 1, q_max = 12)
## AR/MA
##   0 1 2 3 4 5 6 7 8 9 10 11 12 13
## 0 o o o o o o o o o o o  o  x  o 
## 1 x o o o o o o o o o o  o  x  o 
## 2 o x o o o o o o o o o  o  o  o 
## 3 x x x o o o o o o o o  o  o  o 
## 4 x x x x o o o o o o o  o  o  o 
## 5 x x o x o o o o o o o  o  o  o 
## 6 x o o x o x o o o o o  o  o  o 
## 7 x o x x o x o o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(4,1,5) 
## 
## Coefficients:
##           ar1     ar2      ar3      ar4      ma1      ma2     ma3     ma4
##       -0.2750  0.4927  -0.2505  -0.8488  -0.6975  -0.7685  0.7276  0.7147
## s.e.   0.0519  0.0554   0.0493   0.0482   0.0348   0.0276  0.0424  0.0297
##           ma5
##       -0.9762
## s.e.   0.0317
## 
## sigma^2 = 13.22:  log likelihood = -849.02
## AIC=1718.04   AICc=1718.77   BIC=1755.5

Berdasarkan pendugaan parameter di atas, nilai AIC terkecil \(1718.04\) dimiliki oleh model ARIMA(4,1,5) dan seluruh parameternya signifikan sehingga model yang dipilih adalah model ARIMA(4,1,5).

5.2 Manual

Pembuktian Function nya sudah benar.

5.2.1 ARIMA(0,1,1)

model1.da=Arima(train.diff, order=c(0,1,1),method="ML")
summary(model1.da)
## Series: train.diff 
## ARIMA(0,1,1) 
## 
## Coefficients:
##           ma1
##       -1.0000
## s.e.   0.0131
## 
## sigma^2 = 13.87:  log likelihood = -858.02
## AIC=1720.04   AICc=1720.08   BIC=1727.53
## 
## Training set error measures:
##                     ME     RMSE      MAE     MPE     MAPE      MASE        ACF1
## Training set 0.2263963 3.711957 2.701246 102.999 130.2316 0.7194769 -0.01544094
lmtest::coeftest(model1.da)
## 
## z test of coefficients:
## 
##      Estimate Std. Error z value  Pr(>|z|)    
## ma1 -0.999994   0.013122 -76.205 < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Didapatkan nilai AIC sebesar \(1720.04\) dan seluruh parameter signifikan.

Sesuai dengan function

5.2.2 ARIMA(1,1,1)

model2.da=Arima(train.diff, order=c(1,1,1),method="ML")
summary(model2.da)
## Series: train.diff 
## ARIMA(1,1,1) 
## 
## Coefficients:
##           ar1      ma1
##       -0.0099  -1.0000
## s.e.   0.0566   0.0133
## 
## sigma^2 = 13.91:  log likelihood = -858
## AIC=1722.01   AICc=1722.08   BIC=1733.25
## 
## Training set error measures:
##                     ME     RMSE      MAE      MPE     MAPE      MASE
## Training set 0.2282761 3.711646 2.704446 102.3478 130.0943 0.7203291
##                      ACF1
## Training set -0.004925212
lmtest::coeftest(model2.da)
## 
## z test of coefficients:
## 
##       Estimate Std. Error  z value Pr(>|z|)    
## ar1 -0.0099178  0.0565844  -0.1753   0.8609    
## ma1 -0.9999999  0.0133448 -74.9355   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Didapatkan nilai AIC sebesar \(1722.01\) dan parameter ar1 tidak signifikan.

Sesuai dengan function

5.2.3 ARIMA(2,1,2)

model3.da=Arima(train.diff, order=c(2,1,2),method="ML")
summary(model3.da)
## Series: train.diff 
## ARIMA(2,1,2) 
## 
## Coefficients:
##           ar1     ar2      ma1      ma2
##       -0.3613  0.0603  -0.6457  -0.3542
## s.e.   1.1394  0.0650   1.1429   1.1427
## 
## sigma^2 = 13.94:  log likelihood = -857.28
## AIC=1724.55   AICc=1724.75   BIC=1743.28
## 
## Training set error measures:
##                     ME     RMSE      MAE      MPE     MAPE      MASE
## Training set 0.2203966 3.703627 2.703416 95.80655 127.7273 0.7200548
##                      ACF1
## Training set -0.005979234
lmtest::coeftest(model3.da)
## 
## z test of coefficients:
## 
##      Estimate Std. Error z value Pr(>|z|)
## ar1 -0.361269   1.139416 -0.3171   0.7512
## ar2  0.060255   0.064954  0.9277   0.3536
## ma1 -0.645719   1.142861 -0.5650   0.5721
## ma2 -0.354238   1.142704 -0.3100   0.7566

Didapatkan nilai AIC sebesar \(1724.55\) dan semua parameter tidak signifikan.

Sesuai dengan function

5.2.4 ARIMA(3,1,3)

model4.da=Arima(train.diff, order=c(3,1,3),method="ML")
summary(model4.da)
## Series: train.diff 
## ARIMA(3,1,3) 
## 
## Coefficients:
##           ar1     ar2     ar3      ma1      ma2     ma3
##       -0.1041  0.3262  0.0017  -0.9038  -0.3547  0.2585
## s.e.   0.9780  0.4728  0.0887   0.9764   0.7967  0.4738
## 
## sigma^2 = 14.02:  log likelihood = -857.17
## AIC=1728.33   AICc=1728.7   BIC=1754.56
## 
## Training set error measures:
##                     ME    RMSE      MAE      MPE     MAPE      MASE
## Training set 0.2154983 3.70268 2.705672 96.69477 128.6789 0.7206558
##                      ACF1
## Training set -0.005229142
lmtest::coeftest(model4.da)
## 
## z test of coefficients:
## 
##       Estimate Std. Error z value Pr(>|z|)
## ar1 -0.1040802  0.9780405 -0.1064   0.9153
## ar2  0.3261986  0.4727589  0.6900   0.4902
## ar3  0.0017341  0.0886766  0.0196   0.9844
## ma1 -0.9038021  0.9763744 -0.9257   0.3546
## ma2 -0.3546642  0.7967347 -0.4451   0.6562
## ma3  0.2584697  0.4737918  0.5455   0.5854

Didapatkan nilai AIC sebesar \(1728.33\) dan semua parameter tidak signifikan.

Sesuai dengan function

5.2.5 ARIMA(4,1,5)

model5.da=Arima(train.diff, order=c(4,1,5),method="ML")
summary(model5.da)
## Series: train.diff 
## ARIMA(4,1,5) 
## 
## Coefficients:
##           ar1     ar2      ar3      ar4      ma1      ma2     ma3     ma4
##       -0.2750  0.4927  -0.2505  -0.8488  -0.6975  -0.7685  0.7276  0.7147
## s.e.   0.0519  0.0554   0.0493   0.0482   0.0348   0.0276  0.0424  0.0297
##           ma5
##       -0.9762
## s.e.   0.0317
## 
## sigma^2 = 13.22:  log likelihood = -849.02
## AIC=1718.04   AICc=1718.77   BIC=1755.5
## 
## Training set error measures:
##                    ME     RMSE      MAE      MPE     MAPE      MASE        ACF1
## Training set 0.207726 3.577948 2.622015 107.5843 161.1924 0.6983738 -0.01911452
lmtest::coeftest(model5.da)
## 
## z test of coefficients:
## 
##      Estimate Std. Error  z value  Pr(>|z|)    
## ar1 -0.275029   0.051891  -5.3001 1.157e-07 ***
## ar2  0.492659   0.055361   8.8991 < 2.2e-16 ***
## ar3 -0.250506   0.049259  -5.0855 3.667e-07 ***
## ar4 -0.848818   0.048201 -17.6100 < 2.2e-16 ***
## ma1 -0.697516   0.034758 -20.0675 < 2.2e-16 ***
## ma2 -0.768509   0.027565 -27.8799 < 2.2e-16 ***
## ma3  0.727565   0.042374  17.1699 < 2.2e-16 ***
## ma4  0.714674   0.029735  24.0347 < 2.2e-16 ***
## ma5 -0.976213   0.031736 -30.7602 < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
best.model.da <- model5.da

6 Analisis Sisaan

Model terbaik hasil identifikasi kemudian dicek asumsi sisaannya. Sisaan model ARIMA harus memenuhi asumsi normalitas, kebebasan sisaan, dan kehomogenan ragam. Diagnostik model dilakukan secara eksplorasi dan uji formal.

6.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan.da <- best.model.da$residuals 
par(mfrow=c(2,2)) 
qqnorm(sisaan.da) 
qqline(sisaan.da, col = "blue", lwd = 2) 
plot(c(1:length(sisaan.da)),sisaan.da) 
acf(sisaan.da) 
pacf(sisaan.da) 

Berdasarkan plot kuantil-kuantil normal, secara eksplorasi ditunjukkan sisaan tidak menyebar normal ditandai dengan titik titik yang cenderung tidak mengikuti garis \(45^{\circ}\). Kemudian dapat dilihat juga lebar pita sisaan yang cenderung sama menandakan bahwa sisaan memiliki ragam yang homogen. Plot ACF dan PACF sisaan ARIMA(4,1,5) juga tidak signifikan pada lag 13 yang menandakan saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

6.2 Uji Formal

6.2.1 Sisaan Menyebar Normal

ks.test(sisaan.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan.da
## D = 0.27186, p-value < 2.2e-16
## alternative hypothesis: two-sided

Selain dengan eksplorasi, asumsi tersebut dapat diuji menggunakan uji formal. Pada tahapan ini uji formal yang digunakan untuk normalitas adalah uji Kolmogorov-Smirnov (KS). Hipotesis pada uji KS adalah sebagai berikut.

\(H_0\) : Sisaan menyebar normal

\(H_1\) : Sisaan tidak menyebar normal

Berdasarkan uji KS tersebut, didapat p-value sebesar \(2.2e-16\) yang kurang dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa sisaan tidak menyebar normal. Hal ini sesuai dengan hasil eksplorasi menggunakan plot kuantil-kuantil normal.

6.2.2 Sisaan saling bebas/tidak ada autokorelasi

Box.test(sisaan.da, type = "Ljung")  #tak tolak H0 > sisaan saling bebas
## 
##  Box-Ljung test
## 
## data:  sisaan.da
## X-squared = 0.11582, df = 1, p-value = 0.7336

Selanjutnya akan dilakukan uji formal untuk kebebasan sisaan menggunakan uji Ljung-Box. Hipotesis yang digunakan adalah sebagai berikut.

\(H_0\) : Sisaan saling bebas

\(H_1\) : Sisaan tidak tidak saling bebas

Berdasarkan uji Ljung-Box tersebut, didapat p-value sebesar \(0.7336\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa sisaan saling bebas. Hal ini sesuai dengan hasil eksplorasi menggunakan plot ACF dan PACF.

6.2.3 Sisaan homogen

Box.test((sisaan.da)^2, type = "Ljung")  #tak tolak H0 > sisaan homogen
## 
##  Box-Ljung test
## 
## data:  (sisaan.da)^2
## X-squared = 5.9174, df = 1, p-value = 0.01499

Hipotesis yang digunakan untuk uji kehomogenan ragam adalah sebagai berikut.

\(H_0\) : Ragam sisaan homogen

\(H_1\) : Ragam sisaan tidak homogen

Berdasarkan uji Ljung-Box terhadap sisaan kuadrat tersebut, didapat p-value sebesar \(0.01499\) yang lebih kecil dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa ragam sisaan tidak homogen.

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan.da
## t = 1.0289, df = 313, p-value = 0.3043
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.1895198  0.6049718
## sample estimates:
## mean of x 
##  0.207726

Terakhir, dengan uji-t, akan dicek apakah nilai tengah sisaan sama dengan nol. Hipotesis yang diujikan sebagai berikut.

\(H_0\) : nilai tengah sisaan sama dengan 0

\(H_1\) : nilai tengah sisaan tidak sama dengan 0

Berdasarkan uji-ttersebut, didapat p-value sebesar \(0.3043\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

7 Peramalan

7.1 Ramal

Peramalan dilakukan menggunakan fungsi forecast() . Contoh peramalan berikut ini dilakukan untuk 54 hari ke depan.

#---FORECAST---#
ramalan.da <- forecast::forecast(best.model.da, h = 54) 
ramalan.da
##     Point Forecast     Lo 80    Hi 80     Lo 95    Hi 95
## 316    0.251247616 -4.429551 4.932046 -6.907416 7.409911
## 317   -0.635499219 -5.317692 4.046694 -7.796295 6.525297
## 318   -0.128136086 -4.811768 4.555496 -7.291132 7.034860
## 319   -0.637500928 -5.322216 4.047214 -7.802154 6.527152
## 320   -0.342710902 -5.063782 4.378360 -7.562966 6.877544
## 321   -0.049140884 -4.774811 4.676529 -7.276430 7.178148
## 322   -0.287710304 -5.019938 4.444518 -7.525028 6.949608
## 323    0.281044764 -4.466269 5.028359 -6.979345 7.541435
## 324   -0.316677265 -5.067468 4.434114 -7.582385 6.949031
## 325   -0.061508105 -4.812310 4.689294 -7.327233 7.204217
## 326   -0.366134987 -5.120338 4.388068 -7.637061 6.904791
## 327   -0.489678815 -5.265427 4.286069 -7.793555 6.814198
## 328   -0.162341996 -4.938168 4.613484 -7.466337 7.141653
## 329   -0.453515624 -5.238579 4.331548 -7.771639 6.864608
## 330    0.077352536 -4.707775 4.862480 -7.240868 7.395573
## 331   -0.189234844 -4.978144 4.599674 -7.513239 7.134770
## 332   -0.059287005 -4.848233 4.729659 -7.383348 7.264774
## 333   -0.112195459 -4.911606 4.687215 -7.452261 7.227870
## 334   -0.417452850 -5.220890 4.385984 -7.763675 6.928770
## 335   -0.165832430 -4.969314 4.637649 -7.512124 7.180459
## 336   -0.482471552 -5.289866 4.324922 -7.834746 6.869803
## 337   -0.150044849 -4.961043 4.660953 -7.507831 7.207742
## 338   -0.201391612 -5.013104 4.610321 -7.560271 7.157488
## 339   -0.157756598 -4.970828 4.655314 -7.518713 7.203200
## 340   -0.009559831 -4.829433 4.810314 -7.380920 7.361800
## 341   -0.298128259 -5.117989 4.521732 -7.669469 7.073212
## 342   -0.113099695 -4.933293 4.707094 -7.484949 7.258750
## 343   -0.380316300 -5.200505 4.439873 -7.752159 6.991527
## 344   -0.269171794 -5.093856 4.555512 -7.647889 7.109546
## 345   -0.232795206 -5.057484 4.591894 -7.611520 7.145930
## 346   -0.278159695 -5.106216 4.549897 -7.662035 7.105716
## 347   -0.048785922 -4.877877 4.780305 -7.434243 7.336671
## 348   -0.237673732 -5.066763 4.591416 -7.623129 7.147782
## 349   -0.092233925 -4.921490 4.737022 -7.477943 7.293476
## 350   -0.244244807 -5.074458 4.585968 -7.631418 7.142929
## 351   -0.278164151 -5.110081 4.553753 -7.667944 7.111616
## 352   -0.219827055 -5.051774 4.612120 -7.609653 7.169999
## 353   -0.337954461 -5.172515 4.496606 -7.731777 7.055868
## 354   -0.139199035 -4.973824 4.695426 -7.533120 7.254722
## 355   -0.237881636 -5.072455 4.596692 -7.631723 7.155960
## 356   -0.132748260 -4.967361 4.701864 -7.526650 7.261154
## 357   -0.159800685 -4.995847 4.676246 -7.555895 7.236294
## 358   -0.244552162 -5.080853 4.591749 -7.641036 7.151931
## 359   -0.177143600 -5.013653 4.659366 -7.573947 7.219659
## 360   -0.319898868 -5.157021 4.517223 -7.717639 7.077841
## 361   -0.203234163 -5.040907 4.634439 -7.601817 7.195348
## 362   -0.250597764 -5.088260 4.587065 -7.649164 7.147968
## 363   -0.201551981 -5.039892 4.636788 -7.601155 7.198051
## 364   -0.146427083 -4.985241 4.692387 -7.546754 7.253900
## 365   -0.224587443 -5.063421 4.614246 -7.624945 7.175770
## 366   -0.148016428 -4.987041 4.691008 -7.548665 7.252632
## 367   -0.263022213 -5.102007 4.575962 -7.663610 7.137566
## 368   -0.220880184 -5.060234 4.618474 -7.622033 7.180273
## 369   -0.241966723 -5.081293 4.597360 -7.643078 7.159145

7.2 Plot

data.ramalan.da <- ramalan.da$mean
plot(ramalan.da)

Berdasarkan hasil plot ramalan di atas, dapat dilihat bahwa ramalan ARIMA(4,1,5) cenderung stabil hingga akhir periode. Selanjutnya, dapat dicari nilai akurasi antara hasil ramalan dengan data uji sebagai berikut.

pt_1 <- train.ts[length(train.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan.da
hasil <- diffinv(hasil.forc.Diff, differences = 1) + pt_1
#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train.ts,hasil)

Dapat dilihat bahwa rata-rata harga lelang plat nomor mobil di shanghai diramalkan akan terus menurun setiap periodenya.

7.3 Perbandingan

perbandingan.da<-matrix(data=c(head(test.ts, n=54), hasil[-1]),
                     nrow = 54, ncol = 2)
colnames(perbandingan.da)<-c("Aktual","Hasil Forecast")
perbandingan.da
##       Aktual Hasil Forecast
##  [1,] 103.95      104.20124
##  [2,] 101.10      103.56575
##  [3,] 102.06      103.43761
##  [4,] 102.17      102.80011
##  [5,]  99.92      102.45740
##  [6,]  97.83      102.40826
##  [7,] 102.40      102.12055
##  [8,] 102.51      102.40159
##  [9,] 102.74      102.08491
## [10,] 102.30      102.02341
## [11,] 104.30      101.65727
## [12,] 103.81      101.16759
## [13,] 106.96      101.00525
## [14,] 106.21      100.55173
## [15,] 102.57      100.62909
## [16,] 104.98      100.43985
## [17,] 109.82      100.38056
## [18,] 105.45      100.26837
## [19,] 102.05       99.85092
## [20,] 103.63       99.68508
## [21,] 103.65       99.20261
## [22,] 104.00       99.05257
## [23,] 105.66       98.85118
## [24,] 105.83       98.69342
## [25,] 106.62       98.68386
## [26,] 110.19       98.38573
## [27,] 112.18       98.27263
## [28,] 110.26       97.89232
## [29,] 111.20       97.62314
## [30,] 113.40       97.39035
## [31,] 115.50       97.11219
## [32,] 118.15       97.06340
## [33,] 116.25       96.82573
## [34,] 115.01       96.73350
## [35,] 114.99       96.48925
## [36,] 116.75       96.21109
## [37,] 115.00       95.99126
## [38,] 120.11       95.65330
## [39,] 121.66       95.51411
## [40,] 120.58       95.27622
## [41,] 122.77       95.14348
## [42,] 124.25       94.98368
## [43,] 125.30       94.73912
## [44,] 126.61       94.56198
## [45,] 121.23       94.24208
## [46,] 124.25       94.03885
## [47,] 123.43       93.78825
## [48,] 126.57       93.58670
## [49,] 126.66       93.44027
## [50,] 126.42       93.21568
## [51,] 127.11       93.06767
## [52,] 125.49       92.80464
## [53,] 125.78       92.58376
## [54,] 124.83       92.34180
accuracy(ts(hasil[-1]), head(test.ts, n=54))
##                ME     RMSE      MAE     MPE     MAPE      ACF1 Theil's U
## Test set 14.47885 19.11476 14.91738 12.0552 12.49469 0.9509729  7.698132

Didapatkan nilai MAPE sebesar \(12.49469\%\) (lebih dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(4,1,5) sudah cukup baik.