quantstrat in R: Setting a date based exit signal

quantitative-finance, quantmod, quantstrat, r, xts

Solution

quantstrat, as described in the manual, is a signals-based framework. It is not designed for filters based trades really.

You could do what you want by using the delay argument to your exit rule. Set the delay to be one day, and the prefer argument to prefer a different price column.

I'm not going to write it for you, but that is enough information to solve your problem.

Problem

Much of quantstrat and the accompanying examples seem to be set around entering and exiting trades by crossing some kind of technical indicator. However, let's say you have an arbitrary indicator which you're using to trigger an entry to the trade, but then you want to just unwind the trade on the next day's open or close. How would you best implement this example? Let's take the following example: - Two instruments: XYZ and ABC - Entry Signal: Can be anything - we just want to enter the trade any time our "signal" evaluates to true. For this example, let's say any time the ratio of XYZ/ABC changes by more than 1% in either direction from Open to Close on T+0 - Exit Signal: A market event such as an Open or Close. Let's say, in this example, we want to unwind the trade we set above at the next day's open. For instance, writing something like this using `blotter` would be relatively easy: Assume xts object called `ratio` with columns for: - ABC OHLC, - XYZ OHLC, - the ratio of ABC/XYZ expressed as an OHLC - currency OHLC "CCY" (this is a cross currency pair) - our indicator (the OpCl(ABC/XYZ)), - "signal up?" which will evaluate to 1 if the indicator is > 1%, else 0 if not - "signal dn?" which will evaluate to 1 if the indicator is < -1%, else 0 if not Our code would then be: ``` for( i in 1:nrow(ratio) ) { ## Define the dates: CurrentDate <- index(ratio[i,]) NextDate <- index(ratio[i+1,]) ## Define the prices: XYZClosePrice <- as.numeric(ratio$XYZ.Close[i,]) ABCClosePrice <- as.numeric(ratio$ABC.Close[i,]) XYZOpenPrice <- as.numeric(ratio$XYZ.Open[i+1,]) ABCOpenPrice <- as.numeric(ratio$ABC.Open[i+1,]) CCYClosePrice <- as.numeric(ratio$CCY.Close[i,]) CCYOpenPrice <- as.numeric(ratio$CCY.Open[i+1,]) ## Define the spread: SpreadOp <- ABCOpenPrice/XYZOpenPrice SpreadCl <- ABCClosePrice/XYZClosePrice ## Define the hedge ratio (let's say XYZ has a multiplier of 25 and ABC of 50) HedgeOp <- 25 * ((CCYOpenPrice/50)/SpreadOp) HedgeCl <- 25 * ((CCYClosePrice/50)/SpreadCl) # We want to trade 20 lots of XYZ each time with the corresponding hedge amount of ABC Posn <- round(20 * HedgeCl,0) ## Add the trading rules (if move > 1% / else move <-1%): # >= +1 % move if(ratio[i,'signal up?']==1){ ## enter position on today's close addTxn(strat.name, Symbol='XYZ', TxnDate=CurrentDate, TxnPrice=XYZClosePrice, TxnQty = 20 , TxnFees=0) addTxn(strat.name, Symbol='ABC', TxnDate=CurrentDate, TxnPrice=ABCClosePrice, TxnQty = - Posn , TxnFees=0) ## exit position tomorrow's open addTxn(strat.name, Symbol='XYZ', TxnDate=NextDate, TxnPrice=XYZOpenPrice, TxnQty = - 20, TxnFeABC=0) addTxn(strat.name, Symbol='ABC', TxnDate=NextDate, TxnPrice=ABCOpenPrice, TxnQty = Posn , TxnFeABC=0)} else { # <= -1% move if(ratio[i,'signal dn?']==1){ ## enter position on today's close addTxn(strat.name, Symbol='XYZ', TxnDate=CurrentDate, TxnPrice=XYZClosePrice, TxnQty = -20 , TxnFees=0) addTxn(strat.name, Symbol='ABC', TxnDate=CurrentDate, TxnPrice=ABCClosePrice, TxnQty = Posn , TxnFees=0) # exit position on tomorrow's open addTxn(strat.name, Symbol='XYZ', TxnDate=NextDate, TxnPrice=XYZOpenPrice, TxnQty = 20, TxnFees=0) addTxn(strat.name, Symbol='ABC', TxnDate=NextDate, TxnPrice=ABCOpenPrice, TxnQty = - Posn , TxnFees=0)} } ``` This works just fine. But let's say we want to implement this in `quantstrat` -- it gets a bit trickier. Assuming all portfolios, accounts, indicators and signals etc are set up correctly, i would then add these trading rules to enter the trade: ``` > strat <- add.rule(strat, name='ruleSignal', + arguments = list(sigcol="Cl.gt.1pct", sigval=TRUE, orderqty=20, + ordertype='market', orderside='long', pricemethod='market'), + type='enter', path.dep=TRUE,symbol='XYZ') > strat <- add.rule(strat, name='ruleSignal', + arguments = list(sigcol="Cl.lt.1pct", sigval=TRUE, orderqty=Posn, + ordertype='market', orderside='short', pricemethod='market'), + type='enter', path.dep=TRUE,symbol='ABC') ``` My question is: How do I enter the next two `ruleSignal` 's to simply unwind the pair on the next day's open? I know it probably has something to do with the `timestamp` argument in `ruleSignal` but I can't figure out how I'd implement it. There may be a very simple solution here, but I've caught myself in a bit of a loop trying to solve this one. As ever, any help very much appreciated.

Original source