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)
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.
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"
)
| 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 |
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")
| 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")
| 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.
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.")
| 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.
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).
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).
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:
Menghitung rata-rata bergerak pertama
\[ S_{t} =\frac{Y_{t} + Y_{t-1}+…+Y_{t-n-1}}{n} \]
Menghitung rata-rata bergerak kedua
\[ S'_{t} =\frac{S_{t} + S_{t-1}+…+S_{t-n-1}}{n} \]
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 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:
Menentukan smoothing pertama \[ S'_{t} =\alpha X_{t}+(1-\alpha)S'_{t-1} \]
Menentukan smoothing kedua \[ S''_{t} =\alpha S'_{t}+(1-\alpha)S''_{t-1} \]
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 |
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).
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} \]
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} \]
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\% \]
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 .
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.