1.Download 10 industry portfolio returns

rm(list=ls())
industry10 <- read.table('10_Industry_Portfolios_Wout_Div01.txt', header = TRUE )
str(industry10)
## 'data.frame':    1126 obs. of  11 variables:
##  $ Date : int  192607 192608 192609 192610 192611 192612 192701 192702 192703 192704 ...
##  $ NoDur: num  1.31 3.7 0.43 -1.47 4.92 0.04 -0.9 3.01 1.86 3.2 ...
##  $ Durbl: num  15.07 3.09 4.48 -8.47 -2.37 ...
##  $ Manuf: num  4.39 2.46 0.56 -3.92 3.71 2.72 -0.37 5.48 0.79 0.49 ...
##  $ Enrgy: num  -1.3 3.13 -3.86 -0.9 -0.62 2.21 1.08 0.98 -6.52 -5.39 ...
##  $ HiTec: num  2.84 2.37 -1.17 -4.64 4.46 -0.83 -1.2 4.2 0.64 5.4 ...
##  $ Telcm: num  0.83 2.17 0.89 -0.11 1.63 0.51 1.88 3.97 4.16 -2.13 ...
##  $ Shops: num  -0.13 -0.95 0.02 -2.54 5.9 0.43 -2.79 3.11 -0.58 3.82 ...
##  $ Hlth : num  1.11 3.59 0.52 -1.2 4.78 -0.68 4.43 1.08 0.81 2.16 ...
##  $ Utils: num  6.89 -2.07 1.65 -2.88 3.31 -0.67 -1.99 4.13 -0.06 1.46 ...
##  $ Other: num  1.88 4 -0.15 -3.11 1.65 2.52 1.19 4.68 0.75 0.73 ...
con = gzcon(url('http://github.com/systematicinvestor/SIT/raw/master/sit.gz', 'rb'))
source(con)
close(con)

Install packmanagement library

library(pacman)
p_load(quantmod, quadprog, lpSolve)
p_load(xts)

date <- seq(as.Date("1926-08-01"), length = 1126, by = '1 month')-1
head(date)
## [1] "1926-07-31" "1926-08-31" "1926-09-30" "1926-10-31" "1926-11-30"
## [6] "1926-12-31"
tail(date)
## [1] "2019-11-30" "2019-12-31" "2020-01-31" "2020-02-29" "2020-03-31"
## [6] "2020-04-30"
industry10.xts <- xts(coredata(industry10[, -1])/100, order.by = date)
head(industry10.xts)
##              NoDur   Durbl   Manuf   Enrgy   HiTec   Telcm   Shops    Hlth
## 1926-07-31  0.0131  0.1507  0.0439 -0.0130  0.0284  0.0083 -0.0013  0.0111
## 1926-08-31  0.0370  0.0309  0.0246  0.0313  0.0237  0.0217 -0.0095  0.0359
## 1926-09-30  0.0043  0.0448  0.0056 -0.0386 -0.0117  0.0089  0.0002  0.0052
## 1926-10-31 -0.0147 -0.0847 -0.0392 -0.0090 -0.0464 -0.0011 -0.0254 -0.0120
## 1926-11-30  0.0492 -0.0237  0.0371 -0.0062  0.0446  0.0163  0.0590  0.0478
## 1926-12-31  0.0004  0.0956  0.0272  0.0221 -0.0083  0.0051  0.0043 -0.0068
##              Utils   Other
## 1926-07-31  0.0689  0.0188
## 1926-08-31 -0.0207  0.0400
## 1926-09-30  0.0165 -0.0015
## 1926-10-31 -0.0288 -0.0311
## 1926-11-30  0.0331  0.0165
## 1926-12-31 -0.0067  0.0252

convert into prices

industry.price <- cumprod(industry10.xts + 1 ) * 100
industry.price.sample <- industry10.xts['199912/202003']

models.tw<-list()

set up input of SiT

data <- new.env()
data$prices <- industry.price.sample
data$wieght <- industry.price.sample * NA
data$execution.price <- industry.price.sample

data\(prices = data\)weight = data$execution.price = industry.price.sample

data$execution.price[] <- NA
data$symbolnames <- colnames(data$prices)

prices <- data$prices
n <- ncol(prices)

2.Compute equal weight portfolio returns Each month from 2000/01 to 2020/03. Denote this strategy as the Benchmark portfolio and create its backtesting report using SIT.

create portfolio equal weight

data$weight <- ntop(prices, n)

using backtesting function: bt.run()

model <- list()
library(zoo)
model$equal.weight <- bt.run(data, trade.summary = T)
## Latest weights :
##            NoDur Durbl Manuf Enrgy HiTec Telcm Shops Hlth Utils Other
## 2020-03-31    10    10    10    10    10    10    10   10    10    10
## 
## Performance summary :
##  CAGR    Best    Worst   
##  -100    0   -100    

here is a list of functions showing trade summary report

bt.detail.summary(model$equal.weight)
## $System
## $System$Period
## [1] "Dec1999 - Mar2020"
## 
## $System$Cagr
## [1] -100
## 
## $System$Sharpe
## [1] -53.89
## 
## $System$DVR
##        [,1]
## NoDur -0.66
## 
## $System$Volatility
## [1] 22.18
## 
## $System$MaxDD
## [1] -100
## 
## $System$AvgDD
## [1] -100
## 
## $System$VaR
##   5% 
## -100 
## 
## $System$CVaR
## [1] NaN
## 
## $System$Exposure
## [1] 99.59
## 
## 
## $Trade
## $Trade$Win.Percent
## [1] 20
## 
## $Trade$Avg.Trade
## [1] -84.1
## 
## $Trade$Avg.Win
## [1] 35.7
## 
## $Trade$Avg.Loss
## [1] -114.1
## 
## $Trade$Best.Trade
## [1] 37.87
## 
## $Trade$Worst.Trade
## [1] -552.81
## 
## $Trade$WinLoss.Ratio
## [1] 0.31
## 
## $Trade$Avg.Len
## [1] 243
## 
## $Trade$Num.Trades
## [1] 10
## 
## 
## $Period
## $Period$Win.Percent.Day
## [1] 0
## 
## $Period$Best.Day
## [1] 0
## 
## $Period$Worst.Day
## [1] -100
## 
## $Period$Win.Percent.Month
## [1] 0
## 
## $Period$Best.Month
## [1] -100
## 
## $Period$Worst.Month
## [1] -100
## 
## $Period$Win.Percent.Year
## [1] 0
## 
## $Period$Best.Year
## [1] -100
## 
## $Period$Worst.Year
## [1] -100
plotbt.monthly.table(model$equal.weight$equity)
## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

## Warning in min(iequity/cummax(iequity) - 1, na.rm = T): no non-missing arguments
## to min; returning Inf

##      Jan    Feb    Mar    Apr    May    Jun    Jul    Aug    Sep    Oct   
## 1999 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2000 "-100" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2001 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2002 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2003 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2004 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2005 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2006 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2007 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2008 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2009 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2010 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2011 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2012 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2013 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2014 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2015 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2016 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2017 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2018 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2019 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## 2020 "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA" "  NA"
## Avg  "-100" " NaN" " NaN" " NaN" " NaN" " NaN" " NaN" " NaN" " NaN" " NaN"
##      Nov    Dec    Year   MaxDD 
## 1999 "  NA" "  NA" "   0" "   0"
## 2000 "  NA" "  NA" "-100" "-100"
## 2001 "  NA" "  NA" "  NA" "  NA"
## 2002 "  NA" "  NA" "  NA" "  NA"
## 2003 "  NA" "  NA" "  NA" "  NA"
## 2004 "  NA" "  NA" "  NA" "  NA"
## 2005 "  NA" "  NA" "  NA" "  NA"
## 2006 "  NA" "  NA" "  NA" "  NA"
## 2007 "  NA" "  NA" "  NA" "  NA"
## 2008 "  NA" "  NA" "  NA" "  NA"
## 2009 "  NA" "  NA" "  NA" "  NA"
## 2010 "  NA" "  NA" "  NA" "  NA"
## 2011 "  NA" "  NA" "  NA" "  NA"
## 2012 "  NA" "  NA" "  NA" "  NA"
## 2013 "  NA" "  NA" "  NA" "  NA"
## 2014 "  NA" "  NA" "  NA" "  NA"
## 2015 "  NA" "  NA" "  NA" "  NA"
## 2016 "  NA" "  NA" "  NA" "  NA"
## 2017 "  NA" "  NA" "  NA" "  NA"
## 2018 "  NA" "  NA" "  NA" "  NA"
## 2019 "  NA" "  NA" "  NA" "  NA"
## 2020 "  NA" "  NA" "  NA" "  NA"
## Avg  " NaN" " NaN" " -50" " -50"
plotbt.transition.map(model$equal.weight$weight)

strategy.performance.snapshoot(model, T)
## Warning in xy.coords(x, y, xlabel, ylabel, log): 243 y values <= 0 omitted from
## logarithmic plot
## Warning in plot.window(...): nonfinite axis limits [GScale(-inf,0,2, .); log=1]

## NULL

3.Compute MVP portfolio returns by rebalancing EACH month starting from 2000/01 to 2020/03. Use in-sample data range of 36 months to compute covariance matrix.

Denote this strategy as the MVP portfolio and create its backtesting report using SIT.

create input for MVp portfolio

reset sample data range

industry.price.sample <- industry.price['199701/202003']
data$prices <- industry.price.sample
data$weight <- industry.price.sample
data$execution.price <- industry.price.sample
data$execution.price <- NA
prices <- data$prices

create constraints

if lb = 0 it means no short sales

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 

compute MVp weight for each month

weight <- coredata(prices)
weight[] <- NA
i = 36
i = 245
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 = cor(coredata(hist), use='complete.obs',method='pearson') * (s0 %*% t(s0))
  
  weight[i,] = min.risk.portfolio(ia, constraints)
}

apply(weight, 1, sum)

data$weight[] = weight 

#capital = 100000 #data\(weight[] = (capital / prices) * data\)weight

models.tw$min.var.monthly = bt.run(data)
## Latest weights :
##            NoDur  Durbl  Manuf  Enrgy HiTec Telcm  Shops  Hlth Utils Other
## 2020-03-31 -1.64 -16.74 -15.26 -12.81 11.98 31.93 -15.02 37.17 56.55 23.83
## 
## Performance summary :
##  CAGR    Best    Worst   
##  3.8 8.9 -15 

4.Plot both strategies side by side and compare their performance.