Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    Updating Stop Loss based on current profit

    General Code/Help
    5
    7
    409
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • B
      bgrosso last edited by

      Hi,

      I am currently issuing a bracket order as follows:

      self.buy_bracket(exectype=bt.Order.Market,
                                       size=qty,
                                       limitprice=cash*3*self.p.risk / qty + self.data.close[0],
                                       stopprice=stop_price,
                                       )
      

      I wish to update the stop order issue based on the profit of the current trade. There is only one trade open at any given moment. I tried to use the trail order and trailpercent method but it doesn't seem to work.

      In general, here's what I would like the system to do:

      if profit > 20, stop loss should be at break-even
      if profit > 40, stop loss should be at 20
      ... and so on.

      Any clever ideas on how to implement it?

      1 Reply Last reply Reply Quote 1
      • A
        ab_trader last edited by

        If you really want action like in that last paragraph, than each next() you cancel existing stop order, calculate profit and new stop price, and issue new stop order. No bracket orders required.

        But it seems that it is not that easy.

        1 Reply Last reply Reply Quote 0
        • B
          bgrosso last edited by

          Cool, thanks!

          1 Reply Last reply Reply Quote 0
          • run-out
            run-out last edited by

            You can manage the stoplimit prices by resetting the price in the stop order. Set the initial stop order manually after the buy, then reset the stop price as price climbs. This has the advantage of not creating and cancelling stop orders over and over.

            I'm not 100% sure this is acceptable to change the price of the outstanding stop order this way, but it's working on my machine.

            You can set the price manually any way you wish.

            I borrowed this code from here.

            class BaseStrategy(bt.Strategy):
                params = dict(fast_ma=10, slow_ma=20,)
            
                def __init__(self):
                    self.reset_price = 0
                    self.so = []
            
                    # omitting a data implies self.datas[0] (aka self.data and self.data0)
                    fast_ma = bt.ind.EMA(period=self.p.fast_ma)
                    slow_ma = bt.ind.EMA(period=self.p.slow_ma)
                    # our entry point
                    self.crossup = bt.ind.CrossUp(fast_ma, slow_ma)
            
            
            class ManualStopOrStopTrail(BaseStrategy):
                params = dict(
                    stop_loss=0.15,  # price is .15 below the purchase price at intervals.
                )
            
                def notify_order(self, order):
                    if not order.status == order.Completed:
                        return  # discard any other notification
            
                    if order.status == order.Canceled:
                        return
            
                    if not self.position:  # we left the market
                        print("SELL@price: {} {:.2f}".format(self.date, order.executed.price))
                        self.so = []
                        return
            
                    # We have entered the market
                    print("BUY @price: {} {:.2f}".format(self.date, order.executed.price))
            
                    stop_price = order.executed.price - self.p.stop_loss
                    self.so = [self.sell(exectype=bt.Order.Stop, price=stop_price)]
                    self.reset_price = order.executed.price + self.p.stop_loss
            
                def next(self):
                    self.date = self.data.datetime.date()
                    print("{} {:.2f}".format(self.date, self.data[0]))
            
                    if len(self.so) > 0 and self.datas[0].close[0] > self.reset_price:
                        new_stop_price = self.reset_price - self.p.stop_loss
                        print("{} Stop price changed to: {:.2f}".format(self.date, new_stop_price))
                        # Change the price in the order in the self.so list.
                        self.so[0].created.price = new_stop_price
                        # Reset the next price limit
                        self.reset_price = self.reset_price + self.p.stop_loss
                    else:
                        pass
            
                    if not self.position and self.crossup > 0:
                        # not in the market and signal triggered
                        self.buy()
            
            

            Here's an output using .15 cent intervals.

            2004-03-23 22.04
            2004-03-24 22.25
            2004-03-25 23.47
            BUY @price: 2004-03-25 23.38
            2004-03-26 23.57
            2004-03-26 Stop price changed to: 23.38
            2004-03-29 23.84
            2004-03-29 Stop price changed to: 23.52
            2004-03-30 24.39
            2004-03-30 Stop price changed to: 23.67
            2004-03-31 24.24
            2004-03-31 Stop price changed to: 23.82
            2004-04-01 24.73
            2004-04-01 Stop price changed to: 23.97
            2004-04-02 25.08
            2004-04-02 Stop price changed to: 24.12
            2004-04-05 25.00
            2004-04-05 Stop price changed to: 24.27
            SELL@price: 2004-04-05 24.27
            2004-04-06 24.39
            2004-04-07 24.17
            2004-04-08 28.11
            2004-04-12 27.57
            
            
            1 Reply Last reply Reply Quote 1
            • vladisld
              vladisld last edited by

              It will most probably not work in real live trading. For this to work updating the 'order.created.price' should generate some sort of notification to the broker , and I think there is no such functionality.

              1 Reply Last reply Reply Quote 1
              • B
                booboothefool last edited by

                @vladisld Were you able to verify whether the quick update of the stop loss works in live trading?

                vladisld 1 Reply Last reply Reply Quote 0
                • vladisld
                  vladisld @booboothefool last edited by

                  @booboothefool said in Updating Stop Loss based on current profit:

                  @vladisld Were you able to verify whether the quick update of the stop loss works in live trading?

                  I didn't try it on a real live broker - not using this technique in my system. However if we'll take a look at the backtrader code, we'll see that updating the price member of the existing order - will just update the price member - that's all. No communication with a broker is done at that point nor in any point further the road ( so it works by chance in internal broker simulator).

                  AFAIU updating the existing order through live broker will move the order to the end of the order queue for this particular price - something that is not required for local simulation.

                  I believe this was already discussed here

                  1 Reply Last reply Reply Quote 1
                  • 1 / 1
                  • First post
                    Last post
                  Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
                  $(document).ready(function () { app.coldLoad(); }); }