options(repos = c(CRAN = "https://cloud.r-project.org"))
install.packages("tidyverse")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'tidyverse' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
install.packages("lubridate")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'lubridate' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'lubridate'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problem copying
## C:\Users\Karo\AppData\Local\R\win-library\4.5\00LOCK\lubridate\libs\x64\lubridate.dll
## to
## C:\Users\Karo\AppData\Local\R\win-library\4.5\lubridate\libs\x64\lubridate.dll:
## Permission denied
## Warning: restored 'lubridate'
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
install.packages("readxl")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'readxl' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'readxl'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problem copying
## C:\Users\Karo\AppData\Local\R\win-library\4.5\00LOCK\readxl\libs\x64\readxl.dll
## to C:\Users\Karo\AppData\Local\R\win-library\4.5\readxl\libs\x64\readxl.dll:
## Permission denied
## Warning: restored 'readxl'
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
install.packages("highcharter")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'highcharter' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
install.packages("tidyquant")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'tidyquant' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
install.packages("timetk")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'timetk' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
install.packages("tibbletime")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'tibbletime' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'tibbletime'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problem copying
## C:\Users\Karo\AppData\Local\R\win-library\4.5\00LOCK\tibbletime\libs\x64\tibbletime.dll
## to
## C:\Users\Karo\AppData\Local\R\win-library\4.5\tibbletime\libs\x64\tibbletime.dll:
## Permission denied
## Warning: restored 'tibbletime'
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
install.packages("quantmod")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'quantmod' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
install.packages("PerformanceAnalytics")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'PerformanceAnalytics' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'PerformanceAnalytics'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problem copying
## C:\Users\Karo\AppData\Local\R\win-library\4.5\00LOCK\PerformanceAnalytics\libs\x64\PerformanceAnalytics.dll
## to
## C:\Users\Karo\AppData\Local\R\win-library\4.5\PerformanceAnalytics\libs\x64\PerformanceAnalytics.dll:
## Permission denied
## Warning: restored 'PerformanceAnalytics'
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
install.packages("scales")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'scales' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.5.3
## Warning: package 'readr' was built under R version 4.5.2
## Warning: package 'forcats' was built under R version 4.5.2
## Warning: package 'lubridate' was built under R version 4.5.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.2.0
## ✔ forcats 1.0.1 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.2 ✔ tibble 3.2.1
## ✔ lubridate 1.9.5 ✔ tidyr 1.3.1
## ✔ purrr 1.0.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(lubridate)
library(readxl)
## Warning: package 'readxl' was built under R version 4.5.3
library(highcharter)
## Warning: package 'highcharter' was built under R version 4.5.2
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(tidyquant)
## Warning: package 'tidyquant' was built under R version 4.5.3
## Warning: package 'xts' was built under R version 4.5.3
## Warning: package 'quantmod' was built under R version 4.5.3
## Warning: package 'TTR' was built under R version 4.5.3
## Warning: package 'PerformanceAnalytics' was built under R version 4.5.3
## ── Attaching core tidyquant packages ─────────────────────── tidyquant 1.0.12 ──
## ✔ PerformanceAnalytics 2.0.8 ✔ TTR 0.24.4
## ✔ quantmod 0.4.28 ✔ xts 0.14.2
## ── Conflicts ────────────────────────────────────────── tidyquant_conflicts() ──
## ✖ zoo::as.Date() masks base::as.Date()
## ✖ zoo::as.Date.numeric() masks base::as.Date.numeric()
## ✖ dplyr::filter() masks stats::filter()
## ✖ xts::first() masks dplyr::first()
## ✖ dplyr::lag() masks stats::lag()
## ✖ xts::last() masks dplyr::last()
## ✖ PerformanceAnalytics::legend() masks graphics::legend()
## ✖ quantmod::summary() masks base::summary()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(timetk)
## Warning: package 'timetk' was built under R version 4.5.3
##
## Attaching package: 'timetk'
##
## The following object is masked from 'package:tidyquant':
##
## FANG
library(tibbletime)
## Warning: package 'tibbletime' was built under R version 4.5.3
## Registered S3 method overwritten by 'tibbletime':
## method from
## seq.hms hms
##
## Attaching package: 'tibbletime'
##
## The following object is masked from 'package:tidyquant':
##
## FANG
##
## The following object is masked from 'package:stats':
##
## filter
library(quantmod)
library(PerformanceAnalytics)
library(scales)
## Warning: package 'scales' was built under R version 4.5.3
##
## Attaching package: 'scales'
##
## The following object is masked from 'package:purrr':
##
## discard
##
## The following object is masked from 'package:readr':
##
## col_factor
# a) hindade allalaadimine
symbols <- c("VTI", "GLD", "TLT","BTC-USD", "VNQ", "TIP", "VXUS", "QUAL")
prices <-
getSymbols(symbols,
src = 'yahoo',
from = "2020-12-31",
to = "2025-12-31",
auto.assign = TRUE,
warnings = FALSE) %>%
map(~Ad(get(.))) %>%
reduce(merge) %>%
`colnames<-`(symbols)
colnames(prices)[colnames(prices) == "BTC-USD"] <- "BTCUSD"
prices <- na.omit(prices)
# b) Hinnad kuisteks tootlusteks
prices_monthly <- to.monthly(prices,
indexAt = "lastof",
OHLC = FALSE)
head(prices_monthly, 5)
## VTI GLD TLT BTCUSD VNQ TIP VXUS
## 2020-12-31 181.3900 178.36 133.9169 29001.72 70.53813 105.2224 51.13775
## 2021-01-31 180.7842 172.61 129.0521 34316.39 70.56305 105.5027 51.26525
## 2021-02-28 186.4596 161.81 121.6536 46339.76 72.97992 103.7222 52.44680
## 2021-03-31 193.2615 159.96 115.2725 58918.83 76.73987 103.4502 53.42740
## 2021-04-30 202.9952 165.66 118.1486 57750.18 82.77147 104.9292 54.91007
## QUAL
## 2020-12-31 108.9324
## 2021-01-31 105.8484
## 2021-02-28 109.2324
## 2021-03-31 114.6718
## 2021-04-30 120.1803
asset_returns_xts <-
Return.calculate(prices_monthly,
method = "log") %>%
na.omit()
head(asset_returns_xts,5)
## VTI GLD TLT BTCUSD VNQ
## 2021-01-31 -0.003345042 -0.03276927 -3.700354e-02 0.16826782 0.0003531877
## 2021-02-28 0.030910615 -0.06461193 -5.903890e-02 0.30037739 0.0336777004
## 2021-03-31 0.035829568 -0.01149897 -5.387882e-02 0.24016039 0.0502370398
## 2021-04-30 0.049138073 0.03501369 2.464439e-02 -0.02003438 0.0756620593
## 2021-05-31 0.004549864 0.07397862 2.208426e-05 -0.48104278 0.0080418536
## TIP VXUS QUAL
## 2021-01-31 0.002660232 0.00249021 -0.02871940
## 2021-02-28 -0.017020613 0.02278610 0.03146915
## 2021-03-31 -0.002626233 0.01852452 0.04859642
## 2021-04-30 0.014195979 0.02737303 0.04691930
## 2021-05-31 0.010187452 0.03026357 0.01005657
# c) Portfelli kuised tootlused
w <- c(0.20,
0.10,
0.10,
0.15,
0.10,
0.10,
0.15,
0.10)
tibble(w, symbols) #kontroll rida, kuvab kaalud ja sümbolid
## # A tibble: 8 × 2
## w symbols
## <dbl> <chr>
## 1 0.2 VTI
## 2 0.1 GLD
## 3 0.1 TLT
## 4 0.15 BTC-USD
## 5 0.1 VNQ
## 6 0.1 TIP
## 7 0.15 VXUS
## 8 0.1 QUAL
tibble(w, symbols) %>%
summarise(total_weight = sum(w)) #kontroll rida, kas summa on 1
## # A tibble: 1 × 1
## total_weight
## <dbl>
## 1 1
portfolio_returns_xts_rebalanced_monthly <-
Return.portfolio(asset_returns_xts,
weights = w,
rebalance_on = "months") %>%
`colnames<-`("returns")
head(portfolio_returns_xts_rebalanced_monthly, 5)
## returns
## 2021-01-31 0.01539682
## 2021-02-28 0.04710419
## 2021-03-31 0.04905159
## 2021-04-30 0.03057195
## 2021-05-31 -0.05647825
# d - portfelli hindamine
# d.1) sd:
portfolio_sd_xts_builtin <-
StdDev(asset_returns_xts, weights = w)
portfolio_sd_xts_builtin_percent <-
round(portfolio_sd_xts_builtin * 100, 2)
portfolio_sd_xts_builtin_percent[1,1]
## [1] 4.63
# d.2) keskmine kuine tootlus
portfolio_mean_monthly <-
mean(portfolio_returns_xts_rebalanced_monthly)
portfolio_mean_monthly_percent <-
round(portfolio_mean_monthly * 100, 2)
portfolio_mean_monthly_percent
## [1] 0.79
# d.3) Sharpe'i suhe
portfolio_sharpe <-
SharpeRatio(portfolio_returns_xts_rebalanced_monthly,
Rf = 0.0025,
FUN = "StdDev")
round(portfolio_sharpe, 2)
## returns
## StdDev Sharpe (Rf=0.2%, p=95%): 0.12
# hinnangud
#saadud tulemused
#Portfoolio standardhälve on 4,63%. Standardhälve näitab riski, mis kaasneb portfelliga. Portfelli risk on hajutatud ja keskmised tootlused varadel jäävad portfoolio keskmise tootluse juurde.
#Portfelli keskmine kuine tootlus on 0,79%, ehk oodatav aastane tootlus on 9.9%. See on hea tulemus, mis üldjuhul ületab inflatsiooni ja ei ole suure riskiga.
#Keskmiselt on kuine parim tootlus olnud BITCOIN-il, umbes 2 protsendi juures, ja sellele on järgnenud kuld, mille tootlus on olnud kuiselt 1,4% juures. Need varad on olnud kõige tootlikumad viimastel aastatel meie portfooliost, aga meie portfoolio tulemus ei jää alla, samas risk on hajutatud.
#Sharpe ratio, mis jääb alla 1, näitab meile siiski, et risk on liialt suur tootluse kohta. Hetkel portfelli Sharpe suhe 0,11 on halb näitaja, sest kõrgem suhtarv näitab paremat tootlust riski suhtes. Soovitame portfellis osakaale ümber juhtida, et hajutada riski enam.
#e
results_tbl <- tibble(
Naitaja = c("Standardhälve (%)",
"Keskmine kuine tootlus (%)",
"Sharpe'i suhe"),
Vaartus = c(
portfolio_sd_xts_builtin_percent[1,1],
as.numeric(portfolio_mean_monthly_percent),
round(as.numeric(portfolio_sharpe), 2)
)
)
results_tbl
## # A tibble: 3 × 2
## Naitaja Vaartus
## <chr> <dbl>
## 1 Standardhälve (%) 4.63
## 2 Keskmine kuine tootlus (%) 0.79
## 3 Sharpe'i suhe 0.12
#e
portfolio_returns_df <-
portfolio_returns_xts_rebalanced_monthly %>%
data.frame(date = index(.), returns = coredata(.)) %>%
remove_rownames() %>%
as_tibble()
head(portfolio_returns_df, 5)
## # A tibble: 5 × 3
## returns date returns.1
## <dbl> <date> <dbl>
## 1 0.0154 2021-01-31 0.0154
## 2 0.0471 2021-02-28 0.0471
## 3 0.0491 2021-03-31 0.0491
## 4 0.0306 2021-04-30 0.0306
## 5 -0.0565 2021-05-31 -0.0565
# f
install.packages("ggrepel")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'ggrepel' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'ggrepel'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problem copying
## C:\Users\Karo\AppData\Local\R\win-library\4.5\00LOCK\ggrepel\libs\x64\ggrepel.dll
## to C:\Users\Karo\AppData\Local\R\win-library\4.5\ggrepel\libs\x64\ggrepel.dll:
## Permission denied
## Warning: restored 'ggrepel'
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
library(ggrepel)
## Warning: package 'ggrepel' was built under R version 4.5.3
asset_returns_dplyr_byhand <-
asset_returns_xts %>%
{data.frame(date = index(.), coredata(.))} %>%
remove_rownames() %>%
as_tibble()
asset_returns_long <-
asset_returns_dplyr_byhand %>%
gather(asset, returns, -date) %>%
group_by(asset)
portfolio_returns_dplyr_byhand <-
portfolio_returns_df
risk_return_plot_data <-
asset_returns_long %>%
group_by(asset) %>%
summarise(expected_return = mean(returns),
stand_dev = sd(returns)) %>%
add_row(asset = "Portfolio",
stand_dev = sd(portfolio_returns_dplyr_byhand$returns),
expected_return = mean(portfolio_returns_dplyr_byhand$returns))
risk_return_plot_data %>%
ggplot(aes(x = stand_dev,
y = expected_return,
label = asset,
color = asset)) +
geom_point(size = 2) +
geom_text_repel(show.legend = FALSE) +
ylab("expected return") +
xlab("standard deviation") +
ggtitle("Oodatavad tootlused ja risk") +
scale_y_continuous(labels = percent) +
scale_x_continuous(labels = percent) +
theme(plot.title = element_text(hjust = 0.5))

risk_return_plot_data
## # A tibble: 9 × 3
## asset expected_return stand_dev
## <chr> <dbl> <dbl>
## 1 BTCUSD 0.0186 0.174
## 2 GLD 0.0134 0.0410
## 3 QUAL 0.0101 0.0465
## 4 TIP 0.000760 0.0178
## 5 TLT -0.00714 0.0429
## 6 VNQ 0.00392 0.0545
## 7 VTI 0.0104 0.0443
## 8 VXUS 0.00653 0.0404
## 9 Portfolio 0.00794 0.0463
# g
market_symbol <- "^GSPC"
getSymbols(market_symbol,
src = "yahoo",
from = "2020-12-31",
to = "2025-12-31",
auto.assign = TRUE,
warnings = FALSE)
## [1] "GSPC"
market_prices <- Ad(GSPC)
market_prices_monthly <- to.monthly(market_prices,
indexAt = "lastof",
OHLC = FALSE)
market_returns_xts <-
Return.calculate(market_prices_monthly,
method = "log") %>%
na.omit() %>%
`colnames<-`("market_returns")
beta_data_xts <-
merge(portfolio_returns_xts_rebalanced_monthly,
market_returns_xts) %>%
na.omit()
portfolio_beta_xts <-
CAPM.beta(beta_data_xts$returns,
beta_data_xts$market_returns)
portfolio_beta_xts
## [1] 0.9120886
#Beeta on 0.912 portfelli jaoks, mis tähendab, et keskmine volatiilsus on madalam portfellil kui S&P500 indeksil, ehk selle süstemaatiline risk on madalam tururiskist. Madalama riskiga portfellil jääb sageli ka tootlus madalamaks.
# h
install.packages("PortfolioAnalytics")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'PortfolioAnalytics' successfully unpacked and MD5 sums checked
## Warning: cannot remove prior installation of package 'PortfolioAnalytics'
## Warning in file.copy(savedcopy, lib, recursive = TRUE): problem copying
## C:\Users\Karo\AppData\Local\R\win-library\4.5\00LOCK\PortfolioAnalytics\libs\x64\PortfolioAnalytics.dll
## to
## C:\Users\Karo\AppData\Local\R\win-library\4.5\PortfolioAnalytics\libs\x64\PortfolioAnalytics.dll:
## Permission denied
## Warning: restored 'PortfolioAnalytics'
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
install.packages("ROI")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'ROI' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
install.packages("ROI.plugin.quadprog")
## Installing package into 'C:/Users/Karo/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'ROI.plugin.quadprog' successfully unpacked and MD5 sums checked
##
## The downloaded binary packages are in
## C:\Users\Karo\AppData\Local\Temp\RtmpeSfUrC\downloaded_packages
library(PortfolioAnalytics)
## Warning: package 'PortfolioAnalytics' was built under R version 4.5.3
## Loading required package: foreach
## Warning: package 'foreach' was built under R version 4.5.3
##
## Attaching package: 'foreach'
##
## The following objects are masked from 'package:purrr':
##
## accumulate, when
##
## Registered S3 method overwritten by 'PortfolioAnalytics':
## method from
## print.constraint ROI
library(ROI)
## Warning: package 'ROI' was built under R version 4.5.3
## ROI: R Optimization Infrastructure
## Registered solver plugins: nlminb, symphony, glpk, quadprog.
## Default solver: auto.
##
## Attaching package: 'ROI'
##
## The following objects are masked from 'package:PortfolioAnalytics':
##
## is.constraint, objective
library(ROI.plugin.quadprog)
## Warning: package 'ROI.plugin.quadprog' was built under R version 4.5.3
fund_names <- colnames(asset_returns_xts)
init <- portfolio.spec(assets = fund_names)
init <- add.constraint(portfolio = init,
type = "full_investment")
init <- add.constraint(portfolio = init,
type = "long_only")
minvar <- add.objective(portfolio = init,
type = "risk",
name = "var")
opt_minvar <- optimize.portfolio(R = asset_returns_xts,
portfolio = minvar,
optimize_method = "ROI")
minvar_weights <- extractWeights(opt_minvar)
chart.Weights(opt_minvar)

minvar_weights
## VTI GLD TLT BTCUSD VNQ
## 3.054516e-18 1.705743e-02 4.562795e-17 0.000000e+00 -1.517624e-17
## TIP VXUS QUAL
## 9.829426e-01 3.568853e-17 5.509916e-17
sum(minvar_weights)
## [1] 1
minvar_weights_tbl <- tibble(
asset = names(minvar_weights),
weight = round(as.numeric(minvar_weights), 4)
)
minvar_weights_tbl
## # A tibble: 8 × 2
## asset weight
## <chr> <dbl>
## 1 VTI 0
## 2 GLD 0.0171
## 3 TLT 0
## 4 BTCUSD 0
## 5 VNQ 0
## 6 TIP 0.983
## 7 VXUS 0
## 8 QUAL 0
round(sum(minvar_weights), 4)
## [1] 1
#Minimaalse riski ja Parima ROI-ga portfoolio oleks meil olnud, kui oleksime pannud 98,3% varast USA riigivõlakirjadesse ja 1.7% varadest kulda.
#See tulemus on loogiline, sest USA võlakirjasid ja kulda peetakse madala volatiilsusega varadeks. Neid sageli kaasataksegi portfelli, et maandada muude varadega kaasnevat riski.