R Markdown

This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.

When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:

install.packages("pacman")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.2'
## (as 'lib' is unspecified)
install.packages('curl', repos = 'http://cran.r-project.org')
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.2'
## (as 'lib' is unspecified)
install.packages("devtools")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.2'
## (as 'lib' is unspecified)
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✔ ggplot2 3.3.5     ✔ purrr   0.3.4
## ✔ tibble  3.1.6     ✔ dplyr   1.0.9
## ✔ tidyr   1.2.0     ✔ stringr 1.4.0
## ✔ readr   2.1.2     ✔ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
library(readr)
ETF6_20080101_20200430 <- read_csv("ETF6_20080101-20200430.csv")
## Rows: 14935 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): 證券代碼, 簡稱
## dbl (2): 年月日, 收盤價(元)
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
rm(list = ls())

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':    3041 obs. of  7 variables:
##  $ date   : int  20080102 20080103 20080104 20080107 20080108 20080109 20080110 20080111 20080114 20080115 ...
##  $ 0050   : num  39.6 39 39 37.2 37.6 ...
##  $ 0052   : num  27.1 26.1 25.9 24.1 24.1 ...
##  $ 0056   : num  14.6 14.4 14.4 14.2 14.4 ...
##  $ 0061   : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 006206 : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 00638R : num  NA NA NA NA NA NA NA NA NA NA ...
# 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 
## 2008-01-02 39.6472 27.0983 14.5739      NA      NA      NA
## 2008-01-03 38.9876 26.0676 14.3758      NA      NA      NA
## 2008-01-04 38.9876 25.9346 14.4041      NA      NA      NA
## 2008-01-07 37.2064 24.1391 14.1777      NA      NA      NA
## 2008-01-08 37.5692 24.1391 14.3531      NA      NA      NA
## 2008-01-09 38.2619 24.2721 14.4663      NA      NA      NA
# SIT 

devtools::install_github('systematicinvestor/SIT.date')
## Skipping install of 'SIT.date' from a github remote, the SHA1 (6263da60) has not changed since last install.
##   Use `force = TRUE` to force installation
library(curl)
## Using libcurl 7.68.0 with GnuTLS/3.6.13
## 
## Attaching package: 'curl'
## 
## The following object is masked from 'package:readr':
## 
##     parse_date
curl_download('https://github.com/systematicinvestor/SIT/raw/master/SIT.tar.gz', 'sit',mode = 'wb',quiet=T)
install.packages('sit', repos = NULL, type='source')
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.2'
## (as 'lib' is unspecified)
library(SIT)
## Loading required package: SIT.date
## 
## Attaching package: 'SIT'
## 
## The following object is masked from 'package:TTR':
## 
##     DVI
## 
## The following objects are masked from 'package:dplyr':
## 
##     count, lst
## 
## The following object is masked from 'package:purrr':
## 
##     cross
## 
## The following object is masked from 'package:tibble':
## 
##     lst
## 
## The following object is masked from 'package:base':
## 
##     close
#
data <- new.env()
# 1. prices; 2. weight; 3. execution.price
# buy and hold
# etf56 <- etf6.xts$`0056`
# head(etf56)
# data$prices = data$weight = data$execution.price = etf56
# data$weight[] <- 1
# data$execution.price[] <- NA
# names(data)
# 
# etf52 <- etf6.xts$`0052`
# head(etf52)
# data$prices = data$weight = data$execution.price = etf52
# data$weight[] <- 1
# data$execution.price[] <- NA
# names(data)
#
model <- list()
#
last <- xts::last
etf3 <- etf6.xts[, 1:3]
head(etf3)
##            0050    0052    0056   
## 2008-01-02 39.6472 27.0983 14.5739
## 2008-01-03 38.9876 26.0676 14.3758
## 2008-01-04 38.9876 25.9346 14.4041
## 2008-01-07 37.2064 24.1391 14.1777
## 2008-01-08 37.5692 24.1391 14.3531
## 2008-01-09 38.2619 24.2721 14.4663
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   
##  6.4 8   -7  
## 
## Latest weights :
##            e50
## 2020-04-30 100
## 
## Performance summary :
##  CAGR    Best    Worst   
##  5.3 7   -6.4    
## 
## Latest weights :
##            e52
## 2020-04-30 100
## 
## Performance summary :
##  CAGR    Best    Worst   
##  7.3 10  -9.2    
## 
## Latest weights :
##            e52
## 2020-04-30 100
## 
## Performance summary :
##  CAGR    Best    Worst   
##  0.9 10  -9.2    
## 
## Latest weights :
##            e56
## 2020-04-30 100
## 
## Performance summary :
##  CAGR    Best    Worst   
##  5.3 7   -6.9    
## 
## Latest weights :
##            e56
## 2020-04-30 100
## 
## Performance summary :
##  CAGR    Best    Worst   
##  9.9 7   -5.3    
#-------------------------------------------------
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     "Jan2008 - Apr2020" "Jan2008 - Apr2020" "Jan2008 - Apr2020"
## Cagr       "6.43"              "5.3"               "7.32"             
## Sharpe     "0.42"              "0.49"              "0.41"             
## DVR        "0.37"              "0.39"              "0.33"             
## Volatility "20.06"             "12.22"             "26.2"             
## MaxDD      "-52.38"            "-23.13"            "-59.41"           
## AvgDD      "-3.57"             "-3.08"             "-5.19"            
## VaR        "-1.93"             "-1.17"             "-2.64"            
## CVaR       "-3.07"             "-1.94"             "-3.94"            
## Exposure   "99.97"             "62.08"             "99.97"            
##            e52.sma.cross       e56                 e56.sma.cross      
## Period     "Jan2008 - Apr2020" "Jan2008 - Apr2020" "Jan2008 - Apr2020"
## Cagr       "0.93"              "5.27"              "9.94"             
## Sharpe     "0.14"              "0.39"              "0.99"             
## DVR        "0.03"              "0.33"              "0.93"             
## Volatility "17.63"             "17.17"             "10.38"            
## MaxDD      "-56.14"            "-54.36"            "-14.95"           
## AvgDD      "-7.84"             "-3.42"             "-2.15"            
## VaR        "-1.74"             "-1.61"             "-0.93"            
## CVaR       "-2.93"             "-2.86"             "-1.62"            
## Exposure   "60.77"             "99.97"             "61.82"
# --------------------------------------------------
# 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   
##  6.9 7.5 -7  
#
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     "Jan2008 - Apr2020" "Jan2008 - Apr2020" "Jan2008 - Apr2020"
## Cagr       "6.43"              "5.3"               "7.32"             
## Sharpe     "0.42"              "0.49"              "0.41"             
## DVR        "0.37"              "0.39"              "0.33"             
## Volatility "20.06"             "12.22"             "26.2"             
## MaxDD      "-52.38"            "-23.13"            "-59.41"           
## AvgDD      "-3.57"             "-3.08"             "-5.19"            
## VaR        "-1.93"             "-1.17"             "-2.64"            
## CVaR       "-3.07"             "-1.94"             "-3.94"            
## Exposure   "99.97"             "62.08"             "99.97"            
##            e52.sma.cross       e56                 e56.sma.cross      
## Period     "Jan2008 - Apr2020" "Jan2008 - Apr2020" "Jan2008 - Apr2020"
## Cagr       "0.93"              "5.27"              "9.94"             
## Sharpe     "0.14"              "0.39"              "0.99"             
## DVR        "0.03"              "0.33"              "0.93"             
## Volatility "17.63"             "17.17"             "10.38"            
## MaxDD      "-56.14"            "-54.36"            "-14.95"           
## AvgDD      "-7.84"             "-3.42"             "-2.15"            
## VaR        "-1.74"             "-1.61"             "-0.93"            
## CVaR       "-2.93"             "-2.86"             "-1.62"            
## Exposure   "60.77"             "99.97"             "61.82"            
##            etf3.EqWeight.bh   
## Period     "Jan2008 - Apr2020"
## Cagr       "6.86"             
## Sharpe     "0.45"             
## DVR        "0.4"              
## Volatility "19"               
## MaxDD      "-54.89"           
## AvgDD      "-2.99"            
## VaR        "-1.88"            
## CVaR       "-2.97"            
## Exposure   "99.97"
#=============================================================
# 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
## 2008-01-31 36.2499 23.2680 12.8646
## 2008-02-29 40.1420 25.5356 14.0079
## 2008-03-31 39.8781 25.1366 14.4324
## 2008-04-30 42.1541 26.7326 14.8851
## 2008-05-31 41.0326 26.1008 14.5625
## 2008-06-30 36.2828 23.1416 12.9608
etf3.w <- to.weekly(etf3, indexAt = 'lastof', OHLC = FALSE)
## Warning in !missing(sec) && sec%%1 != 0: 'length(x) = 635 > 1' in coercion to
## 'logical(1)'
head(etf3.w)
##                e50     e52     e56
## 2008-01-04 38.9876 25.9346 14.4041
## 2008-01-11 38.0310 24.3319 14.6022
## 2008-01-18 38.5917 23.8598 14.1777
## 2008-01-25 37.2064 23.6071 13.4702
## 2008-02-01 37.2064 23.4475 13.0457
## 2008-02-15 37.8001 23.9396 13.3004
# 

#=================================================================
# 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
## 
## The following object is masked from 'package:purrr':
## 
##     cross
## 
## The following object is masked from 'package:ggplot2':
## 
##     alpha
#
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,] 3.548395e-01 3.249237e-06 0.645157209
##  [37,] 3.501257e-01 3.383977e-06 0.649870930
##  [38,] 3.954709e-01 5.865392e-05 0.604470484
##  [39,] 4.192845e-01 5.503587e-05 0.580660509
##  [40,] 4.492127e-01 5.870654e-05 0.550728555
##  [41,] 4.660544e-01 5.882625e-05 0.533886777
##  [42,] 4.141297e-01 5.637663e-05 0.585813917
##  [43,] 3.558882e-01 3.327323e-06 0.644108502
##  [44,] 4.180990e-01 6.984814e-05 0.581831113
##  [45,] 6.707811e-05 9.737346e-06 0.999923185
##  [46,] 3.603791e-05 1.255191e-05 0.999951410
##  [47,] 9.264865e-05 4.022900e-05 0.999867122
##  [48,] 6.367868e-05 2.478303e-05 0.999911538
##  [49,] 1.868810e-03 5.399110e-05 0.998077199
##  [50,] 4.308897e-03 3.884127e-04 0.995302690
##  [51,] 9.343817e-05 1.343380e-01 0.865568534
##  [52,] 7.659467e-05 1.864131e-03 0.998059275
##  [53,] 1.143490e-01 8.566478e-05 0.885565311
##  [54,] 1.739962e-01 1.537630e-04 0.825849993
##  [55,] 7.104099e-05 1.039039e-01 0.896025043
##  [56,] 7.217282e-05 5.296033e-02 0.946967496
##  [57,] 3.725149e-04 3.906479e-02 0.960562692
##  [58,] 4.676133e-02 2.344156e-01 0.718823071
##  [59,] 3.532859e-03 2.579955e-01 0.738471634
##  [60,] 1.471350e-04 3.032328e-01 0.696620015
##  [61,] 3.383555e-04 3.534301e-01 0.646231579
##  [62,] 4.514338e-04 3.584635e-01 0.641085100
##  [63,] 1.019360e-03 3.801865e-01 0.618794174
##  [64,] 4.854637e-02 3.125623e-01 0.638891361
##  [65,] 1.757853e-01 2.905735e-01 0.533641180
##  [66,] 2.389682e-01 2.390117e-01 0.522020088
##  [67,] 2.180737e-01 2.525311e-01 0.529395149
##  [68,] 2.073465e-01 2.890609e-01 0.503592549
##  [69,] 2.920664e-01 3.030327e-01 0.404900929
##  [70,] 2.108804e-01 3.128610e-01 0.476258624
##  [71,] 2.119345e-01 3.248594e-01 0.463206126
##  [72,] 4.205077e-01 2.291860e-01 0.350306293
##  [73,] 3.941721e-01 2.598153e-01 0.346012636
##  [74,] 3.881702e-01 3.272173e-01 0.284612469
##  [75,] 3.731096e-01 3.006048e-01 0.326285633
##  [76,] 4.414048e-01 2.592310e-01 0.299364231
##  [77,] 5.565125e-01 1.740247e-01 0.269462833
##  [78,] 5.918189e-01 2.793501e-01 0.128830929
##  [79,] 5.949265e-01 2.753396e-01 0.129733898
##  [80,] 6.207780e-01 2.237308e-01 0.155491196
##  [81,] 9.201688e-01 1.080510e-02 0.069026055
##  [82,] 8.867629e-01 4.903935e-03 0.108333126
##  [83,] 9.773911e-01 3.738151e-04 0.022235061
##  [84,] 9.254658e-01 4.472267e-04 0.074086991
##  [85,] 8.360549e-01 1.961012e-03 0.161984103
##  [86,] 8.056748e-01 1.021364e-03 0.193303821
##  [87,] 7.458415e-01 2.731037e-04 0.253885435
##  [88,] 8.362098e-01 1.390575e-04 0.163651096
##  [89,] 8.933735e-01 2.809926e-04 0.106345470
##  [90,] 9.348899e-01 1.385098e-04 0.064971584
##  [91,] 9.924601e-01 4.339439e-05 0.007496475
##  [92,] 9.400630e-01 2.133533e-05 0.059915630
##  [93,] 9.921954e-01 4.080649e-05 0.007763758
##  [94,] 8.964081e-01 2.208673e-05 0.103569788
##  [95,] 8.537640e-01 2.409648e-05 0.146211922
##  [96,] 8.302974e-01 2.675367e-05 0.169675804
##  [97,] 7.757457e-01 2.474003e-05 0.224229587
##  [98,] 8.180390e-01 2.323727e-05 0.181937734
##  [99,] 6.736303e-01 1.867559e-05 0.326350995
## [100,] 6.111157e-01 1.689412e-05 0.388867428
## [101,] 6.049608e-01 1.557929e-05 0.395023572
## [102,] 6.157108e-01 1.820289e-05 0.384270988
## [103,] 6.775525e-01 1.234945e-05 0.322435161
## [104,] 6.636579e-01 1.164560e-05 0.336330470
## [105,] 6.601354e-01 1.074428e-05 0.339853883
## [106,] 6.879546e-01 1.126581e-05 0.312034175
## [107,] 6.844247e-01 1.025015e-05 0.315565029
## [108,] 6.914718e-01 1.012252e-05 0.308518114
## [109,] 7.266469e-01 1.102526e-05 0.273342115
## [110,] 7.544220e-01 1.121070e-05 0.245566783
## [111,] 7.633757e-01 1.322273e-05 0.236611062
## [112,] 7.673717e-01 1.342543e-05 0.232614887
## [113,] 7.324403e-01 1.468977e-05 0.267545033
## [114,] 7.469210e-01 1.429787e-05 0.253064687
## [115,] 7.488131e-01 1.294000e-05 0.251174003
## [116,] 7.217452e-01 1.149741e-05 0.278243316
## [117,] 6.290584e-01 1.247859e-05 0.370929153
## [118,] 5.882724e-01 9.407269e-06 0.411718152
## [119,] 5.763055e-01 1.353535e-05 0.423680937
## [120,] 5.742669e-01 1.493682e-05 0.425718170
## [121,] 5.854529e-01 1.184987e-05 0.414535213
## [122,] 5.759277e-01 1.261745e-05 0.424059711
## [123,] 5.930528e-01 1.465591e-05 0.406932508
## [124,] 5.781426e-01 1.058465e-05 0.421846812
## [125,] 5.938460e-01 1.178948e-05 0.406142176
## [126,] 5.677347e-01 1.256961e-05 0.432252773
## [127,] 4.303263e-01 1.376488e-05 0.569659958
## [128,] 4.636123e-01 2.088299e-05 0.536366866
## [129,] 4.977120e-01 2.056603e-05 0.502267459
## [130,] 8.947075e-02 1.760397e-05 0.910511642
## [131,] 1.644829e-01 1.174734e-05 0.835505359
## [132,] 1.230427e-01 1.322863e-05 0.876944118
## [133,] 1.981367e-01 1.111005e-05 0.801852195
## [134,] 1.536536e-01 1.271208e-05 0.846333689
## [135,] 1.360303e-01 1.363474e-05 0.863956080
## [136,] 1.625490e-01 1.377061e-05 0.837437224
## [137,] 1.589876e-01 1.096594e-05 0.841001385
## [138,] 1.633204e-01 1.098421e-05 0.836668635
## [139,] 2.059597e-02 1.548506e-05 0.979388545
## [140,] 1.564765e-02 1.527667e-05 0.984337077
## [141,] 1.038049e-02 1.519358e-05 0.989604321
## [142,] 9.702991e-04 1.160429e-05 0.999018097
## [143,] 5.009475e-04 1.216192e-05 0.999486891
## [144,] 1.938941e-04 1.063642e-05 0.999795469
## [145,] 1.408883e-04 9.698083e-06 0.999849414
## [146,] 7.660880e-05 8.422007e-06 0.999914969
## [147,] 2.533141e-05 6.006477e-06 0.999968662
## [148,] 2.019810e-05 5.206983e-06 0.999974595
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   
##  5.1 12.1    -12.2   
#
plotbt.strategy.sidebyside(model, return.table=T, make.plot = T)

##            e50                 e50.sma.cross       e52                
## Period     "Jan2008 - Apr2020" "Jan2008 - Apr2020" "Jan2008 - Apr2020"
## Cagr       "6.43"              "5.3"               "7.32"             
## Sharpe     "0.42"              "0.49"              "0.41"             
## DVR        "0.37"              "0.39"              "0.33"             
## Volatility "20.06"             "12.22"             "26.2"             
## MaxDD      "-52.38"            "-23.13"            "-59.41"           
## AvgDD      "-3.57"             "-3.08"             "-5.19"            
## VaR        "-1.93"             "-1.17"             "-2.64"            
## CVaR       "-3.07"             "-1.94"             "-3.94"            
## Exposure   "99.97"             "62.08"             "99.97"            
##            e52.sma.cross       e56                 e56.sma.cross      
## Period     "Jan2008 - Apr2020" "Jan2008 - Apr2020" "Jan2008 - Apr2020"
## Cagr       "0.93"              "5.27"              "9.94"             
## Sharpe     "0.14"              "0.39"              "0.99"             
## DVR        "0.03"              "0.33"              "0.93"             
## Volatility "17.63"             "17.17"             "10.38"            
## MaxDD      "-56.14"            "-54.36"            "-14.95"           
## AvgDD      "-7.84"             "-3.42"             "-2.15"            
## VaR        "-1.74"             "-1.61"             "-0.93"            
## CVaR       "-2.93"             "-2.86"             "-1.62"            
## Exposure   "60.77"             "99.97"             "61.82"            
##            etf3.EqWeight.bh    mvp.month          
## Period     "Jan2008 - Apr2020" "Jan2008 - Apr2020"
## Cagr       "6.86"              "5.14"             
## Sharpe     "0.45"              "0.49"             
## DVR        "0.4"               "0.37"             
## Volatility "19"                "11.6"             
## MaxDD      "-54.89"            "-17.84"           
## AvgDD      "-2.99"             "-6.42"            
## VaR        "-1.88"             "-5.38"            
## CVaR       "-2.97"             "-8.1"             
## Exposure   "99.97"             "75.68"
plotbt(model)
#====================
# multiple models
#====================
#*****************************************************************
# Create Constraints
#*****************************************************************
constraints = new.constraints(n, lb = 0, ub = 1)

# SUM x.i = 1
constraints = add.constraints(rep(1, n), 1, type = '=', constraints)        

#*****************************************************************
# Create Portfolios
#*****************************************************************          
ret = prices / mlag(prices) - 1
weight = coredata(prices)
weight[] = NA
#
weights = list()
# Equal Weight 1/N Benchmark
weights$equal.weight = weight
weights$equal.weight[] = ntop(prices, n)
start.i = 35
weights$equal.weight[1:start.i,] = NA
#
weights$min.var = weight
weights$min.maxloss = weight
weights$min.mad = weight
weights$min.cvar = weight
weights$min.cdar = weight
weights$min.cor.insteadof.cov = weight
weights$min.mad.downside = weight
weights$min.risk.downside = weight
#
#
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)
  
}

models = list()
# i = "equal.weight"
for(i in names(weights)) {
  data$weight[] = NA
  data$weight[] = weights[[i]]    
  models[[i]] = bt.run.share(data, clean.signal = F)
}
## Latest weights :
##              e50   e52   e56
## 2020-04-30 33.33 33.33 33.33
## 
## Performance summary :
##  CAGR    Best    Worst   
##  5.6 12.9    -13.4   
## 
## Latest weights :
##            e50 e52 e56
## 2020-04-30   0   0   0
## 
## Performance summary :
##  CAGR    Best    Worst   
##  0   0   0   
## 
## Latest weights :
##            e50 e52 e56
## 2020-04-30   0   0   0
## 
## Performance summary :
##  CAGR    Best    Worst   
##  0   0   0   
## 
## Latest weights :
##            e50 e52 e56
## 2020-04-30   0   0   0
## 
## Performance summary :
##  CAGR    Best    Worst   
##  0   0   0   
## 
## Latest weights :
##            e50 e52 e56
## 2020-04-30   0   0   0
## 
## Performance summary :
##  CAGR    Best    Worst   
##  0   0   0   
## 
## Latest weights :
##            e50 e52 e56
## 2020-04-30   0   0   0
## 
## Performance summary :
##  CAGR    Best    Worst   
##  0   0   0   
## 
## Latest weights :
##            e50 e52 e56
## 2020-04-30   0   0   0
## 
## Performance summary :
##  CAGR    Best    Worst   
##  0   0   0   
## 
## Latest weights :
##            e50 e52 e56
## 2020-04-30   0   0   0
## 
## Performance summary :
##  CAGR    Best    Worst   
##  0   0   0   
## 
## Latest weights :
##            e50 e52 e56
## 2020-04-30   0   0   0
## 
## Performance summary :
##  CAGR    Best    Worst   
##  0   0   0   
# Plot perfromance
plotbt(models, plotX = T, log = 'y', LeftMargin = 3)            
mtext('Cumulative Performance', side = 2, line = 1)

# Plot Strategy Statistics  Side by Side
plotbt.strategy.sidebyside(models)
## Warning in cor(y, x): the standard deviation is zero
## Warning in min(drawdown[x[1]:x[2]], na.rm = T): no non-missing arguments to min;
## returning Inf
## Warning in cor(y, x): the standard deviation is zero
## Warning in min(drawdown[x[1]:x[2]], na.rm = T): no non-missing arguments to min;
## returning Inf
## Warning in cor(y, x): the standard deviation is zero
## Warning in min(drawdown[x[1]:x[2]], na.rm = T): no non-missing arguments to min;
## returning Inf
## Warning in cor(y, x): the standard deviation is zero
## Warning in min(drawdown[x[1]:x[2]], na.rm = T): no non-missing arguments to min;
## returning Inf
## Warning in cor(y, x): the standard deviation is zero
## Warning in min(drawdown[x[1]:x[2]], na.rm = T): no non-missing arguments to min;
## returning Inf
## Warning in cor(y, x): the standard deviation is zero
## Warning in min(drawdown[x[1]:x[2]], na.rm = T): no non-missing arguments to min;
## returning Inf
## Warning in cor(y, x): the standard deviation is zero
## Warning in min(drawdown[x[1]:x[2]], na.rm = T): no non-missing arguments to min;
## returning Inf
## Warning in cor(y, x): the standard deviation is zero
## Warning in min(drawdown[x[1]:x[2]], na.rm = T): no non-missing arguments to min;
## returning Inf
summary(cars)
##      speed           dist       
##  Min.   : 4.0   Min.   :  2.00  
##  1st Qu.:12.0   1st Qu.: 26.00  
##  Median :15.0   Median : 36.00  
##  Mean   :15.4   Mean   : 42.98  
##  3rd Qu.:19.0   3rd Qu.: 56.00  
##  Max.   :25.0   Max.   :120.00

Including Plots

You can also embed plots, for example:

Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot.