library(xts)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(PerformanceAnalytics)
## 
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
## 
##     legend
library(ggplot2)
data <- read.csv("myetf4.csv", stringsAsFactors = FALSE)

colnames(data)[1] <- "Date"
data$Date <- as.Date(data$Date)

data[,-1] <- lapply(data[,-1], function(x) as.numeric(as.character(x)))
data <- na.omit(data)

data_xts <- xts(data[,-1], order.by = data$Date)

ret_daily <- na.omit(diff(log(data_xts)))
ret_daily <- ret_daily["2015-12-14/2018-12-28"]

price_monthly <- to.monthly(data_xts, indexAt = "lastof", OHLC = FALSE)
ret_monthly <- na.omit(diff(log(price_monthly)))

cov_mat <- cov(ret_monthly) + diag(1e-6, ncol(ret_monthly))
mean_ret <- colMeans(ret_monthly)

one_vec <- rep(1, ncol(ret_monthly))
inv_cov <- solve(cov_mat)

w_gmvp <- inv_cov %*% one_vec / as.numeric(t(one_vec) %*% inv_cov %*% one_vec)

ret_gmvp <- sum(w_gmvp * mean_ret)
sd_gmvp <- sqrt(t(w_gmvp) %*% cov_mat %*% w_gmvp)

w_tan <- inv_cov %*% mean_ret / as.numeric(t(one_vec) %*% inv_cov %*% mean_ret)

ret_tan <- sum(w_tan * mean_ret)
sd_tan <- sqrt(t(w_tan) %*% cov_mat %*% w_tan)

portfolio_returns <- c()
portfolio_risk <- c()

set.seed(123)

for(i in 1:5000){
  w <- runif(ncol(ret_monthly))
  w <- w / sum(w)
  
  port_return <- sum(w * mean_ret)
  port_risk <- sqrt(t(w) %*% cov_mat %*% w)
  
  portfolio_returns <- c(portfolio_returns, port_return)
  portfolio_risk <- c(portfolio_risk, port_risk)
}

df <- data.frame(Risk = portfolio_risk, Return = portfolio_returns)

ggplot(df, aes(x = Risk, y = Return)) +
  geom_point(alpha = 0.3) +
  
  # GMVP
  geom_point(aes(x = sd_gmvp, y = ret_gmvp), size = 4) +
  
  # Tangency
  geom_point(aes(x = sd_tan, y = ret_tan), size = 4) +
  
  ggtitle("Efficient Frontier with GMVP and Tangency Portfolio") +
  xlab("Risk (Standard Deviation)") +
  ylab("Expected Return") +
  theme_minimal()
## Warning in geom_point(aes(x = sd_gmvp, y = ret_gmvp), size = 4): All aesthetics have length 1, but the data has 5000 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
##   a single row.
## Warning in geom_point(aes(x = sd_tan, y = ret_tan), size = 4): All aesthetics have length 1, but the data has 5000 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
##   a single row.

results <- data.frame(
  Portfolio = c("GMVP", "Tangency"),
  Return = c(ret_gmvp, ret_tan),
  Risk = c(sd_gmvp, sd_tan)
)

print(results)
##   Portfolio      Return       Risk
## 1      GMVP 0.005306363 0.02507979
## 2  Tangency 0.018702323 0.04708399
ret_gmvp_series <- xts(ret_monthly %*% w_gmvp, order.by = index(ret_monthly))
ret_tan_series  <- xts(ret_monthly %*% w_tan, order.by = index(ret_monthly))

combined <- merge(ret_gmvp_series, ret_tan_series)
colnames(combined) <- c("GMVP", "Tangency")

charts.PerformanceSummary(combined, main = "Cumulative Returns Comparison")

This analysis shows how the GMVP and Tangency Portfolio can be constructed using four Taiwan ETFs. Using daily data, the GMVP minimizes risk but results in lower returns. When using monthly data, the results change slightly due to smoother return patterns affecting the calculations.

The Tangency Portfolio, assuming a zero risk-free rate, provides a better balance between risk and return by maximizing return per unit of risk. Overall, the GMVP suits risk-averse investors, while the Tangency Portfolio is more suitable for those seeking higher returns.