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/

    Orders not executed after a certain time period

    General Code/Help
    3
    8
    68
    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.
    • zachlim98
      zachlim98 last edited by

      I'm not sure what the bug is but when I change the length of the data being backtested, the orders stop being executed after a while. Here's what I mean:

      2012 - 2020:
      ab262de3-1cf2-45b7-b4a8-6e5510906c75-image.png

      2019 - 2020:
      f5e50edc-8b57-4f08-8023-16c1d1f6dc4c-image.png

      I don't get why the orders clump up like that for the 2012 - 2020 backtest and don't have any many orders for 2019 (when there are when we limit the backtest period to 2019).

      Code as follows:

      Strategy:

      class RSIStrat(bt.Strategy):
          
          def __init__(self):
              self.dataclose= self.datas[0].close    # Keep a reference to the "close" line in the data[0] dataseries
              self.rsi= bt.indicators.RelativeStrengthIndex()
              self.stoch = bt.indicators.Stochastic()
              self.ATR= bt.indicators.AverageTrueRange(period=7)
              self.MAC = bt.indicators.MACDHisto()
              self.order = None # Property to keep track of pending orders.  There are no orders when the strategy is initialized.
              self.buyprice = None
              self.buycomm = None
          
          def log(self, txt, dt=None):
              # Logging function for the strategy.  'txt' is the statement and 'dt' can be used to specify a specific datetime
              dt = dt or self.datas[0].datetime.date(0)
              print('{0},{1}'.format(dt.isoformat(),txt))
          
          def notify_order(self, order):
              # 1. If order is submitted/accepted, do nothing 
              if order.status in [order.Submitted, order.Accepted]:
                  return
              # 2. If order is buy/sell executed, report price executed
              if order.status in [order.Completed]: 
                  if order.isbuy():
                      self.log('BUY EXECUTED, Price: {0:8.2f}, Cost: {1:8.2f}, Comm: {2:8.2f}'.format(
                          order.executed.price,
                          order.executed.value,
                          order.executed.comm))
                      
                      self.buyprice = order.executed.price
                      self.buycomm = order.executed.comm
                  else:
                      self.log('SELL EXECUTED, {0:8.2f}, Cost: {1:8.2f}, Comm{2:8.2f}'.format(
                          order.executed.price, 
                          order.executed.value,
                          order.executed.comm))
                  
                  self.bar_executed = len(self) #when was trade executed
              # 3. If order is canceled/margin/rejected, report order canceled
              elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                  self.log('Order Canceled/Margin/Rejected')
                  
              self.order = None
          
          def notify_trade(self,trade):
              if not trade.isclosed:
                  return
              
              self.log('OPERATION PROFIT, GROSS {0:8.2f}, NET {1:8.2f}'.format(
                  trade.pnl, trade.pnlcomm))
          
          def next(self):
              # Log the closing prices of the series from the reference
              # self.log('Close, {0:8.2f}'.format(self.dataclose[0]))
      
              if self.order: # check if order is pending, if so, then break out
                  return
                      
              # since there is no order pending, are we in the market?    
              if not self.position: # not in the market
                  if (self.rsi < 50) and (self.MAC < 0) and (self.stoch < 50):
                      price = self.dataclose[0]
                      price_limit = price - (2.8*self.ATR)
                      price_stop = price + (1.2*self.ATR)
                      atr_price = self.ATR[0]
      
                      self.order = self.sell_bracket(
                          size=100,
                          price=price,
                          stopprice=price_stop,
                          limitprice=price_limit,
                      )
                      self.log('SHORT AT: {:8.2f}, Limit: {:8.2f}, Stop: {:8.2f}, ATR: {}'.format(price,price_limit,price_stop,atr_price))
      
                  elif (self.rsi > 50) and (self.stoch.k > 50) and (self.MAC > 0):
                      price = self.dataclose[0]
                      price_limit = price + (2.8*self.ATR)
                      price_stop = price - (1.2*self.ATR)
                      atr_price = self.ATR[0]
      
                      self.order = self.buy_bracket(
                          size=100,
                          price=price,
                          stopprice=price_stop,
                          limitprice=price_limit,
                      )
                      self.log('BUY AT: {:8.2f}, Limit: {:8.2f}, Stop: {:8.2f}, ATR: {}'.format(price,price_limit,price_stop,atr_price))
      

      Cerebro:

      if __name__ == '__main__':
          cerebro = bt.Cerebro()
          cerebro.addstrategy(RSIStrat)
          cerebro.broker.setcash(100000.0)
          cerebro.broker.setcommission(commission=0.001)
      
          data = bt.feeds.YahooFinanceData(dataname='AMD',
                                           fromdate=datetime(2012, 1, 1),
                                           todate=datetime(2020, 1, 1))
          cerebro.adddata(data) 
          print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
          cerebro.run()
          print('Ending Portfolio Value: %.2f' % cerebro.broker.getvalue())
          cerebro.plot()
      

      Would appreciate any help. Thanks!

      J run-out 2 Replies Last reply Reply Quote 0
      • J
        Jonny8 @zachlim98 last edited by

        @zachlim98
        Hi,

        can you post a log?

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

          Are your buy and sell brackets reversed?

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

            @run-out Hi! Thanks for your reply. I've tried both ways though, putting the buy bracket first and then the sell bracket and results are unfortunately still the same. It's so strange because it clearly works on shorter backtest periods.

            1 Reply Last reply Reply Quote 0
            • zachlim98
              zachlim98 @Jonny8 last edited by

              @Jonny8 Hi! Thanks for your reply. Sure, will post one later but it's basically what you see in the plot. Just two clusters of orders around those periods for the 2012 - 2020 backtest period

              1 Reply Last reply Reply Quote 0
              • zachlim98
                zachlim98 @Jonny8 last edited by

                @Jonny8 Hey there! I have the log and I think I see the problem. It appears that there is a long gap (between 2012 and 2016) where my order is ordered but not executed

                2012-05-29,OPERATION PROFIT, GROSS   -26.82, NET   -28.07
                2012-05-29,SHORT AT:     6.46, Limit:     5.74, Stop:     6.77
                2016-07-25,SELL EXECUTED,     6.46, Cost:  -646.00, Comm    0.65
                2016-07-26,BUY EXECUTED, Price:     6.77, Cost:  -646.00, Comm:     0.68
                

                Why do you think that could be the case?

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

                  @zachlim98 said in Orders not executed after a certain time period:

                  price = self.dataclose[0]

                  You could be setting an order for the price and the price moves away from it, never filling. You should use valid to cancel the order if it is not filled within n bars.

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

                    @run-out Ah I see! Thanks so much for your help. Yes, I changed it to a marker order instead of a limit order and it ran well.

                    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(); }); }