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/

    get_leverage() calls

    General Code/Help
    2
    5
    1264
    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.
    • T
      ThatBlokeDave last edited by

      Hello,
      Just wondering what logic is for the following get_leverage call:

      self.broker.get_leverage()

      To get the actual allowed leverage, I understand that the documentation states I should use self.broker.getcommissioninfo(self.data).get_leverage() and it will return the maximum allowed leverage from the commission scheme used on the data provided.

      https://www.backtrader.com/docu/commission-schemes/commission-schemes.html#backtrader.CommissionInfo.get_leverage

      However, self.broker.get_leverage() appears to be doing a different calculation and I would just like to verify what it should be doing. I did not see this call listed in the broker reference. This makes me wonder whether it is officially supported or perhaps documented elsewhere?

      https://www.backtrader.com/docu/broker.html

      Below is some output from the terminal during each next() call when I am in a position. I am setup to use 50:1 leverage and trading EUR/USD on a daily timeframe.

      broker.get_leverage:               145.19184069936887
      getcomissioninfo.get_leverage:     50
      broker.get_leverage:               178.6195034400227
      getcomissioninfo.get_leverage:     50
      broker.get_leverage:               474.8882681564292
      getcomissioninfo.get_leverage:     50
      broker.get_leverage:               327.1642405932362
      getcomissioninfo.get_leverage:     50
      broker.get_leverage:               208.94326737873922
      getcomissioninfo.get_leverage:     50
      broker.get_leverage:               157.34070563454415
      getcomissioninfo.get_leverage:     50
      broker.get_leverage:               132.42585214696592
      getcomissioninfo.get_leverage:     50
      

      and the next() call:

          def next(self):
              bar = len(self.data)
              #print(bar)
              com = self.broker.getcommissioninfo(self.data).get_leverage()
              print('broker.get_leverage:               {}'.format(self.broker.get_leverage()))
              print('getcomissioninfo.get_leverage:     {}'.format(com))
      

      Note: This is not blocking anything for me, I am just curious and would like a better understanding. No rush to reply.

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

        @ThatBlokeDave said in get_leverage() calls:

        To get the actual allowed leverage, I understand that the documentation states I should use self.broker.getcommissioninfo(self.data).get_leverage() and it will return the maximum allowed leverage from the commission scheme used on the data provided.

        A pointer to the part in the docs that state the that you should use self.broker.getcommissioninfo(self.data).get_leverage() would be welcome. Because it shouldn't be so. The method is meant for usage inside the broker. Unless you subclass the scheme, that method will return whatever you have used during instantiation.

        @ThatBlokeDave said in get_leverage() calls:

        However, self.broker.get_leverage() appears to be doing a different calculation

        It's not a different calculation. It's different altogether. Invoking that method, which is intended for user consumption unlike the one above, reports the actual leverage level in the market.

        Seeing the output some initial thoughts:

        • There is a bug in the calculation
        • You are using a multiplier

        But with just the printouts and no background it's difficult to make any kind of diagnosis.

        1 Reply Last reply Reply Quote 0
        • T
          ThatBlokeDave last edited by

          A pointer to the part in the docs that state the that you should use self.broker.getcommissioninfo(self.data).get_leverage() would be welcome.

          I did provide a pointer... Possibly the docs have been misinterpreted. Simply I wanted to get the leverage used within a strategy and found the line:

          Returns the level of leverage allowed for this comission scheme

          This seemed perfect for my needs and returns the value I wanted.

          I am not setting any multiplier. This is actually linked to my question about Margin close outs the other day. I am trying to see if I can implement it in the strategy.

          It is a work in progress but I will post it below.... I still need to come up with a good way of accounting for applying the correct margin when the base account is not the same as the currency in which the instrument is denominated in. I.e I need to account for a currency exchange.

          import backtrader as bt
          from datetime import datetime
          
          
          class MarginCO(bt.Strategy):
              '''
              This strategy contains some additional methods that can be used to calcuate
              whether a position should be subject to a margin close out from Oanda.
              '''
              def check_mco(self, value, margin_used):
                  '''
                  Make a check to see if the margin close out value has fallen below half
                  of the margin used, close the position.
          
                  value: value of the portfolio for a given data. This is essentially the
                  same as the margin close out value which is balance + pnl
                  margin_used: Initial margin
                  '''
          
                  if value < (margin_used /2):
                      close = self.close()
                      close.addinfo(name='MCO')
                  else:
                      return
          
              def notify_order(self,order):
          
                  if order.status == order.Completed:
                      ep = order.executed.price
                      es = order.executed.size
                      tv = ep * es
                      leverage = self.broker.getcommissioninfo(self.data).get_leverage()
                      self.margin = (ep * es) / leverage
                      if 'name' in order.info:
                          if order.info['name'] == 'Entry':
                              print('{}: Entry Order Completed '.format(self.dt))
                              print('{}: Order Executed Price: {}, Executed Size {}'.format(self.dt,ep,es,))
                              print('{}: Position Value: {} Margin Used: {}'.format(self.dt,tv,self.margin))
                          elif order.info['name'] == 'MCO':
                              print('{}: WARNING: Margin Close Out'.format(self.dt))
                          else:
                              print('{}: Close Order Completed'.format(self.dt))
          
          
          class Mltests(MarginCO):
              params = (('size', 10000),)
          
              def __init__(self):
                  self.count = 0
                  self.buybars = [1, 150]
                  self.closebars = [100, 250]
          
              def next(self):
                  bar = len(self.data)
                  self.dt = self.data.datetime.date()
                  ex_rate = self.datas[1].close[0]
                  com = self.broker.getcommissioninfo(self.data).get_leverage()
                  print('broker.get_leverage:               {}'.format(self.broker.get_leverage()))
                  print('getcomissioninfo.get_leverage:     {}'.format(com))
                  print('{} Close: {}'.format(self.datas[1]._name, ex_rate))
                  if not self.position:
                      if bar in self.buybars:
                          entry = self.buy(size=self.p.size)
                          entry.addinfo(name='Entry')
                  else:
                      self.check_mco(value=self.broker.get_value(), margin_used=self.margin)
                      if bar in self.closebars:
                          close = self.close()
                          close.addinfo(name='Close')
          
                  self.count += 1
          
              def notify_trade(self, trade):
                  if trade.isclosed:
                      print('{}: Trade closed '.format(self.dt))
                      print('{}: PnL Gross {}, Net {}\n\n'.format(self.dt,
                                                          round(trade.pnl,2),
                                                          round(trade.pnlcomm,2)))
          
          
          
          class OandaCSVData(bt.feeds.GenericCSVData):
              params = (
                  ('nullvalue', float('NaN')),
                  ('dtformat', '%Y-%m-%dT%H:%M:%S.%fZ'),
                  ('datetime', 6),
                  ('time', -1),
                  ('open', 5),
                  ('high', 3),
                  ('low', 4),
                  ('close', 1),
                  ('volume', 7),
                  ('openinterest', -1),
              )
          
          
          
          tframes = dict(
              minutes=bt.TimeFrame.Minutes,
              daily=bt.TimeFrame.Days,
              weekly=bt.TimeFrame.Weeks,
              monthly=bt.TimeFrame.Months)
          
          
          #Variable for our starting cash
          startcash = 10000
          
          #Create an instance of cerebro
          cerebro = bt.Cerebro()
          
          #Set commission
          cerebro.broker.setcommission(leverage=50)
          
          #Add our strategy
          cerebro.addstrategy(Mltests)
          
          #get oanda data
          data = OandaCSVData(
              dataname='data/EUR_USD-2005-2017-D1.csv',
              romdate=datetime(2005,1,1),
              todate=datetime(2006,1,1))
          
          data1 = OandaCSVData(
              dataname='data/EUR_GBP-2005-2017-D1.csv',
              romdate=datetime(2005,1,1),
              todate=datetime(2006,1,1))
          
          #Add the data to Cerebro
          cerebro.adddata(data, name='inst')
          cerebro.adddata(data1, name='ex_rate') #exchange rate for GBP to EUR
          # Set our desired cash start
          cerebro.broker.setcash(startcash)
          
          # Run over everything
          cerebro.run()
          
          
          portvalue = cerebro.broker.getvalue()
          pnl = portvalue - startcash
          
          print('Final Portfolio Value: ${}'.format(portvalue))
          print('P/L: ${}'.format(pnl))
          
          #Finally plot the end results
          cerebro.plot(style='candlestick')
          
          B 1 Reply Last reply Reply Quote 0
          • B
            backtrader administrators @ThatBlokeDave last edited by

            The pointer is to the reference of the class which can be overridden CommInfoBase. It doesn't say that you get your actual leverage from that call nor that this is meant for user consumption. That class provides an interface which is used by the broker, not by the end user.

            Of course you may override it and call it if it serves your purpose.

            1 Reply Last reply Reply Quote 0
            • T
              ThatBlokeDave last edited by

              Ok thanks.

              Sure, since I am trying to simulate a margin close out, I think this serves a good purpose as I can use this to work out the initial margin required for a position.

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