1 Introduction

Kali ini kami akan mencoba menganalisis dan memberikan model prediksi harga saham mingguan menggunakan dataset Time Series dari Saham S&P 500. Dataset ini kami dapatkan melalui Kagle dengan rentang waktu mulai dari 23 November 2015 - 20 November 2020. Perlu diingat bahwa harga saham itu bersifat fluktuatif untuk pergerakkannya, jadi sulit sekali untuk mendapatkan model terbaik karena banyak faktor yang berpengaruh didalamnya.

Tujuan : Melalui model sederhana ini kami akan mencoba melakukan prediksi harga saham untuk 7 hari kedepan

2 Data Preprocess

Pertama, kami akan menyimpan dataset yang dibutuhkan kedalam objek stock menggunakan fungsi read.csv dari R dan menampilkan 6 data teratas dari dataframe menggunakan fungsi head() untuk melihat data yang dimiliki.

2.1 Table Preview

stock <- read.csv("data input/yahoo_stock.csv")
head(stock)

Deskripsi kolom:

  • Date : Tanggal trading
  • High : Harga tertinggi
  • Low : Harga terendah
  • Open : Harga saat transaksi saham dibuka
  • Close : Harga saat transaksi saham telah ditutup
  • Volume : Jumlah total aktivitas perdagangan
  • Adj.Close : Nilai yang disesuaikan menjadi faktor dalam aksi korporasi seperti dividen, stock split, dan penerbitan saham baru.

Kemudian kami perlu melihat struktur data untuk melihat jumlah data, kolom yang ada, hingga tipe data dari setiap kolom. Apakah diperlukan penyesuaian atau tidak, menggunakan fungsi glimpse() yang ada pada library dplyr.

glimpse(stock)
## Rows: 1,825
## Columns: 7
## $ Date      <chr> "2015-11-23", "2015-11-24", "2015-11-25", "2015-11-26", "201…
## $ High      <dbl> 2095.61, 2094.12, 2093.00, 2093.00, 2093.29, 2093.29, 2093.2…
## $ Low       <dbl> 2081.39, 2070.29, 2086.30, 2086.30, 2084.13, 2084.13, 2084.1…
## $ Open      <dbl> 2089.41, 2084.42, 2089.30, 2089.30, 2088.82, 2088.82, 2088.8…
## $ Close     <dbl> 2086.59, 2089.14, 2088.87, 2088.87, 2090.11, 2090.11, 2090.1…
## $ Volume    <dbl> 3587980000, 3884930000, 2852940000, 2852940000, 1466840000, …
## $ Adj.Close <dbl> 2086.59, 2089.14, 2088.87, 2088.87, 2090.11, 2090.11, 2090.1…

Terlihat bahwa kolom Date belum bertipe data date oleh karena itu kami perlu untuk memperbaiki tipe data tersebut. Selain itu juga kita hanya menggunakan kolom Date dan Open untuk analisis kita, kami memilih kolom Open karena ini menjadi nilai harga kumulatif saham sebelum terjadinya transaksi di hari tersebut. Kita juga malakukan arrange() dan padding time series mengunakan fungsi pad () untuk memastikan data waktu tidak ada yang terlewat ataupun kosong.

stock_clean <- stock %>% 
  mutate(Date = ymd(Date)) %>% 
  select(Date, Open) %>% 
  arrange() %>% 
  pad()

3 Model Fitting and Evaluation

Tujuan dari dilakukannya Model Fitting dan Evaluation pada data time series adalah untuk membangun model prediksi yang akurat dan menguji sejauh mana model tersebut dapat memprediksi nilai-nilai masa depan dengan baik. Langkah ini penting dalam analisis time series karena membantu memahami performa model dan mengidentifikasi apakah model tersebut dapat diandalkan untuk melakukan prediksi masa depan.

3.1 Time Series Object

Pertama kami akan membuat objek time series yang akan disimpan pada objek stock_ts

# simpan dalam object stock_ts
stock_ts <- ts(data = stock_clean$Open, # yang ditinjau adalah kolomnya 
               frequency = 7 ) # perulangan yang ingin ditinjau mingguan
stock_ts %>% autoplot()

Dilanjutkan dengan proses decomposition pada objek TS. Tujuannya untuk menguraikan tipe-tipe data pada setiap komponen time series yang ada agar tepat dalam penentuan pemilihan model untuk forecast nya.

stock_decom <- stock_ts %>% decompose(type = "multiplicative")
stock_decom %>% autoplot()

3.2 Spliting Data

Setelah itu kami akan melakukan cross-validation dengan aturan yang sudah di identifikasi sebelumnya yakni dengan menggunakan fungsi head() dan tail() pada objek time series yang sudah dibuat

  • Data train (data untuk model): data real di tahun 2015 - 2020 tanpa satu minggu terakhir yang di simpan kedalam object stock_train
  • Data test (unseen data) : data seminggu terakhir yang disimpan dengan kedalam object stock_test
# test menggunakan `tail()`
stock_test <- tail(stock_ts,7)
range(stock_clean$Date)
## [1] "2015-11-23" "2020-11-20"
# train menggunakan `head()`
stock_train <- head(stock_ts,-7)

3.3 Holt’s Winters Model

Pertama tentunya kami akan membuat model Holt’s Winters terlebih dahulu

hw_model <- HoltWinters(stock_train) # Membuat model 

Kemudian kami ingin meramalkan dan mengevaluasi model dengan beberapa kondisi:

  • Gunakan fungsi forecast() untuk forcasting data mingguan

  • Pastikan bahwa forcast_hw sebagai vector sebelum melakukan evaluasi model

forcast_hw <- forecast(stock_train, h = 7) # Melakukan forecasting
stock_train %>% 
  autoplot() + 
  autolayer(forcast_hw$fitted, series = "Fitted Data") +
  autolayer(forcast_hw$mean, series = "Forecast") +
  autolayer(stock_test, series = "Test Data") # Membuat visualisasi

# Melakukan evaluasi model
hw_forcast <- as.vector(forcast_hw$mean)
hw_acc <- accuracy(hw_forcast,stock_test)
hw_acc
##                ME    RMSE      MAE       MPE     MAPE      ACF1 Theil's U
## Test set 28.34609 37.6122 28.34666 0.7868607 0.786877 0.2580653  1.334341

Didapatkan MAE yang cukup besar yakni di angka 28.3%

3.4 Arima Model

Pertama tentunya kami akan membuat model Arima terlebih dahulu

# Membuat model
arima_model <- stlm(stock_train, method="arima")

Kemudian kami ingin meramalkan dan mengevaluasi model dengan beberapa kondisi:

  • Gunakan fungsi forecast() untuk forcasting data mingguan

  • Pastikan bahwa forcast_arima sebagai vector sebelum melakukan evaluasi model

forcast_arima <- forecast(arima_model, h=7) # Melakukan forecasting
stock_train %>% 
  autoplot() + 
  autolayer(arima_model$fitted, series = "Fitted Data") +
  autolayer(forcast_arima$mean, series = "Forecast") +
  autolayer(stock_test, series = "Test Data") # Visualisasi

# Melakukan evaluasi model
arima_forcast <- as.vector(forcast_arima$mean)
arima_acc <- accuracy(arima_forcast,stock_test)
arima_acc
##                ME     RMSE      MAE       MPE      MAPE      ACF1 Theil's U
## Test set 27.84687 35.21841 28.22594 0.7736397 0.7843101 0.3387263   1.24784

Didapatkan MAE yang cukup besar yakni di angka 28.2%

3.5 STLM Model

Pertama tentunya kami akan membuat model STLM terlebih dahulu

stlm_model <- stock_train %>% 
              stlm(lambda = NULL) %>% 
              forecast(h=7*2) # Membuat model dan forecasting
stock_train %>% 
  autoplot() + 
  autolayer(stlm_model$fitted, series = "Fitted Data") +
  autolayer(stlm_model$mean, series = "Forecast") +
  autolayer(stock_test, series = "Test Data") # Membuat visualisasi

Kemudian kami ingin meramalkan dan mengevaluasi model dengan beberapa kondisi:

  • Pastikan bahwa stlm_model sebagai vector sebelum melakukan evaluasi model

  • Melakukan evaluasi model menggunakan fungsi accuracy() dan memasukannya pada objek stlm_acc

# Melakukan evaluasi model
stlm_forcast <- as.vector(stlm_model$mean)
stlm_acc <- accuracy(stlm_forcast,stock_test)
stlm_acc 
##                ME     RMSE      MAE       MPE      MAPE      ACF1 Theil's U
## Test set 24.08308 31.48037 24.38284 0.6687468 0.6771844 0.3135758  1.115124

Didapatkan MAE cukup kecil model sebelumnya 24.3%

3.6 TBATS Model

Pertama tentunya kami akan membuat model TBATS terlebih dahulu

  • Gunakan fungsi forecast() untuk forcasting data mingguan
# Membuat model dan forecasting
log_tbats <- stock_train %>% 
           log() %>% 
           tbats(use.box.cox = NULL, 
                 use.trend = NULL,
                 use.damped.trend = NULL)

tbats_model <- forecast(log_tbats, h=7)
plot(tbats_model) # Visualisasi

Kemudian kami ingin mengevaluasi model dengan beberapa kondisi:

  • Pastikan bahwa tbats_model sebagai vector sebelum melakukan evaluasi model
# Melakukan evaluasi model
tbats_forcast <- as.vector(exp(tbats_model$mean))
tbats_acc <- accuracy(tbats_forcast,stock_test)
tbats_acc
##                ME     RMSE      MAE       MPE      MAPE      ACF1 Theil's U
## Test set 28.56128 37.77464 28.56128 0.7928705 0.7928705 0.2580653  1.340112

Didapatkan MAE yang cukup besar yakni di angka 28.5%

3.7 Compare Multiple Model

Setelah melakukan model fitting dan evaluation menggunakan fungsi accuracy() maka didapatkan hasil evaluasi model sebagai berikut, dimana kami fokus pada nilai MAE yang dihasilkan disetiap modelnya:

MAE_model <- data.frame(Model = c("Holt’s Winters", "Arima","STML", "TBATS"),
                   MAE = c(28.3, 28.2, 24.3, 28.5)) # Membuat dataframe untuk nilai MAE
MAE_model

Maka didapatkan model STML sebagai model terbaik dengan MAE sebesar 24.3

4 Assumption Checking

4.1 No-Autocorrelation for residuals

Untuk mengecek ada/tidaknya autokorelasi pada hasil forecasting time series bisa menggunakan uji Ljung-box dengan menggunakan fungsi Box.test(residual model, type = "Ljung-Box") yang akan menghasilkan sebuah nilai p-value. Hipotesis yang digunakan yaitu:

  • H0: residual has no-autocorrelation

  • H1: residual has autocorrelation

yang diinginkan p-value > 0.05 (alpha), no-autocorrelation

# menggunakan Ljung-Box test
Box.test(stlm_model$residuals, type = "Ljung-Box")
## 
##  Box-Ljung test
## 
## data:  stlm_model$residuals
## X-squared = 0.016156, df = 1, p-value = 0.8989

p-value > 0.05, maka gagal tolak H0 (residual no-autocorrelation), artinya tidak adanya autokorelasi pada hasil forecasting

4.2 Normality of residuals

Untuk mengecek normality residual pada hasil forecasting time series kami bisa melakukan uji normality (shapiro test) dengan menggunakan fungsi shapiro.test(residual model)

  • H0: residual menyebar normal

  • H1: residual tidak menyebar normal

yang diinginkan p-value > 0.05 (alpha), residual menyebar normal

shapiro.test(stlm_model$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  stlm_model$residuals
## W = 0.84065, p-value < 2.2e-16

p-value < 0,05 (alpha), maka tolak H0 (residual tidak menyebar normal). Sehingga asumsi residual tidak terpenuhi yang mengartikan bahwa residual tidak menyebar secara normal, hal ini tentu saja disebabkan karena harga saham bersifat fluktuatif dan banyak sekali faktor yang mempengaruhi nilai saham tersebut.

5 Conclusion

Memalui analisis time series sederhana ini didapakan model STLM menjadi model dengan MAE terkecil yakni berada di nilai 24.3%. Namun hal ini tentunya belum cukup untuk dijadikan tools bagi trader dalam mengambil keputusan pada market. Karena tujuan projek ini hanyalah untuk pembelajaran pertama kami dalam melakukan analisis time series. Terimakasih dan Semoga Bermanfaat