Nilai tukar, atau kurs, adalah perbandingan nilai antara mata uang suatu negara dengan mata uang negara lain, yang berfungsi sebagai jembatan untuk menyamakan harga barang dan jasa dalam berbagai mata uang.
Belakangan ini, pelemahan rupiah terhadap dolar AS terus berlanjut, sehingga setiap satuan valuta asing menjadi lebih mahal jika dikonversi ke rupiah. Puncak dari melemah nya kurs rupiah terhadap dolar AS terjadi pada tanggal 8 sampai 9 April 2025 ini, dengan nilai tukar 1 USD sebesar Rp 16.860,-
Kondisi ini menimbulkan kekhawatiran di banyak pihak, mulai dari pemerintah yang harus mengatur kebijakan moneter dan fiskal, pelaku usaha yang menghadapi biaya impor bahan baku yang meningkat, hingga masyarakat umum yang merasakan dampak kenaikan harga barang sehari-hari. Investor pun turut mencermati pergerakan ini karena berpotensi memengaruhi aliran modal dan prospek investasi di dalam negeri. Dengan demikian, stabilitas kurs rupiah menjadi isu sentral yang menuntut perhatian dan langkah antisipatif dari semua pihak.
Berdasarkan latar belakang tersebut, diperlukan analisis lebih lanjut untuk memproyeksikan pergerakan nilai tukar rupiah dalam beberapa periode ke depan, sehingga pemerintah dapat merumuskan kebijakan yang tepat, dan investor maupun pelaku usaha dapat mengambil keputusan strategis yang lebih matang. Adapun analisis pada penelitian ini menggunakan model ARIMA, Neural Network, dan Moving Average.
library(MASS)
library(hms)
library(car)
## Loading required package: carData
library(forecast)
## Warning: package 'forecast' was built under R version 4.4.3
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(tseries)
library(timeSeries)
## Loading required package: timeDate
##
## Attaching package: 'timeSeries'
## The following objects are masked from 'package:graphics':
##
## lines, points
library(quadprog)
library(zoo)
## Warning: package 'zoo' was built under R version 4.4.3
##
## Attaching package: 'zoo'
## The following object is masked from 'package:timeSeries':
##
## time<-
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
library(fracdiff)
library(fUnitRoots)
library(lmtest)
library(nortest)
library(MLmetrics)
## Warning: package 'MLmetrics' was built under R version 4.4.3
##
## Attaching package: 'MLmetrics'
## The following object is masked from 'package:base':
##
## Recall
library(Metrics)
## Warning: package 'Metrics' was built under R version 4.4.3
##
## Attaching package: 'Metrics'
## The following object is masked from 'package:forecast':
##
## accuracy
library(neuralnet)
## Warning: package 'neuralnet' was built under R version 4.4.3
library(dplyr)
##
## Attaching package: 'dplyr'
## The following object is masked from 'package:neuralnet':
##
## compute
## The following objects are masked from 'package:timeSeries':
##
## filter, lag
## The following object is masked from 'package:car':
##
## recode
## The following object is masked from 'package:MASS':
##
## select
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(tensorflow)
## Warning: package 'tensorflow' was built under R version 4.4.3
library(keras3)
##
## Attaching package: 'keras3'
## The following objects are masked from 'package:tensorflow':
##
## set_random_seed, shape
library(TTR)
Data yang digunakan dalam penelitian ini adalah data harian nilai tukar rupiah terhadap dolar AS periode 1 April 2024 hingga 30 April 2025. Adapun sumber data diperoleh dari laman website : https://www.investing.com/currencies/usd-idr-historical-data
import_data = read.csv(file.choose(), header = T, sep = ",")
head(import_data)
## Date Price Open High Low Vol. Change..
## 1 9/2/2024 15520 15497.5 15555.0 15492.5 NA 0.45%
## 2 9/3/2024 15520 15547.5 15583.5 15522.5 NA 0.00%
## 3 9/4/2024 15470 15530.0 15542.5 15470.0 NA -0.32%
## 4 9/5/2024 15395 15422.5 15432.5 15394.0 NA -0.48%
## 5 9/6/2024 15360 15390.0 15398.5 15352.0 NA -0.23%
## 6 9/9/2024 15450 15475.0 15485.0 15416.0 NA 0.59%
kurs_rupiah = ts(data = import_data$Price)
cat("total data :",length(kurs_rupiah))
## total data : 172
ts.plot(kurs_rupiah, main = "Nilai Tukar Rupiah Terhadap Dolar AS", ylab = "Nilai Tukar")
points(kurs_rupiah, cex = 0.8, pch = 21)
grid()
Berdasarkan time series plot diatas dapat diketahui bahwa nilai tukar rupiah mengalami fluktuasi di tiap periode nya dan cenderung mengalami trend naik.
Sebelum melakukan tahap analisis menggunakan model Autoregressive Integrated Moving Average (ARIMA), Moving Average (MA) dan Neural Network (NN) dilakukan tahap pembagian data atau splitting data dengan rasio 85% untuk data training dan 15% untuk data testing atau dapat ditulis sebagai 85:15
jumlah_train = round(NROW(kurs_rupiah)*0.85,0)
jumlah_test = NROW(kurs_rupiah)-jumlah_train
data_train = kurs_rupiah[1:jumlah_train]
data_test = kurs_rupiah[(jumlah_train+1):(jumlah_test+jumlah_train)]
cat("Jumlah data train =",jumlah_train,"\nJumlah data test =",jumlah_test)
## Jumlah data train = 146
## Jumlah data test = 26
Model ARIMA merupakan salah satu model statistik yang digunakan untuk menganalisis (memprediksi serta meramalkan) data runtun waktu. Model ini merupakan gabungan dari model Autoregressive (AR), model Integrated (I), dan model Moving Average (MA). Adapun persamaan dari model ARIMA dapat ditulis sebagai berikut.
\[\phi_p(B)(1-B)^dZ_t=\theta_q(B)\varepsilon_t\]
Berikut langkah-langkah dalam melakukan pemodelan ARIMA
Dalam melakukan pemodelan ARIMA, maka tahapan awal yang harus dilakukan adalah melakukan stasioneritas pada data, hal ini dikarenakan dalam melakukan pemodelan ARIMA harus memenuhi syarat stasioneritas data. Terdapat dua tahapan dalam stasioneritas yaitu stasioneritas terhadap variansi dan stasioneritas terhadap rata-rata.
boxcox(data_train~1,lambda = seq(-9,32,by=1))
nilai = powerTransform(data_train)
nilai$lambda
## data_train
## 10.84763
Karena nilai \(\lambda\) yang dihasilkan adalah 10,847 dimana nilai tersebut tidak mendekati 1 maka dapat dilakukan tahapan transformasi.
| \(\lambda\) | Transformasi |
|---|---|
| -2 | \(y^-2\) |
| -1 | \(y^-1\) |
| -0,5 | \(\frac{1}{\sqrt{y}}\) |
| 0 | \(log(y)\) |
| 0,5 | \(\sqrt{y}\) |
| 1 | \(y\) |
| 2 | \(y^2\) |
dikarenakan jika kita memangkatkan data dengan 10,847 akan membuat data lebih besar maka kita dapat melakukan proses transformasi data dengan cara log.
data_trans = log(data_train)
head(data_trans)
## [1] 9.649885 9.649885 9.646658 9.641798 9.639522 9.645364
Setelah melakukan tahap transformasi maka dilakukan tahap stasioneritas rata-rata. Pengecekan stasioneritas rata-rata dapat dilakukan dengan melihat grafik Autocorrelation Function (ACF) dan uji Augmented Dickey Fuller (ADF).
acf(data_trans, lag.max = 1/4*NROW(data_trans), main = "Grafik ACF Data Transformasi")
Berdasarkan grafik diatas dapat diketahui bahwa nilai ACF mengalami turun secara eksponensial, maka dapat disimpulkan bahwa data transformasi belum stasioner dalam rata-rata. Untuk dapat menguatkan keputusan, maka dilakukan pengujian ADF sebagai berikut.
adfTest(data_trans)
##
## Title:
## Augmented Dickey-Fuller Test
##
## Test Results:
## PARAMETER:
## Lag Order: 1
## STATISTIC:
## Dickey-Fuller: 1.3578
## P VALUE:
## 0.9549
##
## Description:
## Tue May 13 12:33:42 2025 by user: ASUS
Dikarenakan nilai p-value ADF test lebih dari taraf signifikansi, maka diputuskan \(H_0\) gagal ditolak. Sehingga disimpulkan data belum stasioner dalam rata-rata. Kemudian dilakukan tahap differencing sebagai berikut.
diff_1 = diff(data_trans, differences = 1, lag = 1)
head(diff_1)
## [1] 0.000000000 -0.003226850 -0.004859883 -0.002276054 0.005842276
## [6] -0.000323677
adfTest(diff_1)
## Warning in adfTest(diff_1): p-value smaller than printed p-value
##
## Title:
## Augmented Dickey-Fuller Test
##
## Test Results:
## PARAMETER:
## Lag Order: 1
## STATISTIC:
## Dickey-Fuller: -7.8593
## P VALUE:
## 0.01
##
## Description:
## Tue May 13 12:33:42 2025 by user: ASUS
Setelah dilakukan proses differencing, maka dapat disimpulkan bahwa data sudah stasioner dalam rata-rata.
Identifikasi model ARIMA dapat dilakukan dengan melihat grafik Autocorrelation Function (ACF) dan Partial Autocorrelation Function (PACF)
acf(diff_1, 1/4*NROW(diff_1), main = "ACF diff 1")
grid()
pacf(diff_1, 1/4*NROW(diff_1), main = "PACF diff 1")
grid()
Dikarenakan saat melakukan tahap identifikasi model pada grafik ACF dan PACF nya tidak ada nilai ACF yang keluar maka akan dilakukan tahap differencing kedua
diff_2 = diff(data_trans, differences = 2, lag = 1)
head(diff_2)
## [1] -0.003226850 -0.001633033 0.002583830 0.008118329 -0.006165953
## [6] -0.002918868
acf(diff_2, 1/4*NROW(diff_2), main = "ACF diff 2")
grid()
pacf(diff_2, 1/4*NROW(diff_2), main = "PACF diff 2")
grid()
Berdasarkan grafik ACF dan PACF data differencing kedua maka diketahui bahwa nilai ACF cut off setelah lag kedua, maka orde untuk MA (q) adalah 2. Sedangkan nilai PACF cut off setelah lag keempat sehingga diketahui bahwa orde AR (p) adalah 4. Oleh karena itu, terdapat
ARIMA (0,2,1)
ARIMA (0,2,2)
ARIMA (1,2,0)
ARIMA (2,2,0)
ARIMA (3,2,0)
ARIMA (4,2,0)
ARIMA (1,2,1)
ARIMA (2,2,1)
ARIMA (3,2,1)
ARIMA (4,2,1)
ARIMA (1,2,2)
ARIMA (2,2,2)
ARIMA (3,2,2)
ARIMA (4,2,2)
model1 = Arima(data_trans, order = c(0,2,1))
model2 = Arima(data_trans, order = c(0,2,2))
model3 = Arima(data_trans, order = c(1,2,0))
model4 = Arima(data_trans, order = c(2,2,0))
model5 = Arima(data_trans, order = c(3,2,0))
model6 = Arima(data_trans, order = c(4,2,0))
model7 = Arima(data_trans, order = c(1,2,1))
model8 = Arima(data_trans, order = c(2,2,1))
model9 = Arima(data_trans, order = c(3,2,1))
model10 = Arima(data_trans, order = c(4,2,1))
model11 = Arima(data_trans, order = c(1,2,2))
model12 = Arima(data_trans, order = c(2,2,2))
model13 = Arima(data_trans, order = c(3,2,2))
model14 = Arima(data_trans, order = c(4,2,2))
db = NROW(data_trans)
cat("========== MODEL 1 ==========")
## ========== MODEL 1 ==========
coeftest(model1, df = db-1)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ma1 -0.999999 0.020836 -47.994 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("========== MODEL 2 ==========")
## ========== MODEL 2 ==========
coeftest(model2, df = db-2)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ma1 -0.963997 0.082772 -11.6465 <2e-16 ***
## ma2 -0.036002 0.080195 -0.4489 0.6542
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("========== MODEL 3 ==========")
## ========== MODEL 3 ==========
coeftest(model3, df = db-1)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ar1 -0.497446 0.071918 -6.9168 1.37e-10 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("========== MODEL 4 ==========")
## ========== MODEL 4 ==========
coeftest(model4, df = db-2)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ar1 -0.641753 0.080067 -8.0152 3.434e-13 ***
## ar2 -0.284209 0.079916 -3.5563 0.0005094 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("========== MODEL 5 ==========")
## ========== MODEL 5 ==========
coeftest(model5, df = db-3)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ar1 -0.701137 0.081478 -8.6052 1.241e-14 ***
## ar2 -0.420483 0.093916 -4.4772 1.534e-05 ***
## ar3 -0.213099 0.081672 -2.6092 0.01004 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("========== MODEL 6 ==========")
## ========== MODEL 6 ==========
coeftest(model6,df = db-4)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ar1 -0.743000 0.081537 -9.1124 6.905e-16 ***
## ar2 -0.504074 0.098126 -5.1370 9.052e-07 ***
## ar3 -0.356438 0.098760 -3.6091 0.000425 ***
## ar4 -0.204274 0.082737 -2.4690 0.014737 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("========== MODEL 7 ==========")
## ========== MODEL 7 ==========
coeftest(model7, df = db-2)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ar1 0.038782 0.083486 0.4645 0.643
## ma1 -0.999999 0.020470 -48.8527 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("========== MODEL 8 ==========")
## ========== MODEL 8 ==========
coeftest(model8, df = db-3)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ar1 0.037958 0.083475 0.4547 0.6500
## ar2 0.036141 0.083499 0.4328 0.6658
## ma1 -0.999996 0.020219 -49.4575 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("========== MODEL 9 ==========")
## ========== MODEL 9 ==========
coeftest(model9, df = db-4)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ar1 0.038956 0.083402 0.4671 0.6412
## ar2 0.036568 0.083404 0.4384 0.6617
## ar3 -0.037238 0.083964 -0.4435 0.6581
## ma1 -0.999999 0.020422 -48.9661 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("========== MODEL 10 ==========")
## ========== MODEL 10 ==========
coeftest(model10, df = db-5)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ar1 0.035744 0.083366 0.4288 0.6687
## ar2 0.037721 0.083301 0.4528 0.6514
## ar3 -0.036161 0.083795 -0.4315 0.6667
## ar4 -0.053985 0.084429 -0.6394 0.5236
## ma1 -0.999993 0.020668 -48.3847 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("========== MODEL 11 ==========")
## ========== MODEL 11 ==========
coeftest(model11, df = db-3)
## Warning in sqrt(diag(se)): NaNs produced
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ar1 -0.76169 NaN NaN NaN
## ma1 -0.23767 NaN NaN NaN
## ma2 -0.76233 NaN NaN NaN
cat("========== MODEL 12 ==========")
## ========== MODEL 12 ==========
coeftest(model12, df = db-4)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ar1 -0.791633 0.475210 -1.6659 0.09795 .
## ar2 0.050019 0.084019 0.5953 0.55257
## ma1 -0.169223 0.468480 -0.3612 0.71847
## ma2 -0.830770 0.468340 -1.7739 0.07823 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("========== MODEL 13 ==========")
## ========== MODEL 13 ==========
coeftest(model13, df = db-5)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ar1 0.959744 0.103560 9.2675 2.938e-16 ***
## ar2 -0.010023 0.114102 -0.0878 0.9301
## ar3 -0.091822 0.085550 -1.0733 0.2850
## ma1 -1.957489 0.069262 -28.2621 < 2.2e-16 ***
## ma2 0.957533 0.069144 13.8484 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("========== MODEL 14 ==========")
## ========== MODEL 14 ==========
coeftest(model14, df = db-6)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## ar1 0.93576636 0.10988792 8.5156 2.33e-14 ***
## ar2 -0.00041231 0.11331871 -0.0036 0.9971
## ar3 -0.06960022 0.11330101 -0.6143 0.5400
## ar4 -0.03396384 0.08708066 -0.3900 0.6971
## ma1 -1.93550453 0.07952193 -24.3393 < 2.2e-16 ***
## ma2 0.93561176 0.07941843 11.7808 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Berdasarkan hasil pengujian signifikansi parameter terdapat 5 model ARIMA yang signifikan yaitu model ARIMA (0,2,1), ARIMA (1,2,0), ARIMA (2,2,0), ARIMA (3,2,0), dan ARIMA (4,2,0). Kemudian dari keempat model yang terbentuk akan dilakukan tahap pengujian diagnostik model
Terdapat dua pengujian diagnostik model, yakni pengujian normalitas residual model ARIMA dan pengujian independensi residual model ARIMA (white noise)
Pengujian normalitas residual model ARIMA dilakukan menggunakan uji
lillie.test(resid(model1))
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: resid(model1)
## D = 0.056696, p-value = 0.2997
lillie.test(resid(model3))
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: resid(model3)
## D = 0.05716, p-value = 0.288
lillie.test(resid(model4))
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: resid(model4)
## D = 0.053589, p-value = 0.3854
lillie.test(resid(model5))
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: resid(model5)
## D = 0.042326, p-value = 0.7535
lillie.test(resid(model6))
##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: resid(model6)
## D = 0.036209, p-value = 0.9109
Berdasarkan pengujian normalitas menggunakan uji Kolmogorov-Smirnov maka dapat disimpulkan bahwa seluruh model ARIMA memenuhi asumsi normalitas residual.
##### MODEL 3 ########
p_val_model1 = NROW(resid(model1))
for (i in 1:p_val_model1) {
model1_box = Box.test(resid(model1), lag = i, type = "Ljung-Box")
p_val_model1[i] = model1_box$p.value
}
# Plot p-value
plot(1:NROW(resid(model1)), p_val_model1, type = "p", pch = 1 ,xlab = "Lag", ylab = "p-value", main = "Ljung-Box Model 1 ARIMA(0,2,1)", ylim = c(0,1))
abline(h = 0.05, col = "blue", lty = 2)
##### MODEL 3 ########
p_val_model3 = NROW(resid(model3))
for (i in 1:p_val_model3) {
model3_box = Box.test(resid(model3), lag = i, type = "Ljung-Box")
p_val_model3[i] = model3_box$p.value
}
# Plot p-value
plot(1:NROW(resid(model3)), p_val_model3, type = "p", pch = 1 ,xlab = "Lag", ylab = "p-value", main = "Ljung-Box Model 3 ARIMA(1,2,0)", ylim = c(0,1))
abline(h = 0.05, col = "blue", lty = 2)
##### MODEL 4 ########
p_val_model4 = NROW(resid(model4))
for (i in 1:p_val_model4) {
model4_box = Box.test(resid(model4), lag = i, type = "Ljung-Box")
p_val_model4[i] = model4_box$p.value
}
# Plot p-value
plot(1:NROW(resid(model4)), p_val_model4, type = "p", pch = 1 ,xlab = "Lag", ylab = "p-value", main = "Ljung-Box Model 4 ARIMA(2,2,0)", ylim = c(0,1))
abline(h = 0.05, col = "blue", lty = 2)
##### MODEL 5 ########
p_val_model5 = NROW(resid(model5))
for (i in 1:p_val_model5) {
model5_box = Box.test(resid(model5), lag = i, type = "Ljung-Box")
p_val_model5[i] = model5_box$p.value
}
# Plot p-value
plot(1:NROW(resid(model5)), p_val_model5, type = "p", pch = 1 ,xlab = "Lag", ylab = "p-value", main = "Ljung-Box Model 5 ARIMA(3,2,0)", ylim = c(0,1))
abline(h = 0.05, col = "blue", lty = 2)
##### MODEL ########
p_val_model6 = NROW(resid(model6))
for (i in 1:p_val_model6) {
model6_box = Box.test(resid(model6), lag = i, type = "Ljung-Box")
p_val_model6[i] = model6_box$p.value
}
# Plot p-value
plot(1:NROW(resid(model6)), p_val_model6, type = "p", pch = 1 ,xlab = "Lag", ylab = "p-value", main = "Ljung-Box Model 6 ARIMA(4,2,0)", ylim = c(0,1))
abline(h = 0.05, col = "blue", lty = 2)
Menggunakan uji Ljung-Box Test model yang memenuhi asumsi normalitas dan independensi residual adalah model ARIMA (4,2,0).
Setelah didapatkan model ARIMA yang memenuhi asumsi normalitas residual dan independensi residual, kemudian pada tahapan ini akan dilakukan prediksi dan peramalan menggunakan model ARIMA (4,2,0).
prediksi_arima = exp(fitted.values(model6))
head(prediksi_arima)
## Time Series:
## Start = 1
## End = 6
## Frequency = 1
## [1] 15453.17 15722.24 15510.03 15441.00 15350.86 15321.26
ramal_arima = exp(predict(model6, n.ahead =28)$pred)
head(ramal_arima)
## Time Series:
## Start = 147
## End = 152
## Frequency = 1
## [1] 16583.22 16621.64 16641.21 16673.99 16709.27 16741.86
Berdasarkan tahapan prediksi dan peramalan, berikut disajikan grafik prediksi dan peramalan model ARIMA (4,2,0).
plot(1:172,kurs_rupiah, type = "l", main = "Grafik Prediksi dan Peramalan ARIMA", ylab = "Nilai Kurs IDR", xlab = "Time", ylim = c(15000,17500))
points(kurs_rupiah, cex = 0.9, pch = 21)
lines(1:146,prediksi_arima, col = "blue")
lines(147:172,ramal_arima[1:26], col = "red")
lines(173:174,ramal_arima[27:28], col = "green")
abline(v = 146, lty = 2)
abline(v = 172, lty = 2)
legend("topleft", legend = c("Data aktual","Prediksi In sample", "Prediksi Out Sample", "Peramalan"),
col = c("black","blue","red","green"), lty = 1, pch = 20, lwd = 3, bty = "o", cex = 0.8)
grid()
Berdasarkan grafik time series nilai tukar Rupiah terhadap Dolar AS, tampak bahwa hasil prediksi dari model ARIMA mampu mengikuti pola data historis dengan cukup baik. Prediksi dalam in-sample menunjukkan kesesuaian yang tinggi terhadap data aktual, sementara prediksi out-sample juga masih mencerminkan arah tren yang serupa. Peramalan jangka pendek yang dilakukan menunjukkan kecenderungan peningkatan nilai tukar, meskipun hanya untuk dua hari ke depan. Secara keseluruhan, model ARIMA menunjukkan performa yang baik dalam memodelkan dan memproyeksikan pergerakan nilai tukar, khususnya dalam jangka pendek.
Evaluasi model ARIMA dilakukan dengan menggunakan tiga metrik utama, yaitu MAPE (Mean Absolute Percentage Error), SMAPE (Symmetric Mean Absolute Percentage Error), dan RMSE (Root Mean Squared Error). Berikut adala hasil evaluasi untuk model ARIMA yang dibangun:
in_sample_arima = c(
MAPE_Arima_in = MAPE(prediksi_arima,data_train)*100,
SMAPE_Arima_in = smape(data_train, prediksi_arima)*100,
RMSE_Arima_in = RMSE(prediksi_arima, data_train)
)
out_sample_arima = c(
MAPE_Arima_out = MAPE(ramal_arima[1:26], data_test) * 100,
SMAPE_Arima_out = smape(data_test, ramal_arima[1:26]) * 100,
RMSE_Arima_out = RMSE(ramal_arima[1:26], data_test)
)
hasil_evaluasi_arima = data.frame(
Metrik = c("MAPE (%)", "SMAPE (%)", "RMSE"),
In_Sample = round(in_sample_arima, 3),
Out_Sample = round(out_sample_arima, 3),
row.names = NULL
)
# Menampilkan tabel
hasil_evaluasi_arima
## Metrik In_Sample Out_Sample
## 1 MAPE (%) 0.343 1.599
## 2 SMAPE (%) 0.343 1.582
## 3 RMSE 68.279 312.756
Berdasarkan hasil evaluasi model ARIMA, dapat disimpulkan bahwa model ini menunjukkan akurasi yang sangat baik pada data pelatihan dengan nilai MAPE dan SMAPE yang rendah, yaitu 0.343%, serta RMSE sebesar 68.279. Namun, pada data uji, akurasi model menurun dengan MAPE sebesar 1.599%, SMAPE 1.582%, dan RMSE 312.756, yang menunjukkan adanya peningkatan kesalahan prediksi. Meskipun model ARIMA cukup baik untuk meramalkan nilai tukar rupiah terhadap dolar AS pada data yang telah ada, performanya perlu ditingkatkan agar lebih robust dalam menghadapi fluktuasi nilai tukar di periode mendatang.
Neural network merupakan model komputasi yang merupakan bagian dari kecerdasan buatan dan terinspirasi dari jaringan saraf dan struktur otak manusia.
Model ini dapat digunakan untuk mempelajari pola-pola kompleks dalam data termasuk untuk melakukan prediksi dan peramalan. Struktur neural network terdiri dari beberapa lapisan yaitu input layer, hidden layer,output layer dan fungsi aktivasi.
Input layer yaitu lapisan masukan yang memiliki beberapa neuron input yang tidak memiliki fungsi transfer, namun memiliki faktor skala di setiap input untuk mentransimisikan sinyal pada faktor skala di setiap input.
Hidden layer merupakan lapisan yang menghubungkan input dan output layer dengan melalui bobot yang dihitung ke lapisan keluaran.
Output layer merupakan lapisan keluaran yang terdiri dari satu atau beberapa neuron yang mewakili sebuah kelas dari kumpulan data keluaran.
Fungsi aktivasi merupakan fungsi yang menentukan bagaimana neuron memproses sinyal input dan mengirimkannya ke lapisan berikutnya.
Pada penelitian ini tahapan training model neural network dimulai dari tahap standarisasi data, kemudian menentukan variabel masukan, pelatihan algoritma yang digunakan yang pada penelitian ini menggunakan resilient backpropagation, kemudian dilakukan destandarisasi data, lalu pemilihan neural network terbaik, lalu melakukan peramalan.
Dilakukan standarisasi data dikarenakan data observasi memiliki perbedaan nilai yang cukup besar, dapat dilihat juga dari grafik time series plot diawal analisis yang cenderung menunjukkan pola trend. Standarisasi dilakukan sehingga data observasi dapat berfluktuasi disekitar rata-rata
max_asli = max(kurs_rupiah)
min_asli = min(kurs_rupiah)
data_standarisasi = 2*((as.numeric(kurs_rupiah) - min_asli)/(max_asli - min_asli))-1
head(data_standarisasi)
## [1] -0.5197740 -0.5197740 -0.5762712 -0.6610169 -0.7005650 -0.5988701
Setelah mendapatkan data yang terstandarisasi kemudian dilakukan tahapan pembentukan data input pada model Neural Network dengan melihat nilai PACF yang signifikan.
pacf(data_standarisasi, main = "PACF Data Standarisasi", lag.max = 80)
grid()
Variabel masukan dipilih berdasarkan pada lag yang signifikan pada grafik PACF, dan berdasarkan output yang terlihat, dapat diketahui bahwa nilai PACF signifikan pada lag ke-1 sehingga lag ini menjadi variabel masukannya. Selanjutnya, data keluaran yang digunakan dilambangkan dengan Y. Data Y ini yaitu data kurs nilai tukar rupiah terhadap dollar setelah standarisasi yang selanjutnya data masukan dan keluaran dimulai dari t=2.
Kemudian dilakukan proses pelatihan Resilient Backpropagation dengan maksimal 2 hidden layer proses dengan 1 neuron, 2 neuron dan 3 neuron. Kondisi pemberhentian yang digunakan adalah maksimum iterasi sebesar 10.000 target dan target eror sebesar 0,005. Diperoleh hasil pelatihan sebagai berikut:
y = data.frame(
nilai_asli = data_standarisasi
) %>%
mutate(
nilai_lag = dplyr::lag(nilai_asli, n = 1, default = NA)
)
head(y)
## nilai_asli nilai_lag
## 1 -0.5197740 NA
## 2 -0.5197740 -0.5197740
## 3 -0.5762712 -0.5197740
## 4 -0.6610169 -0.5762712
## 5 -0.7005650 -0.6610169
## 6 -0.5988701 -0.7005650
trainy = y[1:length(data_train),]
trainy = na.omit(trainy)
testy = y[length(data_train)+1:172,]
head(trainy)
## nilai_asli nilai_lag
## 2 -0.5197740 -0.5197740
## 3 -0.5762712 -0.5197740
## 4 -0.6610169 -0.5762712
## 5 -0.7005650 -0.6610169
## 6 -0.5988701 -0.7005650
## 7 -0.6045198 -0.5988701
head(testy)
## nilai_asli nilai_lag
## 147 0.6892655 0.6440678
## 148 0.6723164 0.6892655
## 149 0.6497175 0.6723164
## 150 0.6497175 0.6497175
## 151 0.6497175 0.6497175
## 152 0.6497175 0.6497175
attach(trainy)
attach(testy)
## The following objects are masked from trainy:
##
## nilai_asli, nilai_lag
Selanjutnya yaitu melakukan destandarisasi data dari hasil pelatihan algoritma Resilient Backpropagation dengan menggunakan 1 neuron, 2 neuron dan 3 neuron pada kedua hidden layer. 1 hidden layer
predict_NN1 = ts(mlp_1_1$net.result[[1]])
kembali_NN1 = ((predict_NN1 + 1) / 2) * (max(kurs_rupiah) - min(kurs_rupiah)) + min(kurs_rupiah)
predict_NN2 = ts(mlp_1_2$net.result[[1]])
kembali_NN2 = ((predict_NN2 + 1) / 2) * (max(kurs_rupiah) - min(kurs_rupiah)) + min(kurs_rupiah)
predict_NN3 = ts(mlp_1_3$net.result[[1]])
kembali_NN3 = ((predict_NN3 + 1) / 2) * (max(kurs_rupiah) - min(kurs_rupiah)) + min(kurs_rupiah)
Tahap selanjutnya yaitu melakukan pemilihan neural network terbaik dengan menggunakan kriteria MAPE, RMSE, dan SMAPE. Adapun hasil analisis diperoleh sebagai berikut:
MAPE_pemilihan_nn = c(
MAPE_NN1 = MAPE(ts(kembali_NN1),ts(data_train[2:146]))*100,
MAPE_NN2 = MAPE(ts(kembali_NN2),ts(data_train[2:146]))*100,
MAPE_NN3 = MAPE(ts(kembali_NN3),ts(data_train[2:146]))*100,
MAPE_NN_11 = MAPE(ts(kembali_NN_1_1),ts(data_train[2:146]))*100,
MAPE_NN_12 = MAPE(ts(kembali_NN_1_2),ts(data_train[2:146]))*100,
MAPE_NN_13 = MAPE(ts(kembali_NN_1_3),ts(data_train[2:146]))*100,
MAPE_NN_21 = MAPE(ts(kembali_NN_2_1),ts(data_train[2:146]))*100,
MAPE_NN_22 = MAPE(ts(kembali_NN_2_2),ts(data_train[2:146]))*100,
MAPE_NN_23 = MAPE(ts(kembali_NN_2_3),ts(data_train[2:146]))*100
)
RMSE_pemilihan_nn = c(
RMSE_NN1 = RMSE(ts(data_train[2:146]),ts(kembali_NN1)),
RMSE_NN2 = RMSE(ts(kembali_NN2),ts(data_train[2:146])),
RMSE_NN3 = RMSE(ts(kembali_NN3),ts(data_train[2:146])),
RMSE_NN_11 = RMSE(ts(kembali_NN_1_1),ts(data_train[2:146])),
RMSE_NN_12 = RMSE(ts(kembali_NN_1_2),ts(data_train[2:146])),
RMSE_NN_13 = RMSE(ts(kembali_NN_1_3),ts(data_train[2:146])),
RMSE_NN_21 = RMSE(ts(kembali_NN_2_1),ts(data_train[2:146])),
RMSE_NN_22 = RMSE(ts(kembali_NN_2_2),ts(data_train[2:146])),
RMSE_NN_23 = RMSE(ts(kembali_NN_2_3),ts(data_train[2:146]))
)
SMAPE_pemilihan_nn = c(
SMAPE_NN1 = smape(ts(data_train[2:146]),ts(kembali_NN1))*100,
SMAPE_NN2 = smape(ts(data_train[2:146]),ts(kembali_NN2))*100,
SMAPE_NN3 = smape(ts(data_train[2:146]),ts(kembali_NN3))*100,
SMAPE_NN_11 = smape(ts(data_train[2:146]),ts(kembali_NN_1_1))*100,
SMAPE_NN_12 = smape(ts(data_train[2:146]),ts(kembali_NN_1_2))*100,
SMAPE_NN_13 = smape(ts(data_train[2:146]),ts(kembali_NN_1_3))*100,
SMAPE_NN_21 = smape(ts(data_train[2:146]),ts(kembali_NN_2_1))*100,
SMAPE_NN_22 = smape(ts(data_train[2:146]),ts(kembali_NN_2_2))*100,
SMAPE_NN_23 = smape(ts(data_train[2:146]),ts(kembali_NN_2_3))*100
)
Nama_baris_pemilihan_NN = c(
"NN (1)",
"NN (2)",
"NN (3)",
"NN (1,1)",
"NN (1,2)",
"NN (1,3)",
"NN (2,1)",
"NN (2,2)",
"NN (2,3)"
)
pemilihan_nn_terbaik = data.frame(
pilih_mape = round(MAPE_pemilihan_nn, 3),
pilih_rmse = round(RMSE_pemilihan_nn, 3),
pilih_smape = round(SMAPE_pemilihan_nn, 3),
row.names = Nama_baris_pemilihan_NN
)
colnames(pemilihan_nn_terbaik) = c("MAPE", "RMSE", "SMAPE")
pemilihan_nn_terbaik
## MAPE RMSE SMAPE
## NN (1) 0.294 59.071 0.294
## NN (2) 0.294 59.127 0.294
## NN (3) 0.295 59.125 0.295
## NN (1,1) 0.293 59.104 0.294
## NN (1,2) 0.292 58.992 0.292
## NN (1,3) 0.294 59.103 0.294
## NN (2,1) 0.291 59.105 0.292
## NN (2,2) 0.295 59.195 0.295
## NN (2,3) 0.292 59.026 0.292
Berdasarkan hasil evaluasi, dapat dilihat bahwa dari 1 neuron, 2 neuron dan 3 neuron pada kedua hidden layer cenderung menghasilkan nilai akurasi yang mirip, yang kemampuan peramalan yang sangat baik karena mengahasilkan MAPE dibawah 10% dan SMAPE yang juga dibawah 10%, selain itu nilai RMSE yang dihasilkan juga cukup kecil dimana keseluruhan modek Neural Network yang dibentuk memiliki error berkisar disekitar Rp 59. Sehingga dapat diambil kesimpulan bahwa model Neural Network terbaik adalah model NN dengan 1 neuron pada hidden layer pertama dan 2 neuron pada hidden layer kedua.
Setelah diperoleh NN terbaik, selanjutnya yaitu melakukan prediksi pada outsample untuk 26 hari serta peramalan untuk 2 hari kedepannya menggunakan model NN dengan 1 neuron pada hidden layer pertama dan 2 neuron pada hidden layer kedua.
last_lag = tail(trainy$nilai_asli, 1)
forecast_normalized <- numeric(28)
current_lag = last_lag
for (i in 1:28) {
new_data = data.frame(nilai_lag = current_lag)
pred = neuralnet::compute(mlp_2_1_2, covariate = new_data)
forecast_normalized[i] = pred$net.result[1, 1]
current_lag = forecast_normalized[i]
}
forecast_denormalized = ((forecast_normalized + 1) / 2) * (max_asli - min_asli) + min_asli
head(forecast_denormalized)
## [1] 16495.95 16461.67 16438.36 16421.80 16409.67 16400.60
Setelah diperoleh NN terbaik, selanjutnya yaitu melakukan prediksi pada outsample untuk 26 hari serta peramalan untuk 2 hari kedepannya dengan menggunakan metode NN 2 neuron dengan hidden layer pertama menggunakan 1 neuron dan hidden layer kedua menggunakan 2 neuron.
Hasil_NN = ts(c(NA,kembali_NN_1_2,forecast_denormalized[1:26],forecast_denormalized[27:28]))
plot(1:172,kurs_rupiah, type = "l", main = "Grafik Prediksi dan Peramalan NN", ylab = "Nilai Kurs IDR", xlab = "Time")
points(kurs_rupiah, cex = 0.9, pch = 21)
lines(1:146,Hasil_NN[1:146], col = "blue")
lines(147:172,Hasil_NN[147:172], col = "red")
lines(173:174,Hasil_NN[173:174], col = "green")
abline(v = 146, lty = 2)
abline(v = 172, lty = 2)
legend("topleft", legend = c("Data aktual","Prediksi In sample", "Prediksi Out Sample", "Peramalan"),
col = c("black","blue","red","green"), lty = 1, pch = 20, lwd = 3, bty = "o", cex = 0.8)
grid()
Berdasarkan hasil grafik berikut, dapat dilihat bahwa pola data aktual dan hasil peramalan periode 25 Maret 2025 hingga 29 April 2025 cenderung tidak mengikuti pola data aktual. Hasil peramalan untuk 2 periode selanjutnya juga cenderung tidak mengikuti pola aktual dan harga kurs uang yang menurun.
Dilakukan kembali evaluasi model nn untuk melihat perbandingan akurasi dari ketiga perhitungan yang digunakan pada insample dan outsample.
in_sample_nn = c(
MAPE_NN_in = MAPE(ts(kembali_NN_1_2),ts(data_train[2:146]))*100,
SMAPE_NN_in = smape(ts(data_train[2:146]),ts(kembali_NN_1_2)) * 100,
RMSE_NN_in = RMSE(ts(kembali_NN_1_2), ts(data_train[2:146]))
)
out_sample_nn = c(
MAPE_NN_out = MAPE(forecast_denormalized[1:26], data_test) * 100,
SMAPE_NN_out = smape(data_test, forecast_denormalized[1:26]) * 100,
RMSE_NN_out = RMSE(forecast_denormalized[1:26], data_test)
)
hasil_evaluasi_nn = data.frame(
Metrik = c("MAPE (%)", "SMAPE (%)", "RMSE"),
In_Sample = round(in_sample_nn, 3),
Out_Sample = round(out_sample_nn, 3),
row.names = NULL
)
hasil_evaluasi_nn
## Metrik In_Sample Out_Sample
## 1 MAPE (%) 0.292 1.965
## 2 SMAPE (%) 0.292 1.989
## 3 RMSE 58.992 362.889
Berdasarkan hasil evaluasi model Neural Network, dapat disimpulkan bahwa model ini menunjukkan akurasi yang sangat baik pada data training dengan nilai MAPE dan SMAPE yang rendah, yaitu 0.292%, serta RMSE sebesar 58.992. Sedangkan akurasi pada data testing nilai MAPE, SMAPE, dan RMSE model mengalami penuruanan akurasi, dimana nilai MAPE yang dihasilkan menjadi sebesar 1.965%%, SMAPE sebesar 1.989%, dan RMSE sebesar 362.88.
sama seperti pengerjaan model Neural Network dengan package neuralnet, berikut pengerjaan Neural Network menggunakan package keras.
x_train = as.matrix(trainy$nilai_lag)
y_train = as.matrix(trainy$nilai_asli)
y_test = as.matrix(testy$nilai_asli[1:26])
x_test = as.matrix(testy$nilai_lag[1:26])
tensorflow::tf$random$set_seed(2)
model_nn = keras_model_sequential() %>%
layer_dense(units = 3, activation = "tanh", input_shape = 1,
kernel_regularizer = regularizer_l2(0.008)) %>%
layer_layer_normalization() %>%
layer_dense(units = 2, activation = "tanh",
kernel_regularizer = regularizer_l2(0.002)) %>%
layer_dense(units = 1, activation = "linear")
model_nn %>% compile(
optimizer = optimizer_adam(learning_rate = 0.005),
loss = "mse",
metrics = list("mae")
)
history = model_nn %>% fit(
x = x_train,
y = y_train,
epochs = 800,
batch_size = 8,
validation_data = list(x_test, y_test),
callbacks = list(
callback_early_stopping(
monitor = "val_loss",
min_delta = 0.005,
patience = 10,
restore_best_weights = TRUE
),
callback_reduce_lr_on_plateau(
monitor = "val_loss",
factor = 0.1,
patience = 10
)
)
)
## Epoch 1/800
## 19/19 - 1s - 76ms/step - loss: 0.0736 - mae: 0.1770 - val_loss: 0.2357 - val_mae: 0.4421 - learning_rate: 0.0050
## Epoch 2/800
## 19/19 - 0s - 6ms/step - loss: 0.0581 - mae: 0.1616 - val_loss: 0.3239 - val_mae: 0.5336 - learning_rate: 0.0050
## Epoch 3/800
## 19/19 - 0s - 7ms/step - loss: 0.0512 - mae: 0.1507 - val_loss: 0.3217 - val_mae: 0.5325 - learning_rate: 0.0050
## Epoch 4/800
## 19/19 - 0s - 7ms/step - loss: 0.0487 - mae: 0.1477 - val_loss: 0.3120 - val_mae: 0.5242 - learning_rate: 0.0050
## Epoch 5/800
## 19/19 - 0s - 7ms/step - loss: 0.0467 - mae: 0.1463 - val_loss: 0.3214 - val_mae: 0.5339 - learning_rate: 0.0050
## Epoch 6/800
## 19/19 - 0s - 7ms/step - loss: 0.0440 - mae: 0.1426 - val_loss: 0.3206 - val_mae: 0.5337 - learning_rate: 0.0050
## Epoch 7/800
## 19/19 - 0s - 7ms/step - loss: 0.0411 - mae: 0.1381 - val_loss: 0.3227 - val_mae: 0.5364 - learning_rate: 0.0050
## Epoch 8/800
## 19/19 - 0s - 6ms/step - loss: 0.0374 - mae: 0.1312 - val_loss: 0.3177 - val_mae: 0.5323 - learning_rate: 0.0050
## Epoch 9/800
## 19/19 - 0s - 6ms/step - loss: 0.0334 - mae: 0.1229 - val_loss: 0.3059 - val_mae: 0.5219 - learning_rate: 0.0050
## Epoch 10/800
## 19/19 - 0s - 6ms/step - loss: 0.0291 - mae: 0.1130 - val_loss: 0.2860 - val_mae: 0.5035 - learning_rate: 0.0050
## Epoch 11/800
## 19/19 - 0s - 6ms/step - loss: 0.0251 - mae: 0.1032 - val_loss: 0.2600 - val_mae: 0.4784 - learning_rate: 0.0050
dikarenakan bobot yang dapat berubah dan learning rate yang dapat berubah pada tahap training, maka peneliti melakukan save terlebih dahulu model awal yang telah terbentuk. sehingga diperoleh grafik pelatihan sebagai berikut.
#save_model(model_nn, "model_final.keras")
model = load_model("model_final.keras")
train_pred_norm = predict(model, x_train)
## 5/5 - 0s - 23ms/step
test_pred_norm = predict(model, x_test)
## 1/1 - 0s - 26ms/step
kembali_NN_keras_in = ((train_pred_norm + 1) / 2) * (max(kurs_rupiah) - min(kurs_rupiah)) + min(kurs_rupiah)
head(kembali_NN_keras_in)
## [,1]
## [1,] 15516.16
## [2,] 15516.16
## [3,] 15466.20
## [4,] 15394.52
## [5,] 15362.52
## [6,] 15446.68
last_window = tail(x_train, 1)
forecasts_nn_keras = numeric(28)
for (i in 1:28) {
pred_nn_keras = predict(model, last_window)
forecasts_nn_keras[i] = pred_nn_keras
last_window = cbind(last_window[, -1], pred_nn_keras)
}
## 1/1 - 0s - 31ms/step
## 1/1 - 0s - 32ms/step
## 1/1 - 0s - 37ms/step
## 1/1 - 0s - 31ms/step
## 1/1 - 0s - 35ms/step
## 1/1 - 0s - 29ms/step
## 1/1 - 0s - 32ms/step
## 1/1 - 0s - 31ms/step
## 1/1 - 0s - 31ms/step
## 1/1 - 0s - 31ms/step
## 1/1 - 0s - 32ms/step
## 1/1 - 0s - 18ms/step
## 1/1 - 0s - 32ms/step
## 1/1 - 0s - 32ms/step
## 1/1 - 0s - 21ms/step
## 1/1 - 0s - 24ms/step
## 1/1 - 0s - 27ms/step
## 1/1 - 0s - 29ms/step
## 1/1 - 0s - 31ms/step
## 1/1 - 0s - 32ms/step
## 1/1 - 0s - 33ms/step
## 1/1 - 0s - 39ms/step
## 1/1 - 0s - 33ms/step
## 1/1 - 0s - 31ms/step
## 1/1 - 0s - 31ms/step
## 1/1 - 0s - 31ms/step
## 1/1 - 0s - 32ms/step
## 1/1 - 0s - 31ms/step
balik_fcst_nn_keras = ((forecasts_nn_keras + 1) / 2) * (max(kurs_rupiah) - min(kurs_rupiah)) + min(kurs_rupiah)
head(balik_fcst_nn_keras)
## [1] 16466.64 16447.09 16433.22 16423.20 16415.86 16410.44
hasil_nn_keras = ts(c(NA,kembali_NN_keras_in,balik_fcst_nn_keras))
plot(1:172,kurs_rupiah, type = "l", main = "Grafik Prediksi dan Peramalan NN", ylab = "Nilai Kurs IDR", xlab = "Time")
points(kurs_rupiah, cex = 0.9, pch = 21)
lines(1:146,hasil_nn_keras[1:146], col = "blue")
lines(147:172,hasil_nn_keras[147:172], col = "red")
lines(173:174,hasil_nn_keras[173:174],col = "green")
abline(v = 146, lty = 2)
abline(v = 172, lty = 2)
legend("topleft", legend = c("Data aktual","Prediksi In sample", "Prediksi Out Sample","Peramalan"),
col = c("black","blue","red","green"), lty = 1, pch = 20, lwd = 3, bty = "o", cex = 0.8)
grid()
in_sample_nn_keras = c(
MAPE_NN_keras_in = MAPE(hasil_nn_keras[2:146],data_train[2:146])*100,
SMAPE_NN_keras_in = smape(data_train[2:146], hasil_nn_keras[2:146]) * 100,
RMSE_NN_keras_in = RMSE(hasil_nn_keras[2:146], data_train[2:146])
)
out_sample_nn_keras = c(
MAPE_NN_keras_out = MAPE(hasil_nn_keras[147:172], data_test) * 100,
SMAPE_NN_keras_out = smape(data_test, hasil_nn_keras[147:172]) * 100,
RMSE_NN_keras_out = RMSE(hasil_nn_keras[147:172], data_test)
)
hasil_evaluasi_nn_keras = data.frame(
Metrik = c("MAPE (%)", "SMAPE (%)", "RMSE"),
In_Sample = round(in_sample_nn_keras, 3),
Out_Sample = round(out_sample_nn_keras, 3),
row.names = NULL
)
hasil_evaluasi_nn_keras
## Metrik In_Sample Out_Sample
## 1 MAPE (%) 0.302 1.874
## 2 SMAPE (%) 0.302 1.895
## 3 RMSE 60.179 344.625
Moving Average (MA) adalah salah satu metode peramalan yang paling sederhana namun efektif dalam menganalisis data deret waktu. Pada dasarnya, MA digunakan untuk meratakan fluktuasi jangka pendek dalam data dan menyoroti tren atau pola yang lebih besar. Dalam pemodelan MA, prediksi masa depan didasarkan pada rata-rata nilai data sebelumnya dalam suatu periode tertentu. Tujuan utama dari penggunaan Moving Average adalah untuk mempermudah identifikasi tren dan siklus yang ada dalam data deret waktu.
Single Moving Average adalah suatu metode peramalan dengan menggunakan data-data pada masa lalu, kemudian di jumlahkan dan melakukan perhitungan rata rata untuk mengetahui suatu informasi yang mungkin akan terjadi. Untuk menentukan ramalan pada periode yang akan datang, diperlukan data historis dengan jang ka waktu tertentu . Metode single moving average memiliki karater khusus yaitu memerlukan data historis dengan jangka waktu tertentu dan semakin pajang waktunya maka moving average yang akan dihasilkan akan semakin halus. Persamaan matematis single moving average dapat dilihat dibawah ini:
\[ M_t=\frac{X_t+X_{t-1}+X_{t-2}+...+X_{t-n+1}}{n} \]
kererangan:
\(M_t\): Moving Average Periode ke-t
\(X_t\): Nilai rill periode ke-t
\(n\): Jumlah batas dalam Moving Average
SMA_order_2 = SMA(data_train, n = 2)
head(SMA_order_2)
## [1] NA 15520.0 15495.0 15432.5 15377.5 15405.0
SMA_order_3 = SMA(data_train, n = 3)
head(SMA_order_3)
## [1] NA NA 15503.33 15461.67 15408.33 15401.67
Double moving average adalah metode yang mencari rata-rata bergerak kemudian dicari rata rata bergerak dari rata-rata bergerak dan dibuat peramalannya. Rata-rata bergerak artinya rata-rata dicari menggunakan data terbaru dan menghilangkan data yang lama. Banyaknya data yang digunakan untuk mencari rata-rata bergerak adalah ordo. Langkah peramalan rata-rata bergerak meliputi tiga aspek yaitu penentuan rata-rata bergerak tunggal pada periode 𝑡, penyesuaian terhadap perbedaan rata-rata bergerak tunggal dan ganda pada periode 𝑡, dan penyesuaian untuk trend dari periode 𝑡 ke 𝑡 + 1. Langkah-langkah peramalan double moving average 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}\)
Menghitung besarnya konstanta \(a_t=2S_t^`-S_t^{``}\)
Menghitung besarnya koefisien trend \(b_t=\frac{2}{n-1}(S_t^`-S_t^{``})\)
Menghitung besarnya peramalan \(F_{t+m}=a_t+b_t\)
sma_dma_2 = SMA(data_train, n=2)
dma_2 = SMA(sma_dma_2, n=2)
At_2 = 2*sma_dma_2-dma_2
Bt_2 = sma_dma_2-dma_2
pemulusan_dma_2 = At_2+Bt_2
head(pemulusan_dma_2)
## [1] NA NA 15470.0 15370.0 15322.5 15432.5
sma_dma_3 = SMA(data_train, n=3)
dma_3 = SMA(sma_dma_3, n=3)
At_3 = 2*sma_dma_3-dma_3
Bt_3 = sma_dma_3-dma_3
pemulusan_dma_3 = At_3+Bt_3
head(pemulusan_dma_3)
## [1] NA NA NA NA 15309.44 15357.22
Pada bagian ini, dilakukan peramalan nilai tukar rupiah terhadap dolar AS menggunakan metode Moving Average, yang terdiri dari Single Moving Average (SMA) dan Double Moving Average (DMA):
forecast_sma2 = function(data, last_n, horizon) {
forecasts = numeric(horizon)
n = length(data)
# Ambil 2 nilai terakhir dari data
last_two = tail(data, last_n)
for (i in 1:horizon) {
# Hitung SMA untuk periode berikutnya
next_forecast = mean(last_two)
forecasts[i] = next_forecast
# Update last_two: geser nilai dan tambahkan ramalan terbaru
last_two = c(last_two[-1], next_forecast)
}
return(forecasts)
}
forecast_sma3 = function(data, last_n, horizon) {
forecasts = numeric(horizon)
n <- length(data)
# Ambil 3 nilai terakhir dari data
last_three = tail(data, last_n)
for (i in 1:horizon) {
# Hitung SMA untuk periode berikutnya
next_forecast = mean(last_three)
forecasts[i] = next_forecast
# Update last_three: geser nilai dan tambahkan ramalan terbaru
last_three = c(last_three[-1], next_forecast)
}
return(forecasts)
}
fcst_sma2 = forecast_sma2(data_train, last_n = 2, horizon = 26)
fcst_sma3 = forecast_sma3(data_train, last_n = 3, horizon = 26)
head(fcst_sma2)
## [1] 16522.50 16536.25 16529.38 16532.81 16531.09 16531.95
head(fcst_sma3)
## [1] 16505.00 16516.67 16523.89 16515.19 16518.58 16519.22
dma_forecast <- function(data, order = 2, horizon = 17) {
# Hitung moving average pertama
sma = SMA(data, n = order)
# Hitung moving average kedua
dma = SMA(sma, n = order)
# Hitung komponen dasar
At = 2 * sma - dma
Bt = (sma - dma) * (2 / (order - 1))
# Ambil nilai terakhir yang valid
last_valid = max(which(!is.na(At)))
last_At = At[last_valid]
last_Bt = Bt[last_valid]
# Generate ramalan
ramalan = last_At + last_Bt * (1:horizon)
return(list(
data_asli = data,
ramalan = ramalan,
parameter = c(At = last_At, Bt = last_Bt),
horizon = horizon
))
}
fcst_dma_2 = dma_forecast(data_train, order = 2, horizon = 26)$ramalan
fcst_dma_3 = dma_forecast(data_train, order = 3, horizon = 26)$ramalan
head(fcst_dma_2)
## [1] 16582.5 16622.5 16662.5 16702.5 16742.5 16782.5
head(fcst_dma_3)
## [1] 16535 16550 16565 16580 16595 16610
Untuk menentukan metode peramalan terbaik antara Single Moving Average (SMA) dan Double Moving Average (DMA), dilakukan evaluasi kinerja masing-masing metode berdasarkan tiga metrik akurasi, yaitu MAPE, RMSE, dan SMAPE. Hasilnya dapat dilihat dibawah ini:
MAPE_SMA_DMA = c(
MAPE_SMA2 = MAPE(SMA_order_2[2:146],data_train[2:146])*100,
MAPE_SMA3 = MAPE(SMA_order_3[3:146],data_train[3:146])*100,
MAPE_DMA2 = MAPE(pemulusan_dma_2[3:146],data_train[3:146])*100,
MAPE_DMA3 = MAPE(pemulusan_dma_3[5:146],data_train[5:146])*100
)
RMSE_SMA_DMA = c(
RMSE_SMA2 = RMSE(SMA_order_2[2:146],data_train[2:146]),
RMSE_SMA3 = RMSE(SMA_order_3[3:146],data_train[3:146]),
RMSE_DMA2 = RMSE(pemulusan_dma_2[3:146],data_train[3:146]),
RMSE_DMA3 = RMSE(pemulusan_dma_3[5:146],data_train[5:146])
)
SMAPE_SMA_DMA = c(
SMAPE_SMA2 = smape(data_train[2:146],SMA_order_2[2:146])*100,
SMAPE_SMA3 = smape(data_train[3:146],SMA_order_3[3:146])*100,
SMAPE_DMA2 = smape(data_train[3:146],pemulusan_dma_2[3:146])*100,
SMAPE_DMA3 = smape(data_train[5:146],pemulusan_dma_3[5:146])*100
)
baris_pemilihan_SMA_DMA = c(
"SMA 2",
"SMA 3",
"DMA 2",
"DMA 3"
)
pemilihan_SMA_DMA_Terbaik = data.frame(
pilih_mape = round(MAPE_SMA_DMA, 3),
pilih_rmse = round(RMSE_SMA_DMA, 3),
pilih_smape = round(SMAPE_SMA_DMA, 3),
row.names = baris_pemilihan_SMA_DMA
)
colnames(pemilihan_SMA_DMA_Terbaik) = c("MAPE", "RMSE", "SMAPE")
pemilihan_SMA_DMA_Terbaik
## MAPE RMSE SMAPE
## SMA 2 0.146 30.138 0.147
## SMA 3 0.226 45.769 0.226
## DMA 2 0.146 30.155 0.146
## DMA 3 0.248 49.878 0.248
berdasarkan hasil tersebut maka dapat diketahui bahwa double moving avarage orde 2 merupakan model yang memiliki nilai MAPE, RMSE, dan SMAPE terkecil.
Grafik berikut menunjukkan hasil prediksi dan peramalan nilai tukar rupiah terhadap dolar AS menggunakan model DMA orde 2. Grafik ini menggambarkan bagaimana model mengikuti pola data historis dan memperkirakan nilai ke depan. Hasilnya ditampilkan sebagai berikut:
hasil_dma_2 = ts(c(pemulusan_dma_2,fcst_dma_2))
plot(1:172,kurs_rupiah, type = "l", main = "Grafik Prediksi dan Peramalan DMA", ylab = "Nilai Kurs IDR", xlab = "Time", ylim = c(15000,17600))
points(kurs_rupiah, cex = 0.9, pch = 21)
lines(1:146,hasil_dma_2[1:146], col = "blue")
lines(147:172,hasil_dma_2[147:172], col = "red")
abline(v = 146, lty = 2)
abline(v = 172, lty = 2)
legend("topleft", legend = c("Data aktual","Prediksi In sample", "Prediksi Out Sample"),
col = c("black","blue","red"), lty = 1, pch = 20, lwd = 3, bty = "o", cex = 0.8)
grid()
(Berdasarkan grafik time series nilai tukar Rupiah terhadap Dolar AS, model Double Moving Average (DMA) orde 2 mampu mengikuti pola data historis dengan cukup baik. Prediksi in-sample yang ditunjukkan oleh garis biru mendekati data aktual, menandakan kecocokan model terhadap pola yang telah terjadi. Sementara itu, prediksi out-sample yang digambarkan dengan garis merah menunjukkan kecenderungan naik, meskipun mulai menyimpang dari data aktual. Hal ini menunjukkan bahwa model cukup efektif dalam memodelkan data historis, namun akurasi peramalan cenderung menurun seiring waktu. Secara umum, DMA orde 2 memberikan hasil yang layak untuk prediksi jangka pendek.
Evaluasi dilakukan untuk menilai akurasi dan kinerja model Double Moving Average (DMA) orde 2 dalam memprediksi nilai tukar Rupiah terhadap Dolar AS. Hasil evaluasi model disajikan sebagai berikut:
in_sample_dma = c(
MAPE_DMA2_in = MAPE(pemulusan_dma_2[3:146],data_train[3:146])*100,
SMAPE_DMA2_in = smape(data_train[3:146],pemulusan_dma_2[3:146])*100,
RMSE_DMA2_in = RMSE(pemulusan_dma_2[3:146],data_train[3:146])
)
out_smaple_dma = c(
MAPE_DMA2_out = MAPE(fcst_dma_2, data_test) * 100,
SMAPE_DMA2_out = smape(data_test, fcst_dma_2) * 100,
RMSE_DMA2_out = RMSE(fcst_dma_2, data_test)
)
hasil_evaluasi_dma = data.frame(
Metrik = c("MAPE (%)", "SMAPE (%)", "RMSE"),
In_Sample = round(in_sample_dma, 3),
Out_Sample = round(out_smaple_dma, 3),
row.names = NULL
)
hasil_evaluasi_dma
## Metrik In_Sample Out_Sample
## 1 MAPE (%) 0.146 2.171
## 2 SMAPE (%) 0.146 2.140
## 3 RMSE 30.155 420.695
Model DMA orde 2 menunjukkan akurasi yang sangat baik pada data in-sample, dengan nilai MAPE dan SMAPE sebesar 0,146% dan RMSE 30,155, yang menandakan kesalahan prediksi sangat kecil. Pada data out-sample, akurasi menurun dengan MAPE sebesar 2,171%, SMAPE 2,140%, dan RMSE meningkat menjadi 420,695. Meskipun terjadi penurunan, model tetap cukup baik untuk peramalan jangka pendek.
Setelah dilakukan analisis data kurs rupiah menggunakan model ARIMA, NN, dan MA. Kemudian dilakukan tahap evaluasi untuk melihat model manakah yang menghasilkan MAPE, RMSE, dan SMAPE terkecil bagi data in sampledan out sample.
mape_in_sample_seluruh = c(
MAPE_Arima_in = MAPE(prediksi_arima,data_train)*100,
MAPE_NN_in = MAPE(ts(kembali_NN_1_2),ts(data_train[2:146]))*100,
MAPE_NN_keras_in = MAPE(hasil_nn_keras[2:146],data_train[2:146])*100,
MAPE_DMA2_in = MAPE(pemulusan_dma_2[3:146],data_train[3:146])*100
)
mape_out_sample_seluruh = c(
MAPE_Arima_out = MAPE(ramal_arima[1:26], data_test) * 100,
MAPE_NN_out = MAPE(forecast_denormalized[1:26], data_test) * 100,
MAPE_NN_keras_out = MAPE(hasil_nn_keras[147:172], data_test) * 100,
MAPE_DMA2_out = MAPE(fcst_dma_2, data_test) * 100
)
smape_in_sample_seluruh = c(
SMAPE_Arima_in = smape(data_train, prediksi_arima)*100,
SMAPE_NN_in = smape(ts(data_train[2:146]),ts(kembali_NN_1_2)) * 100,
SMAPE_NN_keras_in = smape(data_train[2:146], hasil_nn_keras[2:146]) * 100,
SMAPE_DMA2_in = smape(data_train[3:146],pemulusan_dma_2[3:146])*100
)
smape_out_sample_seluruh = c(
SMAPE_Arima_out = smape(data_test, ramal_arima[1:26]) * 100,
SMAPE_NN_out = smape(data_test, forecast_denormalized[1:26]) * 100,
SMAPE_NN_keras_out = smape(data_test, hasil_nn_keras[147:172]) * 100,
SMAPE_DMA2_out = smape(data_test, fcst_dma_2) * 100
)
rmse_in_sample_seluruh = c(
RMSE_Arima_in = RMSE(prediksi_arima, data_train),
RMSE_NN_in = RMSE(ts(kembali_NN_1_2), ts(data_train[2:146])),
RMSE_NN_keras_in = RMSE(hasil_nn_keras[2:146], data_train[2:146]),
RMSE_DMA2_in = RMSE(pemulusan_dma_2[3:146],data_train[3:146])
)
rmse_out_sample_seluruh = c(
RRMSE_Arima_out = RMSE(ramal_arima[1:26], data_test),
RMSE_NN_out = RMSE(forecast_denormalized[1:26], data_test),
RMSE_NN_keras_out = RMSE(hasil_nn_keras[147:172], data_test),
RMSE_DMA2_out = RMSE(fcst_dma_2, data_test)
)
hasil_evaluasi_keseluruhan <- data.frame(
MAPE_In = round(mape_in_sample_seluruh, 3),
MAPE_Out = round(mape_out_sample_seluruh, 3),
SMAPE_In = round(smape_in_sample_seluruh, 3),
SMAPE_Out = round(smape_out_sample_seluruh, 3),
RMSE_In = round(rmse_in_sample_seluruh, 3),
RMSE_Out = round(rmse_out_sample_seluruh, 3),
row.names = c("ARIMA", "NN (Neural Net)", "NN (Keras)", "DMA Orde 2")
)
# Menambahkan nama kolom yang lebih deskriptif
colnames(hasil_evaluasi_keseluruhan) <- c(
"MAPE In Sample (%)",
"MAPE Out Sample (%)",
"SMAPE In Sample (%)",
"SMAPE Out Sample (%)",
"RMSE In Sample",
"RMSE Out Sample"
)
# Menampilkan hasil
hasil_evaluasi_keseluruhan
## MAPE In Sample (%) MAPE Out Sample (%) SMAPE In Sample (%)
## ARIMA 0.343 1.599 0.343
## NN (Neural Net) 0.292 1.965 0.292
## NN (Keras) 0.302 1.874 0.302
## DMA Orde 2 0.146 2.171 0.146
## SMAPE Out Sample (%) RMSE In Sample RMSE Out Sample
## ARIMA 1.582 68.279 312.756
## NN (Neural Net) 1.989 58.992 362.889
## NN (Keras) 1.895 60.179 344.625
## DMA Orde 2 2.140 30.155 420.695
Berdasarkan hasil evaluasi matriks keseluruhan model yang digunakan, maka model Neural Network merupakan model terbaik yang dapat digunakan untuk menganalis nilai tukar rupiah terhadap dolar AS periode 1 April 2024 hingga 30 April 2025.
Berdasarkan ketiga model yang digunakan, model neural network dengan menggunakan bantuan pacakage keras merupakan model terbaik yang dapat digunakan untuk menganalisis data nilai tukar rupiah terhadap dolar AS periode 1 April 2024 hingga 30 April 2025. Hal ini dikarenakan model tersebut memiliki nilai MAPE, SMAPE, dan RMSE in sample terkecil, selain itu hasil nilai MAPE, SMAPE, dan RMSE dari out sample juga tidak terlalu jauh dengan in sample nya yang menandakan tidak terjadi over fitting pada model tersebut.
Sebaiknya peneliti selanjutnya dapat melakuakn hybrid pada model ARIMA dengan Neural Network untuk dapat meningkatkan akurasi dan menangkap pola-pola data yang belum bisa ditangkap model ARIMA atau Neural Network.
Nama Penulis : Yusri Abdul Fahmi, Mochamad Afif Nurdiansyah, Nabila
Aulia, Felicia Joy Rotua Tamba
Email Penulis :
fahmi2004.bukitpinang@gmail.com,
afifnurdiansyah12@gmail.com,
nauliax712@gmail.com, feliciajrtamba@gmail.com