For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

Custom Indicator RVI; float division by zero



  • So I am trying to build the relative volatility index indicator in backtrader. However, I get an error:

    dst[i] = op(srca[i], srcb[i])                                                                                       ZeroDivisionError: float division by zero   
    

    I understand that there are multiple points in my indicator logic where a division by zero could occur, such as rviHi declaration. However, I can't seem to find a way to fix this. Can anyone with knowledge of the relative volatility index check if my math/formula is right? Or is this a logic/programming error I committed?

    Code:

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    import backtrader as bt
    from datetime import datetime
    from backtrader.indicators import EMA
    from backtrader.indicators import StdDev
    import backtrader.indicators as btind
    
    class RVI(bt.Indicator):
        lines = ('dummyline',)
    
        params = (('value', 5),)
    
        def __init__(self):
            stDevHi = StdDev(self.data.high, period=10)
            stDevLo = StdDev(self.data.low, period=10)
            avgStDevHiUp = bt.If(self.data.high  > self.data.high(-1),EMA(stDevHi, period = 14), 0)
    
            avgStDevHiDown= bt.If(self.data.high  < self.data.high(-1),EMA(stDevHi, period = 14), 0)
    
    
            avgStDevLoUp = bt.If(self.data.low  > self.data.low(-1),EMA(stDevLo, period = 14), 0)
    
     
            avgStDevLoDown = bt.If(self.data.low  < self.data.low(-1),EMA(stDevLo, period = 14), 0)
    
    
            rviHi = bt.If((avgStDevHiDown + avgStDevHiUp) == 0, 50, (100* avgStDevHiUp) / (avgStDevHiUp + avgStDevHiDown))
    
    
            rviLo = bt.If((avgStDevLoUp + avgStDevLoDown) == 0,50, (100* avgStDevLoUp) / (avgStDevLoUp + avgStDevLoDown))
    
    
            self.lines.dummyline = (rviHi + rviLo) / 2
    class firstStrategy(bt.Strategy):
    
        def __init__(self):
            self.rsi_small = RVI(self.data)
            self.sma = btind.EMA(self.data, period = 20)
    
        def next(self):
            if not self.position:
                if (self.sma < self.data.close and self.rsi_small > self.rsi_small[-1]):
                    self.buy(size=10)
                    #print('{},BUY,{}'.format(self.datetime.datetime(), self.data.close[0]))
                    #print(self.datetime.date())
                if (self.sma > self.data.close and self.rsi_small < self.rsi_small[-1]):
                    self.sell(size=10)
                    #print('{},SELL,{}'.format(self.datetime.datetime(), self.data.close[0]))
                    #print(self.datetime.date())
            else:
                if self.rsi_small < self.rsi_small[-1] and self.data.close < self.sma and self.position.size > 0:
                    self.close(size=10)
                if self.rsi_small > self.rsi_small[-1] and self.data.close > self.sma and self.position.size < 0:
                    self.close(size=10)
    
    
    #Variable for our starting cash
    startcash = 10000
    
    #Create an instance of cerebro
    cerebro = bt.Cerebro()
    
    #Add our strategy
    cerebro.addstrategy(firstStrategy)
    
    #Get Apple data from Yahoo Finance.
    #data = bt.feeds.Quandl(
    #    dataname='AAPL',
    #    fromdate = datetime(2016,1,1),
    #    todate = datetime(2017,1,1),
    #    buffered= True
    #    )
    data = bt.feeds.YahooFinanceData(
        dataname='AAPL',
        fromdate = datetime(2000,1,1),
        todate = datetime(2020,1,1),
        timeframe = bt.TimeFrame.Days,
        buffered= True
        )
    #Add the data to Cerebro
    cerebro.adddata(data)
    
    
    
    # Set our desired cash start
    cerebro.broker.setcash(startcash)
    
    # Run over everything
    cerebro.run()
    
    #Get final portfolio Value
    portvalue = cerebro.broker.getvalue()
    pnl = portvalue - startcash
    
    #Print out the final result
    print('Final Portfolio Value: ${}'.format(portvalue))
    print('P/L: ${}'.format(pnl))
    
    #Finally plot the end results
    cerebro.plot(style='candlestick')
    

    Thanks for any help



  • Have a look here. bt.DivByZero



  • Thank you, thats exactly what I needed. Didn't realize backtrader had this function.


Log in to reply
 

});