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 :

    0_1498131005804_haDelta_test.png

    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.


  • administrators

    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 numpy arrays, the suspicion would be that your installation of numpy is 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)

    0_1498155427729_820414da-d0da-47f2-9cf3-921b54b0259a-image.png



  • 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.


  • administrators

    There has been some rewrite and some new functionality added, because the HeikinAshi indicator (not the filter) is defined on a recursive basis and needs to disable runonce (or else let the users find about it)

    The haDelta included will automatically instantiate a HeikinAshi indicator unless autoheikin=False. With this in mind the user doesn't have to add the HeikinAshi filter to use haDelta and several other indicators can be applied to the same data feed.

    If all indicators have to be applied to data feed with a HeikinAshi filter, then autoheikin=False will avoid the automatic invocation of the indicator.


  • administrators

    This is a chart in which the haDelta is applied to two data feeds

    • The first is the raw version and the autoheikin is left with the default value of True
    • The second is the data feed with a HeikinAshi filter and here the indicator is applied with autoheikin=False

    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.

    0_1498470675852_8686dd62-c042-45e6-883d-33ec1fb60fd2-image.png



  • 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.


  • administrators

    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 x from idx periods ago.



  • Thank you.

    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.


  • administrators

    The most challenging part of that calculation is:

    upw = dtr = false and dtr[1] and utr ;
    dnw = utr = false and utr[1] and dtr ;
    

    Because both statements seem to always yield: False

    A ver liberal interpretation would be:

    • If dtr[1] and utr[1] are not yet available (there is only 1 bar) the result will be false (or 0)


  • 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.

    The same

    upw = (not dtr) & dtr[-1] & utr
    dnw = (not dtr) & dtr[-1] & utr
    

    In Metastock:

    Assignation :=
    Comparison =


Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.