etf4.df <- read.csv('myetf4.csv')
str(etf4.df)
## 'data.frame': 751 obs. of 5 variables:
## $ Index : chr "2015-12-14" "2015-12-15" "2015-12-16" "2015-12-17" ...
## $ X0050 : num 53.3 53.3 54.1 54.8 54.5 ...
## $ X0056 : num 18.2 18.4 18.6 18.8 18.9 ...
## $ X006205: num 31.1 31.6 31.6 32.2 32.2 ...
## $ X00646 : num 19.6 19.6 19.9 20.1 19.9 ...
etf4 <- read_csv('myetf4.csv')
##
## ── Column specification ────────────────────────────────────────────────────────────────────────────────────────
## cols(
## Index = col_date(format = ""),
## `0050` = col_double(),
## `0056` = col_double(),
## `006205` = col_double(),
## `00646` = col_double()
## )
str(etf4)
## tibble [751 × 5] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ Index : Date[1:751], format: "2015-12-14" "2015-12-15" ...
## $ 0050 : num [1:751] 53.3 53.3 54.1 54.8 54.5 ...
## $ 0056 : num [1:751] 18.2 18.4 18.6 18.8 18.9 ...
## $ 006205: num [1:751] 31.1 31.6 31.6 32.2 32.2 ...
## $ 00646 : num [1:751] 19.6 19.6 19.9 20.1 19.9 ...
## - attr(*, "spec")=
## .. cols(
## .. Index = col_date(format = ""),
## .. `0050` = col_double(),
## .. `0056` = col_double(),
## .. `006205` = col_double(),
## .. `00646` = col_double()
## .. )
head(etf4)
## # A tibble: 6 x 5
## Index `0050` `0056` `006205` `00646`
## <date> <dbl> <dbl> <dbl> <dbl>
## 1 2015-12-14 53.3 18.2 31.1 19.6
## 2 2015-12-15 53.3 18.4 31.6 19.6
## 3 2015-12-16 54.1 18.6 31.6 19.9
## 4 2015-12-17 54.8 18.8 32.2 20.0
## 5 2015-12-18 54.5 19.0 32.2 19.8
## 6 2015-12-21 54.4 19.0 33 19.6
etf4.xts <- xts(etf4[, -1], order.by = etf4$Index)
head(etf4.xts)
## 0050 0056 006205 00646
## 2015-12-14 53.29 18.25 31.06 19.61
## 2015-12-15 53.33 18.38 31.59 19.63
## 2015-12-16 54.14 18.56 31.60 19.89
## 2015-12-17 54.77 18.81 32.23 20.05
## 2015-12-18 54.50 18.95 32.18 19.85
## 2015-12-21 54.41 19.02 33.00 19.64
etf4.ret <- etf4.xts %>% Return.calculate() %>% na.omit()
head(etf4.ret)
## 0050 0056 006205 00646
## 2015-12-15 0.0007506099 0.007123288 0.0170637476 0.001019888
## 2015-12-16 0.0151884493 0.009793254 0.0003165559 0.013245033
## 2015-12-17 0.0116364980 0.013469828 0.0199367089 0.008044243
## 2015-12-18 -0.0049297060 0.007442850 -0.0015513497 -0.009975062
## 2015-12-21 -0.0016513761 0.003693931 0.0254816656 -0.010579345
## 2015-12-22 0.0023892667 -0.003680336 0.0030303030 0.004073320
#compute average returns and covariance matrix
Mean.arithmetic(etf4.ret)
## 0050 0056 006205 00646
## Arithmetic Mean 0.0004632227 0.0003846366 -0.0002118311 0.0002554122
cov(etf4.ret)
## 0050 0056 006205 00646
## 0050 7.837060e-05 4.559164e-05 4.467258e-05 3.663388e-05
## 0056 4.559164e-05 4.526413e-05 2.673674e-05 2.353543e-05
## 006205 4.467258e-05 2.673674e-05 1.304184e-04 2.910367e-05
## 00646 3.663388e-05 2.353543e-05 2.910367e-05 5.902892e-05
#Q1 (Daily)compute optimal weights for 4 ETFs based on daily returns of the period
ETF.names <- c("0050", "0056", "006205", "00646")
mu.vec = c(0.0004632227, 0.0003846366, -0.0002118311, 0.0002554122)
names(mu.vec) = ETF.names
sigma.mat = matrix(c(7.837060e-05, 4.559164e-05, 4.467258e-05, 3.663388e-05,
4.559164e-05, 4.526413e-05, 2.673674e-05, 2.353543e-05,
4.467258e-05, 2.673674e-05, 1.304184e-04, 2.910367e-05,
3.663388e-05, 2.353543e-05, 2.910367e-05, 5.902892e-05) ,
nrow=4, ncol=4)
dimnames(sigma.mat) = list(ETF.names, ETF.names)
mu.vec
## 0050 0056 006205 00646
## 0.0004632227 0.0003846366 -0.0002118311 0.0002554122
sigma.mat
## 0050 0056 006205 00646
## 0050 7.837060e-05 4.559164e-05 4.467258e-05 3.663388e-05
## 0056 4.559164e-05 4.526413e-05 2.673674e-05 2.353543e-05
## 006205 4.467258e-05 2.673674e-05 1.304184e-04 2.910367e-05
## 00646 3.663388e-05 2.353543e-05 2.910367e-05 5.902892e-05
x.vec = rep(1,4)/4
names(x.vec) = ETF.names
mu.p.x = crossprod (x.vec,mu.vec)
sig2.p.x = t(x.vec) %*% sigma.mat %*%x.vec
sig.p.x = sqrt ( sig2.p.x)
mu.p.x
## [,1]
## [1,] 0.0002228601
sig.p.x
## [,1]
## [1,] 0.00673438
top.mat = cbind(2*sigma.mat, rep(1, 4))
bot.vec = c(rep(1, 4), 0)
Am.mat = rbind(top.mat, bot.vec)
b.vec = c(rep(0, 4), 1)
z.m.mat = solve(Am.mat)%*%b.vec
m.vec = z.m.mat [1:4,1]
m.vec
## 0050 0056 006205 00646
## -0.2193578 0.7283718 0.1076234 0.3833627
#portfolio return and standard deviation
mu.gmin = as.numeric(crossprod(m.vec, mu.vec))
mu.gmin
## [1] 0.0002536644
sig2.gmin = as.numeric(t(m.vec)%*%sigma.mat%*%m.vec)
sig.gmin = sqrt(sig2.gmin)
sig.gmin
## [1] 0.005904942
#another way of computing Minimum Variance Portfolio
one.vec = rep(1,4)
sigma.inv.mat = solve(sigma.mat)
top.mat = sigma.inv.mat%*%one.vec
bot.val = as.numeric ((t(one.vec)%*%sigma.inv.mat%*%one.vec))
m.mat = top.mat/bot.val
m.mat[,1]
## 0050 0056 006205 00646
## -0.2193578 0.7283718 0.1076234 0.3833627
#Q2 (Monthly)convert into monthly frequency
etf4.mon.ret <- etf4.xts %>% to.monthly(indexAt = 'lastof', OHLC = FALSE) %>%
Return.calculate() %>% na.omit
head(etf4.mon.ret)
## 0050 0056 006205 00646
## 2016-01-31 -0.01981651 -0.013785790 -0.173070915 -0.038883350
## 2016-02-29 0.02864096 0.043548387 -0.027578391 -0.003630705
## 2016-03-31 0.05550500 -0.002575992 0.082750583 0.026028110
## 2016-04-30 -0.04724138 -0.037190083 -0.024757804 0.009639777
## 2016-05-31 0.02515382 0.016630901 0.004415011 0.022110553
## 2016-06-30 0.03636364 0.029551451 -0.025641026 -0.026057030
#compute average returns and covariance matrix
Mean.arithmetic(etf4.mon.ret)
## 0050 0056 006205 00646
## Arithmetic Mean 0.008819836 0.007086721 -0.005355481 0.00451063
cov(etf4.mon.ret)
## 0050 0056 006205 00646
## 0050 0.0011751458 0.0008661004 0.0008472189 0.0003928466
## 0056 0.0008661004 0.0009080806 0.0005553289 0.0003572509
## 006205 0.0008472189 0.0005553289 0.0024412877 0.0006736296
## 00646 0.0003928466 0.0003572509 0.0006736296 0.0008605161
#compute optimal weights for 4 ETFs based on monthly returns of the period
ETF.names <- c("0050", "0056", "006205", "00646")
mu.vec = c(0.008819836, 0.007086721, -0.005355481, 0.00451063)
names(mu.vec) = ETF.names
sigma.mat = matrix(c(0.0011751458, 0.0008661004, 0.0008472189, 0.0003928466,
0.0008661004, 0.0009080806, 0.0005553289, 0.0003572509,
0.0008472189, 0.0005553289, 0.0024412877, 0.0006736296,
0.0003928466, 0.0003572509, 0.0006736296, 0.0008605161) ,
nrow=4, ncol=4)
dimnames(sigma.mat) = list(ETF.names, ETF.names)
mu.vec
## 0050 0056 006205 00646
## 0.008819836 0.007086721 -0.005355481 0.004510630
sigma.mat
## 0050 0056 006205 00646
## 0050 0.0011751458 0.0008661004 0.0008472189 0.0003928466
## 0056 0.0008661004 0.0009080806 0.0005553289 0.0003572509
## 006205 0.0008472189 0.0005553289 0.0024412877 0.0006736296
## 00646 0.0003928466 0.0003572509 0.0006736296 0.0008605161
x.vec = rep(1,4)/4
names(x.vec) = ETF.names
mu.p.x = crossprod (x.vec,mu.vec)
sig2.p.x = t(x.vec) %*% sigma.mat %*%x.vec
sig.p.x = sqrt ( sig2.p.x)
mu.p.x
## [,1]
## [1,] 0.003765426
sig.p.x
## [,1]
## [1,] 0.02825086
top.mat = cbind(2*sigma.mat, rep(1, 4))
bot.vec = c(rep(1, 4), 0)
Am.mat = rbind(top.mat, bot.vec)
b.vec = c(rep(0, 4), 1)
z.m.mat = solve(Am.mat)%*%b.vec
m.vec = z.m.mat [1:4,1]
m.vec
## 0050 0056 006205 00646
## 0.003183681 0.474049222 0.001203766 0.521563330
#portfolio return and standard deviation
mu.gmin = as.numeric(crossprod(m.vec, mu.vec))
mu.gmin
## [1] 0.005733667
sig2.gmin = as.numeric(t(m.vec)%*%sigma.mat%*%m.vec)
sig.gmin = sqrt(sig2.gmin)
sig.gmin
## [1] 0.02490441
#another way of computing Minimum Variance Portfolio
one.vec = rep(1,4)
sigma.inv.mat = solve(sigma.mat)
top.mat = sigma.inv.mat%*%one.vec
bot.val = as.numeric ((t(one.vec)%*%sigma.inv.mat%*%one.vec))
m.mat = top.mat/bot.val
m.mat[,1]
## 0050 0056 006205 00646
## 0.003183681 0.474049222 0.001203766 0.521563330