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/

    Make an Indicator off a Custom 'Line'

    General Code/Help
    3
    11
    1795
    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.
    • C
      cwse last edited by

      Hi,

      Is it possible to apply an indicator on a custom data "line"?

      Eg. have a simplemovingaverage on a custom data line (which is not OHLC data)?

      If so, whats the best approach?

      Thanks!

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

        There is no best approach. You can pass any line to indicators.

        1 Reply Last reply Reply Quote 0
        • C
          cwse last edited by

          Thanks @backtrader , how?

          For example in the following code, where do you set the indicators name so that backtrader doesnt use the OHLC data?

           for i, d in enumerate(d for d in self.datas):
                      self.sma_mth[d] = bt.indicators.SimpleMovingAverage(d, period=21)
          

          For example, if my line is called 'X'; this doesnt appear to work?

          for i, d in enumerate(d for d in self.datas):
                      self.smaX[d] = bt.indicators.SimpleMovingAverage(d.lines.X, period=5)
          

          I get this error:

          AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'X'
          
          1 Reply Last reply Reply Quote 0
          • B
            backtrader administrators last edited by backtrader

            And what is the definition of data feed d? Sorry, but some lines out of context are proof of nothing.

            Things can be analyzed if you post something complete. Else ...

            @cwse said in Make an Indicator off a Custom 'Line':

            I get this error:

            AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'X'
            

            Where is the implication in that error message that OHLC is being used?

            1 Reply Last reply Reply Quote 0
            • C
              cwse last edited by

              Hi @backtrader

              I am not trying to prove anything, I am simply asking for help. How do I set a indicator (eg bt.indicators.simpleMovingAverage) to use a specific line?

              Note on the above error it specifically says OHLC

              This section is at the start of my Strategy code in the init:

                  def __init__(self):
                      self.o = {}  # orders per data (main, stop, limit, manual-close)
                      self.sma_mth = {}
                      self.sma50 = {}
                      self.sma20 = {}
                      self.sma10 = {}
                      self.sma5 = {}
                      self.sma3 = {}
                      self.sma2 = {}
                      #self.bollinger = {}
                      for i, d in enumerate(d for d in self.datas):
                          self.sma_mth[d] = bt.indicators.SimpleMovingAverage(d, period=21) #https://cryptocurrencyhaus.com/crypto-trading-how-to-use-simple-moving-averages/
                          self.sma50[d] = bt.indicators.SimpleMovingAverage(d, period=50)
                          self.sma20[d] = bt.indicators.SimpleMovingAverage(d, period=20) #https://cryptocurrencyhaus.com/crypto-trading-how-to-use-simple-moving-averages/
                          self.sma10[d] = bt.indicators.SimpleMovingAverage(d, period=10)
                          self.sma5[d] = bt.indicators.SimpleMovingAverage(d, period=5)
                          self.sma3[d] = bt.indicators.SimpleMovingAverage(d, period=3)
                          self.sma2[d] = bt.indicators.SimpleMovingAverage(d, period=2)
              

              My data has been fed to backtrader and is hence referd to as self.datas.

              Any tips helpers or pointers in the right direction, on how to use custom lines here would be much appreciated!

              Thank you!!

              1 Reply Last reply Reply Quote 0
              • Robin Dhillon
                Robin Dhillon last edited by

                I dont quite understand what you mean by using a custom data line, because you can literally use any line data as a input for your indicators. So to put this into context.
                suppose I have an indicator which depends on the SMA12 and SMA26 of a line dataset, lets call it cumulative_average.

                def __ init__ (self):
                      sma12 = bt.indicators.SimpleMovingAverage(self.datas[0], period=12)
                      sma26 = bt.indicators.SimpleMovingAverage(self.datas[0], period=26)
                      cumulative_average = sma26 - sma12 + self.datas[0].close
                      another_average = bt.indicators.SimpleMovingAverage(cumulative_average, period = 14)
                

                So basically you performed some arithmetic operation on your line data and assigned it to cumulative_average and found the SMA of the line data. Essentially you made a new line data which you can further implement in your next method.
                You can refer to the docs for more info.

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

                  @backtrader said in Make an Indicator off a Custom 'Line':

                  And what is the definition of data feed d? Sorry, but some lines out of context are proof of nothing.

                  @backtrader said in Make an Indicator off a Custom 'Line':

                  Things can be analyzed if you post something complete. Else ...
                  @cwse said in Make an Indicator off a Custom 'Line':

                  I get this error:

                  AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'X'
                  
                  1 Reply Last reply Reply Quote 0
                  • C
                    cwse last edited by

                    Hi @backtrader

                    Here is my data loader, I use many custom "analysis_cols"

                    class CustomBTStockLoader(btfeeds.PandasData):
                        #  None : column not present
                        #  -1 : autodetect position or case-wise equal name
                        #  >= 0 : numeric index to the colum in the pandas dataframe
                        #  string : column name (as index) in the pandas dataframe
                    
                    
                        params = (
                                     ('openinterest', None),
                                     ('open', 'Open'),
                                     ('high', 'High'),
                                     ('low', 'Low'),
                                     ('close','Close'),
                                     ('volume','Volume')
                                 ) \
                                 + tuple((e,-1) for e in v.analysiscols)   #<--- this loads my custom data columns.
                    
                        if v.Custom_Alg == True:
                            lines = tuple(v.analysiscols) #('Opportunity',)
                            datafields = btfeeds.PandasData.datafields + v.analysiscols
                        else:
                            datafields = btfeeds.PandasData.datafields
                    

                    I feel my question is pretty straight forward though and we are going on a bit of a tangent.

                    How do you specify the data which an indicator uses?

                    I believe it should just be a matter of editing this single line of code (following) where the indicator is created, to somehow specify the "line" of interest. Could you please tell me how?

                    self.sma_mth[d] = bt.indicators.SimpleMovingAverage(d, period=21)
                    B 1 Reply Last reply Reply Quote 0
                    • B
                      backtrader administrators @cwse last edited by backtrader

                      @cwse said in Make an Indicator off a Custom 'Line':

                      I feel my question is pretty straight forward though and we are going on a bit of a tangent.

                      It is not and you are the only one going off roads.

                      @cwse said in Make an Indicator off a Custom 'Line':

                      class CustomBTStockLoader(btfeeds.PandasData):
                          #  None : column not present
                          #  -1 : autodetect position or case-wise equal name
                          #  >= 0 : numeric index to the colum in the pandas dataframe
                          #  string : column name (as index) in the pandas dataframe
                      
                      
                          params = (
                                       ('openinterest', None),
                                       ('open', 'Open'),
                                       ('high', 'High'),
                                       ('low', 'Low'),
                                       ('close','Close'),
                                       ('volume','Volume')
                                   ) \
                                   + tuple((e,-1) for e in v.analysiscols)   #<--- this loads my custom data columns.
                      
                          if v.Custom_Alg == True:
                              lines = tuple(v.analysiscols) #('Opportunity',)
                              datafields = btfeeds.PandasData.datafields + v.analysiscols
                          else:
                              datafields = btfeeds.PandasData.datafields
                      

                      This code contains NO custom lines (see below). Now if we look backwards, you ask:

                      Make an Indicator off a Custom 'Line'
                      

                      When queried about information you answer

                      @cwse said in Make an Indicator off a Custom 'Line':

                      For example, if my line is called 'X'; this doesnt appear to work?

                      for i, d in enumerate(d for d in self.datas):
                                  self.smaX[d] = bt.indicators.SimpleMovingAverage(d.lines.X, period=5)
                      
                      

                      I get this error:

                      AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'X'
                      

                      Which is already an indication that you have defined NO custom lines (i.e.: X is not defined). When asked to show the definition for data d it still takes 2 extra posts until it is shown.

                      And the super data d contains as expected NO custom lines. Why?

                      Because for sure your v.Custom_Alg is NOT set to True.

                      God knows what v and where it is defined. Show it? Of course not. It is all about being straightforward. wasn't it?

                      The answer: to use custom lines you have first to define them. See Docs - Extending a Data feed

                      If you want to twist things until they don't work, your straightforward problem.

                      1 Reply Last reply Reply Quote 0
                      • C
                        cwse last edited by

                        Hi @backtrader

                        I am sorry this is turning to be a difficult to answer, it must be very complex process to add a line to an indicator in Backtrader. I am passing many lines into my strategy at present and do not need help with extending data feeds, this process works just fine thank you.

                        Apologies if you think I am twisting things, I just didn't want to copy my over 2000 lines of code as I think it is distracting from the question at hand. I don't think it is a good use of your or my time to turn this into a full code review. I can assure you I am passing over 20 lines via pandas dataframes with ~30columns into the custom data loader with no issues, using my analysiscols to specify the list of column names to pass as lines. These lines are used by my Backtrader strategy in many places.

                        Given it appears to not be a straightforward process to pass a line to an indicator, and I am not aware of any documentation on how to specify a line for use in an indicator, I will just calculate the SMA outside of BT (in pandas) and pass it into backtrader as another line.

                        I am a big fan of backtrader software and use it daily, so this workaround will do just fine.

                        Thank you!

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

                          @cwse said in Make an Indicator off a Custom 'Line':

                          I am sorry this is turning to be a difficult to answer, it must be very complex process to add a line to an indicator in Backtrader

                          IT IS NOT. Your code is broken and you are the only one making things difficult.

                          @cwse said in Make an Indicator off a Custom 'Line':

                          I am passing many lines into my strategy at present and do not need help with extending data feeds, this process works just fine thank you.

                          Apparently YOU NEED HELP.

                          If if works so smoothly, can you please say why this happens

                          @cwse said in Make an Indicator off a Custom 'Line':

                          For example, if my line is called 'X'; this doesnt appear to work?

                          for i, d in enumerate(d for d in self.datas):
                                      self.smaX[d] = bt.indicators.SimpleMovingAverage(d.lines.X, period=5)
                          
                          

                          I get this error:

                          AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'X'
                          

                          Because the translation to plain English is: "data feed d has no line with the name X".

                          @cwse said in Make an Indicator off a Custom 'Line':

                          I just didn't want to copy my over 2000 lines of code as I think it is distracting from the question at hand

                          Posting, reposting, non-working snippets, broken code is a lot easier than doing something simple. Of course ... because you have 2000 lines. You can only do complex things

                          Doing this was very difficult for someone who can write 2000 lines of code

                          class GenericCSV_X(bt.feeds.GenericCSVData):
                              lines = ('X',)
                              params = dict(dtformat='%Y-%m-%d', X=4)  # X same as close
                          
                          class St(bt.Strategy):
                              def __init__(self):
                                  bt.ind.SMA(self.data.lines.X)  # or self.data.X
                          
                          cerebro = bt.Cerebro()
                          cerebro.adddata(GenericCSV_X(dataname='../../datas/2006-day-001.txt'))
                          cerebro.addstrategy(St)
                          cerebro.run()
                          

                          And it works ... Holy Cow! A total of 10 code lines + 2 blanks. You can add the import backtrader as bt.

                          @cwse said in Make an Indicator off a Custom 'Line':

                          Given it appears to not be a straightforward process to pass a line to an indicator

                          IT IS STRAIGHTFORWARD. Your code is broken. But you prefer to post, repost and remix broken questions and broken snippets rather than asking straightforward questions and presenting straightforward code.

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