I'm trying to create a Bollinger Band Strategy using QuantStrat that uses multiple standard deviations, exiting on a previous level's Bollinger Band or the Moving Average if there are no Bands below the examined Band. To do so, I made this code to create unique entry and exit rules for each level:
initEQ<-10000
MAperiod_input<- 200
stdev_input<-3.5
transaction_cost_input<-0
levels_input<-10
profit_ticks_input<-1
strategy.st <- portfolio.st <- account.st <- "BBands"
stdev_list<-seq(stdev_input/levels_input, stdev_input, by = stdev_input/levels_input)
initPortf(portfolio.st, symbols = c("PairsFinal"))
initAcct(account.st, portfolios = portfolio.st, initEq = initEQ)
initOrders(portfolio.st)
strategy(strategy.st, store = T)
#####
#Loop to create entries and exits for each level of Bollinger Band
for(i in c(1:length(stdev_list))){
BollbandLabel<-paste0("BollBand",i)
upperBandCrossLabel<-paste0("upperBandCross",i)
lowerBandCrossLabel<-paste0("lowerBandCross",i)
exitBollBandLabel<-paste0("exitBollBand",i)
upperExitBandCrossLabel<-ifelse(i - profit_ticks_input > 0, paste0("upperExitBandCross",i), "Cross.mid")
lowerExitBandCrossLabel<-ifelse(i - profit_ticks_input > 0, paste0("lowerExitBandCross",i), "Cross.mid")
exit_stdev<-ifelse(which(stdev_list[i] %in% stdev_list) - profit_ticks_input > 0, stdev_list[(i - profit_ticks_input)],0)
add.indicator(strategy.st, name = strategy.st, arguments = list(HLC = quote(HLC(mktdata)) , n = MAperiod_input, sd = stdev_list[i]), label = BollbandLabel)
##Enters
add.signal(strategy.st, "sigCrossover", arguments = list(columns = c("Cl", paste0("dn.",BollbandLabel)), relationship = "lt"), label = upperBandCrossLabel)
add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = upperBandCrossLabel, orderqty = -100, orderside='short', sigval = T, ordertype = "market", TxnFees = transaction_cost_input),type = 'enter')
add.signal(strategy.st, "sigCrossover", arguments = list(columns = c("Cl", paste0("up.",BollbandLabel)), relationship = "gt"), label = lowerBandCrossLabel)
add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = lowerBandCrossLabel, orderqty = 100, orderside='long', sigval = T, ordertype = "market", TxnFees = transaction_cost_input),type = 'enter')
##Exits
if(upperExitBandCrossLabel != "Cross.mid"){
add.indicator(strategy.st, name = "BBands", arguments = list(HLC = quote(HLC(mktdata)) , n = MAperiod_input, sd = stdev_list[i - profit_ticks_input]), label = exitBollBandLabel)
add.signal(strategy.st, "sigCrossover", arguments = list(columns = c("Cl", paste0("up.",exitBollBandLabel)), relationship = "lt"), label = upperExitBandCrossLabel)
add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = upperExitBandCrossLabel, orderqty = 100, orderside='long', sigval = T, ordertype = "market", TxnFees = transaction_cost_input),type = 'exit')
add.signal(strategy.st, "sigCrossover", arguments = list(columns = c("Cl", paste0("dn.",exitBollBandLabel)), relationship = "gt"), label = lowerExitBandCrossLabel)
add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = lowerExitBandCrossLabel, orderqty = -100, orderside='short', sigval = T, ordertype = "market", TxnFees = transaction_cost_input),type = 'exit')
}else{
add.signal(strategy.st, "sigCrossover", arguments = list(columns = c("Cl", "Cross.mid"), relationship = "lt"), label = upperExitBandCrossLabel)
add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = upperExitBandCrossLabel, orderqty = 100, orderside='long', sigval = T, ordertype = "market", TxnFees = transaction_cost_input),type = 'exit')
add.signal(strategy.st, "sigCrossover", arguments = list(columns = c("Cl", "Cross.mid"), relationship = "gt"), label = lowerExitBandCrossLabel)
add.rule(strategy.st, name = "ruleSignal", arguments = list(sigcol = lowerExitBandCrossLabel, orderqty = -100, orderside='short', sigval = T, ordertype = "market", TxnFees = transaction_cost_input),type = 'exit')
}
}
strat<-applyStrategy(strategy.st, portfolio.st, mktdata = OHLC(PairsFinal))
updatePortf(portfolio.st)
strat<-getPortfolio(portfolio.st)$summary
tradeStats(portfolio.st)
However, I only want a single order at each level, and this code seems to be repeating already filled orders. Is there a way to limit each Bollinger Band of this ruleset to a single Open Position until it exits? This is my first time using QuantStrat, so if there's a multi-level function I missed, please let me know.