Setup Library

library(quantmod)
library(PerformanceAnalytics)
library(tseries)
library(moments)
library(xts)
options(stringsAsFactors = FALSE)
 knitr::opts_chunk$set(message = FALSE, warning = FALSE)

Data Saham

Import Data Saham

#Portofolio 1 Menggunakan 3 Saham
saham1 <- c("ICBP.JK","UNVR.JK","MYOR.JK")
start <- as.Date("2026-01-01")
end   <- as.Date("2026-03-31")

getSymbols(saham1, src="yahoo", from=start, to=end, adjust=TRUE)
## [1] "ICBP.JK" "UNVR.JK" "MYOR.JK"
#portofolio 2 Menggunakan 4 Saham
saham2 <- c("GOTO.JK","BUKA.JK","ASGR.JK","MTDL.JK")
start <- as.Date("2026-01-01")
end   <- as.Date("2026-03-31")

getSymbols(saham2, src="yahoo", from=start, to=end, adjust=TRUE)
## [1] "GOTO.JK" "BUKA.JK" "ASGR.JK" "MTDL.JK"

Data Harian

# Close price harian Portofolio 1
price_dailysaham1 <- merge(Cl(ICBP.JK),Cl(UNVR.JK),Cl(MYOR.JK))
colnames(price_dailysaham1) <- c("ICBP","UNVR","MYOR")
# Close price harian Portofolio 2
price_dailysaham2 <- merge(Cl(GOTO.JK),Cl(BUKA.JK),Cl(ASGR.JK),Cl(MTDL.JK))
colnames(price_dailysaham2) <- c("GOTO","BUKA","ASGR","MDTL")

Exploratory Data Analysis Data Harga Saham

Variabel Data Saham

colnames(ICBP.JK)
## [1] "ICBP.JK.Open"     "ICBP.JK.High"     "ICBP.JK.Low"      "ICBP.JK.Close"   
## [5] "ICBP.JK.Volume"   "ICBP.JK.Adjusted"
colnames(UNVR.JK)
## [1] "UNVR.JK.Open"     "UNVR.JK.High"     "UNVR.JK.Low"      "UNVR.JK.Close"   
## [5] "UNVR.JK.Volume"   "UNVR.JK.Adjusted"
colnames(MYOR.JK)
## [1] "MYOR.JK.Open"     "MYOR.JK.High"     "MYOR.JK.Low"      "MYOR.JK.Close"   
## [5] "MYOR.JK.Volume"   "MYOR.JK.Adjusted"
colnames(GOTO.JK)
## [1] "GOTO.JK.Open"     "GOTO.JK.High"     "GOTO.JK.Low"      "GOTO.JK.Close"   
## [5] "GOTO.JK.Volume"   "GOTO.JK.Adjusted"
colnames(BUKA.JK)
## [1] "BUKA.JK.Open"     "BUKA.JK.High"     "BUKA.JK.Low"      "BUKA.JK.Close"   
## [5] "BUKA.JK.Volume"   "BUKA.JK.Adjusted"
colnames(ASGR.JK)
## [1] "ASGR.JK.Open"     "ASGR.JK.High"     "ASGR.JK.Low"      "ASGR.JK.Close"   
## [5] "ASGR.JK.Volume"   "ASGR.JK.Adjusted"
colnames(MTDL.JK)
## [1] "MTDL.JK.Open"     "MTDL.JK.High"     "MTDL.JK.Low"      "MTDL.JK.Close"   
## [5] "MTDL.JK.Volume"   "MTDL.JK.Adjusted"

Harga Saham Harian

Statistik Deskriptif

#Portofolio 1
data.frame(
  Mean = apply(price_dailysaham1,2,mean),
  Median = apply(price_dailysaham1,2,median),
  SD   = apply(price_dailysaham1,2,sd),
  Skew = apply(price_dailysaham1,2,skewness),
  Kurt = apply(price_dailysaham1,2,kurtosis)
)
##          Mean Median       SD       Skew     Kurt
## ICBP 7869.907   8025 400.9829 -0.6534830 2.248036
## UNVR 2205.278   2250 247.1220  0.2017334 1.917320
## MYOR 2126.296   2145 178.2096 -0.1878361 2.105879
#Portofolio 2
data.frame(
  Mean = apply(price_dailysaham2,2,mean),
  Median = apply(price_dailysaham2,2,median),
  SD   = apply(price_dailysaham2,2,sd),
  Skew = apply(price_dailysaham2,2,skewness),
  Kurt = apply(price_dailysaham2,2,kurtosis)
)
##            Mean Median         SD        Skew     Kurt
## GOTO   60.53704   60.0   4.851426 -0.14562687 2.365045
## BUKA  147.22222  148.0  10.125005  0.07851605 1.918571
## ASGR 1530.46296 1590.0 200.073733 -0.69114172 2.183406
## MDTL  572.03704  572.5  19.267690 -0.26811178 2.443015

Plot

#Portofolio 1
cols <- c("blue","red","green","yellow")
plot.zoo(price_dailysaham1, col=cols, main="Daily Closing Prices saham 1")

#Portofolio 2
cols <- c("purple","red","black","yellow")
plot.zoo(price_dailysaham2, col=cols, main="Daily Closing Prices saham 2")

Return harian

#Portofolio 1
ret_dailysaham1 <- na.omit(diff(log(price_dailysaham1)))
#Portofolio 2
ret_dailysaham2 <- na.omit(diff(log(price_dailysaham2)))

Statistik Deskriptif

#Portofolio 1
data.frame(
  Mean = apply(ret_dailysaham1,2,mean),
  Median = apply(ret_dailysaham1,2,median),
  SD   = apply(ret_dailysaham1,2,sd),
  Skew = apply(ret_dailysaham1,2,skewness),
  Kurt = apply(ret_dailysaham1,2,kurtosis)
)
##              Mean       Median         SD        Skew     Kurt
## ICBP -0.002098597  0.000000000 0.02111161 -0.10109832 3.520453
## UNVR -0.006719431 -0.007722046 0.03461759  0.21249281 3.002529
## MYOR -0.003302055  0.000000000 0.02601978 -0.05584167 2.797484
#Portofolio 2
data.frame(
  Mean = apply(ret_dailysaham2,2,mean),
  Median = apply(ret_dailysaham2,2,median),
  SD   = apply(ret_dailysaham2,2,sd),
  Skew = apply(ret_dailysaham2,2,skewness),
  Kurt = apply(ret_dailysaham2,2,kurtosis)
)
##               Mean Median         SD       Skew     Kurt
## GOTO -0.0053370337      0 0.02642739  0.3231029 4.673251
## BUKA -0.0019074739      0 0.02688708  0.1771942 4.438257
## ASGR  0.0053475033      0 0.04695587  1.9386816 9.929132
## MDTL -0.0006451201      0 0.01697068 -0.3867740 3.120826

Analisis Portofolio

#Proporsi Saham
modal <- 120000000

# Equal Weight (Proporsi Sama)
w1 <- rep(1/3, 3)
w2 <- rep(1/4, 4)

# Return Harian Portofolio
ret_p1 <- ret_dailysaham1 %*% w1
ret_p2 <- ret_dailysaham2 %*% w2

# Statistik Portofolio (Poin b)
mean_p1 <- mean(ret_p1)
risiko_p1 <- sqrt(t(w1) %*% cov(ret_dailysaham1) %*% w1)
risiko_p1
##            [,1]
## [1,] 0.01924389
mean_p2 <- mean(ret_p2)
risiko_p2 <- sqrt(t(w2) %*% cov(ret_dailysaham2) %*% w2)
risiko_p2
##            [,1]
## [1,] 0.01844783
# Analisis Profit 
profit_p1 <- sum(ret_p1) * modal
profit_p1
## [1] -25694575
profit_p2 <- sum(ret_p2) * modal
profit_p2
## [1] -4041978
cat("Portofolio 1 - Return Rata-rata:", mean_p1, "| Risiko:", risiko_p1, "\n")
## Portofolio 1 - Return Rata-rata: -0.004040028 | Risiko: 0.01924389
cat("Portofolio 2 - Return Rata-rata:", mean_p2, "| Risiko:", risiko_p2, "\n")
## Portofolio 2 - Return Rata-rata: -0.0006355311 | Risiko: 0.01844783
# Optimasi Mean-Variance 
opt1 <- portfolio.optim(ret_dailysaham1)
opt1
## $pw
## [1] 0.3392150 0.3354046 0.3253804
## 
## $px
##  [1] -4.111594e-03  8.786345e-04 -1.255420e-02  1.515061e-03 -2.611525e-03
##  [6] -6.837075e-03  7.652344e-05 -1.161096e-02 -9.894893e-03 -6.961515e-04
## [11]  2.643705e-03 -2.397959e-03  1.081145e-02  6.618356e-03 -1.710599e-03
## [16] -3.136632e-02 -3.094072e-02 -3.550712e-02  3.786229e-02  4.244704e-02
## [21]  4.684581e-03 -1.282706e-02  2.520657e-02  2.061402e-02  9.278277e-03
## [26] -1.535332e-02 -2.427545e-03 -1.423330e-03 -8.563136e-03 -1.507191e-04
## [31] -1.774530e-02 -1.192725e-03  1.678598e-02 -1.729630e-02  7.833310e-03
## [36] -2.032532e-02  7.859068e-03 -4.561683e-02 -1.709538e-02 -4.237073e-02
## [41]  8.581922e-03  3.982466e-04 -5.428718e-02  2.501690e-02  7.670936e-04
## [46] -6.719268e-03 -3.004940e-02  2.365731e-03  2.204875e-02 -3.106872e-03
## [51]  7.281440e-03 -2.499745e-02 -3.909419e-03
## 
## $pm
## [1] -0.004040028
## 
## $ps
## [1] 0.01924273
w_mv1 <- opt1$pw  
risiko_mv1 <- opt1$ps 
risiko_mv1
## [1] 0.01924273
opt2 <- portfolio.optim(ret_dailysaham2)
opt2
## $pw
## [1] 0.1433428 0.0000000 0.1138301 0.7428271
## 
## $px
##  [1]  8.333891e-03  5.087059e-03 -1.288356e-02 -6.930660e-04  9.646679e-04
##  [6]  7.596420e-03 -8.343633e-03 -2.519826e-03 -9.828661e-03  8.219774e-04
## [11] -1.280768e-02  3.820270e-03  3.327957e-02 -1.393546e-04 -9.459906e-03
## [16]  3.736005e-05 -2.166210e-02 -8.127613e-04  1.858503e-02 -1.803825e-02
## [21]  1.646127e-02  1.193634e-02 -1.827913e-02 -7.342097e-03 -3.188727e-03
## [26]  7.795479e-04  1.397371e-02 -1.109859e-02 -1.068367e-02  1.317472e-02
## [31]  8.512552e-03 -3.502742e-03  3.393015e-03 -1.628171e-03  3.211324e-02
## [36] -4.338776e-02  8.914131e-03 -2.697776e-02  1.418289e-03 -2.408437e-02
## [41]  1.943449e-02 -2.090277e-02 -2.765114e-02  1.461941e-02 -8.035409e-03
## [46]  8.773295e-03 -5.598367e-03 -4.684447e-03  1.894975e-02  2.471379e-02
## [51]  2.019034e-02  1.012874e-03 -1.634621e-02
## 
## $pm
## [1] -0.0006355311
## 
## $ps
## [1] 0.01546866
w_mv2 <- opt2$pw 
risiko_mv2 <- opt2$ps 
risiko_mv2
## [1] 0.01546866
cat("Portofolio 1 - Return Optimal:", opt1$target.return, "| Risiko Minimal:", opt1$ps, "\n")
## Portofolio 1 - Return Optimal: | Risiko Minimal: 0.01924273
cat("Portofolio 2 - Return Optimal:", opt2$target.return, "| Risiko Minimal:", opt2$ps, "\n")
## Portofolio 2 - Return Optimal: | Risiko Minimal: 0.01546866
analisis_mv_optimal <- data.frame(
  Keterangan = c("Return Portofolio (Optimal)", "Risiko Portofolio (Minimal SD)"),
  Portofolio_1_3Saham = as.numeric(c(opt1$target.return, opt1$ps)),
  Portofolio_2_4Saham = as.numeric(c(opt2$target.return, opt2$ps))
)
analisis_mv_optimal
##                       Keterangan Portofolio_1_3Saham Portofolio_2_4Saham
## 1    Return Portofolio (Optimal)          0.01924273          0.01546866
## 2 Risiko Portofolio (Minimal SD)          0.01924273          0.01546866
# Menampilkan bobot optimal per saham
cat("\nBobot Optimal Portofolio 1 (ICBP, UNVR, MYOR):\n")
## 
## Bobot Optimal Portofolio 1 (ICBP, UNVR, MYOR):
names(w_mv1) <- colnames(ret_dailysaham1)
print(round(w_mv1, 4))
##   ICBP   UNVR   MYOR 
## 0.3392 0.3354 0.3254
cat("\nBobot Optimal Portofolio 2 (GOTO, BUKA, BELI, MTDL):\n")
## 
## Bobot Optimal Portofolio 2 (GOTO, BUKA, BELI, MTDL):
names(w_mv2) <- colnames(ret_dailysaham2)
print(round(w_mv2, 4))
##   GOTO   BUKA   ASGR   MDTL 
## 0.1433 0.0000 0.1138 0.7428

Analisis Value at Risk (VaR)

Setup VaR

set.seed(2026)
alpha <- 0.05

VaR Return Harian

Historical Simulation

#Portofolio 1
VaR_hist_p1 <- quantile(ret_p1, probs = alpha, na.rm = TRUE)
#Portofolio 2
VaR_hist_p2 <- quantile(ret_p2, probs = alpha, na.rm = TRUE)

Mean-Variance (MV)

#saham 1
VaR_mv_p1 <- mean_p1 + qnorm(alpha) * risiko_p1
#Saham 2
VaR_mv_p2 <- mean_p2 + qnorm(alpha) * risiko_p2

Monte Carlo

#Portofolio 1
sim_p1 <- rnorm(10000, mean = mean_p1, sd = risiko_p1)
VaR_mc_p1 <- quantile(sim_p1, probs = alpha)
#Portofolio 2
sim_p2 <- rnorm(10000, mean = mean_p2, sd = risiko_p2)
VaR_mc_p2 <- quantile(sim_p2, probs = alpha)

Cornish-Fisher Expansion

# Portofolio 1
s1 <- skewness(ret_p1); k1 <- kurtosis(ret_p1); z <- qnorm(alpha)
z_cf1 <- z + (1/6)*(z^2-1)*s1 + (1/24)*(z^3-3*z)*(k1-3) - (1/36)*(2*z^3-5*z)*s1^2
VaR_cf_p1 <- mean_p1 + z_cf1 * risiko_p1

# Portofolio 2
s2 <- skewness(ret_p2); k2 <- kurtosis(ret_p2); z <- qnorm(alpha)
z_cf2 <- z + (1/6)*(z^2-1)*s2 + (1/24)*(z^3-3*z)*(k2-3) - (1/36)*(2*z^3-5*z)*s2^2
VaR_cf_p2 <- mean_p2 + z_cf2 * risiko_p2

Summary VaR Daily

VaR_summary_daily <- data.frame(
  Metode = c("Historical", "Mean-Variance", "Monte Carlo", "Cornish-Fisher"),
  Portofolio_1_3Saham = as.numeric(c(VaR_hist_p1, VaR_mv_p1, VaR_mc_p1, VaR_cf_p1)),
  Portofolio_2_4Saham = as.numeric(c(VaR_hist_p2, VaR_mv_p2, VaR_mc_p2, VaR_cf_p2))
)
VaR_summary_daily
##           Metode Portofolio_1_3Saham Portofolio_2_4Saham
## 1     Historical         -0.03822728         -0.02941584
## 2  Mean-Variance         -0.03569340         -0.03097951
## 3    Monte Carlo         -0.03549863         -0.03078655
## 4 Cornish-Fisher         -0.03678592         -0.02907944

Hasil

VaR_nominal <- VaR_summary_daily
VaR_nominal[, 2:3] <- VaR_summary_daily[, 2:3] * modal
print("Summary VaR (Nominal Rupiah):")
## [1] "Summary VaR (Nominal Rupiah):"
VaR_nominal
##           Metode Portofolio_1_3Saham Portofolio_2_4Saham
## 1     Historical            -4587274            -3529901
## 2  Mean-Variance            -4283208            -3717541
## 3    Monte Carlo            -4259836            -3694386
## 4 Cornish-Fisher            -4414311            -3489532