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/

    Indicator for Log Returns of data feeds

    Indicators/Strategies/Analyzers
    indicator
    2
    5
    76
    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, dear @backtrader

      I try to create an indicator that lets me calculate the log-returns for a given period for each "data". The following code failed, I assume that I made a mistake with ApplyN?

      class LogReturns(bt.Indicator):
          lines = ('logreturns',)
      
          def __init__(self):
              self.lines.logreturns = bt.ind.ApplyN(bt.ind.PercentChange(self.data, period=1) + 1, func=lambda x: math.log(x[0]))
      

      Can you kindly show me how I can correctly calculate a log-return indicator?

      Thanks!
      J

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

        This analyzer exists if you are ok using an analyzer.

        https://www.backtrader.com/docu/analyzers-reference/#logreturnsrolling

        Which means you can look at the code for creating the log return analyzer to help making your own:
        https://github.com/backtrader2/backtrader/blob/master/backtrader/analyzers/logreturnsrolling.py

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

          @run-out

          Thanks for pointing this out. I also came across the analyzer, but as far as I understand the backtrader platform this approach doesn't work as analyzers are "a different type of animal" when compared to indicators. Or have you been able to use an analyzer as an input inside next?

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

            I took the liberty of writing up the code.

            import datetime
            import backtrader as bt
            import math
            
            class LogReturns(bt.Indicator):
                params = (
                    ("log_period", 1),
                )
                lines = ('logreturns',)
            
                def next(self):
                    # This makes sure enough bars have passed before trying to calcualte the log return.
                    if len(self) < self.p.log_period:
                        return
                    self.l.logreturns[0] = (math.log(self.datas[0].close[0] / self.datas[0].close[-1]) / self.p.log_period) * 100
            
            
            class Strat(bt.Strategy):
                params = dict(log_period=1)
            
                def log(self, txt, dt=None):
                    """ Logging function fot this strategy"""
                    dt = dt or self.data.datetime[0]
                    if isinstance(dt, float):
                        dt = bt.num2date(dt)
                    print("%s, %s" % (dt.date(), txt))
            
                # Added log return to the signal printout.
                def print_signal(self):
                    self.log(
                        "o {:7.2f}\th {:7.2f}\tl {:7.2f}\tc {:7.2f}\tlog_return {:3.3f}".format(
                            self.datas[0].open[0],
                            self.datas[0].high[0],
                            self.datas[0].low[0],
                            self.datas[0].close[0],
                            self.lr[0],
                        )
                    )
            
                def __init__(self):
                    self.lr = LogReturns(log_period=self.p.log_period)
            
            
                def next(self):
                    self.print_signal()
            
            
            if __name__ == "__main__":
            
                cerebro = bt.Cerebro()
            
                for s in ['AAPL']:
                    data = bt.feeds.YahooFinanceData(
                        dataname=s,
                        timeframe=bt.TimeFrame.Days,
                        fromdate=datetime.datetime(2019, 11, 4),
                        todate=datetime.datetime(2020, 11, 4),
                        reverse=False,
                    )
                    cerebro.adddata(data)
            
                cerebro.addstrategy(Strat)
            
                # Execute
                cerebro.run()
            

            Which prints out something like:

            2019-11-04, o   63.07	h   63.20	l   62.60	c   63.12	log_return -55.771
            2019-11-05, o   63.01	h   63.29	l   62.83	c   63.03	log_return -0.143
            2019-11-06, o   62.94	h   63.11	l   62.59	c   63.05	log_return 0.032
            2019-11-07, o   63.61	h   64.01	l   63.46	c   63.78	log_return 1.151
            2019-11-08, o   63.60	h   64.03	l   63.15	c   63.95	log_return 0.266
            2019-11-11, o   63.50	h   64.53	l   63.50	c   64.46	log_return 0.794
            
            J 1 Reply Last reply Reply Quote 3
            • J
              jf @run-out last edited by

              @run-out Amazing, thanks a lot! Your help in this regard is highly appreciated!

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