UAS Optimasi

5 data saham pada Bursa Efek Indonesia LQ45

DHELA ASAFIANI AGATHA

December 20, 2023

Pendahuluan

Dalam praktik ini, penulis memilih 5 saham berikut untuk diolah datanya, antara lain:


  • Kalbe Farma Tbk (KLBF.JK)
  • Indofood CBP Sukses Makmur Tbk (ICBP.JK)
  • Indofood Sukses Makmur Tbk (INDF.JK)
  • Industri Jamu dan Farmasi Sido Muncul Tbk (SIDO.JK)
  • unilever INDONESIA (Persero) Tbk (UNVR.JK)

LibrarY

pacman::p_load(tidyverse,
               tidyquant,
               tidyr,
               DT,
               timetk,
               forcats,
               plotly,
               timetk,
               rmdformats)

Grafik Market Saham dari awal tahun 2023

Di bawah ini merupakan koding untuk melihat grafik pertumbuhan market saham dari 1 Januari 2023 hinga hari ini, adalah sebagai berikut:

stock <- c('KLBF.JK', 'ICBP.JK', 'INDF.JK', 'SIDO.JK','UNVR.JK')


data_harga <- tq_get(stock,
                     from = '2023-01-01',
                     to   = Sys.Date(),
                     get  = 'stock.prices')

data_harga %>%
  plot_ly(x = ~date,
          type = 'candlestick',
          open = ~open,
          close = ~close,
          high = ~high,
          low = ~low) %>%
layout(title = 'Harga 5 Stock Saham Tahun 2023',
         xaxis = list(rangeslider = list(visible = F)))

Hasil Output: Grafik atau plot di atas merupakan grafik pertumbuhan market saham dari 1 Januari 2023 hingga hari ini.

Proses Optimasi

Import Data

stock <- c('KLBF.JK', 'ICBP.JK', 'INDF.JK', 'SIDO.JK','UNVR.JK')


data_harga <- tq_get(stock,
                     from = '2023-01-01',
                     to   = Sys.Date(),
                     get  = 'stock.prices')

data_harga

Hasil Output: Ada 1.165 data output dari 5 saham yang dipilih dengan nilai jual tertinggi, terendah, hingga volume terdapat di tabel tersebut.

Return Saham

return_saham <- data_harga %>%
  group_by(symbol) %>%
  tq_transmute(select     = adjusted,
               mutate_fun = periodReturn,
               period     = 'daily',
               col_rename = 'ret',
               type       = 'log')
 
datatable(return_saham)
rerataan_return <- return_saham %>% # Rata-rata pengembalian portofolio saham
  spread(symbol, value = ret) %>%
  tk_xts()

datatable(rerataan_return)

Matriks Kovariansi

Menghitung matriks kovariansi untuk semua stok saham dengan mengalikan dengan 365 dalam format tahunan, sebagai berikut:

kov_metriks <- cov(rerataan_return) * 252
kov_metriks
##             ICBP.JK     INDF.JK     KLBF.JK     SIDO.JK     UNVR.JK
## ICBP.JK 0.062584405 0.011496445 0.006946459 0.006922401 0.011291524
## INDF.JK 0.011496445 0.038330515 0.007618546 0.002528558 0.008781774
## KLBF.JK 0.006946459 0.007618546 0.099701736 0.010627966 0.021147041
## SIDO.JK 0.006922401 0.002528558 0.010627966 0.093157173 0.013345334
## UNVR.JK 0.011291524 0.008781774 0.021147041 0.013345334 0.070028165

Hasil Output: Dikalikan 252 hari Karena dalam satu tahun, biasanya hari kerja berlaku 252 hari (karena ada hari libur dll)

Rata-rata pengembalian portofolio saham

rerata_oi <- colMeans(rerataan_return)
rerata_oi
##       ICBP.JK       INDF.JK       KLBF.JK       SIDO.JK       UNVR.JK 
##  0.0002474151 -0.0001443074 -0.0008493001 -0.0010356133 -0.0010540967

Hasil Output: Pada hasil di atas dapat dilihat bahwa rata-rata nilai return paling tinggi adalah saham ICBP atau Indofood CBP Sukses Makmur Sebaliknya, saham INDF atau Indofood Sukses Makmur mendapat nilai paling rendah dibandingkan dengan 4 saham lainnya.

Penerapan Metode Portofolio


  • Bobot acak
  • Rata-rata pengembalian aset
  • Risiko portofolio
  • Bobot portofolio

Membuat bobot acak

# membuat bobot acak
acak <- runif(n = length(data_harga))
acak <- acak/sum(acak)

Rata-rata pengembalian aset

Penulis ingin menghitung rata-rata pengembalian aset, sebagai berikut:

# rata-rata pengembalian aset
port_returns <- (sum(acak * rerata_oi) + 1)^252 - 1
port_returns
## [1] -0.0928083

Hasil Output: Rata-rata pengembalian aset -0.1125351 artinya investasi anda rata-rata RUGI sebesar 11.25% setahun.

Risiko portofolio

Penulis ingin menghitung risiko portofolio, sebagai berikut:

# risiko portofolio

# Assuming you have 5 stocks
acak <- runif(5)
acak <- acak / sum(acak)

# Convert acak to a matrix or one-column vector if necessary
acak_matrix <- matrix(acak, nrow = 5, ncol = 1)

# Calculate portfolio risk
port_risk <- sqrt(t(acak_matrix) %*% (kov_metriks %*% acak_matrix))
port_risk
##           [,1]
## [1,] 0.1642992

Hasil Output: Nilai 0.1724537 ini menunjukkan tingkat risiko yang sedang, yang cukup umum untuk portofolio saham. Semakin tinggi angkanya, semakin besar kemungkinan nilai investasi Anda naik turun secara signifikan.

Bobot portofolio sharpe ratio

Penulis ingin menghitung bobot portofolio sharpe ratio, sebagai berikut:

# bobot portofolio sharpe ratio
sharpe_ratio <- port_returns/port_risk
sharpe_ratio
##            [,1]
## [1,] -0.5648738

Membentuk protofolio secara acak

Proses pembentukan protfolio secara acak dengan simulasi 5000 kali untuk memastikan signifikansinya secara statistik, sebagai berikut:

num_port <- 5000

all_wts <- matrix(nrow = num_port, ncol = length(data_harga))
port_returns <- vector('numeric', length = num_port)
port_risk <- vector('numeric', length = num_port)
sharpe_ratio <- vector('numeric', length = num_port)

Lalu jalankan loop sebanyak 5000 kali, sebagai berikut:

# Number of portfolios to simulate
num_portfolios <- length(port_returns)

# Initialize all_wts with the correct dimensions
all_wts <- matrix(nrow = num_portfolios, ncol = 5)

for (i in seq_along(port_returns)) {
  
  # Generate random weights for 5 stocks
  acak <- runif(5)
  acak <- acak/sum(acak)
  
  all_wts[i,] <- acak 
  
  # Calculate portfolio return
  port_ret <- sum(acak * rerata_oi)
  port_ret <- ((port_ret + 1)^252) - 1
  
  port_returns[i] <- port_ret
  
  # Calculate portfolio risk
  port_sd <- sqrt(t(acak) %*% (kov_metriks  %*% acak))
  port_risk[i] <- port_sd
  
  # Calculate Sharpe Ratio
  sr <- port_ret/port_sd
  sharpe_ratio[i] <- sr
}

Lalu membuat tabel data untuk menyimpan semua nilai nya, sebagai berikut:

portfolio_values <- tibble(Return = port_returns,
                             Risk = port_risk,
                      SharpeRatio = sharpe_ratio)


all_wts <- tk_tbl(all_wts)

colnames(all_wts) <- colnames(rerataan_return)

portfolio_values <- tk_tbl(cbind(all_wts, portfolio_values))

datatable(portfolio_values)

Hasil Output: Penulis telah berhasil menentukan bobot untuk setiap aset dengan mengukur risiko dan pengembalian, serta menghitung sharpe_ratio dari setiap portofolio. Langkah berikutnya adalah mengidentifikasi portofolio yang paling optimal, yaitu yang memiliki varian minimum dan nilai Sharpe ratio tertinggi, untuk memaksimalkan efisiensi investasi.


Sekarang kita akan menghitung variansi minimum, sebagai berikut:

Variansi minimum

library(forcats)  # menggunakan fungsi `fct_reorder`

# Minumum Variansi
min_var <- portfolio_values[which.min(portfolio_values$Risk),]
min_var
p <- min_var %>%
  gather(ICBP.JK:UNVR.JK, key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset,Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Aset', 
       y = 'Bobot', 
       title = "Bobot Portofolio dengan Variansi Minimum") +
  scale_y_continuous(labels = scales::percent) +
  theme(legend.position="none")

ggplotly(p)

Hasil Output: Dari hasil bagan di atas, portofolio varian minimum tidak memiliki alokasi untuk KLBF dan SIDO sangat sedikit. Mayoritas protofolio dlimpahkan investasinya ke saham ICBP dan INDF

# Maksimum Sharpe Ratio
max_sr <- portfolio_values[which.max(portfolio_values$SharpeRatio),]

p <- max_sr %>%
  gather(ICBP.JK:UNVR.JK, key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset,Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Aset', 
       y = 'Bobot', 
       title = "Bobot Portofolio Tangensi (Maksimum Sharpe Ratio)") +
  scale_y_continuous(labels = scales::percent)+
  theme(legend.position="none")

ggplotly(p)

Hasil Output: Dari hasil bagan di atas, portofolio dengan rasio sharpe tertinggi di raih oleh ICBP,, kemudian di susul oleh INDF dan UNVR. Portofolio dengan sharpe terendah adalah SIDO

Batas Efisien Portofolio

Plot semua portofolio acak dan akan di visualisasikan sesuai dengan batas efisien nya, sebagai berikut:

p <- portfolio_values %>%
  ggplot(aes(x = Risk, y = Return, color = SharpeRatio)) +
  geom_point() +
  scale_color_gradient(low = "#BA292E", high = "#314FDD") +
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Risiko Tahunan',
       y = 'Pengembalian Tahunan',
       title = "Optimasi Portofolio & Perbatasan yang Efisien") +
  geom_point(aes(x = Risk, y = Return), data = min_var, color = 'yellow') +
  geom_point(aes(x = Risk, y = Return), data = max_sr, color = 'yellow') +
  annotate('text', x = 0.31, y = 0.31, label = "Portofolio Tangensi") +
  annotate('text', x = 0.24, y = 0.11, label = "Portofolio Varians minimum") +
  annotate(geom = 'segment', x = 0.3023, xend = 0.3023,  y = 0.23, 
           yend = 0.29, color = 'red', arrow = arrow(type = "open")) +
  annotate(geom = 'segment', x = 0.25, xend = 0.25,  y = 0.015, 
           yend = 0.10, color = 'red', arrow = arrow(type = "open"))
  
ggplotly(p)