required_packages <- c(“quantmod”, “tidyquant”, “lubridate”, “timetk”, “purrr”, “xts”, “dplyr”, “ggplot2”, “zoo”)
install_missing <- required_packages[!(required_packages %in% installed.packages()[,“Package”])] if(length(install_missing)) install.packages(install_missing)
library(quantmod) library(tidyquant) library(lubridate) library(timetk) library(purrr) library(xts) library(dplyr) library(ggplot2) library(zoo)
tickers <- c(“SPY”, “QQQ”, “EEM”, “IWM”, “EFA”, “TLT”, “IYR”, “GLD”) start_date <- “2010-01-01” end_date <- Sys.Date()
etf_data <- map(tickers, ~getSymbols(.x, src = “yahoo”, from = start_date, to = end_date, auto.assign = FALSE)) etf_prices <- do.call(merge, lapply(etf_data, Ad)) # Extract adjusted closing prices
etf_weekly_returns <- etf_prices %>% periodReturn(period = “weekly”, type = “log”)
etf_monthly_returns <- etf_prices %>% periodReturn(period = “monthly”, type = “log”)
monthly_returns_tbl <- etf_monthly_returns %>% as_tibble(rownames = “date”) %>% mutate(date = as.Date(date))
ff_url <- “http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors.CSV” ff_data <- read.csv(ff_url, skip = 3)
names(ff_data)[1] <- “Date” ff_data <- ff_data %>% mutate(Date = as.Date(paste0(substr(Date, 1, 4), “-”, substr(Date, 5, 6), “-01”)), Mkt_RF = as.numeric(Mkt.RF)/100, SMB = as.numeric(SMB)/100, HML = as.numeric(HML)/100) %>% select(Date, Mkt_RF, SMB, HML) %>% na.omit()
ff_xts <- xts(ff_data[, -1], order.by = ff_data$Date)
merged_data <- left_join(monthly_returns_tbl, ff_data, by = c(“date” = “Date”))
merged_data <- na.omit(merged_data)
start_cov <- as.Date(“2010-02-01”) end_cov <- as.Date(“2015-01-01”)
capm_cov_matrix <- cov(subset(merged_data, date >= start_cov & date <= end_cov)[, -1]) ff_cov_matrix <- cov(subset(merged_data, date >= start_cov & date <= end_cov)[, -c(1, length(merged_data))])
gmv_weights_capm <- solve(capm_cov_matrix) %*% rep(1, ncol(capm_cov_matrix)) gmv_weights_capm <- gmv_weights_capm / sum(gmv_weights_capm)
gmv_weights_ff <- solve(ff_cov_matrix) %*% rep(1, ncol(ff_cov_matrix)) gmv_weights_ff <- gmv_weights_ff / sum(gmv_weights_ff)
compute_gmv_weights <- function(return_matrix) { cov_matrix <- cov(return_matrix) weights <- solve(cov_matrix) %*% rep(1, ncol(cov_matrix)) return(weights / sum(weights)) }
window_size <- 60 gmv_returns_capm <- rollapply(merged_data[, -1], width = window_size, FUN = compute_gmv_weights, by.column = FALSE, align = “right”) gmv_returns_ff <- rollapply(merged_data[, -c(1, length(merged_data))], width = window_size, FUN = compute_gmv_weights, by.column = FALSE, align = “right”)
cum_returns_capm <- cumsum(gmv_returns_capm) cum_returns_ff <- cumsum(gmv_returns_ff)
ggplot() + geom_line(aes(x = seq_along(cum_returns_capm), y = cum_returns_capm), color = “blue”) + geom_line(aes(x = seq_along(cum_returns_ff), y = cum_returns_ff), color = “red”) + labs(title = “Cumulative Returns of GMV Portfolios”, x = “Time”, y = “Cumulative Return”)