Tujuan

❓Tujuan dari laporan ini ialah untuk analisis dan prediksi harga minyak dunia sebagai rangkaian proses seleksi project Data Science Intern di KALLA GROUP

Eksplorasi Data (EDA)

Pengenalan Dataset

data <- read.csv("data_input/Copy of brentcrudeoil - dailybrentoil.csv")
data$Date <- as.POSIXct(data$Date, format="%m/%d/%Y %H:%M:%S") # Mengubah format kolom "Date" menjadi DateTime
data <- data[, -c(8:10)] 
glimpse(data)
Rows: 759
Columns: 7
$ Date       <dttm> 2021-01-04 23:58:00, 2021-01-05 23:58:00, 2021-01-06 23:58…
$ Close      <dbl> 50.23, 51.87, 52.02, 52.20, 53.33, 53.33, 54.12, 54.13, 54.…
$ chg.close. <dbl> 50.23, 1.64, 0.15, 0.18, 1.13, 0.00, 0.79, 0.01, 0.30, -0.9…
$ Low        <dbl> 49.97, 50.01, 51.21, 51.89, 52.31, 52.66, 53.35, 53.75, 53.…
$ chg.low.   <dbl> 49.97, 0.04, 1.20, 0.68, 0.42, 0.35, 0.69, 0.40, -0.07, -0.…
$ High       <dbl> 51.88, 52.26, 52.37, 52.34, 53.61, 53.48, 54.23, 54.82, 54.…
$ chg.high.  <dbl> 51.88, 0.38, 0.11, -0.03, 1.27, -0.13, 0.75, 0.59, -0.26, -…
  • Metadata dari dataset tersebut adalah sebagai berikut :

  • Date : Tanggal data dalam format “YYYY-MM-DD HH:MM:SS”.

  • Close : Harga penutupan.

  • chg.close. : Perubahan harga penutupan.

  • Low : Harga terendah.

  • chg.low. : Perubahan harga terendah.

  • High : Harga tertinggi.

  • chg.high. : Perubahan harga tertinggi.

Analisis Statistik deskriptif Awal

# Ubah tipe data
data$Date <- as.Date(data$Date) 
summary(data)
      Date                Close          chg.close.             Low        
 Min.   :2021-01-04   Min.   : 50.23   Min.   :-17.14000   Min.   : 49.97  
 1st Qu.:2021-10-04   1st Qu.: 72.44   1st Qu.: -0.80000   1st Qu.: 71.48  
 Median :2022-07-07   Median : 79.82   Median :  0.21000   Median : 78.76  
 Mean   :2022-07-06   Mean   : 80.31   Mean   :  0.09999   Mean   : 79.18  
 3rd Qu.:2023-04-08   3rd Qu.: 88.20   3rd Qu.:  1.08000   3rd Qu.: 87.23  
 Max.   :2024-01-10   Max.   :114.19   Max.   : 50.23000   Max.   :113.39  
    chg.low.              High          chg.high.       
 Min.   :-13.99000   Min.   : 51.88   Min.   :-18.0500  
 1st Qu.: -0.68000   1st Qu.: 73.44   1st Qu.: -0.5750  
 Median :  0.14000   Median : 80.75   Median :  0.1600  
 Mean   :  0.09978   Mean   : 81.37   Mean   :  0.1024  
 3rd Qu.:  0.99500   3rd Qu.: 90.33   3rd Qu.:  0.8500  
 Max.   : 49.97000   Max.   :115.06   Max.   : 51.8800  

đź’ˇ Insight :

  • Dataset ini mencakup rentang waktu mulai dari 4 Januari 2021 hingga 10 Januari 2024
  • Harga penutupan (Close) berkisar antara 50.23 hingga 114.19 dengan rata-rata harga closing sekitar 80.31
  • Perubahan harga penutupan (chg.close) memiliki nilai minimum -17.14 dan maksimum 50.23, dengan rata-rata perubahan harga closing sekitar 0.1
  • Harga terendah (Low) berkisar antara 49.97 hingga 113.39, dengan rata-rata harga terendah berkisar 79.18
  • Perubahan Harga Terendah (chg.low) memiliki nilai minimum -13.99 dan maksimum 49.97 dengan rata-rata sekitar 0.10
  • Harga Tertinggi (High) berkisar antara 51.88 hingga 115.06, dengan rata-rata harga tertinggi sekitar 81.37
  • Perubahan Harga Tertinggi (chg.high) memiliki nilai minimum -18.05 dan maksimum 51.88

Visual Time Series Awal

Sebelum masuk tahapan selanjutnya, cek apakah ada missing value atau tidak

colSums(is.na(data))
      Date      Close chg.close.        Low   chg.low.       High  chg.high. 
         0          0          0          0          0          0          0 

Tidak ada Missing Value.

oil_data <- arrange(data, Date)
head(oil_data)
# Pembuatan Data Time Series
oil_ts <- ts(oil_data$Close, frequency = 1)

plot(oil_ts, main = "Time Series Plot : Harga Penutupan Minyak")

Dalam contoh ini, saya menggunakan frekuensi 1 karena menggunakan tipe data harian. Berdasarkan plot diatas data memiliki trend dan teramsuk multiplikatif, pola musiman dalam data sulit diidentifikasi, sehingga analisa lanjutan yang tepat ialah menggunakan model ARIMA. Namun, ada beberapa yang perlu diperhatikan :

  • Meskipun pola musiman tidak terlihat dalam plot, tetap ada kemungkinan bahwa ada fluktuasi musiman yang lebih subtil dalam data yang tidak terlihat secara kasat mata.
  • Perlu dilakukan lebih banyak analisis dan eksplorasi data untuk memastikan apakah benar-benar tidak ada pola musiman yang signifikan dalam data.

Untuk kasus ini, kita abaikan pola musiman yang tidak signifikan, karena tujuan kali ini ialah hanya untuk forecasting.

Analisis Time Series (ARIMA)

đź’ˇ Pendekatan yang tepat dalam kasus ini adalah menggunakan model ARIMA untuk melakukan analisis dan prediksi. Model ARIMA dapat membantu mengidentifikasi pola, tren, dan fluktuasi dalam data time series. Dengan mempertimbangkan ketidakadaan pola musiman yang jelas dalam data harian

# Menghitung mean dan varians
mean_ts <- mean(oil_ts)
var_ts <- var(oil_ts)
cat("Mean:", mean_ts, "\n")
Mean: 80.30797 
cat("Variance:", var_ts, "\n")
Variance: 151.8757 
  • Syarat agar data dapat diolah menggunakan ARIMA ialah datanya harus bersifat stasioner, maka perlu di lakukan tes menggunakan ADF Test.
# Menggunakan library "tseries"
library(tseries)

# Melakukan ADF test
adf_test <- adf.test(oil_ts)
cat("ADF Test Results:\n")
ADF Test Results:
print(adf_test)

    Augmented Dickey-Fuller Test

data:  oil_ts
Dickey-Fuller = -1.8845, Lag order = 9, p-value = 0.6272
alternative hypothesis: stationary

Hasil uji ADF menunjukkan bahwa nilai p adalah 0.62, yang lebih besar dari tingkat signifikansi 0.05. Oleh karena itu, kita gagal menolak hipotesis nol bahwa data tidak stasioner. Ini menunjukkan bahwa kemungkinan data tersebut tidak stasioner.

Differencing

  • Untuk membuat data menjadi stasioner, kita dapat menggunakan differencing. Hal ini dilakukan agar ketika melakukan prediksi tidak ada multicolinearity terhadap data-data sebelumnya.
# differencing 1 kali
oil_ts %>% 
  diff() %>% 
  adf.test()

    Augmented Dickey-Fuller Test

data:  .
Dickey-Fuller = -10.307, Lag order = 9, p-value = 0.01
alternative hypothesis: stationary

đź’ˇ Berdasarkan hasil uji ADF, nilai p-value sebesar 0.01 yang artinya data termasuk stasioner.

ARIMA (p, 1, q)

Model Auto ARIMA

oil_auto <- auto.arima(oil_ts)
oil_auto
Series: oil_ts 
ARIMA(0,1,2) 

Coefficients:
          ma1      ma2
      -0.1102  -0.1327
s.e.   0.0360   0.0360

sigma^2 = 3.989:  log likelihood = -1598.9
AIC=3203.81   AICc=3203.84   BIC=3217.7

Evaluasi Model

Setelah melakukan fitting model ARIMA, langkah selanjutnya adalah melakukan evaluasi kualitas model. Pada bagian ini, kita akan menggunakan fungsi accuracy() dari package forecast untuk melihat MAPE

accuracy(oil_auto$fitted, oil_ts)
                 ME     RMSE      MAE        MPE     MAPE        ACF1 Theil's U
Test set 0.04486349 1.993199 1.317777 0.03854151 1.608936 0.005880479 0.9912048
library(MLmetrics)
MAPE(y_pred = oil_auto$fitted, 
     y_true = oil_ts)*100
[1] 1.608936

đź’ˇ Hasil MAPE sebesar 1.608936 menunjukkan bahwa rata-rata persentase kesalahan dalam prediksi harga minyak adalah sekitar1.6%. Semakin rendah nilai MAPE, semakin baik kualitas prediksi.

Visualisasi Forecasting

Langkah selanjutnya adalah melakukan visualisasi dengan memperbarui jendela waktu menggunakan data bulan terakhir. Model ARIMA dibangun menggunakan data bulan terakhir untuk membuat prediksi.

Forecasting dengan Data Tahun Terakhir

  • Pertama, kita akan memperbarui jendela waktu dengan menggunakan data Tahun terakhir. Hal ini dilakukan untuk membangun model ARIMA dengan menggunakan data terbaru dan melakukan prediksi untuk periode ke depan.
# Memperbarui window dengan data tahun terakhir
oil_ts_last_year <- tail(oil_ts, 260)  # jumlah hari kerja dalam setahun

# Membuat model ARIMA dengan data tahun terakhir
model_last_year <- auto.arima(oil_ts_last_year)

# Plot time series dan fitted values
autoplot(oil_ts_last_year) +
  autolayer(fitted(model_last_year), lwd = 0.7) +
  labs(x = "Tanggal", y = "Harga Minyak", title = "Time Series Plot dengan Fitted Values") +
  temaku +
  scale_y_continuous(limits = c(0, max(oil_ts_last_year, na.rm = TRUE) * 1.1))

Selanjutnya, data dibagi menjadi data training (sebagian besar data asli) dan data testing (30 data terakhir) untuk evaluasi model. Data training diuji menggunakan uji ADF untuk memastikan bahwa data stasioner.

data_train <- head(oil_ts, n = length(oil_ts) - 30)  # Data train tidak termasuk data test terakhir
data_test <- tail(oil_ts, n = 30)  # Data test terakhir
data_train %>% adf.test()

    Augmented Dickey-Fuller Test

data:  .
Dickey-Fuller = -1.9312, Lag order = 8, p-value = 0.6074
alternative hypothesis: stationary
data_train %>% 
  diff(lag = 1, differences = 1) %>% 
  adf.test()

    Augmented Dickey-Fuller Test

data:  .
Dickey-Fuller = -10.188, Lag order = 8, p-value = 0.01
alternative hypothesis: stationary
train_auto_arima <- auto.arima(data_train)
train_auto_arima
Series: data_train 
ARIMA(1,1,1) 

Coefficients:
         ar1      ma1
      0.6257  -0.7555
s.e.  0.1053   0.0879

sigma^2 = 4.054:  log likelihood = -1541.55
AIC=3089.09   AICc=3089.12   BIC=3102.86

Forecasting untuk Periode ke Depan

Selanjutnya, kita akan melakukan forecasting harga Minyak untuk periode ke depan. Kita akan menggunakan model ARIMA yang telah dibangun sebelumnya untuk melakukan prediksi selama 30 hari ke depan.

forecast <- forecast(train_auto_arima, h =45)
# Visualisasi
autoplot(oil_ts) +
  autolayer(fitted(train_auto_arima), series = "Fitted Data") +
  autolayer(forecast, series = "Forecast") +
  autolayer(data_test, series = "Test Data") +
  labs(x = "Waktu", y = "Harga Minyak", title = "Forecasting Harga Minyak Dunia") +
  scale_y_continuous(limits = c(0, max(oil_ts, na.rm = TRUE) * 1.1)) +
  temaku

Grafik tersebut menampilkan prediksi harga Minyak dunia selama 30 hari ke depan berdasarkan model ARIMA yang telah dibangun. Garis biru merupakan prediksi harga Minyak dunia, sedangkan area hijau menggambarkan interval prediksi.

Dengan melakukan forecasting, kita dapat memperoleh informasi tentang kemungkinan pergerakan harga Minyak dunia di masa mendatang. Namun, perlu diingat bahwa prediksi ini masih bersifat perkiraan dan dapat dipengaruhi oleh banyak faktor eksternal.

Model ML (LSTM)

Bagian ini menggunakan LSTM bertujuan untuk melakukan prediksi harga minyak menggunakan pendekatan deep learning. Normalisasi dilakukan untuk memastikan bahwa nilai-nilai dalam data berada dalam skala yang sama.

library(tensorflow)
library(keras)

# Persiapkan data
oil_data <- arrange(data, Date)
oil_ts <- ts(oil_data$Close, frequency = 1)

# Normalisasi data
normalized_data <- scale(oil_ts)

# Pembagian data training dan testing
train_size <- floor(length(normalized_data) * 0.8)
train_data <- normalized_data[1:train_size]
test_data <- normalized_data[(train_size + 1):length(normalized_data)]

Pembuatan Model

# Definisi model
model <- keras_model_sequential() %>%
  layer_lstm(units = 128, activation = 'relu', input_shape = c(1, 1)) %>%
  layer_dense(units = 64, activation = 'relu') %>% 
  layer_dense(units = 32, activation = 'relu') %>% 
  layer_dense(units = 1)

# Compile model
model %>% compile(
  loss = 'mean_squared_error',
  optimizer = optimizer_adam()
)

Evaluasi Model LSTM

Setelah model dilatih, dilakukan prediksi terhadap data test dan hasilnya dinormalisasi kembali untuk mendapatkan prediksi dalam skala asli data.

# Fungsi untuk menghitung metrik evaluasi
hitung_metrik <- function(y_true, y_pred) {
  metrics <- data.frame(
    MAPE = MAPE(y_true = y_true, y_pred = y_pred),
    MSE = MSE(y_true = y_true, y_pred = y_pred),
    RMSE = RMSE(y_true = y_true, y_pred = y_pred),
    MAE = MAE(y_true = y_true, y_pred = y_pred)
  )
  return(metrics)
}

# Contoh penggunaan fungsi
metrik_hasil <- hitung_metrik(y_true = oil_data$Close[(train_size + 1):length(oil_data$Close)], y_pred = predicted_values)

# Menampilkan hasil metrik dalam bentuk dataframe
print(metrik_hasil)
          MAPE          MSE       RMSE        MAE
1 0.0002822752 0.0008663908 0.02943452 0.02248515

Forecasting

# Membuat dataframe dari hasil prediksi
hasil_prediksi_df <- data.frame(
  Tanggal = seq(Sys.Date() + 1, by = "days", length.out = days_to_predict),
  Prediksi_Harga_Minyak = predicted_values_future
)

# Menampilkan dataframe hasil prediksi
print(hasil_prediksi_df)
      Tanggal Prediksi_Harga_Minyak
1  2024-01-14              75.96765
2  2024-01-15              76.04511
3  2024-01-16              76.12223
4  2024-01-17              76.19780
5  2024-01-18              76.27145
6  2024-01-19              76.33994
7  2024-01-20              76.40359
8  2024-01-21              76.46273
9  2024-01-22              76.51765
10 2024-01-23              76.56863
11 2024-01-24              76.61516
12 2024-01-25              76.65723
13 2024-01-26              76.69526
14 2024-01-27              76.72963
15 2024-01-28              76.76069
# Plot prediksi masa depan dengan Plotly
library(plotly)

# Membuat dataframe untuk plot
future_plot <- data.frame(Days = 1:(length(oil_ts) + days_to_predict),
                          Price = c(oil_ts, rep(NA, days_to_predict)),
                          Predicted_Price = c(rep(NA, length(oil_ts)), predicted_values_future))

# Membuat plot interaktif menggunakan Plotly
plot_ly(data = future_plot, type = 'scatter', mode = 'lines') %>%
  add_trace(x = ~Days, y = ~Price, name = 'Harga Minyak', line = list(color = 'black', width = 1)) %>%
  add_trace(x = ~Days, y = ~Predicted_Price, name = 'Prediksi Harga Minyak', line = list(color = 'red', width = 1.5, dash = 'solid')) %>%
  layout(title = 'Prediksi Harga Minyak 15 Hari ke Depan',
         xaxis = list(title = 'Hari'),
         yaxis = list(title = 'Harga Minyak'))

Penutup

Dalam laporan ini, telah dilakukan analisis time series untuk kasus data harga Minyak Dunia. Berdasarkan hasil analisis, ditemukan beberapa insight penting tentang pola dan tren harga Minyak. Terdapat perbandingan antara model ARIMA dan LSTM dalam meramalkan harga minyak. Evaluasi model LSTM menghasilkan performa yang sangat baik dengan MAPE sebesar 0.00395825 sebaliknya, model ARIMA memiliki nilai MAPE sebesar 1.608936, menunjukkan tingkat kesalahan yang lebih tinggi dibandingkan dengan LSTM.

Kedua model telah dibangun dan dievaluasi untuk melakukan prediksi harga Minyak ke depan. Prediksi ini dapat memberikan gambaran tentang kemungkinan pergerakan harga Minyak di masa mendatang, namun tetap perlu diperhatikan bahwa prediksi ini masih memiliki tingkat ketidakpastian.

Dalam analisis lanjutan, dapat dilakukan pengembangan lebih lanjut seperti eksplorasi pola musiman yang lebih detail, pengujian model dengan metrik lain, atau penggunaan model lainnya…