[R-SIG-Finance] Stop Loss orders in quantstrat

Sanjay Mansabdar sanjay.mansabdar at yahoo.com
Tue Feb 20 10:55:22 CET 2018


 Greetings,
Here is my implementation of the stop loss code based on suggestions from Brian and others that I have received. To recap, the current implementation of the stop loss is to compare the price midbar to the stop limit price calculated as entry price - threshold. This causes intra day whipsaws to exit positions. I would like to model the stop loss mechanism that I follow in my trading, which is to compare the closing price on any day to entry price - threshold and if true then exit using a market order at open the following day. 
This is a long only system where MACD signal crossing zero generates the long position taken at the Close of the next day. This is done via the usual quantstrat functions, drawing from the macd demo code.
I also calculate the buy signal with cross = FALSE and lag this signal by 1 day to indicate if there is a position ( as the Stop Loss order needs to be position aware). This is called 'longpos'
Once the position is taken , I calculate an indicator SLPX that is essentially the stop loss price. If the close on any day is below this stop loss price then a market order is triggered to sell out. The SLPX indicator needs to work by taking  the buy signal, lagging this by a day as the opening trade is taken the next day and using this calculate the stop loss price which is entry price*(1-stop loss percent). This is the indicator "SLPX" This updates whenever a new position is taken else equals the previous value carried forward.
I create another signal that triggers when the closing price is below the stop loss as returned by the SLPX indicator. This is the signal "SLCondition"
A final signal "SLTrigger" [using sigFormula triggers if "longpos" and "SLCondition" are true simultaneously, with cross = TRUE so that this is evaluated only the first time this happens.
A Stop Loss order is fired as a market order if "SLTrigger" is set to 1. This will happen one day after.
There is also an exit condition if the MACD signal moves below zero (with its own signal) and the exit order is set as an oco with the stop loss order.
The code is attached with this mail and also presented at the end of this mail. I suspect there are much easier ways of doing this, however as an R novice, I am not quite sure of how else to make the indicators and signals position aware which they need to be to trigger the stop losses in this way the next day, and based on the close of the previous day, rather than on the same day and based on the low of the day. I will appreciate any help with how to do this, if there is an easier way.
When I run this the error I get is as follows. 
------
 applyStrategy(strategy=strat.name , portfolios=portfoli .... [TRUNCATED] Error in attr(x, "tsp") <- c(1, NROW(x), 1) :   attempt to set an attribute on NULLIn addition: Warning messages:1: In rm("account.st", "portfolio.st", "stock.str", "stratMACD", "initDate",  :  object 'stratMACD' not found2: In rm("account.st", "portfolio.st", "stock.str", "stratMACD", "initDate",  :  object 'start_t' not found3: In rm("account.st", "portfolio.st", "stock.str", "stratMACD", "initDate",  :  object 'end_t' not found
------
A few questions if anyone can help.
1. What am I doing wrong? 2. Is it even possible to make the signals position aware as I have done given that Ive seen in the documentation that they are not supposed to be path dependent (as I imagine position awareness demands)3. If yes, Is there a way of referencing positions and prices within signals?

Thanks in advance for any pointers. Quantstrat is an excellent bit of work from my perspective and I hope to learn enough about it to use it in my trading and to contribute to it.
Sanjay
########################



Full Code:
####################################################################################### This script tries to implement a stop loss on a closing price basis.# Rules:# BTO: when MACD crosses threshold of zero from below# STC: when MACD crosses threshold of zero from above# Stop Loss: If on any day the closing price is less than the BTO*(1-X), exit at market # on open the next day where X is the loss tolerable######################################################################################
# libraries###########################################################################
require(quantstrat)


# remove old parameters ##############################################################
try(rm("order_book.macd",pos=.strategy),silent=TRUE)
try(rm("account.macd","portfolio.macd",pos=.blotter),silent=TRUE)
try(rm("account.st","portfolio.st","stock.str","stratMACD","initDate","initEq",'start_t','end_t'),silent=TRUE)
# settingup quantstrat ##############################################################
stock.str='AAPL' 
currency('USD')
stock(stock.str,currency='USD',multiplier=1)
initDate<-'2009-12-31'
initEq=1000000
portfolio.st<-'macd'
account.st<-'macd'
strat.name <- 'stratMACD'
initPortf(portfolio.st,symbols=stock.str, initDate=initDate)
initAcct(account.st,portfolios=portfolio.st, initDate=initDate)
initOrders(portfolio=portfolio.st,initDate=initDate)
strategy(strat.name,store = TRUE)
# System parameters ##################################################################
fastMA <- 12 
slowMA <- 26 
signalMA <- 9
maType <-"EMA"
slpercent <-0.05
# Get Data ###########################################################################
getSymbols(stock.str,from=initDate)
# Custom Indicator Function #########################################################
# This is a function to create an indicator that is path dependent.# This function looks at the MACD signal that triggers an entry trade and then creates the appropriate stop loss# level for that entry. This will be used to create a signal 
SLPX<-function(OHLC,slpercent){  slpx<-rep(NA, times = nrow(OHLC))    # create the output vector and fill with NA  OHLC$longlag<-lag(OHLC$signal.gt.zero.x,n=1) #lag the BTO signal by 1 bar as position taken the next day  for (counter in (1:nrow(OHLC))){    slpx[counter]    if (!is.na(OHLC[counter]$longlag)) {  # do nothing if the signal is an NA value      if(OHLC[counter]$longlag==1) {        slpx[counter] = Op(OHLC[counter])*(1-slpercent) # if signal is 1, then figure out operating stop loss      } else {        slpx[counter] = slpx[counter-1] # is signal is zero then carry forward previously calculated value      }    }          }    return(slpx)}

# Add Indicator MACD   ###############################################################
add.indicator(strategy = strat.name,              name = "MACD",              arguments = list(x = quote(Cl(mktdata)), nFast=fastMA, nSlow = maSlow, nSig = signalMA, maType=maType)                )

# Add BTO Signal ######################################################################
add.signal(strategy = strat.name,           name = "sigThreshold",           arguments = list(column = "signal.MACD.ind",                            relationship = "gt",                            threshold = 0,                            cross = TRUE                            ),            label = "signal.gt.zero.x"              )
# Add STC Signal ######################################################################
add.signal(strategy = strat.name,           name = "sigThreshold",           arguments = list(column = "signal.MACD.ind",                            relationship = "lt",                            threshold = 0,                            cross = TRUE                            ),           label = "signal.lt.zero.x"          )
# Add signal that indicates whether there is a position due to BTO signal
add.signal(strategy = strat.name,           name = "sigThreshold",           arguments = list(column = "signal.MACD.ind",                            relationship = "gt",                            threshold = 0,                            cross = FALSE           ),           label = "signal.gt.zero.pos"  )
# Lag the above signal by 1 bar as long position gets taken the next bar ############
add.indicator (strategy = strat.name,                 name = "lag",                 arguments = (list(x=quote(mktdata$signal.gt.zero.pos), n=1)),                 label = "longpos"                 )

# Add SLPX Indicator ################################################################
add.indicator( strategy = strat.name,               name = "SLPX",               arguments = (list(OHLC=quote(mktdata), slpercent = 0.05)),               label = "SLPX")               


# Add signal to check whether Close on any day is less that the stop loss level from# the indicator SLPX  ###############################################################
add.signal(strategy = strat.name,           name = "sigComparison",           arguments = list(columns=c(quote(Cl(mktdata)),"SLPX")),           label = "SLCondition")        
# Check whether longpos and SL condition are met simultaneously #####################
add.signal( strategy = strat.name,            name = "sigFormula",            arguments = list(formula = "longpos & SLCondition", cross = TRUE),            label = "SLTrigger"          )
# Add BTO Rule #######################################################################
add.rule(strategy = strat.name,         name =  "ruleSignal",         arguments = list(                          sigcol = "signal.gt.zero.x",                          sigval = TRUE,                          orderqty = 100,                          prefer = "Open",                          replace = TRUE,                          ordertype = 'market',                          orderside = 'long',                          threshold = NULL                          ),         type= "enter",         label = "enterlong"        )
# Add STC Rule #######################################################################
add.rule(strategy = strat.name,         name =  "ruleSignal",         arguments = list(           sigcol = "signal.lt.zero.x",           sigval = TRUE,           orderqty = 'all',           prefer = "Open",           replace = FALSE,           ordertype = 'market',           orderside = 'long',           threshold = NULL,           orderset = 'ocolong'         ),         type= "exit",         label = "exitlong")
# Add Stop Loss Rule [part of orderset 'ocolong'] ##############################
add.rule(strategy = strat.name,         name =  "ruleSignal",         arguments = list(           sigcol = "SLTrigger",           sigval = TRUE,           orderqty = 'all',           prefer = "Open",           replace = FALSE,           ordertype = 'market',           orderside = 'long',           threshold = NULL,           orderset = 'ocolong'         ),         type= "exit",         label = "SL")

#Apply Strategy #######################################################################
applyStrategy(strategy=strat.name , portfolios=portfolio.st)
# Updates #############################################################################
updatePortf(Portfolio=portfolio.st,Dates=paste('::',as.Date(Sys.time()),sep=''))
#  Outputs ############################################################################
chart.Posn(Portfolio=portfolio.st,Symbol=stock.str)
plot(add_MACD(fast=fastMA, slow=slowMA, signal=signalMA,maType="EMA"))
print ('order book')

getOrderBook(portfolio.st)
print('transactions')

getTxns(Portfolio=portfolio.st, Symbol=stock.str)



    On Tuesday, February 13, 2018, 6:28:13 PM GMT+5:30, Sanjay Mansabdar <s

  I have  been trying to implement what Brian has suggested for a simple long only macd based strategy.  Given that I am new to quantstrat, this may be quite an elementary question, but here goes. 
1. I have a simple long only MACD based system that gives me entry and exit signals on T.2. On the basis os a long signal I trigger a market order to buy on T+1, at the open.3. Based on this execution, I need to set a hard stop on the position entered in #2, that is x% below the execution price of 2, with the comparison being done at the close of each day, and if the signal triggers on some day D, the order is executed as a market sell order on the next day D+1.My signal essentially says "Check to see if the closing price on any day is less than the execution prices of the last opening trade minus a threshold and if it is, trigger a signal".4. This clearly needs, at any point, the value of the execution price of the market order in #2, the timestamp of #2 5.Finally the rule that triggers the market sell order described in #3 would need to know the existing position size as well.
I am not quite sure how to extract these state variables to include in the signal and in the rule. Any help on this would be appreciated. 
Thanks in advance.

    On Tuesday, February 13, 2018, 12:42:07 PM GMT+5:30, Sanjay Mansabdar <

 I am not sure how to reply to digest messages in the thread, so apologies in advance for errors
@Brian, I think there is no error with the implementation as it stands of stop limit orders. However IMHO stop loss logic is not necessarily the same thing as stop limit orders and perhaps needs to be thought of separately. I will try and follow the route you have suggested.
Thanks
Regards    
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://stat.ethz.ch/pipermail/r-sig-finance/attachments/20180220/b891c547/attachment.html>

-------------- next part --------------
A non-text attachment was scrubbed...
Name: macd_SL6.R
Type: application/octet-stream
Size: 7792 bytes
Desc: not available
URL: <https://stat.ethz.ch/pipermail/r-sig-finance/attachments/20180220/b891c547/attachment.obj>


More information about the R-SIG-Finance mailing list