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/

    How can I create an indicator and ignore div by 0 error in data?

    Indicators/Strategies/Analyzers
    3
    6
    128
    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.
    • MX Bao
      MX Bao last edited by

      I am trying to create an indicator and have some div by 0 error. Can you replace the div by 0 with 0 in the indicator?
      For some minute data, the high and low is the same. I will get a div by 0 for these minute bars.

      Also How could I do a Moving average of 15 minutes of f1 divided by the 15 total of price*volume?
      I am wondering how could I do this in a way like lambda

      Thanks!

      import backtrader as bt
      import backtrader.feeds as btfeed
      
      
      class customCSV(btfeed.GenericCSVData):
          params = (
              ('dtformat', '%Y-%m-%d %H:%M:%S'),
              ('datetime', 0),
              ('open', 1),
              ('high', 2),
              ('low', 3),
              ('close', 4),
              ('volume', 5),
              ('openinterest', -1)
          )
      
      
      class SmaCross(bt.SignalStrategy):
          params = (('pfast', 10), ('pslow', 30),)
      
          def __init__(self):
      
              self.data.f1=(self.data.close-self.data.open)/(self.data.high-self.data.low) * self.data.volume*(self.data.high+self.data.low) /2 
      
      
      cerebro = bt.Cerebro()
      
      data = customCSV(dataname='C:\\Test\\SPY.csv')
      
      cerebro.adddata(data)
      cerebro.addstrategy(SmaCross)
      cerebro.run()
      cerebro.plot()
      
      1 Reply Last reply Reply Quote 0
      • run-out
        run-out last edited by

        Your question has two parts.
        Part 1: Try this out.

        self.data.f1 = bt.If(
        (self.data.high-self.data.low)!=0, 
        (self.data.close-self.data.open)/(self.data.high-self.data.low) * self.data.volume*(self.data.high+self.data.low) /2 
        , 
        0)
        

        Part 2:
        Have a look at this page and see if this helps.

        1 Reply Last reply Reply Quote 0
        • MX Bao
          MX Bao last edited by

          thanks, run-out!
          I did try your code for part 1. But I still get the same error. Can you try ur code on this csv?

          http://www.sharecsv.com/dl/83a4571ad89d5e20bc01f9a84c686784/SPY.csv

          Here is the error:

          Traceback (most recent call last):
            File "C:/Users/XXX/PycharmProjects/TD/Test.py", line 41, in <module>
              cerebro.run()
            File "C:\Users\XXX\AppData\Local\Programs\Python\Python38-32\lib\site-packages\backtrader\cerebro.py", line 1127, in run
              runstrat = self.runstrategies(iterstrat)
            File "C:\Users\XXX\AppData\Local\Programs\Python\Python38-32\lib\site-packages\backtrader\cerebro.py", line 1293, in runstrategies
              self._runonce(runstrats)
            File "C:\Users\XXX\AppData\Local\Programs\Python\Python38-32\lib\site-packages\backtrader\cerebro.py", line 1652, in _runonce
              strat._once()
            File "C:\Users\XXX\AppData\Local\Programs\Python\Python38-32\lib\site-packages\backtrader\lineiterator.py", line 297, in _once
              indicator._once()
            File "C:\Users\XXX\AppData\Local\Programs\Python\Python38-32\lib\site-packages\backtrader\linebuffer.py", line 631, in _once
              self.once(self._minperiod, self.buflen())
            File "C:\Users\XXX\AppData\Local\Programs\Python\Python38-32\lib\site-packages\backtrader\linebuffer.py", line 755, in once
              self._once_op(start, end)
            File "C:\Users\XXX\AppData\Local\Programs\Python\Python38-32\lib\site-packages\backtrader\linebuffer.py", line 772, in _once_op
              dst[i] = op(srca[i], srcb[i])
          ZeroDivisionError: float division by zero
          
          1 Reply Last reply Reply Quote 0
          • vladisld
            vladisld last edited by

            Please take a look at the following post. Quoting some code from there:

            class BollingerBandsPct(BollingerBands):
                '''
                Extends the Bollinger Bands with a Percentage line
                '''
                lines = ('pctb',)
                params = (('safediv', False), ('safezero', 0.0))
                plotlines = dict(pctb=dict(_name='%B'))  # display the line as %B on chart
            
                def __init__(self):
                    super(BollingerBandsPct, self).__init__()
                    if not self.p.safediv:
                        self.l.pctb = (self.data - self.l.bot) / (self.l.top - self.l.bot)
                    else:
                        self.l.pctb = DivByZero(self.data - self.l.bot, self.l.top - self.l.bot, self.p.safezero)
            
            class BollingerBandsPct_SafeDiv(BollingerBandsPct):
                params = (('safediv', True),)
            

            Also the following doc may be relevant: https://www.backtrader.com/blog/2019-07-08-canonical-or-not/canonical-or-not/

            MX Bao 1 Reply Last reply Reply Quote 1
            • MX Bao
              MX Bao @vladisld last edited by

              @vladisld Thanks for your reply!
              I tried the MFI code here https://www.backtrader.com/blog/2019-07-17-mfi-generic/mfi-generic/ and the indicator is calculated and displayed.

              After I make minor changes, the indicator is not displaying anymore. But the code did run and plot is fine except no indicator. This is really weird. I have not tried the moving average yet.

              class MoneyFlowIndex(bt.Indicator):
                  lines = ('mfi',)
                  params = (
                      ('period', 14),
                  )
                  def init(self):
                      money_flow_raw = (self.data.high - self.data.low)
                      money_flow_net = (self.data.close - self.data.open)
                      mfiratio = bt.ind.DivByZero(money_flow_net, money_flow_raw, zero=0.5)*50+50
                      self.l.mfi =  mfiratio
              cerebro = bt.Cerebro()
              
              data = customCSV(dataname='E:\\SPY.csv')
              
              cerebro.adddata(data)
              myind = MoneyFlowIndex(data)
              myind.plotinfo.subplot = True
              cerebro.add_signal(bt.SIGNAL_LONGSHORT, MoneyFlowIndex)
              cerebro.run()
              cerebro.plot()
              
              MX Bao 1 Reply Last reply Reply Quote 0
              • MX Bao
                MX Bao @MX Bao last edited by

                I find out that I forget to use init method to initialize. Sorry

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