Optimasi Portofolio
Tugas Portofolio Saham
*Kontak | : \(\downarrow\)* |
naufal3433@gmail.com | |
https://www.instagram.com/m_naufalardiansyah/ | |
RPubs | https://rpubs.com/muhamad_naufal/ |
**
library(tidyquant)
## Warning: package 'tidyquant' was built under R version 4.2.2
## Loading required package: lubridate
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
## Loading required package: PerformanceAnalytics
## Warning: package 'PerformanceAnalytics' was built under R version 4.2.2
## Loading required package: xts
## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
##
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
##
## legend
## Loading required package: quantmod
## Loading required package: TTR
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(plotly)
## Warning: package 'plotly' was built under R version 4.2.2
## Loading required package: ggplot2
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
library(timetk)
## Warning: package 'timetk' was built under R version 4.2.2
= c('BBCA.JK','TLKM.JK','BBRI.JK','ASII.JK','UNVR.JK')
tick
= tq_get(tick,
pricedata from = '2020-01-01',
to = Sys.Date(),
get = 'stock.prices')
pricedata
Pengembalian
Setelah menginput 5 data saham, kita dapat menghitung pengembalian harian untuk beberapa saham ini dengan menggunakan pengembalian logaritmik yang bertujuan untuk memastikan data stasioner.
<- pricedata %>%
log_ret_tidy 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) # print data dalam tabel
## Warning: package 'DT' was built under R version 4.2.1
datatable(log_ret_tidy)
Kita dapat menggunakan fungsi spread() untuk mengubah datatable menjadi format lebar dan menggunakan xts() untuk mengubahnya menjadi objek time series.
library(tidyr)
= log_ret_tidy %>%
log_ret_xts 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
<- colMeans(log_ret_xts)
mean_ret print ( round (mean_ret, 4))
## ASII.JK BBCA.JK BBRI.JK TLKM.JK UNVR.JK
## -1e-04 4e-04 3e-04 1e-04 -7e-04
Matriks Kovariansi
<- cov(log_ret_xts) * 252
cov_mat print(round(cov_mat,4))
## ASII.JK BBCA.JK BBRI.JK TLKM.JK UNVR.JK
## ASII.JK 0.1381 0.0523 0.0689 0.0510 0.0406
## BBCA.JK 0.0523 0.0824 0.0632 0.0442 0.0342
## BBRI.JK 0.0689 0.0632 0.1445 0.0535 0.0370
## TLKM.JK 0.0510 0.0442 0.0535 0.1079 0.0322
## UNVR.JK 0.0406 0.0342 0.0370 0.0322 0.1292
Penerapan Metode Portofolio
Dalam menerapkan metode portofolio,
<- runif(n = length(tick))
wts <- wts/sum(wts)
wts
<- (sum(wts * mean_ret) + 1)^252 - 1
port_returns <- sqrt(t(wts) %*% (cov_mat %*% wts))
port_risk <- port_returns/port_risk sharpe_ratio
<- 5000
num_port
<- matrix(nrow = num_port, ncol = length(tick))
all_wts <- vector('numeric', length = num_port)
port_returns <- vector('numeric', length = num_port)
port_risk <- vector('numeric', length = num_port) sharpe_ratio
for (i in seq_along(port_returns)) {
<- runif(length(tick))
wts <- wts/sum(wts)
wts
<- wts
all_wts[i,]
<- sum(wts * mean_ret)
port_ret <- ((port_ret + 1)^252) - 1
port_ret
<- port_ret
port_returns[i]
<- sqrt(t(wts) %*% (cov_mat %*% wts))
port_sd <- port_sd
port_risk[i]
<- port_ret/port_sd
sr <- sr
sharpe_ratio[i] }
<- tibble(Return = port_returns,
portfolio_values Risk = port_risk,
SharpeRatio = sharpe_ratio)
<- tk_tbl(all_wts) 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)
<- tk_tbl(cbind(all_wts, portfolio_values)) 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)
library(forcats)
## Warning: package 'forcats' was built under R version 4.2.1
<- portfolio_values[which.min(portfolio_values$Risk),]
min_var
<- min_var %>%
p gather(ASII.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)
<- portfolio_values[which.max(portfolio_values$SharpeRatio),]
max_sr
<- max_sr %>%
p gather(ASII.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)
Batas Efisien Portofolio
<- portfolio_values %>%
p 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.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)