etf6 <- read.table('ETF6_20080101-20200430.csv', sep = ',', header = T)
#
head(etf6)
##   證券代碼          簡稱   年月日 收盤價.元.
## 1  0050    元大台灣50    20080102    39.6472
## 2  0052    富邦科技      20080102    27.0983
## 3  0056    元大高股息    20080102    14.5739
## 4  0050    元大台灣50    20080103    38.9876
## 5  0052    富邦科技      20080103    26.0676
## 6  0056    元大高股息    20080103    14.3758
etf6 <- etf6[, -2]
colnames(etf6) <- c('id', 'date', 'price')
head(etf6)
##        id     date   price
## 1 0050    20080102 39.6472
## 2 0052    20080102 27.0983
## 3 0056    20080102 14.5739
## 4 0050    20080103 38.9876
## 5 0052    20080103 26.0676
## 6 0056    20080103 14.3758
library(pacman)
p_load(reshape2, xts, quantmod)

etf6.l <- dcast(etf6, date~id)
## Using price as value column: use value.var to override.
head(etf6.l)
##       date 0050    0052    0056    0061    006206  00638R 
## 1 20080102 39.6472 27.0983 14.5739      NA      NA      NA
## 2 20080103 38.9876 26.0676 14.3758      NA      NA      NA
## 3 20080104 38.9876 25.9346 14.4041      NA      NA      NA
## 4 20080107 37.2064 24.1391 14.1777      NA      NA      NA
## 5 20080108 37.5692 24.1391 14.3531      NA      NA      NA
## 6 20080109 38.2619 24.2721 14.4663      NA      NA      NA
etf6.l <- na.omit(etf6.l)
# head(etf6.l)

str(etf6.l)
## 'data.frame':    1214 obs. of  7 variables:
##  $ date   : int  20150518 20150519 20150520 20150521 20150522 20150525 20150526 20150527 20150528 20150529 ...
##  $ 0050   : num  58.7 59.6 59.1 58.6 59.1 ...
##  $ 0052   : num  34.8 34.9 35 34.6 35.1 ...
##  $ 0056   : num  19.1 19.2 19.2 19 19 ...
##  $ 0061   : num  21.8 22.4 22.7 22.8 23.3 ...
##  $ 006206 : num  33.5 34.5 34.9 35 35.9 ...
##  $ 00638R : num  20 19.5 19.2 19.2 18.6 ...
##  - attr(*, "na.action")= 'omit' Named int [1:1827] 1 2 3 4 5 6 7 8 9 10 ...
##   ..- attr(*, "names")= chr [1:1827] "1" "2" "3" "4" ...
# convert into xts
etf6.xts <- xts(etf6.l[, -1], order.by = as.Date(as.character(etf6.l$date), format = '%Y%m%d'))
class(etf6.xts)
## [1] "xts" "zoo"
head(etf6.xts)
##            0050    0052    0056    0061    006206  00638R 
## 2015-05-18 58.6843 34.8094 19.0693   21.77   33.46   20.03
## 2015-05-19 59.5614 34.8596 19.1931   22.43   34.46   19.51
## 2015-05-20 59.1437 35.0268 19.1931   22.70   34.91   19.19
## 2015-05-21 58.6007 34.6339 18.9687   22.79   35.03   19.17
## 2015-05-22 59.0602 35.1104 18.9919   23.33   35.90   18.60
## 2015-05-25 59.0602 34.8596 18.9687   23.65   36.80   17.99
# SIT 
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:base':
## 
##     close
#
data <- new.env()

model <- list()

etf3 <- etf6.xts[, 1:3]
head(etf3)
##            0050    0052    0056   
## 2015-05-18 58.6843 34.8094 19.0693
## 2015-05-19 59.5614 34.8596 19.1931
## 2015-05-20 59.1437 35.0268 19.1931
## 2015-05-21 58.6007 34.6339 18.9687
## 2015-05-22 59.0602 35.1104 18.9919
## 2015-05-25 59.0602 34.8596 18.9687
names(etf3)
## [1] "0050   " "0052   " "0056   "
colnames(etf3) <- c('e50', 'e52', 'e56')
names(etf3)
## [1] "e50" "e52" "e56"
md = 50
i = 'e50'
for(i in names(etf3)) {
  data$prices = data$weight = data$execution.price = etf3[, i]
  data$weight[] <- 1
  data$execution.price[] <- NA
  model[[i]] <- bt.run(data)
  sma <- SMA(data$prices, md)
  data$weight[] <- iif(data$prices >= sma, 1, 0)
  i <- paste(i, '.sma.cross', sep = '')
  model[[i]] <- bt.run(data)
}
## Latest weights :
##            e50
## 2020-04-30 100
## 
## Performance summary :
##  CAGR    Best    Worst   
##  7.9 8   -7  
## 
## Latest weights :
##            e50
## 2020-04-30 100
## 
## Performance summary :
##  CAGR    Best    Worst   
##  5.8 2.3 -5.7    
## 
## Latest weights :
##            e52
## 2020-04-30 100
## 
## Performance summary :
##  CAGR    Best    Worst   
##  13.3    10  -9.2    
## 
## Latest weights :
##            e52
## 2020-04-30 100
## 
## Performance summary :
##  CAGR    Best    Worst   
##  10.6    4.3 -6.7    
## 
## Latest weights :
##            e56
## 2020-04-30 100
## 
## Performance summary :
##  CAGR    Best    Worst   
##  7.6 6.5 -6.2    
## 
## Latest weights :
##            e56
## 2020-04-30 100
## 
## Performance summary :
##  CAGR    Best    Worst   
##  6.1 2.4 -5.1    
#-------------------------------------------------
strategy.performance.snapshoot(model, T)

## NULL
plotbt(model, plotX = T, log = 'y', LeftMargin = 3)            
mtext('Cumulative Performance', side = 2, line = 1)
plotbt.strategy.sidebyside(model, return.table=T, make.plot = F)
##            e50                 e50.sma.cross       e52                
## Period     "May2015 - Apr2020" "May2015 - Apr2020" "May2015 - Apr2020"
## Cagr       "7.89"              "5.83"              "13.34"            
## Sharpe     "0.56"              "0.63"              "0.7"              
## DVR        "0.47"              "0.36"              "0.6"              
## Volatility "16.23"             "10.01"             "21.67"            
## MaxDD      "-28.22"            "-19.71"            "-30.2"            
## AvgDD      "-2.67"             "-2.52"             "-3.55"            
## VaR        "-1.51"             "-1"                "-2.07"            
## CVaR       "-2.4"              "-1.63"             "-3.11"            
## Exposure   "99.92"             "61.61"             "99.92"            
##            e52.sma.cross       e56                 e56.sma.cross      
## Period     "May2015 - Apr2020" "May2015 - Apr2020" "May2015 - Apr2020"
## Cagr       "10.63"             "7.63"              "6.05"             
## Sharpe     "0.84"              "0.66"              "0.8"              
## DVR        "0.68"              "0.6"               "0.62"             
## Volatility "13.4"              "12.68"             "7.97"             
## MaxDD      "-19.08"            "-25.15"            "-10.39"           
## AvgDD      "-2.78"             "-2.56"             "-1.95"            
## VaR        "-1.35"             "-1.22"             "-0.84"            
## CVaR       "-2.1"              "-2.06"             "-1.36"            
## Exposure   "63.18"             "99.92"             "63.1"
# --------------------------------------------------
# Add equal-weighted portfolio for 3 ETFs
# --------------------------------------------------
data$prices = data$weight = data$execution.price = etf3
data$execution.price[] <- NA
prices <- data$prices
n <- ncol(prices)
data$weight <- ntop(prices, n)
model$etf3.EqWeight.bh <- bt.run(data)
## Latest weights :
##              e50   e52   e56
## 2020-04-30 33.33 33.33 33.33
## 
## Performance summary :
##  CAGR    Best    Worst   
##  10  7.5 -6.2    
#
strategy.performance.snapshoot(model, T)

## NULL
plotbt(model, plotX = T, log = 'y', LeftMargin = 3)            
mtext('Cumulative Performance', side = 2, line = 1)
plotbt.strategy.sidebyside(model, return.table=T, make.plot = F)
##            e50                 e50.sma.cross       e52                
## Period     "May2015 - Apr2020" "May2015 - Apr2020" "May2015 - Apr2020"
## Cagr       "7.89"              "5.83"              "13.34"            
## Sharpe     "0.56"              "0.63"              "0.7"              
## DVR        "0.47"              "0.36"              "0.6"              
## Volatility "16.23"             "10.01"             "21.67"            
## MaxDD      "-28.22"            "-19.71"            "-30.2"            
## AvgDD      "-2.67"             "-2.52"             "-3.55"            
## VaR        "-1.51"             "-1"                "-2.07"            
## CVaR       "-2.4"              "-1.63"             "-3.11"            
## Exposure   "99.92"             "61.61"             "99.92"            
##            e52.sma.cross       e56                 e56.sma.cross      
## Period     "May2015 - Apr2020" "May2015 - Apr2020" "May2015 - Apr2020"
## Cagr       "10.63"             "7.63"              "6.05"             
## Sharpe     "0.84"              "0.66"              "0.8"              
## DVR        "0.68"              "0.6"               "0.62"             
## Volatility "13.4"              "12.68"             "7.97"             
## MaxDD      "-19.08"            "-25.15"            "-10.39"           
## AvgDD      "-2.78"             "-2.56"             "-1.95"            
## VaR        "-1.35"             "-1.22"             "-0.84"            
## CVaR       "-2.1"              "-2.06"             "-1.36"            
## Exposure   "63.18"             "99.92"             "63.1"             
##            etf3.EqWeight.bh   
## Period     "May2015 - Apr2020"
## Cagr       "9.96"             
## Sharpe     "0.72"             
## DVR        "0.64"             
## Volatility "15.12"            
## MaxDD      "-27.42"           
## AvgDD      "-2.37"            
## VaR        "-1.4"             
## CVaR       "-2.28"            
## Exposure   "99.92"
#=============================================================
# MVP investment strategy
#=============================================================
# monthly rebalance
# covariance matrix 
# use monthly returns to compute monthly covariance matrix
etf3.m <- to.monthly(etf3, indexAt = 'lastof', OHLC = FALSE)
head(etf3.m)
##                e50     e52     e56
## 2015-05-31 59.3943 35.3361 19.1312
## 2015-06-30 57.9742 33.8397 18.3418
## 2015-07-31 55.2593 31.4489 16.9875
## 2015-08-31 52.0431 28.6985 16.0820
## 2015-09-30 52.1267 29.5512 16.2832
## 2015-10-31 54.4474 31.1813 17.5373
etf3.w <- to.weekly(etf3, indexAt = 'lastof', OHLC = FALSE)
head(etf3.w)
##                e50     e52     e56
## 2015-05-22 59.0602 35.1104 18.9919
## 2015-05-29 59.3943 35.3361 19.1312
## 2015-06-05 57.1806 33.7477 18.5740
## 2015-06-12 57.4730 33.7227 18.0710
## 2015-06-18 57.1388 33.6474 18.1948
## 2015-06-26 58.8513 38.2536 18.5353
# 

#=================================================================
# MVP portfolio
#=================================================================
# Reset inputs to SIT bt function
data$prices = data$weight = data$execution.price = etf3.m
#data$prices <- industry.price.sample
#data$weight <- industry.price.sample
#data$execution.price <- industry.price.sample
data$execution.price[] <- NA
prices <- data$prices
n <- ncol(prices)
#*****************************************************************
# Create Constraints
#*****************************************************************
constraints = new.constraints(n, lb = 0, ub = +Inf)
# SUM x.i = 1
constraints = add.constraints(rep(1, n), 1, type = '=', constraints)        
#
ret = prices / mlag(prices) - 1
weight = coredata(prices)
weight[] = NA
i = 36
for (i in 36:dim(weight)[1]) {
  # using 36 historical monthly returns
  hist = ret[ (i- 36 +1):i, ]
  hist = na.omit(hist)
  # create historical input assumptions
  ia = create.historical.ia(hist, 12)
  # s0 = apply(coredata(hist),2, sd)     
  ia$cov = cov(coredata(hist))
  #ia$cov = cor(coredata(hist), use='complete.obs',method='kendall') * (s0 %*% t(s0))
  # use min.risk.portfolio() to compute MVP weights
  weight[i,] = min.risk.portfolio(ia, constraints)
}
## Loading required package: kernlab
## 
## Attaching package: 'kernlab'
## The following object is masked from 'package:SIT':
## 
##     cross
#
weight
##                e50          e52       e56
##  [1,]           NA           NA        NA
##  [2,]           NA           NA        NA
##  [3,]           NA           NA        NA
##  [4,]           NA           NA        NA
##  [5,]           NA           NA        NA
##  [6,]           NA           NA        NA
##  [7,]           NA           NA        NA
##  [8,]           NA           NA        NA
##  [9,]           NA           NA        NA
## [10,]           NA           NA        NA
## [11,]           NA           NA        NA
## [12,]           NA           NA        NA
## [13,]           NA           NA        NA
## [14,]           NA           NA        NA
## [15,]           NA           NA        NA
## [16,]           NA           NA        NA
## [17,]           NA           NA        NA
## [18,]           NA           NA        NA
## [19,]           NA           NA        NA
## [20,]           NA           NA        NA
## [21,]           NA           NA        NA
## [22,]           NA           NA        NA
## [23,]           NA           NA        NA
## [24,]           NA           NA        NA
## [25,]           NA           NA        NA
## [26,]           NA           NA        NA
## [27,]           NA           NA        NA
## [28,]           NA           NA        NA
## [29,]           NA           NA        NA
## [30,]           NA           NA        NA
## [31,]           NA           NA        NA
## [32,]           NA           NA        NA
## [33,]           NA           NA        NA
## [34,]           NA           NA        NA
## [35,]           NA           NA        NA
## [36,] 5.708131e-01 1.013557e-05 0.4291768
## [37,] 5.938460e-01 1.178948e-05 0.4061422
## [38,] 5.677347e-01 1.256961e-05 0.4322528
## [39,] 4.303263e-01 1.376488e-05 0.5696600
## [40,] 4.636123e-01 2.088299e-05 0.5363669
## [41,] 4.977120e-01 2.056603e-05 0.5022675
## [42,] 8.947075e-02 1.760397e-05 0.9105116
## [43,] 1.644829e-01 1.174734e-05 0.8355054
## [44,] 1.230427e-01 1.322863e-05 0.8769441
## [45,] 1.981367e-01 1.111005e-05 0.8018522
## [46,] 1.536536e-01 1.271208e-05 0.8463337
## [47,] 1.360303e-01 1.363474e-05 0.8639561
## [48,] 1.625490e-01 1.377061e-05 0.8374372
## [49,] 1.589876e-01 1.096594e-05 0.8410014
## [50,] 1.633204e-01 1.098421e-05 0.8366686
## [51,] 2.059597e-02 1.548506e-05 0.9793885
## [52,] 1.564765e-02 1.527667e-05 0.9843371
## [53,] 1.038049e-02 1.519358e-05 0.9896043
## [54,] 9.702991e-04 1.160429e-05 0.9990181
## [55,] 5.009475e-04 1.216192e-05 0.9994869
## [56,] 1.938941e-04 1.063642e-05 0.9997955
## [57,] 1.408883e-04 9.698083e-06 0.9998494
## [58,] 7.660880e-05 8.422007e-06 0.9999150
## [59,] 2.533141e-05 6.006477e-06 0.9999687
## [60,] 2.019810e-05 5.206983e-06 0.9999746
weight <- round(weight, digits = 2)
#format(round(weight, 2), nsmall = 2)
#apply(weight, 1, sum)

data$weight[] = weight     
#capital = 100000
#data$weight[] = (capital / prices) * data$weight
model$mvp.month = bt.run(data, type = "weight")
## Latest weights :
##            e50 e52 e56
## 2020-04-30   0   0 100
## 
## Performance summary :
##  CAGR    Best    Worst   
##  4   12.1    -12.2   
#
plotbt.strategy.sidebyside(model, return.table=T, make.plot = T)

##            e50                 e50.sma.cross       e52                
## Period     "May2015 - Apr2020" "May2015 - Apr2020" "May2015 - Apr2020"
## Cagr       "7.89"              "5.83"              "13.34"            
## Sharpe     "0.56"              "0.63"              "0.7"              
## DVR        "0.47"              "0.36"              "0.6"              
## Volatility "16.23"             "10.01"             "21.67"            
## MaxDD      "-28.22"            "-19.71"            "-30.2"            
## AvgDD      "-2.67"             "-2.52"             "-3.55"            
## VaR        "-1.51"             "-1"                "-2.07"            
## CVaR       "-2.4"              "-1.63"             "-3.11"            
## Exposure   "99.92"             "61.61"             "99.92"            
##            e52.sma.cross       e56                 e56.sma.cross      
## Period     "May2015 - Apr2020" "May2015 - Apr2020" "May2015 - Apr2020"
## Cagr       "10.63"             "7.63"              "6.05"             
## Sharpe     "0.84"              "0.66"              "0.8"              
## DVR        "0.68"              "0.6"               "0.62"             
## Volatility "13.4"              "12.68"             "7.97"             
## MaxDD      "-19.08"            "-25.15"            "-10.39"           
## AvgDD      "-2.78"             "-2.56"             "-1.95"            
## VaR        "-1.35"             "-1.22"             "-0.84"            
## CVaR       "-2.1"              "-2.06"             "-1.36"            
## Exposure   "63.18"             "99.92"             "63.1"             
##            etf3.EqWeight.bh    mvp.month          
## Period     "May2015 - Apr2020" "May2015 - Apr2020"
## Cagr       "9.96"              "3.99"             
## Sharpe     "0.72"              "0.41"             
## DVR        "0.64"              "0.23"             
## Volatility "15.12"             "10.9"             
## MaxDD      "-27.42"            "-15.46"           
## AvgDD      "-2.37"             "-7.77"            
## VaR        "-1.4"              "-3.7"             
## CVaR       "-2.28"             "-8.86"            
## Exposure   "99.92"             "40"
plotbt(model)