Question on trailing stop orders



  • Hi,

    in the example here , trail stop order is created as below
    '''

    def next(self):
        if not self.position:
            if self.crup:
                o = self.buy()
                self.order = None
                print('*' * 50)
    
        elif self.order is None:
            if self.p.stoptype == bt.Order.StopTrailLimit:
                price = self.data.close[0]
                plimit = self.data.close[0] + self.p.limitoffset
            else:
                price = None
                plimit = None
    
            self.order = self.sell(exectype=self.p.stoptype,
                                   price=price,
                                   plimit=plimit,
                                   trailamount=self.p.trailamount,
                                   trailpercent=self.p.trailpercent)
    

    '''

    I have a few doubts.

    1. My understanding of the code: on day 1 new buy order created and 'self.order=None'. The next day, the buy order got executed at open and 'position.size>0', then create a 'StopTrailLimit' order. On day 3, if price reached a certain level, the StopTrailLimit order got executed. What If on day 2 stop price is already reached, there is no way to stop loss because the StopTrailLimit will only be executed on the next bar after creation (which is already day 3)?? What if you want stop loss immediately take effect after position is entered on day 2 at open.

    2. Suppose a StopTrailLimit is never executed and the original position has been closed. If later you want to enter into a new position, I think you have to cancel the existing StopTrailLimit order. Strangely, according to the sample code, if there is pending order (including StopTrailLimit), new buy cannot be created. StopTrailLimit does not die with the original position, but forbids creation of new position??

    I tried to implement stop trail orders on my own. The strategy is long short. Can someone tell me if the implementation is correct? Thank you!

    '''

     def next(self):
        # enter into positions
        if self.buysell>0:
            self.cancel() #cancel existing stop loss orders
            self.buy(exectype=bt.Order.Market) #enter into new position
            self.stop_long = 1 #indicates a new long is just entered, need to put a stop loss sell order
    
        elif self.buysell<0:
            self.cancel()
            self.buy(exectype=bt.Order.Market)
            self.stop_short = 1
    
        #create trailing stop loss orders
        elif self.stop_long == 1 and self.position.size>0:
            self.stop_long = self.sell(exectype=bt.Order.StopTrailLimit,
                                   trailpercent=self.p.trailpercent)
        elif self.stop_short == 1 and self.position.size<0:
            self.stop_short = self.buy(exectype=bt.Order.StopTrailLimit,
                                   trailpercent=self.p.trailpercent)
    

    '''



  • @Yelloww said in Question on trailing stop orders:

    Couple thoughts that might help or not.

    My understanding of the code: on day 1 new buy order created and 'self.order=None'. The next day, the buy order got executed at open and 'position.size>0', then create a 'StopTrailLimit' order. On day 3, if price reached a certain level, the StopTrailLimit order got executed. What If on day 2 stop price is already reached, there is no way to stop loss because the StopTrailLimit will only be executed on the next bar after creation (which is already day 3)??

    Correct.

    What if you want stop loss immediately take effect after position is entered on day 2 at open.

    If you will use cheat-on-open, then you will have an ability to check what is going on at day's open and issue stoptrail order at open. It should be executed at the same day if condition met. Or you need to move to lower timeframe.

    Suppose a StopTrailLimit is never executed and the original position has been closed. If later you want to enter into a new position, I think you have to cancel the existing StopTrailLimit order.

    Correct.



  • I post my own implementation of trail stop orders here. It may not be absolutely correct/optimum. Just for the reference of any one who are interested.

    There are 2 rules:

    1. position can be both long/short
    2. all new long/short orders must be executed successfully.

    '''

    def next(self):
        # need to go long
        if self.curr_buysell[0] > 0 and self.prev_buysell <= 0 and self.position.size <= 0:
            if self.position.size < 0:
                self.close_short = self.close()  # close existing positions
                self.close_short.addinfo(ordername="FLATSHORT")
                self.log('FLATSHORT CREATE, size {}'.format(self.close_short.created.size))
                self.cancel(self.stop_short)
            self.enter_long = self.buy()
            self.enter_long.addinfo(ordername="LONGENTER")
            self.log(
                'LONGENTER CREATE, close price {}, size {}'.format(self.data.close[0], self.enter_long.created.size))
    
            self.stop_long = self.sell(exectype=self.p.stoptype, trailpercent=self.p.trailpercent)
            self.stop_long.addinfo(ordername="STOPLONG")
    
        # need to go short
        elif self.curr_buysell[0] < 0 and self.prev_buysell >= 0 and self.position.size >= 0:
            if self.position.size > 0:
                self.close_long = self.close()  # close existing positions
                self.close_long.addinfo(ordername="FLATLONG")
                self.log('FLATLONG CREATE, size {}'.format(self.close_long.created.size))
                self.cancel(self.stop_long)
            self.enter_short = self.sell()
            self.enter_short.addinfo(ordername="SHORTENTER")
            self.log(
                'SHORTENTER CREATE, close price {}, size {}'.format(self.data.close[0], self.enter_short.created.size))
    
            self.stop_short = self.buy(exectype=self.p.stoptype, trailpercent=self.p.trailpercent)
            self.stop_short.addinfo(ordername="STOPSHORT")
    
        self.prev_buysell = self.curr_buysell[0]
    

    '''


Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.