indicator on resampled data
-
Hi
I am having some trouble on resampled data and custom indicator.class BaseStrategy(bt.Strategy): def __init__(self): self.zz = ZigZag(self.data0, period=2, retrace=0.05, minbars=2) def next(self): print('{},{:.5f},{:.5f},{:.5f}'.format(self.data0.datetime.datetime(0), self.zz.l.zigzag[0], self.zz.l.last_high[0], self.zz.l.last_low[0])) def main(): cerebro = bt.Cerebro(oldtrades=True) cerebro.addstrategy(BaseStrategy) df = pd.read_csv('datas\\EURUSD.csv', sep=',', header=0, index_col=0, parse_dates=True) data0 = bt.feeds.PandasData(dataname=df, timeframe=bt.TimeFrame.Minutes) cerebro.adddata(data0) cerebro.resampledata(data0, timeframe=bt.TimeFrame.Minutes, compression=240) cerebro.run(maxcpus=3, stdstats=False, runonce=True) if __name__ == '__main__': main()
Simple enough code that passes in 2 datas. Run an indicator on init and run it on data0 and print out the line values in the next() method. However, the above code does not work. The zz.l.zigzag[0] are always nan. If I remove resampleddata() line, it works and it works with only this single change.
Code of the indicator is below, courtesy of Nikolai. https://community.backtrader.com/topic/1771/zigzag-indicator-for-live-trading/25class ZigZag(bt.ind.PeriodN): # periodN controls number lines to skip i think, so period is 2 so curr_idx start at 2 lines = ('trend', 'last_high', 'last_low', 'zigzag',) plotinfo = dict( subplot=False, plotlinelabels=True, plotlinevalues=True, plotvaluetags=True, ) plotlines = dict( trend=dict(_plotskip=True), last_high=dict(color='green', ls='-', _plotskip=True), last_low=dict(color='black', ls='-', _plotskip=True), zigzag=dict(_name='zz', color='lightblue', ls='-', _skipnan=True), # linewidth=2.0, ls='-', ) params = (dict(period=2, retrace=0.25, minbars=2, _autoplot=True)) def __init__(self): super(ZigZag, self).__init__() assert self.p.retrace > 0, 'Retracement should be above zero.' assert self.p.minbars >= 0, 'Minimal bars should be >= zero.' self.ret = self.data.close * self.p.retrace / 100 self.minbars = self.p.minbars self.count_bars = 0 self.last_pivot_t = 0 self.last_pivot_ago = 0 def prenext(self): # prenext called before the minimum period required for the indicator, this case 2. So called just once. self.l.trend[0] = 0 self.l.last_high[0] = self.data.high[0] self.l.last_low[0] = self.data.low[0] self.l.zigzag[0] = (self.data.high[0] + self.data.low[0]) / 2 # print('prenext: ', self.l.trend[0], self.l.last_high[0], self.l.last_low[0], self.l.zigzag[0] ) def next(self): # this starts at 2nd line of data curr_idx = len(self.data) self.ret = self.data.close[0] * self.p.retrace / 100 self.last_pivot_ago = curr_idx - self.last_pivot_t self.l.trend[0] = self.l.trend[-1] self.l.last_high[0] = self.l.last_high[-1] self.l.last_low[0] = self.l.last_low[-1] self.l.zigzag[0] = float('nan') # print('next1:',curr_idx,self.data.close[0], self.ret, self.last_pivot_t,self.last_pivot_ago,self.l.trend[0],self.l.last_high[0],self.l.last_low[0]) # Search for trend if self.l.trend[-1] == 0: if self.l.last_low[0] < self.data.low[0] and self.l.last_high[0] < self.data.high[0]: # if current bar is higher than last high and last low self.l.trend[0] = 1 self.l.last_high[0] = self.data.high[0] self.last_pivot_t = curr_idx elif self.l.last_low[0] > self.data.low[0] and self.l.last_high[0] > self.data.high[0]: # if current bar is higher than last high and last low self.l.trend[0] = -1 self.l.last_low[0] = self.data.low[0] self.last_pivot_t = curr_idx # Up trend elif self.l.trend[-1] == 1: if self.data.high[0] > self.l.last_high[-1]: self.l.last_high[0] = self.data.high[0] self.count_bars = self.minbars self.last_pivot_t = curr_idx elif self.count_bars <= 0 and self.l.last_high[0] - self.data.low[0] > self.ret and self.data.high[0] < self.l.last_high[0]: self.l.trend[0] = -1 self.count_bars = self.minbars self.l.last_low[0] = self.data.low[0] self.l.zigzag[-self.last_pivot_ago] = self.l.last_high[0] self.last_pivot_t = curr_idx elif self.count_bars < self.minbars and self.data.close[0] < self.l.last_low[0]: self.l.trend[0] = -1 self.count_bars = self.minbars self.l.last_low[0] = self.data.low[0] self.l.zigzag[-self.last_pivot_ago] = self.l.last_high[0] self.last_pivot_t = curr_idx # Down trend elif self.l.trend[-1] == -1: if self.data.low[0] < self.l.last_low[-1]: self.l.last_low[0] = self.data.low[0] self.count_bars = self.minbars self.last_pivot_t = curr_idx elif self.count_bars <= 0 and self.data.high[0] - self.l.last_low[0] > self.ret and self.data.low[0] > self.l.last_low[0]: self.l.trend[0] = 1 self.count_bars = self.minbars self.l.last_high[0] = self.data.high[0] self.l.zigzag[-self.last_pivot_ago] = self.l.last_low[0] self.last_pivot_t = curr_idx elif self.count_bars < self.minbars and self.data.close[0] > self.l.last_high[-1]: self.l.trend[0] = 1 self.count_bars = self.minbars self.l.last_high[0] = self.data.high[0] self.l.zigzag[-self.last_pivot_ago] = self.l.last_low[0] self.last_pivot_t = curr_idx # Decrease minbars counter self.count_bars -= 1
Need some advice why this is happening, even though I have specified that the indicator run on data0. And how can I change the indicator code so that it can run even if resampled data is passed (no need to run on resampled data, but even just running on lower timeframe data would be great!) ?
Thanks