First, we load the required packages and format our ETF dataset.
# Import libraries
library(xts)
library(PerformanceAnalytics)
# Read the CSV file
etf_data <- read.csv("myetf4.csv")
# Convert the Index column to proper Date format
etf_data$Index <- as.Date(etf_data$Index, format="%Y/%m/%d")
# Create an xts time-series object
etf_xts <- xts(etf_data[, -1], order.by = etf_data$Index)
# Subset the data for the in-sample period
insample_data <- etf_xts["2015-12-14/2018-12-28"]
Here we compute the Global Minimum Variance Portfolio using daily returns.
# Get daily discrete returns and remove NAs
daily_returns <- na.omit(Return.calculate(insample_data, method="discrete"))
# Calculate the sample covariance matrix and mean vector
cov_matrix_d <- cov(daily_returns)
mean_vector_d <- colMeans(daily_returns)
# Inverse covariance matrix
inv_cov_d <- solve(cov_matrix_d)
ones_vec_d <- rep(1, ncol(daily_returns))
# Formula for GMVP weights
weights_gmvp_d <- (inv_cov_d %*% ones_vec_d) / as.numeric(t(ones_vec_d) %*% inv_cov_d %*% ones_vec_d)
# Calculate Portfolio Return and Risk (Standard Deviation)
port_ret_d <- t(weights_gmvp_d) %*% mean_vector_d
port_sd_d <- sqrt(t(weights_gmvp_d) %*% cov_matrix_d %*% weights_gmvp_d)
# Display the results
print("Optimal Weights for Daily GMVP:")
## [1] "Optimal Weights for Daily GMVP:"
round(weights_gmvp_d, 4)
## [,1]
## tw0050 -0.2194
## tw0056 0.7284
## tw006205 0.1076
## tw00646 0.3834
cat(sprintf("Expected Daily Return: %f\n", port_ret_d))
## Expected Daily Return: 0.000254
cat(sprintf("Daily Standard Deviation: %f\n", port_sd_d))
## Daily Standard Deviation: 0.005905
Now, we extract the monthly endpoints to calculate the GMVP using monthly returns.
# Extract prices at the end of each month
monthly_prices <- insample_data[endpoints(insample_data, on="months")]
# Calculate monthly returns
monthly_returns <- na.omit(Return.calculate(monthly_prices, method="discrete"))
# Covariance and mean for monthly data
cov_matrix_m <- cov(monthly_returns)
mean_vector_m <- colMeans(monthly_returns)
inv_cov_m <- solve(cov_matrix_m)
ones_vec_m <- rep(1, ncol(monthly_returns))
# Monthly GMVP weights
weights_gmvp_m <- (inv_cov_m %*% ones_vec_m) / as.numeric(t(ones_vec_m) %*% inv_cov_m %*% ones_vec_m)
# Monthly Return and Risk
port_ret_m <- t(weights_gmvp_m) %*% mean_vector_m
port_sd_m <- sqrt(t(weights_gmvp_m) %*% cov_matrix_m %*% weights_gmvp_m)
print("Optimal Weights for Monthly GMVP:")
## [1] "Optimal Weights for Monthly GMVP:"
round(weights_gmvp_m, 4)
## [,1]
## tw0050 0.0032
## tw0056 0.4740
## tw006205 0.0012
## tw00646 0.5216
cat(sprintf("Expected Monthly Return: %f\n", port_ret_m))
## Expected Monthly Return: 0.005734
cat(sprintf("Monthly Standard Deviation: %f\n", port_sd_m))
## Monthly Standard Deviation: 0.024904
Using the monthly data from Q2, we find the tangency portfolio weights. The risk-free rate is assumed to be 0.
risk_free_rate <- 0
# Formula for Tangency Portfolio weights
weights_tangency <- (inv_cov_m %*% (mean_vector_m - risk_free_rate)) /
as.numeric(t(ones_vec_m) %*% inv_cov_m %*% (mean_vector_m - risk_free_rate))
# Tangency Return and Risk
tan_ret_m <- t(weights_tangency) %*% mean_vector_m
tan_sd_m <- sqrt(t(weights_tangency) %*% cov_matrix_m %*% weights_tangency)
print("Optimal Weights for Tangency Portfolio:")
## [1] "Optimal Weights for Tangency Portfolio:"
round(weights_tangency, 4)
## [,1]
## tw0050 1.3051
## tw0056 -0.1577
## tw006205 -0.8475
## tw00646 0.7002
cat(sprintf("Expected Monthly Return (Tangency): %f\n", tan_ret_m))
## Expected Monthly Return (Tangency): 0.018090
cat(sprintf("Monthly Standard Deviation (Tangency): %f\n", tan_sd_m))
## Monthly Standard Deviation (Tangency): 0.044236