Final Project: Rerun the coding file ‘final_2021_solution_update.R’ and use the data you collected from the market. Make sure you collect or download data from the market (not restricted to stocks) and try to keep your portfolio including at least 5 assets. Show the performance of MVP (minimum variance portfolio) based on equal weighting, single factor, three factor and PCA models.

#===========================================================
# CLEANING ENVIRONMENT
#===========================================================
rm(list = ls())
  1. Loading the packages needed
#===========================================================
# 1. LOAD PACKAGES
#===========================================================
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)
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)
library(covFactorModel)
library(RColorBrewer)
  1. Importing data of 7 Indonesian Non-cyclical sector stocks from Yahoo
#===========================================================
# 2. IMPORTING DATA_7 INDONESIAN NON-CYCLICAL SECTOR STOCKS
#===========================================================
tickers = spl('UNVR.JK,INDF.JK,GGRM.JK,JPFA.JK,HMSP.JK,MYOR.JK,ULTJ.JK')
datas <- new.env()
getSymbols(tickers, src = 'yahoo', from = '1980-01-01', env = datas, auto.assign = T)
## Warning: INDF.JK contains missing values. Some functions will not work if
## objects contain missing values in the middle of the series. Consider using
## na.omit(), na.approx(), na.fill(), etc to remove or replace them.
## Warning: GGRM.JK contains missing values. Some functions will not work if
## objects contain missing values in the middle of the series. Consider using
## na.omit(), na.approx(), na.fill(), etc to remove or replace them.
## Warning: JPFA.JK contains missing values. Some functions will not work if
## objects contain missing values in the middle of the series. Consider using
## na.omit(), na.approx(), na.fill(), etc to remove or replace them.
## Warning: HMSP.JK contains missing values. Some functions will not work if
## objects contain missing values in the middle of the series. Consider using
## na.omit(), na.approx(), na.fill(), etc to remove or replace them.
## pausing 1 second between requests for more than 5 symbols
## Warning: MYOR.JK contains missing values. Some functions will not work if
## objects contain missing values in the middle of the series. Consider using
## na.omit(), na.approx(), na.fill(), etc to remove or replace them.
## pausing 1 second between requests for more than 5 symbols
## Warning: ULTJ.JK contains missing values. Some functions will not work if
## objects contain missing values in the middle of the series. Consider using
## na.omit(), na.approx(), na.fill(), etc to remove or replace them.
## pausing 1 second between requests for more than 5 symbols
## [1] "UNVR.JK" "INDF.JK" "GGRM.JK" "JPFA.JK" "HMSP.JK" "MYOR.JK" "ULTJ.JK"
for(i in ls(datas)) datas[[i]] = adjustOHLC(datas[[i]], use.Adjusted=T)
names(datas$UNVR.JK)
## [1] "UNVR.JK.Open"     "UNVR.JK.High"     "UNVR.JK.Low"      "UNVR.JK.Close"   
## [5] "UNVR.JK.Volume"   "UNVR.JK.Adjusted"
head(datas$UNVR.JK)
##            UNVR.JK.Open UNVR.JK.High UNVR.JK.Low UNVR.JK.Close UNVR.JK.Volume
## 2003-09-03     354.3524     388.9234    348.5906      388.9234       43162500
## 2003-09-04     397.5661     432.1371    388.9234      394.6852       82850000
## 2003-09-05     394.6852     403.3279    391.8043      397.5661       24055000
## 2003-09-08     397.5662     397.5662    383.1616      391.8044       18007500
## 2003-09-09     391.8043     391.8043    380.2806      383.1616       14075000
## 2003-09-10     380.2807     380.2807    368.7570      368.7570       14190000
##            UNVR.JK.Adjusted
## 2003-09-03         388.9234
## 2003-09-04         394.6852
## 2003-09-05         397.5661
## 2003-09-08         391.8044
## 2003-09-09         383.1616
## 2003-09-10         368.7570
#Data Preparation
bt.prep(datas, align='remove.na')
names(datas)
##  [1] "prices"          "UNVR.JK"         "MYOR.JK"         "dates"          
##  [5] "weight"          ".getSymbols"     "symbolnames"     "execution.price"
##  [9] "JPFA.JK"         "GGRM.JK"         "HMSP.JK"         "ULTJ.JK"        
## [13] "INDF.JK"
#Data Checking
head(datas$HMSP.JK)
##            HMSP.JK.Open HMSP.JK.High HMSP.JK.Low HMSP.JK.Close HMSP.JK.Volume
## 2005-09-29     151.9392     152.8329    151.9392      151.9392        2627165
## 2005-09-30     155.5142     156.4079    151.9391      155.5142       19650667
## 2005-10-03     155.5142     155.5142    151.9391      155.5142         159222
## 2005-10-04     154.6204     155.5142    154.6204      154.6204        1831054
## 2005-10-05     151.9392     153.7267    151.9392      151.9392        1074749
## 2005-10-06     153.7266     153.7266    153.7266      153.7266          66342
##            HMSP.JK.Adjusted
## 2005-09-29         151.9392
## 2005-09-30         155.5142
## 2005-10-03         155.5142
## 2005-10-04         154.6204
## 2005-10-05         151.9392
## 2005-10-06         153.7266
head(datas$prices)
##             GGRM.JK  HMSP.JK  INDF.JK  JPFA.JK  MYOR.JK  ULTJ.JK  UNVR.JK
## 2005-09-29 7249.801 151.9392 475.9389 31.37117 17.88706 58.47855 522.6602
## 2005-09-30 7350.961 155.5142 496.3361 31.37117 18.16654 58.47855 525.8865
## 2005-10-03 7418.402 155.5142 469.1397 31.37117 17.88706 58.47855 542.0180
## 2005-10-04 7587.000 154.6204 496.3361 31.37117 19.56397 59.64812 564.6020
## 2005-10-05 7620.721 151.9392 496.3361 31.37117 19.84346 59.64812 554.9231
## 2005-10-06 7418.402 153.7266 475.9389 32.83030 19.28448 63.15683 574.2809
  1. Calculating the monthly prices & returns of the imported data
#===========================================================
# 3. CALCULATING MONTHLY PRICES & RETURNS
#===========================================================
#Convert daily prices into monthly prices
prices_monthly <- to.monthly(datas$prices, indexAt = "last", OHLC = FALSE) # indexAt = 'endof'
## Warning in to.period(x, "months", indexAt = indexAt, name = name, ...): missing
## values removed from data
head(prices_monthly)
##             GGRM.JK  HMSP.JK  INDF.JK  JPFA.JK  MYOR.JK  ULTJ.JK  UNVR.JK
## 2005-09-30 7350.961 155.5142 496.3361 31.37117 18.16654 58.47855 525.8865
## 2005-10-31 6878.881 162.7312 557.5283 35.74855 17.88706 59.64812 564.6020
## 2005-11-30 7384.679 160.8714 577.9257 34.28942 16.48963 58.47855 558.1495
## 2005-12-30 7856.762 165.5209 618.7205 35.74855 22.91779 72.51341 559.3682
## 2006-01-31 7283.522 157.1518 598.3231 38.66680 23.47676 63.15683 562.6393
## 2006-02-28 7418.402 158.0818 571.1265 40.12592 20.40243 59.64812 559.3682
#Convert monthly prices into monthly return
monthly.ret <- na.omit(Return.calculate(prices_monthly, method = "discrete"))
head(monthly.ret)
##                GGRM.JK      HMSP.JK     INDF.JK     JPFA.JK     MYOR.JK
## 2005-10-31 -0.06422012  0.046407710  0.12328789  0.13953517 -0.01538476
## 2005-11-30  0.07352908 -0.011428483  0.03658541 -0.04081637 -0.07812499
## 2005-12-30  0.06392729  0.028901711  0.07058831  0.04255324  0.38983052
## 2006-01-31 -0.07296133 -0.050561982 -0.03296716  0.08163272  0.02439022
## 2006-02-28  0.01851856  0.005917411 -0.04545460  0.03773568 -0.13095226
## 2006-03-31 -0.04545462 -0.023529525  0.05952377  0.00000000  0.06849303
##                ULTJ.JK      UNVR.JK
## 2005-10-31  0.02000007  0.073619530
## 2005-11-30 -0.01960791 -0.011428431
## 2005-12-30  0.24000014  0.002183555
## 2006-01-31 -0.12903229  0.005847770
## 2006-02-28 -0.05555556 -0.005813773
## 2006-03-31  0.07843117 -0.005847880
  1. Importing Fama French factors before conducting the three factors model
#===========================================================
# 4. FAMA FRENCH FACTORS
#===========================================================
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
#*****************************************************************
# In this case we will use data from 2005-01 to 2021-05
#*****************************************************************
dates <- '2005-01::2021-05'
X <- monthly.ret[dates]
head(X)
##                GGRM.JK      HMSP.JK     INDF.JK     JPFA.JK     MYOR.JK
## 2005-10-31 -0.06422012  0.046407710  0.12328789  0.13953517 -0.01538476
## 2005-11-30  0.07352908 -0.011428483  0.03658541 -0.04081637 -0.07812499
## 2005-12-30  0.06392729  0.028901711  0.07058831  0.04255324  0.38983052
## 2006-01-31 -0.07296133 -0.050561982 -0.03296716  0.08163272  0.02439022
## 2006-02-28  0.01851856  0.005917411 -0.04545460  0.03773568 -0.13095226
## 2006-03-31 -0.04545462 -0.023529525  0.05952377  0.00000000  0.06849303
##                ULTJ.JK      UNVR.JK
## 2005-10-31  0.02000007  0.073619530
## 2005-11-30 -0.01960791 -0.011428431
## 2005-12-30  0.24000014  0.002183555
## 2006-01-31 -0.12903229  0.005847770
## 2006-02-28 -0.05555556 -0.005813773
## 2006-03-31  0.07843117 -0.005847880
dim(X)
## [1] 188   7
#Convert daily prices into monthly prices
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] 196   3
  1. Computing estimated coefficients in 3 ways
#=============================================================================
# 5. COMPUTING ESTIMATED COEFFICIENTS
#=============================================================================
#****************************************************************************
# First Way: Based on CAPM Model, Computing Covariance Matrix for the 7-stocks 
# Portfolio Using Past 84-month Returns from 2013/01 to 2019/12.
# The first approach is using covFactorModel package.
#****************************************************************************
insample_range <- '2013-01::2019-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
## GGRM.JK 0.004313663  0.2195276
## HMSP.JK 0.004235259 -0.4012193
## INDF.JK 0.008618843  1.1827043
## JPFA.JK 0.015389381  1.1988523
## MYOR.JK 0.016557086 -1.6554832
## ULTJ.JK 0.024315814 -0.6525357
## UNVR.JK 0.011233395 -1.8496954
#***************************************************************************************
#Instead of using package, we can also use matrix notation to compute covariance matrix
#***************************************************************************************
F_ <- cbind(ones = 1, f$Mkt.RF[insample_range])
Gamma <- t(X[insample_range]) %*% F_ %*% solve(t(F_) %*% F_)  
colnames(Gamma) <- c("alpha", "beta")
alpha <- Gamma[, 1]  
beta <- Gamma[, 2]   
print(Gamma)
##               alpha       beta
## GGRM.JK 0.004313663  0.2195276
## HMSP.JK 0.004235259 -0.4012193
## INDF.JK 0.008618843  1.1827043
## JPFA.JK 0.015389381  1.1988523
## MYOR.JK 0.016557086 -1.6554832
## ULTJ.JK 0.024315814 -0.6525357
## UNVR.JK 0.011233395 -1.8496954
#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
##               GGRM.JK       HMSP.JK       INDF.JK       JPFA.JK       MYOR.JK
## GGRM.JK  5.478408e-03 -4.897683e-06  1.443727e-05  1.463439e-05 -2.020848e-05
## HMSP.JK -4.897683e-06  5.678143e-03 -2.638625e-05 -2.674652e-05  3.693400e-05
## INDF.JK  1.443727e-05 -2.638625e-05  4.735230e-03  7.884273e-05 -1.088731e-04
## JPFA.JK  1.463439e-05 -2.674652e-05  7.884273e-05  2.183516e-02 -1.103596e-04
## MYOR.JK -2.020848e-05  3.693400e-05 -1.088731e-04 -1.103596e-04  6.738179e-03
## ULTJ.JK -7.965502e-06  1.455814e-05 -4.291413e-05 -4.350005e-05  6.006879e-05
## UNVR.JK -2.257923e-05  4.126689e-05 -1.216455e-04 -1.233064e-04  1.702726e-04
##               ULTJ.JK       UNVR.JK
## GGRM.JK -7.965502e-06 -2.257923e-05
## HMSP.JK  1.455814e-05  4.126689e-05
## INDF.JK -4.291413e-05 -1.216455e-04
## JPFA.JK -4.350005e-05 -1.233064e-04
## MYOR.JK  6.006879e-05  1.702726e-04
## ULTJ.JK  1.108788e-02  6.711573e-05
## UNVR.JK  6.711573e-05  3.404555e-03
#****************************************************************************
#Second way : Using lm() function 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]
## GGRM.JK  0.2195276
## HMSP.JK -0.4012193
## INDF.JK  1.1827043
## JPFA.JK  1.1988523
## MYOR.JK -1.6554832
## ULTJ.JK -0.6525357
## UNVR.JK -1.8496954
sigeps = crossprod(fit$residuals)/(T-2)
sigeps = diag(diag(sigeps))
sigeps
##             [,1]        [,2]        [,3]       [,4]        [,5]      [,6]
## [1,] 0.005475728 0.000000000 0.000000000 0.00000000 0.000000000 0.0000000
## [2,] 0.000000000 0.005669191 0.000000000 0.00000000 0.000000000 0.0000000
## [3,] 0.000000000 0.000000000 0.004657449 0.00000000 0.000000000 0.0000000
## [4,] 0.000000000 0.000000000 0.000000000 0.02175524 0.000000000 0.0000000
## [5,] 0.000000000 0.000000000 0.000000000 0.00000000 0.006585785 0.0000000
## [6,] 0.000000000 0.000000000 0.000000000 0.00000000 0.000000000 0.0110642
## [7,] 0.000000000 0.000000000 0.000000000 0.00000000 0.000000000 0.0000000
##             [,7]
## [1,] 0.000000000
## [2,] 0.000000000
## [3,] 0.000000000
## [4,] 0.000000000
## [5,] 0.000000000
## [6,] 0.000000000
## [7,] 0.003214307
cov_1f = sigF*beta_%*%t(beta_)+sigeps
cov_1f # This is covariance matrix computed from single factor model (from lm())
##               GGRM.JK       HMSP.JK       INDF.JK       JPFA.JK       MYOR.JK
## GGRM.JK  5.478408e-03 -4.897683e-06  1.443727e-05  1.463439e-05 -2.020848e-05
## HMSP.JK -4.897683e-06  5.678143e-03 -2.638625e-05 -2.674652e-05  3.693400e-05
## INDF.JK  1.443727e-05 -2.638625e-05  4.735230e-03  7.884273e-05 -1.088731e-04
## JPFA.JK  1.463439e-05 -2.674652e-05  7.884273e-05  2.183516e-02 -1.103596e-04
## MYOR.JK -2.020848e-05  3.693400e-05 -1.088731e-04 -1.103596e-04  6.738179e-03
## ULTJ.JK -7.965502e-06  1.455814e-05 -4.291413e-05 -4.350005e-05  6.006879e-05
## UNVR.JK -2.257923e-05  4.126689e-05 -1.216455e-04 -1.233064e-04  1.702726e-04
##               ULTJ.JK       UNVR.JK
## GGRM.JK -7.965502e-06 -2.257923e-05
## HMSP.JK  1.455814e-05  4.126689e-05
## INDF.JK -4.291413e-05 -1.216455e-04
## JPFA.JK -4.350005e-05 -1.233064e-04
## MYOR.JK  6.006879e-05  1.702726e-04
## ULTJ.JK  1.108788e-02  6.711573e-05
## UNVR.JK  6.711573e-05  3.404555e-03
  1. Backtesting portfolio using SIT package
#===========================================================
# 6. BACKTESTING PORTFOLIO_SIT PACKAGE
#===========================================================
dates <- '2005-01::2021-05'
X <- monthly.ret[dates]
head(X)
##                GGRM.JK      HMSP.JK     INDF.JK     JPFA.JK     MYOR.JK
## 2005-10-31 -0.06422012  0.046407710  0.12328789  0.13953517 -0.01538476
## 2005-11-30  0.07352908 -0.011428483  0.03658541 -0.04081637 -0.07812499
## 2005-12-30  0.06392729  0.028901711  0.07058831  0.04255324  0.38983052
## 2006-01-31 -0.07296133 -0.050561982 -0.03296716  0.08163272  0.02439022
## 2006-02-28  0.01851856  0.005917411 -0.04545460  0.03773568 -0.13095226
## 2006-03-31 -0.04545462 -0.023529525  0.05952377  0.00000000  0.06849303
##                ULTJ.JK      UNVR.JK
## 2005-10-31  0.02000007  0.073619530
## 2005-11-30 -0.01960791 -0.011428431
## 2005-12-30  0.24000014  0.002183555
## 2006-01-31 -0.12903229  0.005847770
## 2006-02-28 -0.05555556 -0.005813773
## 2006-03-31  0.07843117 -0.005847880
dim(X)
## [1] 188   7
tail(X)
##                 GGRM.JK     HMSP.JK     INDF.JK     JPFA.JK     MYOR.JK
## 2020-12-30 -0.029585799 -0.01311475 -0.03521127  0.09737833  0.13865546
## 2021-01-29 -0.079878049 -0.12956809 -0.11678832 -0.07167239  0.02952030
## 2021-02-26 -0.032471836  0.01908401  0.00000000  0.12867645 -0.02867384
## 2021-03-31 -0.008904110  0.02996253  0.09090909  0.25081439 -0.03321033
## 2021-04-30 -0.002073255 -0.04000003 -0.01136364  0.11959599 -0.06106870
## 2021-05-31 -0.081717452 -0.03787877 -0.02681992 -0.05687204  0.03252033
##                 ULTJ.JK     UNVR.JK
## 2020-12-30 -0.006211180 -0.03770626
## 2021-01-29 -0.056250000 -0.05782312
## 2021-02-26  0.003311258  0.01083030
## 2021-03-31  0.000000000 -0.06071427
## 2021-04-30  0.062706271 -0.08745248
## 2021-05-31 -0.046583851 -0.02499995
#Convert daily prices to the monthly prices at the expected date
prices_monthly <- to.monthly(datas$prices, indexAt = "last", OHLC = FALSE) # indexAt = 'endof'
## Warning in to.period(x, "months", indexAt = indexAt, name = name, ...): missing
## values removed from data
head(prices_monthly)
##             GGRM.JK  HMSP.JK  INDF.JK  JPFA.JK  MYOR.JK  ULTJ.JK  UNVR.JK
## 2005-09-30 7350.961 155.5142 496.3361 31.37117 18.16654 58.47855 525.8865
## 2005-10-31 6878.881 162.7312 557.5283 35.74855 17.88706 59.64812 564.6020
## 2005-11-30 7384.679 160.8714 577.9257 34.28942 16.48963 58.47855 558.1495
## 2005-12-30 7856.762 165.5209 618.7205 35.74855 22.91779 72.51341 559.3682
## 2006-01-31 7283.522 157.1518 598.3231 38.66680 23.47676 63.15683 562.6393
## 2006-02-28 7418.402 158.0818 571.1265 40.12592 20.40243 59.64812 559.3682
prices_monthly <- prices_monthly[dates]
head(prices_monthly)
##             GGRM.JK  HMSP.JK  INDF.JK  JPFA.JK  MYOR.JK  ULTJ.JK  UNVR.JK
## 2005-09-30 7350.961 155.5142 496.3361 31.37117 18.16654 58.47855 525.8865
## 2005-10-31 6878.881 162.7312 557.5283 35.74855 17.88706 59.64812 564.6020
## 2005-11-30 7384.679 160.8714 577.9257 34.28942 16.48963 58.47855 558.1495
## 2005-12-30 7856.762 165.5209 618.7205 35.74855 22.91779 72.51341 559.3682
## 2006-01-31 7283.522 157.1518 598.3231 38.66680 23.47676 63.15683 562.6393
## 2006-02-28 7418.402 158.0818 571.1265 40.12592 20.40243 59.64812 559.3682
tail(prices_monthly)
##            GGRM.JK  HMSP.JK INDF.JK  JPFA.JK MYOR.JK ULTJ.JK  UNVR.JK
## 2020-12-30   41000 1422.310    6850 1437.995    2710    1600 7219.333
## 2021-01-29   37725 1238.024    6050 1334.931    2790    1510 6801.889
## 2021-02-26   36500 1261.651    6050 1506.705    2710    1515 6875.555
## 2021-03-31   36175 1299.453    6600 1884.608    2620    1515 6458.111
## 2021-04-30   36100 1247.475    6525 2110.000    2460    1610 5893.333
## 2021-05-31   33150 1200.222    6350 1990.000    2540    1535 5746.000
#*****************************************************************
# 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] "ULTJ.JK" "MYOR.JK" "HMSP.JK" "JPFA.JK" "GGRM.JK" "INDF.JK" "UNVR.JK"
# Check if the column name is 'Close'
head(data_m$UNVR.JK)
##               Close
## 2005-09-30 7350.961
## 2005-10-31 6878.881
## 2005-11-30 7384.679
## 2005-12-30 7856.762
## 2006-01-31 7283.522
## 2006-02-28 7418.402
#
bt.prep(data_m, align='remove.na', dates = dates)
names(data_m)
##  [1] "prices"          "execution.price" "weight"          "dates"          
##  [5] "symbolnames"     "ULTJ.JK"         "MYOR.JK"         "HMSP.JK"        
##  [9] "JPFA.JK"         "GGRM.JK"         "INDF.JK"         "UNVR.JK"
  1. Calculating MVP based on based on equal weighting, CAPM (single factor), Fama French (three factors), and PCA models.
#===========================================================
# 7. CALCULATING MINIMUM VARIANCE PORTFOLIO (MVP)
#===========================================================
#===========================================================
# a. 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)
##              GGRM.JK   HMSP.JK   INDF.JK   JPFA.JK   MYOR.JK   ULTJ.JK
## 2005-09-30 0.1428571 0.1428571 0.1428571 0.1428571 0.1428571 0.1428571
## 2005-10-31 0.1428571 0.1428571 0.1428571 0.1428571 0.1428571 0.1428571
## 2005-11-30 0.1428571 0.1428571 0.1428571 0.1428571 0.1428571 0.1428571
## 2005-12-30 0.1428571 0.1428571 0.1428571 0.1428571 0.1428571 0.1428571
## 2006-01-31 0.1428571 0.1428571 0.1428571 0.1428571 0.1428571 0.1428571
## 2006-02-28 0.1428571 0.1428571 0.1428571 0.1428571 0.1428571 0.1428571
##              UNVR.JK
## 2005-09-30 0.1428571
## 2005-10-31 0.1428571
## 2005-11-30 0.1428571
## 2005-12-30 0.1428571
## 2006-01-31 0.1428571
## 2006-02-28 0.1428571
data_m$weight[1:83, ] <- NA
models$equal.weight = bt.run.share(data_m)
## Latest weights :
##            GGRM.JK HMSP.JK INDF.JK JPFA.JK MYOR.JK ULTJ.JK UNVR.JK
## 2021-05-31    8.74   21.27    5.07   16.77   35.62    7.58    4.95
## 
## Performance summary :
##  CAGR    Best    Worst   
##  5.9 14.2    -10.9   
head(models$equal.weight$ret, 86)
##               GGRM.JK
## 2005-09-30 0.00000000
## 2005-10-31 0.00000000
## 2005-11-30 0.00000000
## 2005-12-30 0.00000000
## 2006-01-31 0.00000000
## 2006-02-28 0.00000000
## 2006-03-31 0.00000000
## 2006-04-28 0.00000000
## 2006-05-31 0.00000000
## 2006-06-30 0.00000000
## 2006-07-31 0.00000000
## 2006-08-31 0.00000000
## 2006-09-29 0.00000000
## 2006-10-31 0.00000000
## 2006-11-30 0.00000000
## 2006-12-28 0.00000000
## 2007-01-31 0.00000000
## 2007-02-28 0.00000000
## 2007-03-30 0.00000000
## 2007-04-30 0.00000000
## 2007-05-31 0.00000000
## 2007-06-29 0.00000000
## 2007-07-31 0.00000000
## 2007-08-31 0.00000000
## 2007-09-28 0.00000000
## 2007-10-31 0.00000000
## 2007-11-30 0.00000000
## 2007-12-31 0.00000000
## 2008-01-31 0.00000000
## 2008-02-29 0.00000000
## 2008-03-31 0.00000000
## 2008-04-30 0.00000000
## 2008-05-30 0.00000000
## 2008-06-30 0.00000000
## 2008-07-29 0.00000000
## 2008-08-29 0.00000000
## 2008-09-26 0.00000000
## 2008-10-31 0.00000000
## 2008-11-28 0.00000000
## 2008-12-31 0.00000000
## 2009-01-30 0.00000000
## 2009-02-27 0.00000000
## 2009-03-31 0.00000000
## 2009-04-30 0.00000000
## 2009-05-29 0.00000000
## 2009-06-30 0.00000000
## 2009-07-31 0.00000000
## 2009-08-31 0.00000000
## 2009-09-30 0.00000000
## 2009-10-30 0.00000000
## 2009-11-30 0.00000000
## 2009-12-30 0.00000000
## 2010-01-29 0.00000000
## 2010-02-25 0.00000000
## 2010-03-31 0.00000000
## 2010-04-30 0.00000000
## 2010-05-31 0.00000000
## 2010-06-30 0.00000000
## 2010-07-30 0.00000000
## 2010-08-31 0.00000000
## 2010-09-30 0.00000000
## 2010-10-29 0.00000000
## 2010-11-30 0.00000000
## 2010-12-30 0.00000000
## 2011-01-31 0.00000000
## 2011-02-28 0.00000000
## 2011-03-31 0.00000000
## 2011-04-29 0.00000000
## 2011-05-31 0.00000000
## 2011-06-30 0.00000000
## 2011-07-29 0.00000000
## 2011-08-26 0.00000000
## 2011-09-30 0.00000000
## 2011-10-31 0.00000000
## 2011-11-30 0.00000000
## 2011-12-30 0.00000000
## 2012-01-31 0.00000000
## 2012-02-29 0.00000000
## 2012-03-30 0.00000000
## 2012-04-30 0.00000000
## 2012-05-31 0.00000000
## 2012-06-29 0.00000000
## 2012-07-31 0.00000000
## 2012-08-31 0.00000000
## 2012-09-28 0.02360928
## 2012-10-31 0.04232746
# 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 :
##            GGRM.JK HMSP.JK INDF.JK JPFA.JK MYOR.JK ULTJ.JK UNVR.JK
## 2021-05-31   14.29   14.29   14.29   14.29   14.29   14.29   14.29
## 
## Performance summary :
##  CAGR    Best    Worst   
##  6.1 12  -10.7   
head(models$equal.weight.share$ret, 86)
##               GGRM.JK
## 2005-09-30 0.00000000
## 2005-10-31 0.00000000
## 2005-11-30 0.00000000
## 2005-12-30 0.00000000
## 2006-01-31 0.00000000
## 2006-02-28 0.00000000
## 2006-03-31 0.00000000
## 2006-04-28 0.00000000
## 2006-05-31 0.00000000
## 2006-06-30 0.00000000
## 2006-07-31 0.00000000
## 2006-08-31 0.00000000
## 2006-09-29 0.00000000
## 2006-10-31 0.00000000
## 2006-11-30 0.00000000
## 2006-12-28 0.00000000
## 2007-01-31 0.00000000
## 2007-02-28 0.00000000
## 2007-03-30 0.00000000
## 2007-04-30 0.00000000
## 2007-05-31 0.00000000
## 2007-06-29 0.00000000
## 2007-07-31 0.00000000
## 2007-08-31 0.00000000
## 2007-09-28 0.00000000
## 2007-10-31 0.00000000
## 2007-11-30 0.00000000
## 2007-12-31 0.00000000
## 2008-01-31 0.00000000
## 2008-02-29 0.00000000
## 2008-03-31 0.00000000
## 2008-04-30 0.00000000
## 2008-05-30 0.00000000
## 2008-06-30 0.00000000
## 2008-07-29 0.00000000
## 2008-08-29 0.00000000
## 2008-09-26 0.00000000
## 2008-10-31 0.00000000
## 2008-11-28 0.00000000
## 2008-12-31 0.00000000
## 2009-01-30 0.00000000
## 2009-02-27 0.00000000
## 2009-03-31 0.00000000
## 2009-04-30 0.00000000
## 2009-05-29 0.00000000
## 2009-06-30 0.00000000
## 2009-07-31 0.00000000
## 2009-08-31 0.00000000
## 2009-09-30 0.00000000
## 2009-10-30 0.00000000
## 2009-11-30 0.00000000
## 2009-12-30 0.00000000
## 2010-01-29 0.00000000
## 2010-02-25 0.00000000
## 2010-03-31 0.00000000
## 2010-04-30 0.00000000
## 2010-05-31 0.00000000
## 2010-06-30 0.00000000
## 2010-07-30 0.00000000
## 2010-08-31 0.00000000
## 2010-09-30 0.00000000
## 2010-10-29 0.00000000
## 2010-11-30 0.00000000
## 2010-12-30 0.00000000
## 2011-01-31 0.00000000
## 2011-02-28 0.00000000
## 2011-03-31 0.00000000
## 2011-04-29 0.00000000
## 2011-05-31 0.00000000
## 2011-06-30 0.00000000
## 2011-07-29 0.00000000
## 2011-08-26 0.00000000
## 2011-09-30 0.00000000
## 2011-10-31 0.00000000
## 2011-11-30 0.00000000
## 2011-12-30 0.00000000
## 2012-01-31 0.00000000
## 2012-02-29 0.00000000
## 2012-03-30 0.00000000
## 2012-04-30 0.00000000
## 2012-05-31 0.00000000
## 2012-06-29 0.00000000
## 2012-07-31 0.00000000
## 2012-08-31 0.00000000
## 2012-09-28 0.02360928
## 2012-10-31 0.04169903
head(models$equal.weight$ret)
##            GGRM.JK
## 2005-09-30       0
## 2005-10-31       0
## 2005-11-30       0
## 2005-12-30       0
## 2006-01-31       0
## 2006-02-28       0
#*****************************************************************
# 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 = 84
# 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 = 84
for( i in 84:dim(weight)[1]) {
  hist = ret[ (i- 84 + 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] 189   7
head(weight, 90)
##          GGRM.JK    HMSP.JK   INDF.JK      JPFA.JK    MYOR.JK   ULTJ.JK
##  [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,]         NA         NA        NA           NA         NA        NA
## [61,]         NA         NA        NA           NA         NA        NA
## [62,]         NA         NA        NA           NA         NA        NA
## [63,]         NA         NA        NA           NA         NA        NA
## [64,]         NA         NA        NA           NA         NA        NA
## [65,]         NA         NA        NA           NA         NA        NA
## [66,]         NA         NA        NA           NA         NA        NA
## [67,]         NA         NA        NA           NA         NA        NA
## [68,]         NA         NA        NA           NA         NA        NA
## [69,]         NA         NA        NA           NA         NA        NA
## [70,]         NA         NA        NA           NA         NA        NA
## [71,]         NA         NA        NA           NA         NA        NA
## [72,]         NA         NA        NA           NA         NA        NA
## [73,]         NA         NA        NA           NA         NA        NA
## [74,]         NA         NA        NA           NA         NA        NA
## [75,]         NA         NA        NA           NA         NA        NA
## [76,]         NA         NA        NA           NA         NA        NA
## [77,]         NA         NA        NA           NA         NA        NA
## [78,]         NA         NA        NA           NA         NA        NA
## [79,]         NA         NA        NA           NA         NA        NA
## [80,]         NA         NA        NA           NA         NA        NA
## [81,]         NA         NA        NA           NA         NA        NA
## [82,]         NA         NA        NA           NA         NA        NA
## [83,]         NA         NA        NA           NA         NA        NA
## [84,] 0.05589156 0.01591301 0.3246627 -0.013006255 0.02859097 0.5062156
## [85,] 0.05847307 0.01962355 0.3266480 -0.013353038 0.02987714 0.5021791
## [86,] 0.06180055 0.01674760 0.3264893 -0.012456929 0.02991491 0.5040421
## [87,] 0.05976579 0.02157313 0.3282562 -0.012163659 0.02993290 0.5029061
## [88,] 0.05612153 0.02355748 0.3423882 -0.006194351 0.03170148 0.4716754
## [89,] 0.05597230 0.02389361 0.3424201 -0.009048950 0.03303158 0.4669915
## [90,] 0.04914426 0.02209458 0.3336246 -0.010966224 0.03508294 0.4717945
##          UNVR.JK
##  [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,]         NA
## [61,]         NA
## [62,]         NA
## [63,]         NA
## [64,]         NA
## [65,]         NA
## [66,]         NA
## [67,]         NA
## [68,]         NA
## [69,]         NA
## [70,]         NA
## [71,]         NA
## [72,]         NA
## [73,]         NA
## [74,]         NA
## [75,]         NA
## [76,]         NA
## [77,]         NA
## [78,]         NA
## [79,]         NA
## [80,]         NA
## [81,]         NA
## [82,]         NA
## [83,]         NA
## [84,] 0.08173233
## [85,] 0.07655218
## [86,] 0.07346246
## [87,] 0.06972958
## [88,] 0.08075027
## [89,] 0.08673983
## [90,] 0.09922533
tail(weight)
##          GGRM.JK   HMSP.JK    INDF.JK      JPFA.JK   MYOR.JK   ULTJ.JK
## [184,] 0.1300397 0.1275431 0.10359087 -0.003374394 0.2870957 0.2324561
## [185,] 0.1108294 0.1367895 0.09553085  0.002374656 0.2864743 0.2529835
## [186,] 0.1103073 0.1401726 0.09223626  0.003637190 0.2819134 0.2502825
## [187,] 0.1075244 0.1370056 0.09428081  0.008114382 0.2925011 0.2451933
## [188,] 0.1048438 0.1277215 0.08931505  0.008158930 0.3021587 0.2398539
## [189,] 0.1090243 0.1317076 0.09043708  0.005751088 0.2993620 0.2367152
##          UNVR.JK
## [184,] 0.1226489
## [185,] 0.1150177
## [186,] 0.1214507
## [187,] 0.1153804
## [188,] 0.1279482
## [189,] 0.1270027
# 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 :
##            GGRM.JK HMSP.JK INDF.JK JPFA.JK MYOR.JK ULTJ.JK UNVR.JK
## 2021-05-31   10.48   12.77    8.93    0.82   30.22   23.99   12.79
## 
## Performance summary :
##  CAGR    Best    Worst   
##  3.2 14.4    -12.9   
#=================================================================
# b. CAPM (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 = 84
f <- fama_lib_month[dates]/100
for( i in 84:dim(weight_1)[1]) {
  hist = ret[ (i- 84 + 1):i, ]
  Xi <- hist
  fi <- f$Mkt.RF[(i - 84 + 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 = 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] 189   7
head(weight_1, 90)
##         GGRM.JK   HMSP.JK   INDF.JK    JPFA.JK    MYOR.JK   ULTJ.JK   UNVR.JK
##  [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,]        NA        NA        NA         NA         NA        NA        NA
## [61,]        NA        NA        NA         NA         NA        NA        NA
## [62,]        NA        NA        NA         NA         NA        NA        NA
## [63,]        NA        NA        NA         NA         NA        NA        NA
## [64,]        NA        NA        NA         NA         NA        NA        NA
## [65,]        NA        NA        NA         NA         NA        NA        NA
## [66,]        NA        NA        NA         NA         NA        NA        NA
## [67,]        NA        NA        NA         NA         NA        NA        NA
## [68,]        NA        NA        NA         NA         NA        NA        NA
## [69,]        NA        NA        NA         NA         NA        NA        NA
## [70,]        NA        NA        NA         NA         NA        NA        NA
## [71,]        NA        NA        NA         NA         NA        NA        NA
## [72,]        NA        NA        NA         NA         NA        NA        NA
## [73,]        NA        NA        NA         NA         NA        NA        NA
## [74,]        NA        NA        NA         NA         NA        NA        NA
## [75,]        NA        NA        NA         NA         NA        NA        NA
## [76,]        NA        NA        NA         NA         NA        NA        NA
## [77,]        NA        NA        NA         NA         NA        NA        NA
## [78,]        NA        NA        NA         NA         NA        NA        NA
## [79,]        NA        NA        NA         NA         NA        NA        NA
## [80,]        NA        NA        NA         NA         NA        NA        NA
## [81,]        NA        NA        NA         NA         NA        NA        NA
## [82,]        NA        NA        NA         NA         NA        NA        NA
## [83,]        NA        NA        NA         NA         NA        NA        NA
## [84,] 0.1147953 0.1070467 0.2143652 0.04518558 0.04702557 0.3448608 0.1267207
## [85,] 0.1154380 0.1074035 0.2152707 0.04537034 0.04720630 0.3429900 0.1263213
## [86,] 0.1155807 0.1077548 0.2147433 0.04526610 0.04713133 0.3427952 0.1267286
## [87,] 0.1155384 0.1071722 0.2146291 0.04529557 0.04713947 0.3435805 0.1266447
## [88,] 0.1187136 0.1198909 0.2198811 0.04630157 0.04936194 0.3157269 0.1301239
## [89,] 0.1191409 0.1195074 0.2215505 0.04607732 0.04920009 0.3145284 0.1299955
## [90,] 0.1166826 0.1202855 0.2159777 0.04620396 0.05041389 0.3203952 0.1300411
tail(weight_1)
##          GGRM.JK   HMSP.JK   INDF.JK    JPFA.JK   MYOR.JK   ULTJ.JK   UNVR.JK
## [184,] 0.1530023 0.1398117 0.1191477 0.03111713 0.1825224 0.2332738 0.1411249
## [185,] 0.1494830 0.1410791 0.1175703 0.03167631 0.1821279 0.2389171 0.1391464
## [186,] 0.1481966 0.1423281 0.1167477 0.03190315 0.1812203 0.2368311 0.1427730
## [187,] 0.1458659 0.1412417 0.1163061 0.03147071 0.1901634 0.2324238 0.1425285
## [188,] 0.1455562 0.1411408 0.1158669 0.03143990 0.1916472 0.2249347 0.1494142
## [189,] 0.1464869 0.1414640 0.1155808 0.03116168 0.1909967 0.2249725 0.1493375
# 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 :
##            GGRM.JK HMSP.JK INDF.JK JPFA.JK MYOR.JK ULTJ.JK UNVR.JK
## 2021-05-31   14.56   14.11   11.59    3.14   19.16   22.49   14.94
## 
## Performance summary :
##  CAGR    Best    Worst   
##  4.1 12.4    -12.3   
models$mvp.capm.cov$cagr
## [1] 0.04121181
models$mvp.hist.cov$cagr
## [1] 0.03174668
#=================================================================
# c. FAMA FRENCH (Three Factors 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 = 84
f <- fama_lib_month[dates]/100
for( i in 84:dim(weight_1)[1]) {
  hist = ret[ (i- 84 + 1):i, ]
  Xi <- hist
  fi <- f[(i - 84 + 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] 189   7
head(weight_3, 90)
##         GGRM.JK    HMSP.JK   INDF.JK    JPFA.JK    MYOR.JK   ULTJ.JK   UNVR.JK
##  [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,]        NA         NA        NA         NA         NA        NA        NA
## [61,]        NA         NA        NA         NA         NA        NA        NA
## [62,]        NA         NA        NA         NA         NA        NA        NA
## [63,]        NA         NA        NA         NA         NA        NA        NA
## [64,]        NA         NA        NA         NA         NA        NA        NA
## [65,]        NA         NA        NA         NA         NA        NA        NA
## [66,]        NA         NA        NA         NA         NA        NA        NA
## [67,]        NA         NA        NA         NA         NA        NA        NA
## [68,]        NA         NA        NA         NA         NA        NA        NA
## [69,]        NA         NA        NA         NA         NA        NA        NA
## [70,]        NA         NA        NA         NA         NA        NA        NA
## [71,]        NA         NA        NA         NA         NA        NA        NA
## [72,]        NA         NA        NA         NA         NA        NA        NA
## [73,]        NA         NA        NA         NA         NA        NA        NA
## [74,]        NA         NA        NA         NA         NA        NA        NA
## [75,]        NA         NA        NA         NA         NA        NA        NA
## [76,]        NA         NA        NA         NA         NA        NA        NA
## [77,]        NA         NA        NA         NA         NA        NA        NA
## [78,]        NA         NA        NA         NA         NA        NA        NA
## [79,]        NA         NA        NA         NA         NA        NA        NA
## [80,]        NA         NA        NA         NA         NA        NA        NA
## [81,]        NA         NA        NA         NA         NA        NA        NA
## [82,]        NA         NA        NA         NA         NA        NA        NA
## [83,]        NA         NA        NA         NA         NA        NA        NA
## [84,] 0.1084401 0.09946205 0.2407462 0.03985597 0.04665202 0.3470972 0.1177464
## [85,] 0.1089879 0.09986887 0.2416018 0.04006016 0.04682863 0.3453371 0.1173155
## [86,] 0.1091677 0.10038412 0.2406194 0.04006577 0.04649909 0.3453941 0.1178699
## [87,] 0.1092028 0.10000879 0.2411517 0.03968103 0.04653161 0.3458037 0.1176205
## [88,] 0.1121166 0.11313234 0.2466584 0.04035408 0.04855380 0.3175521 0.1216326
## [89,] 0.1128293 0.11229594 0.2487243 0.03991052 0.04834940 0.3157299 0.1221607
## [90,] 0.1103589 0.11362848 0.2417988 0.04110288 0.04910347 0.3203859 0.1236217
tail(weight_3)
##          GGRM.JK   HMSP.JK   INDF.JK    JPFA.JK   MYOR.JK   ULTJ.JK   UNVR.JK
## [184,] 0.1503660 0.1379182 0.1199567 0.03231837 0.1852583 0.2350303 0.1391521
## [185,] 0.1453846 0.1421613 0.1185030 0.03306159 0.1843279 0.2402611 0.1363007
## [186,] 0.1439377 0.1431954 0.1175903 0.03296817 0.1843244 0.2385927 0.1393914
## [187,] 0.1408346 0.1427098 0.1167004 0.03121124 0.1933701 0.2358711 0.1393028
## [188,] 0.1402721 0.1408792 0.1160734 0.03143374 0.1968044 0.2268273 0.1477098
## [189,] 0.1420407 0.1409025 0.1157030 0.03142472 0.1956406 0.2258141 0.1484743
# 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 :
##            GGRM.JK HMSP.JK INDF.JK JPFA.JK MYOR.JK ULTJ.JK UNVR.JK
## 2021-05-31   14.03   14.09   11.61    3.14   19.68   22.68   14.77
## 
## Performance summary :
##  CAGR    Best    Worst   
##  4.2 12.4    -12.3   
#=================================================================
# d. PRINCIPAL COMPONENT ANALYSIS (PCA)
#=================================================================
X_i <-X[1:84,] 
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
## GGRM.JK 0.02628758 -0.049315229 -0.0223801161 -0.05465939
## HMSP.JK 0.03058379 -0.005467683  0.0003314439 -0.02364755
## INDF.JK 0.03412201 -0.060882258 -0.0382898552 -0.06377484
## JPFA.JK 0.05531731 -0.181530276 -0.0780533965  0.05384842
## MYOR.JK 0.05287540 -0.071509844 -0.0323362435 -0.03374303
## ULTJ.JK 0.03338365 -0.135004575  0.1481203175 -0.00387014
## UNVR.JK 0.02781668 -0.019793575 -0.0041662546 -0.00667288
#
# 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.057285372 -0.0290389434 -0.068929850
## [2,] -0.006476672 -0.0006698376 -0.034609680
## [3,] -0.068769418 -0.0459158734 -0.063199106
## [4,] -0.181603175 -0.0608790312  0.075564190
## [5,] -0.085970599 -0.0428769455 -0.039648161
## [6,] -0.127673016  0.1539737431 -0.013285625
## [7,] -0.021609515 -0.0042045047 -0.004577221
# fiti = lm(formula = X_i ~ t(B))
Sigma_PCA3 <- Sigma
Sigma_PCA3
##             [,1]          [,2]        [,3]         [,4]        [,5]        [,6]
## [1,] 0.014091485  0.0027761099 0.009629135  0.006962440 0.008902901 0.003758338
## [2,] 0.002776110  0.0086589522 0.002663454 -0.001398289 0.001957734 0.001183570
## [3,] 0.009629135  0.0026634539 0.015412356  0.010508469 0.010386609 0.002549800
## [4,] 0.006962440 -0.0013982892 0.010508469  0.042961470 0.015226859 0.012808135
## [5,] 0.008902901  0.0019577341 0.010386609  0.015226859 0.018051662 0.004900952
## [6,] 0.003758338  0.0011835700 0.002549800  0.012808135 0.004900952 0.040213041
## [7,] 0.001675511  0.0003011902 0.001968404  0.003834449 0.002219538 0.002172380
##              [,7]
## [1,] 0.0016755106
## [2,] 0.0003011902
## [3,] 0.0019684035
## [4,] 0.0038344487
## [5,] 0.0022195376
## [6,] 0.0021723799
## [7,] 0.0056250047
diag(Sigma_PCA3)
## [1] 0.014091485 0.008658952 0.015412356 0.042961470 0.018051662 0.040213041
## [7] 0.005625005
# error
norm(Sigma_PCA3 - cov(X_i), "F")
## [1] 0.008265346
#*****************************************************************
# 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.25380059 0.17843390 0.13120690 0.10552187 0.08619573 0.08168248 0.06769319 
## 
##  7  variables and  84 observations.
summary(pc.fit)
## Importance of components:
##                           Comp.1    Comp.2    Comp.3     Comp.4     Comp.5
## Standard deviation     0.2538006 0.1784339 0.1312069 0.10552187 0.08619573
## Proportion of Variance 0.4495486 0.2222010 0.1201447 0.07770989 0.05185169
## Cumulative Proportion  0.4495486 0.6717496 0.7918943 0.86960422 0.92145590
##                            Comp.6     Comp.7
## Standard deviation     0.08168248 0.06769319
## Proportion of Variance 0.04656389 0.03198021
## Cumulative Proportion  0.96801979 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.25380059 0.17843390 0.13120690 0.10552187 0.08619573 0.08168248 0.06769319 
## 
##  7  variables and  84 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.057285372 -0.0290389434 -0.068929850
## [2,] -0.006476672 -0.0006698376 -0.034609680
## [3,] -0.068769418 -0.0459158734 -0.063199106
## [4,] -0.181603175 -0.0608790312  0.075564190
## [5,] -0.085970599 -0.0428769455 -0.039648161
## [6,] -0.127673016  0.1539737431 -0.013285625
## [7,] -0.021609515 -0.0042045047 -0.004577221
#
#
plot(pc.fit,col=brewer.pal(7,"Set2"),ylim=c(0,0.07))

loadings(pc.fit)
## 
## Loadings:
##         Comp.1 Comp.2 Comp.3 Comp.4 Comp.5 Comp.6 Comp.7
## GGRM.JK  0.224  0.162  0.522  0.293  0.751              
## HMSP.JK                0.262  0.477 -0.389  0.740       
## INDF.JK  0.269  0.256  0.479  0.165 -0.521 -0.569 -0.104
## JPFA.JK  0.711  0.339 -0.572  0.220                     
## MYOR.JK  0.337  0.239  0.300 -0.733         0.333  0.289
## ULTJ.JK  0.500 -0.858  0.101                            
## UNVR.JK                      -0.270         0.112 -0.949
## 
##                Comp.1 Comp.2 Comp.3 Comp.4 Comp.5 Comp.6 Comp.7
## SS loadings     1.000  1.000  1.000  1.000  1.000  1.000  1.000
## Proportion Var  0.143  0.143  0.143  0.143  0.143  0.143  0.143
## Cumulative Var  0.143  0.286  0.429  0.571  0.714  0.857  1.000
pc.fit$loadings[, 1:3]
##             Comp.1      Comp.2      Comp.3
## GGRM.JK 0.22436262  0.16177181  0.52221587
## HMSP.JK 0.02536639  0.00373157  0.26220460
## INDF.JK 0.26934079  0.25579077  0.47879947
## JPFA.JK 0.71126299  0.33914839 -0.57247794
## MYOR.JK 0.33671055  0.23886134  0.30037638
## ULTJ.JK 0.50004132 -0.85776573  0.10065253
## UNVR.JK 0.08463535  0.02342270  0.03467725
# 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
## 2005-10-31  0.03821218  0.03303570 -0.0688982628
## 2005-11-30 -0.13210802 -0.01124371  0.0238242646
## 2005-12-30  0.22374918 -0.08626179  0.1651031375
## 2006-01-31 -0.11634409  0.10740181 -0.1459590741
## 2006-02-28 -0.14552348  0.00392537 -0.1038965436
## 2006-03-31 -0.02503732 -0.05976932  0.0002345293
pc.fit$scores[, 1:3]
##                  Comp.1        Comp.2        Comp.3
## 2005-10-31  0.038212184  0.0330357033 -0.0688982628
## 2005-11-30 -0.132108017 -0.0112437075  0.0238242646
## 2005-12-30  0.223749181 -0.0862617912  0.1651031375
## 2006-01-31 -0.116344088  0.1074018117 -0.1459590741
## 2006-02-28 -0.145523480  0.0039253701 -0.1038965436
## 2006-03-31 -0.025037324 -0.0597693206  0.0002345293
## 2006-04-28  0.283742277  0.1214460020  0.0985581842
## 2006-05-31 -0.407889696  0.0635513634 -0.0981050140
## 2006-06-30 -0.009780020 -0.3237799014 -0.0205695773
## 2006-07-31 -0.016217279  0.0488272333  0.1071050228
## 2006-08-31 -0.071423040  0.1079406727  0.0720869751
## 2006-09-29  0.195296303 -0.1225613964  0.0468369664
## 2006-10-31  0.163902600 -0.2262654892 -0.0215427800
## 2006-11-30  0.327523256  0.2551072648 -0.1466452271
## 2006-12-28 -0.183340956 -0.0906674449  0.1155835488
## 2007-01-31 -0.090189240  0.0202210927  0.1355683529
## 2007-02-28 -0.072000566 -0.0100893170 -0.0413922501
## 2007-03-30 -0.139492897 -0.0494778548 -0.0294797009
## 2007-04-30 -0.039852323  0.1488301610 -0.0101928238
## 2007-05-31  0.819897850  0.2199435991 -0.5373433558
## 2007-06-29  0.096791108 -0.1852320484  0.2130661248
## 2007-07-31 -0.100241811 -0.0841427645 -0.0373508095
## 2007-08-31 -0.318791221  0.0702670677 -0.0801966896
## 2007-09-28  0.309968214 -0.4871582015 -0.0086707759
## 2007-10-31 -0.050745273  0.2754567754 -0.0448996286
## 2007-11-30 -0.120380051 -0.0748333772  0.0071416554
## 2007-12-31 -0.082250691 -0.0434948215  0.0165557883
## 2008-01-31 -0.283090981  0.1929739205 -0.0060261340
## 2008-02-29 -0.166487233 -0.0448852892 -0.0131023123
## 2008-03-31 -0.137068496 -0.4802295313 -0.1247932929
## 2008-04-30 -0.246461093 -0.0591430380  0.0472200342
## 2008-05-30  0.571434283  0.2026964251 -0.2526447900
## 2008-06-30 -0.218774077 -0.1818977955 -0.1117473985
## 2008-07-29 -0.017993105  0.1205669616  0.0602791920
## 2008-08-29 -0.221920950  0.0410823722 -0.0731750532
## 2008-09-26 -0.287543741 -0.2069814525 -0.0127695889
## 2008-10-31 -0.559824569 -0.2692061915 -0.3200337898
## 2008-11-28 -0.101275399 -0.0901349528 -0.0320250220
## 2008-12-31 -0.023482361 -0.2450110360 -0.0528827700
## 2009-01-30 -0.058096734  0.1326860800  0.1214245315
## 2009-02-27 -0.055849103 -0.0771229012 -0.1281944580
## 2009-03-31  0.116521892  0.1018019001 -0.0108085874
## 2009-04-30  0.068074346  0.2422931460  0.3620071780
## 2009-05-29  0.261116822  0.3397672180  0.3767185690
## 2009-06-30  0.087017762  0.1208004885 -0.0271027713
## 2009-07-31  0.371935588  0.2044862566  0.1352046072
## 2009-08-31 -0.041134641  0.0650161906  0.0863901178
## 2009-09-30  0.126668983  0.1005407420  0.1444756382
## 2009-10-30 -0.095737848  0.0865045498 -0.1044514406
## 2009-11-30  0.451283219  0.2020930133 -0.0732895323
## 2009-12-30  0.024007744  0.1355319981  0.2208409244
## 2010-01-29 -0.121323938 -0.0687639665  0.1492784320
## 2010-02-25 -0.114837985 -0.0228164588  0.0366936403
## 2010-03-31  0.007630307 -0.0246930464 -0.0682784347
## 2010-04-30  0.183168138  0.1066599078  0.0228853892
## 2010-05-31 -0.037484498 -0.1482149673  0.2129622724
## 2010-06-30  0.086802671  0.2049961123  0.1205805513
## 2010-07-30  0.498457926  0.3169542901 -0.2601746663
## 2010-08-31 -0.027199219 -0.0390091582  0.0819640612
## 2010-09-30  1.194791038 -0.7872218873  0.0802594990
## 2010-10-29 -0.199628260 -0.1045230671  0.0902713562
## 2010-11-30 -0.234249199  0.0905006664 -0.1870803140
## 2010-12-30 -0.183807171  0.0796673528  0.0424867365
## 2011-01-31 -0.270612844  0.0959300689 -0.1220221431
## 2011-02-28 -0.094188531 -0.0312869412 -0.0268271945
## 2011-03-31  0.150101029  0.0925049166  0.0842175398
## 2011-04-29  0.112672887 -0.2921261792 -0.0178672476
## 2011-05-31  0.078028749  0.0797583968 -0.0218126826
## 2011-06-30  0.086843450  0.1078981184 -0.0241757525
## 2011-07-29  0.218195201  0.0670959029  0.1062443431
## 2011-08-26 -0.252364815  0.0895450387 -0.0178833368
## 2011-09-30 -0.372179827 -0.0063905908 -0.1325652473
## 2011-10-31  0.135459487  0.0479538815  0.0010512784
## 2011-11-30 -0.162278963 -0.0738541571  0.1087049985
## 2011-12-30 -0.205200383 -0.0642325213  0.0379054692
## 2012-01-31 -0.024256752 -0.0254387563 -0.0617853438
## 2012-02-29 -0.014916369  0.0194843659  0.0462877367
## 2012-03-30 -0.022197639 -0.0069431154  0.0572604953
## 2012-04-30 -0.035484604 -0.0009003216  0.0177703729
## 2012-05-31 -0.125582216  0.0003181936 -0.0603624440
## 2012-06-29  0.110598930  0.1999852904 -0.0099296297
## 2012-07-31 -0.113135508 -0.1467769044  0.0614884802
## 2012-08-31 -0.160811876  0.0308558603 -0.1264442395
## 2012-09-28  0.008195478 -0.0421220799 -0.0391398633
# time series plot of principal component factors
# library(PerformanceAnalytics)
# chart.TimeSeries(pc.fit$scores[, 1, drop=FALSE], colorset="blue")
# 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                                    
## GGRM.JK 0.22436262  0.16177181  0.52221587 -0.22436262 -0.16177181 -0.52221587
## HMSP.JK 0.02536639  0.00373157  0.26220460 -0.02536639 -0.00373157 -0.26220460
## INDF.JK 0.26934079  0.25579077  0.47879947 -0.26934079 -0.25579077 -0.47879947
## JPFA.JK 0.71126299  0.33914839 -0.57247794 -0.71126299 -0.33914839  0.57247794
## MYOR.JK 0.33671055  0.23886134  0.30037638 -0.33671055 -0.23886134 -0.30037638
## ULTJ.JK 0.50004132 -0.85776573  0.10065253 -0.50004132  0.85776573 -0.10065253
## UNVR.JK 0.08463535  0.02342270  0.03467725 -0.08463535 -0.02342270 -0.03467725
# 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
## 2005-10-31  0.038212184  0.130272725
## 2005-11-30 -0.132108017 -0.040047475
## 2005-12-30  0.223749181  0.315809722
## 2006-01-31 -0.116344088 -0.024283547
## 2006-02-28 -0.145523480 -0.053462939
## 2006-03-31 -0.025037324  0.067023217
## 2006-04-28  0.283742277  0.375802818
## 2006-05-31 -0.407889696 -0.315829154
## 2006-06-30 -0.009780020  0.082280522
## 2006-07-31 -0.016217279  0.075843263
## 2006-08-31 -0.071423040  0.020637501
## 2006-09-29  0.195296303  0.287356844
## 2006-10-31  0.163902600  0.255963141
## 2006-11-30  0.327523256  0.419583797
## 2006-12-28 -0.183340956 -0.091280415
## 2007-01-31 -0.090189240  0.001871301
## 2007-02-28 -0.072000566  0.020059975
## 2007-03-30 -0.139492897 -0.047432355
## 2007-04-30 -0.039852323  0.052208218
## 2007-05-31  0.819897850  0.911958392
## 2007-06-29  0.096791108  0.188851649
## 2007-07-31 -0.100241811 -0.008181270
## 2007-08-31 -0.318791221 -0.226730680
## 2007-09-28  0.309968214  0.402028755
## 2007-10-31 -0.050745273  0.041315269
## 2007-11-30 -0.120380051 -0.028319509
## 2007-12-31 -0.082250691  0.009809851
## 2008-01-31 -0.283090981 -0.191030439
## 2008-02-29 -0.166487233 -0.074426691
## 2008-03-31 -0.137068496 -0.045007955
## 2008-04-30 -0.246461093 -0.154400551
## 2008-05-30  0.571434283  0.663494824
## 2008-06-30 -0.218774077 -0.126713535
## 2008-07-29 -0.017993105  0.074067436
## 2008-08-29 -0.221920950 -0.129860409
## 2008-09-26 -0.287543741 -0.195483199
## 2008-10-31 -0.559824569 -0.467764027
## 2008-11-28 -0.101275399 -0.009214857
## 2008-12-31 -0.023482361  0.068578181
## 2009-01-30 -0.058096734  0.033963808
## 2009-02-27 -0.055849103  0.036211438
## 2009-03-31  0.116521892  0.208582433
## 2009-04-30  0.068074346  0.160134887
## 2009-05-29  0.261116822  0.353177363
## 2009-06-30  0.087017762  0.179078304
## 2009-07-31  0.371935588  0.463996129
## 2009-08-31 -0.041134641  0.050925900
## 2009-09-30  0.126668983  0.218729524
## 2009-10-30 -0.095737848 -0.003677306
## 2009-11-30  0.451283219  0.543343761
## 2009-12-30  0.024007744  0.116068285
## 2010-01-29 -0.121323938 -0.029263397
## 2010-02-25 -0.114837985 -0.022777444
## 2010-03-31  0.007630307  0.099690849
## 2010-04-30  0.183168138  0.275228679
## 2010-05-31 -0.037484498  0.054576044
## 2010-06-30  0.086802671  0.178863213
## 2010-07-30  0.498457926  0.590518468
## 2010-08-31 -0.027199219  0.064861322
## 2010-09-30  1.194791038  1.286851580
## 2010-10-29 -0.199628260 -0.107567719
## 2010-11-30 -0.234249199 -0.142188658
## 2010-12-30 -0.183807171 -0.091746630
## 2011-01-31 -0.270612844 -0.178552303
## 2011-02-28 -0.094188531 -0.002127989
## 2011-03-31  0.150101029  0.242161570
## 2011-04-29  0.112672887  0.204733428
## 2011-05-31  0.078028749  0.170089291
## 2011-06-30  0.086843450  0.178903991
## 2011-07-29  0.218195201  0.310255743
## 2011-08-26 -0.252364815 -0.160304274
## 2011-09-30 -0.372179827 -0.280119286
## 2011-10-31  0.135459487  0.227520029
## 2011-11-30 -0.162278963 -0.070218421
## 2011-12-30 -0.205200383 -0.113139842
## 2012-01-31 -0.024256752  0.067803789
## 2012-02-29 -0.014916369  0.077144173
## 2012-03-30 -0.022197639  0.069862902
## 2012-04-30 -0.035484604  0.056575937
## 2012-05-31 -0.125582216 -0.033521674
## 2012-06-29  0.110598930  0.202659472
## 2012-07-31 -0.113135508 -0.021074967
## 2012-08-31 -0.160811876 -0.068751335
## 2012-09-28  0.008195478  0.100256019
#
# 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
## GGRM.JK 0.22436262  0.16177181  0.52221587
## HMSP.JK 0.02536639  0.00373157  0.26220460
## INDF.JK 0.26934079  0.25579077  0.47879947
## JPFA.JK 0.71126299  0.33914839 -0.57247794
## MYOR.JK 0.33671055  0.23886134  0.30037638
## ULTJ.JK 0.50004132 -0.85776573  0.10065253
## UNVR.JK 0.08463535  0.02342270  0.03467725
colSums(p3)
##    Comp.1    Comp.2    Comp.3 
## 2.1517200 0.1649608 1.1264481
# create factor mimicking portfolio by normalizing weights to unity
p3 = p3/colSums(p3)
p3
##             Comp.1       Comp.2      Comp.3
## GGRM.JK 0.10427129  0.980667936  0.46359512
## HMSP.JK 0.15377219  0.003312687  0.12185814
## INDF.JK 0.23910625  0.118877350  2.90250382
## JPFA.JK 0.33055555  2.055932716 -0.50821509
## MYOR.JK 2.04115445  0.212048233  0.13959826
## ULTJ.JK 0.44390976 -0.398641889  0.61016015
## UNVR.JK 0.03933381  0.141989427  0.03078459
barplot(p3[,1], horiz=F, main="Factor mimicking weights", col=brewer.pal(7,"Set3"), cex.names = 0.75, las=2)

# create first 3 factors
f3 = X_i %*% p3
head(f3)
##            Comp.1      Comp.2     Comp.3
## [1,]  0.056414212  0.23792420  0.2751346
## [2,] -0.167453518 -0.01786923  0.1364060
## [3,]  0.944382959  0.14596394  0.4173403
## [4,] -0.003545775  0.14963390 -0.2523057
## [5,] -0.287737977  0.08391175 -0.1941613
## [6,]  0.180265905 -0.05515027  0.2060652
head(pc.fit$scores[, 1:3])
##                 Comp.1      Comp.2        Comp.3
## 2005-10-31  0.03821218  0.03303570 -0.0688982628
## 2005-11-30 -0.13210802 -0.01124371  0.0238242646
## 2005-12-30  0.22374918 -0.08626179  0.1651031375
## 2006-01-31 -0.11634409  0.10740181 -0.1459590741
## 2006-02-28 -0.14552348  0.00392537 -0.1038965436
## 2006-03-31 -0.02503732 -0.05976932  0.0002345293
# chart.TimeSeries(f1, main="First principal component factor", colorset="blue")
# 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
## GGRM.JK  0.0007099487 -0.04893042  0.113405117  0.14545838
## HMSP.JK  0.0268890600 -0.03685023  0.004043170  0.07725371
## INDF.JK -0.0004551373 -0.07376988  0.083166278  0.29546456
## JPFA.JK -0.0028226686  0.04201929  0.407896667 -0.06794934
## MYOR.JK -0.0003863505  0.42380927 -0.053468794 -0.05027695
## ULTJ.JK -0.0068659585  0.32927061 -0.130471219  0.06323544
## UNVR.JK  0.0170216167  0.08367073 -0.002776087 -0.01730858
# can also use solve(qr(X.mat), returns.mat)
beta.hat = G.hat[2:4,]
beta.hat
##              GGRM.JK     HMSP.JK     INDF.JK     JPFA.JK     MYOR.JK
## Factor 1 -0.04893042 -0.03685023 -0.07376988  0.04201929  0.42380927
## Factor 2  0.11340512  0.00404317  0.08316628  0.40789667 -0.05346879
## Factor 3  0.14545838  0.07725371  0.29546456 -0.06794934 -0.05027695
##              ULTJ.JK      UNVR.JK
## Factor 1  0.32927061  0.083670729
## Factor 2 -0.13047122 -0.002776087
## Factor 3  0.06323544 -0.017308581
B
##              [,1]          [,2]         [,3]
## [1,] -0.057285372 -0.0290389434 -0.068929850
## [2,] -0.006476672 -0.0006698376 -0.034609680
## [3,] -0.068769418 -0.0459158734 -0.063199106
## [4,] -0.181603175 -0.0608790312  0.075564190
## [5,] -0.085970599 -0.0428769455 -0.039648161
## [6,] -0.127673016  0.1539737431 -0.013285625
## [7,] -0.021609515 -0.0042045047 -0.004577221
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
##             GGRM.JK      HMSP.JK     INDF.JK      JPFA.JK      MYOR.JK
## GGRM.JK 0.014380093 1.446684e-03 0.008967669 0.0116028363 0.0055147023
## HMSP.JK 0.001446684 8.959740e-03 0.002713868 0.0002426334 0.0003520953
## INDF.JK 0.008967669 2.713868e-03 0.015456194 0.0108127170 0.0069478635
## JPFA.JK 0.011602836 2.426334e-04 0.010812717 0.0430883834 0.0153313751
## MYOR.JK 0.005514702 3.520953e-04 0.006947864 0.0153313751 0.0181154869
## ULTJ.JK 0.004273211 1.044330e-03 0.007282532 0.0057098132 0.0119388051
## UNVR.JK 0.001131545 1.647882e-05 0.001278558 0.0036044703 0.0033332718
##             ULTJ.JK      UNVR.JK
## GGRM.JK 0.004273211 1.131545e-03
## HMSP.JK 0.001044330 1.647882e-05
## INDF.JK 0.007282532 1.278558e-03
## JPFA.JK 0.005709813 3.604470e-03
## MYOR.JK 0.011938805 3.333272e-03
## ULTJ.JK 0.041314212 2.264390e-03
## UNVR.JK 0.002264390 5.809946e-03
Sigma_PCA3
##             [,1]          [,2]        [,3]         [,4]        [,5]        [,6]
## [1,] 0.014091485  0.0027761099 0.009629135  0.006962440 0.008902901 0.003758338
## [2,] 0.002776110  0.0086589522 0.002663454 -0.001398289 0.001957734 0.001183570
## [3,] 0.009629135  0.0026634539 0.015412356  0.010508469 0.010386609 0.002549800
## [4,] 0.006962440 -0.0013982892 0.010508469  0.042961470 0.015226859 0.012808135
## [5,] 0.008902901  0.0019577341 0.010386609  0.015226859 0.018051662 0.004900952
## [6,] 0.003758338  0.0011835700 0.002549800  0.012808135 0.004900952 0.040213041
## [7,] 0.001675511  0.0003011902 0.001968404  0.003834449 0.002219538 0.002172380
##              [,7]
## [1,] 0.0016755106
## [2,] 0.0003011902
## [3,] 0.0019684035
## [4,] 0.0038344487
## [5,] 0.0022195376
## [6,] 0.0021723799
## [7,] 0.0056250047
diag(cov.pc3)
##     GGRM.JK     HMSP.JK     INDF.JK     JPFA.JK     MYOR.JK     ULTJ.JK 
## 0.014380093 0.008959740 0.015456194 0.043088383 0.018115487 0.041314212 
##     UNVR.JK 
## 0.005809946
# error difference between pca and empirical covariance matrix
norm(cov.pc3 - cov(X_i), "F")
## [1] 0.01689651
norm(Sigma_PCA3 - cov(X_i), "F")
## [1] 0.008265346
  1. Plotting the MVP performance based on equal weighting, CAPM (single factor), Fama French (three factors), and PCA models.
#============================================================
# 8. PERFORMANCE PLOTTING OF MVP (Minimum Variance Portfolio)
# Based on Equal Weighting, CAPM, Fama French, and PCA
#============================================================
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')
}

  1. Conclusion

->CAGR is a pro forma number that provides a “smoothed” annual yield, so it can give the illusion that there is a steady growth rate even when the value of the underlying investment can vary significantly. ->A maximum drawdown (MaxDD) is the maximum observed loss from a peak to a trough of a portfolio, before a new peak is attained. ->The equal-weight share portfolio for the chosen 7 Indonesian non-cyclical sector stocks performed well during that period with 6.13% CAGR, which is the highest among the other portfolio strategies. But we found out that the maximum drawdown (MaxDD) using this strategy is also the highest among the other portfolio strategies with -34.06% maximum drawdown (MaxDD). But, if we compare the maximum drawdown (MaxDD) of equal-weight strategy rate with the other strategies, there are no significant differences because the lowest maximum drawdown (MaxDD) using the basic equal-weight strategy is -25.21%.