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/

    Notify_trade: trade.size is zero at trade closed

    Indicators/Strategies/Analyzers
    3
    11
    1716
    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.
    • J
      Julianus last edited by Julianus

      Hey All,

      I've added a new sizer to enable partial contracts to buy based on cash available (crypto space). Algo seems to work fine except that at closed trades the trade.size is printed as zero.
      Any thoughts on the reason of this behaviour?
      How could I easily get the given trade's quantity, price data?

      Thanks a lot

      here're the main elements:

      class maxRiskSizer(bt.Sizer):
          params = (('risk', 1),)
       
          def __init__(self):
              if self.p.risk > 1 or self.p.risk < 0:
                  raise ValueError('Risk parameter is not ok!')
       
          def _getsizing(self, comminfo, cash, data, isbuy):
              if isbuy == True:
                  size = (cash * self.p.risk) / data[0]
              else:
                  size = ((cash * self.p.risk) / data[0]) * -1
              return size
      
      class SmaCross(bt.Strategy):
      ...
              def notify_trade(self, trade):
                  if trade.justopened:
                      print('----TRADE OPENED----')
                      print('Size: {:.3f}, value: {:.3f}'.format(trade.size, trade.value))
                  elif trade.isclosed:
                      print('----TRADE CLOSED----')
                      print('Profit: {} Gross {}, Net {}'.format(trade.size, round(trade.pnl,2), round(trade.pnlcomm,2)))
                  else:
                      return
      

      This gives the following output:

      ----TRADE OPENED----
      Size: 0.670, value: 9997.320
      ----TRADE CLOSED----
      Profit: 0.0 Gross 361.16, Net 361.16
      ----TRADE OPENED----
      Size: 0.728, value: 10361.163
      ----TRADE CLOSED----
      Profit: 0.0 Gross -802.0, Net -802.0
      ----TRADE OPENED----
      Size: 0.688, value: 9557.100
      ...
      
      1 Reply Last reply Reply Quote 0
      • A
        ab_trader last edited by

        Seems logical: trade already closed, all sold or covered, now size is equal zero. Why it should be different?

        If you want to keep size of the trade after it is closed, then keep size from trade.open event. If you are changing trade size, then work with the appropriate orders data - Orders. Or track position size during trading - Position.

        B J 3 Replies Last reply Reply Quote 1
        • B
          backtrader administrators @ab_trader last edited by

          @julianus said in Notify_trade: trade.size is zero at trade closed:

          Any thoughts on the reason of this behaviour?

          @ab_trader said in Notify_trade: trade.size is zero at trade closed:

          If you are changing trade size

          The answer by @ab_trader is already pointing out the reason: the size of a trade can change. It would seem that you think a trade is made up solely of a single order, but a Trade can have many different sizes from its birth until it dies.

          See this simple example:

          • You open a long trade with size 10
          • You sell to reduce the size to 5
          • You buy to increase size to 25
          • You sell to close the trade (size is 0) and you actually sell so much with a single order, that you actually open a 2nd (new) trade with size -5

          See Docs - Trade

          1 Reply Last reply Reply Quote 1
          • J
            Julianus @ab_trader last edited by Julianus

            @ab_trader, @backtrader thanks.
            What's strange is that other trade subclasses (trade.pnl, trade.pnlcomm) give the correct figure, while trade.value did not at the same call. Or these are handled differently by bt?

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

              In your code different outputs are called for tradejust.opened state and trade.isclosed state. So it is impossible to compare outputs for trade.value, trade.pnl and trade.pnlcomm for different trade states. Not sure how you did it, probably used another code. Only trade.size appeared in both states, but it is named as Profit (why?) second time.

              I am more than sure that bt returns correct figures every time, but it is difficult to check correctly due to some inconsistency in the code.

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

                @julianus said in Notify_trade: trade.size is zero at trade closed:

                while trade.value did not at the same call

                What is wrong with trade.value? You print it once and it shows the value. What are you expecting?

                You a printing "Profit: {}" and using trade.size for it. That's for sure giving the wrong idea when one is reading the output.

                @julianus said in Notify_trade: trade.size is zero at trade closed:

                What's strange is that other trade subclasses (trade.pnl, trade.pnlcomm)

                Those are NOT subclasses. They are attributes (call them values if you wish)

                J 1 Reply Last reply Reply Quote 0
                • J
                  Julianus @backtrader last edited by Julianus

                  @backtrader, @ab_trader, thanks for the prompt answer.
                  I've cleaned the code a little, unfortunately zero still appears ('Profit' stuck there incorrectly during my tries, should've been switched like below).

                  Full code:

                  from collections import OrderedDict
                  
                  class maxRiskSizer(bt.Sizer):
                      params = (('risk', 1),)
                   
                      def __init__(self):
                          if self.p.risk > 1 or self.p.risk < 0:
                              raise ValueError('Risk parameter is not ok!')
                   
                      def _getsizing(self, comminfo, cash, data, isbuy):
                          if isbuy == True:
                              size = (cash * self.p.risk) / data[0]
                          else:
                              size = ((cash * self.p.risk) / data[0]) * -1
                          return size
                  
                  class SmaCross(bt.Strategy):
                          params = (
                              ('pfast', 15),
                              ('pslow', 100),
                              ('printlog', False),
                          )
                      
                          def log(self, txt, dt=None):
                              ''' Logging function fot this strategy'''
                              dt = dt or self.datas[0].datetime.datetime(0)
                              print('%s, %s' % (dt.isoformat(), txt))
                  
                          def __init__(self):
                              self.dataclose = self.datas[0].close
                              
                              self.order = None
                              self.buyprice = None
                              self.buycomm = None
                              
                              self.sma1 = bt.ind.SimpleMovingAverage(self.data.close, period=self.params.pfast)
                              self.sma2 = bt.ind.SimpleMovingAverage(self.data.close, period=self.params.pslow)
                              self.Cross = bt.ind.CrossOver(self.sma1, self.sma2)
                          
                          def next(self):
                              if self.order:
                                  return
                              
                              if not self.position:
                                  if self.Cross and pd.notna(self.sma1[0] and self.sma2[0]):
                                      self.buy()
                                      
                              else:
                                  if self.Cross == -1:
                                      self.close()
                                      
                          def notify_trade(self, trade):
                              if trade.justopened:
                                  print('----TRADE OPENED----')
                                  print('Size: {:.3f}, value: {:.3f}'.format(trade.size, trade.value))
                              elif trade.isclosed:
                                  print('----TRADE CLOSED----')
                                  print('Size: {:.3f} Profit: Gross {:.3f}, Net {:.3f}'.format(trade.size, trade.pnl, trade.pnlcomm))
                              else:
                                  return
                              
                  
                  if __name__ == '__main__':
                      
                      startcash = 10000
                      
                      cerebro = bt.Cerebro()
                      
                      cerebro.addstrategy(SmaCross)
                  
                      modpath = os.path.dirname('D:\\_projectPy\\')
                      datapath = os.path.join(modpath, 'test4.csv')
                  
                      data = bt.feeds.GenericCSVData(
                          dataname=datapath,
                          timeframe=bt.TimeFrame.Minutes, compression=60,
                          datetime=0,
                          open = 1,
                          high = 3,
                          low = 4,
                          close = 2,
                          volume = 5,
                          openinterest = -1,
                          fromdate = datetime(2018, 1, 1, 1, 0, 1),
                          todate = datetime(2018, 1, 20, 0, 0, 1),
                          separator=',',
                          dtformat=('%Y-%m-%d %H:%M:%S')
                          )
                  
                      cerebro.adddata(data)
                      
                      cerebro.broker.setcash(startcash)
                      
                      cerebro.addsizer(maxRiskSizer, risk=1)
                      
                      strategies = cerebro.run(maxcpus=1)
                  

                  Output:

                  ----TRADE OPENED----
                  Size: 0.670, value: 9997.320
                  ----TRADE CLOSED----
                  Size: 0.000 Profit: Gross 361.163, Net 361.163
                  ----TRADE OPENED----
                  Size: 0.728, value: 10361.163
                  ----TRADE CLOSED----
                  Size: 0.000 Profit: Gross -801.999, Net -801.999
                  ----TRADE OPENED----
                  Size: 0.688, value: 9557.100
                  ----TRADE CLOSED----
                  Size: 0.000 Profit: Gross -496.562, Net -496.562
                  
                  B 1 Reply Last reply Reply Quote 0
                  • B
                    backtrader administrators @Julianus last edited by

                    @julianus said in Notify_trade: trade.size is zero at trade closed:

                    unfortunately zero still appears

                    And it will always appear. As stated above by @ab_trader and myself: when the trade is closed, it is closed because the size is 0.

                    You may want to re-elaborate what your problem actually is and what you are missing, because right not it is unclear.

                    J 1 Reply Last reply Reply Quote 0
                    • J
                      Julianus @backtrader last edited by

                      @backtrader, ok thanks understood.
                      I asked this one as the second question in my initial post:
                      "How could I easily get the given trade's quantity, price data?"

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

                        @ab_trader said in Notify_trade: trade.size is zero at trade closed:

                        If you want to keep size of the trade after it is closed, then keep size from trade.open event. If you are changing trade size, then work with the appropriate orders data - Orders. Or track position size during trading - Position.

                        J 1 Reply Last reply Reply Quote 0
                        • J
                          Julianus @backtrader last edited by Julianus

                          @backtrader, ok.

                          I'm going to deep-dive in the platform once again from the beginning, so then hopefully those questions/topics will be clearer.

                          Don't you consider having a discord channel for very interactive chats?

                          Thanks anyway.

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