Kestasioneran Data Deret Waktu pada Data Minyak Mentah WTI

Package

Terdapat 6 packages yang digunakan, yaitu:

readxl, TTR, TSA, tseries, graphics, dan forecast

Data

Harga Minyak Mentah WTI (West Texas Index Crude Oil Price)

AlMadi dan Zhang (2011), Pasar minyak mentah dunia memiliki 4 tolak ukur (benchmark) internasional utama yang digunakan untuk penetapan harga minyak mentah lainnya, yaitu 2 di West - West Texas Intermediate (WTI) di AS dan Brent di Eropa, dan 2 di Asia - Dubai dan Oman. Benchmark digunakan untuk menentukan harga ekspor minyak mentah setelah melakukan penyesuaian terkait perbedaan kualitas dan lokasi.

Deskripsi Data dan Time Series Plot

Data yang digunakan dalam pemodelan deret waktu ini adalah sebanyak 128 amatan yaitu Harga Minyak WTI untuk January 2012 hingga Agustus 2022 dengan periode pengamatan bulanan. Dengan Time Series Plot sebagai berikut:

data <- read_excel("D:/MPDW/WTI Crude Oil (2).xlsx", sheet = 2)
head(data)
## # A tibble: 6 x 1
##   Terakhir
##      <dbl>
## 1     98.5
## 2    107. 
## 3    103. 
## 4    105. 
## 5     86.5
## 6     85.0
ts.dt <- ts(data)
ts.plot(ts.dt, xlab = "Time Period", ylab = "Crude Oil Prices",
        main = "Time Series Plot of WTI Crude Oil Prices")

Pergerakan harga minyak mentah cenderung nonstasioner serta dipengaruhi oleh banyak faktor. Berbagai metode peramalan dapat memberikan hasil yang baik jika deretan harga yang terbentuk merepresentasikan fungsi yang cenderung linier. Namun, fluktuasi harga riil minyak mentah cenderung memiliki karakteristik nonlinier dan nonstasioner. Hal ini disebabkan oleh kompleksitas intrinsik dari pasar minyak (Herawati dan Djunaidy 2014).

Eksplorasi Data

par(mfrow = c(2,2))
ts.plot(ts.dt[1:30,], xlab = "Time Period", ylab = "Crude Oil Prices",
        main = "Time Series Plot of WTI Crude Oil Prices ", sub = "(Januari 2012 - June 2014)")

ts.plot(ts.dt[31:96,], xlab = "Time Period", ylab = "Crude Oil Prices",
        main = "Time Series Plot of WTI Crude Oil Prices", sub = "(Juli 2014 - Desember 2019)")
ts.plot(ts.dt[97:128,], xlab = "Time Period", ylab = "Crude Oil Prices",
        main = "Time Series Plot of WTI Crude Oil Prices", sub = "(Januari 2020 - Agustus 2022)")

Berdasarkan plot time series di atas, terlihat bahwa data merupakan data gabungan stasioner dan trend naik di akhir periode.

Terlihat pula dari ketiga plot diatas bahwa harga minyak WTI berfluktuatif. Seperti yang ditunjukkan pada plot untuk periode waktu Juli 2014-Desember 2019, dimana pada awal periode terjadi penurunan yang begitu signifikan. Lonjakan pasokan minyak dan minimnya permintaan merupakan faktor utama di belakang kejatuhan harga minyak semenjak pertengahan 2014. Ditambah lagi bangkitnya minyak shale dari Amerika Serikat dan juga penolakan OPEC untuk menurunkan produksinya. Selain itu pada awal tahun 2016 juga terjadi penurunan, dimana pada Februari 2016 harga minyak WTI hanya sebesar 33.75 USD. Yang mana jika dibandingkan sejak Juli 2014, di mana harga minyak berada di puncaknya, nilai ini sudah jatuh 70 persen (Bareksa.com)

Dan pada plot untuk periode waktu Januari 2020-Agustus 2022, dimana masa pandemic yang ikut memengaruhi harga minyak WTI. Menurut Widyastuti N L dan Nugroho Hanan (Juni 2020), yaitu Permintaan minyak mentah yang sudah mulai terjadi pada kuartal pertama tahun 2020, akan terus menurun hingga mencapai titik terbawahnya pada akhir kuartal ke-2, kemudian diperkirakan naik lagi dan mencapai titik keseimbangannya dengan pasokan (supply) minyak bumi pada akhir kuartal ke-3 tahun 2020. Dalam masa penurunan permintaan tersebut, minyak yang dikonsumsi akan berkurang hingga lebih 10 juta barel per hari, atau bahkan 15-20 juta barel per hari. Atau sekitar 20%-30% menurut beberapa analisis yang lain. Produksi minyak mentah tidak mungkin bisa diturunkan seketika, dalam masa penurunan permintaan yang tajam tersebut akan terbentuk stock minyak yang cukup besar. Hal ini membuat harga minyak turun.

Namun turunnya harga minyak bukan saja karena dampak Covid-19, tapi juga didorong oleh “pertikaian” (conflict) dalam industri minyak sendiri. Pertikaian, khususnya dalam kelompok produsen, diawali oleh Saudi Arabia dan Rusia, menyangkut kesepakatan mengenai berapa jumlah minyak mentah yang seharusnya diproduksi.

Smoothing (Pemulusan)

Splitting Data

#SPLIT data 80:20
train <- data[1:102,]
test <- data[103:128,]

train.ts <- ts(train)
test.ts <- ts(test)
par(mfrow = c(1,2))
ts.plot(train.ts, xlab = "Time Period", ylab = "Crude Oil Prices",
        main = "Time Series Plot of Data Training")
ts.plot(test.ts, xlab = "Time Period", ylab = "Crude Oil Prices",
        main = "Time Series Plot of Data Testing")

Double Moving Average

Pola data yang cenderung menunjukkan pola trend, sehingga untuk pemulusan digunakan Double Moving Average(DMA).

Penentuan n optimum

Dalam pemulusan dengan menggunakan Double Moving Average perlu ditentukan nilai n optimum, agar model ini menjadi model yang baik, ditunjukkan dengan ukuran keakuratan seperti SSE, MSE, RMSE, MAD, atau MAPE yang minimum

iterasi_dma <- function(x,min,max,metode=c("SSE","MSE","RMSE","MAD","MAPE")){
  df.master <- data.frame()
  z <- max-min+1
  temp <- sqrt(z)
  a <- round(temp) 
  b=a
  if(a*b<z){
    b=b+1
  }
  par(mfrow=c(a,b))
  for(i in min:max) {
    df_ts_sma <- TTR::SMA(x,  n=i)
    df_ts_dma <- TTR::SMA(df_ts_sma, n=i)
    At <- 2*df_ts_sma-df_ts_dma
    Bt <- df_ts_sma-df_ts_dma
    pemulusan_dma <- At+Bt
    ramal_dma <- c(NA, pemulusan_dma)
    df_dma <- cbind(df_aktual=c(x,NA), pemulusan_dma=c(pemulusan_dma,NA), ramal_dma)
    error.dma <- df_dma[, 1] - df_dma[, 3]
    SSE.dma <- sum(error.dma^2, na.rm = T)
    MSE.dma <- mean(error.dma^2, na.rm = T)
    RMSE.dma <- sqrt(mean(error.dma^2, na.rm = T))
    MAD.dma <- mean(abs(error.dma), na.rm = T)
    r.error.dma <- (error.dma/df_dma[, 1])*100 
    MAPE.dma <- mean(abs(r.error.dma), na.rm = T)
    ak <- data.frame(n=i,SSE=SSE.dma,MSE=MSE.dma,RMSE=RMSE.dma,
                     MAD=MAD.dma,MAPE=MAPE.dma)
    df.master <- rbind(df.master,ak)
    ts.plot(x,main=paste("Double Moving Average n =",i), lwd = 1)
    lines(pemulusan_dma,col="green",lwd=0.5)
    lines(ramal_dma,col="red",lwd= 0.5)
  }
  opt <- df.master$n[which.min(df.master[,metode])]
  return(list(Akurasi=df.master,n.optimum=paste("n optimum adalah",opt)))
}
dma_iter<-iterasi_dma(train.ts,2,10, metode= "MAPE")

tibble::as_tibble(dma_iter[[1]])
## # A tibble: 9 x 6
##       n    SSE   MSE  RMSE   MAD  MAPE
##   <int>  <dbl> <dbl> <dbl> <dbl> <dbl>
## 1     2  4855.  49.0  7.00  5.23  9.48
## 2     3  8020.  82.7  9.09  6.60 12.4 
## 3     4 10169. 107.  10.3   7.72 14.9 
## 4     5 11073. 119.  10.9   8.13 15.9 
## 5     6 12288. 135.  11.6   8.68 16.8 
## 6     7 13447. 151.  12.3   8.99 17.7 
## 7     8 14729. 169.  13.0   9.57 19.0 
## 8     9 16004. 188.  13.7  10.3  20.6 
## 9    10 16890. 203.  14.3  11.0  22.3
dma_iter[[2]]
## [1] "n optimum adalah 2"

Dari hasil perbandingan model DMA dengan n dari 2 hingga 10, nilai MAPE minimum didapatkan ketika n bernilai 2

DMA dengan n optimum

Melakukan pemulusan data menggunakan DMA dengan n sebesar 2 sebagai berikut:

# Fungsi Double Moving Average
dma_function <- function(x,n,metode=c("SSE","MSE","RMSE","MAD","MAPE")){
  df.master <- data.frame()
  df_ts_sma <- TTR::SMA(x,  n=n)
  df_ts_dma <- TTR::SMA(df_ts_sma, n=n)
  At <- 2*df_ts_sma-df_ts_dma
  Bt <- df_ts_sma-df_ts_dma
  pemulusan_dma <- At+Bt
  ramal_dma <- c(NA, pemulusan_dma)
  df_dma <- cbind(df_aktual=c(x,NA), pemulusan_dma=c(pemulusan_dma,NA), ramal_dma)
  error.dma <- df_dma[, 1] - df_dma[, 3]
  SSE.dma <- sum(error.dma^2, na.rm = T)
  MSE.dma <- mean(error.dma^2, na.rm = T)
  RMSE.dma <- sqrt(mean(error.dma^2, na.rm = T))
  MAD.dma <- mean(abs(error.dma), na.rm = T)
  r.error.dma <- (error.dma/df_dma[, 1])*100 
  MAPE.dma <- mean(abs(r.error.dma), na.rm = T)
  ak <- data.frame(n=n,SSE=SSE.dma,MSE=MSE.dma,RMSE=RMSE.dma,
                     MAD=MAD.dma,MAPE=MAPE.dma)
  df.master <- rbind(df.master,ak)
  ts.plot(x,main=paste("Double Moving Average n =",n), lwd = 1)
  lines(pemulusan_dma,col="green",lwd=0.5)
  lines(ramal_dma,col="red",lwd= 0.5)
  return(list(df_dma, df.master))
}
smoothing_dma<-dma_function(train.ts, n=2, metode = .)

tibble::as_tibble(tail(smoothing_dma[[1]]))
## # A tibble: 6 x 3
##   df_aktual pemulusan_dma ramal_dma
##       <dbl>         <dbl>     <dbl>
## 1      44.8         40.0      54.5 
## 2      20.5         17.1      40.0 
## 3      18.8          6.70     17.1 
## 4      35.5         34.7       6.70
## 5      39.3         47.6      34.7 
## 6      NA           NA        47.6
tibble::as_tibble(smoothing_dma[[2]])
## # A tibble: 1 x 6
##       n   SSE   MSE  RMSE   MAD  MAPE
##   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1     2 4855.  49.0  7.00  5.23  9.48

Duble Exponential Smoothing

Penentuan parameter optimum

iterasi_des <- function(x,alfa=NULL,beta=NULL,metrik=c("SSE","MSE","RMSE", "MAPE")){
  df.master <- data.frame()
  par(mfrow=c(3,3))
    for (i in alfa) {
      for (j in beta) {
        df_des <- HoltWinters(x, alpha = i, beta=j, gamma=F)
        datades <- data.frame(x,c(NA, NA, df_des$fitted[,1]))
        error<-datades[,1]-datades[,2]
        MAPE<-mean(abs((error[3:length(error)]/datades[3:length(error),1])*100))
        sse <- df_des$SSE 
        mse <- sse/length(x)
        rmse <-sqrt(mse)
        ak <- data.frame(Alpha=i,Beta=j,SSE=sse,MSE=mse,RMSE=rmse, MAPE)
        df.master <- rbind(df.master,ak)
        datades <- data.frame(x, c(NA, NA, df_des$fitted[,1]))
        colnames(datades) = c("y","yhat")
        ts.plot(x,xlab="periode  waktu", ylab="Yt",  col="blue", lty=3,main=paste("DES Alpha=",i,"Beta=",j))
        points(x)
        lines (datades[,2], col="red",lwd=2)
      }
    }
  opt <- df.master$Alpha[which.min(df.master[,metrik])]
    opt2 <- df.master$Beta[which.min(df.master[,metrik])]
    return(list(Akurasi=df.master,n.optimum=paste("Alpha optimum adalah",opt,
                                                  ",Beta optimum adalah",opt2)))
    
}
iterasi_des(train.ts, alfa = seq(0.1,0.9, 0.1), beta = seq(0.1,0.9, 0.1), metrik = "MAPE")

## $Akurasi
##    Alpha Beta       SSE       MSE      RMSE      MAPE
## 1    0.1  0.1 60420.812 592.36090 24.338465 33.434716
## 2    0.1  0.2 33078.812 324.30208 18.008389 22.082936
## 3    0.1  0.3 29967.096 293.79506 17.140451 22.082751
## 4    0.1  0.4 30409.124 298.12867 17.266403 23.556232
## 5    0.1  0.5 29909.648 293.23184 17.124014 23.747225
## 6    0.1  0.6 28048.092 274.98130 16.582560 23.098588
## 7    0.1  0.7 25525.562 250.25060 15.819311 21.312703
## 8    0.1  0.8 23415.429 229.56303 15.151338 20.726247
## 9    0.1  0.9 22419.044 219.79454 14.825469 20.649836
## 10   0.2  0.1 20926.938 205.16606 14.323619 17.917175
## 11   0.2  0.2 16177.007 158.59811 12.593574 16.284840
## 12   0.2  0.3 15127.378 148.30762 12.178162 15.875399
## 13   0.2  0.4 14582.928 142.96988 11.957001 15.982064
## 14   0.2  0.5 14573.741 142.87981 11.953234 16.240125
## 15   0.2  0.6 14997.938 147.03861 12.125948 16.565347
## 16   0.2  0.7 15552.777 152.47821 12.348207 17.428767
## 17   0.2  0.8 15951.655 156.38878 12.505550 18.029325
## 18   0.2  0.9 16083.510 157.68147 12.557128 18.149239
## 19   0.3  0.1 12950.227 126.96301 11.267786 14.497017
## 20   0.3  0.2 11041.455 108.24956 10.404305 13.406524
## 21   0.3  0.3 10752.123 105.41297 10.267082 13.487621
## 22   0.3  0.4 10855.285 106.42436 10.316219 13.905927
## 23   0.3  0.5 11070.139 108.53078 10.417811 14.563476
## 24   0.3  0.6 11238.682 110.18316 10.496817 15.071510
## 25   0.3  0.7 11345.880 111.23412 10.546759 15.327087
## 26   0.3  0.8 11443.540 112.19157 10.592052 15.406869
## 27   0.3  0.9 11567.802 113.40983 10.649405 15.578168
## 28   0.4  0.1  9635.440  94.46509  9.719316 12.765276
## 29   0.4  0.2  8704.898  85.34213  9.238081 12.173503
## 30   0.4  0.3  8677.171  85.07030  9.223356 12.555884
## 31   0.4  0.4  8814.234  86.41406  9.295916 13.034166
## 32   0.4  0.5  8964.480  87.88706  9.374810 13.296079
## 33   0.4  0.6  9103.907  89.25399  9.447433 13.372129
## 34   0.4  0.7  9242.447  90.61223  9.519046 13.396941
## 35   0.4  0.8  9381.186  91.97241  9.590225 13.569095
## 36   0.4  0.9  9513.008  93.26479  9.657370 13.638916
## 37   0.5  0.1  7828.788  76.75282  8.760869 11.737221
## 38   0.5  0.2  7330.037  71.86311  8.477211 11.619116
## 39   0.5  0.3  7384.401  72.39608  8.508589 11.899783
## 40   0.5  0.4  7521.560  73.74078  8.587245 12.004506
## 41   0.5  0.5  7663.024  75.12769  8.667623 12.106865
## 42   0.5  0.6  7796.641  76.43766  8.742863 12.134801
## 43   0.5  0.7  7918.880  77.63608  8.811134 12.075750
## 44   0.5  0.8  8025.032  78.67678  8.869993 11.949409
## 45   0.5  0.9  8111.501  79.52452  8.917652 11.974163
## 46   0.6  0.1  6684.713  65.53640  8.095456 11.060043
## 47   0.6  0.2  6402.985  62.77437  7.923028 10.972442
## 48   0.6  0.3  6485.970  63.58795  7.974205 11.034780
## 49   0.6  0.4  6613.416  64.83741  8.052168 11.096977
## 50   0.6  0.5  6734.786  66.02732  8.125719 11.045529
## 51   0.6  0.6  6839.505  67.05397  8.188649 11.028261
## 52   0.6  0.7  6923.790  67.88029  8.238950 10.972964
## 53   0.6  0.8  6986.404  68.49416  8.276120 11.080729
## 54   0.6  0.9  7028.616  68.90800  8.301084 11.292594
## 55   0.7  0.1  5891.656  57.76133  7.600087 10.448477
## 56   0.7  0.2  5728.019  56.15705  7.493801 10.318806
## 57   0.7  0.3  5816.930  57.02873  7.551737 10.297504
## 58   0.7  0.4  5927.507  58.11282  7.623176 10.374900
## 59   0.7  0.5  6024.605  59.06475  7.685359 10.464480
## 60   0.7  0.6  6101.760  59.82118  7.734415 10.491950
## 61   0.7  0.7  6159.109  60.38342  7.770677 10.631558
## 62   0.7  0.8  6199.578  60.78017  7.796164 10.830501
## 63   0.7  0.9  6227.496  61.05388  7.813698 10.984395
## 64   0.8  0.1  5315.039  52.10823  7.218603  9.869692
## 65   0.8  0.2  5221.450  51.19069  7.154767  9.753680
## 66   0.8  0.3  5310.310  52.06186  7.215390  9.946628
## 67   0.8  0.4  5409.216  53.03153  7.282275 10.073540
## 68   0.8  0.5  5494.695  53.86956  7.339588 10.099574
## 69   0.8  0.6  5565.530  54.56402  7.386746 10.229840
## 70   0.8  0.7  5626.041  55.15727  7.426794 10.369036
## 71   0.8  0.8  5682.511  55.71090  7.463973 10.509952
## 72   0.8  0.9  5741.932  56.29345  7.502896 10.677383
## 73   0.9  0.1  4892.924  47.96984  6.926026  9.331836
## 74   0.9  0.2  4849.030  47.53951  6.894890  9.489583
## 75   0.9  0.3  4944.648  48.47694  6.962538  9.676914
## 76   0.9  0.4  5048.804  49.49808  7.035487  9.746427
## 77   0.9  0.5  5147.791  50.46854  7.104121  9.914294
## 78   0.9  0.6  5245.522  51.42669  7.171240 10.047833
## 79   0.9  0.7  5350.214  52.45308  7.242450 10.249832
## 80   0.9  0.8  5471.457  53.64173  7.324052 10.522653
## 81   0.9  0.9  5619.447  55.09262  7.422440 10.805432
## 
## $n.optimum
## [1] "Alpha optimum adalah 0.9 ,Beta optimum adalah 0.1"

DES dengan parameter optimum

des_function<- function(x,alfa=NULL,beta=NULL,metrik=c("SSE","MSE","RMSE")){
  df.master <- data.frame()
        df_des <- HoltWinters(x, alpha = alfa, beta=beta, gamma=F)
        datades <- data.frame(x,c(NA, NA, df_des$fitted[,1]))
        error<-datades[,1]-datades[,2]
        mape<-mean(abs((error[3:length(error)]/datades[3:length(error),1])*100))
        sse <- df_des$SSE 
        mse <- sse/length(x)
        rmse <-sqrt(mse)
        ak <- data.frame(SSE=sse,MSE=mse,RMSE=rmse, MAPE=mape)
        df.master <- rbind(df.master,ak)
        datades <- data.frame(x, c(NA, NA, df_des$fitted[,1]))
        colnames(datades) = c("y","yhat")
        ts.plot(x,xlab="periode  waktu", ylab="Yt",  col="blue", lty=3,main=paste("DES Alpha=",alfa,"Beta=",beta))
        points(x)
        lines (datades[,2], col="red",lwd=2)
         return(df.master)
      }
smoothing_des<-des_function(train.ts, alfa = 0.9, beta = 0.1, metrik = .)

smoothing_des
##        SSE      MSE     RMSE     MAPE
## 1 4892.924 47.96984 6.926026 9.331836

Forecasting

Double Moving Average

df_ts_sma <- TTR::SMA(train.ts,  n=2)
df_ts_dma <- TTR::SMA(df_ts_sma, n=2)
At <- 2*df_ts_sma-df_ts_dma
Bt <- df_ts_sma-df_ts_dma
pemulusan_dma <- At+Bt
ramal_dma <- c(NA, pemulusan_dma)
df_dma <- cbind(df_aktual=c(train.ts,NA), pemulusan_dma=c(pemulusan_dma,NA), ramal_dma)
head (df_dma)
##      df_aktual pemulusan_dma ramal_dma
## [1,]     98.48            NA        NA
## [2,]    107.07            NA        NA
## [3,]    103.02       107.315        NA
## [4,]    104.87       102.845   107.315
## [5,]     86.53        87.455   102.845
## [6,]     84.96        75.790    87.455

Eksploratif: DMA Plot

ts.plot(data, xlab="periode waktu", ylab="Yt", col="blue", lty=1,
        xlim=c(0,150),ylim=c(0,160),gpars=list(col.main="black",col.axis="white",col.sub="black"))
points(data,col="black")
par(col = "black")
lines(pemulusan_dma,col="red",lwd=2,lty=1)
par(col = "black")
lines(ramal_dma,col="green",lwd= 2,lty=1)
title("Rataan Bergerak  Berganda N=2", cex.main=1, font.main=4 ,col.main="black")
legend("topright", c("Data Aktual","Pemulusan","Ramalan"),lty=1,col=c ("blue","red","green"))
box(col="black",lwd=2)

Berdasarkan times series plot metode DMA, n yang optimum adalah 2, karena data training DMA dengan n=2 lebih mendekati sebaran pola dari data aktual dibandingkan hasil peramalannya

Double Exponential Smoothing

df_des <- HoltWinters(train.ts, alpha = 0.9, beta=0.1, gamma=F)
datades <- data.frame(train.ts,c(NA, NA, df_des$fitted[,1]))
colnames(datades)=c("y","yhat")
head(datades)
##        y      yhat
## 1  98.48        NA
## 2 107.07        NA
## 3 103.02 115.66000
## 4 104.87 111.73640
## 5  86.53 112.39106
## 6  84.96  93.62303
ramal_des <- forecast::forecast(df_des,h=3)
(df_ramal_des <- data.frame(ramal_des))
##     Point.Forecast    Lo.80    Hi.80    Lo.95    Hi.95
## 103       37.60995 28.70389 46.51602 23.98930 51.23061
## 104       36.68618 24.15391 49.21844 17.51973 55.85263
## 105       35.76240 19.96448 51.56032 11.60157 59.92324
ts.plot(data, xlab="periode  waktu", ylab="Yt", col="blue", lty=1,
        xlim=c(0,150),ylim=c(0,150))
points(data,col="black")
par(col="black")
lines(datades[,2], col="red",lwd=2) #nilai dugaan
par(col="black")
lines(ts(df_ramal_des$Point.Forecast,start = 108), col="green",lwd=2) #nilai dugaan
title("Double Exponential Smoothing Alpha=0.9 Beta = 0.1",cex.main=1, font.main=4 ,col.main="black")
legend("bottomright", c("Data aktual", "Fitted DES","Ramalan"), lty=1,col=c ("blue","red","green"))
box(col="black",lwd=2)

Berdasarkan time series plot DES, plot data training hasil fitted menggunakan metode pemulusan DES dengan α = 0.9 dan β = 0.1 menampilkan plot yang berpola tidak terlalu jauh dari plot data aktual dibandingkan dengan data peramalannya.