Optimasi
Tugas 2
| Kontak | : \(\downarrow\) |
| yosia.yosia@student.matanauniversity.ac.id | |
| yyosia | |
| RPubs | https://rpubs.com/yosia/ |
Optimalisasi Portofolio
Import Data
ITMG.JK = PT Indo Tambangraya Megah Tbk
BBCA.JK = PT Bank Central Asia Tbk
BRIS.JK = PT Bank Syariah Indonesia Tbk
BIPI.JK = PT Astrindo Nusantara Infrastruktur Tbk
BUMI.JK = PT Bumi Resources Tbk
library(tidyquant)
library(plotly)
library(timetk)tick <- c('ITMG.JK', 'BBCA.JK', 'BRIS.JK', 'BIPI.JK', 'BUMI.JK')
price_data <- tq_get(tick,
from = '2020-01-01',
to = '2022-12-09',
get = 'stock.prices')
head(price_data)Return
Selanjutnya menghitung pengembalian (Return) harian untuk saham-saham ini dengan menggunakan pengembalian logaritmik (untuk memastikan data stasioner).
log_ret_tidy <- price_data %>%
group_by(symbol) %>%
tq_transmute(select = adjusted,
mutate_fun = periodReturn,
period = 'daily',
col_rename = 'ret',
type = 'log')
library(DT)
datatable(log_ret_tidy)Selanjutnya akan digunakan fungsi spread() untuk
mengubahnya menjadi format lebar. dan kita juga akan mengubahnya menjadi
objek time series menggunakan fungsi xts() .
library(tidyr)
log_ret_xts <- log_ret_tidy %>%
spread(symbol, value = ret) %>%
tk_xts()## Warning: Non-numeric columns being dropped: date
## Using column `date` for date_var.
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 BIPI.JK BRIS.JK BUMI.JK ITMG.JK
## 0.0004 0.0018 0.0019 0.0013 0.0023
Matriks Kovariansi
Selanjutnya, menghitung matriks kovarians untuk semua stok dengan mengalikannya dengan 252 dalam format tahunan.
cov_mat <- cov(log_ret_xts) * 252
print(round(cov_mat,4))## BBCA.JK BIPI.JK BRIS.JK BUMI.JK ITMG.JK
## BBCA.JK 0.0831 0.0034 0.0590 0.0094 0.0456
## BIPI.JK 0.0034 0.2165 -0.0006 0.0427 0.0244
## BRIS.JK 0.0590 -0.0006 0.4782 0.0300 0.0743
## BUMI.JK 0.0094 0.0427 0.0300 0.4120 0.0734
## ITMG.JK 0.0456 0.0244 0.0743 0.0734 0.2240
Penerapan Metode Portofolio
Bobot 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_riskSelanjutnya dilakukan proses pembetukan portofolio secara acak dengan simulasi 5000 kali untuk memastikan signifikansinya secara statistik. Persiapkan vektor kosong untuk masing-masing langkah diatas:
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)Selanjutnya mari kita jalankan for loop 5000 kali.
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
}Selanjutnya, membuat tabel data untuk menyimpan semua nilai secara bersamaan.
portfolio_values <- tibble(Return = port_returns,
Risk = port_risk,
SharpeRatio = sharpe_ratio)
all_wts <- tk_tbl(all_wts)## Warning in tk_tbl.data.frame(as.data.frame(data), preserve_index,
## rename_index, : Warning: No index to preserve. Object otherwise converted to
## tibble successfully.
colnames(all_wts) <- colnames(log_ret_xts)
portfolio_values <- tk_tbl(cbind(all_wts, portfolio_values))## Warning in tk_tbl.data.frame(cbind(all_wts, portfolio_values)): Warning: No
## index to preserve. Object otherwise converted to tibble successfully.
datatable(portfolio_values)Sekarang, kita sudah memiliki bobot di setiap aset dengan risiko dan pengembalian bersama dengan Sharpe ratio dari setiap portofolio. Selanjutnya, mari kita 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:ITMG.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 dapat kita amati, portofolio Varian minimum tidak memiliki alokasi untuk ITMG.JK dan BRIS.JK sangat sedikit. Mayoritas portofolio diinvestasikan di saham BUMI.JK, BIPI.JK & BBCA.JK.
Portofolio Tangensi
Selanjutnya, mari kita lihat portofolio tangency atau portofolio dengan Sharpe ratio tertinggi.
max_sr <- portfolio_values[which.max(portfolio_values$SharpeRatio),]
p <- max_sr %>%
gather(BBCA.JK:ITMG.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)Tidak mengherankan, portofolio dengan rasio Sharpe tertinggi hanya memiliki sedikit investasi di BBCA.JK & BUMI.JK. Portofolio ini sebenarnya memiliki sebagian besar aset yang diinvestasikan di BRIS.JK, BIPI.JK, ITMG.JK. Ketiga saham tersebut berkinerja terbaik dalam satu dekade.
Batas Efisien Portofolio
Akhirnya mari kita plot semua portofolio acak dan memvisualisasikan batas efisien.
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.329, y = 0.78, label = "Portofolio Tangensi") +
annotate('text', x = 0.287, y = 0.429, label = "Portofolio Varians minimum") +
annotate(geom = 'segment', x = 0.3163, xend = 0.3163, y = 0.659,
yend = 0.74, color = 'red', arrow = arrow(type = "open")) +
annotate(geom = 'segment', x = 0.2383, xend = 0.2383, y = 0.328,
yend = 0.40, color = 'red', arrow = arrow(type = "open"))
ggplotly(p)