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/

    math.log with linebuffer._LineDelay object

    Indicators/Strategies/Analyzers
    3
    9
    525
    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.
    • M
      marsario last edited by

      Hello!

      This is my indicator:

      class weightedlogmeanInd(bt.Indicator):
      
          lines = ('mean',)  # output line (array)
          params = (
              ('speed', 4),
              ('tau',0.01),
          )
      
          def __init__(self):
              weights = findweights(self.p.speed,self.p.tau) #this is an array
              change_sum = 0
              period = len(weights)
              for day in range(0,-period,-1):
                  change = self.data.close(0-day) - ( self.data.close(-1-day))
      #            change = math.log(self.data.close(0-day)) - math.log( self.data.close(-1-day))
                  weighted_change = change * weights[-day]
                  change_sum = change_sum + weighted_change 
              self.lines.mean = change_sum / period
      

      I would like to change this line:

      change = self.data.close(0-day) - ( self.data.close(-1-day))
      

      into the line below, which is now commented out:

      change = math.log(self.data.close(0-day)) - math.log( self.data.close(-1-day))
      

      When I do it, I get the following error message:

      TypeError: must be real number, not _LineDelay
      

      Basically, I would like to use the logarithm to get the price change from yesterday to today. What would be the best way to do it?

      Thanks a lot!

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

        @marsario There's a built in Log function in backtrader. It will provide you with the log of a single number in next, not for a whole line in init.

        All of this:

        for day in range(0,-period,-1):
        change = self.data.close(0-day) - ( self.data.close(-1-day))
        change = math.log(self.data.close(0-day)) - math.log( self.data.close(-1-day))
        weighted_change = change * weights[-day]
        change_sum = change_sum + weighted_change

        Needs to move into next, and you don't need range.
        I haven't tested the following, but generally it should look something like:

        def next(self):
            self.close_log[0] = bt.Log(self.datas[0].close[0])
            self.change[0] = self.close_log[0] - self.close_log[-1]
            self.weighted_change[0] = self.change[0] * self.weights[0]
            self.change_sum[0] = self.change_sum[-1] + self.weighted_change[0]
        

        With respect to indexing, you don't have to go back the extra [-1] since backtrader sees the bar at [0] as closed.

        RunBacktest.com

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

          @run-out said in math.log with linebuffer._LineDelay object:

          def next(self):
          self.close_log[0] = bt.Log(self.datas[0].close[0])
          self.change[0] = self.close_log[0] - self.close_log[-1]
          self.weighted_change[0] = self.change[0] * self.weights[0]
          self.change_sum[0] = self.change_sum[-1] + self.weighted_change[0]

          Hi, thanks for your suggestion!

          I'm getting AttributeError that backtrader doesn't have a Log method. That's suppose to be an indicator, isn't it?

          If so I should be able to recreate it.

          A 1 Reply Last reply Reply Quote 0
          • M
            marsario last edited by

            @run-out

            I'm trying to implement the indicator with a different logic. And I don't understand what happens.

            class weightedlogmeanInd(bt.Indicator):
            
                lines = ('mean',)  # output line (array)
                params = (
                    ('speed', 4),
                    ('tau',0.01),
                )
                weights = []
            
                def __init__(self):
                    self.weights = findweights(self.p.speed,self.p.tau)
                    today=self.data.get(ago=0,size=len(self.weights))
                    yesterday=self.data.get(ago=-1,size=len(self.weights))
                    print("len(today):",len(today))
                    print("len(yesterday):",len(yesterday))
                    print("What is happening in today?", (today) )
                    print("What is happening in yesterday?",(yesterday) )
                    
                    growth = np.log(today)-np.log(yesterday)
                    
                    print("data close:",self.data.close(0))
                    print("What is happening in growth?", growth )
                    
            

            The printout and error message:

            (base) Simones-Air:Learning Backtrader simoneromeo$ python 26\ onestock\ strategy.py 
            Launching the strategy
            Starting logmean strategy
            len(today): 0
            len(yesterday): 27
            What is happening in today? array('d')
            What is happening in yesterday? array('d', [133.74, 137.18, 136.76, 136.91, 136.01, 135.39, 135.13, 135.37, 133.19, 130.84, 129.71, 129.87, 126.0, 125.86, 125.35, 120.99, 121.26, 127.79, 125.12, 122.06, 120.13, 121.42, 116.36, 121.09, 119.98, 121.96, 121.03])
            Traceback (most recent call last):
              File "26 onestock strategy.py", line 150, in <module>
                cerebro.run()
             ...
              File "26 onestock strategy.py", line 46, in __init__
                growth = np.log(today)-np.log(yesterday)
            ValueError: operands could not be broadcast together with shapes (0,) (27,) 
            
            

            I don't undestand: why does self.data.get(ago=0,size=len(self.weights) return an empty array and self.data.get(ago=-1,size=len(self.weights) return an array with the right length?

            1 Reply Last reply Reply Quote 0
            • M
              marsario last edited by

              @run-out

              After some unsuccessful attempts, i came back to the strategy you recommended. I defined log like this:

              from backtrader.functions import MultiLogic
              
              
              class Log(MultiLogic):
                  flogic = math.log
              

              Also, added one more line to the code you recommended so that I passed the mean to the line object:

              
              class weightedlogmeanInd(bt.Indicator):
              
                  lines = ('mean',)  # output line (array)
                  params = (
                      ('speed', 4),
                      ('tau',0.01),
                  )
                  
              def next(self):
                  self.close_log[0] = Log(self.datas[0].close[0])
                  self.change[0] = self.close_log[0] - self.close_log[-1]
                  self.weighted_change[0] = self.change[0] * self.weights[0]
                  self.change_sum[0] = self.change_sum[-1] + self.weighted_change[0]
                  self.lines.mean[0]= bt.Sum(self.change_sum)/len(self.weights)
              

              This doesn't send an error, but doesn't behave as I wished (ideally, it should create a Mean line for each day of the datafeed. I realize that I don't understand how to use Indicators' Next method (I have created indicators but always inside Init). I wish I could find more resources to learn – Platform concepts and Indicators Development don't help me enough apparently. Do you have recommendations of how I could learn to build this indicator?

              run-out 1 Reply Last reply Reply Quote 0
              • A
                ab_trader @marsario last edited by

                @marsario said in math.log with linebuffer._LineDelay object:

                I'm getting AttributeError that backtrader doesn't have a Log method. That's suppose to be an indicator, isn't it?

                i think @run-out used the log function implemented in backtrader2. if you use baseline bt package, than it is not there.

                • If my answer helped, hit reputation up arrow at lower right corner of the post.
                • Python Debugging With Pdb
                • New to python and bt - check this out
                run-out 1 Reply Last reply Reply Quote 0
                • M
                  marsario last edited by

                  @ab_trader Is there a way still to find the logarithm inside an indicator? The solution that I thought I found is a mess and it won't work.

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

                    @ab_trader woops!

                    RunBacktest.com

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

                      @marsario said in math.log with linebuffer._LineDelay object:

                      self.lines.mean[0]= bt.Sum(self.change_sum)/len(self.weights)

                      I think you are close. This line:

                      self.lines.mean[0]= bt.Sum(self.change_sum)/len(self.weights)
                      

                      The self.change_sum is already a sum from the previous line. It's cummulative. So I think this line should read:

                      self.lines.mean[0]= self.change_sum[0]/len(self.weights)
                      

                      Also, in your first line.

                      self.close_log[0] = math.log(self.datas[0].close[0])
                      

                      Import math and try that. self.datas[0].close[0] is a scalar and math.log should work.

                      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