For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
2019-10-02: The community is currently in read-only mode

Develop Heikinashi Indicators

• Thank you for develop best backtrading app!

I have problem when I develop Heikin-Ashi Indicators.
I can't get value that i want.
when i want develop autocorrelation indicators, what should I do?

My code show below

from datetime import datetime
import backtrader as bt

class HeikinAshi(bt.indicators.PeriodN):
"""
Heikin Ashi candlesticks:

Parameter:
No needs

Description:
Heikin-Ashi candlesticks are a weighted version of candlesticks calculated with the following formula

Formula:
h_close = (open + high + low + close) / 4
h_high = maximum of high, open, or close (whichever is highest)
h_low = minimum of low, open, or close (whichever is lowest)
h_open = (open of previous bar + close of previous bar) / 2

https://en.wikipedia.org/wiki/Candlestick_chart#Heikin_Ashi_candlesticks
http://stockcharts.com/school/doku.php?id=chart_school:chart_analysis:heikin_ashi
"""
lines = ('signal', 'ha_close', 'ha_open')

def __init__(self):
super(HeikinAshi, self).__init__()

open = self.data.open
high = self.data.high
low = self.data.low
close = self.data.close

self.ha_close = (open + high + low + close) / 4
# h_high = bt.Max(open, high, low, close)
# h_low = bt.Min(open, high, low, close)
self.ha_open = (self.ha_open(-1) + self.ha_close(-1)) / 2

def next(self):
print(self.ha_open)  # <- Value is 'nan', I wanna numeric

class NoStrategy(bt.Strategy):
def __init__(self):
HeikinAshi(self.data)

if __name__ == '__main__':
cerebro = bt.Cerebro()
data0 = bt.feeds.YahooFinanceData(dataname='YHOO', fromdate=datetime(2011, 1, 1),
todate=datetime(2012, 12, 31))

cerebro.run()
#cerebro.plot()

• I resolve by myself :D

I use once method instead of next.

from datetime import datetime
import backtrader as bt

class HeikinAshi(bt.Indicator):
"""
Heikin Ashi candlesticks:

Parameter:
No needs

Description:
Heikin-Ashi candlesticks are a weighted version of candlesticks calculated with the following formula

Formula:
h_close = (open + high + low + close) / 4
h_high = maximum of high, open, or close (whichever is highest)
h_low = minimum of low, open, or close (whichever is lowest)
h_open = (open of previous bar + close of previous bar) / 2

https://en.wikipedia.org/wiki/Candlestick_chart#Heikin_Ashi_candlesticks
http://stockcharts.com/school/doku.php?id=chart_school:chart_analysis:heikin_ashi
"""
lines = ('signal', 'ha_close', 'ha_open')

def __init__(self):
super(HeikinAshi, self).__init__()

open = self.data.open
high = self.data.high
low = self.data.low
close = self.data.close

self.ha_close = (open + high + low + close) / 4
# h_high = bt.Max(open, high, low, close)
# h_low = bt.Min(open, high, low, close)

def once(self, start, end):
ha_close = self.ha_close.array
ha_open = self.ha_open.array

for i in range(start, end):
if i == 1:
ha_open[i] = self.data.open
else:
ha_open[i] = (ha_open[i - 1] + ha_close[i - 1]) / 2

class NoStrategy(bt.Strategy):
def __init__(self):
HeikinAshi(self.data)

if __name__ == '__main__':
cerebro = bt.Cerebro()
data0 = bt.feeds.YahooFinanceData(dataname='YHOO', fromdate=datetime(2011, 1, 1),
todate=datetime(2012, 12, 31))

cerebro.run()
#cerebro.plot()

• I noticed simple code below.
I think once method doesn't work when I use resampledata.

def __init__(self):
super(HeikinAshi, self).__init__()
open = self.data.open
high = self.data.high
low = self.data.low
close = self.data.close

self.ha_open = open

self.ha_close = (open + high + low + close) / 4
# h_high = bt.Max(open, high, low, close)
# h_low = bt.Min(open, high, low, close)
self.ha_open = (self.ha_open(-1) + self.ha_close(-1)) / 2

•     self.ha_open = (self.ha_open(-1) + self.ha_close(-1)) / 2

def next(self):
print(self.ha_open)  # <- Value is 'nan', I wanna numeric

The initial problem here is:

• ha_open(-1) needs a seed value which is not being provided and the recursive calculation fails

As such, the only value the platform can fill in advance is NaN and any calculation with Nan will return the same.

A seed value could be provided during nextstart or oncestart. It is what the ExponentialMovingAverage for example does, by using a SimpleMovingAverage as the seed value.

def once(self, start, end):
ha_close = self.ha_close.array
ha_open = self.ha_open.array

for i in range(start, end):
if i == 1:
ha_open[i] = self.data.open
else:
ha_open[i] = (ha_open[i - 1] + ha_close[i - 1]) / 2

Same here. oncestart is the one in which ha_open should be seeded and not here.

But the major problem is here:
@santa3 said in Develop Heikinashi Indicators:

self.ha_close = (open + high + low + close) / 4
self.ha_open = (self.ha_open(-1) + self.ha_close(-1)) / 2

Because the calculations are not being assigned to the lines but simply to an attribute of the class. This should be

>         self.lines.ha_close = (open + high + low + close) / 4
>         self.lines.ha_open = (self.lines.ha_open(-1) + self.lines.ha_close(-1)) / 2

Which still doesn't solve the problem of the recursive calculation and the seed. And in this case oncestart or nextstart wouldn't be good because the calculation is over when they are seen and the seed used for the calculation is NaN already. In any case the problem can be solved by seeding during the entire prenext phase.

def prenext(self):
self.lines.ha_open = self.data.open

When the indicator moves to next, there will be something at index [-1], because values were recorded in the appropriate line by prenext.

• This indicator is now in the development branch

});