Portofolio Optimasi

~ Tugas Optimasi ~


Kontak : \(\downarrow\)
Email
Instagram https://www.instagram.com/dsciencelabs/
RPubs https://rpubs.com/dsciencelabs/

Impor Data

Saham untuk membangun portofolio dan komuditas saham yang diinginkan adalah sebagai berikut:
* BCA JKT (BBCA)
* Bank Mandiri (BMRI)
* Bank BRI (BRIS)
* Indofood Sukses Makmur (INDF)
* Unilever Indonesia (UNVR)

library(tidyquant)
library(plotly)
library(timetk)

#daftar data saham yang ingin diimport
tick <- c('BBCA.JK', 'BMRI.JK', 'BRIS.JK', 'INDF.JK', 'UNVR.JK')

price_data <- tq_get(tick,
                     from = '2020-01-01',
                     to = '2022-12-09',
                     get = 'stock.prices')
head(price_data)

Pengembaliam

Menghitung return harian untuk saham-saham diatas dengan menggunakan pengembalian logaritmik.

log_ret_tidy <- price_data %>%
  group_by(symbol) %>%
  tq_transmute(select = adjusted,
               mutate_fun = periodReturn,
               period = 'daily',
               col_rename = 'ret',
               type = 'log')

#log_ret_tidy$ret <-round(log_ret_tidy$ret,4)

library(DT)
datatable(log_ret_tidy)

Selanjutnya menggunakan fungsi spread() untuk mengubahnya menjadi format lebar dan mengubahnya menjadi objek time series menggunakan fungsi xts()

library(tidyr)

log_ret_xts <- log_ret_tidy %>%
  spread(symbol, value = ret) %>%
  tk_xts()

datatable(log_ret_xts)

Rata-rata pengembalian

Menghitung rata-rata pengembalian harian untuk setiap aset.

mean_ret <- colMeans(log_ret_xts)
print(round(mean_ret,4))
## BBCA.JK BMRI.JK BRIS.JK INDF.JK UNVR.JK 
##  0.0004  0.0005  0.0019  0.0000 -0.0007

Matriks Kovariansi

Untuk menghitung matriks kovarians untuk semua stok dengan mengalikannya dengan 360 dalam format tahunan.

cov_mat <- cov(log_ret_xts) * 360
print(round(cov_mat,4))
##         BBCA.JK BMRI.JK BRIS.JK INDF.JK UNVR.JK
## BBCA.JK  0.1187  0.0957  0.0843  0.0471  0.0494
## BMRI.JK  0.0957  0.2109  0.1278  0.0667  0.0540
## BRIS.JK  0.0843  0.1278  0.6831  0.0795  0.0571
## INDF.JK  0.0471  0.0667  0.0795  0.1408  0.0659
## UNVR.JK  0.0494  0.0540  0.0571  0.0659  0.1857

Penerapan Metode Portofolio

Langkah-langkah untuk memperhitungkan oengembalian dan risiko portofolio sebagai berikut:
* Bobok acak
* rata-rata pengembalian aset
* Risiko Portofolio
* Bobot Portofolio

wts <- runif(n = length(tick))
wts <- wts/sum(wts)

port_returns <- (sum(wts * mean_ret) + 1)^252 - 1
port_risk <- sqrt(t(wts) %*% (cov_mat %*% wts))
sharpe_ratio <- port_returns/port_risk

Selanjutnya melakukan proses pembentukann portofolio secara acak dengan simuasi 5000 kali untuk memastikan signifikansinya secara statistik.

num_port <- 5000

# matriks kosong untuk menyimpan bobot
all_wts <- matrix(nrow = num_port, ncol = length(tick))

# vektor kosong untuk menyimpan pengembalian portofolio
port_returns <- vector('numeric', length = num_port)

# vektor kosong untuk menyimpan standar deviasi portofolio
port_risk <- vector('numeric', length = num_port)

#vektor kosong untuk menyimpan portofolio sharpe ratio
sharpe_ratio <- vector('numeric', length = num_port)

Selanjutnya dijalankan for loop 5000 kali.

for(i in seq_along(port_returns)) {
  
  wts<- runif(length(tick))
  wts <- wts/sum(wts)
  
  #menyimpan proporsi saham dalam matriks
  all_wts[i,] <- wts
  
  #pengembalian portofolio
  port_ret <- sum(wts * mean_ret)
  port_ret <- ((port_ret +1)^360) - 1
  
  #menyimpan nilai pengembalian portofolio
  port_returns[i] <- port_ret
  
  # membuat dan menyimpan risiko portofolio
  port_sd <- sqrt(t(wts) %*% (cov_mat %*% wts))
  port_risk[i] <-port_sd
  
  #Membuat dan menyimpan portofolio sharpe ratio
  # dengan asumsi tingkat bebas risiko 0%
  sr <- port_ret/port_sd
  sharpe_ratio[i] <- sr
  
}

Selanjutnya, membuat tabel data untuk menyimpan semua nilai secara bersamaan.

# menyimpan nilai dalam tabel
portfolio_values <- tibble(Return  = port_returns,
                            Risk = port_risk,
                            SharpeRatio = sharpe_ratio)

# mengubah matriks mwnjadi tibble
all_wts <- tk_tbl(all_wts)

# mengubah nama kolom
colnames(all_wts) <- colnames(log_ret_xts)

# menyisir (susun) semua nilai bersama-sama
portfolio_values <- tk_tbl(cbind(all_wts, portfolio_values))

#print hasil dalam tabel
datatable(portfolio_values)

Karena sudah memiliki bobot di setiap aset dengan risiko dan pengembalian bersama dengan sharpe ratio dari setiap portofolio mari lihat portofolio yang paling penting dengan varians minimum dan juga sharpe ratio tertinggi.

Variansi Minimum

library(forcats)

min_var <- portfolio_values[which.min(portfolio_values$Risk),]

p <- min_var %>%
  gather(BBCA.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)

seperti yang kita amati, portofolio varian minimum tidak memiliki alokasi untuk saham Bank Mandiri dan Bank BRI Syariah. mayoritas portfolio diinvestasikan di saham Bank BCA dan saham Indofood Sukses Makmur

Portofolio Tangensi

# maksimum sharpe ratio
max_sr <- portfolio_values[which.max(portfolio_values$SharpeRatio),]

rii <- max_sr %>%
  gather(BBCA.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 Portfolio Tangensi(Max Sharpe Ratio)") +
  scale_y_continuous(labels = scales::percent) +
  theme(legend.position = "none")

ggplotly(rii)

portofolio dengan rasio sharpe tertinggi hanya memiliki sedikit investasi di Unilever dan Indofood. Portofolio ini sebenarnya memiliki sebagian besar aset yang diinvestasikan di BRIS.JK, BMRI.JK, BBCA.JK. Ketiga saham tersebut berkinerja terbaik dalam satu dekade.

Batas Efisien Portofolio

p <- portfolio_values %>%
  ggplot(aes(x = Risk, y = Return, color = SharpeRatio)) +
  geom_point() +
  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 = 'red') +
  geom_point(aes(x = Risk,y = Return), data = max_sr, color = 'red') +
  annotate('text', x = 0.71, y = 0.81, label = "Portofolio Tangensi") +
  annotate('text', x = 0.290, y = 0.250, label = "Portofolio Varians minimum") +
  annotate(geom = 'segment', x = 0.6920, xend = 0.6920,  y = 0.500, 
           yend = 0.6800, color = 'red', arrow = arrow(type = "open")) +
  annotate(geom = 'segment', x = 0.2870, xend = 0.2870,  y = 0.06, 
           yend = 0.200, color = 'red', arrow = arrow(type = "open"))
  

ggplotly(p)