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/

    Cancelling Bracket order following closing of the main side

    General Code/Help
    4
    17
    1738
    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.
    • Rumen Nenov
      Rumen Nenov last edited by

      For while I've been trying to solve following problem: When I place bracket order with stop and limit, and if later the trade is closed not by stop or limit orders, but by the strategy logic, they (the children orders - Stop and Limit) remain active and one of them gets executed later. To avoid this I need to cancel it by using the order reference and call self.cancel(sop_order) or similar.

      My logic suggests that to call it I need to use something like if trade.isclosed: or maybe if self.position.size == 0: and then call the order by its id and this is where I get super confused.

      I wrote about this previously but couldn't find a solution since.

      Any ideas how to implement this part the code?

      Thanks,
      Rumen

      1 Reply Last reply Reply Quote 0
      • B
        backtrader administrators last edited by

        The fundamental problem is that a position open by a bracket should not have additional logic to close the position independently.

        But if you insist in shooting yourself in the foot, the only thing you have to do is to keep a reference to any of the bracketing orders (stop-loss side or take-profit side) and cancel it whenever you close the position with the bracket-foreign logic.

        if logic_orders_to_close_the_position:
           self.cancel(take_profit_order)
        
        1 Reply Last reply Reply Quote 1
        • Dallascat
          Dallascat last edited by

          Hi @Rumen-Nenov...did you get this figured out? I am at a similar junction you were when you wrote this. Thanks!

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

            @Dallascat Do you just have the one bracket order or multiple different orders?

            RunBacktest.com

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

              @run-out I am still fairly new to BT and python. Basically there are 3 signals generated - long, short or out. I have just learned on how to put in brackets if I want to use a PT and SL. But there are times when none of those gets hit and a signal to get out of the position hits (goes flat) and that leaves the PT and SL open if I use the brackets. So I assume I need to do it another way (issue PT and SL separately, and have them cancelled when the position == 0) instead of the brackets, unless there was a way to cancel the brackets if I went flat. Make sense?

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

                @Dallascat said in Cancelling Bracket order following closing of the main side:

                @run-out I am still fairly new to BT and python. Basically there are 3 signals generated - long, short or out. I have just learned on how to put in brackets if I want to use a PT and SL. But there are times when none of those gets hit and a signal to get out of the position hits (goes flat) and that leaves the PT and SL open if I use the brackets. So I assume I need to do it another way (issue PT and SL separately, and have them cancelled when the position == 0) instead of the brackets, unless there was a way to cancel the brackets if I went flat. Make sense?

                Thank you for that explanation. Could you please include your code? Thanks.

                RunBacktest.com

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

                  @run-out Sure, this is just a simple strategy for my learning purposes of BT and python:

                  `from future import (absolute_import, division, print_function,
                  unicode_literals)
                  from datetime import datetime
                  import backtrader as bt

                  Create a Strategy

                  class TestStrategy(bt.Strategy):
                  params = (('order_pct', 0.95), ("buy_price_adjust", 0.0), ("buy_limit_adjust", 0.02), ("buy_stop_adjust", 0.02))

                  def log(self, txt, dt=None):
                      """ Logging function for this strategy"""
                      dt = dt or self.datas[0].datetime.date(0)
                      print('%s, %s' % (dt.isoformat(), txt))
                  
                  def __init__(self):
                      # Keep a reference to the "close" line in the data[0] dataseries
                      self.bar_executed = len(self)
                      self.dataclose = self.datas[0].close
                  
                      # Create an order list
                      self.o_li = list()
                  
                      # To keep track of pending orders and buy price/commission
                      self.order = None
                      self.buyprice = None
                      self.buycomm = None
                  
                      # Add EMA and TRIX
                      self.ema = bt.indicators.ExponentialMovingAverage((self.datas[0].high + self.datas[0].low) / 2, period=50,
                                                                        plotname="EMAMid")
                      self.ema2 = bt.indicators.ExponentialMovingAverage((self.datas[0].high + self.datas[0].low) / 2, period=15,
                                                                        plotname="EMAMid")
                      self.atr = bt.indicators.ATR(period=50, movav=bt.indicators.MovAv.Exponential)
                  
                      # Indicators for plotting
                      bt.indicators.ExponentialMovingAverage(self.datas[0], period=50)
                  
                  def notify_order(self, order):
                      if order.status in [order.Submitted, order.Accepted]:
                          # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                          return
                  
                      # Check if an order has been completed
                      # Attention: broker could reject order if not enough cash
                      if order.status in [order.Completed, order.Canceled, order.Margin]:
                          if order.isbuy():
                              self.log(
                                  'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Size %.2f' %
                                  (order.executed.price,
                                   order.executed.value,
                                   order.executed.comm,
                                   order.executed.size))
                  
                              self.buyprice = order.executed.price
                              self.buycomm = order.executed.comm
                          else:  # Sell
                              self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Size %.2f' %
                                       (order.executed.price,
                                        order.executed.value,
                                        order.executed.comm,
                                        order.executed.size))
                          self.bar_executed = len(self)
                  
                      elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                          self.log('Order Canceled/Margin/Rejected')
                  
                      # Clean up the order list.
                      if not order.alive() and order in self.o_li:
                          self.o_li.remove(order)
                  
                      # Write down: no pending order
                      self.order = None
                  
                  def notify_trade(self, trade):
                      if not trade.isclosed:
                          return
                  
                      self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm))
                  
                  def next(self):
                      # Check if an order is pending ... if yes, we cannot send a 2nd one
                      if self.order:
                          return
                      # Check if we are in the market
                      if not self.position:
                  
                          if self.ema[0] >= self.ema[-1] and (self.ema2[0] >= self.ema2[-1]):
                              price = self.data.close[0] * (1.0 - self.p.buy_price_adjust)
                              price_limit = price + self.atr[0]
                              price_stop = price - self.atr[0]
                  
                              self.long_buy_order = self.buy_bracket(
                                  data=self.datas[0],
                                  size=None,
                                  exectype=bt.Order.Limit,
                                  plimit=price,
                                  stopprice=price_stop,
                                  stopexec=bt.Order.Stop,
                                  limitprice=price_limit,
                                  limitexec=bt.Order.Limit,
                              )
                  
                          if self.ema[0] <= self.ema[-1] and (self.ema2[0] <= self.ema2[-1]):
                              price = self.data.close[0] * (1.0 - self.p.buy_price_adjust)
                              price_limit = price - self.atr[0]
                              price_stop = price + self.atr[0]
                  
                              self.short_sell_order = self.sell_bracket(
                                  data=self.datas[0],
                                  size=None,
                                  exectype=bt.Order.Limit,
                                  plimit=price,
                                  stopprice=price_stop,
                                  stopexec=bt.Order.Stop,
                                  limitprice=price_limit,
                                  limitexec=bt.Order.Limit,
                              )
                  
                      if self.position.size > 0 and (self.ema[0] <= self.ema[-1] or (self.ema2[0] <= self.ema2[-1])):
                          self.close()
                  
                      if self.position.size < 0 and (self.ema[0] >= self.ema[-1] or (self.ema2[0] >= self.ema2[-1])):
                          self.close()
                  

                  if name == 'main':
                  # Variable for our starting cash
                  startcash = 100000

                  # Create a cerebro entity
                  cerebro = bt.Cerebro()
                  
                  # Add a strategy
                  cerebro.addstrategy(TestStrategy)
                  
                  # Create a Data Feed
                  data = bt.feeds.YahooFinanceData(dataname='AAPL',
                                                   fromdate=datetime(2019, 6, 1),
                                                   todate=datetime(2020, 11, 9),
                                                   buffered=True)
                  
                  # Add the Data Feed to Cerebro
                  cerebro.adddata(data)
                  
                  # Set our desired cash start
                  cerebro.broker.setcash(startcash)
                  
                  # Add a FixedSize sizer according to the stake
                  cerebro.addsizer(bt.sizers.FixedSize, stake=50)
                  
                  # Set the commission
                  cerebro.broker.setcommission(commission=0.0)
                  
                  # Add Analyzers:
                  cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name="mySharpe", riskfreerate=0.001)
                  cerebro.addanalyzer(bt.analyzers.Returns, _name='returns')
                  cerebro.addanalyzer(bt.analyzers.SQN, _name='sqn')
                  
                  # Print out the starting conditions
                  print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
                  
                  # Run over everything
                  cerebro.run()
                  
                  portvalue = cerebro.broker.getvalue()
                  pnl = portvalue - startcash
                  
                  # Print out the final result
                  print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
                  print('Final Portfolio Value: ${}'.format(portvalue))
                  print('P/L: ${}'.format(pnl))
                  
                  # Plot the results
                  cerebro.plot(style='bar', bardown='grey', barup="0.75", volume=False, grid=False)`
                  
                  1 Reply Last reply Reply Quote 0
                  • Dallascat
                    Dallascat last edited by

                    Sorry, I don't know why it didn't markdown the whole code.

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

                      @Dallascat said in Cancelling Bracket order following closing of the main side:

                      self.long_buy_order

                      Yes you have two possible exits from your position. The bracket orders and your custom code:

                      if self.position.size > 0 and (self.ema[0] <= self.ema[-1] or (self.ema2[0] <= self.ema2[-1])):
                              self.close()
                      
                          if self.position.size < 0 and (self.ema[0] >= self.ema[-1] or (self.ema2[0] >= self.ema2[-1])):
                              self.close()
                      

                      I would recommend you change your order lists from self.long_buy_order and self.short_sell_order to self.order which you have already established in init. You may wish to initialize as a list.

                      self.order = []
                      

                      By making these buy/sell lists into one list, you can now cancel out any orders in this list if you close the position in your custom code at the bottom

                      for o in self.order: 
                          self.cancel(o)
                      

                      So it would look like:

                      if self.position.size > 0 and (self.ema[0] <= self.ema[-1] or (self.ema2[0] <= self.ema2[-1])):
                              self.close()
                              for o in self.order: 
                                  self.cancel(o)
                      
                          if self.position.size < 0 and (self.ema[0] >= self.ema[-1] or (self.ema2[0] >= self.ema2[-1])):
                              self.close()
                              for o in self.order: 
                                  self.cancel(o)
                      

                      RunBacktest.com

                      Dallascat 2 Replies Last reply Reply Quote 0
                      • Dallascat
                        Dallascat @run-out last edited by

                        @run-out Awesome thanks! I will make those changes this weekend and get back!

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

                          @run-out I tried to implement your suggestions, I and I know I am doing something wrong with the list. I get an error :

                          "line 110, in next for o in self.order:
                          TypeError: 'NoneType' object is not iterable"

                          Code:

                          from __future__ import (absolute_import, division, print_function,
                                                  unicode_literals)
                          from datetime import datetime
                          import backtrader as bt
                          
                          # Create a Strategy
                          class TestStrategy(bt.Strategy):
                          
                              def log(self, txt, dt=None):
                                  """ Logging function for this strategy"""
                                  dt = dt or self.datas[0].datetime.date(0)
                                  print('%s, %s' % (dt.isoformat(), txt))
                          
                              def __init__(self):
                                  # Keep a reference to the "close" line in the data[0] dataseries
                                  self.bar_executed = len(self)
                                  self.dataclose = self.datas[0].close
                          
                                  # Create an order list
                                  self.o_li = list()
                          
                                  # To keep track of pending orders and buy price/commission
                                  self.order = []
                                  self.buyprice = None
                                  self.buycomm = None
                          
                                  # Add EMAs
                                  self.ema = bt.indicators.ExponentialMovingAverage((self.datas[0].high + self.datas[0].low) / 2, period=50)
                                  self.ema2 = bt.indicators.ExponentialMovingAverage((self.datas[0].high + self.datas[0].low) / 2, period=15)
                                  self.atr = bt.indicators.ATR(period=50, movav=bt.indicators.MovAv.Exponential)
                          
                              def notify_order(self, order):
                                  if order.status in [order.Submitted, order.Accepted]:
                                      # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                                      return
                          
                                  # Check if an order has been completed
                                  # Attention: broker could reject order if not enough cash
                                  if order.status in [order.Completed, order.Canceled, order.Margin]:
                                      if order.isbuy():
                                          self.log(
                                              'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Size %.2f' %
                                              (order.executed.price,
                                               order.executed.value,
                                               order.executed.comm,
                                               order.executed.size))
                          
                                          self.buyprice = order.executed.price
                                          self.buycomm = order.executed.comm
                                      else:  # Sell
                                          self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Size %.2f' %
                                                   (order.executed.price,
                                                    order.executed.value,
                                                    order.executed.comm,
                                                    order.executed.size))
                                      self.bar_executed = len(self)
                          
                                  elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                                      self.log('Order Canceled/Margin/Rejected')
                          
                                  # Clean up the order list.
                                  if not order.alive() and order in self.o_li:
                                      self.o_li.remove(order)
                          
                                  # Write down: no pending order
                                  self.order = None
                          
                              def notify_trade(self, trade):
                                  if not trade.isclosed:
                                      return
                          
                                  self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm))
                          
                              def next(self):
                                  # Check if an order is pending ... if yes, we cannot send a 2nd one
                                  if self.order:
                                      return
                                  # Check if we are in the market
                                  if not self.position:
                          
                                      if self.ema[0] >= self.ema[-1] and (self.ema2[0] >= self.ema2[-1]):
                                          price = self.data.close[0]
                                          price_limit = price + self.atr[0]
                                          price_stop = price - self.atr[0]
                          
                                          self.order = self.buy_bracket(
                                              data=self.datas[0],
                                              size=None,
                                              exectype=bt.Order.Limit,
                                              plimit=price,
                                              stopprice=price_stop,
                                              stopexec=bt.Order.Stop,
                                              limitprice=price_limit,
                                              limitexec=bt.Order.Limit,
                                          )
                          
                                      if self.ema[0] <= self.ema[-1] and (self.ema2[0] <= self.ema2[-1]):
                                          price = self.data.close[0]
                                          price_limit = price - self.atr[0]
                                          price_stop = price + self.atr[0]
                          
                                          self.order = self.sell_bracket(
                                              data=self.datas[0],
                                              size=None,
                                              exectype=bt.Order.Limit,
                                              plimit=price,
                                              stopprice=price_stop,
                                              stopexec=bt.Order.Stop,
                                              limitprice=price_limit,
                                              limitexec=bt.Order.Limit,
                                          )
                          
                                  if self.position.size > 0 and (self.ema[0] <= self.ema[-1] or (self.ema2[0] <= self.ema2[-1])):
                                      self.close()
                                      for o in self.order:
                                          self.cancel(o)
                          
                                  if self.position.size < 0 and (self.ema[0] >= self.ema[-1] or (self.ema2[0] >= self.ema2[-1])):
                                      self.close()
                                      for o in self.order:
                                          self.cancel(o)
                          
                          
                          if __name__ == '__main__':
                              # Variable for our starting cash
                              startcash = 100000
                          
                              # Create a cerebro entity
                              cerebro = bt.Cerebro()
                          
                              # Add a strategy
                              cerebro.addstrategy(TestStrategy)
                          
                              # Create a Data Feed
                              data = bt.feeds.YahooFinanceData(dataname='AAPL',
                                                               fromdate=datetime(2019, 6, 1),
                                                               todate=datetime(2020, 11, 9),
                                                               buffered=True)
                          
                              # Add the Data Feed to Cerebro
                              cerebro.adddata(data)
                          
                              # Set our desired cash start
                              cerebro.broker.setcash(startcash)
                          
                              # Add a FixedSize sizer according to the stake
                              cerebro.addsizer(bt.sizers.FixedSize, stake=50)
                          
                              # Set the commission
                              cerebro.broker.setcommission(commission=0.0)
                          
                              # Add Analyzers:
                              cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name="mySharpe", riskfreerate=0.001)
                              cerebro.addanalyzer(bt.analyzers.Returns, _name='returns')
                              cerebro.addanalyzer(bt.analyzers.SQN, _name='sqn')
                          
                              # Print out the starting conditions
                              print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
                          
                              # Run over everything
                              cerebro.run()
                          
                              portvalue = cerebro.broker.getvalue()
                              pnl = portvalue - startcash
                          
                              # Print out the final result
                              print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
                              print('Final Portfolio Value: ${}'.format(portvalue))
                              print('P/L: ${}'.format(pnl))
                          
                              # Plot the results
                              cerebro.plot(style='bar', bardown='grey', barup="0.75", volume=False, grid=False)
                          
                          run-out 1 Reply Last reply Reply Quote 0
                          • run-out
                            run-out @Dallascat last edited by

                            @Dallascat said in Cancelling Bracket order following closing of the main side:

                            for o in self.order:
                            self.cancel(o)

                            Just debug in here. The list self.order contains None and this is throwing an error.

                            RunBacktest.com

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

                              @run-out Thanks so much for your guidance! I'm still racking my brain against the well....is the error in

                              # To keep track of pending orders and buy price/commission
                                      self.order = []
                                      self.buyprice = None
                                      self.buycomm = None
                              

                              or

                              # Clean up the order list.
                                      if not order.alive() and order in self.o_li:
                                          self.o_li.remove(order)
                              
                                      # Write down: no pending order
                                      self.order = None
                              

                              or none of the above . LOL! Thanks again!!

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

                                @Dallascat This is getting too fragmented for me. Could you put the entire code in one block for me? I will then copy it to my ide and look at it.

                                Also, right after that, put in the latest error code you are getting.

                                Thanks.

                                RunBacktest.com

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

                                  @run-out Sure, I did get rid of the error, but not sure if I am doing the list right or not (I assume NOT, lol) because it runs, but only triggers two trades at the beginning then nothing. Thanks Again

                                  import backtrader as bt
                                  from datetime import datetime
                                  
                                  
                                  class Strategy(bt.Strategy):
                                  
                                      def log(self, txt, dt=None):
                                          """ Logging function fot this strategy"""
                                          dt = dt or self.data.datetime[0]
                                          if isinstance(dt, float):
                                              dt = bt.num2date(dt)
                                          print("%s, %s" % (dt.date(), txt))
                                  
                                      def __init__(self):
                                          # Keep a reference to the "close" line in the data[0] dataseries
                                          self.bar_executed = len(self)
                                          self.dataclose = self.datas[0].close
                                  
                                          # Create an order list
                                          self.o_li = list()
                                  
                                          # To keep track of pending orders and buy price/commission
                                          self.order = []
                                          self.buyprice = None
                                          self.buycomm = None
                                  
                                          # Add EMA and TRIX
                                          self.ema = bt.indicators.ExponentialMovingAverage((self.datas[0].high + self.datas[0].low) / 2, period=100,
                                                                                            plotname="EMAMid")
                                          self.trix = bt.indicators.TRIX(self.datas[0], period=5, plot=True)
                                          self.atr = bt.indicators.ATR(period=100, movav=bt.indicators.MovAv.Exponential)
                                  
                                      def notify_order(self, order):
                                          if order.status in [order.Submitted, order.Accepted]:
                                              # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                                              return
                                  
                                          # Check if an order has been completed
                                          # Attention: broker could reject order if not enough cash
                                          if order.status in [order.Canceled, order.Margin]:
                                              if order.isbuy():
                                                  self.log("BUY FAILED, Cancelled or Margin")
                                              self.log
                                          if order.status in [order.Completed, order.Canceled, order.Margin]:
                                              if order.isbuy():
                                                  self.log(
                                                      "BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f"
                                                      % (order.executed.price, order.executed.value, order.executed.comm)
                                                  )
                                  
                                                  self.buyprice = order.executed.price
                                                  self.buycomm = order.executed.comm
                                              else:  # Sell
                                                  self.log(
                                                      "SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f"
                                                      % (order.executed.price, order.executed.value, order.executed.comm)
                                                  )
                                  
                                              self.bar_executed = len(self)
                                  
                                          # Cleans up the order list.
                                          if not order.alive() and order in self.o_li:
                                              self.o_li.remove(order)
                                  
                                      def notify_trade(self, trade):
                                          if not trade.isclosed:
                                              return
                                  
                                          self.log("OPERATION PROFIT, GROSS %.2f, NET %.2f" % (trade.pnl, trade.pnlcomm))
                                  
                                      def next(self):
                                          # Simply log the closing price of the series from the reference
                                          global price, price_limit, price_stop
                                          self.log('ATR: %.2f' % (self.atr[0]))
                                  
                                          if self.position.size == 0 and len(self.o_li) == 0:
                                              if self.ema[0] >= self.ema[-1] and (self.trix[0] >= self.trix[-1]):
                                                  price = self.data.close[0]
                                                  price_limit = price + self.atr[0]
                                                  price_stop = price - self.atr[0]
                                  
                                                  self.order = self.buy_bracket(
                                                      data=self.datas[0],
                                                      size=None,
                                                      exectype=bt.Order.Limit,
                                                      plimit=price,
                                                      stopprice=price_stop,
                                                      stopexec=bt.Order.Stop,
                                                      limitprice=price_limit,
                                                      limitexec=bt.Order.Limit,
                                                  )
                                  
                                          if self.position.size == 0 and len(self.o_li) == 0:
                                              if self.ema[0] <= self.ema[-1] and (self.trix[0] <= self.trix[-1]):
                                                  price = self.data.close[0]
                                                  price_limit = price - self.atr[0]
                                                  price_stop = price + self.atr[0]
                                  
                                                  self.order = self.sell_bracket(
                                                      data=self.datas[0],
                                                      size=None,
                                                      exectype=bt.Order.Limit,
                                                      plimit=price,
                                                      stopprice=price_stop,
                                                      stopexec=bt.Order.Stop,
                                                      limitprice=price_limit,
                                                      limitexec=bt.Order.Limit,
                                                  )
                                  
                                              # Store orders in a list
                                              self.o_li = [o for o in self.order]
                                  
                                              self.log(
                                                  "LONG BUY limit Targets: Buy {:8.2f}, Target {:8.2f}, Stop {:8.2f}".format(
                                                      price, price_limit, price_stop
                                                  )
                                              )
                                  
                                          if self.position.size > 0:
                                              if self.ema[0] <= self.ema[-1] or (self.trix[0] <= self.trix[-1]):
                                                  print("Sell shares at {}".format(self.data.close[0]))
                                                  self.close()
                                                  self.o_li = list()
                                  
                                          if self.position.size < 0:
                                              if self.ema[0] >= self.ema[-1] or (self.trix[0] >= self.trix[-1]):
                                                  print("Sell shares at {}".format(self.data.close[0]))
                                                  self.close()
                                                  self.o_li = list()
                                  
                                  
                                  if __name__ == '__main__':
                                      # Variable for our starting cash
                                      startcash = 100000
                                  
                                      # Create a cerebro entity
                                      cerebro = bt.Cerebro()
                                  
                                      # Add a strategy
                                      cerebro.addstrategy(Strategy)
                                  
                                      # Create a Data Feed
                                      data = bt.feeds.YahooFinanceData(dataname='AAPL',
                                                                       fromdate=datetime(2019, 6, 1),
                                                                       todate=datetime(2020, 11, 9),
                                                                       buffered=True)
                                  
                                      # Add the Data Feed to Cerebro
                                      cerebro.adddata(data)
                                  
                                      # Set our desired cash start
                                      cerebro.broker.setcash(startcash)
                                  
                                      # Add a FixedSize sizer according to the stake
                                      cerebro.addsizer(bt.sizers.FixedSize, stake=50)
                                  
                                      # Set the commission
                                      cerebro.broker.setcommission(commission=0.0)
                                  
                                      # Add Analyzers:
                                      cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name="mySharpe", riskfreerate=0.001)
                                      cerebro.addanalyzer(bt.analyzers.Returns, _name='returns')
                                      cerebro.addanalyzer(bt.analyzers.SQN, _name='sqn')
                                  
                                      # Print out the starting conditions
                                      print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
                                  
                                      # Run over everything
                                      cerebro.run()
                                  
                                      portvalue = cerebro.broker.getvalue()
                                      pnl = portvalue - startcash
                                  
                                      # Print out the final result
                                      print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
                                      print('Final Portfolio Value: ${}'.format(portvalue))
                                      print('P/L: ${}'.format(pnl))
                                  
                                      # Plot the results
                                      cerebro.plot(style='bar', bardown='grey', barup="0.75", volume=False, grid=False)
                                  
                                  1 Reply Last reply Reply Quote 0
                                  • Dallascat
                                    Dallascat last edited by

                                    @run-out If not too busy, have you had a chance to look at my code? TY!

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

                                      @run-out said in Cancelling Bracket order following closing of the main side:

                                      Normally when using a list or dictionary to track orders, if you remove the orders from the list at the right spots, there should be no issues with the list.

                                      However, I tend to get a bit cautious (lazy?) and insert a clause at the beginning of next() that checks if:

                                      • Are there any open positions, and...

                                      • Are there any live orders.

                                      If there are no open positions and no live orders, really the list should be empty. The code looks something like:

                                      def next(self):
                                          if self.position.size == 0 and len([o for o in self.o_li if o.status < 4]) == 0:
                                              self.o_li = list()
                                      

                                      Order status of 4 is completed, and higher are all dead orders.

                                      Then another thing I notice in your code is that you have bracket orders with purchase price which is fine. But if the stock trends permanantly away from your purchase price, you will be left with a set of orders that will never fill, blocking future intended orders, since there are open orders.

                                      Since in your bracket orders you entering the market at last close, probably best to leave exectype as Market and no plimit, or alternatively insert a valid period so the bracket expires after so many bars.

                                      RunBacktest.com

                                      1 Reply Last reply Reply Quote 1
                                      • 1 / 1
                                      • First post
                                        Last post
                                      Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors