Can BT resample the data in the user defined Indicator?
-
For example, I would define a Indicator with 5-mins bar data, but in the indicator I need the day time frame ATR(100days),then I would compare the 5-min bar data with the Day time frame ATR(100). how can I get the day timeframe ATR with the 5min bar?
-
- define 2 data feeds - 5 min
data1
and dailydata2
. - calculate ATR using daily data feed
self.atr = bt.indicators.ATR(self.datas[1], period=100)
- use
self.atr
in the other indicator
self.other_indicator = bt.indicators.SMA(self.datas[0], period=50) + self.atr
This can be done in the strategy
__init__
or other indicator__init__
. - define 2 data feeds - 5 min
-
@ab_trader Thanks, I knew this method, and I used the resampling method with one data feed.It worked well. I think Both methods are coupling the indicators with different time frame.
But is it possible to define a new indicator to including the logic, not as your logic in the user defined Strategy?
-
Can BT resample the data in the user defined Indicator?
The direct answer to the question posed in the title: No.
Indicators DO NOT touch the data, they calculate something using the provided data feeds.
You can always pass two data feeds to the indicator (one
5-min
and another1-day
) and create indicators on each of them and compare things (directly between indicators or data-vs-indicator) -
@backtrader Thanks.
How can I implement below logic(in the TradingView) in the BT, I know I can use ab_trader's method, but seems too much logic in the Strategy, How can I put these logic in a Indicator instead of Strategy? The ATR is a Day timeframe indicator, the others are mins:
code ref from linkstudy(title='[RS]MTF Volatility Stop V0', shorttitle='mtfVS', overlay=true) multiplier = input(title='True Range Multiplier', type=float, defval=1.618) tf = input(title='Timeframe to pool ATR:', type=string, defval='D', confirm=false) length = input(title='ATR Length', type=integer, defval=20, minval=1) range = security(tickerid, tf, atr(length)) trend = na(trend[1]) ? +1 : close > vstop[1] ? +1 : close < vstop[1] ? -1 : trend[1] max_close = change(trend) != 0 ? close : close >= max_close[1] ? close : max_close[1] min_close = change(trend) != 0 ? close : close <= min_close[1] ? close : min_close[1] vstop = na(vstop[1]) ? hl2 : change(trend) > 0 ? close - (multiplier * range) : trend > 0 ? max(vstop[1], max_close - (multiplier * range)) : change(trend) < 0 ? close + (multiplier * range) : trend < 0 ? min(vstop[1], min_close + (multiplier * range)) : vstop[1] plot(title='mtfVS', series=vstop, style=circles, color=close>=vstop?lime:red, transp=0, linewidth=2) plot(title='mtfVS', series=vstop, style=line, color=black, transp=0, linewidth=1)
-
@backtrader @ab_trader
I finally implement the Indicator as below code, it seems work. but two small questions, when the ATR is coupled? and how do I set the minperiod when data with different time frames, I worked around by using len(self.l.art)>0, else it would raise errors.import numpy as np import backtrader as bt from ext.ult.ult import * from ext.Ind.OCHLInd import OCHLInd # https://www.tradingview.com/script/mtWhbCRf-RS-MTF-Volatility-Stop-V0/ class MtfVSInd(bt.Indicator): """ """ lines = ('trend', 'vs', 'max_close', 'min_close', 'atr') params = ( ('period', 5), ('factor', 1.618), ('mode', 0) # debug modes ) plotinfo = dict(subplot=False) plotlines = dict(vs=dict(_plotskip=False), trend=dict(_plotskip=True, _method='bar', alpha=0.50, width=1.0), max_close=dict(_plotskip=True, color='black'), min_close=dict(_plotskip=True, color='red'), atr=dict(_plotskip=True), ) def _plotinit(self): if self.p.mode == 1: self.plotinfo.subplot = True self.plotlines.vs._plotskip = True self.plotlines.trend._plotskip = True self.plotlines.max_close._plotskip = True self.plotlines.min_close._plotskip = True self.plotlines.atr._plotskip = False elif self.p.mode == 2: self.plotinfo.subplot = True self.plotlines.vs._plotskip = True self.plotlines.trend._plotskip = False self.plotlines.max_close._plotskip = True self.plotlines.min_close._plotskip = True self.plotlines.atr._plotskip = True elif self.p.mode == 3: self.plotinfo.subplot = True self.plotlines.vs._plotskip = True self.plotlines.trend._plotskip = True self.plotlines.max_close._plotskip = False self.plotlines.min_close._plotskip = False self.plotlines.atr._plotskip = True def __init__(self): # the ATR is Day time frame self.l.atr = bt.ind.ATR(self.data1, period=self.p.period) # get the avg(high+low) self.hl = OCHLInd(self.data0, type='hl') super(MtfVSInd, self).__init__() def next(self): if len(self.l.atr) > 0: if np.isnan(self.l.trend[-1]): self.l.trend[0] = 1 elif self.data0.l.close[0] > self.l.vs[-1]: self.l.trend[0] = 1 elif self.data0.l.close[0] < self.l.vs[-1]: self.l.trend[0] = -1 else: self.l.trend[0] = self.l.trend[-1] chg_trend = self.l.trend[0] - self.l.trend[-1] if chg_trend != 0: self.l.max_close[0] = self.data0.l.close[0] elif self.data0.l.close[0] >= self.l.max_close[-1]: self.l.max_close[0] = self.data0.l.close[0] else: self.l.max_close[0] = self.l.max_close[-1] if chg_trend != 0: self.l.min_close[0] = self.data0.l.close[0] elif self.data0.l.close[0] <= self.l.min_close[-1]: self.l.min_close[0] = self.data0.l.close[0] else: self.l.min_close[0] = self.l.min_close[-1] if np.isnan(self.l.vs[-1]): self.l.vs[0] = self.hl[0] elif chg_trend > 0: self.l.vs[0] = self.data0.l.close[0] - self.p.factor * self.l.atr[0] elif self.l.trend[0] > 0: self.l.vs[0] = max(self.l.vs[-1], self.l.max_close[0] - self.p.factor * self.l.atr[0]) elif chg_trend < 0: self.l.vs[0] = self.data0.l.close[0] + self.p.factor * self.l.atr[0] elif self.l.trend[0] < 0: self.l.vs[0] = min(self.l.vs[-1], self.l.min_close[0] + self.p.factor * self.l.atr[0]) else: self.l.vs[0] = self.l.vs[-1]