For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

How to use tick data for stop loss in live trading?



  • I can't seem to find a posting regarding this --

    How does one use live tick data for stop loss where the strategy itself otherwise uses a different time frame (e.g. 10 second bars) for entries and exits?

    This is for LIVE trading, so:
    --adddata() has not worked (adddata seems to work only for backtesting when you have a defined data set)
    --cerebro.resampledata does not seem to be able to process resampling to 1 tick (or any tick amounts, just for time intervals).

    (New to backtrader and python so anything stated above can be challenged freely.)

    Thanks a lot,



  • I am keen to see responses on this too.

    For Stop Losses you can place these with your broker at the time of placing the order. The SL will be hit and executed by the broker regardless of Backtrader timeframes.

    I typically work on 1min bars in the current market however fast price movements sometimes mean I am not getting the best close position timing when the exit condition is hit.

    The only solution I've been able to think of (but not yet tried) is to set up 'data' and 'data1' on two different timeframes. 'data' would be for say 5 sec bar (for closing positions) and 'data1' would be for the entry conditions on a higher timeframe (i.e. 1min).



  • Ok - so I've worked up a solution.

    Let's assume you want to enter or exit (dynamic take profit or stop loss) faster than the next bar of your primary timeframe that drives your indicators. In this example I have my main indicators on data1 with timeframe = 1 min. I also have data0 set to 5 sec.

    Adapting the line coupler examples from here to Bollinger Bands, instead of Pivot Points and SMAs:
    https://www.backtrader.com/docu/concepts/#lines-coupling
    and here:
    https://www.backtrader.com/blog/posts/2016-05-05-indicators-mixing-timeframes/indicators-mixing-timeframes/

    In this scenario, instead of waiting 1min to complete the bar to enter a position, if 5 second bars from self.data0.low or self.data0.high breach the Bollinger bands defined using 1min, then orders will be placed.

    This provided a much faster response to shifting prices that sometimes triggered an entry but then moved away from the 'optimal' trade point before the 1 min bar was complete.

    From my testing, be sure to only reference the coupled Bollinger references. If referring to self.boll (pre-couple), errors will occur. That had me stumped for a while when using legacy code that wasn't referencing the bb line coupling.

    class TheStrategy(bt.Strategy):
    
        params = (
            bbperiod = 20
            devfactor = 2
            )
    
        def __init__(self):
    
            self.boll = bb_lc = bt.indicators.BollingerBands(self.data1, period=self.p.bbperiod, devfactor=self.p.devfactor, plot=False) #Standard, uncoupled Bollinger Band indicator.
    
            #BELOW: LINE COUPLED BOLLINGER BANDS AND DATA0
    
            bb_lc1 = bb_lc()    #Couple the Boll Band indicators
            self.bb_lc1_range = bb_lc1.top - bb_lc1.bot     #Range between BB top and bottom lines
            
            self.bb_lc1_top = bb_lc1.top    #Reference for formulas later in next() [not shown]
            self.bb_lc1_bot = bb_lc1.bot    #Reference for formulas later in next() [not shown]
            
            self.buysig = (self.data0.low < bb_lc1.bot) #BUY when data0 (5 secs) falls below BB Bottom on data1 lines (1min)
            self.sellsig = (self.data0.high > bb_lc1.top)   #SELL when data0 (5 secs) moves above BB Top on data1 lines (1min)
    
        def next(self):
    
            if not self.position:
                if  (self.buysig[0]):
                    #BUY ORDER
                if (self.sellsig[0]):
                    #SELL ORDER
                
    


  • @kirahvi Is this the type of solution you were looking for?



  • @mics Thanks! Looks good. I was just looking for intra-bar stoploss functionality which seems to be a built-in-method (as I've found out). Now the problem has become how to close a stoploss once the original position closes.



  • @kirahvi Give the the Stop Loss order a name and then cancel it as part of completing an close order.

    When a new position is opened and a stop loss is placed in association with it, give it a name. For instance, here the buy_ord places a long position and sets a Stop Loss with designation of self.stop_ord.

    When a trigger occurs to close the position, the Stop Loss is cancelled as shown below.

    def openlong(self, *args):
        
        buy_ord = self.buy(exectype=bt.Order.Market, size=self.stake)
    
        self.stop_ord = self.sell(exectype=bt.Order.Stop, price=self.long_stop, size=self.stake)
        
        self.stop_ord.addinfo(name=self.productname+'LongStopLoss')
    
    
    def closelong(self, *args):
    
        posi = abs(self.position.size)
    
        cls_ord = self.close(size=posi)
            
        cancel = self.cancel(self.stop_ord)
    


  • @mics, This is exactly the scenario I'm working on. Thank you!! I'll give it a try and report back.



  • @mics Yes, it works! Thanks so much!


Log in to reply
 

});