Issue with custom indicator and 2 timeframes
-
Hi to everyone!
I've got a problem that i can't resolve for some time.
I use custon indicator in my code. It works perfectly with one time frame data, but it completely does not work with two of them.
I initialize both timeframes in initdef __init__(self): # Keep a reference to the "close" line in the data[0] dataseries self.dataclose1 = self.datas[0].close self.dataclose30 = self.datas[1].close # To keep track of pending orders self.order = None #это расчет зигзага по таймфрейму 1 минута self.zigzag1 = Zigzag1.ZigZag(self.dataclose1) self.SMA = bt.indicators.SmoothedMovingAverage(self.dataclose1, period=10) #это расчет зигзага по таймфрейму 30 минут self.zigzag30 = Zigzag1.ZigZag(self.dataclose30) self.SMA30 = bt.indicators.SmoothedMovingAverage(self.dataclose30, period=30) self.ZZLevels1 = pd.DataFrame(columns = ['ZZ1','Index_in_Data1']) self.ZZLevels30 = pd.DataFrame(columns = ['ZZ30','Index_in_Data30'])
After that i try to call lines of zigzag in my next part:
def next(self): if self.order: return df1 = pd.DataFrame({'ZZ1': [self.zigzag1.lines.zigzag_peak[0]],'Index_in_Data1': [self.zigzag1.lines.last_pivot_t[0]]}) df30 = pd.DataFrame({'ZZ30': [self.zigzag30.lines.zigzag_peak[0]],'Index_in_Data30': [self.zigzag30.lines.last_pivot_t[0]]})
and here is when i print result I've got nothing. I thought that the problem is with data and i've checked everything with SMA indicator, and SMA was calculated correctly for both timeframes.
And here is I create two timeframes data.
cerebro = bt.Cerebro() # Add a strategy cerebro.addstrategy(TestStrategy) ticker = 'RTS' exporter = Exporter() asset = exporter.lookup(name=ticker, market=Market.FUTURES) asset_id = asset[asset['name'] == ticker].index[0] fromdate1=datetime.date(2021, 7, 1) data = exporter.download(asset_id, market=Market.FUTURES, timeframe=Timeframe.MINUTES1, start_date=fromdate1) data['<DATE>'] = data['<DATE>'].apply(lambda x: str(x)) data['<TIME>'] = data['<TIME>'].apply(lambda x: str(x)) data['<DATE>'] =data['<DATE>']+' '+ data['<TIME>'] data['<DATE>'] = data['<DATE>'].apply(lambda x: pd.to_datetime(str(x), format='%Y-%m-%d %H:%M:%S.%f')) rts = pd.DataFrame(data) rts = rts.set_index('<DATE>') rts= rts.loc[:,['<OPEN>','<HIGH>', '<LOW>', '<CLOSE>','<VOL>']] rts.index.names = ['Date'] rts.columns=['Open','High','Low','Close','Volume'] #print(rts) data1 = bt.feeds.PandasData(dataname=rts) print(data1) cerebro.adddata(data1,name = '1M') data30 = cerebro.resampledata(data1, name='data30', timeframe=bt.TimeFrame.Minutes, compression = 30) print(data30) # Add the Data Feed to Cerebro cerebro.adddata(data30,name = '30M')
I think that also you may need my code of zigzag:
import backtrader as bt import datetime import math class ZigZag(bt.ind.PeriodN): ''' Identifies Peaks/Troughs of a timeseries ''' lines = ( 'trend', 'last_pivot_t', 'last_pivot_x', 'last_pivot_ago', 'zigzag_peak', 'zigzag_valley', 'zigzag', 'last_zigzag', ) # Fancy plotting name # plotlines = dict(logreturn=dict(_name='log_ret')) plotinfo = dict( subplot=False, plotlinelabels=True, plotlinevalues=True, plotvaluetags=True, ) plotlines = dict( trend=dict(marker='', markersize=0.0, ls='', _plotskip=True), last_pivot_t=dict(marker='', markersize=0.0, ls='', _plotskip=True), last_pivot_x=dict(marker='', markersize=0.0, ls='', _plotskip=True), last_pivot_ago=dict(marker='', markersize=0.0, ls='', _plotskip=True), zigzag_peak=dict(marker='*', markersize=4.0, color='blue', fillstyle='full', ls=''), zigzag_valley=dict(marker='*', markersize=4.0, color='green', fillstyle='full', ls=''), zigzag=dict(_name='zigzag', color='blue', ls='-', _skipnan=True), last_zigzag=dict(_name='last_zigzag', color='blue', ls='--', _skipnan=True), ) # update value to standard for Moving Averages params = ( ('period', 9), ('up_retrace', 0.1), ('dn_retrace', 0.1), ('bardist', 0.02), # distance to max/min in absolute perc ) def __init__(self): super(ZigZag, self).__init__() if not self.p.up_retrace: raise ValueError('Upward retracement should not be zero.') if not self.p.dn_retrace: raise ValueError('Downward retracement should not be zero.') if self.p.up_retrace < 0: self.p.up_retrace = -self.p.up_retrace if self.p.dn_retrace > 0: self.p.dn_retrace = -self.p.dn_retrace self.p.up_retrace = self.p.up_retrace / 100 self.p.dn_retrace = self.p.dn_retrace / 100 self.missing_val = float('Nan') def prenext(self): self.lines.trend[0] = 0 self.lines.last_pivot_t[0] = 0 self.lines.last_pivot_x[0] = self.data[0] self.lines.last_pivot_ago[0] = 0 self.lines.zigzag_peak[0] = self.missing_val self.lines.zigzag_valley[0] = self.missing_val self.lines.zigzag[0] = self.missing_val self.lines.last_zigzag[0] = self.missing_val def next(self): data = self.data trend = self.lines.trend last_pivot_t = self.lines.last_pivot_t last_pivot_x = self.lines.last_pivot_x last_pivot_ago = self.lines.last_pivot_ago zigzag_peak = self.lines.zigzag_peak zigzag_valley = self.lines.zigzag_valley zigzag = self.lines.zigzag last_zigzag = self.lines.last_zigzag x = data[0] r = x / last_pivot_x[-1] - 1 curr_idx = len(data) - 1 trend[0] = trend[-1] last_pivot_x[0] = last_pivot_x[-1] last_pivot_t[0] = last_pivot_t[-1] last_pivot_ago[0] = curr_idx - last_pivot_t[0] zigzag_peak[0] = self.missing_val zigzag_valley[0] = self.missing_val zigzag[0] = self.missing_val last_zigzag[0] = x if trend[-1] == 0: if r >= self.p.up_retrace: piv = last_pivot_x[0] * (1 - self.p.bardist) zigzag_peak[-int(last_pivot_ago[0])] = piv zigzag[-int(last_pivot_ago[0])] = last_pivot_x[0] trend[0] = 1 last_pivot_x[0] = x last_pivot_t[0] = curr_idx elif r <= self.p.dn_retrace: piv = last_pivot_x[0] * (1 + self.p.bardist) zigzag_peak[-int(last_pivot_ago[0])] = piv zigzag[-int(last_pivot_ago[0])] = last_pivot_x[0] trend[0] = -1 last_pivot_x[0] = x last_pivot_t[0] = curr_idx elif trend[-1] == -1: if r >= self.p.up_retrace: piv = last_pivot_x[0] * (1 - self.p.bardist) zigzag_peak[-int(last_pivot_ago[0])] = piv zigzag[-int(last_pivot_ago[0])] = last_pivot_x[0] trend[0] = 1 last_pivot_x[0] = x last_pivot_t[0] = curr_idx elif x < last_pivot_x[-1]: last_pivot_x[0] = x last_pivot_t[0] = curr_idx elif trend[-1] == 1: if r <= self.p.dn_retrace: piv = last_pivot_x[0] * (1 + self.p.bardist) zigzag_peak[-int(last_pivot_ago[0])] = piv zigzag[-int(last_pivot_ago[0])] = last_pivot_x[0] trend[0] = -1 last_pivot_x[0] = x last_pivot_t[0] = curr_idx elif x > last_pivot_x[-1]: last_pivot_t[0] = curr_idx last_pivot_x[0] = x idx = 1 while idx < len(self.zigzag) and math.isnan(zigzag[-idx]): last_zigzag[-idx] = self.missing_val idx += 1 if idx < len(self.data): last_zigzag[-idx] = zigzag[-idx]
It would be great if you can advice me what to do to make my two dataframes zigzag working.
Please notice that you might have issue with loading data if you do not use FInam explorer. It is loaded easily with pip finamexporter:from finam import Exporter, Market, LookupComparator,Timeframe
-
@duni4i you did not define the timeframe and compression for data1 when adding it, for data30 you did it by defining resample data to be 30 minutes (your code resamples from 1 day data, which will not work). I hope this is your issue, since i did not run your code.
-
#print(rts) data1 = bt.feeds.PandasData(dataname=rts) print(data1) cerebro.adddata(data1,name = '1M', timeframe=bt.TimeFrame.Minutes, compression = 1) data30 = cerebro.resampledata(data1, name='data30', timeframe=bt.TimeFrame.Minutes, compression = 30) print(data30) # Add the Data Feed to Cerebro # no need to add since already added with resampledata: cerebro.adddata(data30,name = '30M')
-
@dasch thanks for your respond, but it did not
help me. Now python does not understand what i do
-
@duni4i
timeframe
parameter may be specified duringPandasData
instantiation:data = bt.feeds.PandasData(dataname=df,timeframe=...
-
@vladisld Thank you. Now data is loaded but indicator still does not work and make all data 'Nan'
-
@vladisld perhaps I'm not pretty correct but after loading 2 timeframes i see correct data for my indicator when I debug each step and I see an array with correct calculations but it is zero because when i add second timeframe indicator starts to recalculate every time when next starts and all previous data are Nan. SO my question is how to call proper calculations from my indicator and not allow it to recalculate?