#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)