Anggota Tim

  1. Berryl Bagas Wirawan (G14190006)
  2. Mely Amelia (G14190017)
  3. Radja Ahmad Nur Fikri (G14190028)
  4. Vahrio Rizal Tampany (G14190035)
  5. Dyah Listyowati (G14190061)

Load library yang dibutuhkan

library(tidyverse) #data manipulation
library(lubridate) # date manipulation
library(forecast) # time series library
library(TTR) # for Simple moving average function
library(MLmetrics) # calculate error
library(tseries) # adf.test
library(fpp)
library(padr)
library(zoo)
library(dplyr)
library(ggplot2)
library(gridExtra)
library(imputeTS)
library(quantmod)

Data Proyek

IHSG adalah indeks harga saham gabungan secara umum dan berfungsi sebagai pengukuran kinerja suatu saham gabungan di Bursa Efek Indonesia (BEI). IHSG dipengaruhi oleh faktor eksternal yaitu tingkat suku bunga luar negeri dan indeks harga saham luar negeri serta faktor internal yaitu nilai tukar rupiah terhadap USD, inflasi, suku bunga deposito, suku bunga Sertifikat Bank Indonesia, dan jumlah uang yang ada di masyarakat (Purba 2014). Data yang digunakan adalah data IHSG sektoral keuangan (JKFINA) periode Januari 2012 sampai dengan Maret 2022 yang diperoleh dari www.yahoo.finance.com.

Load data yang akan digunakan

start <- as.POSIXct("2012-01-01")
end <- as.POSIXct("2022-03-31")
getSymbols(Symbols = "^JKFINA",src = "yahoo", from = start, to = end)

[1] “^JKFINA”

class(JKFINA)

[1] “xts” “zoo”

head(JKFINA)
       JKFINA.Open JKFINA.High JKFINA.Low JKFINA.Close JKFINA.Volume

2012-01-02 492.05 493.50 488.52 491.10 84100000 2012-01-03 491.82 496.68 491.77 496.62 269100000 2012-01-04 495.90 501.61 495.85 499.21 254800000 2012-01-05 498.94 499.97 494.75 496.29 545200000 2012-01-06 496.01 496.85 490.24 492.98 204600000 2012-01-09 492.26 498.93 488.91 498.93 539600000 JKFINA.Adjusted 2012-01-02 491.10 2012-01-03 496.62 2012-01-04 499.21 2012-01-05 496.29 2012-01-06 492.98 2012-01-09 498.93

colnames(JKFINA)

[1] “JKFINA.Open” “JKFINA.High” “JKFINA.Low” “JKFINA.Close”
[5] “JKFINA.Volume” “JKFINA.Adjusted”

df <- data.frame(JKFINA)
df <- cbind(Date=rownames(df),df)
rownames(df) <- 1:nrow(df)

Tabel 1 memperlihatkan seluruh variabel yang akan digunakan. Data yang akan diguakan hanya harga saat closing, sehingga hanya kolom tanggal dan kolom harga closing yang akan diambil. Tabel 2 memperlihatkan sebagian dari data yang akan digunakan.

df1 <- df %>%
      select(c(Date,JKFINA.Close))
df1$Date <- ymd(df1$Date)
head(df1) %>% knitr::kable(
    align = "c",
  caption = "Lima data pertama *subset* data yang digunakan"
)
Lima data pertama subset data yang digunakan
Date JKFINA.Close
2012-01-02 491.10
2012-01-03 496.62
2012-01-04 499.21
2012-01-05 496.29
2012-01-06 492.98
2012-01-09 498.93

Eksplorasi Data

Pada data tersebut, terlihat bahwa terdapat beberapa tanggal yang terlewati, seperti pada tanggal 1 Januari 2012, 7 Januari 2012, dan 8 Januari 2012 dan masih banyak lagi. Setelah dilakukan investigasi, ternyata tanggal-tanggal ini terletak pada hari Sabtu dan Minggu, dan hari libur nasional, sehingga tanggal-tanggal yang dilewati ini harus dimasukkan dalam dataset tersebut seperti pada Tabel 3.

date.seq <- data.frame("Date" = seq(ymd(start), ymd(end), by = "days"))
df1 <- merge(date.seq, df1, by = "Date", all.x = T)
knitr::kable(head(df1), 
             caption = "Data dengan tanggal yang benar", align = "c", 
             label = "data_tanggal_bener")
Data dengan tanggal yang benar
Date JKFINA.Close
2012-01-01 NA
2012-01-02 491.10
2012-01-03 496.62
2012-01-04 499.21
2012-01-05 496.29
2012-01-06 492.98

Pada analisis data deret waktu, tidak boleh ada data yang kosong dan periode deret waktu harus seragam untuk seluruh data. Untuk itu, pengecekan data kosong atau missing-values harus dilakukan terlebih dahulu.

sum(is.na(df1))
## [1] 1248

Terdapat 1248 data kosong yang berada pada dataset tersebut, sehingga harus dilakukan interpolasi terlebih dahulu. Interpolasi yang digunakan adalah spline interpolation dimana data dibagi menjadi beberapa bagian lalu data kosong disubstitusikan berdasarkan data pada bagian tersebut. Metode ini relatif mudah digunakan dan pola dan karakteristik data tetap dipertahankan (Rappai 2015).

Menurut Wang (2013), model matematika untuk spline interpolation dapat digambarkan sebagai berikut:

Untuk i = 1,2,…,n titik data, interpolasi untuk semua pasangan knots \((x_{i-1},y_{i-1})\) dan \((x_i,y_i)\) dengan polinomial :

\[y=q_i(x) ;i = 1,2,…,n\]

kelengkungan kurva fungsi \(y=f(x)\) adalah

\[k = \frac{y"}{(1+y'^2)^\frac{2}{3}}\]

Data yang sudah dilakukan imputasi dapat dilihat pada Tabel 4.

dataimp = na_interpolation(df1, option = "spline")
head(dataimp) %>% knitr::kable(caption = "Data yang sudah diimputasi")
Data yang sudah diimputasi
Date JKFINA.Close
2012-01-01 491.10
2012-01-02 491.10
2012-01-03 496.62
2012-01-04 499.21
2012-01-05 496.29
2012-01-06 492.98
sum(is.na(dataimp))
## [1] 0

Pada dataset tersebut sudah tidak ada lagi missing values sehingga analisis deret waktu dapat dilanjutkan. Setelah itu, data akan diagregasi menjadi data bulanan.

Plot data sebelum interpolasi dan setelah interpolasi dapat dilihat pada Gambar 1.

windowsFonts(Times = windowsFont("Times New Roman"))

ggplot_na_imputations(df1$JKFINA.Close, dataimp$JKFINA.Close,
                      title = NULL,
                      subtitle = NULL,
                      size_points = 1.5, 
                      size_imputations = 0.75,
                      xlab = "\nTahun", 
                      ylab = "Harga saat closing\n",
                      x_axis_labels = dataimp$Date,
                      label_known = "Sebelum imputasi", 
                      label_imputations = "Setelah imputasi",
                      shape_points = 20,
                      shape_imputations = 20,
                      legend_size = 5, 
                      theme = theme_classic(base_family = 'Times', 
                                         base_size = 12))
Plot data interpolasi dan data asli.

Plot data interpolasi dan data asli.

Terlihat bahwa imputasi data dengan metode spline interpolation dapat memberikan nilai-nilai yang memiliki pola yang sama dengan data aslinya. Setelah melakukan imputasi, maka data akan diagregasikan menjadi data rataan per harga closing IHSG per bulannya. Data setelah diagregasi dapat dilihat pada Tabel 5.

dataimp$Date <- floor_date(ymd(dataimp$Date),"month")
df2 <- dataimp %>%
      group_by(Date) %>%
      summarize(Close = mean(JKFINA.Close))
head(df2) %>% knitr::kable(caption = "Data agregasi per bulan.")
Data agregasi per bulan.
Date Close
2012-01-01 499.9487
2012-02-01 487.7797
2012-03-01 496.7415
2012-04-01 522.1882
2012-05-01 501.7686
2012-06-01 484.4287

Statistika deskriptif singkat dari data dapat dilihat pada Tabel 6.

summary(df2)
##       Date                Close       
##  Min.   :2012-01-01   Min.   : 484.4  
##  1st Qu.:2014-07-16   1st Qu.: 662.9  
##  Median :2017-02-01   Median : 824.5  
##  Mean   :2017-01-30   Mean   : 926.3  
##  3rd Qu.:2019-08-16   3rd Qu.:1203.4  
##  Max.   :2022-03-01   Max.   :1615.8

Didapatkan nilai rata-rata sebesar 926.3 dan median sebesar 824.5. Untuk nilai minimum data tersebut yaitu sebesar 484.429 terjadi pada bulan Juni tahun 2012 sedangkan untuk nilai maksimum data tersebut sebesar 1615.753 terjadi pada bulan Maret tahun 2022.

Pada bulan Desember 2019 IHSG bergerak menguat hingga 4,79% hal tersebut sudah biasa terjadi karena sejak tahun 2011 sudah 7 kali IHSG selalu meningkat pada penutupan perdagangan (akhir tahun). Selain peristiwa akhir tahun, peristiwa Idul Adha di Indonesia pun bisa memberikan efek positif terhadap IHSG (Nugroho. 2017).

Salah satu metode eksplorasi yang paling cepat untuk dilakukan adalah dengan melakukan plot time-series. Plot ini memperlihatkan secara cepat bagaimana pola dan trend dari data itu sendiri.

ggplot(df2, aes(x = Date, y = Close)) +
    geom_line(width = 1.5, col = "steelblue") +
    geom_point(size = 1.5, col = "steelblue") +
    scale_x_date(date_breaks = "year", date_labels = "%Y") +
    scale_y_continuous(breaks = seq(200, 
                                    1500,
                                    by = 200)
                       ) +
    xlab("\nPeriode Waktu") +
    ylab("Harga saat closing\n") +
    theme_classic() +
    theme(text = element_text(size = 12, family = "Times"), 
          panel.border = element_rect(color = "gray", fill = NA))
Plot time series data IHSG.

Plot time series data IHSG.

Pada Grafik 2, seiring dengan berjalannya waktu, harga closing IHSG semakin meningkat. Tentunya hal ini bukan tanpa sebab, karena IHSG sangat terikat dengan fenomena ekonomi makro, baik internal, seperti inflasi, suku bunga, nilai tukar, dan lainnya, serta eksternal, seperti indeks bursa harga luar negeri, harga minyak mentah, harga emas, dan kestabilan politik suatu negara (Wijaya 2015). Penelitian oleh Tambunan dan Aminda (2021) menyatakan bahwa trend naiknya IHSG dapat dijelaskan secara kuat oleh kurs rupiah. Dari plot tersebut tidak terlihat adanya plot musiman. Hal ini ditandai dengan tidak adanya pola siklik pada data tersebut.

Dengan semakin meningkatknya grafik, maka menandakan bahwa terdapat trend positif pada data IHSG tersebut. Dalam menentukan metode pemulusan yang paling tepat, data yang memiliki trend dapat dimuluskan dengan metode DMA (Double Moving Average) dan metode DES (Double Exponential Smoothing) (Layakana dan Iskandar 2020; Fajri dan Johan 2017).

Pemulusan Data

Metode pemulusan (smoothing) adalah metode peramalan dengan mengadakan penghalusan atau pemulusan terhadap data masa lalu yaitu dengan mengambil rata-rata dari nilai pada beberapa periode untuk menaksir nilai pada suatu periode (Hommy, 2018).

Double moving average

metode double moving average adalah metode pemulusan dengan menghitung rata-rata bergerak sebanyak dua kali kemudian dilanjutkan dengan peramalan menggunakan suatu persamaan tertentu (Afifah, 2020). Adapun langkah-langkah yang dilakukan antara lain sebagai berikut:

  1. Menghitung rata-rata bergerak pertama

    \[ S_{t} =\frac{Y_{t} + Y_{t-1}+…+Y_{t-n-1}}{n} \]

  2. Menghitung rata-rata bergerak kedua

    \[ S'_{t} =\frac{S_{t} + S_{t-1}+…+S_{t-n-1}}{n} \]

  3. Menentukan besarnya nilai konstanta, slope, dan peramalan

    \[ A_{t} =2S_{t}-S'_{t} \]

    \[ B_{t} =\frac{2}{n-1}(S_{t}-S'_{t}) \]

    \[ \hat{Y} = A_{t} +B_{t}(h) \]

Data akan dipisah terlebih dahulu menjadi data training dan data testing. Pemisahan data harus memperhatikan trend dari dataset. Data testing tetap harus mempertahankan trend data secara kesluruhan. Partisi data dapat dilihat pada plot berikut.

ggplot(df2, aes(x = Date, y = Close)) +
    geom_line(width = 1.5, col = "steelblue") +
    geom_point(size = 1.5, col = "steelblue") +
    scale_x_date(date_breaks = "year", date_labels = "%Y") +
    scale_y_continuous(breaks = seq(200, 
                                    1500,
                                    by = 200)
                       ) +
    geom_vline(xintercept = as.numeric(ymd("2019-02-01")), linetype = "dashed", color = "red") +
    xlab("\nPeriode Waktu") +
    ylab("Harga saat closing\n") +
    theme_classic() +
    theme(text = element_text(size = 12, family = "Times"), 
          panel.border = element_rect(color = "gray", fill = NA))

Partisi yang ditentukan untuk data training memiliki rentang dari Januari 2012 sampai dengan Desember 2018. Sedangkan data testing berawal dari Januari 2019 sampai dengan Maret 2022. Indeks data Desember 2018 dapat dilihat sebagai berikut.

nov_2019 <- which(df2$Date == "2019-11-01")
dma_train_ts <- ts(df2$Close[1:nov_2019])
dma_test_ts <- ts(df2$Close[(nov_2019+1):nrow(df2)])
DMA_test <- function(train.data, test.data, order, ramal) {
    ts.train.data <- ts(train.data)
    ts.test.data <- ts(test.data)
    
    #Menghitung SMA 1
    s1 <- SMA(ts.train.data, order)
    s2 <- SMA(s1, order)
    
    #Menghitung At dan Bt masing2
    At <- 2*s1 - s2
    Bt <- (2/(order-1)) * (s1 - s2)
    
    #Menghitug dma
    dma.smooth <- At + Bt
    data.ramal2<- c(NA, dma.smooth)
    
    #Permaalan
    f <- c()
    t <- c(1:ramal)
    
    for(i in t) {
        f[i] = At[length(At)] + Bt[length(Bt)]*i
    }
    
    #Hasil smoothing
    hasil <- cbind(data_aktual = c(ts.train.data, rep(NA,  ramal)), 
                   s1 = c(s1, rep(NA,  ramal)), 
                   s2 = c(s2, rep(NA,  ramal)), 
                   At = c(At, rep(NA,  ramal)), 
                   Bt = c(Bt,rep(NA,  ramal)), 
                   smoothing = c(data.ramal2, f[-1]))
    
    #Hitung akurasi
    
    akurasi_train <- accuracy(ts(hasil[,6][1:length(ts.train.data)]), ts.train.data)
    
    akurasi_test <- accuracy(ts(f), ts.test.data[1:length(f)])
    
    forc <- c(rep(NA, nrow(hasil)), f)
    
    list(hasil = hasil, akurasi_train = akurasi_train, akurasi_test = akurasi_test, 
         forc = hasil[,6][length(ts.train.data):length(nrow(hasil))])
}

DMA_test(dma_train_ts, dma_test_ts, 2, 10)$hasil %>% knitr::kable()
data_aktual s1 s2 At Bt smoothing
499.9487 NA NA NA NA NA
487.7797 493.8642 NA NA NA NA
496.7415 492.2606 493.0624 491.4588 -1.6036044 NA
522.1882 509.4649 500.8627 518.0670 17.2042644 489.8552
501.7686 511.9784 510.7216 513.2352 2.5135469 535.2713
484.4287 493.0987 502.5385 483.6588 -18.8797520 515.7487
508.4259 496.4273 494.7630 498.0916 3.3286473 464.7790
531.3839 519.9049 508.1661 531.6437 23.4775942 501.4203
533.5661 532.4750 526.1900 538.7601 12.5701086 555.1213
545.3448 539.4555 535.9652 542.9457 6.9804331 551.3302
556.9867 551.1657 545.3106 557.0209 11.7102905 549.9261
548.4074 552.6971 551.9314 553.4627 1.5313338 568.7312
571.2086 559.8080 556.2525 563.3635 7.1109356 554.9941
617.2952 594.2519 577.0300 611.4739 34.4438973 570.4744
648.8105 633.0529 613.6524 652.4533 38.8009473 645.9178
662.6359 655.7232 644.3880 667.0583 22.6703155 691.2543
669.8311 666.2335 660.9783 671.4887 10.5103398 689.7286
600.4651 635.1481 650.6908 619.6055 -31.0853686 681.9990
581.6699 591.0675 613.1078 569.0272 -44.0806365 588.5201
554.7886 568.2292 579.6484 556.8101 -22.8382845 524.9466
547.3893 551.0889 559.6591 542.5188 -17.1403052 533.9718
582.1992 564.7942 557.9416 571.6469 13.7053251 525.3785
562.1292 572.1642 568.4792 575.8492 7.3699767 585.3522
533.2130 547.6711 559.9177 535.4245 -24.4931125 583.2192
562.5268 547.8699 547.7705 547.9693 0.1987733 510.9314
599.9910 581.2589 564.5644 597.9534 33.3889816 548.1680
629.8554 614.9232 598.0910 631.7554 33.6643303 631.3423
650.9982 640.4268 627.6750 653.1786 25.5036236 665.4197
660.6570 655.8276 648.1272 663.5280 15.4007750 678.6822
648.4766 654.5668 655.1972 653.9364 -1.2607877 678.9288
674.6176 661.5471 658.0570 665.0373 6.9803121 652.6756
682.5639 678.5907 670.0689 687.1125 17.0436173 672.0176
695.4986 689.0312 683.8110 694.2515 10.4404980 704.1562
687.7357 691.6172 690.3242 692.9101 2.5859367 704.6920
709.6591 698.6974 695.1573 702.2376 7.0802577 695.4961
726.1880 717.9236 708.3105 727.5366 19.2261347 709.3178
732.6393 729.4136 723.6686 735.1587 11.4900798 746.7628
769.3089 750.9741 740.1939 761.7543 21.5604560 746.6488
802.5615 785.9352 768.4546 803.4158 34.9611066 783.3148
808.1677 805.3646 795.6499 815.0793 19.4293821 838.3769
761.0800 784.6238 794.9942 774.2534 -20.7407664 834.5087
712.8807 736.9803 760.8021 713.1586 -47.6434760 753.5127
692.6362 702.7585 719.8694 685.6475 -34.2218756 665.5151
663.1511 677.8936 690.3261 665.4612 -24.8648204 651.4257
626.5650 644.8580 661.3758 628.3402 -33.0356008 640.5964
663.9591 645.2620 645.0600 645.4640 0.4039929 595.3046
667.6745 665.8168 655.5394 676.0942 20.5547477 645.8680
673.7550 670.7147 668.2658 673.1637 4.8979426 696.6489
678.9112 676.3331 673.5239 679.1423 5.6183517 678.0616
693.5029 686.2071 681.2701 691.1440 9.8739813 684.7606
701.2695 697.3862 691.7966 702.9758 11.1791697 701.0180
682.7082 691.9888 694.6875 689.2902 -5.3973797 714.1550
661.9836 672.3459 682.1674 662.5244 -19.6429756 683.8928
674.2167 668.1001 670.2230 665.9773 -4.2457415 642.8814
724.1405 699.1786 683.6393 714.7178 31.0784344 661.7315
796.7165 760.4285 729.8035 791.0534 61.2498925 745.7962
791.1104 793.9134 777.1709 810.6559 33.4849534 852.3033
802.9547 797.0325 795.4730 798.5921 3.1191011 844.1408
776.6032 789.7790 793.4057 786.1522 -7.2535608 801.7112
779.8309 778.2171 783.9980 772.4361 -11.5618754 778.8986
804.9161 792.3735 785.2953 799.4517 14.1564374 760.8743
824.5381 814.7271 803.5503 825.9039 22.3535773 813.6082
852.6654 838.6017 826.6644 850.5391 23.8746470 848.2575
880.8657 866.7655 852.6836 880.8475 28.1638083 874.4137
914.2122 897.5390 882.1523 912.9257 30.7734186 909.0113
936.2092 925.2107 911.3748 939.0466 27.6717478 943.6991
959.9715 948.0903 936.6505 959.5301 22.8796124 966.7183
981.3294 970.6504 959.3704 981.9305 22.5601227 982.4097
992.2494 986.7894 978.7199 994.8589 16.1389829 1004.4906
1023.0098 1007.6296 997.2095 1018.0497 20.8401691 1010.9979
1056.7905 1039.9001 1023.7649 1056.0354 32.2705475 1038.8899
1092.1278 1074.4591 1057.1796 1091.7386 34.5589994 1088.3060
1149.6095 1120.8686 1097.6639 1144.0734 46.4094891 1126.2976
1194.5315 1172.0705 1146.4696 1197.6715 51.2018836 1190.4829
1165.5996 1180.0656 1176.0680 1184.0631 7.9950535 1248.8733
1118.5246 1142.0621 1161.0638 1123.0604 -38.0034643 1192.0582
1048.9115 1083.7181 1112.8901 1054.5460 -58.3440556 1085.0569
1029.6971 1039.3043 1061.5112 1017.0974 -44.4137388 996.2020
1024.1022 1026.8997 1033.1020 1020.6973 -12.4046611 972.6837
1079.6107 1051.8564 1039.3780 1064.3348 24.9567912 1008.2927
1066.2815 1072.9461 1062.4013 1083.4909 21.0896394 1089.2916
1047.5248 1056.9031 1064.9246 1048.8816 -16.0429718 1104.5805
1125.8686 1086.6967 1071.7999 1101.5935 29.7935764 1032.8387
1168.7631 1147.3159 1117.0063 1177.6255 60.6191877 1131.3871
1212.3006 1190.5319 1168.9239 1212.1399 43.2159846 1238.2447
1237.8623 1225.0814 1207.8066 1242.3562 34.5495666 1255.3558
1238.6500 1238.2561 1231.6688 1244.8435 13.1747106 1276.9058
1290.7510 1264.7005 1251.4783 1277.9226 26.4443386 1258.0182
1229.9310 1260.3410 1262.5207 1258.1612 -4.3594928 1304.3670
1278.5367 1254.2339 1257.2874 1251.1803 -6.1071275 1253.8017
1316.0219 1297.2793 1275.7566 1318.8020 43.0454409 1245.0732
1269.0651 1292.5435 1294.9114 1290.1756 -4.7358014 1361.8475
1256.1511 1262.6081 1277.5758 1247.6404 -29.9354210 1285.4398
1249.3688 1252.7599 1257.6840 1247.8359 -9.8481304 1217.7049
1272.0590 1260.7139 1256.7369 1264.6909 7.9539697 1237.9877
NA NA NA NA NA 1272.6449
NA NA NA NA NA 1280.5988
NA NA NA NA NA 1288.5528
NA NA NA NA NA 1296.5068
NA NA NA NA NA 1304.4607
NA NA NA NA NA 1312.4147
NA NA NA NA NA 1320.3687
NA NA NA NA NA 1328.3227
NA NA NA NA NA 1336.2766
NA NA NA NA NA 1344.2306
DMA_test(dma_train_ts, dma_test_ts, 2, 10)$akurasi_train %>% knitr::kable()
ME RMSE MAE MPE MAPE ACF1 Theil’s U
Test set 0.1931353 37.57502 29.92694 0.0736124 3.807155 0.1304273 1.215431
DMA_test(dma_train_ts, dma_test_ts, 2, 10)$akurasi_test %>% knitr::kable()
ME RMSE MAE MPE MAPE
Test set -169.9868 234.3264 204.6396 -17.00233 19.58336

Lakukan looping untuk menentukan order optimum pemulusan untuk data training.

n <- 1:((nrow(df2))/3)
MAPE_err <- c()
MAE_err <- c()
for (i in n) {
    MAPE_err[i] <- DMA_test(dma_train_ts, dma_test_ts, n[i], length(dma_test_ts))$akurasi_train[5]
    MAE_err[i] <- DMA_test(dma_train_ts, dma_test_ts, n[i], length(dma_test_ts))$akurasi_train[3]
}
err <- cbind(n, MAPE_err, MAE_err) %>% as.data.frame()

err %>% ggplot() +
    geom_line(aes(x = n, y = MAPE_err, col = "steelblue"),  show.legend = T) +
    geom_line(aes(x = n, y = MAE_err, col = "red"),  show.legend = T) +
    scale_color_manual(name = NULL, 
                       values = c("steelblue" = "steelblue", 
                                  "red" = "red"), 
                       labels = c("MAPE", "MAE")) +
    xlab("n") +
    ylab("Error") +
    theme_classic() +
    theme(legend.position = "bottom")

Dari plot error tersebut terlihat bahwa MAPE cenderung stabil untuk semua \(n\), sedangkan MAE cenderung berfluktuasi. Nilai terendah untuk MAPE dan MAE dapat dilihat di bawah ini.

err[order(MAPE_err, MAE_err),] %>% 
  head() %>% 
  knitr::kable(digits = 3, row.names = F)
n MAPE_err MAE_err
2 3.807 29.927
3 4.139 32.941
4 4.760 37.994
5 5.655 44.996
6 5.925 47.977
39 6.223 74.810

Terlihat bahwa nilai order DMA yang memiliki MAPE dan MAE terendah adalah untuk \(n = 2\).

Plot dari pemulusan dapat dilihat sebagai berikut

close.ts <- ts(df2$Close)
dma_forecast <- DMA_test(dma_train_ts, dma_test_ts, order = 2, ramal = length(dma_test_ts))
data.frame(date = seq(ymd("2012-01-01"), ymd("2022-08-01"), by = "month"), 
           smooth = c(ts(DMA_test(dma_train_ts, dma_test_ts, 2, length(dma_test_ts))$hasil[,6]), rep(NA, 5)),
           actual = c(close.ts, rep(NA, 5))) %>% 
    ggplot() +
    geom_line(aes(x = date, y = actual, col = "steelblue")) +
    geom_line(aes(x = date, y = smooth, col = "red")) +
    scale_color_manual(name = NULL, 
                       values = c("steelblue" = "steelblue", 
                                  "red" = "red"), 
                       labels = c("Data aktual", 
                                  "Hasil Pemulusan dan Peramalan")) +
    xlab("Tanggal") +
    ylab("Harga Closing IHSG") +
    theme_classic() +
    theme(legend.position = "bottom")

Hasil dari pemulusan dapat dilihat sebagari berikut

DMA_opt <- DMA_test(dma_train_ts, dma_test_ts, 2, length(dma_test_ts))

data.frame("Forecast" = DMA_opt$hasil[98:nrow(DMA_opt$hasil),6])
##    Forecast
## 1  1288.553
## 2  1296.507
## 3  1304.461
## 4  1312.415
## 5  1320.369
## 6  1328.323
## 7  1336.277
## 8  1344.231
## 9  1352.185
## 10 1360.139
## 11 1368.093
## 12 1376.046
## 13 1384.000
## 14 1391.954
## 15 1399.908
## 16 1407.862
## 17 1415.816
## 18 1423.770
## 19 1431.724
## 20 1439.678
## 21 1447.632
## 22 1455.586
## 23 1463.540
## 24 1471.494
## 25 1479.448
## 26 1487.402

Akurasi untuk data peramalan dapat dilihat sebagai berikut.

DMA_opt$akurasi_test
##                 ME     RMSE      MAE       MPE    MAPE
## Test set -61.28563 160.0078 126.1595 -6.523419 10.8388

Terlihat bahwa hasil pemulusan masih dapat menggambarkan pergerakan data aktual. Ditambah dengan memiliki nilai error paling kecil, maka nilai ordo optimum untuk pemulusan DMA data IHSG bulanan adalah dua.

Metode Double Exponential Smoothing

Metode double exponential smoothing digunakan untuk data yang menunjukan adanya trend. metode ini menggunakan parameter alpha yang memiliki niali antara 0 dan 1. Menurut Makridakis et. al (1988) double exponential smoothing mempunyai model umum dengan tahapan sebagai berikut:

  1. Menentukan smoothing pertama \[ S'_{t} =\alpha X_{t}+(1-\alpha)S'_{t-1} \]

  2. Menentukan smoothing kedua \[ S''_{t} =\alpha S'_{t}+(1-\alpha)S''_{t-1} \]

  3. Menentukan besarnya nilai konstanta, slope, dan peramalan \[ A_{t} =2S'_{t}-S''_{t} \] \[ B_{t} =\frac{\alpha}{1-\alpha}(S'_{t}-S''_{t}) \] \[ F_{t+h}=\hat{Y}_{t+h} = A_{t} +B_{t}(h) \]

Pertama data dibagi menjadi data training dan data testing terlebih dahulu.

nov_2019 <- which(df2$Date == "2019-11-01")
ses_train_ts <- ts(df2$Close[1:nov_2019])
ses_test_ts <- ts(df2$Close[(nov_2019+1):nrow(df2)])

Mirip dengan metode DMA, metode DES digunakan untuk data yang memiliki pola trend. Akan terdapat dua komponen yang akan dikenakan smoothing, yaitu trend dan level, dengan level adalah nilai data yang dikenakan smoothing dan level adalah faktor trend yang dikenakan smoothing (Nazim dan Afthanorhan 2014).

des.opt <- HoltWinters(ses_train_ts, gamma = FALSE)
des.opt$alpha;des.opt$beta
## alpha 
##     1
##       beta 
## 0.06280267
des.forecast <- forecast(des.opt, h = length(ses_test_ts))

data.frame(date = df2$Date, 
           smoothing  = c(des.opt$x, rep(NA, (123-98+3))),
           actual = df2$Close,  
           forecasted = c(rep(NA, 98-3), des.forecast$mean)) %>% 
    ggplot() +
    geom_line(aes(x = date, y = actual, color = "steelblue"), size = 1) +
    geom_line(aes(x = date, y = smoothing, color = "orange"), size = 1, linetype = "dashed") +
    geom_line(aes(x = date, y = forecasted, color = "red"), size = 1) +
    scale_color_manual(name = NULL,
                       values = c("steelblue" = "steelblue", 
                                  "orange" = "orange",
                                  "red" = "red"), 
                       labels = c("Data Aktual", 
                                  "Data Pemulusan",
                                  "Data Ramalan")) +
    xlab("Tanggal") +
    ylab("Harga IHSG Closing") +
    theme_classic() +
    theme(legend.position = "bottom")

Terlihat bahwa dengan menggunakan metode DES, trend dari data tersebut masih terpelihara seperti yang terlihat pada data ramalan tersebut. Nilai akurasi dari ramalan tersebut dapat dilihat sebagai berikut. Data peramalan yang terbentuk adalah sebagai berikut.

data.frame("Forecast" = des.forecast$mean) %>% 
  knitr::kable(digits = 3)
Forecast
1281.917
1291.776
1301.634
1311.493
1321.351
1331.209
1341.068
1350.926
1360.785
1370.643
1380.501
1390.360
1400.218
1410.077
1419.935
1429.793
1439.652
1449.510
1459.369
1469.227
1479.085
1488.944
1498.802
1508.661
1518.519
1528.377
1538.236
1548.094
forecasr_accu_des <- accuracy(ts(des.forecast$mean, start = 1), ses_test_ts)[c(3, 5)] %>% as.data.frame()
colnames(forecasr_accu_des) <- "Galat Peramalan"
rownames(forecasr_accu_des) <- c("MAE", "MAPE")

Parameter optimum yang didapatkan adalah sebagai berikut.

data.frame("alpha" = des.forecast$model$alpha, 
           "beta" = des.forecast$model$beta) %>% 
  knitr::kable(digits = 3)
alpha beta
alpha 1 0.063

Nilai Akurasi

Metode pemulusan terbaik dapat ditentukan dengan melihat nilai akurasi tiap metode. Untuk mengetahui metode pemulusan dengan nilai akurasi yang tinggi, maka dihitung nilai kesalahan untuk setiap model pemulusan. Nilai kesalahan yang kecil menunjukan metode pemulusan tersebut baik. Tingkat kesalahan 5% artinya data ramalan yang dihasilkan dari metode tersebut sudah memiliki tingkat akurasi lebih dari 95% atau dengan kata lain peramalan dengan metode tersebut sudah akurat (Irawati dan Sinaga 2018 ).

Singgih dalam penelitian Irawati dan Sinaga (2018) menyebutkan bahwa untuk menghitung nilai kesalahan dapat dilakukan dengan menghitung nilai Mean Absolute Error (MAE) , Mean Square Error (MSE), Mean Absolute Percentage Error (MAPE), dan Root Square Mean Error (RSME).

  1. Mean Absolute Error (MAE)

    MAE digunakan untuk mengukur tingkat akurasi suatu peramalan dengan merata-ratakan kesalahan antara nilai peramalan dengan nilai aktual. Perhitungan nilai MAE didapatkan dengan rumus sebagai berikut.

    \[ MAE = \frac{\sum_{}e_i}{n} \]

  2. Mean Square Error (MSE)

    MSE mengukur tingkat akurasi dengan menjumlahkan kuadrat error atau selisih antara nilai peramalan dengan nilai aktual kemudian membaginya dengan jumlah observasi. Pendekatan ini menghasilkan nilai yang besar karena nilai error dikuadratkan. Perhtiungan nilai MSE didapatkan dengan rumus sebagai berikut.

    \[ MSE = \frac{\sum_{}e_i^2}{n} \]

  3. Mean Absolute Percentage Error (MAPE)

    MAPE adalah nilai rata-rata perbedaan absolut antara nilai peramalan dengan nilai aktual dan dinyatakan sebagai persentase nilai aktual. Nilai MAPE yang kecil menunjukan peramalan yang digunakan akurat. Perhtiungan nilai MAPE didapatkan dengan rumus sebagai berikut.

    \[ MAPE = \frac{1}{n}\sum_{}|\frac{x_i-\hat{x_i}}{x_i}|100\% \]

  4. Root Mean Square Error (RMSE) RMSE merupakan ukuran besarnya kesalahan antara jumlah kuadrat dari nilai peramalan dan nilai observasi. Nilai RMSE yang rendah menunjukan nilai ramalan mendekati nilai aktual.

    \[ RMSE = \sqrt{\frac{\sum_{}e_i^2}{n}} \]

Sebelumnya sudah didapatkan untuk double moving average nilai n optimum adalah 2 dan untuk double exponential smoothing nilai \(\alpha\) optimum adalah 1 dan \(\beta\) optimum adalah 0,06. Selanjutnya akan dibandingkan nilai akurasi untuk kedua metode tersebut.

```r
akurasi_dma_rmse <- DMA_test(dma_train_ts, dma_test_ts, 2, length(dma_test_ts))$akurasi_test[2]
akurasi_des_rmse <- accuracy(ts(des.forecast$mean, start = 1), ses_test_ts)[c(2)]
akurasi_dma_mae <- DMA_test(dma_train_ts, dma_test_ts, 2, length(dma_test_ts))$akurasi_test[c(3)]
akurasi_des_mae <- accuracy(ts(des.forecast$mean, start = 1), ses_test_ts)[c(3)]
akurasi_dma_mape <- DMA_test(dma_train_ts, dma_test_ts, 2, length(dma_test_ts))$akurasi_test[c(5)]
akurasi_des_mape <- accuracy(ts(des.forecast$mean, start = 1), ses_test_ts)[c(5)]
akurasi_dma_mse <- akurasi_dma_rmse**2
akurasi_des_mse <- akurasi_des_rmse**2
akurasi_gab <- data.frame(Model = c("Double Moving Average (n=2)", "Double Exponential Smoothing(alpha = 1, beta =0.06)"),(mae = c(akurasi_dma_mae, akurasi_des_mae)), (mape = c(akurasi_dma_mape, akurasi_des_mape)), (rmse = c(akurasi_dma_rmse, akurasi_des_rmse)), (rmse = c(akurasi_dma_mse, akurasi_des_mse)))
akurasi_gab %>% knitr::kable(digits = 5, row.names = F, col.names = c("Metode", "MAE", "MAPE","RMSE","MSE"), caption="Perbandingan Ukuran Nilai Kesalahan")
```



Table: Perbandingan Ukuran Nilai Kesalahan

|Metode                                              |      MAE|     MAPE|     RMSE|      MSE|
|:---------------------------------------------------|--------:|--------:|--------:|--------:|
|Double Moving Average (n=2)                         | 126.1595| 10.83880| 160.0078| 25602.49|
|Double Exponential Smoothing(alpha = 1, beta =0.06) | 127.7352| 11.21626| 169.8138| 28836.73|

Berdasarkan tabel perbandingan ukuran nilai kesalahan, metode pemulusan double moving average dengan parameter \(n = 2\) memiliki nilai MAPE, RMSE, dan MSE lebih kecil dibandingkan dengan metode pemulusan double exponential smoothing Sehingga, metode pemulusan double moving average dengan parameter \(n = 2\) merupakan metode terbaik .

Daftar Pustaka

Fajri R, Johan TM. 2017. Implementasi peramalan Double Exponential Smoothing pada kasus kekerasaan anak di pusat pelayanan terpadu pemberdayaan perempuan dan anak. Ecotipe. 4(2):6-13.

Rappai G. 2015. Modelling non-equidistant time series using spline interpolation. Hungarian Statistical Review. 19:22-46.

Layakana M, Iskandar S. 2020. Penerapan metode Double Moving Average dan Double Exponential Smoothing dalam meramalkan jumlah produksi Crude Palm Oil (CPO) pada PT. Perkebunan Nusantara IV Unit Dolok Sinumbah. Karismatika. 6(1):44-13.

Malik AD, Juliana A, Widyasella W. 2020. Perbandingan metode eksponensial smoothing dan Arima: studi pada perusahaan barang konsumsi di Indonesia. Moneter: Jurnal Akuntansi dan Keuangan. 7(2):180-185.

Makridakis S, Wheelright CS, McGee EV. 1998. Forecasting: Methods and Application (2nd edition). New Jersey: John Wiley & Sons.

Nazim A, Afthanorhan A. 2014. A comparison between single exponential smoothing (SES), double exponential model (DES), holt’s (brown) and adaptive response rate exponential smoothing (ARRES) techniques in forecasting Malaysia population. Global Journal of Mathematical Analysis. 2(4):276-280.

Sinaga HDE, Irawati N. 2018. Perbandingan Double Moving Average dengan Double Exponential Smoothing pada peramalan bahan medis habis pakai. JURTEKSI (Jurnal Teknologi dan Sistem Informasi).4(2).197-204.

Tambunan N, Aminda RS. 2021. Pengaruh inflasi, suku bunga, dan kurs terhadap Indeks Harga Saham Gabungan (IHSG). Outlook 2022: Transformasi UMKM di Era Pasar Digital; 2021 Desember 20; Sukoharjo. Sukoharjo (ID): Sekolah Tinggi Ilmu Ekonomi AAS. hlm 569-578.

Wang K. 2013. A study of cubic spline interpolation. InSight : Rivier Academic Journal. 4(9).

Wijaya TSJ. 2015. Faktor-faktor yang mempengaruhi nilai IHSG yang terdaftar di Bursa Efek Indonesia. Jurnal Ilmu dan Riset Manajemen. 4(6):1-16.