Heikin Ashi Delta indicator - Work but get warnings.
Hi. With the addition of the filter for the Heikin Ashi candles, I have written code for the Heikin Ashi Delta, which was included in the original article by Dan Valcu in the Stocks & Commodities magazine of February 2014.
The indicator works fine, but I wanted to include a colored area using _fill_gt and _fill_lt, for a better visualization of it.
When I use it it colors correctly, but I receive these two warnings:
.../python2.7/site-packages/backtrader/plot/plot.py:475: RuntimeWarning: invalid value encountered in greater kwargs['where'] = fop(y1, y2) .../python2.7/site-packages/backtrader/plot/plot.py:475: RuntimeWarning: invalid value encountered in less kwargs['where'] = fop(y1, y2)
But if I remove _fill_gt and _fill_lt, from the code, the warnings disappear.
The haDelta indicator code:
#!/usr/bin/env python # -*- coding: utf-8; py-indent-offset:4 -*- from __future__ import (absolute_import, division, print_function, unicode_literals) from backtrader import Indicator from backtrader.indicators import MovAv ''' Heikin Ashi Delta. Defined by Dan Valcu in his book "Heikin-Ashi: How to Trade Without Candlestick Patterns ". This indicator measures difference between Heikin Ashi close and open of Heikin Ashi candles, the body of the candle. To get signals add haDelta smoothed by 3 period moving average. For correct use, the data for the indicator must have been previously passed by the Heikin Ahsi filter. Formula: - haDelta = Heikin Ashi close - Heikin Ashi open - smoothed = movav(haDelta, period) ''' class haDelta(Indicator): alias = ('haD') lines = ('haDelta', 'smoothed') params = (('period', 3), ('movav', MovAv.SMA),) plotinfo = dict(subplot=True, ) plotlines = dict(haDelta=dict(color='red'), smoothed=dict(color='grey', _fill_gt=(0, 'green'), _fill_lt=(0, 'red'), ), ) def __init__(self): self.lines.haDelta = self.data.close - self.data.open self.lines.smoothed = self.p.movav(self.lines.haDelta, period=self.p.period) super(haDelta, self).__init__()
Chart of a test :
I know it is not very relevant, but by debugging the code and by the way learn something about plot in Backtrader, any idea of why the warnings?
And if you consider it appropriate, it could be incorporated into the Backtrader indicators.
The chart below is made with an unmodified copy of your indicators (and using the same data source)
No warnings at all. Because the filling is done using
numpyarrays, the suspicion would be that your installation of
numpyis the one producing the warnings.
In any case it is difficult to imagine which values could actually be wrong there (there are no 'NaN' values)
As I said, except for the warnings the indicator works well.
I'm glad to know that the indicator did not give you any warnings when using it.
I'll test it in another environment.
Thanks for checking it.
There has been some rewrite and some new functionality added, because the
HeikinAshiindicator (not the filter) is defined on a recursive basis and needs to disable
runonce(or else let the users find about it)
haDeltaincluded will automatically instantiate a
autoheikin=False. With this in mind the user doesn't have to add the
HeikinAshifilter to use
haDeltaand several other indicators can be applied to the same data feed.
If all indicators have to be applied to data feed with a
autoheikin=Falsewill avoid the automatic invocation of the indicator.
This is a chart in which the
haDeltais applied to two data feeds
- The first is the raw version and the
autoheikinis left with the default value of
- The second is the data feed with a
HeikinAshifilter and here the indicator is applied with
No difference is appreciated except for the 1st bar. That's because the indicator declares a minimum period of 2 (to account for the recursive definition of
ha_open) where the filter simply takes the values from the data feed to create a 1st artificial bar.
- The first is the raw version and the
This is great!
I was trying to code the HACO indicator and the HACOLT, which use both price series data, and the opening and closing of Heikin Ashi candles. For which I had written a similar code, but this way you raise is simpler.
Thanks for including the haDelta in Backtrader.
This is apparently the original calculation (Source)
In this formula I am using the heikin ashi average closing price: haC haOpen:=(Ref((O+H+L+C)/4,-1) + PREV)/2; haC:=((O+H+L+C)/4+haOpen+Max(H,haOpen)+Min(L,haOpen))/4; This is the HACO digital formula: HACO avg:=Input("Up TEMA average: ",1,100,34); avgdn:=Input("Down TEMA Average: ",1,100,34); haOpen:=(Ref((O+H+L+C)/4,-1) + PREV)/2; haC:=((O+H+L+C)/4+haOpen+Max(H,haOpen)+Min(L,haOpen))/4; TMA1:= Tema(haC,avg); TMA2:= Tema(TMA1,avg); Diff:= TMA1 - TMA2; ZlHa:= TMA1 + Diff; TMA1:= Tema((H+L)/2,avg); TMA2:= Tema(TMA1,avg); Diff:= TMA1 - TMA2; ZlCl:= TMA1 + Diff; ZlDif:=ZlCl-ZlHa; keep1:=Alert(haC>=haOpen,2); keep2:=ZlDif>=0; keeping:=(keep1 OR keep2); keepall:=keeping OR (Ref(keeping,-1) AND (C>=O) OR C>=Ref(C,-1)); keep3:=(Abs(C-O)<(H-L)*.35 AND H>=Ref(L,-1)); utr:=Keepall OR (Ref(keepall,-1) AND keep3); TMA1:= Tema(haC,avgdn); TMA2:= Tema(TMA1,avgdn); Diff:= TMA1 - TMA2; ZlHa:= TMA1 + Diff; TMA1:= Tema((H+L)/2,avgdn); TMA2:= Tema(TMA1,avgdn); Diff:= TMA1 - TMA2; ZlCl:= TMA1 + Diff; ZlDif:=ZlCl-ZlHa; keep1:=Alert(haC<haOpen,2); keep2:=ZlDif<0; keep3:=Abs(C-O)<(H-L)*.35 AND L<=Ref(H,-1); keeping:=keep1 OR keep2; keepall:=keeping OR (Ref(keeping,-1) AND (C<O) OR C<Ref(C,-1)); dtr:=If(Keepall OR (Ref(keepall,-1) AND keep3)=1,1,0); upw:=dtr=0 AND Ref(dtr,-1) AND utr; dnw:=utr=0 AND Ref(utr,-1) AND dtr; result:=If(upw,1,If(dnw,0,PREV)); result
Without having ever spoken Metastock it seems that
Ref(x, -idx)returns the value for the given
I get the formula here, there are for several frameworks.
I have some problems with the code, I will try to solve when have more time.
The most challenging part of that calculation is:
upw = dtr = false and dtr and utr ; dnw = utr = false and utr and dtr ;
Because both statements seem to always yield:
A ver liberal interpretation would be:
utrare not yet available (there is only 1 bar) the result will be
That I thought, Pythonized:
upw = dtr==false and dtr[-1] and utr dnw = utr==false and dtr[-1] and dtr
Meaning upw is true if current dtr is false and utr is true and the previous dtr is false. This would mark an upward trend change.
upw = (not dtr) & dtr[-1] & utr dnw = (not dtr) & dtr[-1] & utr