Pendugaan Parameter, Diagnostik Model, dan Peramalan

Angga Fathan Rofiqy

31 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 8/Chart"

1 Pendahuluan

Dataset yang saya gunakan merupakan koleksi data harga saham historis periode Juli 2018 hingga Juli 2023 dari tujuh 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.

Kami akan menggunakan peubah Adj Close (Adjusted Close), Karena sesuai dengan penjelasan diatas, peubah Adj Close adalah yang paling sesuai untuk dianalisis dibandingkan peubah lainnya.

1.1 Tujuan

Tujuan dari praktikum ini adalah untuk menganalisis pola perkiraan pergerakan harga tujuh saham teknologi terkemuka dengan harapan dapat memberikan rekomendasi kepada pembaca mengenai saham mana yang sebaiknya dipertimbangkan untuk dibeli atau diinvestasikan secara signifikan di antara tujuh perusahaan teknologi besar tersebut.

1.2 Referensi

1.3 Data Preparation

1.3.1 Import Data

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

1.3.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.3.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.3.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')
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.

data <- data %>%
  filter(!row_number() %in% unique(na.idx[, 1]))
data2 <- data

1.3.5 Cek Periode Data

install_load("lubridate")
## Loading required package: timechange
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
dates <- as.Date(data$Date)

# Buat rentang waktu mulai dari tanggal pertama hingga tanggal terakhir dalam data
full_date_range <- seq(min(dates), max(dates), by = "days")

# Bandingkan rentang waktu dengan tanggal yang ada dalam data
missing_dates <- setdiff(full_date_range, dates) 

# Jika 'missing_dates' kosong, maka semua tanggal sudah ada dalam data
if (length(missing_dates) == 0) {
  cat("Semua tanggal ada dalam data.\n")
} else {
  cat("Tanggal yang tidak ada dalam data sebanyak", length(missing_dates),
      "\nAtau sebanyak", length(missing_dates) * 7, 
      "Data Hilang dari ke-7 perusahaan yang ada")
}
## Tanggal yang tidak ada dalam data sebanyak 567 
## Atau sebanyak 3969 Data Hilang dari ke-7 perusahaan yang ada

Inputasi Data

install_load('purrr')
## Warning: package 'purrr' was built under R version 4.2.3
# Fungsi untuk mengisi data yang hilang
fill_missing_data <- function(name) {
  data_filtered <- data2 %>%
    filter(Name == name)
  
  full_date_range <- seq(min(data2$Date), max(data2$Date), by = "days")
  data_frame_template <- data.frame(Date = full_date_range)
  
  # Menambahkan kolom "Name" sesuai dengan perusahaan yang diproses
  data_frame_template$Name <- name
  
  data_filled <- merge(data_frame_template, data_filtered, 
                       by = c("Date", "Name"), all.x = TRUE)
  return(data_filled)
}

# Menggunakan purrr::map untuk memproses setiap nama perusahaan
filled_data_list <- map(unique(data2$Name), fill_missing_data)

# Gabungkan data-data yang telah diisi menjadi satu data frame
final_data <- data.frame()
final_data <- do.call(rbind, filled_data_list)

# Urutkan data berdasarkan "Name" terlebih dahulu, kemudian "Date"
final_data <- final_data %>%
  dplyr::select(1, 2, 7) %>%
  arrange(Name, Date)

#Input Data Hilang
install_load('imputeTS')
## Warning: package 'imputeTS' was built under R version 4.2.3
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
data <- na_interpolation(final_data$`Adj Close`)
ggplot_na_imputations(final_data$`Adj Close`, data)

data <- final_data %>% select(Name, Date) %>% 
  mutate(`Adj Close` = data)

Data sudah di imputasi.

Cek ukuran data

cat("Ukuran data awal adalah", nrow(data2),
    "\nBanyaknya peride data yang hilang", length(missing_dates),
    "(PerSaham.", length(missing_dates) * 7, "Jika semua)",
    "\nUkuran data yang baru seharusnya", 
    nrow(data2) + length(missing_dates) * 7,
    "\nIni sudah sesuai dengan Ukuran data input (", nrow(data), ")")
## Ukuran data awal adalah 8806 
## Banyaknya peride data yang hilang 567 (PerSaham. 3969 Jika semua) 
## Ukuran data yang baru seharusnya 12775 
## Ini sudah sesuai dengan Ukuran data input ( 12775 )

Data sudah benar, siap untuk dianalisis.

1.3.6 Data Cleaned

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

1.4 Eksplorasi Data

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.4.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="firebrick3", 
                                MSFT="deepskyblue2", META="dodgerblue3", 
                                AAPL="lightskyblue4",
                                GOOG="gold3", AMZN="orange2") ) +
  scale_alpha_manual(values = c("NVDA" = 1, "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)

Data saham berakhir pada tanggal 28 juli dengan harga saham tertinggi yakni NVIDIA dan daham terendah yakni Amazon. 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, kami ingin membandingkan pengambilan rentang tahun mana yang lebih baik forcast/peramalannya. Pada Sesi ini hanya akan menggunakan rentang tahun 2022-2023 dengan tren cenderung turun.

1.4.2 Time Series Apple

aapl <- data %>%
  filter(Name == "AAPL", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(aapl) <- NULL
str(aapl)
## 'data.frame':    574 obs. of  3 variables:
##  $ Name     : chr  "AAPL" "AAPL" "AAPL" "AAPL" ...
##  $ Date     : Date, format: "2022-01-01" "2022-01-02" ...
##  $ Adj Close: num  177 179 180 178 173 ...
datatable(aapl, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

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

Ringkasan Data Ajd CLose.

summary(aapl.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   124.7   145.7   156.4   157.8   169.3   195.8
min_value <- min(aapl$`Adj Close`)
min_date <- aapl$Date[which.min(aapl$`Adj Close`)]
percentage <- (which.min(aapl$`Adj Close`) / nrow(aapl)) * 100

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

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

Berdasarkan grafik deret waktu yang disajikan, terlihat bahwa sekitar \(64.47\%\) dari data menunjukkan kecenderungan musiman yang menurun secara multipel. Kemudian, pada tanggal 2023-01-05, terjadi perubahan pola menjadi tren naik.

Pembagian Data Training Dan Test.

#membagi 80% data latih (training) dan 20% data uji (testing)
train_aapl <- aapl[1: round(nrow(aapl) *80/100),]
test_aapl <- aapl[round(nrow(aapl) *80/100 +1): nrow(aapl),]
train_aapl.ts <- ts(train_aapl[,3])
test_aapl.ts <- ts(train_aapl[,3])

data2 <- data %>%
  filter(Date >= as.Date("2022-01-01")) 
#Banyaknya hari untuk di ramal 
h <- nrow(test_aapl); h
## [1] 115
chart <-
ggplot() + 
  geom_line(data = train_aapl, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Latih")) +
  geom_line(data = test_aapl, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Uji")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham Apple",
       subtitle = "Pembagian Data Training dan Test\n") +
  theme(legend.position = "none") +
  scale_colour_manual(name="Keterangan:", 
                      breaks = c("Data Latih", "Data Uji"),
                      values = c("lightskyblue4", "grey30")) + theme.ts1
chart

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

Berdasarkan plot data deret waktu pada data latih (\(80\%\) dari data asli), terlihat bahwa data menunjukkan tren turun musiman multiplikatif. Ini mengisyaratkan bahwa data latih tidak memenuhi kriteria stasioneritas dalam rataan maupun ragam. Di sisi lain, dalam plot data uji (\(20\%\) dari data asli), terlihat adanya tren naik dan kurangnya nilai tengah yang stabil. Ini juga menunjukkan bahwa data uji tidak stasioner dalam rataan.

1.4.3 Time Series Amazon

amzn <- data %>%
  filter(Name == "AMZN", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(amzn) <- NULL
str(amzn)
## 'data.frame':    574 obs. of  3 variables:
##  $ Name     : chr  "AMZN" "AMZN" "AMZN" "AMZN" ...
##  $ Date     : Date, format: "2022-01-01" "2022-01-02" ...
##  $ Adj Close: num  168 169 170 168 164 ...
datatable(amzn, filter = 'top', 
          options = list(pageLength = 5))

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.46  119.73  134.94  170.40
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 = "grey30", linewidth = 1.5) +
  geom_text(aes(x = min_date-1*40, y = max(`Adj Close`)*80/100, label = 
                  paste0("Titik Potong\n","(",round(percentage, 2), "%)",
                         "   ",min_date)), 
            vjust = -1.5, hjust = 0, size = 7, color = "grey30") 
chart

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

Dari grafik deret waktu yang ditampilkan, terlihat bahwa sekitar \(63.2\%\) dari data menunjukkan kecenderungan musiman yang menurun secara aditif. Selanjutnya, pada tanggal 2022-12-28, terjadi perubahan pola menjadi tren naik.

Pembagian Data Training Dan Test.

#membagi 80% data latih (training) dan 20% data uji (testing)
train_amzn <- amzn[1: round(nrow(amzn) *80/100),]
test_amzn <- amzn[round(nrow(amzn) *80/100 +1): nrow(amzn),]
train_amzn.ts <- ts(train_amzn[,3])
test_amzn.ts <- ts(test_amzn[,3])
chart <-
ggplot() + 
  geom_line(data = train_amzn, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Latih")) +
  geom_line(data = test_amzn, 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", "grey30")) + theme.ts1
chart

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

Dari plot deret waktu data latih (\(80\%\) dari data asli), terlihat bahwa data menunjukkan tren turun musiman secara aditif. Ini menunjukkan ketidakstabilan dalam nilai tengah dan variabilitas data latih, yang tidak memenuhi kriteria stasioneritas dalam rataan maupun ragam. Di sisi lain, dalam plot data uji (\(20\%\) dari data asli), terlihat adanya tren naik dan absennya nilai tengah yang stabil. Hal ini juga mengindikasikan bahwa data uji tidak memenuhi kriteria stasioneritas dalam rataan.

1.4.4 Time Series Google

goog <- data %>%
  filter(Name == "GOOG", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(goog) <- NULL
str(goog)
## 'data.frame':    574 obs. of  3 variables:
##  $ Name     : chr  "GOOG" "GOOG" "GOOG" "GOOG" ...
##  $ Date     : Date, format: "2022-01-01" "2022-01-02" ...
##  $ Adj Close: num  145 145 145 144 138 ...
datatable(goog, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

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

Ringkasan Data Ajd CLose.

summary(goog.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   83.49   99.88  111.83  112.68  123.87  148.04
min_value <- min(goog$`Adj Close`)
min_date <- goog$Date[which.min(goog$`Adj Close`)]
percentage <- (which.min(goog$`Adj Close`) / nrow(goog)) * 100

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

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

Melalui visualisasi grafik deret waktu yang disuguhkan, tampaknya sekitar \(53.81\%\) data menggambarkan tren menurun. Lalu, pada tanggal 2021-11-03, terjadi perubahan pola menjadi tren naik.

Pembagian Data Training Dan Test.

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

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

Melalui plot deret waktu dari data latih (\(80\%\) dari data asli), terlihat bahwa data menggambarkan tren menurun yang cukup jelas. Hal ini menunjukkan bahwa data latih tidak menunjukkan sifat stasioneritas dalam rataan. Sementara itu, dalam plot data uji (\(20\%\) dari data asli), tampaknya terdapat tren naik yang signifikan, dan tidak ada nilai tengah yang tetap. Ini juga mengindikasikan bahwa data uji tidak memenuhi kriteria stasioneritas dalam rataan.

1.4.5 Time Series META

meta <- data %>%
  filter(Name == "META", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(meta) <- NULL
str(meta)
## 'data.frame':    574 obs. of  3 variables:
##  $ Name     : chr  "META" "META" "META" "META" ...
##  $ Date     : Date, format: "2022-01-01" "2022-01-02" ...
##  $ Adj Close: num  337 338 339 337 324 ...
datatable(meta, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

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

Ringkasan Data Ajd CLose.

summary(meta.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   88.91  157.08  187.38  194.99  222.99  338.54
min_value <- min(meta$`Adj Close`)
min_date <- meta$Date[which.min(meta$`Adj Close`)]
percentage <- (which.min(meta$`Adj Close`) / nrow(meta)) * 100

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

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

Melalui grafik deret waktu yang disajikan, terlihat bahwa sekitar \(53.81\%\) dari data menunjukkan kecenderungan penurunan tren. Lalu, pada tanggal 2022-11-03, terjadi perubahan pola menjadi tren naik. Pola perubahan ini, beserta tanggal dan persentasenya, serupa dengan yang terlihat dalam pergerakan saham Google.

Pembagian Data Training Dan Test2

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

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

Berdasarkan grafik deret waktu data latih (\(80\%\) dari data asli), tampak bahwa data menunjukkan kombinasi tren turun dan tren naik. Hal ini menunjukkan bahwa data latih tidak memenuhi syarat stasioneritas dalam rataan maupun ragam. Sementara itu, pada plot data uji (\(20\%\) dari data asli), terlihat tren naik yang signifikan dan ketiadaan nilai tengah yang konsisten. Ini juga menandakan bahwa data uji tidak memenuhi syarat stasioneritas dalam rataan.

1.4.6 Time Series Microsoft

msft <- data %>%
  filter(Name == "MSFT", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(msft) <- NULL
str(msft)
## 'data.frame':    574 obs. of  3 variables:
##  $ Name     : chr  "MSFT" "MSFT" "MSFT" "MSFT" ...
##  $ Date     : Date, format: "2022-01-01" "2022-01-02" ...
##  $ Adj Close: num  331 331 330 324 312 ...
datatable(msft, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

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

Ringkasan Data Ajd CLose.

summary(msft.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   212.6   249.1   271.7   275.4   296.6   359.5
min_value <- min(msft$`Adj Close`)
min_date <- msft$Date[which.min(msft$`Adj Close`)]
percentage <- (which.min(msft$`Adj Close`) / nrow(msft)) * 100

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

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

Dalam gambaran grafik deret waktu yang diberikan, sekitar $53.81%$ data menunjukkan adanya tren penurunan yang tampak. Lalu, pada tanggal 2022-11-03, terjadi perubahan pola menjadi tren kenaikan. Karakteristik tanggal dan persentase perubahan pola ini serupa dengan yang dapat ditemukan pada pergerakan saham Google dan META.

Pembagian Data Training Dan Test.

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

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

Dari visualisasi grafik deret waktu pada data latih (\(80\%\) dari data asli), terlihat bahwa data menunjukkan adanya tren turun dan tren naik. Hal ini menunjukkan bahwa data latih tidak memenuhi kriteria stasioneritas dalam rataan maupun ragam. Sementara itu, dalam plot data uji (\(20\%\) dari data asli), tampaknya terdapat tren kenaikan yang signifikan dan ketiadaan nilai tengah yang stabil. Hal ini juga menandakan bahwa data uji tidak memenuhi persyaratan stasioneritas dalam rataan.

1.4.7 Time Series Netflix

nflx <- data %>%
  filter(Name == "NFLX", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(nflx) <- NULL
str(nflx)
## 'data.frame':    574 obs. of  3 variables:
##  $ Name     : chr  "NFLX" "NFLX" "NFLX" "NFLX" ...
##  $ Date     : Date, format: "2022-01-01" "2022-01-02" ...
##  $ Adj Close: num  601 599 597 591 568 ...
datatable(nflx, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

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

Ringkasan Data Ajd CLose.

summary(nflx.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   166.4   232.8   318.8   313.2   368.3   600.8
min_value <- min(nflx$`Adj Close`)
min_date <- nflx$Date[which.min(nflx$`Adj Close`)]
percentage <- (which.min(nflx$`Adj Close`) / nrow(nflx)) * 100

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

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

Berbeda dari yang lain, berdasarkan grafik deret waktu yang disajikan, terlihat bahwa sekitar \(22.84\%\) dari data menunjukkan kecenderungan tren menurun. Kemudian, pada tanggal 2022-05-11, terjadi perubahan pola menjadi tren naik.

Pembagian Data Training Dan Test.

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

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

Berdasarkan plot data deret waktu pada data latih (\(80\%\) dari data asli), terlihat bahwa data menunjukkan tren turun yang drastis dan tren naik yang cukup mulus. Ini mengisyaratkan bahwa data latih tidak memenuhi kriteria stasioneritas dalam rataan maupun ragam. Di sisi lain, dalam plot data uji (\(20\%\) dari data asli), terlihat adanya tren naik dan kurangnya nilai tengah yang stabil. Ini juga menunjukkan bahwa data uji tidak stasioner dalam rataan.

1.4.8 Time Series NVIDIA

nvda <- data %>%
  filter(Name == "NVDA", Date >= as.Date("2022-01-01"))  # Filter data saham Amazon tahun 2022 ke atas

rownames(nvda) <- NULL
str(nvda)
## 'data.frame':    574 obs. of  3 variables:
##  $ Name     : chr  "NVDA" "NVDA" "NVDA" "NVDA" ...
##  $ Date     : Date, format: "2022-01-01" "2022-01-02" ...
##  $ Adj Close: num  296 298 301 293 276 ...
datatable(nvda, filter = 'top', 
          options = list(pageLength = 5))

Mengubah Ajd Close Menjadi Time series.

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

Ringkasan Data Ajd CLose.

summary(nvda.ts)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   112.2   162.5   207.0   225.8   267.7   474.9
min_value <- min(nvda$`Adj Close`)
min_date <- nvda$Date[which.min(nvda$`Adj Close`)]
percentage <- (which.min(nvda$`Adj Close`) / nrow(nvda)) * 100

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

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

Berdasarkan grafik deret waktu yang disajikan, terlihat bahwa sekitar \(50.25\%\) dari data menunjukkan kecenderungan tren menurun. Kemudian, pada tanggal 2022-10-14, terjadi perubahan pola menjadi tren naik dan menaik tajam pada Juli 2023.

Pembagian Data Training Dan Test.

#membagi 80% data latih (training) dan 20% data uji (testing)
train_nvda <- nvda[1:488,]
test_nvda <- nvda[489: nrow(nvda),]
train_nvda.ts <- ts(train_nvda[,3])
test_nvda.ts <- ts(test_nvda[,3])
chart <-
ggplot() + 
  geom_line(data = train_nvda, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Latih")) +
  geom_line(data = test_nvda, linewidth=2,
            aes(x = Date, y = `Adj Close`, col = "Data Uji")) +
  labs(x = "\nPeriode (Tahun)", y='Saham Harga penutup',
       title = "Time Series Saham NVIDIA",
       subtitle = "Pembagian Data Training dan Test\n") +
  theme(legend.position = "none") +
  scale_colour_manual(name="Keterangan:", 
                      breaks = c("Data Latih", "Data Uji"),
                      values = c("green4", "grey30")) + theme.ts1
chart

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

Berdasarkan plot data deret waktu pada data latih (\(80\%\) dari data asli), terlihat bahwa data menunjukkan tren turun dan tren naik yang keduanya mulus. Ini mengisyaratkan bahwa data latih tidak memenuhi kriteria stasioneritas dalam rataan maupun ragam. Di sisi lain, dalam plot data uji (\(20\%\) dari data asli), terlihat adanya tren yang melonjak naik dan kurangnya nilai tengah yang stabil. Ini juga menunjukkan bahwa data uji tidak stasioner dalam rataan.

2 Apple

2.1 Uji Stasioner Data

install_load('tsibble','tseries')

2.1.1 Plot ACF

acf(train_aapl.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.1.2 Uji ADF

tseries::adf.test(train_aapl.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_aapl.ts
## Dickey-Fuller = -2.1521, Lag order = 7, p-value = 0.5136
## 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.5136\) 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.1.3 Plot Box-Cox

install_load('MASS')
index <- seq(1:nrow(train_aapl))
bc = boxcox(train_aapl.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda_aapl <- bc$x[which.max(bc$y)]
#SK
sk_aapl <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda_aapl,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk_aapl), "\n Batas Atas  :", max(sk_aapl) )
##  Lambda : 1.68 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : 0.64 
##  Batas Atas  : 2.72

Gambar di atas menunjukkan nilai rounded value (\(\lambda\)) optimum sebesar \(1.68\) dan pada selang kepercayaan \(95\%\) nilai memiliki batas bawah \(0.64\) dan batas atas \(2.72\). Selang tersebut memuat nilai satu sehingga dapat dikatakan bahwa data saham Apple stasioner dalam ragam. Sehingga data tidak perlu di transformasi.

2.2 Penanganan Ketidakstasioneran Data

2.2.1 Dalam Rataan: Differencing

train_aapl.diff <- diff(train_aapl.ts, differences = 1) 
plot.ts(train_aapl.diff, lty=1, xlab="Periode (Tahun)", 
        col = "lightskyblue4", lwd = 3.5,
        main="Plot Difference Saham Apple")

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).

2.3 Uji Ulang

2.3.1 Plot ACF

acf(train_aapl.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cuts off pada lag 13, dan lag 14. Hal ini menandakan data sudah stasioner dalam rataan dan ketidakstasioneran data telah berhasil tertangani.

2.3.2 Uji ADF

tseries::adf.test(train_aapl.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_aapl.diff
## Dickey-Fuller = -7.2113, Lag order = 7, 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.

2.4 Identifikasi Model

2.4.1 Plot ACF

acf(train_aapl.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cuts off pada lag 13, dan lag 14. Sehingga model tidak dapat di identifikasi dengan plot ACF.

2.4.2 Plot PACF

pacf(train_aapl.diff)

Berdasarkan plot PACF tersebut, terlihat bahwa cuts off pada lag 13 dan 14. Maka model tidak dapat di identifikasi dengan plot PACF.

2.4.3 Plot EACF

install_load('TSA')
eacf(train_aapl.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  x 
## 1 x o o o o o o o o o o  o  o  x 
## 2 x x o o o o o o o o o  o  o  x 
## 3 x x o o o o o o o o o  o  o  x 
## 4 x x x x o o o o o o o  o  o  x 
## 5 x x x x x o o o o o o  o  o  x 
## 6 x x x x x x o o o o o  o  o  x 
## 7 o x x x x o x o o o o  o  o  x

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

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.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

2.5 Pendugaan Parameter Model Tentatif

Untuk menduga parameter model tentatif, kami akan menggunakan function berdasarkan plot EACF yang sudah dirancang sebagai berikut.

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
model_tentatif <- 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) {
      #Pola Matriks segitiga bawah
      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))
          
          #Identifikasi Best Model
            if (keterangan == "Semua parameter signifikan" && 
                !any(is.na(significant_params))) {
              if (aic < best_aic) {
                best_model <- model
                best_aic <- aic
            }
          }
        }
      }
    }
  }
  
  cat("\nModel ARIMA dengan AIC terkecil:\n")
  print(best_model)

  return(models)
}

# Panggil Fungsi
model.tentaif_aapl <- 
  model_tentatif(train_aapl.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  x 
## 1 x o o o o o o o o o o  o  o  x 
## 2 x x o o o o o o o o o  o  o  x 
## 3 x x o o o o o o o o o  o  o  x 
## 4 x x x x o o o o o o o  o  o  x 
## 5 x x x x x o o o o o o  o  o  x 
## 6 x x x x x x o o o o o  o  o  x 
## 7 o x x x x o x o o o o  o  o  x 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(2,1,3) 
## 
## Coefficients:
##           ar1      ar2      ma1     ma2      ma3
##       -0.8685  -0.9914  -0.1071  0.1121  -0.9969
## s.e.   0.0060   0.0058   0.0133  0.0130   0.0158
## 
## sigma^2 = 6.105:  log likelihood = -1063.77
## AIC=2139.54   AICc=2139.73   BIC=2164.29
datatable(model.tentaif_aapl, filter = 'top', 
          options = list(pageLength = 5))

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

model_aapl.da <- Arima(train_aapl.diff, order=c(2,1,3), method="ML")

2.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.

2.6.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_aapl.da <- model_aapl.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_aapl.da) 
qqline(sisaan_aapl.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_aapl.da)), sisaan_aapl.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_aapl.da) 
pacf(sisaan_aapl.da) 

Berdasarkan plot kuantil-kuantil normal, secara eksplorasi ditunjukkan sisaan tidak menyebar normal ditandai dengan tititk-titiknya 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(2,1,3) juga tidak signifikan pada 20 lag awal yang menandakan saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

2.6.2 Uji Formal

2.6.2.1 Sisaan Menyebar Normal

ks.test(sisaan_aapl.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_aapl.da
## D = 0.1621, p-value = 7.04e-11
## 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 \(7.04\times10^{-11}\) yang kurang dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa sisaan tidak menyebar normal. Sesuai dengan qqplot sisaan.

2.6.2.2 Sisaan saling bebas

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

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.8337\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa sisaan saling bebas. Yang berarti tidak ada autokorelasi. Hal ini sesuai dengan hasil eksplorasi menggunakan plot ACF dan PACF.

2.6.2.3 Sisaan homogen

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

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.1129\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa ragam sisaan homogen.

2.6.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_aapl.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_aapl.da
## t = 1.054, df = 457, p-value = 0.2925
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.1044963  0.3462309
## sample estimates:
## mean of x 
## 0.1208673

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.2925\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

2.7 Peramalan

2.7.1 Ramal

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

#---FORECAST---#
ramalan_aapl.da <- forecast::forecast(model_aapl.da, h = h) 
ramalan_aapl.da
##     Point Forecast     Lo 80    Hi 80     Lo 95    Hi 95
## 460    0.218100163 -2.954518 3.390718 -4.634000 5.070200
## 461   -0.234784742 -3.408270 2.938700 -5.088211 4.618641
## 462    0.007039736 -3.166580 3.180659 -4.846593 4.860672
## 463    0.246002021 -2.927624 3.419628 -4.607640 5.099644
## 464   -0.201272311 -3.375778 2.973233 -5.056260 4.653715
## 465   -0.049726531 -3.224275 3.124822 -4.904780 4.805327
## 466    0.262078752 -2.912565 3.436723 -4.593121 5.117278
## 467   -0.158957571 -3.334422 3.016507 -5.015412 4.697497
## 468   -0.102414205 -3.277877 3.073049 -4.958866 4.754037
## 469    0.265886858 -2.909776 3.441549 -4.590870 5.122644
## 470   -0.110031222 -3.286395 3.066332 -4.967860 4.747797
## 471   -0.148681035 -3.325054 3.027692 -5.006525 4.709163
## 472    0.257563960 -2.919104 3.434231 -4.600730 5.115858
## 473   -0.056934852 -3.234143 3.120273 -4.916055 4.802186
## 474   -0.186542984 -3.363830 2.990744 -5.045783 4.672698
## 475    0.237807510 -2.939838 3.415453 -4.621982 5.097597
## 476   -0.002241121 -3.180252 3.175770 -4.862590 4.858108
## 477   -0.214457192 -3.392661 2.963747 -5.075101 4.646186
## 478    0.207828053 -2.970758 3.386414 -4.653399 5.069055
## 479    0.051469072 -3.127318 3.230256 -4.810067 4.913005
## 480   -0.231382312 -3.410503 2.947739 -5.093428 4.630664
## 481    0.169279857 -3.010200 3.348760 -4.693315 5.031875
## 482    0.101726657 -3.077825 3.281278 -4.760977 4.964431
## 483   -0.236814019 -3.416843 2.943215 -5.100249 4.626621
## 484    0.124172720 -3.056154 3.304499 -4.739717 4.988062
## 485    0.146286188 -3.034029 3.326602 -4.717587 5.010159
## 486   -0.230794664 -3.411711 2.950122 -5.095587 4.633998
## 487    0.074769515 -3.106359 3.255898 -4.790347 4.939886
## 488    0.183224389 -2.997865 3.364314 -4.681832 5.048280
## 489   -0.213897295 -3.395670 2.967875 -5.079998 4.652204
## 490    0.023474626 -3.158419 3.205369 -4.842812 4.889762
## 491    0.211021213 -2.970854 3.392896 -4.655237 5.077279
## 492   -0.187185443 -3.369772 2.995401 -5.054531 4.680160
## 493   -0.027281347 -3.209914 3.155352 -4.894699 4.840136
## 494    0.228620097 -2.954051 3.411291 -4.638855 5.096095
## 495   -0.152151160 -3.335504 3.031202 -5.020670 4.716367
## 496   -0.075155128 -3.258512 3.108202 -4.943679 4.793369
## 497    0.235465148 -2.948006 3.418936 -4.633233 5.104164
## 498   -0.110634743 -3.294706 3.073437 -4.980252 4.758983
## 499   -0.117997354 -3.302072 3.066077 -4.987619 4.751624
## 500    0.231514124 -2.952750 3.415778 -4.638398 5.101426
## 501   -0.064730347 -3.249476 3.120016 -4.935379 4.805918
## 502   -0.153947418 -3.338741 3.030846 -5.024668 4.716773
## 503    0.217227234 -2.967814 3.402268 -4.653872 5.088327
## 504   -0.016682227 -3.202067 3.168702 -4.888308 4.854943
## 505   -0.181512470 -3.367027 3.004002 -5.053337 4.690312
## 506    0.193532882 -2.992258 3.379324 -4.678714 5.065780
## 507    0.031223334 -3.154775 3.217222 -4.841341 4.903788
## 508   -0.199627324 -3.385864 2.986610 -5.072557 4.673302
## 509    0.161772554 -3.024735 3.348280 -4.711570 5.035115
## 510    0.076765274 -3.109834 3.263365 -4.796718 4.950249
## 511   -0.207692959 -3.394647 2.979262 -5.081719 4.666333
## 512    0.123627935 -3.063559 3.310815 -4.750754 4.998010
## 513    0.117889228 -3.069309 3.305088 -4.756510 4.992288
## 514   -0.205592390 -3.393251 2.982066 -5.080695 4.669510
## 515    0.081034087 -3.106798 3.268866 -4.794334 4.956402
## 516    0.152798655 -3.035004 3.340601 -4.722525 5.028122
## 517   -0.193683745 -3.382023 2.994656 -5.069828 4.682461
## 518    0.036083093 -3.152363 3.224529 -4.840224 4.912390
## 519    0.180031666 -3.008385 3.368449 -4.696231 5.056295
## 520   -0.172771457 -3.361762 3.016219 -5.049911 4.704368
## 521   -0.009077122 -3.198114 3.179959 -4.886287 4.868133
## 522    0.198520332 -2.990520 3.387561 -4.678696 5.075737
## 523   -0.144057464 -3.333662 3.045547 -5.022137 4.734022
## 524   -0.052343973 -3.241956 3.137268 -4.930435 4.825747
## 525    0.207630178 -2.982039 3.397300 -4.670549 5.085809
## 526   -0.109075204 -3.299257 3.081106 -4.988037 4.769886
## 527   -0.091756694 -3.281938 3.098425 -4.970718 4.787205
## 528    0.207178544 -2.983118 3.397475 -4.671960 5.086317
## 529   -0.069609907 -3.260332 3.121112 -4.949398 4.810178
## 530   -0.125583763 -3.316334 3.065166 -5.005414 4.754247
## 531    0.197431483 -2.993483 3.388346 -4.682651 5.077514
## 532   -0.027609235 -3.218842 3.163623 -4.908178 4.852959
## 533   -0.152397433 -3.343717 3.038922 -5.033100 4.728305
## 534    0.179079902 -3.012434 3.370594 -4.701919 5.060079
## 535    0.014911330 -3.176809 3.206632 -4.866404 4.896227
## 536   -0.171132256 -3.363023 3.020758 -5.052708 4.710443
## 537    0.153196593 -3.038893 3.345286 -4.728683 5.035076
## 538    0.055963826 -3.136232 3.248160 -4.826078 4.938006
## 539   -0.181125269 -3.373584 3.011334 -5.063570 4.701320
## 540    0.121176617 -3.071461 3.313814 -4.761541 5.003894
## 541    0.093679419 -3.098988 3.286347 -4.789084 4.976443
## 542   -0.182136469 -3.375155 3.010882 -5.065437 4.701164
## 543    0.084664263 -3.108493 3.277821 -4.798848 4.968177
## 544    0.126392142 -3.066749 3.319534 -4.757097 5.009881
## 545   -0.174349116 -3.367912 3.019213 -5.058482 4.709783
## 546    0.045470301 -3.148182 3.239122 -4.838799 4.929739
## 547    0.152711063 -3.040912 3.346334 -4.731514 5.036936
## 548   -0.158350376 -3.352434 3.035734 -5.043280 4.726580
## 549    0.005483615 -3.188643 3.199610 -4.879512 4.890479
## 550    0.171577826 -3.022535 3.365691 -4.713397 5.056552
## 551   -0.135093697 -3.329672 3.059484 -5.020779 4.750592
## 552   -0.033418508 -3.228007 3.161170 -4.919119 4.852282
## 553    0.182307279 -3.012302 3.376916 -4.703426 5.068040
## 554   -0.105845145 -3.300888 3.089197 -4.992241 4.780551
## 555   -0.069457269 -3.264499 3.125585 -4.955852 4.816938
## 556    0.184609723 -3.010496 3.379716 -4.701883 5.071103
## 557   -0.072116592 -3.267594 3.123361 -4.959178 4.814945
## 558   -0.101032434 -3.296526 3.094461 -4.988119 4.786054
## 559    0.178594235 -3.017004 3.374192 -4.708651 5.065839
## 560   -0.035589212 -3.231477 3.160299 -4.923278 4.852099
## 561   -0.126792077 -3.322738 3.069154 -5.014570 4.760986
## 562    0.164753375 -3.031325 3.360832 -4.723226 5.052733
## 563    0.001968940 -3.194309 3.198247 -4.886317 4.890255
## 564   -0.145688990 -3.342089 3.050711 -5.034160 4.742782
## 565    0.143930485 -3.052611 3.340472 -4.744758 5.032619
## 566    0.038787257 -3.157869 3.235444 -4.850077 4.927652
## 567   -0.157021515 -3.353873 3.039830 -5.046184 4.732141
## 568    0.117271536 -3.079713 3.314256 -4.772094 5.006637
## 569    0.073174874 -3.123855 3.270205 -4.816260 4.962610
## 570   -0.160457261 -3.357755 3.036841 -5.050303 4.729388
## 571    0.086164148 -3.111241 3.283570 -4.803846 4.976174
## 572    0.103597147 -3.093807 3.301001 -4.786411 4.993605
## 573   -0.156039083 -3.353773 3.041695 -5.046551 4.734473
## 574    0.052166956 -3.145640 3.249974 -4.838456 4.942790

2.7.2 Plot

data.ramalan_aapl.da <- ramalan_aapl.da$mean
plot(ramalan_aapl.da, col = "lightskyblue4", xlab="Periode (Hari)", lwd = 2)

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

pt_1 <- train_aapl.ts[length(train_aapl.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_aapl.da
ramal_aapl <- diffinv(hasil.forc.Diff, differences = 1) + pt_1
#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_aapl.ts, ramal_aapl,  xlab="Periode (Hari)", 
        col = "lightskyblue4", lwd = 3,
        ylab="Saham Harga (USD)",
        main="Plot Ramalan Saham Apple Selama 115 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham Apple diramalkan akan cenderung sedikit menaik setiap periodenya.

2.7.3 Perbandingan

perbandingan_aapl.da <- matrix(data=c(head(test_aapl.ts, n=h), ramal_aapl[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_aapl.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_aapl.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.aapl <- accuracy(ts(ramal_aapl[-1]), head(test_aapl.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_aapl.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.aapl) <- "AAPL"

datatable(akurasi.aapl)

Didapatkan nilai MAPE sebesar \(3.229058\%\) (kurang dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(2,1,3) sudah sangat baik.

3 Amazon

3.1 Uji Stasioner Data

3.1.1 Plot ACF

acf(train_amzn.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.

3.1.2 Uji ADF

tseries::adf.test(train_amzn.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_amzn.ts
## Dickey-Fuller = -2.5799, Lag order = 7, p-value = 0.3326
## 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.3326\) 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.

3.1.3 Plot Box-Cox

index <- seq(1:nrow(train_amzn))
bc = boxcox(train_amzn.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda_amzn <- bc$x[which.max(bc$y)]
#SK
sk_amzn <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda_amzn,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk_amzn), "\n Batas Bawah :", max(sk_amzn) )
##  Lambda : -0.22 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : -0.61 
##  Batas Bawah : 0.16

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

3.2 Penanganan Ketidakstasioneran Data

3.2.1 Dalam Ragam: Transformasi Data

Referensi : https://r-coder.com/box-cox-transformation-r/

Mengutip dari laman tersebut,

\(\mathbf{\lambda}\) Transformation
-2 \(1/x^2\)
-1 \(1/x\)
-0.5 \(1/\sqrt{x}\)
0 \(\log{(x)}\)
0.5 \(\sqrt{x}\)
1 \(x\)
2 \(x^2\)

Nilai rounded value (\(\lambda\)) optimum sebesar \(-0.22\). Nilai ini mendekati nilai \(0\), Sehingga akan menggunakan transformasi \(\log{(x)}\).

train_amzn.ts.new <- log(train_amzn.ts)
bc <- boxcox(train_amzn.ts.new ~ index, lambda = seq(-5, 6, by=0.01))

Setelah di transformasi, Gambar di atas menunjukkan selang memuat nilai satu sehingga dapat dikatakan bahwa data saham Amazon sudah stasioner dalam ragam.

3.2.2 Dalam Rataan: Differencing

train_amzn.diff <- diff(train_amzn.ts.new, differences = 1) 
plot.ts(train_amzn.diff, lty=1, xlab="Periode (Hari)", 
        col = "orange2", lwd = 3.5,
        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.3 Uji Ulang

3.3.1 Plot ACF

acf(train_amzn.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF tidak ada satupun lag yang cuts off. Sejalan dengan penanganannya, data sudah stasioner dalam rataan dan ketidakstasioneran data telah berhasil tertangani.

3.3.2 Uji ADF

tseries::adf.test(train_amzn.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_amzn.diff
## Dickey-Fuller = -7.1696, Lag order = 7, 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.

3.4 Identifikasi Model

3.4.1 Plot ACF

acf(train_amzn.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF tidak ada satupun lag yang cuts off. Sehingga model tidak dapat di identifikasi dengan plot ACF.

3.4.2 Plot PACF

pacf(train_amzn.diff)

Berdasarkan plot tersebut, terlihat bahwa plot PACF cenderung cuts off pada lag ke 20. Sehingga model tidak dapat di identifikasi dengan plot PACF.

3.4.3 Plot EACF

eacf(train_amzn.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  o  o 
## 1 o o o o o o o o o o o  o  o  o 
## 2 x 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 o x o x o o o o o o o  o  o  o 
## 5 o x x x o o o o o o o  o  o  o 
## 6 x x x x x x o o o o o  o  o  o 
## 7 x x x x x 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.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

3.5 Pendugaan Parameter Model Tentatif

model.tentaif_amzn <- 
  model_tentatif(train_amzn.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  o  o 
## 1 o o o o o o o o o o o  o  o  o 
## 2 x 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 o x o x o o o o o o o  o  o  o 
## 5 o x x x o o o o o o o  o  o  o 
## 6 x x x x x x o o o o o  o  o  o 
## 7 x x x x x x o o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(0,1,1) 
## 
## Coefficients:
##           ma1
##       -1.0000
## s.e.   0.0084
## 
## sigma^2 = 0.0005777:  log likelihood = 1052.78
## AIC=-2101.57   AICc=-2101.54   BIC=-2093.32
datatable(model.tentaif_amzn, filter = 'top', 
          options = list(pageLength = 5))

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

model_amzn.da <- Arima(train_amzn.diff, order=c(0,1,1), method="ML")

3.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.

3.6.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_amzn.da <- model_amzn.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_amzn.da) 
qqline(sisaan_amzn.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_amzn.da)), sisaan_amzn.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_amzn.da) 
pacf(sisaan_amzn.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(0,1,1) juga signifikan pada 20 lag awal yang menandakan tidak saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

3.6.2 Uji Formal

3.6.2.1 Sisaan Menyebar Normal

ks.test(sisaan_amzn.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_amzn.da
## D = 0.46778, 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.2\times10^{-16}\) yang kurang dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa sisaan tidak menyebar normal.

3.6.2.2 Sisaan saling bebas/tidak ada autokorelasi

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

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.9723\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa sisaan saling bebas.

3.6.2.3 Sisaan homogen

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

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.002668\) yang lebih kecil dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa ragam sisaan tidak homogen.

3.6.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_amzn.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_amzn.da
## t = 0.63928, df = 457, p-value = 0.523
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.001486809  0.002920538
## sample estimates:
##    mean of x 
## 0.0007168645

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.523\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

3.7 Peramalan

3.7.1 Ramal

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

#---FORECAST---#
ramalan_amzn.da <- forecast::forecast(model_amzn.da, h = h) 
ramalan_amzn.da
##     Point Forecast       Lo 80      Hi 80      Lo 95     Hi 95
## 460   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 461   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 462   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 463   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 464   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 465   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 466   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 467   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 468   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 469   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 470   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 471   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 472   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 473   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 474   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 475   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 476   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 477   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 478   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 479   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 480   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 481   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 482   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 483   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 484   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 485   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 486   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 487   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 488   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 489   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 490   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 491   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 492   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 493   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 494   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 495   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 496   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 497   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 498   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 499   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 500   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 501   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 502   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 503   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 504   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 505   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 506   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 507   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 508   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 509   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 510   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 511   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 512   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 513   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 514   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 515   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 516   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 517   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 518   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 519   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 520   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 521   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 522   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 523   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 524   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 525   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 526   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 527   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 528   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 529   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 530   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 531   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 532   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 533   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 534   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 535   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 536   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 537   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 538   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 539   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 540   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 541   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 542   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 543   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 544   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 545   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 546   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 547   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 548   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 549   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 550   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 551   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 552   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 553   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 554   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 555   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 556   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 557   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 558   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 559   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 560   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 561   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 562   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 563   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 564   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 565   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 566   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 567   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 568   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 569   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 570   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 571   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 572   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 573   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123
## 574   -0.001047453 -0.03188356 0.02978865 -0.0482072 0.0461123

3.7.2 Plot

data.ramalan_amzn.da <- ramalan_amzn.da$mean
plot(ramalan_amzn.da, col = "orange2", xlab="Periode (Hari)", lwd = 2.5)

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

pt_1 <- train_amzn.ts[length(train_amzn.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_amzn.da
#Transformasi Balik
ramal_amzn <- exp(hasil.forc.Diff)
#Diff inv
ramal_amzn <- diffinv(ramal_amzn, differences = 1) + pt_1

#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_amzn.ts, ramal_amzn, xlab="Periode (Hari)", 
        col = "orange2", lwd = 3,
        ylab="Saham Harga (USD)",
        main="Plot Ramalan Saham Amazon Selama 115 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham amazon diramalkan akan terus menaik tajam setiap periodenya.

3.7.3 Perbandingan

perbandingan_amzn.da <- matrix(data=c(head(test_amzn.ts, n=h), ramal_amzn[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_amzn.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_amzn.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.amzn <- accuracy(ts(ramal_amzn[-1]), head(test_amzn.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_amzn.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.amzn) <- "AMZN"
datatable(akurasi.amzn)

Didapatkan nilai MAPE sebesar \(35.30528\%\) (lebih dari \(20\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(0,1,1) sudah cukup baik.

4 Google

4.1 Uji Stasioner Data

4.1.1 Plot ACF

acf(train_goog.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.

4.1.2 Uji ADF

tseries::adf.test(train_goog.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_goog.ts
## Dickey-Fuller = -2.4759, Lag order = 7, p-value = 0.3766
## 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.3766\) 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.

4.1.3 Plot Box-Cox

index <- seq(1:nrow(train_goog))
bc = boxcox(train_goog.ts~index, lambda = seq(-2, 4, by=0.01))

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

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

4.2 Penanganan Ketidakstasioneran Data

4.2.1 Dalam Ragam: Transformasi Data

Referensi : https://r-coder.com/box-cox-transformation-r/

Mengutip dari laman tersebut,

\(\mathbf{\lambda}\) Transformation
-2 \(1/x^2\)
-1 \(1/x\)
-0.5 \(1/\sqrt{x}\)
0 \(\log{(x)}\)
0.5 \(\sqrt{x}\)
1 \(x\)
2 \(x^2\)

Nilai rounded value (\(\lambda\)) optimum sebesar \(-0.13\). Nilai ini mendekati nilai \(0\), Sehingga akan menggunakan transformasi \(\log{(x)}\).

train_goog.ts.new <- log(train_goog.ts)
bc <- boxcox(train_goog.ts.new ~ index, lambda = seq(-5, 6, by=0.01))

Setelah di transformasi, Gambar di atas menunjukkan selang memuat nilai satu sehingga dapat dikatakan bahwa data saham Google sudah stasioner dalam ragam.

4.2.2 Dalam Rataan: Differencing

train_goog.diff <- diff(train_goog.ts.new, differences = 1) 
plot.ts(train_goog.diff, lty=1, xlab="Periode (Hari)", 
        col = "gold3", lwd = 3.5,
        main="Plot Difference Saham Google")

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).

4.3 Uji Ulang

4.3.1 Plot ACF

acf(train_goog.diff)

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

4.3.2 Uji ADF

tseries::adf.test(train_goog.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_goog.diff
## Dickey-Fuller = -8.2243, Lag order = 7, 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.4 Identifikasi Model

4.4.1 Plot ACF

acf(train_goog.diff)

Berdasarkan plot ACF tersebut, terlihat bahwa cuts off 13. Maka model tidak dapat di identifikasi dengan plot ACF.

4.4.2 Plot PACF

pacf(train_goog.diff)

Pada plot PACF terlihat tidak ada satupun lag yang cut off. Maka model tidak dapat di identifikasi dengan plot PACF.

4.4.3 Plot EACF

eacf(train_goog.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  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x 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 o o o o o o o o  o  o  o 
## 5 x o x x x o o o o o o  o  o  o 
## 6 x o x x x x o o o o o  o  o  o 
## 7 x x o x x 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.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

4.5 Pendugaan Parameter Model Tentatif

model.tentaif_goog <- 
  model_tentatif(train_goog.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  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x 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 o o o o o o o o  o  o  o 
## 5 x o x x x o o o o o o  o  o  o 
## 6 x o x x x x o o o o o  o  o  o 
## 7 x x o x x x o o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(0,1,1) 
## 
## Coefficients:
##           ma1
##       -1.0000
## s.e.   0.0089
## 
## sigma^2 = 0.0003726:  log likelihood = 1152.98
## AIC=-2301.96   AICc=-2301.93   BIC=-2293.71
datatable(model.tentaif_goog, filter = 'top', 
          options = list(pageLength = 5))

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

model_goog.da <- Arima(train_goog.diff, order=c(0,1,1), method="ML")

4.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.

4.6.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_goog.da <- model_goog.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_goog.da) 
qqline(sisaan_goog.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_goog.da)), sisaan_goog.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_goog.da) 
pacf(sisaan_goog.da) 

Berdasarkan plot kuantil-kuantil normal, secara eksplorasi ditunjukkan sisaan tidak menyebar normal ditandai dengan titik titik yang cenderung 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(0,1,1) juga signifikan pada 20 lag awal yang menandakan tidak saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

4.6.2 Uji Formal

4.6.2.1 Sisaan Menyebar Normal

ks.test(sisaan_goog.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_goog.da
## D = 0.47199, 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.2\times10^{-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.

4.6.2.2 Sisaan saling bebas/tidak ada autokorelasi

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

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.642\) 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.

4.6.2.3 Sisaan homogen

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

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.03988\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa ragam sisaan homogen.

4.6.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_goog.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_goog.da
## t = 0.8022, df = 457, p-value = 0.4229
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.001047096  0.002491652
## sample estimates:
##    mean of x 
## 0.0007222779

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.4229\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

4.7 Peramalan

4.7.1 Ramal

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

#---FORECAST---#
ramalan_goog.da <- forecast::forecast(model_goog.da, h = h) 
ramalan_goog.da
##     Point Forecast      Lo 80      Hi 80       Lo 95      Hi 95
## 460  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 461  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 462  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 463  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 464  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 465  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 466  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 467  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 468  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 469  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 470  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 471  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 472  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 473  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 474  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 475  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 476  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 477  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 478  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 479  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 480  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 481  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 482  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 483  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 484  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 485  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 486  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 487  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 488  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 489  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 490  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 491  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 492  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 493  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 494  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 495  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 496  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 497  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 498  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 499  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 500  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 501  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 502  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 503  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 504  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 505  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 506  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 507  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 508  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 509  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 510  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 511  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 512  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 513  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 514  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 515  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 516  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 517  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 518  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 519  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 520  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 521  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 522  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 523  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 524  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 525  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 526  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 527  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 528  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 529  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 530  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 531  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 532  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 533  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 534  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 535  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 536  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 537  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 538  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 539  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 540  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 541  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 542  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 543  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 544  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 545  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 546  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 547  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 548  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 549  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 550  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 551  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 552  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 553  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 554  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 555  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 556  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 557  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 558  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 559  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 560  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 561  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 562  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 563  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 564  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 565  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 566  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 567  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 568  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 569  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 570  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 571  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 572  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 573  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584
## 574  -0.0006994061 -0.0254647 0.02406588 -0.03857465 0.03717584

4.7.2 Plot

data.ramalan_goog.da <- ramalan_goog.da$mean
plot(ramalan_goog.da, xlab="Periode (Hari)", col = "gold3", lwd = 2.5)

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

pt_1 <- train_goog.ts[length(train_goog.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_goog.da
#Transformasi Balik
ramal_goog <- exp(hasil.forc.Diff)
#Diff inv
ramal_goog <- diffinv(ramal_goog, differences = 1) + pt_1

#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_goog.ts, ramal_goog, xlab="Periode (Hari)", 
        col = "gold3", lwd = 3.5,
        ylab="Saham Harga (USD)",
        main="Plot Ramalan Saham Google Selama 115 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham Google diramalkan akan terus menaik tajam setiap periodenya.

4.7.3 Perbandingan

perbandingan_goog.da <- matrix(data=c(head(test_goog.ts, n=h), ramal_goog[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_goog.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_goog.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.goog <- accuracy(ts(ramal_goog[-1]), head(test_goog.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_goog.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.goog) <- "GOOG"
datatable(akurasi.goog)

Didapatkan nilai MAPE sebesar \(37.53469\%\) (lebih dari \(20\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(0,1,1) sudah cukup baik.

5 META

5.1 Uji Stasioner Data

5.1.1 Plot ACF

acf(train_meta.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.

5.1.2 Uji ADF

tseries::adf.test(train_meta.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_meta.ts
## Dickey-Fuller = -1.6153, Lag order = 7, p-value = 0.7406
## 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.7406\) 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.

5.1.3 Plot Box-Cox

index <- seq(1:nrow(train_meta))
bc = boxcox(train_meta.ts~index, lambda = seq(-2, 4, by=0.01))

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

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

5.2 Penanganan Ketidakstasioneran Data

5.2.1 Dalam Ragam: Transformasi Data

Referensi : https://r-coder.com/box-cox-transformation-r/

Mengutip dari laman tersebut,

\(\mathbf{\lambda}\) Transformation
-2 \(1/x^2\)
-1 \(1/x\)
-0.5 \(1/\sqrt{x}\)
0 \(\log{(x)}\)
0.5 \(\sqrt{x}\)
1 \(x\)
2 \(x^2\)

Nilai rounded value (\(\lambda\)) optimum sebesar \(-0.21\). Nilai ini mendekati nilai \(0\), Sehingga akan menggunakan transformasi \(\log{(x)}\).

train_meta.ts.new <- log(train_meta.ts)
bc <- boxcox(train_meta.ts.new ~ index, lambda = seq(-5, 6, by=0.01))

Setelah di transformasi, Gambar di atas menunjukkan selang memuat nilai satu sehingga dapat dikatakan bahwa data saham META sudah stasioner dalam ragam.

5.2.2 Dalam Rataan: Differencing

train_meta.diff <- diff(train_meta.ts.new, differences = 1) 
plot.ts(train_meta.diff, lty=1, xlab="Periode (Tahun)", 
        col = "dodgerblue3", lwd = 3.5,
        main="Plot Difference Saham META")

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).

5.3 Uji Ulang

5.3.1 Plot ACF

acf(train_meta.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF tidak ada satupun yang cuts off. Sejalan dengan penanganannya, data sudah stasioner dalam rataan dan ketidakstasioneran data telah berhasil tertangani.

5.3.2 Uji ADF

tseries::adf.test(train_meta.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_meta.diff
## Dickey-Fuller = -8.1905, Lag order = 7, 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.

5.4 Identifikasi Model

5.4.1 Plot ACF

acf(train_meta.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF tidak ada satupun yang cuts off. Maka model tidak dapat di identifikasi dengan plot ACF.

5.4.2 Plot PACF

pacf(train_meta.diff)

Berdasarkan plot tersebut, terlihat bahwa plot PACF tidak ada satupun yang cuts off. Maka model tidak dapat di identifikasi dengan plot PACF.

5.4.3 Plot EACF

eacf(train_meta.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  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x o 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 x x x o o o o o o  o  o  o 
## 6 x x x x x o o o o o o  o  o  o 
## 7 x x x o x 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.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

5.5 Pendugaan Parameter Model Tentatif

model.tentaif_meta <- 
  model_tentatif(train_meta.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  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x o 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 x x x o o o o o o  o  o  o 
## 6 x x x x x o o o o o o  o  o  o 
## 7 x x x o x x o o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(0,1,1) 
## 
## Coefficients:
##           ma1
##       -0.9902
## s.e.   0.0072
## 
## sigma^2 = 0.001085:  log likelihood = 909.92
## AIC=-1815.84   AICc=-1815.81   BIC=-1807.59
datatable(model.tentaif_meta, filter = 'top', 
          options = list(pageLength = 5))

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

model_meta.da <- Arima(train_meta.diff, order=c(0,1,1), method="ML")

5.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.

5.6.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_meta.da <- model_meta.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_meta.da) 
qqline(sisaan_meta.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_meta.da)), sisaan_meta.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_meta.da) 
pacf(sisaan_meta.da) 

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

5.6.2 Uji Formal

5.6.2.1 Sisaan Menyebar Normal

ks.test(sisaan_meta.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_meta.da
## D = 0.46262, 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.2\times 10^{-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.

5.6.2.2 Sisaan saling bebas/tidak ada autokorelasi

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

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.7622\) 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.

5.6.2.3 Sisaan homogen

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

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.966\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa ragam sisaan homogen.

5.6.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_meta.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_meta.da
## t = 1.1857, df = 457, p-value = 0.2364
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.001196463  0.004836206
## sample estimates:
##   mean of x 
## 0.001819871

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.2364\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

5.7 Peramalan

5.7.1 Ramal

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

#---FORECAST---#
ramalan_meta.da <- forecast::forecast(model_meta.da, h = h) 
ramalan_meta.da
##     Point Forecast       Lo 80      Hi 80       Lo 95      Hi 95
## 460    0.002878916 -0.03932878 0.04508661 -0.06167219 0.06743002
## 461    0.002878916 -0.03933081 0.04508864 -0.06167528 0.06743311
## 462    0.002878916 -0.03933283 0.04509066 -0.06167838 0.06743621
## 463    0.002878916 -0.03933485 0.04509268 -0.06168147 0.06743930
## 464    0.002878916 -0.03933687 0.04509471 -0.06168456 0.06744239
## 465    0.002878916 -0.03933890 0.04509673 -0.06168766 0.06744549
## 466    0.002878916 -0.03934092 0.04509875 -0.06169075 0.06744858
## 467    0.002878916 -0.03934294 0.04510077 -0.06169384 0.06745167
## 468    0.002878916 -0.03934496 0.04510280 -0.06169694 0.06745477
## 469    0.002878916 -0.03934699 0.04510482 -0.06170003 0.06745786
## 470    0.002878916 -0.03934901 0.04510684 -0.06170312 0.06746095
## 471    0.002878916 -0.03935103 0.04510886 -0.06170621 0.06746404
## 472    0.002878916 -0.03935305 0.04511088 -0.06170931 0.06746714
## 473    0.002878916 -0.03935507 0.04511291 -0.06171240 0.06747023
## 474    0.002878916 -0.03935710 0.04511493 -0.06171549 0.06747332
## 475    0.002878916 -0.03935912 0.04511695 -0.06171858 0.06747641
## 476    0.002878916 -0.03936114 0.04511897 -0.06172167 0.06747950
## 477    0.002878916 -0.03936316 0.04512099 -0.06172476 0.06748260
## 478    0.002878916 -0.03936518 0.04512301 -0.06172786 0.06748569
## 479    0.002878916 -0.03936720 0.04512503 -0.06173095 0.06748878
## 480    0.002878916 -0.03936922 0.04512706 -0.06173404 0.06749187
## 481    0.002878916 -0.03937125 0.04512908 -0.06173713 0.06749496
## 482    0.002878916 -0.03937327 0.04513110 -0.06174022 0.06749805
## 483    0.002878916 -0.03937529 0.04513312 -0.06174331 0.06750114
## 484    0.002878916 -0.03937731 0.04513514 -0.06174640 0.06750423
## 485    0.002878916 -0.03937933 0.04513716 -0.06174949 0.06750732
## 486    0.002878916 -0.03938135 0.04513918 -0.06175258 0.06751041
## 487    0.002878916 -0.03938337 0.04514120 -0.06175567 0.06751350
## 488    0.002878916 -0.03938539 0.04514322 -0.06175876 0.06751659
## 489    0.002878916 -0.03938741 0.04514524 -0.06176185 0.06751968
## 490    0.002878916 -0.03938943 0.04514726 -0.06176494 0.06752277
## 491    0.002878916 -0.03939145 0.04514928 -0.06176803 0.06752586
## 492    0.002878916 -0.03939347 0.04515130 -0.06177112 0.06752895
## 493    0.002878916 -0.03939549 0.04515332 -0.06177421 0.06753204
## 494    0.002878916 -0.03939751 0.04515534 -0.06177730 0.06753513
## 495    0.002878916 -0.03939953 0.04515736 -0.06178039 0.06753822
## 496    0.002878916 -0.03940155 0.04515938 -0.06178348 0.06754131
## 497    0.002878916 -0.03940357 0.04516140 -0.06178656 0.06754440
## 498    0.002878916 -0.03940559 0.04516342 -0.06178965 0.06754748
## 499    0.002878916 -0.03940761 0.04516544 -0.06179274 0.06755057
## 500    0.002878916 -0.03940963 0.04516746 -0.06179583 0.06755366
## 501    0.002878916 -0.03941165 0.04516948 -0.06179892 0.06755675
## 502    0.002878916 -0.03941366 0.04517150 -0.06180200 0.06755984
## 503    0.002878916 -0.03941568 0.04517351 -0.06180509 0.06756292
## 504    0.002878916 -0.03941770 0.04517553 -0.06180818 0.06756601
## 505    0.002878916 -0.03941972 0.04517755 -0.06181127 0.06756910
## 506    0.002878916 -0.03942174 0.04517957 -0.06181435 0.06757219
## 507    0.002878916 -0.03942376 0.04518159 -0.06181744 0.06757527
## 508    0.002878916 -0.03942578 0.04518361 -0.06182053 0.06757836
## 509    0.002878916 -0.03942780 0.04518563 -0.06182362 0.06758145
## 510    0.002878916 -0.03942981 0.04518764 -0.06182670 0.06758453
## 511    0.002878916 -0.03943183 0.04518966 -0.06182979 0.06758762
## 512    0.002878916 -0.03943385 0.04519168 -0.06183287 0.06759071
## 513    0.002878916 -0.03943587 0.04519370 -0.06183596 0.06759379
## 514    0.002878916 -0.03943789 0.04519572 -0.06183905 0.06759688
## 515    0.002878916 -0.03943990 0.04519773 -0.06184213 0.06759996
## 516    0.002878916 -0.03944192 0.04519975 -0.06184522 0.06760305
## 517    0.002878916 -0.03944394 0.04520177 -0.06184830 0.06760614
## 518    0.002878916 -0.03944596 0.04520379 -0.06185139 0.06760922
## 519    0.002878916 -0.03944797 0.04520580 -0.06185447 0.06761231
## 520    0.002878916 -0.03944999 0.04520782 -0.06185756 0.06761539
## 521    0.002878916 -0.03945201 0.04520984 -0.06186065 0.06761848
## 522    0.002878916 -0.03945402 0.04521186 -0.06186373 0.06762156
## 523    0.002878916 -0.03945604 0.04521387 -0.06186681 0.06762465
## 524    0.002878916 -0.03945806 0.04521589 -0.06186990 0.06762773
## 525    0.002878916 -0.03946008 0.04521791 -0.06187298 0.06763081
## 526    0.002878916 -0.03946209 0.04521992 -0.06187607 0.06763390
## 527    0.002878916 -0.03946411 0.04522194 -0.06187915 0.06763698
## 528    0.002878916 -0.03946613 0.04522396 -0.06188224 0.06764007
## 529    0.002878916 -0.03946814 0.04522597 -0.06188532 0.06764315
## 530    0.002878916 -0.03947016 0.04522799 -0.06188840 0.06764623
## 531    0.002878916 -0.03947217 0.04523001 -0.06189149 0.06764932
## 532    0.002878916 -0.03947419 0.04523202 -0.06189457 0.06765240
## 533    0.002878916 -0.03947621 0.04523404 -0.06189765 0.06765549
## 534    0.002878916 -0.03947822 0.04523605 -0.06190074 0.06765857
## 535    0.002878916 -0.03948024 0.04523807 -0.06190382 0.06766165
## 536    0.002878916 -0.03948225 0.04524009 -0.06190690 0.06766473
## 537    0.002878916 -0.03948427 0.04524210 -0.06190999 0.06766782
## 538    0.002878916 -0.03948629 0.04524412 -0.06191307 0.06767090
## 539    0.002878916 -0.03948830 0.04524613 -0.06191615 0.06767398
## 540    0.002878916 -0.03949032 0.04524815 -0.06191923 0.06767706
## 541    0.002878916 -0.03949233 0.04525016 -0.06192231 0.06768015
## 542    0.002878916 -0.03949435 0.04525218 -0.06192540 0.06768323
## 543    0.002878916 -0.03949636 0.04525419 -0.06192848 0.06768631
## 544    0.002878916 -0.03949838 0.04525621 -0.06193156 0.06768939
## 545    0.002878916 -0.03950039 0.04525822 -0.06193464 0.06769247
## 546    0.002878916 -0.03950241 0.04526024 -0.06193772 0.06769555
## 547    0.002878916 -0.03950442 0.04526225 -0.06194080 0.06769864
## 548    0.002878916 -0.03950644 0.04526427 -0.06194389 0.06770172
## 549    0.002878916 -0.03950845 0.04526628 -0.06194697 0.06770480
## 550    0.002878916 -0.03951046 0.04526830 -0.06195005 0.06770788
## 551    0.002878916 -0.03951248 0.04527031 -0.06195313 0.06771096
## 552    0.002878916 -0.03951449 0.04527232 -0.06195621 0.06771404
## 553    0.002878916 -0.03951651 0.04527434 -0.06195929 0.06771712
## 554    0.002878916 -0.03951852 0.04527635 -0.06196237 0.06772020
## 555    0.002878916 -0.03952054 0.04527837 -0.06196545 0.06772328
## 556    0.002878916 -0.03952255 0.04528038 -0.06196853 0.06772636
## 557    0.002878916 -0.03952456 0.04528239 -0.06197161 0.06772944
## 558    0.002878916 -0.03952658 0.04528441 -0.06197469 0.06773252
## 559    0.002878916 -0.03952859 0.04528642 -0.06197777 0.06773560
## 560    0.002878916 -0.03953060 0.04528843 -0.06198085 0.06773868
## 561    0.002878916 -0.03953262 0.04529045 -0.06198393 0.06774176
## 562    0.002878916 -0.03953463 0.04529246 -0.06198700 0.06774484
## 563    0.002878916 -0.03953664 0.04529447 -0.06199008 0.06774791
## 564    0.002878916 -0.03953866 0.04529649 -0.06199316 0.06775099
## 565    0.002878916 -0.03954067 0.04529850 -0.06199624 0.06775407
## 566    0.002878916 -0.03954268 0.04530051 -0.06199932 0.06775715
## 567    0.002878916 -0.03954469 0.04530253 -0.06200240 0.06776023
## 568    0.002878916 -0.03954671 0.04530454 -0.06200548 0.06776331
## 569    0.002878916 -0.03954872 0.04530655 -0.06200855 0.06776638
## 570    0.002878916 -0.03955073 0.04530856 -0.06201163 0.06776946
## 571    0.002878916 -0.03955275 0.04531058 -0.06201471 0.06777254
## 572    0.002878916 -0.03955476 0.04531259 -0.06201779 0.06777562
## 573    0.002878916 -0.03955677 0.04531460 -0.06202086 0.06777870
## 574    0.002878916 -0.03955878 0.04531661 -0.06202394 0.06778177

5.7.2 Plot

data.ramalan_meta.da <- ramalan_meta.da$mean
plot(ramalan_meta.da, xlab="Periode (Tahun)", col = "dodgerblue3", lwd = 2.5)

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

pt_1 <- train_meta.ts[length(train_meta.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_meta.da
#Transformasi Balik
ramal_meta <- exp(hasil.forc.Diff)
#Diff inv
ramal_meta <- diffinv(ramal_meta, differences = 1) + pt_1

#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_meta.ts, ramal_meta, xlab="Periode (Hari)", 
        col = "dodgerblue3", lwd = 3.5,
        ylab="Saham Harga (USD)",
        main="Plot Ramalan Saham META Selama 115 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham META diramalkan akan terus menaik setiap periodenya.

5.7.3 Perbandingan

perbandingan_meta.da <- matrix(data=c(head(test_meta.ts, n=h), ramal_meta[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_meta.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_meta.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.meta <- accuracy(ts(ramal_meta[-1]), head(test_meta.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_meta.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.meta) <- "META"
datatable(akurasi.meta)

Didapatkan nilai MAPE sebesar \(4.766333\%\) (kurang dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(0,1,1) sudah sangat baik.

6 Microsoft

6.1 Uji Stasioner Data

6.1.1 Plot ACF

acf(train_msft.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.

6.1.2 Uji ADF

tseries::adf.test(train_msft.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_msft.ts
## Dickey-Fuller = -2.0074, Lag order = 7, p-value = 0.5748
## 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.5748\) 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.

6.1.3 Plot Box-Cox

index <- seq(1:nrow(train_msft))
bc = boxcox(train_msft.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda_msft <- bc$x[which.max(bc$y)]
#SK
sk_msft <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda_msft,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk_msft), "\n Batas Atas  :", max(sk_msft) )
##  Lambda : 0.06 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : -0.85 
##  Batas Atas  : 0.96

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

6.2 Penanganan Ketidakstasioneran Data

6.2.1 Dalam Ragam: Transformasi Data

Referensi : https://r-coder.com/box-cox-transformation-r/

Mengutip dari laman tersebut,

\(\mathbf{\lambda}\) Transformation
-2 \(1/x^2\)
-1 \(1/x\)
-0.5 \(1/\sqrt{x}\)
0 \(\log{(x)}\)
0.5 \(\sqrt{x}\)
1 \(x\)
2 \(x^2\)

Nilai rounded value (\(\lambda\)) optimum sebesar \(-0.21\). Nilai ini mendekati nilai \(0\), Sehingga akan menggunakan transformasi \(\log{(x)}\).

train_msft.ts.new <- log(train_msft.ts)
bc <- boxcox(train_msft.ts.new ~ index, lambda = seq(-5, 7, by=0.01))

Setelah di transformasi, Gambar di atas menunjukkan selang memuat nilai satu sehingga dapat dikatakan bahwa data saham Microsoft sudah stasioner dalam ragam.

6.2.2 Dalam Rataan: Differencing

train_msft.diff <- diff(train_msft.ts.new, differences = 1) 
plot.ts(train_msft.diff, lty=1, xlab="Periode (Tahun)", 
        col = "deepskyblue2", lwd = 3.5,
        main="Plot Difference Saham Microsoft")

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).

6.3 Uji Ulang

6.3.1 Plot ACF

acf(train_msft.diff)

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

6.3.2 Uji ADF

tseries::adf.test(train_msft.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_msft.diff
## Dickey-Fuller = -8.0797, Lag order = 7, 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.

6.4 Identifikasi Model

6.4.1 Plot ACF

acf(train_msft.diff)

Berdasarkan plot ACF tersebut, terlihat bahwa cuts off pada lag 5 dan 15. Maka model tidak dapat di identifikasi dengan plot ACF.

6.4.2 Plot PACF

pacf(train_msft.diff)

Berdasarkan plot PACF tersebut, terlihat bahwa cuts off pada lag 14. Maka model tidak dapat di identifikasi dengan plot PACF.

6.4.3 Plot EACF

eacf(train_msft.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  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x x o o o o o o o o o  o  o  o 
## 3 x o o o o o o o o o o  o  o  o 
## 4 x o x x o o o o o o o  o  o  o 
## 5 x x o o x o o o o o o  o  o  o 
## 6 x x x o x o o o o o o  o  o  o 
## 7 x x o o x x x 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), dst.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

6.5 Pendugaan Parameter Model Tentatif

model.tentaif_msft <- 
  model_tentatif(train_msft.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  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x x o o o o o o o o o  o  o  o 
## 3 x o o o o o o o o o o  o  o  o 
## 4 x o x x o o o o o o o  o  o  o 
## 5 x x o o x o o o o o o  o  o  o 
## 6 x x x o x o o o o o o  o  o  o 
## 7 x x o o x x x o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(0,1,1) 
## 
## Coefficients:
##           ma1
##       -0.9959
## s.e.   0.0085
## 
## sigma^2 = 0.0002877:  log likelihood = 1212.74
## AIC=-2421.48   AICc=-2421.46   BIC=-2413.23
datatable(model.tentaif_msft, filter = 'top', 
          options = list(pageLength = 5))

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

model_msft.da <- Arima(train_msft.diff, order=c(0,1,1), method="ML")

6.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.6.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_msft.da <- model_msft.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_msft.da) 
qqline(sisaan_msft.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_msft.da)), sisaan_msft.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_msft.da) 
pacf(sisaan_msft.da) 

Berdasarkan plot kuantil-kuantil normal, secara eksplorasi ditunjukkan sisaan menyebar tidak 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(0,1,1) juga signifikan pada 20 lag awal yang menandakan tidak saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

6.6.2 Uji Formal

6.6.2.1 Sisaan Menyebar Normal

ks.test(sisaan_msft.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_msft.da
## D = 0.47559, 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.2\times 10^{-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.6.2.2 Sisaan saling bebas/tidak ada autokorelasi

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

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.5821\) 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.6.2.3 Sisaan homogen

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

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.2191\) yang lebih besar dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa ragam sisaan homogen.

6.6.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_msft.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_msft.da
## t = 1.4653, df = 457, p-value = 0.1435
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.000394850  0.002709542
## sample estimates:
##   mean of x 
## 0.001157346

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.1435\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

6.7 Peramalan

6.7.1 Ramal

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

#---FORECAST---#
ramalan_msft.da <- forecast::forecast(model_msft.da, h = h) 
ramalan_msft.da
##     Point Forecast       Lo 80      Hi 80       Lo 95      Hi 95
## 460   0.0001743505 -0.02156531 0.02191401 -0.03307359 0.03342229
## 461   0.0001743505 -0.02156549 0.02191419 -0.03307386 0.03342256
## 462   0.0001743505 -0.02156567 0.02191437 -0.03307414 0.03342284
## 463   0.0001743505 -0.02156585 0.02191455 -0.03307441 0.03342311
## 464   0.0001743505 -0.02156602 0.02191472 -0.03307468 0.03342338
## 465   0.0001743505 -0.02156620 0.02191490 -0.03307495 0.03342366
## 466   0.0001743505 -0.02156638 0.02191508 -0.03307523 0.03342393
## 467   0.0001743505 -0.02156656 0.02191526 -0.03307550 0.03342420
## 468   0.0001743505 -0.02156674 0.02191544 -0.03307577 0.03342447
## 469   0.0001743505 -0.02156691 0.02191562 -0.03307605 0.03342475
## 470   0.0001743505 -0.02156709 0.02191579 -0.03307632 0.03342502
## 471   0.0001743505 -0.02156727 0.02191597 -0.03307659 0.03342529
## 472   0.0001743505 -0.02156745 0.02191615 -0.03307686 0.03342556
## 473   0.0001743505 -0.02156763 0.02191633 -0.03307714 0.03342584
## 474   0.0001743505 -0.02156781 0.02191651 -0.03307741 0.03342611
## 475   0.0001743505 -0.02156798 0.02191669 -0.03307768 0.03342638
## 476   0.0001743505 -0.02156816 0.02191686 -0.03307795 0.03342665
## 477   0.0001743505 -0.02156834 0.02191704 -0.03307823 0.03342693
## 478   0.0001743505 -0.02156852 0.02191722 -0.03307850 0.03342720
## 479   0.0001743505 -0.02156870 0.02191740 -0.03307877 0.03342747
## 480   0.0001743505 -0.02156888 0.02191758 -0.03307904 0.03342775
## 481   0.0001743505 -0.02156905 0.02191775 -0.03307932 0.03342802
## 482   0.0001743505 -0.02156923 0.02191793 -0.03307959 0.03342829
## 483   0.0001743505 -0.02156941 0.02191811 -0.03307986 0.03342856
## 484   0.0001743505 -0.02156959 0.02191829 -0.03308013 0.03342884
## 485   0.0001743505 -0.02156977 0.02191847 -0.03308041 0.03342911
## 486   0.0001743505 -0.02156995 0.02191865 -0.03308068 0.03342938
## 487   0.0001743505 -0.02157012 0.02191882 -0.03308095 0.03342965
## 488   0.0001743505 -0.02157030 0.02191900 -0.03308123 0.03342993
## 489   0.0001743505 -0.02157048 0.02191918 -0.03308150 0.03343020
## 490   0.0001743505 -0.02157066 0.02191936 -0.03308177 0.03343047
## 491   0.0001743505 -0.02157084 0.02191954 -0.03308204 0.03343074
## 492   0.0001743505 -0.02157101 0.02191972 -0.03308232 0.03343102
## 493   0.0001743505 -0.02157119 0.02191989 -0.03308259 0.03343129
## 494   0.0001743505 -0.02157137 0.02192007 -0.03308286 0.03343156
## 495   0.0001743505 -0.02157155 0.02192025 -0.03308313 0.03343183
## 496   0.0001743505 -0.02157173 0.02192043 -0.03308341 0.03343211
## 497   0.0001743505 -0.02157191 0.02192061 -0.03308368 0.03343238
## 498   0.0001743505 -0.02157208 0.02192078 -0.03308395 0.03343265
## 499   0.0001743505 -0.02157226 0.02192096 -0.03308422 0.03343292
## 500   0.0001743505 -0.02157244 0.02192114 -0.03308450 0.03343320
## 501   0.0001743505 -0.02157262 0.02192132 -0.03308477 0.03343347
## 502   0.0001743505 -0.02157280 0.02192150 -0.03308504 0.03343374
## 503   0.0001743505 -0.02157298 0.02192168 -0.03308531 0.03343401
## 504   0.0001743505 -0.02157315 0.02192185 -0.03308559 0.03343429
## 505   0.0001743505 -0.02157333 0.02192203 -0.03308586 0.03343456
## 506   0.0001743505 -0.02157351 0.02192221 -0.03308613 0.03343483
## 507   0.0001743505 -0.02157369 0.02192239 -0.03308640 0.03343511
## 508   0.0001743505 -0.02157387 0.02192257 -0.03308668 0.03343538
## 509   0.0001743505 -0.02157404 0.02192275 -0.03308695 0.03343565
## 510   0.0001743505 -0.02157422 0.02192292 -0.03308722 0.03343592
## 511   0.0001743505 -0.02157440 0.02192310 -0.03308749 0.03343620
## 512   0.0001743505 -0.02157458 0.02192328 -0.03308777 0.03343647
## 513   0.0001743505 -0.02157476 0.02192346 -0.03308804 0.03343674
## 514   0.0001743505 -0.02157494 0.02192364 -0.03308831 0.03343701
## 515   0.0001743505 -0.02157511 0.02192381 -0.03308858 0.03343729
## 516   0.0001743505 -0.02157529 0.02192399 -0.03308886 0.03343756
## 517   0.0001743505 -0.02157547 0.02192417 -0.03308913 0.03343783
## 518   0.0001743505 -0.02157565 0.02192435 -0.03308940 0.03343810
## 519   0.0001743505 -0.02157583 0.02192453 -0.03308967 0.03343838
## 520   0.0001743505 -0.02157600 0.02192471 -0.03308995 0.03343865
## 521   0.0001743505 -0.02157618 0.02192488 -0.03309022 0.03343892
## 522   0.0001743505 -0.02157636 0.02192506 -0.03309049 0.03343919
## 523   0.0001743505 -0.02157654 0.02192524 -0.03309076 0.03343947
## 524   0.0001743505 -0.02157672 0.02192542 -0.03309104 0.03343974
## 525   0.0001743505 -0.02157690 0.02192560 -0.03309131 0.03344001
## 526   0.0001743505 -0.02157707 0.02192577 -0.03309158 0.03344028
## 527   0.0001743505 -0.02157725 0.02192595 -0.03309185 0.03344056
## 528   0.0001743505 -0.02157743 0.02192613 -0.03309213 0.03344083
## 529   0.0001743505 -0.02157761 0.02192631 -0.03309240 0.03344110
## 530   0.0001743505 -0.02157779 0.02192649 -0.03309267 0.03344137
## 531   0.0001743505 -0.02157796 0.02192667 -0.03309295 0.03344165
## 532   0.0001743505 -0.02157814 0.02192684 -0.03309322 0.03344192
## 533   0.0001743505 -0.02157832 0.02192702 -0.03309349 0.03344219
## 534   0.0001743505 -0.02157850 0.02192720 -0.03309376 0.03344246
## 535   0.0001743505 -0.02157868 0.02192738 -0.03309404 0.03344274
## 536   0.0001743505 -0.02157886 0.02192756 -0.03309431 0.03344301
## 537   0.0001743505 -0.02157903 0.02192773 -0.03309458 0.03344328
## 538   0.0001743505 -0.02157921 0.02192791 -0.03309485 0.03344355
## 539   0.0001743505 -0.02157939 0.02192809 -0.03309513 0.03344383
## 540   0.0001743505 -0.02157957 0.02192827 -0.03309540 0.03344410
## 541   0.0001743505 -0.02157975 0.02192845 -0.03309567 0.03344437
## 542   0.0001743505 -0.02157992 0.02192863 -0.03309594 0.03344464
## 543   0.0001743505 -0.02158010 0.02192880 -0.03309621 0.03344492
## 544   0.0001743505 -0.02158028 0.02192898 -0.03309649 0.03344519
## 545   0.0001743505 -0.02158046 0.02192916 -0.03309676 0.03344546
## 546   0.0001743505 -0.02158064 0.02192934 -0.03309703 0.03344573
## 547   0.0001743505 -0.02158082 0.02192952 -0.03309730 0.03344601
## 548   0.0001743505 -0.02158099 0.02192969 -0.03309758 0.03344628
## 549   0.0001743505 -0.02158117 0.02192987 -0.03309785 0.03344655
## 550   0.0001743505 -0.02158135 0.02193005 -0.03309812 0.03344682
## 551   0.0001743505 -0.02158153 0.02193023 -0.03309839 0.03344710
## 552   0.0001743505 -0.02158171 0.02193041 -0.03309867 0.03344737
## 553   0.0001743505 -0.02158188 0.02193059 -0.03309894 0.03344764
## 554   0.0001743505 -0.02158206 0.02193076 -0.03309921 0.03344791
## 555   0.0001743505 -0.02158224 0.02193094 -0.03309948 0.03344819
## 556   0.0001743505 -0.02158242 0.02193112 -0.03309976 0.03344846
## 557   0.0001743505 -0.02158260 0.02193130 -0.03310003 0.03344873
## 558   0.0001743505 -0.02158278 0.02193148 -0.03310030 0.03344900
## 559   0.0001743505 -0.02158295 0.02193165 -0.03310057 0.03344928
## 560   0.0001743505 -0.02158313 0.02193183 -0.03310085 0.03344955
## 561   0.0001743505 -0.02158331 0.02193201 -0.03310112 0.03344982
## 562   0.0001743505 -0.02158349 0.02193219 -0.03310139 0.03345009
## 563   0.0001743505 -0.02158367 0.02193237 -0.03310166 0.03345037
## 564   0.0001743505 -0.02158384 0.02193255 -0.03310194 0.03345064
## 565   0.0001743505 -0.02158402 0.02193272 -0.03310221 0.03345091
## 566   0.0001743505 -0.02158420 0.02193290 -0.03310248 0.03345118
## 567   0.0001743505 -0.02158438 0.02193308 -0.03310275 0.03345145
## 568   0.0001743505 -0.02158456 0.02193326 -0.03310303 0.03345173
## 569   0.0001743505 -0.02158473 0.02193344 -0.03310330 0.03345200
## 570   0.0001743505 -0.02158491 0.02193361 -0.03310357 0.03345227
## 571   0.0001743505 -0.02158509 0.02193379 -0.03310384 0.03345254
## 572   0.0001743505 -0.02158527 0.02193397 -0.03310412 0.03345282
## 573   0.0001743505 -0.02158545 0.02193415 -0.03310439 0.03345309
## 574   0.0001743505 -0.02158563 0.02193433 -0.03310466 0.03345336

6.7.2 Plot

data.ramalan_msft.da <- ramalan_msft.da$mean
plot(ramalan_msft.da, xlab="Periode (Tahun)", col = "deepskyblue2", lwd = 2.5)

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

pt_1 <- train_msft.ts[length(train_msft.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_msft.da
#Transformasi Balik
ramal_msft <- exp(hasil.forc.Diff)
#Diff inv
ramal_msft <- diffinv(ramal_msft, differences = 1) + pt_1

#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_msft.ts, ramal_msft, xlab="Periode (Hari)", 
        ylab="Saham Harga (USD)",
        col = "deepskyblue2", lwd = 3.5,
        main="Plot Ramalan Saham Microsoft Selama 115 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham Microsoft diramalkan akan terus menaik setiap periodenya.

6.7.3 Perbandingan

perbandingan_msft.da <- matrix(data=c(head(test_msft.ts, n=h), ramal_msft[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_msft.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_msft.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.msft <- accuracy(ts(ramal_msft[-1]), head(test_msft.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_msft.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.msft) <- "MSFT"
datatable(akurasi.msft)

Didapatkan nilai MAPE sebesar \(7.215409\%\) (kurang dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(0,1,1) sudah sangat baik.

7 Netflix

7.1 Uji Stasioner Data

7.1.1 Plot ACF

acf(train_nflx.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.

7.1.2 Uji ADF

tseries::adf.test(train_nflx.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_nflx.ts
## Dickey-Fuller = -2.7617, Lag order = 7, p-value = 0.2557
## 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.2557\) 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.

7.1.3 Plot Box-Cox

index <- seq(1:nrow(train_nflx))
bc = boxcox(train_nflx.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda_nflx <- bc$x[which.max(bc$y)]
#SK
sk_nflx <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda_nflx,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk_nflx), "\n Batas Atas  :", max(sk_nflx) )
##  Lambda : -0.06 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : -0.38 
##  Batas Atas  : 0.25

Gambar di atas menunjukkan nilai rounded value (\(\lambda\)) optimum sebesar \(-0.06\) dan pada selang kepercayaan \(95\%\) nilai memiliki batas bawah \(-0.38\) dan batas atas \(0.25\). Selang tersebut tidak memuat nilai 1 sehingga dapat dikatakan bahwa data saham Netflix tidak stasioner dalam ragam.

7.2 Penanganan Ketidakstasioneran Data

7.2.1 Dalam Ragam: Transformasi Data

Referensi : https://r-coder.com/box-cox-transformation-r/

Mengutip dari laman tersebut,

\(\mathbf{\lambda}\) Transformation
-2 \(1/x^2\)
-1 \(1/x\)
-0.5 \(1/\sqrt{x}\)
0 \(\log{(x)}\)
0.5 \(\sqrt{x}\)
1 \(x\)
2 \(x^2\)

Nilai rounded value (\(\lambda\)) optimum sebesar \(-0.21\). Nilai ini mendekati nilai \(0\), Sehingga akan menggunakan transformasi \(\log{(x)}\).

train_nflx.ts.new <- log(train_nflx.ts)
bc <- boxcox(train_nflx.ts.new ~ index, lambda = seq(-5, 7, by=0.01))

Setelah di transformasi, Gambar di atas menunjukkan selang memuat nilai satu sehingga dapat dikatakan bahwa data saham Amazon sudah stasioner dalam ragam.

7.2.2 Dalam Rataan: Differencing

train_nflx.diff <- diff(train_nflx.ts.new, differences = 1) 
plot.ts(train_nflx.diff, lty=1, xlab="Periode (Hari)", 
        col = "firebrick3", lwd = 3.5,
        main="Plot Difference Saham Netflix")

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).

7.3 Uji Ulang

7.3.1 Plot ACF

acf(train_nflx.diff)

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

7.3.2 Uji ADF

tseries::adf.test(train_nflx.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_nflx.diff
## Dickey-Fuller = -7.695, Lag order = 7, 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.

7.4 Identifikasi Model

7.4.1 Plot ACF

acf(train_nflx.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cenderung cuts off pada lag ke 21. Maka model tidak dapat di identifikasi dengan plot ACF.

7.4.2 Plot PACF

pacf(train_nflx.diff)

Berdasarkan plot tersebut, terlihat bahwa plot PACF cenderung cuts off pada lag ke 21 dan 22. Maka model tidak dapat di identifikasi dengan plot PACF.

7.4.3 Plot EACF

eacf(train_nflx.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  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x 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 o 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 o x o o o o o o o o o  o  o  o 
## 7 o x x o o o 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), dst.. Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat proses.

7.5 Pendugaan Parameter Model Tentatif

model.tentaif_nflx <- 
  model_tentatif(train_nflx.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  o  o 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x 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 o 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 o x o o o o o o o o o  o  o  o 
## 7 o x x o o o o o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(0,1,1) 
## 
## Coefficients:
##           ma1
##       -0.9881
## s.e.   0.0080
## 
## sigma^2 = 0.001229:  log likelihood = 881.55
## AIC=-1759.09   AICc=-1759.06   BIC=-1750.84
datatable(model.tentaif_nflx, filter = 'top', 
          options = list(pageLength = 5))

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

model_nflx.da <- Arima(train_nflx.diff, order=c(0,1,1), method="ML")

7.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.

7.6.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_nflx.da <- model_nflx.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_nflx.da) 
qqline(sisaan_nflx.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_nflx.da)), sisaan_nflx.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_nflx.da) 
pacf(sisaan_nflx.da) 

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

7.6.2 Uji Formal

7.6.2.1 Sisaan Menyebar Normal

ks.test(sisaan_nflx.da,"pnorm")  #tak tolak H0 > sisaan menyebar normal
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  sisaan_nflx.da
## D = 0.46323, 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.2\times 10^{-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.

7.6.2.2 Sisaan saling bebas/tidak ada autokorelasi

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

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.8597\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa sisaan saling bebas.

7.6.2.3 Sisaan homogen

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

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.9961\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa ragam sisaan homogen.

7.6.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_nflx.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_nflx.da
## t = 1.2282, df = 457, p-value = 0.22
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.001203689  0.005216033
## sample estimates:
##   mean of x 
## 0.002006172

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.22\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

7.7 Peramalan

7.7.1 Ramal

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

#---FORECAST---#
ramalan_nflx.da <- forecast::forecast(model_nflx.da, h = h) 
ramalan_nflx.da
##     Point Forecast       Lo 80      Hi 80       Lo 95      Hi 95
## 460    0.001414115 -0.04350661 0.04633484 -0.06728620 0.07011443
## 461    0.001414115 -0.04350976 0.04633799 -0.06729102 0.07011925
## 462    0.001414115 -0.04351292 0.04634114 -0.06729585 0.07012408
## 463    0.001414115 -0.04351607 0.04634430 -0.06730067 0.07012890
## 464    0.001414115 -0.04351922 0.04634745 -0.06730550 0.07013373
## 465    0.001414115 -0.04352238 0.04635061 -0.06731032 0.07013855
## 466    0.001414115 -0.04352553 0.04635376 -0.06731514 0.07014337
## 467    0.001414115 -0.04352868 0.04635691 -0.06731997 0.07014819
## 468    0.001414115 -0.04353184 0.04636007 -0.06732479 0.07015302
## 469    0.001414115 -0.04353499 0.04636322 -0.06732961 0.07015784
## 470    0.001414115 -0.04353814 0.04636637 -0.06733443 0.07016266
## 471    0.001414115 -0.04354130 0.04636953 -0.06733925 0.07016748
## 472    0.001414115 -0.04354445 0.04637268 -0.06734407 0.07017230
## 473    0.001414115 -0.04354760 0.04637583 -0.06734889 0.07017712
## 474    0.001414115 -0.04355075 0.04637898 -0.06735371 0.07018194
## 475    0.001414115 -0.04355390 0.04638213 -0.06735853 0.07018676
## 476    0.001414115 -0.04355705 0.04638528 -0.06736335 0.07019158
## 477    0.001414115 -0.04356021 0.04638844 -0.06736817 0.07019640
## 478    0.001414115 -0.04356336 0.04639159 -0.06737299 0.07020122
## 479    0.001414115 -0.04356651 0.04639474 -0.06737781 0.07020604
## 480    0.001414115 -0.04356966 0.04639789 -0.06738263 0.07021086
## 481    0.001414115 -0.04357281 0.04640104 -0.06738745 0.07021568
## 482    0.001414115 -0.04357596 0.04640419 -0.06739227 0.07022049
## 483    0.001414115 -0.04357911 0.04640734 -0.06739708 0.07022531
## 484    0.001414115 -0.04358226 0.04641049 -0.06740190 0.07023013
## 485    0.001414115 -0.04358541 0.04641364 -0.06740672 0.07023495
## 486    0.001414115 -0.04358856 0.04641679 -0.06741153 0.07023976
## 487    0.001414115 -0.04359171 0.04641994 -0.06741635 0.07024458
## 488    0.001414115 -0.04359485 0.04642308 -0.06742116 0.07024939
## 489    0.001414115 -0.04359800 0.04642623 -0.06742598 0.07025421
## 490    0.001414115 -0.04360115 0.04642938 -0.06743079 0.07025902
## 491    0.001414115 -0.04360430 0.04643253 -0.06743561 0.07026384
## 492    0.001414115 -0.04360745 0.04643568 -0.06744042 0.07026865
## 493    0.001414115 -0.04361060 0.04643882 -0.06744524 0.07027347
## 494    0.001414115 -0.04361374 0.04644197 -0.06745005 0.07027828
## 495    0.001414115 -0.04361689 0.04644512 -0.06745486 0.07028309
## 496    0.001414115 -0.04362004 0.04644827 -0.06745968 0.07028791
## 497    0.001414115 -0.04362318 0.04645141 -0.06746449 0.07029272
## 498    0.001414115 -0.04362633 0.04645456 -0.06746930 0.07029753
## 499    0.001414115 -0.04362948 0.04645771 -0.06747411 0.07030234
## 500    0.001414115 -0.04363262 0.04646085 -0.06747892 0.07030715
## 501    0.001414115 -0.04363577 0.04646400 -0.06748374 0.07031197
## 502    0.001414115 -0.04363891 0.04646714 -0.06748855 0.07031678
## 503    0.001414115 -0.04364206 0.04647029 -0.06749336 0.07032159
## 504    0.001414115 -0.04364520 0.04647343 -0.06749817 0.07032640
## 505    0.001414115 -0.04364835 0.04647658 -0.06750298 0.07033121
## 506    0.001414115 -0.04365149 0.04647972 -0.06750779 0.07033602
## 507    0.001414115 -0.04365464 0.04648287 -0.06751260 0.07034083
## 508    0.001414115 -0.04365778 0.04648601 -0.06751741 0.07034563
## 509    0.001414115 -0.04366093 0.04648916 -0.06752221 0.07035044
## 510    0.001414115 -0.04366407 0.04649230 -0.06752702 0.07035525
## 511    0.001414115 -0.04366722 0.04649544 -0.06753183 0.07036006
## 512    0.001414115 -0.04367036 0.04649859 -0.06753664 0.07036487
## 513    0.001414115 -0.04367350 0.04650173 -0.06754144 0.07036967
## 514    0.001414115 -0.04367665 0.04650487 -0.06754625 0.07037448
## 515    0.001414115 -0.04367979 0.04650802 -0.06755106 0.07037929
## 516    0.001414115 -0.04368293 0.04651116 -0.06755586 0.07038409
## 517    0.001414115 -0.04368607 0.04651430 -0.06756067 0.07038890
## 518    0.001414115 -0.04368922 0.04651744 -0.06756548 0.07039371
## 519    0.001414115 -0.04369236 0.04652059 -0.06757028 0.07039851
## 520    0.001414115 -0.04369550 0.04652373 -0.06757509 0.07040332
## 521    0.001414115 -0.04369864 0.04652687 -0.06757989 0.07040812
## 522    0.001414115 -0.04370178 0.04653001 -0.06758469 0.07041292
## 523    0.001414115 -0.04370492 0.04653315 -0.06758950 0.07041773
## 524    0.001414115 -0.04370806 0.04653629 -0.06759430 0.07042253
## 525    0.001414115 -0.04371120 0.04653943 -0.06759911 0.07042733
## 526    0.001414115 -0.04371434 0.04654257 -0.06760391 0.07043214
## 527    0.001414115 -0.04371748 0.04654571 -0.06760871 0.07043694
## 528    0.001414115 -0.04372062 0.04654885 -0.06761351 0.07044174
## 529    0.001414115 -0.04372376 0.04655199 -0.06761831 0.07044654
## 530    0.001414115 -0.04372690 0.04655513 -0.06762312 0.07045135
## 531    0.001414115 -0.04373004 0.04655827 -0.06762792 0.07045615
## 532    0.001414115 -0.04373318 0.04656141 -0.06763272 0.07046095
## 533    0.001414115 -0.04373632 0.04656455 -0.06763752 0.07046575
## 534    0.001414115 -0.04373946 0.04656769 -0.06764232 0.07047055
## 535    0.001414115 -0.04374260 0.04657083 -0.06764712 0.07047535
## 536    0.001414115 -0.04374574 0.04657397 -0.06765192 0.07048015
## 537    0.001414115 -0.04374887 0.04657710 -0.06765672 0.07048495
## 538    0.001414115 -0.04375201 0.04658024 -0.06766152 0.07048975
## 539    0.001414115 -0.04375515 0.04658338 -0.06766631 0.07049454
## 540    0.001414115 -0.04375829 0.04658652 -0.06767111 0.07049934
## 541    0.001414115 -0.04376142 0.04658965 -0.06767591 0.07050414
## 542    0.001414115 -0.04376456 0.04659279 -0.06768071 0.07050894
## 543    0.001414115 -0.04376770 0.04659593 -0.06768551 0.07051374
## 544    0.001414115 -0.04377083 0.04659906 -0.06769030 0.07051853
## 545    0.001414115 -0.04377397 0.04660220 -0.06769510 0.07052333
## 546    0.001414115 -0.04377711 0.04660534 -0.06769990 0.07052812
## 547    0.001414115 -0.04378024 0.04660847 -0.06770469 0.07053292
## 548    0.001414115 -0.04378338 0.04661161 -0.06770949 0.07053772
## 549    0.001414115 -0.04378651 0.04661474 -0.06771428 0.07054251
## 550    0.001414115 -0.04378965 0.04661788 -0.06771908 0.07054731
## 551    0.001414115 -0.04379278 0.04662101 -0.06772387 0.07055210
## 552    0.001414115 -0.04379592 0.04662415 -0.06772867 0.07055689
## 553    0.001414115 -0.04379905 0.04662728 -0.06773346 0.07056169
## 554    0.001414115 -0.04380219 0.04663042 -0.06773825 0.07056648
## 555    0.001414115 -0.04380532 0.04663355 -0.06774305 0.07057128
## 556    0.001414115 -0.04380846 0.04663669 -0.06774784 0.07057607
## 557    0.001414115 -0.04381159 0.04663982 -0.06775263 0.07058086
## 558    0.001414115 -0.04381472 0.04664295 -0.06775742 0.07058565
## 559    0.001414115 -0.04381786 0.04664609 -0.06776222 0.07059044
## 560    0.001414115 -0.04382099 0.04664922 -0.06776701 0.07059524
## 561    0.001414115 -0.04382412 0.04665235 -0.06777180 0.07060003
## 562    0.001414115 -0.04382725 0.04665548 -0.06777659 0.07060482
## 563    0.001414115 -0.04383039 0.04665862 -0.06778138 0.07060961
## 564    0.001414115 -0.04383352 0.04666175 -0.06778617 0.07061440
## 565    0.001414115 -0.04383665 0.04666488 -0.06779096 0.07061919
## 566    0.001414115 -0.04383978 0.04666801 -0.06779575 0.07062398
## 567    0.001414115 -0.04384291 0.04667114 -0.06780054 0.07062877
## 568    0.001414115 -0.04384605 0.04667428 -0.06780533 0.07063356
## 569    0.001414115 -0.04384918 0.04667741 -0.06781012 0.07063835
## 570    0.001414115 -0.04385231 0.04668054 -0.06781490 0.07064313
## 571    0.001414115 -0.04385544 0.04668367 -0.06781969 0.07064792
## 572    0.001414115 -0.04385857 0.04668680 -0.06782448 0.07065271
## 573    0.001414115 -0.04386170 0.04668993 -0.06782927 0.07065750
## 574    0.001414115 -0.04386483 0.04669306 -0.06783405 0.07066228

7.7.2 Plot

data.ramalan_nflx.da <- ramalan_nflx.da$mean
plot(ramalan_nflx.da, xlab="Periode (Hari)", col = "firebrick3", lwd = 2.5)

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

pt_1 <- train_nflx.ts[length(train_nflx.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_nflx.da
#Transformasi Balik
ramal_nflx <- exp(hasil.forc.Diff)
#Diff inv
ramal_nflx <- diffinv(ramal_nflx, differences = 1) + pt_1

#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_nflx.ts, ramal_nflx, ylab="Saham Harga (USD)", 
        xlab="Periode (Hari)", 
        col = "firebrick3", lwd = 3.5,
        main="Plot Ramalan Saham Netflix Selama 115 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham Netfilx diramalkan akan terus menaik setiap periodenya.

7.7.3 Perbandingan

perbandingan_nflx.da <- matrix(data=c(head(test_nflx.ts, n=h), ramal_nflx[-1]),
                     nrow = h, ncol = 2)
colnames(perbandingan_nflx.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_nflx.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.nflx <- accuracy(ts(ramal_nflx[-1]), head(test_nflx.ts, n=h)) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_nflx.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.nflx) <- "NFLX"
datatable(akurasi.nflx)

Didapatkan nilai MAPE sebesar \(6.292792\%\) (kurang dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(0,1,1) sudah sangat baik.

8 NVIDIA

8.1 Uji Stasioner Data

8.1.1 Plot ACF

acf(train_nvda.ts)

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

8.1.2 Uji ADF

tseries::adf.test(train_nvda.ts)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_nvda.ts
## Dickey-Fuller = -1.1028, Lag order = 7, p-value = 0.922
## 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.922\) 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.

8.1.3 Plot Box-Cox

index <- seq(1:nrow(train_nvda))
bc = boxcox(train_nvda.ts~index, lambda = seq(-2, 4, by=0.01))

#Nilai Rounded Lambda
lambda_nvda <- bc$x[which.max(bc$y)]
#SK
sk_nvda <- bc$x[bc$y > max(bc$y) - 1/2 * qchisq(.95,1)]
cat(" Lambda :", lambda_nvda,
    "\n\n Selang Kepercyaan 95% \n",
    "Batas Bawah :", min(sk_nvda), "\n Batas Atas  :", max(sk_nvda) )
##  Lambda : 0.09 
## 
##  Selang Kepercyaan 95% 
##  Batas Bawah : -0.28 
##  Batas Atas  : 0.47

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

8.2 Penanganan Ketidakstasioneran Data

8.2.1 Dalam Ragam: Transformasi Data

Referensi : https://r-coder.com/box-cox-transformation-r/

Mengutip dari laman tersebut,

\[ \text{Transformasi}\begin{cases} \frac{x^\lambda-1}{\lambda} & \text{jika } \text{ } \lambda \ne 0 \\ \log(x) & \text{jika } \text{ } \lambda = 0 \end{cases} \]

Nilai rounded value (\(\lambda\)) optimum sebesar \(-0.22 \ne 0\). Sehingga akan menggunakan transformasi\(\frac{x^\lambda-1}{\lambda}\) .

train_nvda.ts.new <- (train_nvda.ts^lambda_nvda-1)/lambda_nvda
bc <- boxcox(train_nvda.ts.new ~ index, lambda = seq(-5, 7, by=0.01))

Setelah di transformasi, Gambar di atas menunjukkan selang memuat nilai satu sehingga dapat dikatakan bahwa data saham Amazon sudah stasioner dalam ragam.

8.2.2 Dalam Rataan: Differencing

train_nvda.diff <- diff(train_nvda.ts.new, differences = 1) 
plot.ts(train_nvda.diff, lty=1, xlab="Periode (Tahun)", 
        col = "green4", lwd = 4,
        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).

8.3 Uji Ulang

8.3.1 Plot ACF

acf(train_nvda.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF tails off dan membentuk pola naik turun.

8.3.2 Uji ADF

tseries::adf.test(train_nvda.diff)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  train_nvda.diff
## Dickey-Fuller = -7.9068, Lag order = 7, 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.

8.4 Identifikasi Model

8.4.1 Plot ACF

acf(train_nvda.diff)

Berdasarkan plot tersebut, terlihat bahwa plot ACF cenderung tails of. Maka model tidak dapat di identifikasi dengan plot ACF.

8.4.2 Plot PACF

pacf(train_nvda.diff)

Berdasarkan plot tersebut, terlihat bahwa plot PACF cenderung tails off. Maka model tidak dapat di identifikasi dengan plot PACF.

8.4.3 Plot EACF

eacf(train_nvda.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  o  x 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x 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 x x o o o o o o o  o  o  o 
## 5 x x x x x o o o o o o  o  o  o 
## 6 x x x x x o o o o o o  o  o  o 
## 7 x x x o x x o o o o o  o  o  o

Identifikasi model menggunakan plot EACF dilakukan dengan melihat ujung segitiga pada pola segitiga nol. Dalam hal ini model tentatif yang terbentuk adalah ARIMA(1,1,2), ARIMA(1,1,1), ARIMA(0,1,1), ARIMA(0,1,2), ARIMA(0,1,3), ARIMA(1,1,3), ARIMA(2,1,3),ARIMA(3,1,3). Namun karena kemungkinannya sangat banyak, maka akan digunakan function agar menyingkat

8.5 Pendugaan Parameter Model Tentatif

model.tentaif_nvda <- 
  model_tentatif(train_nvda.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  o  x 
## 1 x o o o o o o o o o o  o  o  o 
## 2 x 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 x x o o o o o o o  o  o  o 
## 5 x x x x x o o o o o o  o  o  o 
## 6 x x x x x o o o o o o  o  o  o 
## 7 x x x o x x o o o o o  o  o  o 
## 
## Model ARIMA dengan AIC terkecil:
## Series: data 
## ARIMA(0,1,1) 
## 
## Coefficients:
##           ma1
##       -0.9910
## s.e.   0.0064
## 
## sigma^2 = 0.002244:  log likelihood = 791.07
## AIC=-1578.14   AICc=-1578.11   BIC=-1569.76
datatable(model.tentaif_nvda, filter = 'top', 
          options = list(pageLength = 5))

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

model_nvda.da <- Arima(train_nvda.diff, order=c(0,1,1), method="ML")

8.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.

8.6.1 Eksplorasi Sisaan

#Eksplorasi 
sisaan_nvda.da <- model_nvda.da$residuals 
par(mfrow=c(2,2)) 
# QQ-Plot
qqnorm(sisaan_nvda.da) 
qqline(sisaan_nvda.da, col = "dodgerblue3", lwd = 2.5) 
# Plot sisaan
plot(c(1:length(sisaan_nvda.da)), sisaan_nvda.da, 
     main = "Plot Sisaan Model ARIMA",
     xlab = "Periode",
     ylab = "Nilai Sisaan")
abline(h = 0, col = "firebrick2", lty = 2, lwd=2.5)
#Plot ACF dan PACF
acf(sisaan_nvda.da) 
pacf(sisaan_nvda.da) 

Berdasarkan plot kuantil-kuantil normal, secara eksplorasi ditunjukkan sisaan menyebar tidak normal ditandai dengan tititk-titiknya 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 20 lag awal yang menandakan saling bebas. Kondisi ini akan diuji lebih lanjut dengan uji formal.

8.6.2 Uji Formal

8.6.2.1 Sisaan Menyebar Normal

shapiro.test(sisaan_nvda.da)  #tak tolak H0 > sisaan menyebar normal
## 
##  Shapiro-Wilk normality test
## 
## data:  sisaan_nvda.da
## W = 0.95984, p-value = 2.933e-10

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.933\times 10^{-10}\) 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.

8.6.2.2 Sisaan saling bebas/tidak ada autokorelasi

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

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.8017\) 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.

8.6.2.3 Sisaan homogen

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

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.4553\) yang lebih besar dari taraf nyata \(5\%\) sehingga tolak \(H_0\) dan menandakan bahwa ragam sisaan homogen.

8.6.2.4 Nilai tengah sama dengan nol

#4) Nilai tengah sisaan sama dengan nol 
t.test(sisaan_nvda.da, mu = 0, conf.level = 0.95)  #tak tolak h0 > nilai tengah sisaan sama dengan 0
## 
##  One Sample t-test
## 
## data:  sisaan_nvda.da
## t = 1.2442, df = 486, p-value = 0.214
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.001542948  0.006870357
## sample estimates:
##   mean of x 
## 0.002663705

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.214\) yang lebih besar dari taraf nyata \(5\%\) sehingga tak tolak \(H_0\) dan menandakan bahwa nilai tengah sisaan sama dengan nol.

8.7 Peramalan

8.7.1 Ramal

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

#---FORECAST---#
ramalan_nvda.da <- forecast::forecast(model_nvda.da, h = length(test_nvda.ts)) 
ramalan_nvda.da
##     Point Forecast       Lo 80      Hi 80       Lo 95      Hi 95
## 489    0.004125874 -0.05658194 0.06483369 -0.08871872 0.09697047
## 490    0.004125874 -0.05658442 0.06483617 -0.08872251 0.09697425
## 491    0.004125874 -0.05658689 0.06483864 -0.08872629 0.09697804
## 492    0.004125874 -0.05658937 0.06484112 -0.08873008 0.09698182
## 493    0.004125874 -0.05659184 0.06484359 -0.08873386 0.09698561
## 494    0.004125874 -0.05659432 0.06484607 -0.08873764 0.09698939
## 495    0.004125874 -0.05659679 0.06484854 -0.08874143 0.09699318
## 496    0.004125874 -0.05659927 0.06485101 -0.08874521 0.09699696
## 497    0.004125874 -0.05660174 0.06485349 -0.08874900 0.09700075
## 498    0.004125874 -0.05660421 0.06485596 -0.08875278 0.09700453
## 499    0.004125874 -0.05660669 0.06485844 -0.08875657 0.09700831
## 500    0.004125874 -0.05660916 0.06486091 -0.08876035 0.09701210
## 501    0.004125874 -0.05661164 0.06486338 -0.08876413 0.09701588
## 502    0.004125874 -0.05661411 0.06486586 -0.08876792 0.09701966
## 503    0.004125874 -0.05661658 0.06486833 -0.08877170 0.09702345
## 504    0.004125874 -0.05661906 0.06487081 -0.08877548 0.09702723
## 505    0.004125874 -0.05662153 0.06487328 -0.08877927 0.09703101
## 506    0.004125874 -0.05662400 0.06487575 -0.08878305 0.09703480
## 507    0.004125874 -0.05662648 0.06487823 -0.08878683 0.09703858
## 508    0.004125874 -0.05662895 0.06488070 -0.08879061 0.09704236
## 509    0.004125874 -0.05663142 0.06488317 -0.08879440 0.09704614
## 510    0.004125874 -0.05663390 0.06488565 -0.08879818 0.09704993
## 511    0.004125874 -0.05663637 0.06488812 -0.08880196 0.09705371
## 512    0.004125874 -0.05663884 0.06489059 -0.08880574 0.09705749
## 513    0.004125874 -0.05664132 0.06489306 -0.08880952 0.09706127
## 514    0.004125874 -0.05664379 0.06489554 -0.08881330 0.09706505
## 515    0.004125874 -0.05664626 0.06489801 -0.08881709 0.09706883
## 516    0.004125874 -0.05664873 0.06490048 -0.08882087 0.09707262
## 517    0.004125874 -0.05665121 0.06490295 -0.08882465 0.09707640
## 518    0.004125874 -0.05665368 0.06490543 -0.08882843 0.09708018
## 519    0.004125874 -0.05665615 0.06490790 -0.08883221 0.09708396
## 520    0.004125874 -0.05665862 0.06491037 -0.08883599 0.09708774
## 521    0.004125874 -0.05666109 0.06491284 -0.08883977 0.09709152
## 522    0.004125874 -0.05666357 0.06491531 -0.08884355 0.09709530
## 523    0.004125874 -0.05666604 0.06491779 -0.08884733 0.09709908
## 524    0.004125874 -0.05666851 0.06492026 -0.08885111 0.09710286
## 525    0.004125874 -0.05667098 0.06492273 -0.08885489 0.09710664
## 526    0.004125874 -0.05667345 0.06492520 -0.08885867 0.09711042
## 527    0.004125874 -0.05667592 0.06492767 -0.08886245 0.09711420
## 528    0.004125874 -0.05667839 0.06493014 -0.08886623 0.09711798
## 529    0.004125874 -0.05668087 0.06493261 -0.08887001 0.09712176
## 530    0.004125874 -0.05668334 0.06493508 -0.08887379 0.09712554
## 531    0.004125874 -0.05668581 0.06493756 -0.08887757 0.09712932
## 532    0.004125874 -0.05668828 0.06494003 -0.08888135 0.09713309
## 533    0.004125874 -0.05669075 0.06494250 -0.08888512 0.09713687
## 534    0.004125874 -0.05669322 0.06494497 -0.08888890 0.09714065
## 535    0.004125874 -0.05669569 0.06494744 -0.08889268 0.09714443
## 536    0.004125874 -0.05669816 0.06494991 -0.08889646 0.09714821
## 537    0.004125874 -0.05670063 0.06495238 -0.08890024 0.09715199
## 538    0.004125874 -0.05670310 0.06495485 -0.08890402 0.09715576
## 539    0.004125874 -0.05670557 0.06495732 -0.08890779 0.09715954
## 540    0.004125874 -0.05670804 0.06495979 -0.08891157 0.09716332
## 541    0.004125874 -0.05671051 0.06496226 -0.08891535 0.09716710
## 542    0.004125874 -0.05671298 0.06496473 -0.08891913 0.09717087
## 543    0.004125874 -0.05671545 0.06496720 -0.08892290 0.09717465
## 544    0.004125874 -0.05671792 0.06496967 -0.08892668 0.09717843
## 545    0.004125874 -0.05672039 0.06497214 -0.08893046 0.09718220
## 546    0.004125874 -0.05672286 0.06497461 -0.08893423 0.09718598
## 547    0.004125874 -0.05672533 0.06497708 -0.08893801 0.09718976
## 548    0.004125874 -0.05672780 0.06497955 -0.08894179 0.09719353
## 549    0.004125874 -0.05673027 0.06498201 -0.08894556 0.09719731
## 550    0.004125874 -0.05673274 0.06498448 -0.08894934 0.09720109
## 551    0.004125874 -0.05673520 0.06498695 -0.08895311 0.09720486
## 552    0.004125874 -0.05673767 0.06498942 -0.08895689 0.09720864
## 553    0.004125874 -0.05674014 0.06499189 -0.08896066 0.09721241
## 554    0.004125874 -0.05674261 0.06499436 -0.08896444 0.09721619
## 555    0.004125874 -0.05674508 0.06499683 -0.08896822 0.09721996
## 556    0.004125874 -0.05674755 0.06499930 -0.08897199 0.09722374
## 557    0.004125874 -0.05675002 0.06500176 -0.08897577 0.09722751
## 558    0.004125874 -0.05675248 0.06500423 -0.08897954 0.09723129
## 559    0.004125874 -0.05675495 0.06500670 -0.08898331 0.09723506
## 560    0.004125874 -0.05675742 0.06500917 -0.08898709 0.09723884
## 561    0.004125874 -0.05675989 0.06501164 -0.08899086 0.09724261
## 562    0.004125874 -0.05676236 0.06501410 -0.08899464 0.09724639
## 563    0.004125874 -0.05676482 0.06501657 -0.08899841 0.09725016
## 564    0.004125874 -0.05676729 0.06501904 -0.08900219 0.09725393
## 565    0.004125874 -0.05676976 0.06502151 -0.08900596 0.09725771
## 566    0.004125874 -0.05677223 0.06502397 -0.08900973 0.09726148
## 567    0.004125874 -0.05677469 0.06502644 -0.08901351 0.09726525
## 568    0.004125874 -0.05677716 0.06502891 -0.08901728 0.09726903
## 569    0.004125874 -0.05677963 0.06503138 -0.08902105 0.09727280
## 570    0.004125874 -0.05678209 0.06503384 -0.08902483 0.09727657
## 571    0.004125874 -0.05678456 0.06503631 -0.08902860 0.09728035
## 572    0.004125874 -0.05678703 0.06503878 -0.08903237 0.09728412
## 573    0.004125874 -0.05678949 0.06504124 -0.08903614 0.09728789
## 574    0.004125874 -0.05679196 0.06504371 -0.08903992 0.09729166

8.7.2 Plot

data.ramalan_nvda.da <- ramalan_nvda.da$mean
plot(ramalan_nvda.da, xlab="Periode (Tahun)", col = "green4", lwd = 2.5)

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

pt_1 <- train_nvda.ts[length(train_nvda.ts)] #nilai akhir data latih
hasil.forc.Diff <- data.ramalan_nvda.da
#Transformasi Balik
ramal_nvda <- exp(hasil.forc.Diff)
#Diff inv
ramal_nvda <- diffinv(ramal_nvda, differences = 1) + pt_1

#has.1 sama hasilnta dengan: cumsum(c(pt_1,hasil.forc.Diff))
ts.plot(train_nvda.ts, ramal_nvda, ylab="Saham Harga (USD)",
        xlab="Periode (Tahun)", 
        col = "green4", lwd = 3.5,
        main="Plot Ramal Saham NVIDIA Selama 115 Hari Kedepan")

Dapat dilihat bahwa rata-rata harga saham NVIDA diramalkan akan terus Melonjak naik setiap periodenya.

8.7.3 Perbandingan

perbandingan_nvda.da <- matrix(data=c(head(test_nvda.ts, n=h), ramal_nvda[-1]),
                     nrow = h, ncol = 2)
## Warning in matrix(data = c(head(test_nvda.ts, n = h), ramal_nvda[-1]), nrow =
## h, : data length [172] is not a sub-multiple or multiple of the number of rows
## [115]
colnames(perbandingan_nvda.da) <- c("Aktual","Hasil Forecast")
datatable(perbandingan_nvda.da, filter = 'top', 
          options = list(pageLength = 5))
akurasi.nvda <- accuracy(ts(ramal_nvda[-1]), head(test_nvda.ts, 
                                                  n=length(test_nvda.ts))) %>%
  as.data.frame() %>%
  cbind(Model = ramalan_nvda.da[["method"]]) %>% 
  relocate(Model, .before = 1)
row.names(akurasi.nvda) <- "NVDA"
datatable(akurasi.nvda)

Didapatkan nilai MAPE sebesar \(16.67131\%\) (lebih dari \(10\%\)) yang menandakan bahwa hasil peramalan dari model ARIMA(0,1,1) sudah baik.

9 Perbandingan Antar Saham

9.1 Perbandingan Akurasi

akurasi <- rbind(akurasi.aapl, akurasi.amzn, akurasi.goog, akurasi.meta,
                 akurasi.msft, akurasi.nflx, akurasi.nvda) %>%
  mutate(Keterangan = case_when(
    MAPE < 10 ~ "Sangat Baik",
    MAPE >= 10 & MAPE <= 20 ~ "Baik",
    MAPE > 20 & MAPE <= 50 ~ "Layak",
    MAPE > 50 ~ "Tidak Akurat"
  )) %>% relocate(Keterangan, .before = 1)

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

9.2 Perbandingan Hasil Forcast

9.2.1 Perbandingan Data Train dan Test

chart <-
ggplot(data2, aes(x=Date, y=`Adj Close`, color=Name, alpha=Name)) + #Data
  #Label Data Latih 
  annotate( "rect", alpha=0.1, fill="seagreen",
            xmin=as.Date(min(data2$Date)), 
            xmax=data2$Date[ceiling(0.8 * length(data2$Date)/7)],
            ymin=0, ymax=Inf ) + 
  
  annotate( "text", color="seagreen",
            x = as.Date(data2$Date[ceiling(0.8 * length(data2$Date)/7/2)]), 
            y = max(data2$`Adj Close`) * 0.95, 
    label = "Data Latih\n80%", size=10) + 
  
  #Label Data Uji
  annotate( "rect", alpha=0.1, fill="violetred",
            xmin=data2$Date[ceiling(0.8 * length(data2$Date)/7)], 
            xmax=as.Date(max(data2$Date)),
            ymin=0, ymax=Inf ) + 
  
  annotate( "text", color="violetred",
            x = as.Date(data2$Date[ceiling(0.9 * length(data2$Date)/7)]) , 
            y = max(data2$`Adj Close`) * 0.95, 
    label = "Data Uji\n20%", size=10) +
  
  geom_line(aes(color=Name), linewidth=1.5) + #Timeseries
  #Color
  scale_color_manual(values = c(NVDA="green4", NFLX="firebrick3", 
                                MSFT="deepskyblue2", META="dodgerblue3", 
                                AAPL="lightskyblue4",
                                GOOG="gold3", AMZN="orange2") ) +
  
    scale_alpha_manual(values = c("NVDA" = 1, "NFLX" = 1, "MSFT" = 1, 
                                "META" = 1, "AAPL" = 1, "GOOG" = 1, 
                                "AMZN" = 1)) +
  theme.ts + #THeme
  labs(x = "\nPeriode (Tahun)", y='Harga Saham (USD)',
       title = "Time Series MAANG",
       subtitle = "Pembagian Data Latih dan data Uji\n") +
  # Label / legend
  geom_text_repel(
    data=data2[data2$Date == max(data2$Date),], #Posisi di ujung data
    aes(color = Name, label = Name), #Warna garis & label saham
    size = 8, #Ukuran text
    nudge_x = 20, #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(min(data2$Date)), as.Date("2023-09-28"))
  ) +
    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 = data2$Date[ceiling(0.8 * length(data2$Date)/7)] , 
             linetype = "dotted", color = "black", linewidth = 2) 
            
chart

#Export Chart
ggsave("09_banding_train-test.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 23)

Dari Semua data ujinya memiliki pola yang cenderung tren naik.

9.2.2 Perbandingan Data Hasil Forcast

#Pnggabungan data
data3 <- data.frame(
  Date = data2 %>% dplyr::select(Date)  ,
  `Adj Close` = c(as.vector(train_aapl.ts), ramal_aapl[-1],
                  as.vector(train_amzn.ts), ramal_amzn[-1],
                  as.vector(train_goog.ts), ramal_goog[-1],
                  as.vector(train_meta.ts), ramal_meta[-1],
                  as.vector(train_msft.ts), ramal_msft[-1],
                  as.vector(train_nflx.ts), ramal_nflx[-1],
                  as.vector(train_nvda.ts), ramal_nvda[-1] ),
  Name = rep(c("AAPL", "AMZN", "GOOG", "META", "MSFT", "NFLX", "NVDA"), 
              each = length(train_aapl.ts) + h)
)
colnames(data3) <- c("Date", "Adj Close", "Name")
chart <- 
ggplot(data3, aes(x = Date, y = `Adj Close`, color = Name)) +
  #Label Data Asli 
  annotate( "rect", alpha=0.1, fill="seagreen",
            xmin=as.Date(min(data3$Date)), 
            xmax=as.Date(data3$Date[ceiling(nrow(train_aapl))]),
            ymin=0, ymax=Inf ) + 
  
  annotate( "text", color="seagreen",
            x = as.Date(data3$Date[ceiling(nrow(train_aapl)/2)]), 
            y = max(data3$`Adj Close`) * 0.95, 
    label = "Data Asli", size=10) + 
  
  #Label Data Ramal
  annotate( "rect", alpha=0.1, fill="violetred",
            xmin=as.Date(data3$Date[ceiling(nrow(train_aapl))]), 
            xmax=as.Date(max(data3$Date)),
            ymin=0, ymax=Inf ) + 
  
  annotate( "text", color="violetred",
            x = as.Date(data3$Date[ceiling(0.9 * length(data3$Date)/7)]) , 
            y = max(data3$`Adj Close`) * 0.95, 
    label = "Data Ramal\n115 Hari", size=10) +
  #Time Series
  geom_line(aes(color=Name), linewidth=1.5) +
  #Warna Saham
  scale_color_manual(values = c(NVDA="green4", NFLX="firebrick3", 
                                MSFT="deepskyblue2", META="dodgerblue3", 
                                AAPL="lightskyblue4",
                                GOOG="gold3", AMZN="orange2") ) +
  theme.ts + #THeme
  labs(x = "\nPeriode (Tahun)", y='Harga Saham (USD)',
       title = "Ramalan Saham MAANG",
       subtitle = "Peramalan Saham MAANG Selama 115 Hari Kedepan\n") +
  # Label / legend
  geom_text_repel(
    data=data3[data3$Date == max(data3$Date),], #Posisi di ujung data
    aes(color = Name, label = Name), #Warna garis & label saham
    size = 8, #Ukuran text
    nudge_x = 20, #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(min(data3$Date)), 
               as.Date(max(data3$Date)) + 60)
  ) +
    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.Date(data3$Date[ceiling(nrow(train_aapl))]) , 
             linetype = "dotted", color = "black", linewidth = 2)
chart

#Export Chart
ggsave("09_banding_ramal.png", chart, path = export.chart,
        dpi = 300, height = 12, width = 20)