# ================================
# Homework 04 - FINAL VERSION
# ================================
# Libraries
library(xts)
## Warning: package 'xts' was built under R version 4.5.3
## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
library(PerformanceAnalytics)
## Warning: package 'PerformanceAnalytics' was built under R version 4.5.3
##
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
##
## legend
# ================================
# 1. Load Data (SAFE METHOD)
# ================================
data <- read.csv(file.choose(), stringsAsFactors = FALSE)
# Fix column name
colnames(data)[1] <- "Date"
# Convert Date
data$Date <- as.Date(data$Date)
# Convert all ETF columns to numeric (VERY IMPORTANT)
data[,-1] <- lapply(data[,-1], function(x) as.numeric(as.character(x)))
# Remove NA
data <- na.omit(data)
# Convert to xts
data_xts <- xts(data[,-1], order.by = data$Date)
# ================================
# 2. Compute Daily Returns (ROBUST)
# ================================
ret_daily <- na.omit(diff(log(data_xts)))
# In-sample period
ret_daily <- ret_daily["2015-12-14/2018-12-28"]
# ================================
# 3. Q1 - GMVP (Daily)
# ================================
cov_mat <- cov(ret_daily)
# Stability fix
cov_mat <- cov_mat + diag(1e-6, ncol(cov_mat))
one_vec <- rep(1, ncol(ret_daily))
inv_cov <- solve(cov_mat)
w_gmvp_daily <- inv_cov %*% one_vec / as.numeric(t(one_vec) %*% inv_cov %*% one_vec)
mean_ret_daily <- colMeans(ret_daily)
ret_gmvp_daily <- sum(w_gmvp_daily * mean_ret_daily)
sd_gmvp_daily <- sqrt(t(w_gmvp_daily) %*% cov_mat %*% w_gmvp_daily)
# ================================
# 4. Q2 - Monthly GMVP
# ================================
price_monthly <- to.monthly(data_xts, indexAt = "lastof", OHLC = FALSE)
ret_monthly <- na.omit(diff(log(price_monthly)))
cov_mat_m <- cov(ret_monthly)
cov_mat_m <- cov_mat_m + diag(1e-6, ncol(cov_mat_m))
mean_ret_m <- colMeans(ret_monthly)
inv_cov_m <- solve(cov_mat_m)
w_gmvp_m <- inv_cov_m %*% one_vec / as.numeric(t(one_vec) %*% inv_cov_m %*% one_vec)
ret_gmvp_m <- sum(w_gmvp_m * mean_ret_m)
sd_gmvp_m <- sqrt(t(w_gmvp_m) %*% cov_mat_m %*% w_gmvp_m)
# ================================
# 5. Q3 - Tangency Portfolio
# ================================
w_tan <- inv_cov_m %*% mean_ret_m / as.numeric(t(one_vec) %*% inv_cov_m %*% mean_ret_m)
ret_tan <- sum(w_tan * mean_ret_m)
sd_tan <- sqrt(t(w_tan) %*% cov_mat_m %*% w_tan)
# ================================
# 6. Output
# ================================
cat("\n===== Q1: GMVP (Daily) =====\n")
##
## ===== Q1: GMVP (Daily) =====
print(w_gmvp_daily)
## [,1]
## tw0050 -0.1966149
## tw0056 0.7023559
## tw006205 0.1091359
## tw00646 0.3851231
cat("Return:", ret_gmvp_daily, "\n")
## Return: 0.000227557
cat("Risk:", sd_gmvp_daily, "\n")
## Risk: 0.005981864
cat("\n===== Q2: GMVP (Monthly) =====\n")
##
## ===== Q2: GMVP (Monthly) =====
print(w_gmvp_m)
## [,1]
## tw0050 -0.026989941
## tw0056 0.519207969
## tw006205 -0.001733473
## tw00646 0.509515446
cat("Return:", ret_gmvp_m, "\n")
## Return: 0.005306363
cat("Risk:", sd_gmvp_m, "\n")
## Risk: 0.02507979
cat("\n===== Q3: Tangency Portfolio =====\n")
##
## ===== Q3: Tangency Portfolio =====
print(w_tan)
## [,1]
## tw0050 1.2746732
## tw0056 -0.0828287
## tw006205 -0.8957979
## tw00646 0.7039535
cat("Return:", ret_tan, "\n")
## Return: 0.01870232
cat("Risk:", sd_tan, "\n")
## Risk: 0.04708399