rm(list = ls())
library(devtools)
## Warning: package 'devtools' was built under R version 4.3.3
## Loading required package: usethis
## Warning: package 'usethis' was built under R version 4.3.3
setwd("D:/School Folder/HW/Investment")
etf6 <- read.table('finish_data.csv', sep = ',', header = T)
head(etf6)
## id date price
## 1 50 2008-01-02 60.01
## 2 52 2008-01-02 40.14
## 3 56 2008-01-02 25.70
## 4 50 2008-01-03 58.89
## 5 52 2008-01-03 39.10
## 6 56 2008-01-03 25.23
library(pacman)
## Warning: package 'pacman' was built under R version 4.3.3
p_load(reshape2, xts, quantmod)
library(tidyr)
## Warning: package 'tidyr' was built under R version 4.3.3
##
## Attaching package: 'tidyr'
## The following object is masked from 'package:reshape2':
##
## smiths
library(data.table)
## Warning: package 'data.table' was built under R version 4.3.3
##
## Attaching package: 'data.table'
## The following objects are masked from 'package:xts':
##
## first, last
## The following objects are masked from 'package:zoo':
##
## yearmon, yearqtr
## The following objects are masked from 'package:reshape2':
##
## dcast, melt
etf6.l <- dcast(etf6, date ~ id, value.var = "price", fun.aggregate = mean)
## Warning: The dcast generic in data.table has been passed a data.frame and will
## attempt to redirect to the relevant reshape2 method; please note that reshape2
## is superseded and is no longer actively developed, and this redirection is now
## deprecated. Please do this redirection yourself like reshape2::dcast(etf6). In
## the next version, this warning will become an error.
head(etf6.l)
## date 50 52 56
## 1 2008-01-02 60.01 40.14 25.70
## 2 2008-01-03 58.89 39.10 25.23
## 3 2008-01-04 59.01 38.64 25.51
## 4 2008-01-07 56.39 36.16 24.85
## 5 2008-01-08 56.98 35.82 25.38
## 6 2008-01-09 58.20 36.69 25.83
str(etf6.l)
## 'data.frame': 4009 obs. of 4 variables:
## $ date: chr "2008-01-02" "2008-01-03" "2008-01-04" "2008-01-07" ...
## $ 50 : num 60 58.9 59 56.4 57 ...
## $ 52 : num 40.1 39.1 38.6 36.2 35.8 ...
## $ 56 : num 25.7 25.2 25.5 24.9 25.4 ...
library(xts)
# Remove rows with NA values in the date column
etf6.l <- etf6.l[complete.cases(etf6.l$date), ]
# Convert date column to Date format
etf6.l$date <- as.Date(etf6.l$date)
# Convert into xts
etf6.xts <- xts(etf6.l[, -1], order.by = etf6.l$date)
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
library(quantmod)
data <- new.env()
model <- list()
etf3 <- etf6.xts[, 1:3]
head(etf3)
## 50 52 56
## 2008-01-02 60.01 40.14 25.70
## 2008-01-03 58.89 39.10 25.23
## 2008-01-04 59.01 38.64 25.51
## 2008-01-07 56.39 36.16 24.85
## 2008-01-08 56.98 35.82 25.38
## 2008-01-09 58.20 36.69 25.83
names(etf3)
## [1] "50" "52" "56"
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)
prices <- na.omit(data$prices)
# Calculate the moving average
sma <- SMA(prices, md)
data$weight[] <- iif(data$prices >= sma, 1, 0)
i <- paste(i, '.sma.cross', sep = '')
model[[i]] <- bt.run(data)
}
## Latest weights :
## e50
## 2024-04-29 100
##
## Performance summary :
## CAGR Best Worst
## 6.6 16.5 -11.9
## Warning in NextMethod(.Generic): number of items to replace is not a multiple
## of replacement length
## Latest weights :
## e50
## 2024-04-29 0
##
## Performance summary :
## CAGR Best Worst
## 34.5 16.5 -11.6
##
## Latest weights :
## e52
## 2024-04-29 100
##
## Performance summary :
## CAGR Best Worst
## 8 10 -11.6
## Warning in NextMethod(.Generic): number of items to replace is not a multiple
## of replacement length
## Latest weights :
## e52
## 2024-04-29 0
##
## Performance summary :
## CAGR Best Worst
## 38.7 10 -11.6
##
## Latest weights :
## e56
## 2024-04-29 100
##
## Performance summary :
## CAGR Best Worst
## 2.8 7 -8.8
## Warning in NextMethod(.Generic): number of items to replace is not a multiple
## of replacement length
## Latest weights :
## e56
## 2024-04-29 0
##
## Performance summary :
## CAGR Best Worst
## 26.7 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 = T)

## e50 e50.sma.cross e52
## Period "Jan2008 - Apr2024" "Jan2008 - Apr2024" "Jan2008 - Apr2024"
## Cagr "6.6" "34.51" "8.01"
## Sharpe "0.41" "2.12" "0.44"
## DVR "0.33" "1.57" "0.31"
## Volatility "21.99" "14.9" "25.86"
## MaxDD "-52.26" "-11.58" "-58.47"
## AvgDD "-4.63" "-1.56" "-6.16"
## VaR "-1.95" "-0.96" "-2.56"
## CVaR "-3.19" "-1.76" "-3.81"
## Exposure "99.98" "60.26" "99.98"
## e52.sma.cross e56 e56.sma.cross
## Period "Jan2008 - Apr2024" "Jan2008 - Apr2024" "Jan2008 - Apr2024"
## Cagr "38.66" "2.83" "26.74"
## Sharpe "2.03" "0.25" "2.57"
## DVR "1.3" "0.15" "2.03"
## Volatility "17.25" "17.01" "9.64"
## MaxDD "-20.27" "-50.81" "-7.37"
## AvgDD "-2.06" "-5.62" "-1.2"
## VaR "-1.41" "-1.65" "-0.72"
## CVaR "-2.33" "-2.91" "-1.34"
## Exposure "61.26" "99.98" "58.84"
# --------------------------------------------------
# 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
## 2024-04-29 33.33 33.33 33.33
##
## Performance summary :
## CAGR Best Worst
## 6.3 7.5 -6.5
#
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 - Apr2024" "Jan2008 - Apr2024" "Jan2008 - Apr2024"
## Cagr "6.6" "34.51" "8.01"
## Sharpe "0.41" "2.12" "0.44"
## DVR "0.33" "1.57" "0.31"
## Volatility "21.99" "14.9" "25.86"
## MaxDD "-52.26" "-11.58" "-58.47"
## AvgDD "-4.63" "-1.56" "-6.16"
## VaR "-1.95" "-0.96" "-2.56"
## CVaR "-3.19" "-1.76" "-3.81"
## Exposure "99.98" "60.26" "99.98"
## e52.sma.cross e56 e56.sma.cross
## Period "Jan2008 - Apr2024" "Jan2008 - Apr2024" "Jan2008 - Apr2024"
## Cagr "38.66" "2.83" "26.74"
## Sharpe "2.03" "0.25" "2.57"
## DVR "1.3" "0.15" "2.03"
## Volatility "17.25" "17.01" "9.64"
## MaxDD "-20.27" "-50.81" "-7.37"
## AvgDD "-2.06" "-5.62" "-1.2"
## VaR "-1.41" "-1.65" "-0.72"
## CVaR "-2.33" "-2.91" "-1.34"
## Exposure "61.26" "99.98" "58.84"
## etf3.EqWeight.bh
## Period "Jan2008 - Apr2024"
## Cagr "6.31"
## Sharpe "0.42"
## DVR "0.33"
## Volatility "19.07"
## MaxDD "-56.2"
## AvgDD "-3.98"
## VaR "-1.92"
## CVaR "-2.93"
## Exposure "99.98"
