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/

    Create an indicator based on an analyzer

    General Code/Help
    2
    5
    1111
    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
      jf last edited by

      Dear community,

      I would like to create an indicator based on the daily returns of a data series. As far as I understand, the returns are not automatically "available", but first have to be calculated with an analyzer.

      So here is my approach:
      First, I load the data, then I create the analyzer called "myReturn":

      #  Load data from a pre-specified dataframe
      data = bt.feeds.PandasData(dataname=dataframe)
      
      # Add data to cerebro
      cerebro.adddata(data)
      
      # Add analyzer        
      cerebro.addanalyzer(bt.analyzers.TimeReturn,
                                  timeframe=bt.TimeFrame.Days,
                                  data=data,
                                  _name='myReturn')
      

      After I run the strategy, I can access the analyzer (=returns), so that works well:

      thestrats = cerebro.run()
      thestrat = thestrats[0]
      
      tret_analyzer = thestrat.analyzers.getbyname('myReturn')
      print(tret_analyzer.get_analysis())
      

      However, when I would like to create an indicator based on the analyzer, I just can't figure out how to access it. As a simple example, I would like to create two moving averages:

      • a moving average of the price of the last 15 days
      • a moving average of the returns of the last 15 days
      # Sample strategy from backtrader quickstart example
      class TestStrategy(bt.Strategy):
          params = (
              ('maperiod', 15),
          )
      
          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.dataclose = self.datas[0].close
      
              # To keep track of pending orders and buy price/commission
              self.order = None
              self.buyprice = None
              self.buycomm = None
      
              # Add a MovingAverageSimple indicator OF THE CLOSING PRICE
              self.pricesma = bt.indicators.SimpleMovingAverage(
                  self.datas[0], period=self.params.maperiod)
      
              # Add a MovingAverageSimple indicator OF THE RETURNS (=ANALYZER)
              self.returnsma = bt.indicators.SimpleMovingAverage(
                  self.analyzers[0], period=self.params.maperiod)
      

      The problem is obviously the last line in the code, as this seems to be the wrong way to access the values of the analyzers.

      Could anybody tell me how I correctly refer to an analyzer in order to create an indicator? That would be great!

      Thanks a lot!
      jf

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

        An Analyzer is not a data feed and cannot therefore be used as input for an Indicator. In any case you are not calculating returns (as in the returns of your accounts) but the daily variations of the data.

        Why not use the PercentChange indicator on the data and then make a SimpleMovingAverage of that?

        myind = bt.ind.SMA(bt.ind.PctChange(self.data), period=myperiod))
        
        1 Reply Last reply Reply Quote 0
        • J
          jf last edited by

          @backtrader: Ok great, thanks!

          @community: I guess a standard number that traders are interested in is the volatility of returns, which can be used for portfolio construction approaches such as "equal contribution to risk", volatility based risk management, etc.

          As backtrader explained above, it is best to implement this with an indicator based on an indicator. I currently implement return volatility calculation like this (using TA-LIB):

          returnvola = bt.talib.STDDEV(bt.ind.PctChange(self.data.close), timeperiod=30, plot=True)
          

          Would of course be interested to hear from you if somebody implements it differently, for example without TA-LIB... Also, has someone implemented this based on log-returns?

          Thanks!

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

            @jf said in Create an indicator based on an analyzer:

            returnvola = bt.talib.STDDEV(bt.ind.PctChange(self.data.close), timeperiod=30, plot=True)
            

            Would of course be interested to hear from you if somebody implements it differently, for example without TA-LIB

            returnvola = bt.ind.StdDev(bt.ind.PctChange(self.data.close), period=30)
            

            which you can shorten (to make it a lot more generic) to

            returnvola = bt.ind.StdDev(bt.ind.PctChange(self.data), period=30)
            

            or even

            returnvola = bt.ind.StdDev(bt.ind.PctChange(), period=30)
            
            1 Reply Last reply Reply Quote 0
            • J
              jf last edited by

              Perfect, thanks!

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