#1. Download the data file 'hist_prices_df.rds' as your data set. 
#This data set includes daily closing prices for all listed stocks in Taiwan stock market from 1999 to 2017.
#You can use 'readRDS('hist_prices_df.rds')' to import the data.
#rm(list= ls())
rm(list=ls())
data <- readRDS("C:/Users/ankhb/Downloads/hist_prices_df.rds")
str(data)
## 'data.frame':    4746 obs. of  1110 variables:
##  $ date  : int  19990105 19990106 19990107 19990108 19990111 19990112 19990113 19990114 19990115 19990116 ...
##  $ 1101  : num  9.06 9.06 9.27 9.13 8.93 8.89 8.82 8.62 8.79 8.79 ...
##  $ 1102  : num  6.14 6.01 6.01 5.86 5.73 5.53 5.51 5.21 5.34 5.29 ...
##  $ 1103  : num  9.85 9.65 10.12 10.33 10.12 ...
##  $ 1104  : num  4.53 4.39 4.58 4.51 4.34 4.21 4.17 4.24 4.44 4.38 ...
##  $ 1108  : num  7.85 7.63 7.88 7.8 7.58 7.27 7.11 6.92 7.25 7.14 ...
##  $ 1109  : num  9.09 8.89 8.94 8.75 8.7 8.6 8.5 8.45 8.55 8.55 ...
##  $ 1110  : num  6.73 6.73 7.2 7.36 7.2 6.98 7.11 6.98 7.17 7.04 ...
##  $ 1201  : num  13.9 14.8 15.8 16.9 18 ...
##  $ 1203  : num  12.2 12 12.7 12.6 12.4 ...
##  $ 1204  : num  79.6 78.2 83.6 89.1 85.1 ...
##  $ 1206  : num  36.7 34.2 36.5 39 41.7 40.2 40.2 40.5 43.3 46.3 ...
##  $ 1207  : num  27.8 27.8 28 27.8 28 ...
##  $ 1209  : num  13.2 13.1 13.4 13.4 13.4 ...
##  $ 1210  : num  2.75 2.74 2.81 2.82 2.82 2.8 2.76 2.73 2.8 2.76 ...
##  $ 1212  : num  14.2 14.2 14.3 14.8 15.2 ...
##  $ 1213  : num  24.1 23.9 25.6 26.4 26.6 ...
##  $ 1215  : num  4.99 5.03 5.32 5.21 5.36 5.25 5.25 5.12 5.28 5.34 ...
##  $ 1216  : num  7.03 6.85 7.01 6.91 6.73 6.63 6.4 6.28 6.48 6.43 ...
##  $ 1217  : num  13.5 13.2 13.5 13.5 13.4 ...
##  $ 1218  : num  8.41 8.57 9.15 9.77 10.43 ...
##  $ 1219  : num  5.94 6.25 6.5 6.69 7.12 6.62 6.5 6.32 6.62 6.5 ...
##  $ 1220  : num  9.36 9.36 9.66 9.59 10.19 ...
##  $ 1221  : num  7.41 7.7 8.23 8.78 8.98 8.46 8.19 8.36 8.91 9.05 ...
##  $ 1222  : num  53.5 53.3 55.5 54.3 57.5 ...
##  $ 1225  : num  8.04 8.19 8.73 9.31 9.92 9.35 9.42 9.46 9.85 9.85 ...
##  $ 1227  : num  6.2 6.26 6.67 6.43 6.43 6.26 6.08 5.73 5.64 5.91 ...
##  $ 1228  : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 1229  : num  5.26 5.26 5.44 5.38 5.35 5.26 5.1 5.01 5.26 5.26 ...
##  $ 1230  : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 1231  : num  13.2 12.9 12.6 12.4 13 ...
##  $ 1232  : num  3.45 3.47 3.63 3.63 3.87 3.91 3.82 3.86 4.12 4.28 ...
##  $ 1233  : num  6.4 6.2 6.5 6.57 6.47 6.4 6.74 6.4 6.57 6.67 ...
##  $ 1234  : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 1235  : num  4.85 4.85 5.18 5.16 5.06 4.82 4.57 4.37 4.63 4.51 ...
##  $ 1236  : num  3.57 3.47 3.62 3.59 3.57 3.49 3.34 3.27 3.44 3.39 ...
##  $ 1256  : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 1262  : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 1301  : num  10.1 10.4 11.1 11.1 11 ...
##  $ 1303  : num  9.54 9.68 10.15 9.87 9.82 ...
##  $ 1304  : num  5.52 5.28 5.4 5.28 5.49 5.28 5.31 5.25 5.34 5.4 ...
##  $ 1305  : num  9.6 9.6 9.98 10.25 10.25 ...
##  $ 1306  : num  41.6 38.7 40.1 39 38.1 ...
##  $ 1307  : num  3.18 3.16 3.29 3.29 3.26 3.24 3.21 3.13 3.24 3.24 ...
##  $ 1308  : num  6.65 6.38 6.83 6.65 6.67 6.59 6.59 6.44 6.71 6.59 ...
##  $ 1309  : num  14.6 14.4 15.3 15.3 15.4 ...
##  $ 1310  : num  14.5 14.2 14.8 14.6 15.4 ...
##  $ 1311  : num  16.5 16.6 17.5 17.2 17.2 ...
##  $ 1312  : num  10.1 10 10.5 10.6 10.9 ...
##  $ 1313  : num  5.42 5.25 5.59 5.62 5.69 5.73 5.69 5.52 5.69 5.69 ...
##  $ 1314  : num  9.92 9.59 10.15 10.2 9.92 ...
##  $ 1315  : num  7.12 6.72 7.16 7.42 7.31 7.16 7.05 6.94 7.31 7.27 ...
##  $ 1316  : num  29.4 29.9 31.1 32.5 32.8 ...
##  $ 1319  : num  11.3 10.6 11.2 12 12.4 ...
##  $ 1321  : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 1323  : num  3.92 3.89 3.98 3.96 3.89 3.72 3.61 3.38 3.48 3.49 ...
##  $ 1324  : num  9.43 9.85 9.99 9.99 9.79 9.34 9.29 9.29 9.76 9.49 ...
##  $ 1325  : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 1326  : num  6.36 6.43 6.61 6.64 6.5 6.34 6.17 6.17 6.41 6.27 ...
##  $ 1337  : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 1338  : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 1339  : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 1340  : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ 1402  : num  6.63 6.84 6.94 6.99 6.78 6.94 6.91 6.68 6.76 6.63 ...
##  $ 1409  : num  7.02 7.25 7.74 7.74 7.45 7.38 7.35 7.28 7.58 7.35 ...
##  $ 1410  : num  20.5 19.1 19.9 19.6 19.5 ...
##  $ 1413  : num  34.6 34.5 36.9 37.4 36.6 ...
##  $ 1414  : num  12.7 12.7 13.6 14.1 13.8 ...
##  $ 1416  : num  11.6 11.7 12.5 13.4 13.7 ...
##  $ 1417  : num  13.4 12.6 13.1 13.6 13.3 ...
##  $ 1418  : num  74.6 74.3 76.9 76.9 75.4 ...
##  $ 1419  : num  21.9 22.3 23.8 24.8 24.3 ...
##  $ 1423  : num  7.64 8.16 8.73 8.99 8.64 8.29 8.46 8.16 8.73 8.55 ...
##  $ 1431  : num  12.1 11.8 12.6 13.4 14.3 ...
##  $ 1432  : num  43.1 42.7 45.5 45.1 44.6 ...
##  $ 1434  : num  5.72 5.75 6 5.94 5.75 5.69 5.6 5.57 5.72 5.6 ...
##  $ 1435  : num  12.3 12.5 13.3 13.7 13.7 ...
##  $ 1436  : num  13.4 13.3 14.2 15.2 15.7 ...
##  $ 1437  : num  20.3 20.9 22.3 23.3 22.5 ...
##  $ 1438  : num  15.1 15 15.6 15.7 15.6 ...
##  $ 1439  : num  9.59 10.24 10.89 11.16 10.89 ...
##  $ 1440  : num  7.03 7.12 7.55 7.4 7.34 7.12 7.06 7 7.27 7.15 ...
##  $ 1441  : num  42 42 44 43.1 42.2 ...
##  $ 1442  : num  55.4 51.5 51.7 51.9 51.1 ...
##  $ 1443  : num  21.2 21.2 22.6 23.4 23.5 ...
##  $ 1444  : num  5.81 5.81 6.21 6.34 6.18 6 5.87 5.76 5.84 5.84 ...
##  $ 1445  : num  9.37 9.18 9.32 9.47 9.27 9.03 9.23 9.13 9.18 9.23 ...
##  $ 1446  : num  25.5 25.5 26.8 26.8 26.8 ...
##  $ 1447  : num  7.38 7.51 8 8.06 7.69 8 7.9 7.64 7.74 7.53 ...
##  $ 1449  : num  143 140 145 144 145 ...
##  $ 1450  : num  28.9 28.6 29.5 29.3 28.6 ...
##  $ 1451  : num  27.1 27.3 26.8 26.4 26.1 ...
##  $ 1452  : num  8.85 8.8 9.21 9.16 8.94 8.8 8.58 8.31 8.35 8.49 ...
##  $ 1453  : num  63.9 63.9 65.4 64.2 68.5 ...
##  $ 1454  : num  8.78 8.51 8.78 8.74 8.6 8.55 8.65 8.46 8.46 8.65 ...
##  $ 1455  : num  6.5 6.07 6.5 6.54 6.3 6.25 6.3 6.3 6.52 6.41 ...
##  $ 1456  : num  155 157 162 159 155 ...
##  $ 1457  : num  18.9 18.9 20 20.3 19.9 ...
##  $ 1459  : num  6.07 5.79 6.03 5.92 5.79 5.79 5.73 5.6 5.73 5.92 ...
##   [list output truncated]
con = gzcon(url('https://github.com/systematicinvestor/SIT/raw/master/sit.gz', 'rb'))
source(con)
close(con)

##Q2

library(xts)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## Registered S3 method overwritten by 'xts':
##   method     from
##   as.zoo.xts zoo
library(quantmod)
## Loading required package: TTR
## 
## Attaching package: 'TTR'
## The following object is masked _by_ '.GlobalEnv':
## 
##     DVI
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
## Version 0.4-0 included new data defaults. See ?getSymbols.
library(kernlab)
## 
## Attaching package: 'kernlab'
## The following object is masked _by_ '.GlobalEnv':
## 
##     cross
data.1 <- data[,c("date","1101","1102","2030","2031", "3052","6191","6005","9937", "9902","9905")]
sum(is.na(data.1))
## [1] 0
data.xts <- xts(data.1[,-1], order.by= as.Date(as.character(data.1[,1]), 
                                               format = '%Y%m%d'))
str(data.xts)
## An 'xts' object on 1999-01-05/2017-12-29 containing:
##   Data: num [1:4746, 1:10] 9.06 9.06 9.27 9.13 8.93 8.89 8.82 8.62 8.79 8.79 ...
##  - attr(*, "dimnames")=List of 2
##   ..$ : NULL
##   ..$ : chr [1:10] "1101" "1102" "2030" "2031" ...
##   Indexed by objects of class: [Date] TZ: UTC
##   xts Attributes:  
##  NULL

##Q3. Construct equal-weighted portfolio starting from 2007 to 2017.

data.monthly <- to.monthly(data.xts, indexAt = 'lastof', OHLC=F)
data.monthly.1 <- data.monthly["2007/2017"]
data <- new.env()
data$prices <- data.monthly.1
data$weight <- data.monthly.1
data$execution.price <- data$prices
data$execution.price[] <- NA
data$symbolnames <- colnames(data$prices)
prices <- data$prices
n <-  ncol(prices)
data$weight <- ntop(prices, n)
model <- list()
model$equal.weight <- bt.run(data, trade.summary = T)
## Latest weights :
##            1101 1102 2030 2031 3052 6191 6005 9937 9902 9905
## 2017-12-31   10   10   10   10   10   10   10   10   10   10
## 
## Performance summary :
##  CAGR    Best    Worst   
##  8.2 26.7    -30 
capital = 100000
data$weight[] = (capital / prices) * data$weight
equal.weight = bt.run(data, type='share')
## Latest weights :
##            1101 1102 2030 2031 3052 6191 6005 9937 9902 9905
## 2017-12-31   10   10   10   10   10   10   10   10   10   10
## 
## Performance summary :
##  CAGR    Best    Worst   
##  8.2 26.7    -30 
head(equal.weight$ret)
##                  1101
## 2007-01-31 0.00000000
## 2007-02-28 0.04404018
## 2007-03-31 0.06275091
## 2007-04-30 0.01691907
## 2007-05-31 0.00944164
## 2007-06-30 0.13928670
bt.detail.summary(model$equal.weight)
## $System
## $System$Period
## [1] "Jan2007 - Dec2017"
## 
## $System$Cagr
## [1] 8.16
## 
## $System$Sharpe
## [1] 0.44
## 
## $System$DVR
##      [,1]
## 1101 0.27
## 
## $System$Volatility
## [1] 24.9
## 
## $System$MaxDD
## [1] -56.82
## 
## $System$AvgDD
## [1] -12.88
## 
## $System$VaR
##     5% 
## -10.48 
## 
## $System$CVaR
## [1] -15.45
## 
## $System$Exposure
## [1] 99.24
## 
## 
## $Trade
## $Trade$Win.Percent
## [1] 80
## 
## $Trade$Avg.Trade
## [1] 9.4
## 
## $Trade$Avg.Win
## [1] 12.3
## 
## $Trade$Avg.Loss
## [1] -2.5
## 
## $Trade$Best.Trade
## [1] 23.17
## 
## $Trade$Worst.Trade
## [1] -4.69
## 
## $Trade$WinLoss.Ratio
## [1] 4.85
## 
## $Trade$Avg.Len
## [1] 131
## 
## $Trade$Num.Trades
## [1] 10
## 
## 
## $Period
## $Period$Win.Percent.Day
## [1] 59.8
## 
## $Period$Best.Day
## [1] 26.7
## 
## $Period$Worst.Day
## [1] -30
## 
## $Period$Win.Percent.Month
## [1] 59.8
## 
## $Period$Best.Month
## [1] 26.7
## 
## $Period$Worst.Month
## [1] -30
## 
## $Period$Win.Percent.Year
## [1] 63.6
## 
## $Period$Best.Year
## [1] 124.8
## 
## $Period$Worst.Year
## [1] -37.9
plotbt.monthly.table(model$equal.weight$equity)

##      Jan     Feb     Mar     Apr     May     Jun     Jul     Aug    
## 2007 "   NA" "  4.4" "  6.3" "  1.7" "  0.9" " 13.9" " 12.5" " -2.5"
## 2008 " -3.5" " 22.1" "  7.0" "  0.8" " -4.4" "-17.4" " -3.2" " -5.1"
## 2009 " -6.5" "  6.2" " 26.7" " 12.0" " 23.7" " -3.1" " 10.0" " -1.1"
## 2010 "-11.7" "  0.5" "  7.4" " -1.5" "-10.3" " -0.1" "  7.0" "  2.9"
## 2011 "  2.9" " -6.2" "  1.9" "  5.7" "  0.0" " -0.6" "  3.4" "-10.7"
## 2012 "  9.8" "  9.5" " -2.0" " -4.2" " -5.8" "  0.7" "  1.0" " -0.1"
## 2013 "  1.0" " -1.0" " -1.3" "  2.4" "  9.5" " -5.4" "  3.7" "  1.8"
## 2014 "  0.0" "  2.4" "  0.5" " -2.8" "  1.2" "  0.2" "  3.4" "  2.1"
## 2015 " -0.8" "  1.3" "  0.4" "  2.8" " -4.9" " -7.3" " -7.5" " -5.9"
## 2016 " -4.3" "  6.6" "  1.0" " -0.2" " -3.5" "  0.9" "  5.5" "  2.0"
## 2017 " -0.2" "  7.2" "  1.3" " -3.5" "  0.1" "  1.5" "  4.3" "  4.7"
## Avg  " -1.3" "  4.8" "  4.5" "  1.2" "  0.6" " -1.5" "  3.7" " -1.1"
##      Sep     Oct     Nov     Dec     Year    MaxDD  
## 2007 "  8.7" " -7.1" " -7.9" " -4.4" " 26.8" "-18.1"
## 2008 "-30.0" "-14.9" " 11.1" "  1.8" "-37.9" "-56.8"
## 2009 "  6.7" " -1.6" "  1.8" " 14.4" "124.8" " -6.5"
## 2010 "  6.9" " -3.4" " -1.5" "  7.8" "  1.6" "-15.9"
## 2011 "-10.8" "  7.2" "-12.6" "  1.9" "-18.9" "-25.4"
## 2012 "  5.6" " -8.6" "  3.2" "  5.7" " 13.8" "-13.3"
## 2013 "  2.0" "  2.5" "  1.8" "  2.0" " 20.1" " -5.4"
## 2014 " -4.0" " -4.3" "  0.9" "  4.7" "  3.9" " -8.2"
## 2015 "  4.6" "  4.4" " -7.5" "  1.5" "-18.4" "-23.3"
## 2016 " -0.2" "  1.4" "  5.6" "  1.3" " 16.7" " -4.3"
## 2017 " -2.1" "  3.0" " -1.2" "  3.3" " 19.5" " -3.5"
## Avg  " -1.1" " -1.9" " -0.6" "  3.6" " 13.8" "-16.4"
plotbt.transition.map(model$equal.weight$weight)

strategy.performance.snapshoot(model, T)

## NULL

##Q4. Construct MVP portfolio starting from 2004-2017. #Year 2004-2006 will be used as in sample data to compute covariance matrix for MVP.

data.monthly.2 <- data.monthly["2004/2017"]
data.monthly.3 <- data.monthly["2004/2006"]
Sigma_monthly <- cov(data.monthly.3)
head(Sigma_monthly)
##           1101       1102       2030       2031        3052        6191
## 1101  7.095257  5.0740846 2.18635571  -9.092439 -1.25517857   6.0143583
## 1102  5.074085  4.2052961 2.38812929  -4.638566 -0.74942643   4.2501139
## 2030  2.186356  2.3881293 2.94821929   1.608435  0.01046071   1.3755379
## 2031 -9.092439 -4.6385658 1.60843500  25.547909  2.20173071 -10.6009413
## 3052 -1.255179 -0.7494264 0.01046071   2.201731  0.69880214   0.1811707
## 6191  6.014358  4.2501139 1.37553786 -10.600941  0.18117071  15.6384847
##             6005       9937       9902       9905
## 1101  1.14042429  2.4244268 -4.7063449 -0.4099478
## 1102  0.85780929  1.6612253 -2.6602887  0.2480113
## 2030  0.52386786  0.5523721  0.5519893  1.0783350
## 2031 -1.34739071 -3.8166471  9.4305637  4.1072866
## 3052 -0.08237929 -0.5138779  2.1867936  0.2702393
## 6191  1.05226071  1.3534447 -1.1481156 -1.0910728
ones = rep(1,10)     
one.vec = matrix(ones, ncol=1)
a = inv(Sigma_monthly) %*% one.vec
b = t(one.vec)%*%a
mvp.w.monthly =a / as.numeric(b)
mvp.w.monthly
##               [,1]
## 1101 -0.0907159873
## 1102 -0.0515201991
## 2030 -0.0004535364
## 2031 -0.0223156685
## 3052  0.6143532179
## 6191 -0.0036770687
## 6005  0.4946153094
## 9937  0.0297113804
## 9902 -0.2183613720
## 9905  0.2483639243

#Q5. Similar to question 4

data$prices = data$weight = data$execution.price = data.monthly.1
data$execution.price[] <- NA
prices <- data$prices
n <- ncol(prices)
constraints = new.constraints(n, lb = -Inf, ub = +Inf)
constraints = add.constraints(rep(1, n), 1, type = '=', constraints)        
ret = prices / mlag(prices) - 1
weight = coredata(prices)
weight[] = NA
nrow(prices)
## [1] 132
hist <- na.omit(ret[1:36,])
cov(hist)
##             1101        1102        2030        2031        3052
## 1101 0.025224630 0.017736344 0.008955619 0.013911524 0.009786144
## 1102 0.017736344 0.017730725 0.007152839 0.009756524 0.008230059
## 2030 0.008955619 0.007152839 0.018680911 0.018004663 0.015452262
## 2031 0.013911524 0.009756524 0.018004663 0.027504038 0.016857490
## 3052 0.009786144 0.008230059 0.015452262 0.016857490 0.027081196
## 6191 0.007984633 0.007116579 0.010996121 0.012902372 0.012445644
## 6005 0.016335182 0.014006027 0.016743330 0.021576111 0.021809001
## 9937 0.008263227 0.004435278 0.007198008 0.006573010 0.011159201
## 9902 0.017205311 0.010776307 0.018500762 0.017163931 0.018020297
## 9905 0.007637370 0.005559106 0.009326382 0.010834600 0.010762263
##             6191        6005        9937        9902        9905
## 1101 0.007984633 0.016335182 0.008263227 0.017205311 0.007637370
## 1102 0.007116579 0.014006027 0.004435278 0.010776307 0.005559106
## 2030 0.010996121 0.016743330 0.007198008 0.018500762 0.009326382
## 2031 0.012902372 0.021576111 0.006573010 0.017163931 0.010834600
## 3052 0.012445644 0.021809001 0.011159201 0.018020297 0.010762263
## 6191 0.019321391 0.011348404 0.007118646 0.009073662 0.007242802
## 6005 0.011348404 0.033026821 0.009182638 0.021034044 0.012903012
## 9937 0.007118646 0.009182638 0.010752908 0.013451627 0.005993916
## 9902 0.009073662 0.021034044 0.013451627 0.042596166 0.011841623
## 9905 0.007242802 0.012903012 0.005993916 0.011841623 0.011280463
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[36,] = min.risk.portfolio(ia, constraints)
weight[36,]
##        1101        1102        2030        2031        3052        6191 
## -0.36022757  0.56440238  0.12796073  0.13352926 -0.19611934 -0.06739882 
##        6005        9937        9902        9905 
## -0.15946967  0.71520646 -0.13722389  0.37934046
sum(weight[36,])
## [1] 1
model$min.var.monthly <- bt.run(data, trade.summary = T)
## Latest weights :
##            1101 1102 2030 2031 3052 6191 6005 9937 9902 9905
## 2017-12-31 3355 2785 1530 2620  830 1310 1140 3950 1010 2555
## 
## Performance summary :
##  CAGR    Best    Worst   
##  -100    1639    -100    
sum(as.numeric(weight[36,])*as.numeric(ret[37,]))
## [1] -0.08070594
model$min.var.monthly$ret[37, ]
##            1101
## 2010-01-31   -1
plotbt.strategy.sidebyside(model, return.table=T, make.plot = T)
## Warning in max(mret, na.rm = T): no non-missing arguments to max; returning
## -Inf
## Warning in min(mret, na.rm = T): no non-missing arguments to min; returning
## Inf

##            equal.weight        min.var.monthly    
## Period     "Jan2007 - Dec2017" "Jan2007 - Dec2017"
## Cagr       "8.16"              "-100"             
## Sharpe     "0.44"              "-0.96"            
## DVR        "0.27"              "-0.02"            
## Volatility "24.9"              "754.64"           
## MaxDD      "-56.82"            "-100"             
## AvgDD      "-12.88"            "-100"             
## VaR        "-10.48"            "-100"             
## CVaR       "-15.45"            "NaN"              
## Exposure   "99.24"             "99.24"
plotbt(model)