Backtrader Community

    • 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/

    Multiple trades Long/Short Support?

    General Code/Help
    5
    2
    246
    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.
    • Nael Shichida
      Nael Shichida last edited by

      Hey everyone

      Newly enlisted backtrader here, I have been looking at youtube tutorials and the documentation. A lot of the examples cover 1 position at a time such as SMA crossover.

      However I am trying to have multiple buy orders using 1R/R of my portfolio for each trade, regardless of whether I am in a trade or not I want each one to be individually dealt with. The logic for entering long trades is working, however I am using a buy bracket since I need a log to see if the order is executed and if it has been executed, to set a close long either at target or stop price.

      If anyone can help guide me, would be extremely grateful as to how I should formulate the logic in Python?

      class TestStrategy(bt.Strategy):

      def log(self, txt, dt=None):
          ''' Logging function fot 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.order = None
          self.dataclose = self.datas[0].close
          self.dataopen = self.datas[0].open
          self.zone = self.datas[0].close - self.datas[0].open
      
      
      def next(self):
          # Simply log the closing price of the series from the reference
          self.log('Close, %.2f' % self.dataclose[0])
          self.log('Open, %.2f' % self.dataopen[0])
          self.log('Zone, %.2f' % self.zone[0])
          self.log('shift, %.2f' % self.zone[-1])
      
          print(len(self))
          print(self.order)
          print(self.position)
          #
          """Enters Long position if below conditions are met"""
          if self.zone[0] < 0:
              print("Bar is red")
              # current close less than previous close
      
              if self.zone[1] > 0:
                  print("Next candle is green")
                  # Next close less than the previous close
                  if 1.5*abs(self.zone[0]) < abs(self.zone[1]):
                      print("Buy Zone found")
      
                      # BUY, BUY, BUY!!! (with all possible default parameters)
                      self.log('BUY CREATE, %.2f' % self.dataclose[0])
                      # self.buy()
      
                      self.order = self.buy_bracket(limitprice=self.dataopen[0], price=self.dataopen[0],
                                                    stopprice=self.dataclose[0])
                      # print(self.order)
                      print(type(self.order.ref))
      
      1 Reply Last reply Reply Quote 0
      • Pierre Cilliers 0
        Pierre Cilliers 0 last edited by

        Hi @Nael-Shichida

        I would suggest you replace you self.order parameter with a dictionary perhaps. ALSO, you can add a paramter tradeid in the buy_bracket method.

        Consider, for example:

        def log(self, txt, dt=None):
            ''' Logging function fot 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.order = {}
            self.id = 0
            self.dataclose = self.datas[0].close
            self.dataopen = self.datas[0].open
            self.zone = self.datas[0].close - self.datas[0].open
        
        
        def next(self):
            # Simply log the closing price of the series from the reference
            self.log('Close, %.2f' % self.dataclose[0])
            self.log('Open, %.2f' % self.dataopen[0])
            self.log('Zone, %.2f' % self.zone[0])
            self.log('shift, %.2f' % self.zone[-1])
        
            print(len(self))
            print(self.order)
            print(self.position)
            #
            """Enters Long position if below conditions are met"""
            if self.zone[0] < 0:
                print("Bar is red")
                # current close less than previous close
        
                if self.zone[1] > 0:
                    print("Next candle is green")
                    # Next close less than the previous close
                    if 1.5*abs(self.zone[0]) < abs(self.zone[1]):
                        print("Buy Zone found")
        
                        # BUY, BUY, BUY!!! (with all possible default parameters)
                        self.log('BUY CREATE, %.2f' % self.dataclose[0])
                        # self.buy()
        
                        self.order[self.id] = self.buy_bracket(tradeid = self.id,
                                                                                       limitprice=self.dataopen[0],
                                                                                       price=self.dataopen[0], 
                                                                                       stopprice=self.dataclose[0])
                        # print(self.order)
                        print(type(self.order.ref))
        
                        self.id += 1 # this is a simple way, but you can therefore have an id to identify each individual trade
        

        This specific method might not solve your question as you might loose track of what self.id fits with which order. I do feel, however, that this is a starting point for you to have a dictionary of all your submitted order.

        POSSIBLE SOLUTION: I have quite a different way to do it (might get a bit lost now, but putting it here for incase it helps).

        I have a custom order tracking dictionary from which I track all my OPEN ORDERS (orders (buylimits, selllimits, etc.) and trades (long, short, etc.)). At times, my strategy has up to 14 trades open and this works 100%.
        This is a snippet of my self.open_orders tracking when making a BUY trade (opening a long position). My strategy logic, therefore ALWAYS looks at what trades are currently open, what orders are pending, and makes logical decisions on that

        # backtrader built-in action
                        self.buy_bracket(tradeid = self.id,
                                        exectype = bt.Order.Market,
                                        price = close,
                                        size = 0.1, 
                                        limitprice = self.tp,
                                        stopprice = self.sl)
                        # self custom order tracking
                        self.open_orders[self.id] = {'symbol' : 'EURUSD',
                                                 'lots' : 0.1,
                                                 'type' : 'buy',
                                                 'open_price' : close,
                                                 'open_time' : self.datetime.time(ago=0).isoformat(),
                                                 'SL' : self.sl,
                                                 'TP' : self.tp,
                                                 'pnl' : 0.0,
                                                 'commission' : 0.01
                                                 'swap' : 0.0,
                                                 'comment' : ''}
        

        Note, as I can always view self.open_orders, I know exactly which trade I can identify when I need to make any action on it. For example, if I need to close the trade, I can say self.close(tradeid=self.id) and it will close the position and calculate my PnL.

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