1. Import dataDownload ETF daily data from yahoo with ticker names of SPY, QQQ, EEM, IWM, EFA, TLT, IYR andGLD from 2010 to current date (See http://etfdb.com/ for ETF information). (Hint: Use libraryquantmodto help you to download these prices and use adjusted prices for your computation.)

Load necessary libraries

#install.packages(x)
x<-c("quantmod", "tidyquant", "lubridate", "timetk", "purrr","tidyverse", "tibble", "readr", "xts", "PerformanceAnalytics", "magrittr", "dplyr")
lapply(x, require, character.only = TRUE)
## Loading required package: quantmod
## Loading required package: xts
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## Loading required package: TTR
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
## Loading required package: tidyquant
## Loading required package: lubridate
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
## Loading required package: PerformanceAnalytics
## 
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
## 
##     legend
## Loading required package: timetk
## Loading required package: purrr
## Loading required package: tidyverse
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr   1.1.4     ✔ stringr 1.5.0
## ✔ forcats 1.0.0     ✔ tibble  3.2.1
## ✔ ggplot2 3.4.2     ✔ tidyr   1.3.0
## ✔ readr   2.1.5     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::first()  masks xts::first()
## ✖ dplyr::lag()    masks stats::lag()
## ✖ dplyr::last()   masks xts::last()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
## Loading required package: magrittr
## 
## 
## Attaching package: 'magrittr'
## 
## 
## The following object is masked from 'package:tidyr':
## 
##     extract
## 
## 
## The following object is masked from 'package:purrr':
## 
##     set_names
## [[1]]
## [1] TRUE
## 
## [[2]]
## [1] TRUE
## 
## [[3]]
## [1] TRUE
## 
## [[4]]
## [1] TRUE
## 
## [[5]]
## [1] TRUE
## 
## [[6]]
## [1] TRUE
## 
## [[7]]
## [1] TRUE
## 
## [[8]]
## [1] TRUE
## 
## [[9]]
## [1] TRUE
## 
## [[10]]
## [1] TRUE
## 
## [[11]]
## [1] TRUE
## 
## [[12]]
## [1] TRUE
tickers <- c("SPY", "QQQ", "EEM", "IWM", "EFA", "TLT", "IYR", "GLD")

data = new.env()

getSymbols(tickers, src = 'yahoo', auto.assign = TRUE)
## [1] "SPY" "QQQ" "EEM" "IWM" "EFA" "TLT" "IYR" "GLD"
etf_data <- merge(Ad(SPY), Ad(QQQ),Ad(EEM), Ad(IWM),Ad(EFA),Ad(TLT),Ad(IYR),Ad(GLD))

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

head(etf_data)
##                 SPY      QQQ      EEM      IWM      EFA      TLT      IYR   GLD
## 2007-01-03 101.5366 37.48681 27.08176 61.77275 44.58430 52.96931 44.11396 62.28
## 2007-01-04 101.7520 38.19769 26.70778 61.93874 44.45692 53.29048 44.10344 61.65
## 2007-01-05 100.9405 38.01564 25.92689 60.64259 43.78976 53.05853 43.41967 60.17
## 2007-01-08 101.4073 38.04165 26.11506 60.40549 43.85043 53.15369 43.40916 60.48
## 2007-01-09 101.3211 38.23237 25.53176 60.97454 43.89288 53.15369 43.91935 60.85
## 2007-01-10 101.6587 38.68318 25.47295 61.44875 43.55930 52.91580 44.61891 60.59
  1. Calculate weekly and monthly returns using discrete returns.
etf_data.xts <- xts(etf_data)
tail(etf_data)
##               SPY    QQQ   EEM    IWM   EFA    TLT   IYR    GLD
## 2024-05-31 527.37 450.71 41.79 205.77 81.18 90.142 86.67 215.30
## 2024-06-03 527.80 453.13 42.23 204.61 81.41 91.600 86.43 217.22
## 2024-06-04 528.39 454.37 41.64 201.97 81.31 92.670 87.20 215.27
## 2024-06-05 534.67 463.53 42.31 205.06 81.88 93.350 86.99 217.82
## 2024-06-06 534.66 463.37 42.52 203.59 82.16 93.210 87.13 219.43
## 2024-06-07 534.01 462.96 42.04 201.20 81.27 91.500 86.43 211.60

WEEKLY - Only count the last day of the week. exclude na values

weekly_returns <- to.weekly(etf_data.xts, indexAt = "last", OHLC = FALSE)
etf_weekly_returns_log <- na.omit(Return.calculate(weekly_returns, method = "log"))
head(etf_weekly_returns_log)
##                     SPY          QQQ          EEM           IWM           EFA
## 2007-01-12  0.019029577  0.032752846  0.015036649  0.0289017080  0.0123883374
## 2007-01-19 -0.002936382 -0.025481921  0.006591342 -0.0155672319  0.0080392257
## 2007-01-26 -0.004842907 -0.013676681  0.004870716  0.0039785460 -0.0042160675
## 2007-02-02  0.018680196  0.013450422  0.018903425  0.0275406501  0.0179627522
## 2007-02-09 -0.006026066 -0.006360845 -0.010457567  0.0007474486 -0.0009374423
## 2007-02-16  0.012359340  0.018738163  0.033086651  0.0106511194  0.0230441461
##                      TLT           IYR         GLD
## 2007-01-12 -0.0132020364  0.0421051470 0.032698680
## 2007-01-19 -0.0005682573  0.0197801019 0.013262188
## 2007-01-26 -0.0123489856  0.0222955061 0.018401057
## 2007-02-02  0.0073938620  0.0242034729 0.001712739
## 2007-02-09  0.0049191868  0.0056365015 0.028222793
## 2007-02-16  0.0114599576 -0.0006485655 0.003623160
  1. MONTHLY - Only count the last day of the month, exclude na values
monthly_returns <- to.monthly(etf_data.xts, indexAt = "last", OHLC = FALSE)
etf_monthly_returns_log <- na.omit(Return.calculate(monthly_returns, method = "log"))
head(etf_monthly_returns_log)
##                    SPY          QQQ         EEM          IWM          EFA
## 2007-02-28 -0.01981286 -0.016933826 -0.03290651 -0.006575194 -0.001213080
## 2007-03-30  0.01152271  0.005234768  0.05197121  0.009754944  0.028582794
## 2007-04-30  0.04334242  0.054320806  0.03657594  0.016106413  0.036798322
## 2007-05-31  0.03335746  0.031061829  0.04940452  0.042791632  0.023348012
## 2007-06-29 -0.01472828  0.004781240  0.03612274 -0.014486914 -0.003213386
## 2007-07-31 -0.03181104 -0.001471669  0.00711632 -0.072532081 -0.023171218
##                     TLT          IYR         GLD
## 2007-02-28  0.033327736 -0.036432416  0.02513271
## 2007-03-30 -0.017149405 -0.025597000 -0.01119367
## 2007-04-30  0.009009019  0.002928296  0.02032741
## 2007-05-31 -0.023409905  0.001519735 -0.02337429
## 2007-06-29 -0.010186149 -0.091133257 -0.01956775
## 2007-07-31  0.032651998 -0.095052180  0.02337496
  1. Download Fama French 3 factors data and change to digit numbers (not inpercentage): •Go to http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html •Download Fama/French 3 factor returns’ monthly data (Mkt-RF, SMB and HML).
fama <- read_csv("F-F_Research_Data_Factors.CSV")
## Rows: 1172 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (5): Date, Mkt-RF, SMB, HML, RF
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(fama)
## # A tibble: 6 × 5
##     Date `Mkt-RF`   SMB   HML    RF
##    <dbl>    <dbl> <dbl> <dbl> <dbl>
## 1 192607     2.96 -2.56 -2.43  0.22
## 2 192608     2.64 -1.17  3.82  0.25
## 3 192609     0.36 -1.4   0.13  0.23
## 4 192610    -3.24 -0.09  0.7   0.32
## 5 192611     2.53 -0.1  -0.51  0.31
## 6 192612     2.62 -0.03 -0.05  0.28

Format the data frame

colnames(fama) <- paste(c("date","MKT-RF","SMB","HML","RF"))
fama.digit <- fama %>% mutate(date = as.character(date))%>% 
  mutate(date=ymd(parse_date(date,format="%Y%m"))) %>%
  mutate(date=rollback(date))
head(fama.digit)
## # A tibble: 6 × 5
##   date       `MKT-RF`   SMB   HML    RF
##   <date>        <dbl> <dbl> <dbl> <dbl>
## 1 1926-06-30     2.96 -2.56 -2.43  0.22
## 2 1926-07-31     2.64 -1.17  3.82  0.25
## 3 1926-08-31     0.36 -1.4   0.13  0.23
## 4 1926-09-30    -3.24 -0.09  0.7   0.32
## 5 1926-10-31     2.53 -0.1  -0.51  0.31
## 6 1926-11-30     2.62 -0.03 -0.05  0.28
fama.digit.xts <- xts(fama.digit[,-1],order.by=as.Date(fama.digit$date))
head(fama.digit.xts)
##            MKT-RF   SMB   HML   RF
## 1926-06-30   2.96 -2.56 -2.43 0.22
## 1926-07-31   2.64 -1.17  3.82 0.25
## 1926-08-31   0.36 -1.40  0.13 0.23
## 1926-09-30  -3.24 -0.09  0.70 0.32
## 1926-10-31   2.53 -0.10 -0.51 0.31
## 1926-11-30   2.62 -0.03 -0.05 0.28
  1. Merge with ETF Monthly returns using left join
etf_monthly_returns_tibble <- as_tibble(etf_monthly_returns_log, rownames = "date")
etf_monthly_returns_tibble <- etf_monthly_returns_tibble %>% 
  mutate(date = as.Date(date))

merge_data_tibble <- left_join(fama.digit, etf_monthly_returns_tibble, by = "date")
tail(merge_data_tibble)
## # A tibble: 6 × 13
##   date       `MKT-RF`   SMB   HML    RF     SPY     QQQ     EEM     IWM      EFA
##   <date>        <dbl> <dbl> <dbl> <dbl>   <dbl>   <dbl>   <dbl>   <dbl>    <dbl>
## 1 2023-08-31    -5.24 -2.51  1.52  0.43 -0.0164 -0.0149 -0.0686 -0.0522 -0.0401 
## 2 2023-09-30    -3.19 -3.87  0.19  0.47 NA      NA      NA      NA      NA      
## 3 2023-10-31     8.84 -0.02  1.64  0.44 -0.0219 -0.0209 -0.0335 -0.0716 -0.0294 
## 4 2023-11-30     4.87  6.34  4.93  0.43  0.0874  0.103   0.0750  0.0880  0.0790 
## 5 2023-12-31     0.71 -5.09 -2.38  0.47 NA      NA      NA      NA      NA      
## 6 2024-01-31     5.06 -0.24 -3.48  0.42  0.0158  0.0180 -0.0463 -0.0398 -0.00452
## # ℹ 3 more variables: TLT <dbl>, IYR <dbl>, GLD <dbl>
  1. 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 2010/02 - 2015/01.
calc_data <- merge_data_tibble[merge_data_tibble$date>="2010-02-01"&merge_data_tibble$date<="2015-01-01",]
head(calc_data)
## # A tibble: 6 × 13
##   date       `MKT-RF`   SMB   HML    RF     SPY     QQQ      EEM     IWM     EFA
##   <date>        <dbl> <dbl> <dbl> <dbl>   <dbl>   <dbl>    <dbl>   <dbl>   <dbl>
## 1 2010-02-28     6.31  1.48  2.21  0.01 NA      NA      NA       NA      NA     
## 2 2010-03-31     2     4.87  2.89  0.01  0.0591  0.0743  0.0780   0.0791  0.0619
## 3 2010-04-30    -7.89  0.09 -2.44  0.01  0.0154  0.0222 -0.00166  0.0552 -0.0284
## 4 2010-05-31    -5.57 -1.82 -4.7   0.01 NA      NA      NA       NA      NA     
## 5 2010-06-30     6.93  0.2  -0.31  0.01 -0.0531 -0.0616 -0.0141  -0.0806 -0.0208
## 6 2010-07-31    -4.77 -3    -1.9   0.01 NA      NA      NA       NA      NA     
## # ℹ 3 more variables: TLT <dbl>, IYR <dbl>, GLD <dbl>
#replace NA values with 0
columns_to_fill <- c("SPY", "QQQ", "EEM", "IWM", "EFA", "TLT", "IYR", "GLD")
calc_data_fill <- calc_data %>% 
  mutate_at(vars(one_of(columns_to_fill)), ~replace(., is.na(.), 0))
head(calc_data_fill)
## # A tibble: 6 × 13
##   date       `MKT-RF`   SMB   HML    RF     SPY     QQQ      EEM     IWM     EFA
##   <date>        <dbl> <dbl> <dbl> <dbl>   <dbl>   <dbl>    <dbl>   <dbl>   <dbl>
## 1 2010-02-28     6.31  1.48  2.21  0.01  0       0       0        0       0     
## 2 2010-03-31     2     4.87  2.89  0.01  0.0591  0.0743  0.0780   0.0791  0.0619
## 3 2010-04-30    -7.89  0.09 -2.44  0.01  0.0154  0.0222 -0.00166  0.0552 -0.0284
## 4 2010-05-31    -5.57 -1.82 -4.7   0.01  0       0       0        0       0     
## 5 2010-06-30     6.93  0.2  -0.31  0.01 -0.0531 -0.0616 -0.0141  -0.0806 -0.0208
## 6 2010-07-31    -4.77 -3    -1.9   0.01  0       0       0        0       0     
## # ℹ 3 more variables: TLT <dbl>, IYR <dbl>, GLD <dbl>
spy_rf <- calc_data_fill$SPY-calc_data_fill$RF
qqq_rf <- calc_data_fill$QQQ-calc_data_fill$RF
eem_rf <- calc_data_fill$EEM-calc_data_fill$RF
iwm_rf <- calc_data_fill$IWM-calc_data_fill$RF
efa_rf <- calc_data_fill$EFA-calc_data_fill$RF
tlt_rf <- calc_data_fill$TLT-calc_data_fill$RF
iyr_rf <- calc_data_fill$IYR-calc_data_fill$RF
gld_rf <- calc_data_fill$GLD-calc_data_fill$RF
y <- cbind(spy_rf,qqq_rf,eem_rf,iwm_rf,efa_rf,tlt_rf,iyr_rf,gld_rf)
n <- nrow(y)
one.vec <- rep(1,n)
x <- cbind(one.vec,calc_data_fill$`MKT-RF`)
x.mat <- as.matrix(x)
beta <- solve(t(x)%*%x)%*%t(x)%*%y
beta
##                spy_rf        qqq_rf        eem_rf       iwm_rf        efa_rf
## one.vec  0.0058412542  0.0061279844 -0.0010377749  0.007427027 -0.0001841714
##         -0.0009667541 -0.0003856413 -0.0007765374 -0.002014580 -0.0002073968
##              tlt_rf       iyr_rf       gld_rf
## one.vec 0.002284839  0.006201665  0.001221924
##         0.001443861 -0.001060760 -0.002852133
#residual
e.hat <- y - x%*%beta
res.var <- diag(t(e.hat)%*%e.hat)/(n-2)
d <- diag(res.var);d
##             [,1]        [,2]        [,3]        [,4]        [,5]        [,6]
## [1,] 0.001066511 0.000000000 0.000000000 0.000000000 0.000000000 0.000000000
## [2,] 0.000000000 0.001452147 0.000000000 0.000000000 0.000000000 0.000000000
## [3,] 0.000000000 0.000000000 0.002852139 0.000000000 0.000000000 0.000000000
## [4,] 0.000000000 0.000000000 0.000000000 0.002282146 0.000000000 0.000000000
## [5,] 0.000000000 0.000000000 0.000000000 0.000000000 0.001823551 0.000000000
## [6,] 0.000000000 0.000000000 0.000000000 0.000000000 0.000000000 0.001182795
## [7,] 0.000000000 0.000000000 0.000000000 0.000000000 0.000000000 0.000000000
## [8,] 0.000000000 0.000000000 0.000000000 0.000000000 0.000000000 0.000000000
##             [,7]        [,8]
## [1,] 0.000000000 0.000000000
## [2,] 0.000000000 0.000000000
## [3,] 0.000000000 0.000000000
## [4,] 0.000000000 0.000000000
## [5,] 0.000000000 0.000000000
## [6,] 0.000000000 0.000000000
## [7,] 0.001480561 0.000000000
## [8,] 0.000000000 0.001726186
# covariance matrix single factor model
cov.mat <- var(merge_data_tibble$`MKT-RF`)*t(beta)%*%beta + d
cov.mat
##               spy_rf        qqq_rf        eem_rf        iwm_rf        efa_rf
## spy_rf  2.066707e-03  1.031955e-03 -1.515404e-04  0.0012933914 -2.497405e-05
## qqq_rf  1.031955e-03  2.527841e-03 -1.729059e-04  0.0013207497 -2.991951e-05
## eem_rf -1.515404e-04 -1.729059e-04  2.900073e-03 -0.0001752793  1.004851e-05
## iwm_rf  1.293391e-03  1.320750e-03 -1.752793e-04  0.0039718090 -2.710650e-05
## efa_rf -2.497405e-05 -2.991951e-05  1.004851e-05 -0.0000271065  1.825746e-03
## tlt_rf  3.409745e-04  3.836069e-04 -9.964514e-05  0.0004011868 -2.055052e-05
## iyr_rf  1.062857e-03  1.096005e-03 -1.601294e-04  0.0013751696 -2.631167e-05
## gld_rf  2.823238e-04  2.450307e-04  2.701172e-05  0.0004228806  1.045652e-05
##               tlt_rf        iyr_rf        gld_rf
## spy_rf  3.409745e-04  1.062857e-03  2.823238e-04
## qqq_rf  3.836069e-04  1.096005e-03  2.450307e-04
## eem_rf -9.964514e-05 -1.601294e-04  2.701172e-05
## iwm_rf  4.011868e-04  1.375170e-03  4.228806e-04
## efa_rf -2.055052e-05 -2.631167e-05  1.045652e-05
## tlt_rf  1.391230e-03  3.605976e-04 -3.783913e-05
## iyr_rf  3.605976e-04  2.610037e-03  3.025392e-04
## gld_rf -3.783913e-05  3.025392e-04  2.000888e-03
# mvp montly returns of 8 assest CAMP 
one.vec2 <- rep(1,8)
top <- solve(cov.mat)%*%one.vec2
bot <- t(one.vec2)%*%top
mvp_capm <- top/as.numeric(bot)
mvp_capm
##                 [,1]
## spy_rf  0.0864944324
## qqq_rf  0.0587455476
## eem_rf  0.1544821254
## iwm_rf -0.0004280025
## efa_rf  0.2220970846
## tlt_rf  0.2554130590
## iyr_rf  0.0492478399
## gld_rf  0.1739479137
  1. Based on FF 3-factor model, compute MVP monthly returns covariance matrix for the 8-asset portfolio by using past 60-month returns from 2010/02 - 2015/01
t <- dim(calc_data_fill)[1]
markets <- calc_data_fill[,c(2,3,4)]
FM <- calc_data_fill[,c(-1,-2,-3,-4,-5)]
head(FM)
## # A tibble: 6 × 8
##       SPY     QQQ      EEM     IWM     EFA     TLT     IYR      GLD
##     <dbl>   <dbl>    <dbl>   <dbl>   <dbl>   <dbl>   <dbl>    <dbl>
## 1  0       0       0        0       0       0       0       0      
## 2  0.0591  0.0743  0.0780   0.0791  0.0619 -0.0208  0.0930 -0.00440
## 3  0.0154  0.0222 -0.00166  0.0552 -0.0284  0.0327  0.0619  0.0572 
## 4  0       0       0        0       0       0       0       0      
## 5 -0.0531 -0.0616 -0.0141  -0.0806 -0.0208  0.0564 -0.0478  0.0233 
## 6  0       0       0        0       0       0       0       0
FM <- as.matrix(FM)
n <- dim(FM)[2]
one_vec <- rep(1,t)
p <- cbind(one_vec,markets)
p <- as.matrix(p)
b.hat <- solve(t(p)%*%p)%*%t(p)%*%FM
res <- FM-p%*%b.hat
diag.d <- diag(t(res)%*%res)/(t-6)
diag.d
##         SPY         QQQ         EEM         IWM         EFA         TLT 
## 0.001091729 0.001505198 0.002919168 0.002404107 0.001886366 0.001203830 
##         IYR         GLD 
## 0.001583849 0.001847489
retvar <- apply(FM,2,var)
rsq <- 1-diag(t(res)%*%res)/((t-1)/retvar)
res.stdev <- sqrt(diag.d)
factor.cov <- var(FM)*t(b.hat)%*%b.hat+diag(diag.d)
stdev <- sqrt(diag(factor.cov))
factor.cor <- factor.cov/(stdev%*%t(stdev))
factor.cor
##               SPY           QQQ           EEM           IWM           EFA
## SPY  1.000000e+00  1.174100e-04  3.004937e-05  1.259587e-04  6.049202e-05
## QQQ  1.174100e-04  1.000000e+00  2.448028e-05  1.178828e-04  5.612677e-05
## EEM  3.004937e-05  2.448028e-05  1.000000e+00  3.550663e-05  3.057381e-05
## IWM  1.259587e-04  1.178828e-04  3.550663e-05  1.000000e+00  5.905564e-05
## EFA  6.049202e-05  5.612677e-05  3.057381e-05  5.905564e-05  1.000000e+00
## TLT -2.159590e-05 -1.986205e-05 -1.355514e-06 -2.348847e-05 -2.360908e-06
## IYR  8.701328e-05  7.931306e-05  2.660532e-05  9.637960e-05  4.526161e-05
## GLD  7.979925e-06  7.635986e-06  8.033463e-06  1.393527e-05  3.309333e-06
##               TLT           IYR           GLD
## SPY -2.159590e-05  8.701328e-05  7.979925e-06
## QQQ -1.986205e-05  7.931306e-05  7.635986e-06
## EEM -1.355514e-06  2.660532e-05  8.033463e-06
## IWM -2.348847e-05  9.637960e-05  1.393527e-05
## EFA -2.360908e-06  4.526161e-05  3.309333e-06
## TLT  1.000000e+00 -1.003194e-05 -1.971330e-07
## IYR -1.003194e-05  1.000000e+00  1.093377e-05
## GLD -1.971330e-07  1.093377e-05  1.000000e+00
sample.cov <- cov(FM)
sample.cor <- cor(FM)
sample.cov
##               SPY           QQQ           EEM           IWM           EFA
## SPY  0.0010534862  0.0011369269  0.0013841547  0.0014349600  0.0012192996
## QQQ  0.0011369269  0.0014192102  0.0014370760  0.0015302653  0.0013036709
## EEM  0.0013841547  0.0014370760  0.0028280869  0.0019680514  0.0019616188
## IWM  0.0014349600  0.0015302653  0.0019680514  0.0023090518  0.0015865714
## EFA  0.0012192996  0.0013036709  0.0019616188  0.0015865714  0.0018202293
## TLT -0.0007750084 -0.0007801047 -0.0010893462 -0.0010817582 -0.0009381301
## IYR  0.0009281891  0.0009591728  0.0014798170  0.0013584468  0.0011670624
## GLD  0.0003481968  0.0004188970  0.0008232053  0.0006933685  0.0004230876
##               TLT           IYR           GLD
## SPY -7.750084e-04  0.0009281891  3.481968e-04
## QQQ -7.801047e-04  0.0009591728  4.188970e-04
## EEM -1.089346e-03  0.0014798170  8.232053e-04
## IWM -1.081758e-03  0.0013584468  6.933685e-04
## EFA -9.381301e-04  0.0011670624  4.230876e-04
## TLT  1.165485e-03 -0.0003951234 -1.640529e-05
## IYR -3.951234e-04  0.0014917589  5.297311e-04
## GLD -1.640529e-05  0.0005297311  1.873559e-03
one <- rep(1,8)
top.mat <- solve(factor.cov)%*%one
bot.mat <- t(one)%*%top.mat
MVP_FF3 <- top.mat/as.numeric(bot.mat)
MVP_FF3
##           [,1]
## SPY 0.18797574
## QQQ 0.13633160
## EEM 0.07031311
## IWM 0.08533945
## EFA 0.10880251
## TLT 0.17055065
## IYR 0.12956859
## GLD 0.11111837

Compute Global Minimum Variance Portfloio Weights

# Inverse of covariance matrix
inv_cov_mat_capm <- solve(cov.mat)

one_vec <- rep(1, ncol(inv_cov_mat_capm))
gmv_weights_capm <- inv_cov_mat_capm %*% one_vec / sum(inv_cov_mat_capm %*% one_vec)
gmv_weights_capm
##                 [,1]
## spy_rf  0.0864944324
## qqq_rf  0.0587455476
## eem_rf  0.1544821254
## iwm_rf -0.0004280025
## efa_rf  0.2220970846
## tlt_rf  0.2554130590
## iyr_rf  0.0492478399
## gld_rf  0.1739479137
# Inverse of covariance matrix
inv_cov_mat_ff3 <- solve(factor.cov)

gmv_weights_ff3 <- inv_cov_mat_ff3 %*% one_vec / sum(inv_cov_mat_ff3 %*% one_vec)
gmv_weights_ff3
##           [,1]
## SPY 0.18797574
## QQQ 0.13633160
## EEM 0.07031311
## IWM 0.08533945
## EFA 0.10880251
## TLT 0.17055065
## IYR 0.12956859
## GLD 0.11111837