library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ 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(quantmod)
## Loading required package: xts
## Loading required package: zoo
##
## Attaching package: 'zoo'
##
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
##
##
## ######################### Warning from 'xts' package ##########################
## # #
## # The dplyr lag() function breaks how base R's lag() function is supposed to #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or #
## # source() into this session won't work correctly. #
## # #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop #
## # dplyr from breaking base R's lag() function. #
## # #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #
## # #
## ###############################################################################
##
## Attaching package: 'xts'
##
## The following objects are masked from 'package:dplyr':
##
## first, last
##
## Loading required package: TTR
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(PerformanceAnalytics)
##
## Attaching package: 'PerformanceAnalytics'
##
## The following object is masked from 'package:graphics':
##
## legend
library(xts)
library(corpcor)
df <- read.csv("myetf4.csv")
head(df)
## Index tw0050 tw0056 tw006205 tw00646
## 1 2015/12/14 53.29 18.25 31.06 19.61
## 2 2015/12/15 53.33 18.38 31.59 19.63
## 3 2015/12/16 54.14 18.56 31.60 19.89
## 4 2015/12/17 54.77 18.81 32.23 20.05
## 5 2015/12/18 54.50 18.95 32.18 19.85
## 6 2015/12/21 54.41 19.02 33.00 19.64
df$Index <- as.Date(df$Index)
df <- df %>% column_to_rownames("Index")
df_xts <- as.xts(df)
returns <- na.omit(Return.calculate(df_xts, method = "log"))
cov_matrix <- cov(returns)
print(cov_matrix)
## tw0050 tw0056 tw006205 tw00646
## tw0050 7.893835e-05 4.604249e-05 4.513506e-05 3.696405e-05
## tw0056 4.604249e-05 4.562541e-05 2.695112e-05 2.374923e-05
## tw006205 4.513506e-05 2.695112e-05 1.310338e-04 2.938807e-05
## tw00646 3.696405e-05 2.374923e-05 2.938807e-05 5.914357e-05
ones <- rep(1, ncol(cov_matrix))
inv_cov_matrix <- pseudoinverse(cov_matrix)
gmvp_weights <- inv_cov_matrix %*% ones / sum(ones %*% inv_cov_matrix %*% ones)
gmvp_return <- sum(colMeans(returns) * gmvp_weights)
gmvp_std <- sqrt(t(gmvp_weights) %*% cov_matrix %*% gmvp_weights)
gmvp_weights
## [,1]
## [1,] -0.2241314
## [2,] 0.7298726
## [3,] 0.1080760
## [4,] 0.3861827
gmvp_return
## [1] 0.0002263853
gmvp_std
## [,1]
## [1,] 0.005921611
monthly_returns <- na.omit(to.monthly(df_xts, indexAt = "lastof", OHLC = FALSE) %>% Return.calculate(method = "log"))
monthly_cov_matrix <- cov(monthly_returns)
inv_monthly_cov_matrix <- pseudoinverse(monthly_cov_matrix)
gmvp_weights_monthly <- inv_monthly_cov_matrix %*% ones / sum(ones %*% inv_monthly_cov_matrix %*% ones)
gmvp_return_monthly <- sum(colMeans(monthly_returns) * gmvp_weights_monthly)
gmvp_std_monthly <- sqrt(t(gmvp_weights_monthly) %*% monthly_cov_matrix %*% gmvp_weights_monthly)
gmvp_weights_monthly
## [,1]
## [1,] -0.028540599
## [2,] 0.520686730
## [3,] -0.001782652
## [4,] 0.509636521
gmvp_return_monthly
## [1] 0.005304254
gmvp_std_monthly
## [,1]
## [1,] 0.02506921
excess_returns <- colMeans(monthly_returns)
tangency_weights <- inv_monthly_cov_matrix %*% excess_returns / sum(ones %*% inv_monthly_cov_matrix %*% excess_returns)
tangency_weights <- tangency_weights / sum(tangency_weights)
tangency_return <- sum(colMeans(monthly_returns) * tangency_weights)
tangency_std <- sqrt(t(tangency_weights) %*% monthly_cov_matrix %*% tangency_weights)
tangency_weights
## [,1]
## [1,] 1.2789695
## [2,] -0.0873706
## [3,] -0.8967581
## [4,] 0.7051592
tangency_return
## [1] 0.01871875
tangency_std
## [,1]
## [1,] 0.04709414
cat("Global Minimum Variance Portfolio (GMVP):")
## Global Minimum Variance Portfolio (GMVP):
print(gmvp_weights)
## [,1]
## [1,] -0.2241314
## [2,] 0.7298726
## [3,] 0.1080760
## [4,] 0.3861827
cat("GMVP Return:", gmvp_return, "\n")
## GMVP Return: 0.0002263853
cat("GMVP Standard Deviation:", gmvp_std, "\n\n")
## GMVP Standard Deviation: 0.005921611
cat("Tangency Portfolio:")
## Tangency Portfolio:
print(tangency_weights)
## [,1]
## [1,] 1.2789695
## [2,] -0.0873706
## [3,] -0.8967581
## [4,] 0.7051592
cat("Tangency Portfolio Return:", tangency_return, "\n")
## Tangency Portfolio Return: 0.01871875
cat("Tangency Portfolio Standard Deviation:", tangency_std, "\n")
## Tangency Portfolio Standard Deviation: 0.04709414