#Weekly Timing Strategy with Volatility Filter
require(PerformanceAnalytics)
require(quantstrat)
suppressWarnings(rm("order_book.TimingWeekly",pos=.strategy))
suppressWarnings(rm("account.TimingWeekly","portfolio.TimingWeekly",pos=.blotter))
suppressWarnings(rm("account.st","portfolio.st","symbols","stratBBands","initDate","initEq",'start_t','end_t'))
##### Begin Functions #####
#Custom Order Sizing Function to trade percent of equity based on a stopsize
osPCTEQ <- function(timestamp, orderqty, portfolio, symbol, ruletype, ...){
tempPortfolio <- getPortfolio(portfolio.st)
dummy <- updatePortf(Portfolio=portfolio.st, Dates=paste('::',as.Date(timestamp),sep=''))
trading.pl <- sum(getPortfolio(portfolio.st)$summary$Realized.PL) #change to ..$summary$Net.Trading.PL for Total Equity Position Sizing
assign(paste("portfolio.",portfolio.st,sep=""),tempPortfolio,pos=.blotter)
total.equity <- initEq+trading.pl
DollarRisk <- total.equity * trade.percent
ClosePrice <- as.numeric(Cl(mktdata[timestamp,]))
mavg <- as.numeric(mktdata$SMA[timestamp,])
sign1 <- ifelse(ClosePrice > mavg, 1, -1)
sign1[is.na(sign1)] <- 1
Posn = getPosQty(Portfolio = portfolio.st, Symbol = symbol, Date = timestamp)
StopSize <- as.numeric(mktdata$SDEV[timestamp,]*StopMult) #Stop = SDAVG * StopMult !Must have SDAVG or other indictor to determine stop size
#orderqty <- round(DollarRisk/StopSize, digits=0)
orderqty <- ifelse(Posn == 0, sign1*round(DollarRisk/StopSize), 0) # number contracts traded is equal to DollarRisk/StopSize
return(orderqty)
}
#Function that calculates the n period standard deviation of close prices.
#This is used in place of ATR so that I can use only close prices.
SDEV <- function(x, n){
sdev <- runSD(x, n, sample = FALSE)
colnames(sdev) <- "SDEV"
reclass(sdev,x)
}
#Custom indicator function
RBrev1 <- function(x,n){
x <- x
sd <- runSD(x, n, sample= FALSE)
med <- runMedian(sd,n)
mavg <- SMA(x,n)
signal <- ifelse(sd < med & x > mavg,1,0)
colnames(signal) <- "RB"
#ret <- cbind(x,roc,sd,med,mavg,signal) #Only use for further analysis of indicator
#colnames(ret) <- c("close","roc","sd","med","mavg","RB") #Only use for further analysis of indicator
reclass(signal,x)
}
##### End Functions #####
#Symbols to be used in test
#XLY - Consumer Discretionary Select Sector SPDR
#XLP - Consumer Staples Select Sector SPDR
#XLE - Energy Select Sector SPDR
#XLF - Financial Select Sector SPDR
#XLV - Health Care Select Sector SPDR
#XLI - Industrial Select Sector SPDR
#XLK - Technology Select Sector SPDR
#XLB - Materials Select Sector SPDR
#XLU - Utilities Select Sector SPDR
#Symbol list to pass to the getSymbols function
symbols = c("XLY", "XLP", "XLE", "XLF", "XLV", "XLI", "XLK", "XLB", "XLU")
#Load ETFs from yahoo
currency("USD")
stock(symbols, currency="USD",multiplier=1)
getSymbols(symbols, src='yahoo', index.class=c("POSIXt","POSIXct"), from='2000-01-01')
#Data is downloaded as daily data
#Convert to weekly
for(symbol in symbols) {
x<-get(symbol)
x<-to.weekly(x,indexAt='lastof',drop.time=TRUE)
indexFormat(x)<-'%Y-%m-%d'
colnames(x)<-gsub("x",symbol,colnames(x))
assign(symbol,x)
}
#Use the adjusted close prices
#this for loop sets the "Close" column equal to the "Adjusted Close" column
#because the trades are executed based on the "Close" column
for(symbol in symbols) {
x<-get(symbol)
x[,4] <- x[,6]
assign(symbol,x)
}
initDate='1900-01-01'
initEq <- 100000
trade.percent <- 0.01 #percent risk used in sizing function
StopMult = 1 #stop size used in sizing function
#Name the portfolio and account
portfolio.st = 'TimingWeekly'
account.st = 'TimingWeekly'
#Initialization
initPortf(portfolio.st, symbols=symbols, initPosQty=0, initDate=initDate, currency="USD")
initAcct(account.st,portfolios=portfolio.st, initDate=initDate, initEq=initEq)
initOrders(portfolio=portfolio.st,initDate=initDate)
#Name the strategy
strat <- strategy('TimingWeekly')
#Add indicators
#The first indicator is the 52 period SMA
#The second indicator is the SDEV indicator used for stop and position sizing
strat <- add.indicator(strategy = strat, name = "SMA", arguments = list(x = quote(Cl(mktdata)), n=52), label="SMA")
strat <- add.indicator(strategy = strat, name = "RBrev1", arguments = list(x = quote(Cl(mktdata)), n=52), label="RB")
strat <- add.indicator(strategy = strat, name = "SDEV", arguments = list(x = quote(Cl(mktdata)), n=52), label="SDEV")
#Add signals
#The buy signal is when the RB indicator crosses from 0 to 1
#The exit signal is when the close crosses below the SMA
strat <- add.signal(strategy = strat, name="sigThreshold", arguments = list(threshold=1, column="RB",relationship="gte", cross=TRUE),label="RB.gte.1")
strat <- add.signal(strategy = strat, name="sigCrossover", arguments = list(columns=c("Close","SMA"),relationship="lt"),label="Cl.lt.SMA")
#Add rules
strat <- add.rule(strategy = strat, name='ruleSignal', arguments = list(sigcol="RB.gte.1", sigval=TRUE, orderqty=1000, ordertype='market', orderside='long', osFUN = 'osPCTEQ', pricemethod='market', replace=FALSE), type='enter', path.dep=TRUE)
strat <- add.rule(strategy = strat, name='ruleSignal', arguments = list(sigcol="Cl.lt.SMA", sigval=TRUE, orderqty='all', ordertype='market', orderside='long', pricemethod='market',TxnFees=0), type='exit', path.dep=TRUE)
# Process the indicators and generate trades
start_t<-Sys.time()
out<-try(applyStrategy(strategy = strat, portfolios = portfolio.st))
end_t<-Sys.time()
print("Strategy Loop:")
print(end_t-start_t)
start_t<-Sys.time()
updatePortf(Portfolio=portfolio.st,Dates=paste('::',as.Date(Sys.time()),sep=''))
end_t<-Sys.time()
print("updatePortf execution time:")
print(end_t-start_t)
#chart.Posn(Portfolio=portfolio.st,Symbol=symbols)
#Update Account
updateAcct(account.st)
#Update Ending Equity
updateEndEq(account.st)
#ending equity
getEndEq(account.st, Sys.Date()) + initEq
tstats <- tradeStats(Portfolio=portfolio.st, Symbol=symbols)
#View order book to confirm trades
#getOrderBook(portfolio.st)
#Trade Statistics for CAGR, Max DD, and MAR
#calculate total equity curve performance Statistics
ec <- tail(cumsum(getPortfolio(portfolio.st)$summary$Net.Trading.PL),-1)
ec$initEq <- initEq
ec$totalEq <- ec$Net.Trading.PL + ec$initEq
ec$maxDD <- ec$totalEq/cummax(ec$totalEq)-1
ec$logret <- ROC(ec$totalEq, n=1, type="continuous")
ec$logret[is.na(ec$logret)] <- 0
WI <- exp(cumsum(ec$logret)) #growth of $1
#write.zoo(nofilterWI, file = "E:\\nofiltertest.csv", sep=",")
period.count <- NROW(ec)-104 #Use 104 because there is a 104 week lag for the 52 week SD and 52 week median of SD
year.count <- period.count/52
maxDD <- min(ec$maxDD)*100
totret <- as.numeric(last(ec$totalEq))/as.numeric(first(ec$totalEq))
CAGR <- (totret^(1/year.count)-1)*100
MAR <- CAGR/abs(maxDD)
Perf.Stats <- c(CAGR, maxDD, MAR)
names(Perf.Stats) <- c("CAGR", "maxDD", "MAR")
Perf.Stats
#transactions <- getTxns(Portfolio = portfolio.st, Symbol = symbols)
#write.zoo(transactions, file = "E:\\nofiltertxn.csv")
charts.PerformanceSummary(ec$logret, wealth.index = TRUE, ylog = TRUE, colorset = "steelblue2", main = "Strategy with Volatility Filter")