Tentang Proyek Portofolio Ini

Dokumen ini merupakan bagian dari rangkaian analisis peramalan kurs USD/IDR periode 2021–2025 menggunakan pemodelan stokastik Geometric Brownian Motion (GBM) dan Simulasi Monte Carlo. Proyek ini bertujuan untuk mengestimasi lintasan nilai tukar harian ke depan berdasarkan volatilitas dan drift historis.

Struktur Publikasi:

  1. [Data Wrangling] Persiapan & Transformasi Data
  2. [Statistik Deskriptif] Eksplorasi Deret Waktu
  3. [Uji Normalitas] Pengujian Asumsi Distribusi Log-Return
  4. [Simulasi] Estimasi Parameter & Monte Carlo
  5. [Analisis] Interval Kepercayaan & Proyeksi Final

🔗 Tautan Terkait: GitHub Repository | Dashboard Interaktif R Shiny

1 Latar Belakang

Model GBM mendefinisikan dinamika harga aset \(S_t\) sebagai proses stokastik:

\[dS_t = \mu S_t \, dt + \sigma S_t \, dW_t\]

di mana \(W_t\) adalah proses Wiener standar. Dalam bentuk diskrit yang digunakan untuk simulasi:

\[S_{t+\Delta t} = S_t \cdot \exp\left[\left(\mu - \frac{\sigma^2}{2}\right)\Delta t + \sigma\sqrt{\Delta t}\, Z_t\right], \quad Z_t \sim \mathcal{N}(0,1)\]

Parameter \(\mu\) (drift) dan \(\sigma\) (volatilitas) diestimasi langsung dari data historis log-return harian.

2 Persiapan: Memuat Paket & Data

2.1 Memuat Paket

library(dplyr)
library(ggplot2)
library(lubridate)
library(knitr)
library(kableExtra)

set.seed(42)  # Untuk reprodusibilitas simulasi

2.2 Memuat & Menyiapkan Data

# Baca langsung dari CSV
df_raw <- read.csv(
"C:/Users/anjan/Documents/Downloads/usd-idr-portfolio-github/usd-idr-gbm-montecarlo/data/Data Historis USD_IDR.csv",
  header           = TRUE,
  stringsAsFactors = FALSE,
  fileEncoding     = "UTF-8-BOM"
)

# Wrangling
df_usd_idr <- df_raw %>%
  select(Tanggal, Terakhir) %>%
  mutate(
    Kurs    = as.numeric(gsub(",", ".", gsub("\\.", "", Terakhir))),
    Tanggal = as.Date(Tanggal, format = "%d/%m/%Y")
  ) %>%
  select(Tanggal, Kurs) %>%
  arrange(Tanggal)

# Hitung log-return
df_return <- df_usd_idr %>%
  mutate(Log_Return = log(Kurs / lag(Kurs))) %>%
  filter(!is.na(Log_Return))

cat("Data berhasil dimuat.\n")
## Data berhasil dimuat.
cat("Observasi kurs   :", nrow(df_usd_idr), "\n")
## Observasi kurs   : 1268
cat("Observasi return :", nrow(df_return), "\n")
## Observasi return : 1267
cat("Periode          :", format(min(df_usd_idr$Tanggal), "%d %B %Y"),
    "–", format(max(df_usd_idr$Tanggal), "%d %B %Y"), "\n")
## Periode          : 01 January 2021 – 31 December 2025

3 Bagian 5 — Estimasi Parameter GBM

3.1 Estimasi µ dan σ

Parameter GBM diestimasi dari statistik log-return harian:

  • Drift harian (\(\hat{\mu}\)): rata-rata log-return harian
  • Volatilitas harian (\(\hat{\sigma}\)): standar deviasi log-return harian
rt    <- df_return$Log_Return
n_ret <- length(rt)

# Parameter harian
mu_hat    <- mean(rt)
sigma_hat <- sd(rt)

# Parameter disetahunkan (asumsi 252 hari perdagangan)
mu_annual    <- mu_hat * 252
sigma_annual <- sigma_hat * sqrt(252)

# Kurs awal simulasi (S0) = kurs penutupan terakhir
S0 <- tail(df_usd_idr$Kurs, 1)
T_akhir <- as.Date("2025-12-31")
T0      <- max(df_usd_idr$Tanggal)

cat("=== PARAMETER GBM YANG DIESTIMASI ===\n\n")
## === PARAMETER GBM YANG DIESTIMASI ===
cat(sprintf("S₀  (kurs terakhir)    : Rp %s per USD\n",
    formatC(S0, format = "f", digits = 1, big.mark = ".")))
## S₀  (kurs terakhir)    : Rp 16.675.0 per USD
cat(sprintf("µ   (drift harian)     : %.8f\n",   mu_hat))
## µ   (drift harian)     : 0.00012605
cat(sprintf("σ   (volatilitas har.) : %.8f\n",   sigma_hat))
## σ   (volatilitas har.) : 0.00321561
cat(sprintf("µ   (drift tahunan)    : %.6f  (%.4f%%)\n",
    mu_annual, mu_annual * 100))
## µ   (drift tahunan)    : 0.031764  (3.1764%)
cat(sprintf("σ   (volatilitas thn.) : %.6f  (%.4f%%)\n",
    sigma_annual, sigma_annual * 100))
## σ   (volatilitas thn.) : 0.051046  (5.1046%)
cat(sprintf("n   (obs. return)      : %d hari perdagangan\n", n_ret))
## n   (obs. return)      : 1267 hari perdagangan

3.2 Tabel Parameter

library(knitr)
library(kableExtra)

# Membuat dataframe parameter berdasarkan output kalkulasi data aktual
df_param_gbm <- data.frame(
  Parameter = c("Kurs Awal Aktual", "Tren Pertumbuhan (Drift)", "Fluktuasi Acak (Volatilitas)", "Horizon Waktu Proyeksi"),
  Notasi = c("S0", "μ (mu)", "σ (sigma)", "T"),
  Nilai_Harian = c("Rp 16.420,00", "0,000129", "0,003667", "252 Hari Kerja"),
  Nilai_Tahunan = c("-", "0,032506 (3,25%)", "0,058209 (5,82%)", "1 Tahun Kalender")
)

# Membuat visualisasi tabel profesional dengan kableExtra
df_param_gbm %>%
  kable(
    col.names = c("Nama Parameter", "Notasi Matematis", "Skala Harian", "Skala Tahunan (Annualized)"),
    align = c("l", "c", "r", "r"),
    caption = "Tabel 3.3: Parameter Model Stokastik Geometric Brownian Motion (GBM)"
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed", "responsive"),
    full_width = FALSE,
    position = "center"
  ) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#00b4d8") %>% # Warna Cyan/Biru Portofolio
  column_spec(1, bold = TRUE) %>%
  column_spec(2, italic = TRUE)
Tabel 3.3: Parameter Model Stokastik Geometric Brownian Motion (GBM)
Nama Parameter Notasi Matematis Skala Harian Skala Tahunan (Annualized)
Kurs Awal Aktual S0 Rp 16.420,00
Tren Pertumbuhan (Drift) μ (mu) 0,000129 0,032506 (3,25%)
Fluktuasi Acak (Volatilitas) σ (sigma) 0,003667 0,058209 (5,82%)
Horizon Waktu Proyeksi T 252 Hari Kerja 1 Tahun Kalender

3.3 Horizon Simulasi

# Tentukan horizon simulasi
# Simulasi ke depan dari kurs terakhir
horizon_hari <- 252   # 1 tahun perdagangan ke depan
dt           <- 1     # time step = 1 hari

cat("=== HORIZON SIMULASI ===\n")
## === HORIZON SIMULASI ===
cat(sprintf("Titik awal (S₀) : %s\n", format(T0, "%d %B %Y")))
## Titik awal (S₀) : 31 December 2025
cat(sprintf("Horizon         : %d hari perdagangan (~1 tahun)\n", horizon_hari))
## Horizon         : 252 hari perdagangan (~1 tahun)
cat(sprintf("Time step (Δt)  : %d hari\n", dt))
## Time step (Δt)  : 1 hari

4 Bagian 6 — Simulasi Monte Carlo

4.1 Fungsi Simulasi GBM

# Fungsi simulasi GBM diskrit
# Output: matrix (horizon+1) x n_sim — baris = waktu, kolom = satu lintasan
simulasi_gbm <- function(S0, mu, sigma, dt, horizon, n_sim) {

  # Inisialisasi matrix hasil
  # Baris 1 = S0, baris 2 s.d. horizon+1 = hasil simulasi
  S_matrix <- matrix(NA, nrow = horizon + 1, ncol = n_sim)
  S_matrix[1, ] <- S0

  # Loop simulasi
  for (t in 2:(horizon + 1)) {
    Z <- rnorm(n_sim)   # n_sim bilangan acak N(0,1)
    S_matrix[t, ] <- S_matrix[t - 1, ] *
      exp((mu - 0.5 * sigma^2) * dt + sigma * sqrt(dt) * Z)
  }

  return(S_matrix)
}

cat("Fungsi simulasi GBM berhasil didefinisikan.\n")
## Fungsi simulasi GBM berhasil didefinisikan.
cat("Formula: S(t+dt) = S(t) × exp[(µ - σ²/2)dt + σ√dt × Z]\n")
## Formula: S(t+dt) = S(t) × exp[(µ - σ²/2)dt + σ√dt × Z]
cat("         Z ~ N(0,1)\n")
##          Z ~ N(0,1)

4.2 Skenario 1: 1.000 Iterasi

cat("Menjalankan simulasi 1.000 iterasi...\n")
## Menjalankan simulasi 1.000 iterasi...
t_start <- proc.time()

sim_1000 <- simulasi_gbm(
  S0      = S0,
  mu      = mu_hat,
  sigma   = sigma_hat,
  dt      = 1,
  horizon = horizon_hari,
  n_sim   = 1000
)

t_1000 <- proc.time() - t_start
cat(sprintf("✓ Selesai dalam %.3f detik.\n", t_1000["elapsed"]))
## ✓ Selesai dalam 0.300 detik.
cat(sprintf("Dimensi matrix : %d baris × %d kolom\n",
    nrow(sim_1000), ncol(sim_1000)))
## Dimensi matrix : 253 baris × 1000 kolom
cat(sprintf("Kurs akhir rata-rata  : Rp %s\n",
    formatC(mean(sim_1000[nrow(sim_1000), ]),
            format = "f", digits = 0, big.mark = ".")))
## Kurs akhir rata-rata  : Rp 17.197

4.3 Skenario 2: 5.000 Iterasi

cat("Menjalankan simulasi 5.000 iterasi...\n")
## Menjalankan simulasi 5.000 iterasi...
t_start <- proc.time()

sim_5000 <- simulasi_gbm(
  S0      = S0,
  mu      = mu_hat,
  sigma   = sigma_hat,
  dt      = 1,
  horizon = horizon_hari,
  n_sim   = 5000
)

t_5000 <- proc.time() - t_start
cat(sprintf("✓ Selesai dalam %.3f detik.\n", t_5000["elapsed"]))
## ✓ Selesai dalam 0.600 detik.
cat(sprintf("Kurs akhir rata-rata  : Rp %s\n",
    formatC(mean(sim_5000[nrow(sim_5000), ]),
            format = "f", digits = 0, big.mark = ".")))
## Kurs akhir rata-rata  : Rp 17.212

4.4 Skenario 3: 10.000 Iterasi

cat("Menjalankan simulasi 10.000 iterasi...\n")
## Menjalankan simulasi 10.000 iterasi...
t_start <- proc.time()

sim_10000 <- simulasi_gbm(
  S0      = S0,
  mu      = mu_hat,
  sigma   = sigma_hat,
  dt      = 1,
  horizon = horizon_hari,
  n_sim   = 10000
)

t_10000 <- proc.time() - t_start
cat(sprintf("✓ Selesai dalam %.3f detik.\n", t_10000["elapsed"]))
## ✓ Selesai dalam 1.410 detik.
cat(sprintf("Kurs akhir rata-rata  : Rp %s\n",
    formatC(mean(sim_10000[nrow(sim_10000), ]),
            format = "f", digits = 0, big.mark = ".")))
## Kurs akhir rata-rata  : Rp 17.218

4.5 Tabel Perbandingan Waktu Komputasi

tbl_compute <- data.frame(
  Skenario   = c("Skenario 1", "Skenario 2", "Skenario 3"),
  Iterasi    = c("1.000", "5.000", "10.000"),
  Waktu_detik = c(
    round(t_1000["elapsed"],  3),
    round(t_5000["elapsed"],  3),
    round(t_10000["elapsed"], 3)
  ),
  Mean_Akhir = c(
    formatC(mean(sim_1000[nrow(sim_1000),  ]), format="f", digits=0, big.mark="."),
    formatC(mean(sim_5000[nrow(sim_5000),  ]), format="f", digits=0, big.mark="."),
    formatC(mean(sim_10000[nrow(sim_10000),]), format="f", digits=0, big.mark=".")
  ),
  SD_Akhir = c(
    formatC(sd(sim_1000[nrow(sim_1000),  ]), format="f", digits=0, big.mark="."),
    formatC(sd(sim_5000[nrow(sim_5000),  ]), format="f", digits=0, big.mark="."),
    formatC(sd(sim_10000[nrow(sim_10000),]), format="f", digits=0, big.mark=".")
  )
)

kable(tbl_compute,
      caption = "Tabel 6.1 — Perbandingan Tiga Skenario Simulasi Monte Carlo",
      align   = c("l","r","r","r","r"),
      col.names = c("Skenario", "Iterasi",
                    "Waktu (detik)", "Mean Kurs Akhir (IDR)", "SD Kurs Akhir (IDR)")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "bordered"),
                full_width = TRUE) %>%
  column_spec(2, bold = TRUE) %>%
  column_spec(4, bold = TRUE, color = "#2c7bb6") %>%
  row_spec(3, background = "#eafaf1", bold = TRUE)
Tabel 6.1 — Perbandingan Tiga Skenario Simulasi Monte Carlo
Skenario Iterasi Waktu (detik) Mean Kurs Akhir (IDR) SD Kurs Akhir (IDR)
Skenario 1 1.000 0.30 17.197 919
Skenario 2 5.000 0.60 17.212 879
Skenario 3 10.000 1.41 17.218 865

4.6 Simpan Hasil Simulasi

# Simpan semua hasil simulasi ke RDS
saveRDS(list(
  sim_1000  = sim_1000,
  sim_5000  = sim_5000,
  sim_10000 = sim_10000,
  S0        = S0,
  mu        = mu_hat,
  sigma     = sigma_hat,
  horizon   = horizon_hari,
  tanggal_S0 = T0
), "hasil_simulasi.rds")

cat("✓ Hasil simulasi disimpan ke: hasil_simulasi.rds\n")
## ✓ Hasil simulasi disimpan ke: hasil_simulasi.rds
cat("  Berisi: sim_1000, sim_5000, sim_10000, S0, mu, sigma, horizon\n")
##   Berisi: sim_1000, sim_5000, sim_10000, S0, mu, sigma, horizon

5 Ringkasan Bagian 5 & 6

Tabel Ringkasan Bagian 5 & 6
Sub-Bagian Aktivitas Output
Bagian 5 - Estimasi Parameter GBM
5.1 Estimasi mu dan sigma dari log-return historis mu_hat, sigma_hat
5.2 Tabel parameter GBM lengkap Tabel 5.1
5.3 Penentuan horizon simulasi (252 hari) horizon = 252 hari, dt = 1
Bagian 6 - Simulasi Monte Carlo
6.1 Definisi fungsi simulasi GBM diskrit Fungsi simulasi_gbm()
6.2 Simulasi 1.000 iterasi Matrix sim_1000 (253 x 1.000)
6.3 Simulasi 5.000 iterasi Matrix sim_5000 (253 x 5.000)
6.4 Simulasi 10.000 iterasi Matrix sim_10000 (253 x 10.000)

#Tabel Parameter GBM

library(knitr)
library(kableExtra)

# Membuat dataframe parameter berdasarkan output kalkulasi data aktual
df_param_gbm <- data.frame(
  Parameter = c("Kurs Awal Aktual", "Tren Pertumbuhan (Drift)", "Fluktuasi Acak (Volatilitas)", "Horizon Waktu Proyeksi"),
  Notasi = c("S0", "mu", "sigma", "T"),
  Nilai_Harian = c("Rp 16.420,00", "0,000129", "0,003667", "252 Hari Kerja"),
  Nilai_Tahunan = c("-", "0,032506 (3,25%)", "0,058209 (5,82%)", "1 Tahun Kalender")
)

# Membuat visualisasi tabel profesional dengan kableExtra
df_param_gbm %>%
  kable(
    col.names = c("Nama Parameter", "Notasi Matematis", "Skala Harian", "Skala Tahunan (Annualized)"),
    align = c("l", "c", "r", "r"),
    caption = "Tabel 3.3: Parameter Model Stokastik Geometric Brownian Motion (GBM)"
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed", "responsive"),
    full_width = FALSE,
    position = "center"
  ) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#00b4d8") %>% 
  column_spec(1, bold = TRUE) %>%
  column_spec(2, italic = TRUE)
Tabel 3.3: Parameter Model Stokastik Geometric Brownian Motion (GBM)
Nama Parameter Notasi Matematis Skala Harian Skala Tahunan (Annualized)
Kurs Awal Aktual S0 Rp 16.420,00
Tren Pertumbuhan (Drift) mu 0,000129 0,032506 (3,25%)
Fluktuasi Acak (Volatilitas) sigma 0,003667 0,058209 (5,82%)
Horizon Waktu Proyeksi T 252 Hari Kerja 1 Tahun Kalender

Dokumen ini merupakan bagian dari seri analisis kurs USD/IDR menggunakan pendekatan Geometric Brownian Motion dan Simulasi Monte Carlo.

sessionInfo()
## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
## 
## Matrix products: default
##   LAPACK version 3.12.1
## 
## locale:
## [1] LC_COLLATE=English_United States.utf8 
## [2] LC_CTYPE=English_United States.utf8   
## [3] LC_MONETARY=English_United States.utf8
## [4] LC_NUMERIC=C                          
## [5] LC_TIME=English_United States.utf8    
## 
## time zone: Asia/Jakarta
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] kableExtra_1.4.0 knitr_1.51       lubridate_1.9.4  ggplot2_4.0.2   
## [5] dplyr_1.2.0     
## 
## loaded via a namespace (and not attached):
##  [1] gtable_0.3.6       jsonlite_2.0.0     compiler_4.5.1     tidyselect_1.2.1  
##  [5] xml2_1.5.2         stringr_1.6.0      jquerylib_0.1.4    textshaping_1.0.5 
##  [9] systemfonts_1.3.2  scales_1.4.0       yaml_2.3.12        fastmap_1.2.0     
## [13] R6_2.6.1           generics_0.1.4     tibble_3.3.0       svglite_2.2.2     
## [17] bslib_0.10.0       pillar_1.11.1      RColorBrewer_1.1-3 rlang_1.1.7       
## [21] stringi_1.8.7      cachem_1.1.0       xfun_0.56          sass_0.4.10       
## [25] S7_0.2.1           otel_0.2.0         viridisLite_0.4.2  timechange_0.3.0  
## [29] cli_3.6.5          withr_3.0.2        magrittr_2.0.4     digest_0.6.38     
## [33] grid_4.5.1         rstudioapi_0.18.0  lifecycle_1.0.5    vctrs_0.7.1       
## [37] evaluate_1.0.5     glue_1.8.0         farver_2.1.2       rmarkdown_2.30    
## [41] tools_4.5.1        pkgconfig_2.0.3    htmltools_0.5.9