How can I create an indicator and ignore div by 0 error in data?
-
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 lambdaThanks!
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()
-
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. -
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
-
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/
-
@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()
-
I find out that I forget to use init method to initialize. Sorry