Saham

Optimasi


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

data

library(tidyquant)
library(plotly)
library(timetk)
library(DT)
library(tidyr)
library(forcats)
tick <- c('BBCA.JK', 'GGRM.JK', 'JSMR.JK', 'INDF.JK', 'BBRI.JK')
price_data <- tq_get(tick,
                     from = '2020-01-01',
                     to = Sys.Date(),
                     get = 'stock.prices')
head(price_data)

pengembalian

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

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

datatable(log_ret_xts)

Rata-rata pengembalian

mean_ret <- colMeans(log_ret_xts)
print(round(mean_ret, 4))
## BBCA.JK BBRI.JK GGRM.JK INDF.JK JSMR.JK 
##  0.0004  0.0003 -0.0014  0.0000 -0.0008

Matriks Kovariansi

cov_mat <- cov(log_ret_xts) * 252
print(round(cov_mat,4))
##         BBCA.JK BBRI.JK GGRM.JK INDF.JK JSMR.JK
## BBCA.JK  0.0824  0.0634  0.0350  0.0326  0.0472
## BBRI.JK  0.0634  0.1446  0.0449  0.0460  0.0612
## GGRM.JK  0.0350  0.0449  0.1318  0.0480  0.0437
## INDF.JK  0.0326  0.0460  0.0480  0.0975  0.0388
## JSMR.JK  0.0472  0.0612  0.0437  0.0388  0.1621

Penerapan Metode 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

num_port <- 5000

all_wts <- matrix(nrow = num_port, ncol = length(tick))

port_returns <- vector('numeric', length = num_port)

port_risk <- vector('numeric', length = num_port)

sharpe_ratio <- vector('numeric', length = num_port)
for (i in seq_along(port_returns)) {
  wts <- runif(length(tick))
  wts <- wts/sum(wts)
  
  all_wts[i,] <- wts
  
  port_ret <- sum(wts * mean_ret)
  port_ret <- ((port_ret + 1)^252) - 1
  
  port_returns[i] <- port_ret
  
  port_sd <- sqrt(t(wts) %*% (cov_mat %*% wts))
  port_risk[i] <- port_sd
  
  sr <- port_ret/port_sd
  sharpe_ratio[i]<-sr
}
portfolio_values <- tibble(Return = port_returns,
                           Risk = port_risk,
                           SharpeRatio = sharpe_ratio)

all_wts <- tk_tbl(all_wts)

colnames(all_wts) <- colnames(log_ret_xts)

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

datatable(portfolio_values)

Variansi Minimum

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

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

Portofolio Tangensi

max_sr<- portfolio_values[which.max(portfolio_values$SharpeRatio), ]

p <- max_sr %>%
  gather(BBCA.JK:JSMR.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)

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 = 'black') +
  geom_point(aes(x = Risk, y = Return), data = max_sr, color = 'red') +
  annotate('text', x = 0.25, y = 0.10, label = "Portofolio Tangensi") +
  annotate('text', x = 0.255, y = -0.05, label = "Portofolio Varians minimum")
  

ggplotly(p)