# A simple example to demonstrate different exit rules for a multiple unit # strategy. There is a quick profiting taking exit rule implemented via a # chaining limit order (sell limit) for the first unit. And then there is a # longer running unit whose exit rule is governed by a SMA50 cross over. # Special thanks are in order to Ilya Kipnis and Joshua Ulrich for helping me # get this example working. library(quantstrat) # Here's the quoted help from Joshua: # # You need to explicitly set the timezone of your R session using: # Sys.setenv(TZ="UTC"). # # If you do not do this, then the blotter portfolio xts object will be # initialized with your current system's timezone, but the timezone on the GE # data is "UTC" because it has a "Date" class index. That causes the chain # rule's parent order price lookup to fail (because the timestamps do not # match). # # Wow! That is sublte. Even though all the examples clearly show setting the # timezone, I somehow managed to miss it. Sys.setenv(TZ="GMT") # Download data and create filters. tickerSymbol = "GE" strategyStr = 'TwoUnits' GE = getSymbols(tickerSymbol, from = "2012-01-01", to = "2012-11-15", auto.assign = FALSE) GE$SMA50 = SMA(Cl(GE), n = 50) GE$CrossBack = Cl(GE) - GE$SMA50 GE = GE["2012-07-15/"] magicGoLongDay = "2012-07-23" # Prepare a currency, portfolio, etc. currency("USD") stock(tickerSymbol, currency="USD", multiplier=1) rm.strat(strategyStr) initDate = index(GE[1]) - 1 initPortf(name=strategyStr, symbols=tickerSymbol, initDate=initDate, currency="USD") initAcct(name=strategyStr, portfolios=strategyStr, initDate=initDate, initEq=1e4, currency="USD") initOrders(portfolio=strategyStr, initDate=initDate) strategy(strategyStr, store=TRUE) # The indicator function. Force a TRUE value on 6/5/2012 - that's the day we # want to go long. myIndicator <- function(n=2) { indicator = xts(x=rep(0, nrow(GE)), order.by=index(GE) ) names(indicator) = "indValue" indicator[magicGoLongDay, "indValue"] = 1 return( indicator[, "indValue"] ) } add.indicator(strategy=strategyStr, name="myIndicator", arguments=list(n=2), label="indLabel") add.signal( strategy=strategyStr, name="sigThreshold", arguments=list( column = "CrossBack", relationship = "lt", threshold = 0, cross = TRUE ), label="sig.price.lt.sma50" ) add.signal( strategy=strategyStr, name="sigThreshold", arguments=list( column = "indValue.indLabel", relationship = "eq", threshold = 1, cross = TRUE ), label="goLong" ) # Exit all remaining units when price crosses below on SMA50 add.rule(strategy=strategyStr, name='ruleSignal', arguments = list( sigcol = "sig.price.lt.sma50", sigval = TRUE, replace = FALSE, orderside = 'long', ordertype = 'market', orderqty = 'all', prefer = 'Close' ), type = 'exit', label = 'ExitPriceLTSMA50' ) # Exit 1 unit as an initial profit target. add.rule(strategy=strategyStr, name='ruleSignal', arguments = list( sigcol = 'goLong', sigval = TRUE, replace = FALSE, orderside = 'long', ordertype = 'limit', tmult = FALSE, threshold = 1.50, orderqty = -1, # Make sure we reduce the # of units, not add on to them. Thank you Ilya. prefer = 'Open' ), type = 'chain', parent = 'EnterLong', label = 'TakeProfit' ) # Go long 2 units when we have a long signal. add.rule(strategy=strategyStr, name = 'ruleSignal', arguments = list( sigcol = 'goLong', sigval = TRUE, orderside = 'long' , ordertype = 'market', orderqty = 2, prefer = 'Open' ), type = 'enter', label = 'EnterLong' ) out = applyStrategy(strategy=strategyStr, portfolios=strategyStr, verbose=TRUE, debug=TRUE) # Calculate P&L and resulting equity with blotter dateRange=paste( as.character(index(first(GE))-1), '::', as.character(index(last(GE))+1), sep='') updatePortf(strategyStr, Dates = dateRange) updateAcct(strategyStr, Dates = dateRange) updateEndEq(strategyStr, Dates = dateRange) # Prepare for plotting. This only works for a 1 security portfolio. obook = getOrderBook(portfolio=strategyStr) obookXTS = obook[[1]][[1]] transactions = getTxns(Portfolio=strategyStr, Symbol=tickerSymbol) # An xts object full of zeros for plotting. zeros = xts(rep(0,nrow(GE)), order.by=index(GE)) buys = index(obookXTS[1]) sell1 = index(obookXTS[2]) sell2 = index(obookXTS[3]) # Draw the chart, filters, entries and exits. ta = paste("addTA(GE$SMA50, on=1, col=6);", "addTA(GE$CrossBack, col=6);", "addTA(zeros, on=2, col=7);", "addTA(Op(GE[buys,]) , type='p', col='white', pch=22, bg='darkgreen', cex=1.0, on=1 );", "addTA(Op(GE[sell1,]) , type='p', col='white', pch=22, bg='red', cex=1.0, on=1 );", "addTA(Cl(GE[sell2,]) , type='p', col='white', pch=22, bg='red', cex=1.0, on=1 );", sep="" ) chartSeries(GE, TA=ta)