Get data from Yahoo
symbols <- c("SPY","QQQ", "EEM", "IWM", "EFA", "TLT", "IYR", "GLD")
portfolioPrices <- NULL
for (symbol in symbols) {
portfolioPrices <- cbind(portfolioPrices,
getSymbols.yahoo(symbol,
from = '2010-01-01',
to = Sys.Date(),
auto.assign = FALSE)[,6])
}
colnames(portfolioPrices) <- symbols
head(portfolioPrices)
## SPY QQQ EEM IWM EFA TLT IYR
## 2010-01-04 86.86005 40.73329 31.82711 52.51540 37.52378 61.13184 28.10298
## 2010-01-05 87.09000 40.73329 32.05812 52.33482 37.55685 61.52667 28.17046
## 2010-01-06 87.15130 40.48758 32.12519 52.28558 37.71560 60.70301 28.15820
## 2010-01-07 87.51922 40.51390 31.93890 52.67137 37.57009 60.80507 28.40971
## 2010-01-08 87.81046 40.84736 32.19226 52.95863 37.86775 60.77786 28.21954
## 2010-01-11 87.93309 40.68064 32.12519 52.74522 38.17862 60.44437 28.35450
## GLD
## 2010-01-04 109.80
## 2010-01-05 109.70
## 2010-01-06 111.51
## 2010-01-07 110.82
## 2010-01-08 111.37
## 2010-01-11 112.85
2. Calculate weekly and monthly returns using discrete returns
#Change data from daily to weekly
weekly_prices <- to.weekly(portfolioPrices, indexAt = 'last', OHLC = FALSE)
#Calculate weekly returns
weekly_returns <- na.omit(Return.calculate(weekly_prices), method = "discrete")
head(weekly_returns)
## SPY QQQ EEM IWM EFA
## 2010-01-15 -0.008117387 -0.015037882 -0.02893515 -0.01301893 -0.003493974
## 2010-01-22 -0.038982784 -0.036858813 -0.05578075 -0.03062199 -0.055740630
## 2010-01-29 -0.016665246 -0.031024042 -0.03357769 -0.02624317 -0.025802703
## 2010-02-05 -0.006797334 0.004440629 -0.02821288 -0.01397445 -0.019054781
## 2010-02-12 0.012937816 0.018147539 0.03333322 0.02952613 0.005244716
## 2010-02-19 0.028693427 0.024451565 0.02445362 0.03343139 0.022995087
## TLT IYR GLD
## 2010-01-15 2.004757e-02 -0.006304694 -0.004579349
## 2010-01-22 1.010075e-02 -0.041784835 -0.033285246
## 2010-01-29 3.369615e-03 -0.008447871 -0.011290465
## 2010-02-05 -5.451863e-05 0.003223667 -0.012080019
## 2010-02-12 -1.945990e-02 -0.007573861 0.022544905
## 2010-02-19 -8.205810e-03 0.050184807 0.022701796
#Change data from daily to monthly
monthly_prices <- to.monthly(portfolioPrices, indexAt = 'last', OHLC = FALSE)
#Calculate monthly returns
monthly_returns <- na.omit(Return.calculate(monthly_prices), method = "discrete")
head(monthly_returns)
## SPY QQQ EEM IWM EFA
## 2010-02-26 0.03119473 0.04603862 0.017764219 0.04475119 0.002667557
## 2010-03-31 0.06087938 0.07710944 0.081108647 0.08230674 0.063854445
## 2010-04-30 0.01547034 0.02242521 -0.001661697 0.05678439 -0.028045889
## 2010-05-28 -0.07945450 -0.07392379 -0.093935803 -0.07536653 -0.111928183
## 2010-06-30 -0.05174109 -0.05975656 -0.013986722 -0.07743358 -0.020619233
## 2010-07-30 0.06830083 0.07258273 0.109324714 0.06730927 0.116103873
## TLT IYR GLD
## 2010-02-26 -0.003423867 0.05457097 0.032748219
## 2010-03-31 -0.020573940 0.09748445 -0.004386396
## 2010-04-30 0.033218293 0.06388157 0.058834363
## 2010-05-28 0.051083483 -0.05683563 0.030513147
## 2010-06-30 0.057979109 -0.04670116 0.023553189
## 2010-07-30 -0.009464356 0.09404835 -0.050871157
3. Download Fama French 3 factors data and change to digit
numbers
#Import data
library(readr)
F_F_Research_Data_Factors <- read_csv("C:/Users/Admin/OneDrive - 亞洲大學[Asia University]/3rd Year/2nd Sem/1. Investment Portfolio Analysis/F-F_Research_Data_Factors.CSV")
FF3 <- F_F_Research_Data_Factors %>% select(-RF)
FF3 <- FF3 %>%
mutate_at(vars(-1), ~ ./100)
head(FF3)
## # A tibble: 6 × 4
## Time `Mkt-RF` SMB HML
## <dbl> <dbl> <dbl> <dbl>
## 1 192607 0.0296 -0.0256 -0.0243
## 2 192608 0.0264 -0.0117 0.0382
## 3 192609 0.0036 -0.014 0.0013
## 4 192610 -0.0324 -0.0009 0.007
## 5 192611 0.0253 -0.001 -0.0051
## 6 192612 0.0262 -0.0003 -0.0005
4. Merge monthly return data in question 2 and 3
FF3_subset <- FF3 %>%
filter(Time >= 201002 & Time <= 202402)
monthly_returns_subset <- monthly_returns["2010-02-26/2024-02-29"]
monthly_returns_subset_df <- as_tibble(index(monthly_returns_subset)) %>%
rename(time = value) %>%
bind_cols(as_tibble(coredata(monthly_returns_subset)))
merged_monthlyreturns <- bind_cols(monthly_returns_subset_df, FF3_subset[, c("Mkt-RF", "SMB", "HML")])
merged_monthlyreturns_xts <- xts(merged_monthlyreturns[, -1], order.by = merged_monthlyreturns$time)
head(merged_monthlyreturns_xts)
## SPY QQQ EEM IWM EFA
## 2010-02-26 0.03119473 0.04603862 0.017764219 0.04475119 0.002667557
## 2010-03-31 0.06087938 0.07710944 0.081108647 0.08230674 0.063854445
## 2010-04-30 0.01547034 0.02242521 -0.001661697 0.05678439 -0.028045889
## 2010-05-28 -0.07945450 -0.07392379 -0.093935803 -0.07536653 -0.111928183
## 2010-06-30 -0.05174109 -0.05975656 -0.013986722 -0.07743358 -0.020619233
## 2010-07-30 0.06830083 0.07258273 0.109324714 0.06730927 0.116103873
## TLT IYR GLD Mkt-RF SMB HML
## 2010-02-26 -0.003423867 0.05457097 0.032748219 0.0340 0.0119 0.0323
## 2010-03-31 -0.020573940 0.09748445 -0.004386396 0.0631 0.0148 0.0221
## 2010-04-30 0.033218293 0.06388157 0.058834363 0.0200 0.0487 0.0289
## 2010-05-28 0.051083483 -0.05683563 0.030513147 -0.0789 0.0009 -0.0244
## 2010-06-30 0.057979109 -0.04670116 0.023553189 -0.0557 -0.0182 -0.0470
## 2010-07-30 -0.009464356 0.09404835 -0.050871157 0.0693 0.0020 -0.0031
5. Based on CAPM model, compute MVP monthly returns based on
estimated covariance matrix for the 8-asset portfolio by using past
60-month returns from 2019/03 - 2024/02
monthly_returns_60 <- merged_monthlyreturns_xts["2019-03-29/2024-02-29"]
portfolio_8 <- monthly_returns_60[, 1:8]
rf <- monthly_returns_60[, 9]
#Find covariance matrix using CAMP
cov_ma_sim <- function(returns, rf){
n <- nrow(returns)
X <- as.matrix(cbind(rep(1, n), rf))
Y <- as.matrix(returns)
b_hat <- solve(t(X) %*% X) %*% t(X) %*% Y
E_hat = Y - X %*% b_hat
b_hat <- as.matrix(b_hat[-1, ])
diagD_hat <- diag(t(E_hat) %*% E_hat) / (n - 2)
diag(diagD_hat)
cov_sfm <- as.numeric(var(rf)) * b_hat %*% t(b_hat) + diag(diagD_hat)
return(cov_sfm)
}
cov_ma <- cov_ma_sim(portfolio_8, rf)
head(cov_ma)
## SPY QQQ EEM IWM EFA
## SPY 0.0027966270 0.0030811089 0.0021462683 0.0033220117 0.0024368327
## QQQ 0.0030811089 0.0039946832 0.0023958712 0.0037083491 0.0027202271
## EEM 0.0021462683 0.0023958712 0.0030463237 0.0025831972 0.0018948818
## IWM 0.0033220117 0.0037083491 0.0025831972 0.0047665046 0.0029329136
## EFA 0.0024368327 0.0027202271 0.0018948818 0.0029329136 0.0027205586
## TLT 0.0004742554 0.0005294095 0.0003687811 0.0005708025 0.0004187072
## TLT IYR GLD
## SPY 0.0004742554 0.0026231108 4.941832e-04
## QQQ 0.0005294095 0.0029281687 5.516549e-04
## EEM 0.0003687811 0.0020397318 3.842770e-04
## IWM 0.0005708025 0.0031571136 5.947871e-04
## EFA 0.0004187072 0.0023158731 4.363009e-04
## TLT 0.0022599781 0.0004507143 8.491271e-05
#Find MPV weights
MVP_sim <- function(cov_ma){
x <- ncol(cov_ma)
one_ma <- matrix(rep(1,x), ncol = 1)
numerator <- inv(cov_ma) %*% one_ma
denominator <- t(one_ma) %*% inv(cov_ma) %*% one_ma
weights <- numerator/as.vector(denominator)
colnames(weights) <- "Weight"
return(weights)
}
capm_model<- MVP_sim(cov_ma)
capm_model
## Weight
## SPY 0.26923978
## QQQ -0.15320021
## EEM 0.13888788
## IWM -0.20343762
## EFA 0.18519433
## TLT 0.31471311
## IYR 0.04714307
## GLD 0.40145967
6. Based on FF 3-factor model, compute MVP monthly returns
covariance matrix for the 8-asset portfolio by using past 60-month
returns from 2019/03 - 2024/02
#Find covariance matrix using Fama-French 3-factor
N <- nrow(portfolio_8)
ones <- rep(1, N)
portfolio_ma <- as.matrix(portfolio_8)
sigF3 <- as.matrix(var(cbind(monthly_returns_60$`Mkt-RF`,
monthly_returns_60$SMB,
monthly_returns_60$HML)))
X.3 <- cbind(ones, monthly_returns_60$`Mkt-RF`, monthly_returns_60$SMB, monthly_returns_60$HML)
b_hat.3 <- solve(t(X.3) %*% (X.3)) %*% t(X.3) %*% portfolio_ma
E_hat.3 <- portfolio_ma - X.3 %*% b_hat.3
b_hat.3 <- as.matrix(b_hat.3[-1, ])
diagD_hat.3 <- diag(t(E_hat.3) %*% E_hat.3)/(N-4)
cov_3f.3 = t(b_hat.3) %*% sigF3 %*% b_hat.3 + diag(diagD_hat.3)
cov_3f.3
## SPY QQQ EEM IWM EFA
## SPY 0.0027966375 0.0030819544 0.0021149594 0.0032150646 0.0024488147
## QQQ 0.0030819544 0.0039971152 0.0022310968 0.0034372722 0.0025685597
## EEM 0.0021149594 0.0022310968 0.0030889215 0.0028566205 0.0019560003
## IWM 0.0032150646 0.0034372722 0.0028566205 0.0047567735 0.0030050405
## EFA 0.0024488147 0.0025685597 0.0019560003 0.0030050405 0.0027367510
## TLT 0.0004774897 0.0009287771 0.0001633524 0.0002278039 0.0002333281
## IYR 0.0026276838 0.0028521353 0.0020722054 0.0031995815 0.0023538265
## GLD 0.0005383281 0.0007015082 0.0002522824 0.0002771607 0.0003887510
## TLT IYR GLD
## SPY 0.0004774897 0.0026276838 0.0005383281
## QQQ 0.0009287771 0.0028521353 0.0007015082
## EEM 0.0001633524 0.0020722054 0.0002522824
## IWM 0.0002278039 0.0031995815 0.0002771607
## EFA 0.0002333281 0.0023538265 0.0003887510
## TLT 0.0023114617 0.0003576503 0.0002731635
## IYR 0.0003576503 0.0035976986 0.0004432168
## GLD 0.0002731635 0.0004432168 0.0018340873
#Find MVP weights
ff3_model <- MVP_sim(cov_3f.3)
ff3_model
## Weight
## SPY 0.20731603
## QQQ -0.36537733
## EEM 0.18359726
## IWM -0.04233677
## EFA 0.22474296
## TLT 0.35918050
## IYR 0.05991173
## GLD 0.37296563
7. You can invest in the 8-portfolio in 2024/03 based on the optimal
weights of MVP from question 5 and 6. What are the realized portfolio
returns in the March of 2024 using the weights from question 5 and
6?
march_return <- monthly_returns['2024-03-28']
capm_return <- march_return %*% capm_model
capm_return <- as.data.frame(capm_return)
colnames(capm_return) <- "Return"
capm_return <- capm_return %>% mutate(Return = scales::percent(Return, accuracy = 0.001))
capm_return %>% kbl(format = "html", caption = "Portfolio Return in March using CAMP Model")
Portfolio Return in March using CAMP Model
Return
|
4.794%
|
ff3_return <- march_return %*% ff3_model
ff3_return <- as.data.frame(ff3_return)
colnames(ff3_return) <- "Return"
ff3_return <- ff3_return %>% mutate(Return = scales::percent(Return, accuracy = 0.001))
ff3_return %>% kbl(format = "html", caption = "Portfolio Return in March using Fama-French Model")
Portfolio Return in March using Fama-French Model
Return
|
4.949%
|