bar number is greater than length
-
how we can check bar number is greater than length in init
actually i want to perform this piece of code but i am facing issue "object has no attribute 'bar_executed"if (self.bar_executed) > len(self): self.haop1 = (self.open(-1) + self.close(-1)) / 2.0 else: self.haop1 = (self.hacl1(-1) + self.haop1(-1)) / 2.0
-
You haven't defined
self.bar_executed
. If it's a parameter thenself.p.bar_executed
. If defined in init then make sure there's a self in front. -
@run-out
i am executing if bar len is less then 2 so execute if part otherwise execute else part but script all run if part never goes in else part what's wrong i am doingself.haop1 = (self.open(-1) + self.close(-1)) / 2.0 if(len(self)<=2): self.haop1 = self.haop1 else: self.haop1 = (self.hacl1(-1) + self.haop1(-1)) / 2.0
-
@mudassar031 said in bar number is greater than length:
len(self)
I assume that
len(self)
ininit()
is zero. Length is increasing on eachnext()
call. -
@ab_trader
yes in next function i can get len value is there any way to do in init() -
@ab_trader
as placed question many time no reply
i want to calculate compound valuei need to convert this in backtrader and want to calculate ha_open like this
-
@mudassar031
here is my full code can you please let me know which part i need to execute in init and which in next function
i spent lot of time on it please helpimport backtrader as bt class TOS(bt.Strategy): lines = ('super_trend',) params = (('ST_Period', 15),('ST_Coeff', 3),) plotlines = dict(super_trend=dict(_name='ST',color='blue',alpha=1)) def log(self, txt, dt=None): ''' Logging function for this strategy''' dt = dt or self.datas[0].datetime.datetime(0) print('%s, %s' % (dt.isoformat(), txt)) def __init__(self): self.open = self.data.open self.close = self.data.close self.high = self.data.high self.low = self.data.low self.finalUp1 = [0] self.finalDn1 = [0] self.st = [0] #calculate HAcl1 self.hacl1 = (self.open+self.high+self.low+self.close)/4 # calculate compoundvalue self.haop1 = (self.open(-1) + self.close(-1)) / 2.0 if(len(self)<=2): self.haop1 = self.haop1 else: self.haop1 = (self.hacl1(-1) + self.haop1(-1)) / 2.0 #max value self.hahi1 = bt.Max(self.open, bt.Max(self.hacl1,self.haop1)) #min value self.halo1 = bt.Min(self.low, bt.Min(self.hacl1,self.haop1)) #avg of self.hahi1 and self.halo1 self.hahl2_1 = (self.hahi1 + self.halo1) / 2 self.trueRange = bt.Max(self.hahi1, self.hacl1, self.halo1) # True range is equal to the greatest of these values self.newTrueRange = bt.Max( abs(self.hahi1 - self.halo1), abs(self.hahi1 - self.hacl1), abs(self.halo1 - self.hacl1) ) # End manual TrueRange self.atr = ((self.newTrueRange)/self.params.ST_Period) self.iATR1 = (self.atr-1)*((self.params.ST_Period-1)/self.params.ST_Period) self.tmpUp1 = self.hahl2_1 - (self.params.ST_Coeff * self.iATR1); # hahl2 is better than hl2 self.tmpDn1 = self.hahl2_1 + (self.params.ST_Coeff * self.iATR1); # hahl2 is better than hl2 #self.hma = bt.indicators.SmoothedMovingAverage(self.high, period=self.params.ST_Period) def next(self): self.log(f"Number of bars {len(self)}") pre_upband = self.finalUp1[0] pre_lowband = self.finalDn1[0] if self.close[-1] > self.finalUp1[-1]: self.finalUp1[0] = max(self.tmpUp1[0], self.finalUp1[-1]) else: self.finalUp1[0] = self.tmpUp1[0] if self.close[-1] < self.finalDn1[-1]: self.finalDn1[0] = min(self.tmpDn1[0], self.finalDn1[-1]) else: self.finalDn1[0] = self.tmpDn1[0] #self.lines.super_trend[0] = self.finalUp1[0] # Simply log the closing price of the series from the reference self.log('Open: %.2f ' 'Close: %.2f ' 'High: %.2f ' 'Low: %.2f ' 'Hacl1: %.2f ' 'haop1: %.2f ' 'hahi1: %.2f ' 'halo1: %.2f ' 'hahl2_1: %.2f ' 'tr: %.2f ' 'newtr: %.2f ' 'iATR1: %.2f ' 'tmpUp1: %.2f ' 'tmpDn1: %.2f ' 'finalUp1: %.2f ' 'finalDn1: %.2f ' % (self.open[0], self.close[0], self.high[0], self.low[0], self.hacl1[0], self.haop1[0], self.hahi1[0], self.halo1[0], self.hahl2_1[0], self.trueRange[0], self.newTrueRange[0], self.iATR1[0], self.tmpUp1[0], self.tmpDn1[0], self.finalUp1[0], self.finalDn1[0] ) )
-
This is an indicator which returns
CompoundValue
based on the description from your post:class CompoundValue(bt.Indicator): ''' Calculates a compound value according to following rule: if a bar number is greater than `length` then the `data1` value is returned, otherwise the `data2` value is returned (Thinkorswim). ''' lines = ('value',) params = (('length', 1), ('data1', None), ('data2', None),) def __init__(self): pass def next(self): if len(self) <= self.p.length: self.lines.value[0] = self.p.data2[0] else: self.lines.value[0] = self.p.data1[0]
-
This is general approach. Parameters
data1
anddata2
can be removed and the indicator can be simplified, if it is known thatdata1
anddata2
are the data feeds. -
Unfortunately, I understood the idea wrong, that script is incorrect.
-
There is Heikin Ashi indicator in the
bt
which returns HA open, close, high and low values. Why don't you use it? -
@ab_trader
i have to interpret this HeikinAshi + SuperTrend Strategy in Backtrader
https://github.com/sureshja/ThinkOrSwim/blob/master/HeikinAshiSuperTrendStrategy.ts -
@ab_trader
Parameters data1 and data2 can be removed and the indicator can be simplified can you please can any example -
@mudassar031 said in bar number is greater than length:
give any example
-
The part that is concerning you is the ComoundValue part of the equation. In the link you provide to stackoverflow "Understanding & Converting ThinkScripts CompoundValue Function" the post illustrates how CompoundValue works. It's purpose is to provide initial parameters for a recursive formula. They use a fibonocci formula as an example. Heikin ashi also requires such initial parameters.
From the code you are trying to copy, here is the CompoundValue code:
def haop1 = CompoundValue(1, (haop1[1] + hacl1[1]) / 2, (open(period = aggrPd1)[1] + close(period = aggrPd1)[1]) / 2);
You can see here that if the bar is 1 then the formula uses the open and close values at 1, but if not then it uses the previous values, since the seed values are now set.
It has been mentioned to you several times in this question and another that backtrader has a heikin ashi indicator. I'm wondering if you have investigated it to see if the values match your tradingview indicator? If you look a the formual for the backtrader heikin ashi you will find the main body the following:
def __init__(self): o = self.data.open h = self.data.high l = self.data.low c = self.data.close self.l.ha_close = ha_close = (o + h + l + c) / 4.0 self.l.ha_open = ha_open = (self.l.ha_open(-1) + ha_close(-1)) / 2.0 self.l.ha_high = bt.Max(h, ha_open, ha_close) self.l.ha_low = bt.Min(l, ha_open, ha_close) super(HeikinAshi, self).__init__()
This is the seeded part of the formula. But if you look way down to the bottom, you'll also find this:
def prenext(self): # seed recursive value self.lines.ha_open[0] = (self.data.open[0] + self.data.close[0]) / 2.0
Which is backtrader's alread built in 'CompoundValue' part of the formula. The two formulas are the same and should work.
-
@mudassar031 said in bar number is greater than length:
i have to interpret this HeikinAshi + SuperTrend Strategy in Backtrader
https://github.com/sureshja/ThinkOrSwim/blob/master/HeikinAshiSuperTrendStrategy.tsI understand that. The code by the link has two parts: HA candles calculations and SuperTrend calculations. HA candles is already in the
bt
and can be used as an indicator or as a data feed. In other words this part of the TS code is inbt
already:# Heikin Ashi Stuff # Working off of HA open, high, low, close def hacl1 = ( open(period = aggrPd1) + high(period = aggrPd1) + low(period = aggrPd1) + close(period = aggrPd1) ) / 4; def haop1 = CompoundValue(1, (haop1[1] + hacl1[1]) / 2, (open(period = aggrPd1)[1] + close(period = aggrPd1)[1]) / 2); def hahi1 = Max( open(period = aggrPd1), Max( hacl1, haop1 ) ); def halo1 = Min( low(period = aggrPd1), Min( hacl1, haop1 ) );
Then you apply SuperTrend calculations to HA candles and it is done.
CompoundValue
formula is not required, sincebt
HA candles are calculated without it. -
@run-out
i have tried backtrader heikin ashi main body instead of our custom codeself.l.ha_open = ha_open = (self.l.ha_open(-1) + ha_close(-1)) / 2.0
this line of code always return "nan"
-
@mudassar031
resolve it by using prenext function to seed recursive value