R Markdown

This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.

When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:

# Midterm Exam: 
# Upload your url on RPubs to Tronclass. 

#
# Download ETF daily data from yahoo with ticker names of SPY, QQQ, EEM, IWM, EFA, 
# TLT, IYR and GLD from 2018 to 2022.

# 1. Load libraries
library(pacman)
p_load(tidyquant, lubridate, timetk, tidyverse, fPortfolio)

symbols <- c("SPY", "QQQ", "EEM", "IWM", "EFA", "TLT", "IYR", "GLD")

portfolioPrices <- NULL

# symbol = "SPY"
for (symbol in symbols){
  portfolioPrices <- cbind(portfolioPrices,
                           getSymbols.yahoo(symbol, from  = '2018-01-01', to = '2022-12-31', auto.assign = FALSE)[, 6])
}
portfolioPrices
##            SPY.Adjusted QQQ.Adjusted EEM.Adjusted IWM.Adjusted EFA.Adjusted
## 2018-01-02    245.82840    152.88676     43.05478    143.94115     61.24227
## 2018-01-03    247.38338    154.37236     43.46730    144.09074     61.53624
## 2018-01-04    248.42607    154.64244     43.68253    144.47427     62.21066
## 2018-01-05    250.08153    156.19551     44.05919    144.77357     62.55651
## 2018-01-08    250.53882    156.80321     44.05919    144.99806     62.53921
## 2018-01-09    251.10594    156.81288     43.98744    144.80164     62.60839
## 2018-01-10    250.72179    156.44635     43.70943    144.82033     62.48735
## 2018-01-11    252.55106    157.51707     43.97848    147.30823     62.91966
## 2018-01-12    254.19746    158.67468     44.39996    147.92548     63.55085
## 2018-01-16    253.32846    158.22127     44.22957    146.03619     63.49034
##        ...                                                                 
## 2022-12-16    381.81281    273.17209     37.83000    173.72896     65.42000
## 2022-12-19    378.57516    269.33304     37.86000    171.37764     65.26000
## 2022-12-20    379.09320    269.12338     37.85000    172.28429     65.52000
## 2022-12-21    384.76157    273.02734     38.19000    175.25333     66.20000
## 2022-12-22    379.27249    266.34769     37.85000    172.96181     65.66000
## 2022-12-23    381.45419    266.94672     37.80000    173.74889     65.89000
## 2022-12-27    379.94992    263.17258     38.36000    172.58319     65.99000
## 2022-12-28    375.22794    259.69797     37.80000    169.90308     65.29000
## 2022-12-29    381.98218    266.02817     38.43000    174.20720     66.32000
## 2022-12-30    380.97598    265.86841     37.90000    173.71899     65.64000
##            TLT.Adjusted IYR.Adjusted GLD.Adjusted
## 2018-01-02    112.31089     69.33669    125.15000
## 2018-01-03    112.84785     69.22485    124.82000
## 2018-01-04    112.82997     68.14094    125.46000
## 2018-01-05    112.50780     68.20976    125.33000
## 2018-01-08    112.43616     68.59688    125.31000
## 2018-01-09    110.93262     67.80544    124.73000
## 2018-01-10    110.79840     66.97960    125.03000
## 2018-01-11    111.25482     66.74731    125.44000
## 2018-01-12    111.44279     66.20535    126.96000
## 2018-01-16    111.90811     66.38599    127.17000
##        ...                                       
## 2022-12-16    106.30303     84.04142    166.78999
## 2022-12-19    104.51660     83.04708    166.32001
## 2022-12-20    102.66070     82.81839    169.08000
## 2022-12-21    102.91873     83.67352    168.80000
## 2022-12-22    102.89888     83.33544    166.75999
## 2022-12-23    101.39034     84.05137    167.25999
## 2022-12-27     99.38555     83.99171    168.67000
## 2022-12-28     98.80000     82.56981    167.91000
## 2022-12-29     99.92149     84.40933    168.85001
## 2022-12-30     98.80992     83.71329    169.64000
#
# 2. Calculate weekly and monthly returns using log returns
prices_weekly <- to.weekly(portfolioPrices, indexAt = "last", OHLC = FALSE)
prices_monthly <- to.monthly(portfolioPrices, indexAt = "last", OHLC = FALSE)
# 
asset_returns_day_xts <- na.omit(Return.calculate(portfolioPrices))
asset_returns_wk_xts <- na.omit(Return.calculate(prices_weekly))
asset_returns_mon_xts <- na.omit(Return.calculate(prices_monthly))
head(asset_returns_day_xts)
##            SPY.Adjusted  QQQ.Adjusted EEM.Adjusted  IWM.Adjusted  EFA.Adjusted
## 2018-01-03  0.006325459  9.716967e-03  0.009581313  0.0010392940  0.0048001491
## 2018-01-04  0.004214891  1.749540e-03  0.004951428  0.0026617231  0.0109597110
## 2018-01-05  0.006663779  1.004297e-02  0.008622568  0.0020716570  0.0055594285
## 2018-01-08  0.001828566  3.890615e-03  0.000000000  0.0015506097 -0.0002766663
## 2018-01-09  0.002263615  6.169563e-05 -0.001628419 -0.0013546829  0.0011062396
## 2018-01-10 -0.001529853 -2.337381e-03 -0.006320070  0.0001290871 -0.0019332927
##             TLT.Adjusted IYR.Adjusted  GLD.Adjusted
## 2018-01-03  0.0047809859 -0.001612989 -0.0026368504
## 2018-01-04 -0.0001584051 -0.015657898  0.0051273786
## 2018-01-05 -0.0028553268  0.001010036 -0.0010361649
## 2018-01-08 -0.0006367560  0.005675368 -0.0001596128
## 2018-01-09 -0.0133723882 -0.011537482 -0.0046284751
## 2018-01-10 -0.0012099591 -0.012179609  0.0024051585
head(asset_returns_wk_xts)
##            SPY.Adjusted QQQ.Adjusted EEM.Adjusted IWM.Adjusted EFA.Adjusted
## 2018-01-12  0.016458378   0.01587223  0.007734559  0.021771247  0.015894990
## 2018-01-19  0.008959256   0.01124686  0.018784049  0.002782212  0.008571459
## 2018-01-26  0.022003246   0.02759394  0.032513747  0.006305151  0.015108554
## 2018-02-02 -0.038837127  -0.03697398 -0.058179632 -0.036152760 -0.035880359
## 2018-02-09 -0.050644403  -0.05169831 -0.053618740 -0.045895027 -0.054583187
## 2018-02-16  0.044397663   0.05675851  0.067212492  0.044763771  0.041259701
##            TLT.Adjusted IYR.Adjusted GLD.Adjusted
## 2018-01-12 -0.009466099 -0.029385966  0.013005643
## 2018-01-19 -0.011725518  0.006497022 -0.004253315
## 2018-01-26  0.004307014  0.016911862  0.013051805
## 2018-02-02 -0.030431241 -0.029325958 -0.013117887
## 2018-02-09 -0.013715058 -0.041590412 -0.012817492
## 2018-02-16  0.006529235  0.024290286  0.025567064
head(asset_returns_mon_xts)
##            SPY.Adjusted QQQ.Adjusted EEM.Adjusted IWM.Adjusted EFA.Adjusted
## 2018-02-28 -0.036360318 -0.012927819 -0.058984954 -0.038436734 -0.048347815
## 2018-03-29 -0.027410686 -0.040788545  0.005414344  0.012175160 -0.008396243
## 2018-04-30  0.005168179  0.005058636 -0.028168837  0.009813749  0.015212714
## 2018-05-31  0.024309116  0.056729267 -0.026214952  0.061635806 -0.018942620
## 2018-06-29  0.005750861  0.011450250 -0.045456776  0.006143667 -0.015841149
## 2018-07-31  0.037046364  0.027964128  0.035310138  0.016490202  0.028520208
##            TLT.Adjusted IYR.Adjusted GLD.Adjusted
## 2018-02-28 -0.030414501 -0.066573366 -0.020759902
## 2018-03-29  0.028596762  0.037719186  0.006320007
## 2018-04-30 -0.020881501  0.002252501 -0.009539745
## 2018-05-31  0.020043986  0.033712507 -0.011959209
## 2018-06-29  0.006458085  0.040594721 -0.036149448
## 2018-07-31 -0.014368738  0.008314499 -0.022418910
# Q1: Try to find the GMVP for these eight assets using the derived asset_returns data. ----
#   Note that you have to compute optimal weights and GMVP returns using weekly and monthly asset returns. 

# Q2: Given the portfolio return is specified as 0.045 annual rate. ----  
#     Try to find the optimal weights for the minimum variance portfolio.
#     You should use weekly and monthly asset returns to derive the solutions. 

# Q3. Find the tangency portfolio based on Q2. Risk-free rate is assumed to be zero.
#     You should compute the tangency portfolio weights and its returns based on weekly
#     monthly returns.

# Q4. The attached file "berndt.xslx" contains monthly returns of 15 stocks, market index returns (MARKET), ---- 
#     and risk-free monthly rate (RKFREE) for 120 months.
#     Compute GMVP (global minimum variance portfolio) weights and its return by using the covariance derived 
#     from single index model.

# Load necessary libraries
library(quadprog)

# Define expected returns and covariance matrix
expected_returns <- c(0.05, 0.06, 0.07, 0.08) # Example expected returns
cov_matrix <- matrix(c(0.02, 0.01, 0.005, 0.001,
                       0.01, 0.03, 0.004, 0.002,
                       0.005, 0.004, 0.04, 0.003,
                       0.001, 0.002, 0.003, 0.025), nrow = 4) # Example covariance matrix

# Define constraints and other parameters
Amat <- rbind(rep(1, length(expected_returns)), diag(length(expected_returns))) # Equality constraint: weights sum to 1
bvec <- c(1, rep(0, length(expected_returns))) # Right-hand side of the equality constraint
meq <- 1 # Number of equality constraints
Dmat <- 2 * cov_matrix # Quadratic term in the objective function (2 * covariance matrix)
dvec <- rep(0, length(expected_returns)) # Linear term in the objective function

# Solve the quadratic programming problem to get GMVP weights
result <- solve.QP(Dmat, dvec, t(Amat), bvec, meq = meq) # Note the transpose of Amat

# Extract the optimal weights
optimal_weights <- result$solution

# Calculate GMVP expected return and portfolio standard deviation (risk)
expected_return_gmvp <- optimal_weights %*% expected_returns
portfolio_std_gmvp <- sqrt(t(optimal_weights) %*% cov_matrix %*% optimal_weights)

# Print the results
cat("Optimal Weights (GMVP): ", optimal_weights, "\n")
## Optimal Weights (GMVP):  0.3431931 0.1624348 0.1555685 0.3388035
cat("Expected Return (GMVP): ", expected_return_gmvp, "\n")
## Expected Return (GMVP):  0.06489982
cat("Portfolio Standard Deviation (GMVP): ", portfolio_std_gmvp, "\n")
## Portfolio Standard Deviation (GMVP):  0.09800437
# Load necessary libraries
library(quadprog)

# Define expected returns and covariance matrix
expected_returns <- c(0.05, 0.06, 0.07, 0.08) # Example expected returns
cov_matrix <- matrix(c(0.02, 0.01, 0.005, 0.001,
                       0.01, 0.03, 0.004, 0.002,
                       0.005, 0.004, 0.04, 0.003,
                       0.001, 0.002, 0.003, 0.025), nrow = 4) # Example covariance matrix

# Define target portfolio return
target_return <- 0.045 # Example target return

# Define constraints and other parameters
Amat <- rbind(rep(1, length(expected_returns)), diag(length(expected_returns))) # Equality constraint: weights sum to 1
bvec <- c(1, rep(0, length(expected_returns))) # Right-hand side of the equality constraint
meq <- 1 # Number of equality constraints
Dmat <- 2 * cov_matrix # Quadratic term in the objective function (2 * covariance matrix)
dvec <- rep(0, length(expected_returns)) # Linear term in the objective function

# Define additional constraints for target portfolio return
Aeq <- expected_returns
beq <- target_return

# Combine equality constraints
Amat <- rbind(Amat, Aeq)
bvec <- c(bvec, beq)

# Solve the quadratic programming problem to get minimum variance portfolio weights
result <- solve.QP(Dmat, dvec, t(Amat), bvec, meq = meq) # Note the transpose of Amat

# Extract the optimal weights
optimal_weights <- result$solution

# Print the results
cat("Optimal Weights (Minimum Variance Portfolio): ", optimal_weights, "\n")
## Optimal Weights (Minimum Variance Portfolio):  0.3431931 0.1624348 0.1555685 0.3388035
# Load necessary libraries
library(quadprog)
library(readxl)

# Load data for Q1, Q2, and Q3
# Replace with your actual data
asset_returns_weekly <- data.frame(asset1 = c(0.01, 0.02, 0.03, 0.04, 0.02, 0.01, -0.01),
                                   asset2 = c(0.02, 0.03, 0.01, -0.01, -0.02, 0.03, 0.02),
                                   asset3 = c(0.03, 0.01, 0.02, -0.03, -0.01, -0.02, 0.01),
                                   asset4 = c(0.01, -0.02, -0.01, 0.03, 0.02, 0.01, 0.02))
asset_returns_monthly <- data.frame(asset1 = c(0.05, -0.02, 0.03, -0.01, 0.02, 0.01),
                                    asset2 = c(0.03, 0.04, -0.01, 0.02, 0.01, -0.03),
                                    asset3 = c(-0.01, 0.02, 0.03, 0.01, -0.02, -0.01),
                                    asset4 = c(0.02, -0.03, -0.02, 0.01, 0.03, 0.02))
portfolio_return_target <- 0.045

# Q1: GMVP for weekly returns
expected_returns_weekly <- colMeans(asset_returns_weekly)
cov_matrix_weekly <- cov(asset_returns_weekly)
Dmat_weekly <- 2 * cov_matrix_weekly
dvec_weekly <- rep(0, length(expected_returns_weekly))
Amat_weekly <- rbind(rep(1, length(expected_returns_weekly)), diag(length(expected_returns_weekly)))
bvec_weekly <- c(1, rep(0, length(expected_returns_weekly)))
meq_weekly <- 1
result_weekly <- solve.QP(Dmat_weekly, dvec_weekly, t(Amat_weekly), bvec_weekly, meq = meq_weekly)
optimal_weights_weekly <- result_weekly$solution
GMVP_return_weekly <- t(expected_returns_weekly) %*% optimal_weights_weekly

# Q2: Optimal weights for minimum variance portfolio with target return
Aeq_monthly <- colMeans(asset_returns_monthly)
beq_monthly <- portfolio_return_target
Amat_monthly <- rbind(Aeq_monthly, diag(length(expected_returns_weekly)))
bvec_monthly <- c(beq_monthly, rep(0, length(expected_returns_weekly)))
meq_monthly <- 1
result_monthly <- solve.QP(Dmat_weekly, dvec_weekly, t(Amat_monthly), bvec_monthly, meq = meq_monthly)
optimal_weights_monthly <- result_monthly$solution

# Q3: Tangency portfolio weights and returns
tangency_weights_monthly <- optimal_weights_monthly
tangency_return_monthly <- t(expected_returns_weekly) %*% tangency_weights_monthly

cat("\nQ3: Tangency portfolio weights and return (monthly):\n")
## 
## Q3: Tangency portfolio weights and return (monthly):
print(tangency_weights_monthly)
## [1] 1.6403910 1.3436481 0.6496374 1.5052361
cat("Tangency portfolio return (monthly):", tangency_return_monthly, "\n")
## Tangency portfolio return (monthly): 0.05730704
cat("\nQ4: GMVP weights for single index model:\n")
## 
## Q4: GMVP weights for single index model:

Including Plots

You can also embed plots, for example:

Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot.