# https://palomar.home.ece.ust.hk/MAFS6010R_lectures/Rsession_factor_models.html#final_comparison_of_covariance_matrix_estimations_via_different_factor_models
# https://systematicinvestor.wordpress.com/2012/03/19/backtesting-asset-allocation-portfolios/
rm(list = ls())
library(lubridate)
##
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
##
## date, intersect, setdiff, union
library(timetk)
library(purrr)
library(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
library(lpSolve)
#devtools::install_github(‘joshuaulrich/xts’, force = T) #devtools::install_github(‘joshuaulrich/quantmod’, force = T) # #devtools::install_github(‘systematicinvestor/SIT.date’, force = T) #curl::curl_download(‘https://github.com/systematicinvestor/SIT/raw/master/SIT.tar.gz’, #‘SIT.tar.gz’,mode = ‘wb’,quiet=T) #install.packages(‘SIT.tar.gz’, repos = NULL, type=‘source’)
library(SIT)
## Loading required package: SIT.date
##
## Attaching package: 'SIT'
## The following object is masked from 'package:TTR':
##
## DVI
## The following object is masked from 'package:purrr':
##
## cross
## The following object is masked from 'package:base':
##
## close
library(PerformanceAnalytics)
##
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
##
## legend
library(xts)
library(tidyr)
#Import Data
tickers = spl('MA,HAS,JNJ,VRTX,AMZN,NFLX,MSFT,MNST')
datas <- new.env()
getSymbols(tickers, src = 'yahoo', from = '2005-01-01', env = datas, auto.assign = T)
## 'getSymbols' currently uses auto.assign=TRUE by default, but will
## use auto.assign=FALSE in 0.5-0. You will still be able to use
## 'loadSymbols' to automatically load data. getOption("getSymbols.env")
## and getOption("getSymbols.auto.assign") will still be checked for
## alternate defaults.
##
## This message is shown once per session and may be disabled by setting
## options("getSymbols.warning4.0"=FALSE). See ?getSymbols for details.
## pausing 1 second between requests for more than 5 symbols
## pausing 1 second between requests for more than 5 symbols
## pausing 1 second between requests for more than 5 symbols
## pausing 1 second between requests for more than 5 symbols
## [1] "MA" "HAS" "JNJ" "VRTX" "AMZN" "NFLX" "MSFT" "MNST"
for(i in ls(datas)) datas[[i]] = adjustOHLC(datas[[i]], use.Adjusted=T)
names(datas)
## [1] "VRTX" "HAS" ".getSymbols" "NFLX" "MA"
## [6] "AMZN" "MSFT" "MNST" "JNJ"
datas$EEM
## NULL
head(datas$EEM)
## NULL
bt.prep(datas, align='remove.na')
names(datas)
## [1] "VRTX" "prices" "dates" "HAS"
## [5] "weight" ".getSymbols" "symbolnames" "execution.price"
## [9] "NFLX" "MA" "AMZN" "MSFT"
## [13] "MNST" "JNJ"
#
head(datas$SPY)
## NULL
head(datas$prices)
## AMZN HAS JNJ MA MNST MSFT NFLX VRTX
## 2006-05-25 35.63 12.31116 38.98571 4.289672 7.580000 17.29757 4.107143 33.23
## 2006-05-26 36.07 12.39033 39.14048 4.189889 7.632500 17.28300 4.118571 33.75
## 2006-05-30 34.64 12.20560 38.59875 4.103165 7.471250 16.86767 3.928571 32.62
## 2006-05-31 34.61 12.23199 38.83738 4.190823 7.702917 16.50336 3.955714 34.50
## 2006-06-01 35.07 12.33095 39.11469 4.430486 7.656667 16.62723 4.072857 34.35
## 2006-06-02 34.76 12.42991 39.17275 4.381993 7.678333 16.58352 3.992857 34.67
prices_monthly <- to.monthly(datas$prices, indexAt = "last", OHLC = FALSE) # indexAt = 'endof'
head(prices_monthly)
## AMZN HAS JNJ MA MNST MSFT NFLX VRTX
## 2006-05-31 34.61 12.23199 38.83738 4.190823 7.702917 16.50336 3.955714 34.50
## 2006-06-30 38.68 11.94828 38.64388 4.476179 7.932083 16.97697 3.887143 36.71
## 2006-07-31 26.89 12.41766 40.34005 4.277548 7.665000 17.53073 2.955714 33.52
## 2006-08-31 30.83 13.48013 41.94282 5.212882 4.590000 18.79462 2.860000 34.45
## 2006-09-29 32.12 15.10705 42.12446 6.560400 5.413333 20.00129 3.254286 33.65
## 2006-10-31 38.09 17.29476 43.72017 6.919045 5.291667 20.99586 3.951429 40.60
monthly.ret <- na.omit(Return.calculate(prices_monthly, method = "discrete"))
head(monthly.ret)
## AMZN HAS JNJ MA MNST
## 2006-06-30 0.11759604 -0.02319345 -0.004982313 0.06809068 0.02975055
## 2006-07-31 -0.30480871 0.03928422 0.043892354 -0.04437512 -0.03367123
## 2006-08-31 0.14652291 0.08556095 0.039731504 0.21866125 -0.40117417
## 2006-09-29 0.04184233 0.12069001 0.004330586 0.25849770 0.17937538
## 2006-10-31 0.18586554 0.14481394 0.037880769 0.05466816 -0.02247525
## 2006-11-30 0.05907062 0.03202161 -0.016583650 0.37314442 -0.11401587
## MSFT NFLX VRTX
## 2006-06-30 0.02869766 -0.01733467 0.06405794
## 2006-07-31 0.03261806 -0.23961789 -0.08689728
## 2006-08-31 0.07209598 -0.03238270 0.02774466
## 2006-09-29 0.06420299 0.13786224 -0.02322203
## 2006-10-31 0.04972508 0.21422303 0.20653776
## 2006-11-30 0.02613658 0.05856818 0.09113303
#download Fama-French factors from website
url <- "http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_daily_CSV.zip"
temp <- tempfile()
download.file(url, temp, method = "libcurl", mode = "wb")
unzip(temp, "F-F_Research_Data_Factors_daily.CSV")
unlink(temp)
mydata <- read.csv("F-F_Research_Data_Factors_daily.CSV", skip = 4)
mydata <- mydata[-nrow(mydata), ] # remove last row
fama_lib <- xts(x = mydata[, c(2,3,4)], order.by = as.Date(paste(mydata[, 1]), "%Y%m%d"))
str(fama_lib)
## An 'xts' object on 1926-07-01/2021-04-30 containing:
## Data: num [1:24978, 1:3] 0.1 0.45 0.17 0.09 0.21 -0.71 0.62 0.04 0.48 0.04 ...
## - attr(*, "dimnames")=List of 2
## ..$ : NULL
## ..$ : chr [1:3] "Mkt.RF" "SMB" "HML"
## Indexed by objects of class: [Date] TZ: UTC
## xts Attributes:
## NULL
head(fama_lib)
## Mkt.RF SMB HML
## 1926-07-01 0.10 -0.24 -0.28
## 1926-07-02 0.45 -0.32 -0.08
## 1926-07-06 0.17 0.27 -0.35
## 1926-07-07 0.09 -0.59 0.03
## 1926-07-08 0.21 -0.36 0.15
## 1926-07-09 -0.71 0.44 0.56
dates <- '2005-01::2021-03'
X <- monthly.ret[dates]
head(X)
## AMZN HAS JNJ MA MNST
## 2006-06-30 0.11759604 -0.02319345 -0.004982313 0.06809068 0.02975055
## 2006-07-31 -0.30480871 0.03928422 0.043892354 -0.04437512 -0.03367123
## 2006-08-31 0.14652291 0.08556095 0.039731504 0.21866125 -0.40117417
## 2006-09-29 0.04184233 0.12069001 0.004330586 0.25849770 0.17937538
## 2006-10-31 0.18586554 0.14481394 0.037880769 0.05466816 -0.02247525
## 2006-11-30 0.05907062 0.03202161 -0.016583650 0.37314442 -0.11401587
## MSFT NFLX VRTX
## 2006-06-30 0.02869766 -0.01733467 0.06405794
## 2006-07-31 0.03261806 -0.23961789 -0.08689728
## 2006-08-31 0.07209598 -0.03238270 0.02774466
## 2006-09-29 0.06420299 0.13786224 -0.02322203
## 2006-10-31 0.04972508 0.21422303 0.20653776
## 2006-11-30 0.02613658 0.05856818 0.09113303
dim(X)
## [1] 178 8
#
fama_lib_month <- to.monthly(fama_lib, indexAt = "last", OHLC = FALSE) # indexAt = 'endof'
head(fama_lib_month)
## Mkt.RF SMB HML
## 1926-07-31 0.46 -0.12 -0.17
## 1926-08-31 0.58 -0.52 -0.04
## 1926-09-30 0.30 -0.22 0.06
## 1926-10-30 -0.25 0.20 0.25
## 1926-11-30 0.26 0.03 -0.50
## 1926-12-31 0.33 0.30 0.67
f <- fama_lib_month[dates]/100
head(f)
## Mkt.RF SMB HML
## 2005-01-31 0.0097 0.0076 0.0014
## 2005-02-28 -0.0061 0.0027 0.0007
## 2005-03-31 0.0000 -0.0006 0.0065
## 2005-04-29 0.0104 -0.0040 -0.0003
## 2005-05-31 -0.0049 0.0046 0.0033
## 2005-06-30 -0.0063 0.0021 0.0025
dim(f)
## [1] 195 3
#======================================================================
# Use Professor Palomar's package to compute estimated coefficients
# Based on CAPM model, compute covariance matrix for the 8-asset portfolio by using past 60-month returns from 2010/01 - 2014/12.
#======================================================================
devtools::install_github("dppalomar/covFactorModel")
## Error in get(genname, envir = envir) : object 'testthat_print' not found
## Skipping install of 'covFactorModel' from a github remote, the SHA1 (1e7cc3df) has not changed since last install.
## Use `force = TRUE` to force installation
library(covFactorModel)
#
insample_range <- '2010-01::2014-12'
one_factor_model <- factorModel(X[insample_range], type = "M", econ_fact = f$Mkt.RF[insample_range])
names(one_factor_model)
## [1] "alpha" "beta" "factors" "residual"
cbind(alpha = one_factor_model$alpha, beta = one_factor_model$beta)
## alpha Mkt.RF
## AMZN 0.01697563 -0.2085693
## HAS 0.01356192 -0.2763406
## JNJ 0.01239375 1.2967969
## MA 0.02358281 1.2943668
## MNST 0.03401129 1.6321305
## MSFT 0.01124666 0.3790205
## NFLX 0.05205511 1.2534143
## VRTX 0.02456127 -0.5415507
#======================================================================
# we can do the fitting using a more compact matrix notation
F_ <- cbind(ones = 1, f$Mkt.RF[insample_range])
Gamma <- t(X[insample_range]) %*% F_ %*% solve(t(F_) %*% F_) # better: Gamma <- t(solve(t(F_) %*% F_, t(F_) %*% X))
colnames(Gamma) <- c("alpha", "beta")
alpha <- Gamma[, 1] # or alpha <- Gamma[, "alpha"]
beta <- Gamma[, 2] # or beta <- Gamma[, "beta"]
print(Gamma)
## alpha beta
## AMZN 0.01697563 -0.2085693
## HAS 0.01356192 -0.2763406
## JNJ 0.01239375 1.2967969
## MA 0.02358281 1.2943668
## MNST 0.03401129 1.6321305
## MSFT 0.01124666 0.3790205
## NFLX 0.05205511 1.2534143
## VRTX 0.02456127 -0.5415507
# compute Sigma
X <- X[insample_range]
f <- f$Mkt.RF[insample_range]
T <- dim(X)[1]
E <- xts(t(t(X) - Gamma %*% t(F_)), index(X)) # residuals
Psi <- (1/(T-2)) * t(E) %*% E
Sigma <- as.numeric(var(f)) * beta %o% beta + diag(diag(Psi))
Sigma # This is covariance matrix computed from single factor model
## AMZN HAS JNJ MA MNST
## AMZN 6.539575e-03 6.295385e-06 -2.954265e-05 -2.948729e-05 -3.718197e-05
## HAS 6.295385e-06 4.333560e-03 -3.914207e-05 -3.906872e-05 -4.926367e-05
## JNJ -2.954265e-05 -3.914207e-05 1.513699e-03 1.833397e-04 2.311820e-04
## MA -2.948729e-05 -3.906872e-05 1.833397e-04 4.267586e-03 2.307487e-04
## MNST -3.718197e-05 -4.926367e-05 2.311820e-04 2.307487e-04 8.168392e-03
## MSFT -8.634561e-06 -1.144022e-05 5.368609e-05 5.358548e-05 6.756856e-05
## NFLX -2.855434e-05 -3.783263e-05 1.775390e-04 1.772063e-04 2.234481e-04
## VRTX 1.233720e-05 1.634598e-05 -7.670757e-05 -7.656382e-05 -9.654308e-05
## MSFT NFLX VRTX
## AMZN -8.634561e-06 -2.855434e-05 1.233720e-05
## HAS -1.144022e-05 -3.783263e-05 1.634598e-05
## JNJ 5.368609e-05 1.775390e-04 -7.670757e-05
## MA 5.358548e-05 1.772063e-04 -7.656382e-05
## MNST 6.756856e-05 2.234481e-04 -9.654308e-05
## MSFT 3.640926e-03 5.189009e-05 -2.241966e-05
## NFLX 5.189009e-05 4.530811e-02 -7.414142e-05
## VRTX -2.241966e-05 -7.414142e-05 1.777782e-02
#=======================================================================
# We can also use lm() to compute estimated coefficients
fit = lm(formula = X~f)
sigF = as.numeric(var(f))
beta_ = as.matrix(fit$coefficients)
beta_ = as.matrix(beta_[-1,])
beta_
## [,1]
## AMZN -0.2085693
## HAS -0.2763406
## JNJ 1.2967969
## MA 1.2943668
## MNST 1.6321305
## MSFT 0.3790205
## NFLX 1.2534143
## VRTX -0.5415507
sigeps = crossprod(fit$residuals)/(T-2)
# sigeps = as.matrix(var(fit$residuals)) # you can use this way too
sigeps = diag(diag(sigeps))
sigeps
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 0.006534823 0.000000000 0.000000000 0.00000000 0.000000000 0.000000000
## [2,] 0.000000000 0.004325219 0.000000000 0.00000000 0.000000000 0.000000000
## [3,] 0.000000000 0.000000000 0.001330015 0.00000000 0.000000000 0.000000000
## [4,] 0.000000000 0.000000000 0.000000000 0.00408459 0.000000000 0.000000000
## [5,] 0.000000000 0.000000000 0.000000000 0.00000000 0.007877429 0.000000000
## [6,] 0.000000000 0.000000000 0.000000000 0.00000000 0.000000000 0.003625235
## [7,] 0.000000000 0.000000000 0.000000000 0.00000000 0.000000000 0.000000000
## [8,] 0.000000000 0.000000000 0.000000000 0.00000000 0.000000000 0.000000000
## [,7] [,8]
## [1,] 0.00000000 0.00000000
## [2,] 0.00000000 0.00000000
## [3,] 0.00000000 0.00000000
## [4,] 0.00000000 0.00000000
## [5,] 0.00000000 0.00000000
## [6,] 0.00000000 0.00000000
## [7,] 0.04513651 0.00000000
## [8,] 0.00000000 0.01774579
cov_1f = sigF*beta_%*%t(beta_)+sigeps
cov_1f # This is covariance matrix computed from single factor model (from lm())
## AMZN HAS JNJ MA MNST
## AMZN 6.539575e-03 6.295385e-06 -2.954265e-05 -2.948729e-05 -3.718197e-05
## HAS 6.295385e-06 4.333560e-03 -3.914207e-05 -3.906872e-05 -4.926367e-05
## JNJ -2.954265e-05 -3.914207e-05 1.513699e-03 1.833397e-04 2.311820e-04
## MA -2.948729e-05 -3.906872e-05 1.833397e-04 4.267586e-03 2.307487e-04
## MNST -3.718197e-05 -4.926367e-05 2.311820e-04 2.307487e-04 8.168392e-03
## MSFT -8.634561e-06 -1.144022e-05 5.368609e-05 5.358548e-05 6.756856e-05
## NFLX -2.855434e-05 -3.783263e-05 1.775390e-04 1.772063e-04 2.234481e-04
## VRTX 1.233720e-05 1.634598e-05 -7.670757e-05 -7.656382e-05 -9.654308e-05
## MSFT NFLX VRTX
## AMZN -8.634561e-06 -2.855434e-05 1.233720e-05
## HAS -1.144022e-05 -3.783263e-05 1.634598e-05
## JNJ 5.368609e-05 1.775390e-04 -7.670757e-05
## MA 5.358548e-05 1.772063e-04 -7.656382e-05
## MNST 6.756856e-05 2.234481e-04 -9.654308e-05
## MSFT 3.640926e-03 5.189009e-05 -2.241966e-05
## NFLX 5.189009e-05 4.530811e-02 -7.414142e-05
## VRTX -2.241966e-05 -7.414142e-05 1.777782e-02
#=======================================================================
# Backtesting portfolio using SIT package
#=======================================================================
dates <- '2005-01::2021-03'
X <- monthly.ret[dates]
head(X)
## AMZN HAS JNJ MA MNST
## 2006-06-30 0.11759604 -0.02319345 -0.004982313 0.06809068 0.02975055
## 2006-07-31 -0.30480871 0.03928422 0.043892354 -0.04437512 -0.03367123
## 2006-08-31 0.14652291 0.08556095 0.039731504 0.21866125 -0.40117417
## 2006-09-29 0.04184233 0.12069001 0.004330586 0.25849770 0.17937538
## 2006-10-31 0.18586554 0.14481394 0.037880769 0.05466816 -0.02247525
## 2006-11-30 0.05907062 0.03202161 -0.016583650 0.37314442 -0.11401587
## MSFT NFLX VRTX
## 2006-06-30 0.02869766 -0.01733467 0.06405794
## 2006-07-31 0.03261806 -0.23961789 -0.08689728
## 2006-08-31 0.07209598 -0.03238270 0.02774466
## 2006-09-29 0.06420299 0.13786224 -0.02322203
## 2006-10-31 0.04972508 0.21422303 0.20653776
## 2006-11-30 0.02613658 0.05856818 0.09113303
dim(X)
## [1] 178 8
tail(X)
## AMZN HAS JNJ MA MNST
## 2020-10-30 -0.0357541227 0.008173986 -0.07905702 -0.145470847 -0.04526181
## 2020-11-30 0.0434399293 0.124637388 0.06254355 0.165846635 0.10722214
## 2020-12-31 0.0280583237 0.005482124 0.08777995 0.060711424 0.09082336
## 2021-01-29 -0.0155760124 0.002993361 0.03653580 -0.112761444 -0.06109430
## 2021-02-26 -0.0353284326 0.006119783 -0.02257026 0.118751799 0.01048020
## 2021-03-31 0.0003718629 0.025717667 0.03717029 0.006217229 0.03818097
## MSFT NFLX VRTX
## 2020-10-30 -0.037369745 -0.04857710 -0.23430838
## 2020-11-30 0.060060517 0.03144579 0.09306008
## 2020-12-31 0.039005834 0.10195632 0.03771678
## 2021-01-29 0.042891914 -0.01542353 -0.03071843
## 2021-02-26 0.004117931 0.01213389 -0.07215819
## 2021-03-31 0.014588161 -0.03190128 0.01100916
#
prices_monthly <- to.monthly(datas$prices, indexAt = "last", OHLC = FALSE) # indexAt = 'endof'
head(prices_monthly)
## AMZN HAS JNJ MA MNST MSFT NFLX VRTX
## 2006-05-31 34.61 12.23199 38.83738 4.190823 7.702917 16.50336 3.955714 34.50
## 2006-06-30 38.68 11.94828 38.64388 4.476179 7.932083 16.97697 3.887143 36.71
## 2006-07-31 26.89 12.41766 40.34005 4.277548 7.665000 17.53073 2.955714 33.52
## 2006-08-31 30.83 13.48013 41.94282 5.212882 4.590000 18.79462 2.860000 34.45
## 2006-09-29 32.12 15.10705 42.12446 6.560400 5.413333 20.00129 3.254286 33.65
## 2006-10-31 38.09 17.29476 43.72017 6.919045 5.291667 20.99586 3.951429 40.60
prices_monthly <- prices_monthly[dates]
head(prices_monthly)
## AMZN HAS JNJ MA MNST MSFT NFLX VRTX
## 2006-05-31 34.61 12.23199 38.83738 4.190823 7.702917 16.50336 3.955714 34.50
## 2006-06-30 38.68 11.94828 38.64388 4.476179 7.932083 16.97697 3.887143 36.71
## 2006-07-31 26.89 12.41766 40.34005 4.277548 7.665000 17.53073 2.955714 33.52
## 2006-08-31 30.83 13.48013 41.94282 5.212882 4.590000 18.79462 2.860000 34.45
## 2006-09-29 32.12 15.10705 42.12446 6.560400 5.413333 20.00129 3.254286 33.65
## 2006-10-31 38.09 17.29476 43.72017 6.919045 5.291667 20.99586 3.951429 40.60
tail(prices_monthly)
## AMZN HAS JNJ MA MNST MSFT NFLX VRTX
## 2020-10-30 3036.15 81.55690 134.4810 287.9328 76.57 201.0131 475.74 208.36
## 2020-11-30 3168.04 91.72194 142.8919 335.6855 84.78 213.0861 490.70 227.75
## 2020-12-31 3256.93 92.22477 155.4350 356.0654 92.48 221.3977 540.73 236.34
## 2021-01-29 3206.20 92.50083 161.1139 315.9150 86.83 230.8938 532.39 229.08
## 2021-02-26 3092.93 93.06692 157.4775 353.4305 87.74 231.8447 538.85 212.55
## 2021-03-31 3094.08 95.46038 163.3310 355.6278 91.09 235.2268 521.66 214.89
#
#*****************************************************************
# Code Strategies
#******************************************************************
# We need to create environment variable required by SIT
# data_m <- new.env()
#
# data_m$EEM <- prices_monthly$EEM
# colnames(data_m$EEM) <- 'Close'
# head(data_m$EEM)
# Change column names to Close which will be consistent with the requirement of SIT package
# data_m$SPY <- prices_monthly$SPY %>% `colnames<-` (c("Close"))
# data_m$QQQ <- prices_monthly$QQQ %>% `colnames<-` (c("Close"))
# data_m$EEM <- prices_monthly$EEM %>% `colnames<-` (c("Close"))
# data_m$IWM <- prices_monthly$IWM %>% `colnames<-` (c("Close"))
# data_m$EFA <- prices_monthly$EFA %>% `colnames<-` (c("Close"))
# data_m$TLT <- prices_monthly$TLT %>% `colnames<-` (c("Close"))
# data_m$IYR <- prices_monthly$IYR %>% `colnames<-` (c("Close"))
# data_m$GLD <- prices_monthly$GLD %>% `colnames<-` (c("Close"))
# names(data_m)
# head(data_m$EEM)
# Using loop to save time in naming
data_m <- list()
#i = 1
for ( i in 1:length(tickers)){
data_m[[tickers[i]]] <- prices_monthly[,i] %>% `colnames<-` (c("Close"))
}
# data_env <- new.env()
# list2env(data_m, envir = data_env)
# convert from list to environment variable because SIT package requires
# the input data to be environmental variable which can be processed using bt.prep()
data_m <- list2env(data_m)
names(data_m)
## [1] "MNST" "MSFT" "NFLX" "AMZN" "VRTX" "JNJ" "HAS" "MA"
# Check if the column name is 'Close'
head(data_m$EEM)
## NULL
#
bt.prep(data_m, align='remove.na', dates = dates)
names(data_m)
## [1] "prices" "execution.price" "weight" "dates"
## [5] "symbolnames" "MNST" "MSFT" "NFLX"
## [9] "AMZN" "VRTX" "JNJ" "HAS"
## [13] "MA"
#===============================================================
# Equal weighting portfolio
# Equal Weight 1/N Benchmark
#===============================================================
models <- list()
prices <- data_m$prices
# data_m$weight[] = NA
N <- length(tickers)
data_m$weight = ntop(prices, N)
head(data_m$weight)
## AMZN HAS JNJ MA MNST MSFT NFLX VRTX
## 2006-05-31 0.125 0.125 0.125 0.125 0.125 0.125 0.125 0.125
## 2006-06-30 0.125 0.125 0.125 0.125 0.125 0.125 0.125 0.125
## 2006-07-31 0.125 0.125 0.125 0.125 0.125 0.125 0.125 0.125
## 2006-08-31 0.125 0.125 0.125 0.125 0.125 0.125 0.125 0.125
## 2006-09-29 0.125 0.125 0.125 0.125 0.125 0.125 0.125 0.125
## 2006-10-31 0.125 0.125 0.125 0.125 0.125 0.125 0.125 0.125
data_m$weight[1:59, ] <- NA
models$equal.weight = bt.run.share(data_m)
## Latest weights :
## AMZN HAS JNJ MA MNST MSFT NFLX VRTX
## 2021-03-31 10.69 3.58 4.33 21.21 5.18 21.77 15.09 18.16
##
## Performance summary :
## CAGR Best Worst
## 16.2 16.5 -13.7
# head(models$equal.weight$ret, 62)
# Slightly difference between bt.run.share() and bt.run()
capital = 100000
data_m$weight[] = (capital / prices) * data_m$weight
models$equal.weight.share = bt.run(data_m, type='share')
## Latest weights :
## AMZN HAS JNJ MA MNST MSFT NFLX VRTX
## 2021-03-31 12.5 12.5 12.5 12.5 12.5 12.5 12.5 12.5
##
## Performance summary :
## CAGR Best Worst
## 17.2 16.3 -11.2
# head(models$equal.weight.share$ret, 62)
# head(equal.weight$ret)
#================================================================
# MVP portfolio
#*****************************************************************
# Create Constraints
#*****************************************************************
constraints = new.constraints(N, lb = -Inf, ub = +Inf)
# SUM x.i = 1
constraints = add.constraints(rep(1, N), 1, type = '=', constraints)
#
ret = prices / mlag(prices) - 1
weight = coredata(ret)
weight[] = NA
#
# head(data_m$weight)
# compute covariance matrix based on historical 60 months returns
# i = 60
# To make covariance matrix estimate more stable, use the Ledoit-Wolf covariance shrinkage estimator from tawny package
# 1. ia$cov = tawny::cov.shrink(hist) or
# 2. ia$cov = cor(coredata(hist), use='complete.obs', method='spearman') * (s0 %*% t(s0)) or
# 3. ia$cov = cor(coredata(hist), use='complete.obs', method='kendall') * (s0 %*% t(s0)
# i = 60
for( i in 60:dim(weight)[1]) {
hist = ret[ (i- 60 + 1):i, ]
# create historical input assumptions
ia = create.historical.ia(hist, 12) # 12 is annulized factor for monthly returns
s0 = apply(na.omit(coredata(hist)), 2, sd)
ia$cov = cor(coredata(hist), use='complete.obs',method='pearson') * (s0 %*% t(s0))
weight[i,] = min.risk.portfolio(ia, constraints) # use SIT's function min.risk.portfolio()
}
## Loading required package: kernlab
##
## Attaching package: 'kernlab'
## The following object is masked from 'package:SIT':
##
## cross
## The following object is masked from 'package:purrr':
##
## cross
dim(weight)
## [1] 179 8
# 195 8
head(weight, 70)
## AMZN HAS JNJ MA MNST MSFT
## [1,] NA NA NA NA NA NA
## [2,] NA NA NA NA NA NA
## [3,] NA NA NA NA NA NA
## [4,] NA NA NA NA NA NA
## [5,] NA NA NA NA NA NA
## [6,] NA NA NA NA NA NA
## [7,] NA NA NA NA NA NA
## [8,] NA NA NA NA NA NA
## [9,] NA NA NA NA NA NA
## [10,] NA NA NA NA NA NA
## [11,] NA NA NA NA NA NA
## [12,] NA NA NA NA NA NA
## [13,] NA NA NA NA NA NA
## [14,] NA NA NA NA NA NA
## [15,] NA NA NA NA NA NA
## [16,] NA NA NA NA NA NA
## [17,] NA NA NA NA NA NA
## [18,] NA NA NA NA NA NA
## [19,] NA NA NA NA NA NA
## [20,] NA NA NA NA NA NA
## [21,] NA NA NA NA NA NA
## [22,] NA NA NA NA NA NA
## [23,] NA NA NA NA NA NA
## [24,] NA NA NA NA NA NA
## [25,] NA NA NA NA NA NA
## [26,] NA NA NA NA NA NA
## [27,] NA NA NA NA NA NA
## [28,] NA NA NA NA NA NA
## [29,] NA NA NA NA NA NA
## [30,] NA NA NA NA NA NA
## [31,] NA NA NA NA NA NA
## [32,] NA NA NA NA NA NA
## [33,] NA NA NA NA NA NA
## [34,] NA NA NA NA NA NA
## [35,] NA NA NA NA NA NA
## [36,] NA NA NA NA NA NA
## [37,] NA NA NA NA NA NA
## [38,] NA NA NA NA NA NA
## [39,] NA NA NA NA NA NA
## [40,] NA NA NA NA NA NA
## [41,] NA NA NA NA NA NA
## [42,] NA NA NA NA NA NA
## [43,] NA NA NA NA NA NA
## [44,] NA NA NA NA NA NA
## [45,] NA NA NA NA NA NA
## [46,] NA NA NA NA NA NA
## [47,] NA NA NA NA NA NA
## [48,] NA NA NA NA NA NA
## [49,] NA NA NA NA NA NA
## [50,] NA NA NA NA NA NA
## [51,] NA NA NA NA NA NA
## [52,] NA NA NA NA NA NA
## [53,] NA NA NA NA NA NA
## [54,] NA NA NA NA NA NA
## [55,] NA NA NA NA NA NA
## [56,] NA NA NA NA NA NA
## [57,] NA NA NA NA NA NA
## [58,] NA NA NA NA NA NA
## [59,] NA NA NA NA NA NA
## [60,] 0.07782913 0.03137722 0.7903689 -0.05434008 0.009173707 0.06541928
## [61,] 0.07639972 0.04071648 0.7785839 -0.05206156 0.010367126 0.06178763
## [62,] 0.07712825 0.04118901 0.7793875 -0.05308010 0.009052984 0.06201955
## [63,] 0.07155715 0.03160720 0.7952658 -0.06284437 0.005566458 0.05733215
## [64,] 0.06945856 0.03392369 0.7881626 -0.06246487 0.007740626 0.06024423
## [65,] 0.08870090 0.02079686 0.8024643 -0.05434820 0.011109044 0.03091883
## [66,] 0.08527225 0.02606438 0.7903214 -0.05087071 0.016958742 0.03537449
## [67,] 0.08809357 0.02847967 0.7938247 -0.04857773 0.014312228 0.03470435
## [68,] 0.09177453 0.03527649 0.7917262 -0.04481854 0.009960164 0.03226565
## [69,] 0.09746619 0.03301324 0.8090799 -0.04601894 0.009831585 0.01639175
## [70,] 0.09970935 0.02194186 0.8092013 -0.05133660 0.016537753 0.01773513
## NFLX VRTX
## [1,] NA NA
## [2,] NA NA
## [3,] NA NA
## [4,] NA NA
## [5,] NA NA
## [6,] NA NA
## [7,] NA NA
## [8,] NA NA
## [9,] NA NA
## [10,] NA NA
## [11,] NA NA
## [12,] NA NA
## [13,] NA NA
## [14,] NA NA
## [15,] NA NA
## [16,] NA NA
## [17,] NA NA
## [18,] NA NA
## [19,] NA NA
## [20,] NA NA
## [21,] NA NA
## [22,] NA NA
## [23,] NA NA
## [24,] NA NA
## [25,] NA NA
## [26,] NA NA
## [27,] NA NA
## [28,] NA NA
## [29,] NA NA
## [30,] NA NA
## [31,] NA NA
## [32,] NA NA
## [33,] NA NA
## [34,] NA NA
## [35,] NA NA
## [36,] NA NA
## [37,] NA NA
## [38,] NA NA
## [39,] NA NA
## [40,] NA NA
## [41,] NA NA
## [42,] NA NA
## [43,] NA NA
## [44,] NA NA
## [45,] NA NA
## [46,] NA NA
## [47,] NA NA
## [48,] NA NA
## [49,] NA NA
## [50,] NA NA
## [51,] NA NA
## [52,] NA NA
## [53,] NA NA
## [54,] NA NA
## [55,] NA NA
## [56,] NA NA
## [57,] NA NA
## [58,] NA NA
## [59,] NA NA
## [60,] 0.04248265 0.03768918
## [61,] 0.04918436 0.03502229
## [62,] 0.04971010 0.03459274
## [63,] 0.07105093 0.03046468
## [64,] 0.07436125 0.02857395
## [65,] 0.06079157 0.03956668
## [66,] 0.05952938 0.03735004
## [67,] 0.06092575 0.02823740
## [68,] 0.05948049 0.02433502
## [69,] 0.04406403 0.03617223
## [70,] 0.04879693 0.03741424
tail(weight)
## AMZN HAS JNJ MA MNST MSFT
## [174,] -0.04746791 0.1341246 0.5971092 -0.1829207 0.07514950 0.09825748
## [175,] -0.05060838 0.1292616 0.6116818 -0.1712008 0.07331142 0.10873543
## [176,] -0.05536037 0.1436823 0.5768308 -0.1610075 0.08083710 0.09914714
## [177,] -0.05061918 0.1381929 0.5615687 -0.1553686 0.08266347 0.09549654
## [178,] -0.04331664 0.1321348 0.5386311 -0.1591294 0.07824848 0.08660776
## [179,] -0.04016588 0.1311905 0.5316657 -0.1588674 0.06826865 0.08785905
## NFLX VRTX
## [174,] 0.3383856 -0.012637731
## [175,] 0.3612724 -0.062453482
## [176,] 0.3807184 -0.064847947
## [177,] 0.3594550 -0.031388810
## [178,] 0.3737855 -0.006961676
## [179,] 0.3822735 -0.002224169
# Assign minimum variance weights to data_m$weight
capital = 100000
data_m$weight <- data_m$prices
data_m$weight[] <- NA
data_m$weight[] <- weight
data_m$weight[] = (capital / prices) * data_m$weight
models$mvp.hist.cov = bt.run(data_m, type='share')
## Latest weights :
## AMZN HAS JNJ MA MNST MSFT NFLX VRTX
## 2021-03-31 -4.33 13.21 53.86 -15.91 7.82 8.66 37.38 -0.7
##
## Performance summary :
## CAGR Best Worst
## 11 11.5 -10.2
#=================================================================
# CAPM model (single factor model)
#*****************************************************************
# Create Constraints
#*****************************************************************
constraints = new.constraints(N, lb = -Inf, ub = +Inf)
# SUM x.i = 1
constraints = add.constraints(rep(1, N), 1, type = '=', constraints)
#
ret = prices / mlag(prices) - 1
weight_1 = coredata(ret)
weight_1[] = NA
#
# head(data_m$weight)
# compute covariance matrix based on historical 60 months returns
# i = 60
f <- fama_lib_month[dates]/100
for( i in 60:dim(weight_1)[1]) {
hist = ret[ (i- 60 + 1):i, ]
Xi <- hist
fi <- f$Mkt.RF[(i - 60 + 1):i, ]
fiti = lm(formula = Xi ~ fi)
sigF = as.numeric(var(fi))
beta_ = as.matrix(fiti$coefficients)
beta_ = as.matrix(beta_[-1,])
sigeps = crossprod(fiti$residuals)/(T-2)
# sigeps = as.matrix(var(fit$residuals)) # you can use this way too
sigeps = diag(diag(sigeps))
cov_1f = sigF*beta_%*%t(beta_)+sigeps
# cov_1f
ia$cov = cov_1f
weight_1[i, ] = min.risk.portfolio(ia, constraints)
}
dim(weight_1)
## [1] 179 8
# 195 8
head(weight_1, 70)
## AMZN HAS JNJ MA MNST MSFT NFLX
## [1,] NA NA NA NA NA NA NA
## [2,] NA NA NA NA NA NA NA
## [3,] NA NA NA NA NA NA NA
## [4,] NA NA NA NA NA NA NA
## [5,] NA NA NA NA NA NA NA
## [6,] NA NA NA NA NA NA NA
## [7,] NA NA NA NA NA NA NA
## [8,] NA NA NA NA NA NA NA
## [9,] NA NA NA NA NA NA NA
## [10,] NA NA NA NA NA NA NA
## [11,] NA NA NA NA NA NA NA
## [12,] NA NA NA NA NA NA NA
## [13,] NA NA NA NA NA NA NA
## [14,] NA NA NA NA NA NA NA
## [15,] NA NA NA NA NA NA NA
## [16,] NA NA NA NA NA NA NA
## [17,] NA NA NA NA NA NA NA
## [18,] NA NA NA NA NA NA NA
## [19,] NA NA NA NA NA NA NA
## [20,] NA NA NA NA NA NA NA
## [21,] NA NA NA NA NA NA NA
## [22,] NA NA NA NA NA NA NA
## [23,] NA NA NA NA NA NA NA
## [24,] NA NA NA NA NA NA NA
## [25,] NA NA NA NA NA NA NA
## [26,] NA NA NA NA NA NA NA
## [27,] NA NA NA NA NA NA NA
## [28,] NA NA NA NA NA NA NA
## [29,] NA NA NA NA NA NA NA
## [30,] NA NA NA NA NA NA NA
## [31,] NA NA NA NA NA NA NA
## [32,] NA NA NA NA NA NA NA
## [33,] NA NA NA NA NA NA NA
## [34,] NA NA NA NA NA NA NA
## [35,] NA NA NA NA NA NA NA
## [36,] NA NA NA NA NA NA NA
## [37,] NA NA NA NA NA NA NA
## [38,] NA NA NA NA NA NA NA
## [39,] NA NA NA NA NA NA NA
## [40,] NA NA NA NA NA NA NA
## [41,] NA NA NA NA NA NA NA
## [42,] NA NA NA NA NA NA NA
## [43,] NA NA NA NA NA NA NA
## [44,] NA NA NA NA NA NA NA
## [45,] NA NA NA NA NA NA NA
## [46,] NA NA NA NA NA NA NA
## [47,] NA NA NA NA NA NA NA
## [48,] NA NA NA NA NA NA NA
## [49,] NA NA NA NA NA NA NA
## [50,] NA NA NA NA NA NA NA
## [51,] NA NA NA NA NA NA NA
## [52,] NA NA NA NA NA NA NA
## [53,] NA NA NA NA NA NA NA
## [54,] NA NA NA NA NA NA NA
## [55,] NA NA NA NA NA NA NA
## [56,] NA NA NA NA NA NA NA
## [57,] NA NA NA NA NA NA NA
## [58,] NA NA NA NA NA NA NA
## [59,] NA NA NA NA NA NA NA
## [60,] 0.05686594 0.1510929 0.4305811 0.05015941 0.05779332 0.05014609 0.1448397
## [61,] 0.05687191 0.1511282 0.4302659 0.05041776 0.05774930 0.04963676 0.1451084
## [62,] 0.05622834 0.1506700 0.4306342 0.05089247 0.05776042 0.04961835 0.1451982
## [63,] 0.05561291 0.1444594 0.4294557 0.05680025 0.05829546 0.05308205 0.1433751
## [64,] 0.06680349 0.1429472 0.4252998 0.05601470 0.05542776 0.05160215 0.1419638
## [65,] 0.06976960 0.1382716 0.4298696 0.05647285 0.05789554 0.03914050 0.1440393
## [66,] 0.06989978 0.1347698 0.4339531 0.05757943 0.05895068 0.03731231 0.1431713
## [67,] 0.07146909 0.1325493 0.4331714 0.05616649 0.05471233 0.03541899 0.1421959
## [68,] 0.07486064 0.1281545 0.4338631 0.05529816 0.05467167 0.03598601 0.1425410
## [69,] 0.07626443 0.1282828 0.4409171 0.05656702 0.05469353 0.02792388 0.1386400
## [70,] 0.07599612 0.1268518 0.4487767 0.05482404 0.05560280 0.02631219 0.1379022
## VRTX
## [1,] NA
## [2,] NA
## [3,] NA
## [4,] NA
## [5,] NA
## [6,] NA
## [7,] NA
## [8,] NA
## [9,] NA
## [10,] NA
## [11,] NA
## [12,] NA
## [13,] NA
## [14,] NA
## [15,] NA
## [16,] NA
## [17,] NA
## [18,] NA
## [19,] NA
## [20,] NA
## [21,] NA
## [22,] NA
## [23,] NA
## [24,] NA
## [25,] NA
## [26,] NA
## [27,] NA
## [28,] NA
## [29,] NA
## [30,] NA
## [31,] NA
## [32,] NA
## [33,] NA
## [34,] NA
## [35,] NA
## [36,] NA
## [37,] NA
## [38,] NA
## [39,] NA
## [40,] NA
## [41,] NA
## [42,] NA
## [43,] NA
## [44,] NA
## [45,] NA
## [46,] NA
## [47,] NA
## [48,] NA
## [49,] NA
## [50,] NA
## [51,] NA
## [52,] NA
## [53,] NA
## [54,] NA
## [55,] NA
## [56,] NA
## [57,] NA
## [58,] NA
## [59,] NA
## [60,] 0.05852149
## [61,] 0.05882179
## [62,] 0.05899806
## [63,] 0.05891918
## [64,] 0.05994116
## [65,] 0.06454099
## [66,] 0.06436360
## [67,] 0.07431648
## [68,] 0.07462496
## [69,] 0.07671122
## [70,] 0.07373423
tail(weight_1)
## AMZN HAS JNJ MA MNST MSFT
## [174,] 0.09246307 0.09035330 0.2684925 0.08387234 0.06446031 0.04891578
## [175,] 0.09538089 0.08969731 0.2665227 0.08676005 0.06446391 0.05262093
## [176,] 0.09536256 0.09276303 0.2578677 0.08738041 0.06541591 0.05332276
## [177,] 0.09497650 0.09200393 0.2497972 0.09164210 0.07597399 0.05751137
## [178,] 0.09554648 0.09310171 0.2472471 0.09027778 0.07543603 0.05445638
## [179,] 0.09512519 0.09314546 0.2451374 0.08941992 0.07648533 0.05360068
## NFLX VRTX
## [174,] 0.2076641 0.1437786
## [175,] 0.2096846 0.1348697
## [176,] 0.2117629 0.1361247
## [177,] 0.2085731 0.1295218
## [178,] 0.2181206 0.1258139
## [179,] 0.2207411 0.1263448
# Assign minimum variance weights to data_m$weight
capital = 100000
data_m$weight <- data_m$prices
data_m$weight[] <- NA
data_m$weight[] <- weight_1
data_m$weight[] = (capital / prices) * data_m$weight
models$mvp.capm.cov = bt.run(data_m, type='share')
## Latest weights :
## AMZN HAS JNJ MA MNST MSFT NFLX VRTX
## 2021-03-31 9.55 9.31 24.72 9.03 7.54 5.45 21.81 12.58
##
## Performance summary :
## CAGR Best Worst
## 13.9 13.2 -10.4
models$mvp.capm.cov$cagr
## [1] 0.139108
models$mvp.hist.cov$cagr
## [1] 0.1096295
#=================================================================
# FF 3 factor model
#*****************************************************************
# Create Constraints
#*****************************************************************
constraints = new.constraints(N, lb = -Inf, ub = +Inf)
# SUM x.i = 1
constraints = add.constraints(rep(1, N), 1, type = '=', constraints)
#
ret = prices / mlag(prices) - 1
weight_3 = coredata(ret)
weight_3[] = NA
#
# head(data_m$weight)
# compute covariance matrix based on historical 60 months returns
# i = 60
f <- fama_lib_month[dates]/100
for( i in 60:dim(weight_1)[1]) {
hist = ret[ (i- 60 + 1):i, ]
Xi <- hist
fi <- f[(i - 60 + 1):i, ]
fiti = lm(formula = Xi ~ fi)
sigF = as.matrix(var(fi))
beta_ = as.matrix(fiti$coefficients)
beta_ = as.matrix(beta_[-1,])
sigeps = crossprod(fiti$residuals)/(T-4) # note (T - 4)
# sigeps = as.matrix(var(fit$residuals)) # you can use this way too
sigeps = diag(diag(sigeps))
cov_3f = t(beta_)%*% sigF %*% beta_ + sigeps
# cov_1f
ia$cov = cov_3f
weight_3[i, ] = min.risk.portfolio(ia, constraints)
}
dim(weight_3)
## [1] 179 8
# 195 8
head(weight_3, 70)
## AMZN HAS JNJ MA MNST MSFT NFLX
## [1,] NA NA NA NA NA NA NA
## [2,] NA NA NA NA NA NA NA
## [3,] NA NA NA NA NA NA NA
## [4,] NA NA NA NA NA NA NA
## [5,] NA NA NA NA NA NA NA
## [6,] NA NA NA NA NA NA NA
## [7,] NA NA NA NA NA NA NA
## [8,] NA NA NA NA NA NA NA
## [9,] NA NA NA NA NA NA NA
## [10,] NA NA NA NA NA NA NA
## [11,] NA NA NA NA NA NA NA
## [12,] NA NA NA NA NA NA NA
## [13,] NA NA NA NA NA NA NA
## [14,] NA NA NA NA NA NA NA
## [15,] NA NA NA NA NA NA NA
## [16,] NA NA NA NA NA NA NA
## [17,] NA NA NA NA NA NA NA
## [18,] NA NA NA NA NA NA NA
## [19,] NA NA NA NA NA NA NA
## [20,] NA NA NA NA NA NA NA
## [21,] NA NA NA NA NA NA NA
## [22,] NA NA NA NA NA NA NA
## [23,] NA NA NA NA NA NA NA
## [24,] NA NA NA NA NA NA NA
## [25,] NA NA NA NA NA NA NA
## [26,] NA NA NA NA NA NA NA
## [27,] NA NA NA NA NA NA NA
## [28,] NA NA NA NA NA NA NA
## [29,] NA NA NA NA NA NA NA
## [30,] NA NA NA NA NA NA NA
## [31,] NA NA NA NA NA NA NA
## [32,] NA NA NA NA NA NA NA
## [33,] NA NA NA NA NA NA NA
## [34,] NA NA NA NA NA NA NA
## [35,] NA NA NA NA NA NA NA
## [36,] NA NA NA NA NA NA NA
## [37,] NA NA NA NA NA NA NA
## [38,] NA NA NA NA NA NA NA
## [39,] NA NA NA NA NA NA NA
## [40,] NA NA NA NA NA NA NA
## [41,] NA NA NA NA NA NA NA
## [42,] NA NA NA NA NA NA NA
## [43,] NA NA NA NA NA NA NA
## [44,] NA NA NA NA NA NA NA
## [45,] NA NA NA NA NA NA NA
## [46,] NA NA NA NA NA NA NA
## [47,] NA NA NA NA NA NA NA
## [48,] NA NA NA NA NA NA NA
## [49,] NA NA NA NA NA NA NA
## [50,] NA NA NA NA NA NA NA
## [51,] NA NA NA NA NA NA NA
## [52,] NA NA NA NA NA NA NA
## [53,] NA NA NA NA NA NA NA
## [54,] NA NA NA NA NA NA NA
## [55,] NA NA NA NA NA NA NA
## [56,] NA NA NA NA NA NA NA
## [57,] NA NA NA NA NA NA NA
## [58,] NA NA NA NA NA NA NA
## [59,] NA NA NA NA NA NA NA
## [60,] 0.04842715 0.1357863 0.4592521 0.05613880 0.05975124 0.05517867 0.1268433
## [61,] 0.04895882 0.1356565 0.4587749 0.05610711 0.05925775 0.05534075 0.1270160
## [62,] 0.04871341 0.1345362 0.4587999 0.05709223 0.05929200 0.05485767 0.1274504
## [63,] 0.04755795 0.1284438 0.4619051 0.06154855 0.05913337 0.05658082 0.1261895
## [64,] 0.06834662 0.1237107 0.4621842 0.05822498 0.05291668 0.05525798 0.1214689
## [65,] 0.07395036 0.1197986 0.4646616 0.05825459 0.05424676 0.04042605 0.1238027
## [66,] 0.07252312 0.1186421 0.4644371 0.06020387 0.05651412 0.03914572 0.1242230
## [67,] 0.07304868 0.1160514 0.4643233 0.05791766 0.05106528 0.03626438 0.1228793
## [68,] 0.07534593 0.1138328 0.4620345 0.05847413 0.05028882 0.03699772 0.1237610
## [69,] 0.07552435 0.1135430 0.4730067 0.06002339 0.05039039 0.02764751 0.1182869
## [70,] 0.07577531 0.1104433 0.4802681 0.05871723 0.05124038 0.02530697 0.1191462
## VRTX
## [1,] NA
## [2,] NA
## [3,] NA
## [4,] NA
## [5,] NA
## [6,] NA
## [7,] NA
## [8,] NA
## [9,] NA
## [10,] NA
## [11,] NA
## [12,] NA
## [13,] NA
## [14,] NA
## [15,] NA
## [16,] NA
## [17,] NA
## [18,] NA
## [19,] NA
## [20,] NA
## [21,] NA
## [22,] NA
## [23,] NA
## [24,] NA
## [25,] NA
## [26,] NA
## [27,] NA
## [28,] NA
## [29,] NA
## [30,] NA
## [31,] NA
## [32,] NA
## [33,] NA
## [34,] NA
## [35,] NA
## [36,] NA
## [37,] NA
## [38,] NA
## [39,] NA
## [40,] NA
## [41,] NA
## [42,] NA
## [43,] NA
## [44,] NA
## [45,] NA
## [46,] NA
## [47,] NA
## [48,] NA
## [49,] NA
## [50,] NA
## [51,] NA
## [52,] NA
## [53,] NA
## [54,] NA
## [55,] NA
## [56,] NA
## [57,] NA
## [58,] NA
## [59,] NA
## [60,] 0.05862239
## [61,] 0.05888821
## [62,] 0.05925820
## [63,] 0.05864089
## [64,] 0.05788988
## [65,] 0.06485939
## [66,] 0.06431092
## [67,] 0.07844995
## [68,] 0.07926503
## [69,] 0.08157785
## [70,] 0.07910255
tail(weight_3)
## AMZN HAS JNJ MA MNST MSFT
## [174,] 0.09297260 0.08611206 0.2738790 0.08635669 0.06048155 0.04969762
## [175,] 0.09562278 0.08720020 0.2703185 0.08898391 0.06123324 0.05296350
## [176,] 0.09584257 0.09056380 0.2611364 0.08899016 0.06280090 0.05381083
## [177,] 0.09513075 0.08991215 0.2540937 0.09206149 0.07353568 0.05740522
## [178,] 0.09576737 0.09184274 0.2494079 0.09133644 0.07389897 0.05456011
## [179,] 0.09497598 0.09300893 0.2446081 0.09083962 0.07683494 0.05410113
## NFLX VRTX
## [174,] 0.2086505 0.1418501
## [175,] 0.2097610 0.1339168
## [176,] 0.2115070 0.1353484
## [177,] 0.2083110 0.1295499
## [178,] 0.2180522 0.1251343
## [179,] 0.2201700 0.1254614
# Assign minimum variance weights to data_m$weight
capital = 100000
data_m$weight <- data_m$prices
data_m$weight[] <- NA
data_m$weight[] <- weight_3
data_m$weight[] = (capital / prices) * data_m$weight
models$mvp.ff3.cov = bt.run(data_m, type='share')
## Latest weights :
## AMZN HAS JNJ MA MNST MSFT NFLX VRTX
## 2021-03-31 9.58 9.18 24.94 9.13 7.39 5.46 21.81 12.51
##
## Performance summary :
## CAGR Best Worst
## 13.8 13.2 -10.4
#============================================================
# Principal Component Analysis (PCA)
#=============================================================
library(covFactorModel)
X_i <-X[1:60,]
factor_pca <- factorModel(X_i, type = "S", K = 3, max_iter = 10)
cbind(alpha = factor_pca$alpha, beta = factor_pca$beta)
## alpha factor1 factor2 factor3
## AMZN 0.037739835 -0.08360209 0.009611094 -0.009244520
## HAS 0.020044733 -0.03915069 0.013163221 0.005104457
## JNJ 0.005388372 -0.02306895 0.012034167 -0.008177582
## MA 0.038714604 -0.07436711 0.037833409 0.062646553
## MNST 0.015800446 -0.01908231 -0.030757167 0.009161600
## MSFT 0.006234520 -0.04432063 0.019191767 0.010594500
## NFLX 0.047374756 -0.07180474 -0.089119226 -0.004363538
## VRTX 0.015123667 -0.05337934 0.032324795 -0.079211047
#
# Statistical 3-factor model
K <- 3
X_trn <- X_i
T_trn <- dim(X_i)[1]
alpha <- colMeans(X_trn)
X_trn_ <- X_trn - matrix(alpha, T_trn, N, byrow = TRUE)
Sigma_prev <- matrix(0, N, N)
Sigma <- (1/(T_trn-1)) * t(X_trn_) %*% X_trn_
eigSigma <- eigen(Sigma)
while (norm(Sigma - Sigma_prev, "F")/norm(Sigma, "F") > 1e-3) {
B <- eigSigma$vectors[, 1:K] %*% diag(sqrt(eigSigma$values[1:K]), K, K)
Psi <- diag(diag(Sigma - B %*% t(B)))
Sigma_prev <- Sigma
Sigma <- B %*% t(B) + Psi
eigSigma <- eigen(Sigma - Psi)
}
# B: factor loadings
B
## [,1] [,2] [,3]
## [1,] 0.10929581 -0.030483746 0.003133449
## [2,] 0.03879183 -0.009906642 -0.012893169
## [3,] 0.02119561 -0.010404282 0.002155805
## [4,] 0.07268224 -0.023307620 -0.084581828
## [5,] 0.02962411 0.090106764 -0.006842262
## [6,] 0.04416130 -0.008559109 -0.021442576
## [7,] 0.07897783 0.081583122 0.033852929
## [8,] 0.05839933 -0.053151139 0.081089571
# fiti = lm(formula = X_i ~ t(B))
Sigma_PCA3 <- Sigma
Sigma_PCA3
## [,1] [,2] [,3] [,4] [,5]
## [1,] 0.017603623 0.0045013757 0.0026405076 0.0083893351 0.0004695590
## [2,] 0.004501376 0.0058612250 0.0008974926 0.0041409048 0.0003447362
## [3,] 0.002640508 0.0008974926 0.0020597991 0.0016007012 -0.0003243459
## [4,] 0.008389335 0.0041409048 0.0016007012 0.0150401900 0.0006317032
## [5,] 0.000469559 0.0003447362 -0.0003243459 0.0006317032 0.0155581163
## [6,] 0.005020369 0.0020743522 0.0009788509 0.0052228867 0.0006837210
## [7,] 0.006251063 0.0018190079 0.0008981495 0.0009754344 0.0094592080
## [8,] 0.008257138 0.0017464646 0.0019656221 -0.0013752833 -0.0036140853
## [,6] [,7] [,8]
## [1,] 0.0050203694 0.0062510631 0.008257138
## [2,] 0.0020743522 0.0018190079 0.001746465
## [3,] 0.0009788509 0.0008981495 0.001965622
## [4,] 0.0052228867 0.0009754344 -0.001375283
## [5,] 0.0006837210 0.0094592080 -0.003614085
## [6,] 0.0060980190 0.0020635905 0.001295147
## [7,] 0.0020635905 0.0183744713 0.003021136
## [8,] 0.0012951474 0.0030211361 0.015900071
diag(Sigma_PCA3)
## [1] 0.017603623 0.005861225 0.002059799 0.015040190 0.015558116 0.006098019
## [7] 0.018374471 0.015900071
# error
norm(Sigma_PCA3 - cov(X_i), "F")
## [1] 0.01159327
#---------------------------------------------------------------
# By Eric Zivot
# use R princomp() function for principal component analysis
#---------------------------------------------------------------
pc.fit = princomp(X_i)
class(pc.fit)
## [1] "princomp"
names(pc.fit)
## [1] "sdev" "loadings" "center" "scale" "n.obs" "scores" "call"
pc.fit
## Call:
## princomp(x = X_i)
##
## Standard deviations:
## Comp.1 Comp.2 Comp.3 Comp.4 Comp.5 Comp.6 Comp.7
## 0.17643836 0.13794816 0.12370749 0.11255611 0.08953133 0.06534236 0.05699564
## Comp.8
## 0.03493793
##
## 8 variables and 60 observations.
summary(pc.fit)
## Importance of components:
## Comp.1 Comp.2 Comp.3 Comp.4 Comp.5
## Standard deviation 0.1764384 0.1379482 0.1237075 0.1125561 0.08953133
## Proportion of Variance 0.3280788 0.2005506 0.1612813 0.1335151 0.08447772
## Cumulative Proportion 0.3280788 0.5286293 0.6899107 0.8234257 0.90790347
## Comp.6 Comp.7 Comp.8
## Standard deviation 0.06534236 0.05699564 0.03493793
## Proportion of Variance 0.04499682 0.03423540 0.01286431
## Cumulative Proportion 0.95290029 0.98713569 1.00000000
#eigenvalues & eigenvectors
eig.value <- eigen(cov(X_i))$values
pc.fit
## Call:
## princomp(x = X_i)
##
## Standard deviations:
## Comp.1 Comp.2 Comp.3 Comp.4 Comp.5 Comp.6 Comp.7
## 0.17643836 0.13794816 0.12370749 0.11255611 0.08953133 0.06534236 0.05699564
## Comp.8
## 0.03493793
##
## 8 variables and 60 observations.
eig.vec <- eigen(cov(X_i))$vectors
#
B_hat <- eig.vec[, 1:3]%*%diag(sqrt(eig.value[1:3]), 3, 3)
B_hat
## [,1] [,2] [,3]
## [1,] -0.10929581 -0.030483746 0.003133449
## [2,] -0.03879183 -0.009906642 -0.012893169
## [3,] -0.02119561 -0.010404282 0.002155805
## [4,] -0.07268224 -0.023307620 -0.084581828
## [5,] -0.02962411 0.090106764 -0.006842262
## [6,] -0.04416130 -0.008559109 -0.021442576
## [7,] -0.07897783 0.081583122 0.033852929
## [8,] -0.05839933 -0.053151139 0.081089571
#
#
plot(pc.fit)
loadings(pc.fit)
##
## Loadings:
## Comp.1 Comp.2 Comp.3 Comp.4 Comp.5 Comp.6 Comp.7 Comp.8
## AMZN 0.614 0.219 0.186 0.718 0.147
## HAS 0.218 -0.103 -0.101 -0.288 0.764 0.454 0.231
## JNJ 0.119 0.256 -0.952
## MA 0.408 0.168 -0.678 -0.389 -0.423 0.109
## MNST 0.166 -0.648 -0.685 0.201 -0.105 0.171
## MSFT 0.248 -0.172 -0.248 0.314 -0.844 0.179
## NFLX 0.444 -0.586 0.271 0.518 -0.318 -0.125
## VRTX 0.328 0.382 0.650 -0.387 -0.329 -0.249
##
## Comp.1 Comp.2 Comp.3 Comp.4 Comp.5 Comp.6 Comp.7 Comp.8
## SS loadings 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000
## Proportion Var 0.125 0.125 0.125 0.125 0.125 0.125 0.125 0.125
## Cumulative Var 0.125 0.250 0.375 0.500 0.625 0.750 0.875 1.000
pc.fit$loadings[, 1:3]
## Comp.1 Comp.2 Comp.3
## AMZN 0.6142723 0.21913049 0.02511753
## HAS 0.2180206 0.07121327 -0.10335085
## JNJ 0.1191251 0.07479053 0.01728080
## MA 0.4084940 0.16754536 -0.67800274
## MNST 0.1664955 -0.64772681 -0.05484715
## MSFT 0.2481985 0.06152662 -0.17188237
## NFLX 0.4438769 -0.58645514 0.27136300
## VRTX 0.3282202 0.38207362 0.65000903
# pc factors are in the scores component. Note these scores are based on
# centered data
head(pc.fit$scores[, 1:3])
## Comp.1 Comp.2 Comp.3
## 2006-06-30 0.04562732 0.06755789 -0.003999946
## 2006-07-31 -0.39814153 0.07826193 -0.099607154
## 2006-08-31 0.07436684 0.38695527 -0.127339653
## 2006-09-29 0.18331852 -0.12529221 -0.178636022
## 2006-10-31 0.26988699 0.04920042 0.144891876
## 2006-11-30 0.16295140 0.16770275 -0.171682568
pc.fit$scores[, 1:3]
## Comp.1 Comp.2 Comp.3
## 2006-06-30 0.045627319 0.067557891 -0.003999946
## 2006-07-31 -0.398141527 0.078261931 -0.099607154
## 2006-08-31 0.074366836 0.386955268 -0.127339653
## 2006-09-29 0.183318520 -0.125292209 -0.178636022
## 2006-10-31 0.269886987 0.049200420 0.144891876
## 2006-11-30 0.162951400 0.167702749 -0.171682568
## 2006-12-29 -0.162138197 -0.111009282 -0.120590843
## 2007-01-31 -0.076315192 -0.002810830 -0.170678204
## 2007-02-28 -0.156530036 0.017217457 -0.036491478
## 2007-03-30 -0.074197071 -0.088977909 -0.039977776
## 2007-04-30 0.343624393 0.217157013 0.011602793
## 2007-05-31 0.144932574 0.071897250 -0.250327170
## 2007-06-29 -0.105946135 0.023711402 -0.124261516
## 2007-07-31 -0.040207805 0.184896970 0.102077697
## 2007-08-31 -0.027429284 -0.004199007 0.240790002
## 2007-09-28 0.192467578 -0.212801545 -0.019237009
## 2007-10-31 0.197120482 -0.277654356 -0.277360570
## 2007-11-30 -0.259237493 0.248284814 -0.163353995
## 2007-12-31 0.008392794 -0.105650031 -0.059462145
## 2008-01-31 -0.297615527 0.035029859 -0.049075185
## 2008-02-29 -0.175684605 -0.300246815 0.060324018
## 2008-03-31 0.234330487 0.258911642 0.148202495
## 2008-04-30 0.145732269 0.171926944 -0.165274974
## 2008-05-30 -0.004506148 0.195480772 0.003698828
## 2008-06-30 -0.228295855 0.161764204 0.180290271
## 2008-07-31 -0.012882649 0.055318047 0.146336388
## 2008-08-29 -0.067668224 -0.183335297 -0.150108908
## 2008-09-30 -0.172917390 -0.034587810 0.346460649
## 2008-10-31 -0.545658790 0.052010033 -0.026594878
## 2008-11-28 -0.303754659 -0.151846113 -0.034888591
## 2008-12-31 0.286744780 -0.106593362 0.248177861
## 2009-01-30 0.047196534 -0.071133737 0.194715057
## 2009-02-27 -0.012067246 0.017843675 -0.146576046
## 2009-03-31 0.173405677 -0.105240214 -0.048102436
## 2009-04-30 0.135510170 -0.026913534 -0.026343266
## 2009-05-29 -0.188282604 0.133609172 -0.020413133
## 2009-06-30 0.040861816 0.183838909 0.181908369
## 2009-07-31 0.064131809 0.020075204 -0.091778011
## 2009-08-31 -0.041305553 0.003991303 -0.021050290
## 2009-09-30 0.074614372 -0.060712606 0.024359619
## 2009-10-30 0.171040347 -0.034863371 -0.087438896
## 2009-11-30 0.187867393 0.103367572 0.053521044
## 2009-12-31 -0.001488515 0.044982248 -0.004794693
## 2010-01-29 -0.131965427 -0.129561398 0.005032901
## 2010-02-26 -0.047307341 -0.067037389 0.101388762
## 2010-03-31 0.156201898 -0.014748954 -0.055144022
## 2010-04-30 0.070836693 -0.215445677 0.072060797
## 2010-05-28 -0.239705767 -0.085952146 0.120471123
## 2010-06-30 -0.203925251 -0.025351981 -0.010763861
## 2010-07-30 0.025845258 0.045765327 -0.056335333
## 2010-08-31 0.016147461 -0.174176544 0.114591645
## 2010-09-30 0.328572932 -0.069480103 0.010653846
## 2010-10-29 0.105672903 -0.014197225 0.023135044
## 2010-11-30 -0.004752261 -0.162264530 -0.018229748
## 2010-12-31 -0.105135444 0.137354616 0.025684694
## 2011-01-31 0.041614166 -0.135184918 0.100189466
## 2011-02-28 -0.001441982 0.111069651 0.120122107
## 2011-03-31 0.046510814 -0.078779681 0.034525275
## 2011-04-29 0.093966962 0.066147915 0.026152109
## 2011-05-31 0.017010353 -0.135281680 0.014553584
# time series plot of principal component factors
# library(PerformanceAnalytics)
# chart.TimeSeries(pc.fit$scores[, 1, drop=FALSE], colorset="purple")
# compare with direct eigen-value analysis
# notice the sign change on the first set of loadings
eigen.fit = eigen(var(X_i))
names(eigen.fit)
## [1] "values" "vectors"
names(eigen.fit$values) = rownames(eigen.fit$vectors) = colnames(X_i)
cbind(pc.fit$loadings[,1:3], eigen.fit$vectors[, 1:3])
## Comp.1 Comp.2 Comp.3
## AMZN 0.6142723 0.21913049 0.02511753 -0.6142723 -0.21913049 0.02511753
## HAS 0.2180206 0.07121327 -0.10335085 -0.2180206 -0.07121327 -0.10335085
## JNJ 0.1191251 0.07479053 0.01728080 -0.1191251 -0.07479053 0.01728080
## MA 0.4084940 0.16754536 -0.67800274 -0.4084940 -0.16754536 -0.67800274
## MNST 0.1664955 -0.64772681 -0.05484715 -0.1664955 0.64772681 -0.05484715
## MSFT 0.2481985 0.06152662 -0.17188237 -0.2481985 -0.06152662 -0.17188237
## NFLX 0.4438769 -0.58645514 0.27136300 -0.4438769 0.58645514 0.27136300
## VRTX 0.3282202 0.38207362 0.65000903 -0.3282202 -0.38207362 0.65000903
# compute uncentered pc factors from eigenvectors and return data
pc.factors.uc = X_i %*% eigen.fit$vectors
colnames(pc.factors.uc) = paste(colnames(pc.fit$scores),".uc",sep="")
# compare centered and uncentered scores. Note sign change on first factor
# We can treat centered scores as unobservable factor values (F)
cbind(pc.fit$scores[,1,drop=F], -pc.factors.uc[, 1, drop=F])
## Comp.1 Comp.1.uc
## 2006-06-30 0.045627319 1.198071e-01
## 2006-07-31 -0.398141527 -3.239617e-01
## 2006-08-31 0.074366836 1.485467e-01
## 2006-09-29 0.183318520 2.574983e-01
## 2006-10-31 0.269886987 3.440668e-01
## 2006-11-30 0.162951400 2.371312e-01
## 2006-12-29 -0.162138197 -8.795837e-02
## 2007-01-31 -0.076315192 -2.135363e-03
## 2007-02-28 -0.156530036 -8.235021e-02
## 2007-03-30 -0.074197071 -1.724226e-05
## 2007-04-30 0.343624393 4.178042e-01
## 2007-05-31 0.144932574 2.191124e-01
## 2007-06-29 -0.105946135 -3.176631e-02
## 2007-07-31 -0.040207805 3.397202e-02
## 2007-08-31 -0.027429284 4.675054e-02
## 2007-09-28 0.192467578 2.666474e-01
## 2007-10-31 0.197120482 2.713003e-01
## 2007-11-30 -0.259237493 -1.850577e-01
## 2007-12-31 0.008392794 8.257262e-02
## 2008-01-31 -0.297615527 -2.234357e-01
## 2008-02-29 -0.175684605 -1.015048e-01
## 2008-03-31 0.234330487 3.085103e-01
## 2008-04-30 0.145732269 2.199121e-01
## 2008-05-30 -0.004506148 6.967368e-02
## 2008-06-30 -0.228295855 -1.541160e-01
## 2008-07-31 -0.012882649 6.129718e-02
## 2008-08-29 -0.067668224 6.511604e-03
## 2008-09-30 -0.172917390 -9.873756e-02
## 2008-10-31 -0.545658790 -4.714790e-01
## 2008-11-28 -0.303754659 -2.295748e-01
## 2008-12-31 0.286744780 3.609246e-01
## 2009-01-30 0.047196534 1.213764e-01
## 2009-02-27 -0.012067246 6.211258e-02
## 2009-03-31 0.173405677 2.475855e-01
## 2009-04-30 0.135510170 2.096900e-01
## 2009-05-29 -0.188282604 -1.141028e-01
## 2009-06-30 0.040861816 1.150416e-01
## 2009-07-31 0.064131809 1.383116e-01
## 2009-08-31 -0.041305553 3.287428e-02
## 2009-09-30 0.074614372 1.487942e-01
## 2009-10-30 0.171040347 2.452202e-01
## 2009-11-30 0.187867393 2.620472e-01
## 2009-12-31 -0.001488515 7.269131e-02
## 2010-01-29 -0.131965427 -5.778560e-02
## 2010-02-26 -0.047307341 2.687249e-02
## 2010-03-31 0.156201898 2.303817e-01
## 2010-04-30 0.070836693 1.450165e-01
## 2010-05-28 -0.239705767 -1.655259e-01
## 2010-06-30 -0.203925251 -1.297454e-01
## 2010-07-30 0.025845258 1.000251e-01
## 2010-08-31 0.016147461 9.032729e-02
## 2010-09-30 0.328572932 4.027528e-01
## 2010-10-29 0.105672903 1.798527e-01
## 2010-11-30 -0.004752261 6.942757e-02
## 2010-12-31 -0.105135444 -3.095562e-02
## 2011-01-31 0.041614166 1.157940e-01
## 2011-02-28 -0.001441982 7.273785e-02
## 2011-03-31 0.046510814 1.206906e-01
## 2011-04-29 0.093966962 1.681468e-01
## 2011-05-31 0.017010353 9.119018e-02
#
# use first 3 eigen-vectors to compue three factor (with normalization to have pos correlation with market)
# note: cannot treat pc as a portfolio b/c weights do not sum to unity
p3 = pc.fit$loadings[, 1:3]
p3 # refers to B
## Comp.1 Comp.2 Comp.3
## AMZN 0.6142723 0.21913049 0.02511753
## HAS 0.2180206 0.07121327 -0.10335085
## JNJ 0.1191251 0.07479053 0.01728080
## MA 0.4084940 0.16754536 -0.67800274
## MNST 0.1664955 -0.64772681 -0.05484715
## MSFT 0.2481985 0.06152662 -0.17188237
## NFLX 0.4438769 -0.58645514 0.27136300
## VRTX 0.3282202 0.38207362 0.65000903
colSums(p3)
## Comp.1 Comp.2 Comp.3
## 2.54670313 -0.25790205 -0.04431275
# create factor mimicking portfolio by normalizing weights to unity
p3 = p3/colSums(p3)
p3
## Comp.1 Comp.2 Comp.3
## AMZN 0.2412029 -4.94508901 -0.097391758
## HAS -0.8453622 0.02796293 2.332304996
## JNJ -2.6882801 -0.28999587 0.006785559
## MA 0.1604011 -3.78097406 2.628915647
## MNST -0.6455767 -0.25433935 1.237728455
## MSFT -5.6010635 -0.23856583 -0.067492112
## NFLX 0.1742947 13.23445593 -1.052194032
## VRTX -1.2726543 0.15002676 -14.668668093
barplot(p3[,1], horiz=F, main="Factor mimicking weights", col="pink", cex.names = 0.75, las=2)
# create first 3 factors
f3 = X_i %*% p3
head(f3)
## Comp.1 Comp.2 Comp.3
## [1,] -0.19220160 -1.0723932 -0.7730953
## [2,] -0.32397533 -1.5200096 1.4878626
## [3,] -0.29450308 -1.9000210 -0.1139192
## [4,] -0.48393608 0.5779408 1.3702721
## [5,] -0.66017127 1.7272087 -2.8225888
## [6,] -0.08694696 -0.8857004 -0.4915262
head(pc.fit$scores[, 1:3])
## Comp.1 Comp.2 Comp.3
## 2006-06-30 0.04562732 0.06755789 -0.003999946
## 2006-07-31 -0.39814153 0.07826193 -0.099607154
## 2006-08-31 0.07436684 0.38695527 -0.127339653
## 2006-09-29 0.18331852 -0.12529221 -0.178636022
## 2006-10-31 0.26988699 0.04920042 0.144891876
## 2006-11-30 0.16295140 0.16770275 -0.171682568
# chart.TimeSeries(f1, main="First principal component factor", colorset="green")
# estimate factor betas by multivariate regression
n.obs <- dim(X_i)[1]
X.mat = cbind(rep(1, n.obs), f3)
colnames(X.mat) = c("intercept", "Factor 1", "Factor 2", "Factor 3")
XX.mat = crossprod(X.mat)
# multivariate least squares
G.hat = solve(XX.mat)%*%crossprod(X.mat, X_i)
t(G.hat)
## intercept Factor 1 Factor 2 Factor 3
## AMZN 0.033633161 -0.07351432 -0.0079492779 -0.010217222
## HAS 0.014518425 -0.07452909 0.0026532762 0.005809860
## JNJ 0.001978040 -0.04685116 -0.0004155822 -0.001363209
## MA 0.037835912 -0.09858280 -0.0130707619 0.022799102
## MNST 0.004204255 -0.09857632 0.0229773464 0.020257954
## MSFT -0.002083790 -0.13394453 -0.0002948429 0.011803247
## NFLX 0.023346763 -0.06044369 0.0693329756 0.003955469
## VRTX 0.007556629 -0.03241744 -0.0049012245 -0.061724186
# can also use solve(qr(X.mat), returns.mat)
beta.hat = G.hat[2:4,]
beta.hat
## AMZN HAS JNJ MA MNST
## Factor 1 -0.073514322 -0.074529094 -0.0468511563 -0.09858280 -0.09857632
## Factor 2 -0.007949278 0.002653276 -0.0004155822 -0.01307076 0.02297735
## Factor 3 -0.010217222 0.005809860 -0.0013632093 0.02279910 0.02025795
## MSFT NFLX VRTX
## Factor 1 -0.1339445266 -0.060443693 -0.032417440
## Factor 2 -0.0002948429 0.069332976 -0.004901224
## Factor 3 0.0118032473 0.003955469 -0.061724186
B
## [,1] [,2] [,3]
## [1,] 0.10929581 -0.030483746 0.003133449
## [2,] 0.03879183 -0.009906642 -0.012893169
## [3,] 0.02119561 -0.010404282 0.002155805
## [4,] 0.07268224 -0.023307620 -0.084581828
## [5,] 0.02962411 0.090106764 -0.006842262
## [6,] 0.04416130 -0.008559109 -0.021442576
## [7,] 0.07897783 0.081583122 0.033852929
## [8,] 0.05839933 -0.053151139 0.081089571
E.hat = X_i - X.mat%*%G.hat
diagD.hat = diag(crossprod(E.hat)/(n.obs-4))
# compute covariance/correlation matrices with three pc factor
cov.pc3 = t(beta.hat)%*%var(f3)%*%(beta.hat) + diag(diagD.hat)
cov.pc3
## AMZN HAS JNJ MA MNST
## AMZN 0.0183709596 0.0018822098 0.0015848218 0.002128499 0.0009535913
## HAS 0.0018822098 0.0060862053 0.0011124362 0.002151545 0.0019287963
## JNJ 0.0015848218 0.0011124362 0.0021251297 0.001274140 0.0009761364
## MA 0.0021284992 0.0021515450 0.0012741404 0.015601418 0.0021188736
## MNST 0.0009535913 0.0019287963 0.0009761364 0.002118874 0.0161849615
## MSFT 0.0034827756 0.0030067848 0.0020170356 0.004252950 0.0032487444
## NFLX -0.0009199986 0.0008902887 0.0002516180 -0.002642138 0.0049085665
## VRTX 0.0051970799 0.0014497783 0.0020845785 -0.001405968 -0.0011556113
## MSFT NFLX VRTX
## AMZN 0.0034827756 -0.0009199986 0.0051970799
## HAS 0.0030067848 0.0008902887 0.0014497783
## JNJ 0.0020170356 0.0002516180 0.0020845785
## MA 0.0042529504 -0.0026421382 -0.0014059682
## MNST 0.0032487444 0.0049085665 -0.0011556113
## MSFT 0.0061283715 0.0005144678 0.0023391923
## NFLX 0.0005144678 0.0185715836 0.0007272709
## VRTX 0.0023391923 0.0007272709 0.0159231690
Sigma_PCA3
## [,1] [,2] [,3] [,4] [,5]
## [1,] 0.017603623 0.0045013757 0.0026405076 0.0083893351 0.0004695590
## [2,] 0.004501376 0.0058612250 0.0008974926 0.0041409048 0.0003447362
## [3,] 0.002640508 0.0008974926 0.0020597991 0.0016007012 -0.0003243459
## [4,] 0.008389335 0.0041409048 0.0016007012 0.0150401900 0.0006317032
## [5,] 0.000469559 0.0003447362 -0.0003243459 0.0006317032 0.0155581163
## [6,] 0.005020369 0.0020743522 0.0009788509 0.0052228867 0.0006837210
## [7,] 0.006251063 0.0018190079 0.0008981495 0.0009754344 0.0094592080
## [8,] 0.008257138 0.0017464646 0.0019656221 -0.0013752833 -0.0036140853
## [,6] [,7] [,8]
## [1,] 0.0050203694 0.0062510631 0.008257138
## [2,] 0.0020743522 0.0018190079 0.001746465
## [3,] 0.0009788509 0.0008981495 0.001965622
## [4,] 0.0052228867 0.0009754344 -0.001375283
## [5,] 0.0006837210 0.0094592080 -0.003614085
## [6,] 0.0060980190 0.0020635905 0.001295147
## [7,] 0.0020635905 0.0183744713 0.003021136
## [8,] 0.0012951474 0.0030211361 0.015900071
diag(cov.pc3)
## AMZN HAS JNJ MA MNST MSFT
## 0.018370960 0.006086205 0.002125130 0.015601418 0.016184961 0.006128372
## NFLX VRTX
## 0.018571584 0.015923169
# error difference between pca and empirical covariance matrix
norm(cov.pc3 - cov(X_i), "F")
## [1] 0.01382605
norm(Sigma_PCA3 - cov(X_i), "F")
## [1] 0.01159327
#==========================================================
# Plot perfromance
plotbt(models, plotX = T, log = 'y', LeftMargin = 3)
mtext('Cumulative Performance', side = 2, line = 1)
# Plot Strategy Statistics Side by Side
layout(1:1)
plotbt.strategy.sidebyside(models)
# Plot transition maps
layout(1:len(models))
for(m in names(models)) {
plotbt.transition.map(models[[m]]$weight, name=m)
legend('topright', legend = m, bty = 'n')
}
#
```