Indicators: Hull moving average

 

Hull moving average:

Hull moving average

Hull moving average

Author: Mladen Rakic 

Hull moving average
Hull moving average
  • www.mql5.com
Since then the HMA has found its way into charting programs around the world and is regularly discussed on traders bulletin boards in different languages around the world. It was the result of an intellectual curiosity which I placed into the public domain by writing the following article Alan Hul Hull Moving Average. The Hull Moving Average...
 
Thank you
 
Automated-Trading:

Hull moving average:

Author: Mladen Rakic

Is there an EA for this ?

thank you

 
Automated-Trading:

Hull moving average:

Author: Mladen Rakic

Thank you for sharing this very nice indicator code.

I have performed some minor improvements concerning speed, memory (and numerical errors) while not changing the behavior:

** In the class CHull I use circular buffers in order to have constant (non increasing) memory usage (at least in this class)

** I made the initialization also recursive (when the number of available bars is less than m_fullPeriod) in order to increase initialization speed when m_fullPeriod is large.

** At least theoretically numerical errors accumulate in the course of time (although nobody of us will live anymore until errors would be large enough to be a problem).
   For the sake of some perfectionism I programmed a mechanism to avoid accumulation of numerical errors.
   The execution speed gets only negligibly slower.

LEO.org
LEO.org
  • dict.leo.org
Lernen Sie die Übersetzung für 'SUCHWORT' in LEOs Englisch ⇔ Deutsch Wörterbuch. Mit Flexionstabellen der verschiedenen Fälle und Zeiten ✓ Aussprache und relevante Diskussionen ✓ Kostenloser Vokabeltrainer ✓
Files:
 

Nice work. Thanks

PS: since it was only yesterday that I claimed that circular / ring buffers code is (in my opinion) over-complicated in almost all cases, here is my implementation that can show one possible different way that it really does not need to be complicated at all

 

You are right, your code with a circular buffer is really much simpler than mine.

Because I do not use an array for the wsum and lsum at all, I must restore the old values in a complicated way

if the new "value" is not for a new bar but replaces just the last bar's value.

But some of my lengthly code comes from the faster initialization and the avoiding of numerical error accumulation.

 

Sorry, but I fail to see how this :

      bool init(int period, double divisor)
      {
            m_fullPeriod = (int)(period>1 ? period : 1);  
            m_halfPeriod = (int)(m_fullPeriod>1 ? m_fullPeriod/(divisor>1 ? divisor : 1) : 1);
            m_sqrtPeriod = (int) MathSqrt(m_fullPeriod);
            m_weight1 = m_weight2 = m_weight3 = 1; 
               m_arraySize  = ArrayResize(m_array,m_fullPeriod+1);
               return(m_arraySize==(m_fullPeriod+1));
      }

is slower than this :

      bool init(int period, double divisor)
      {
            m_fullPeriod = (int)(period>1 ? period : 1);
            m_halfPeriod = (int)(m_fullPeriod>1 ? m_fullPeriod/(divisor>1 ? divisor : 1) : 1);
            m_sqrtPeriod = (int) sqrt(m_fullPeriod);

            _2invWeight1 = 4.0 / (m_halfPeriod*(m_halfPeriod+1));
            invWeight2 = 2.0 / (m_fullPeriod*(m_fullPeriod+1));
            invWeight3 = 2.0 / (m_sqrtPeriod*(m_sqrtPeriod+1));

            lsum1 = lsum2 = lsum3 = wsum1 = wsum2 = wsum3 = 0;
            wsum1_recalc = wsum2_recalc = wsum3_recalc = 0;
            idxfull = 0;
            idxsqrt = 0;
            countfull = 0;
            countsqrt = 0;
            ArrayResize(value, m_fullPeriod);
            ArrayResize(value3, m_sqrtPeriod);
            int i;
            for(i=0; i<m_fullPeriod; i++)
               value[i] = 0;
            for(i=0; i<m_sqrtPeriod; i++)
               value3[i] = 0;
            nr_calculated = 0;
            recalc_period = 10 * m_fullPeriod;
            recalc_count = recalc_period;
            return(true);
      }

In any case, thanks for posting your code (it seems that these days we chronically lack code posters :))

 
Mladen Rakic:

Sorry, but I fail to see how this :

is slower than this :

In any case, thanks for posting your code (it seems that these days we chronically lack code posters :))

I expressed myself unclear. Of course, your init() function is faster.

But with "initialization" I meant the calculation of the first "m_fullPeriod" indicator values.

This is done only after attaching the indicator to the chart or after changing the parameters.

In your code for every indicator value (with i <= m_fullPeriod) the following two loops must

be executed:

for(int k=0, w1=m_halfPeriod, w2=m_fullPeriod; w2>0 && i>=k; k++, w1--, w2--)

   .............

for(int k=0, w3=m_sqrtPeriod; w3>0 && i>=k; k++, w3--)

   ...............

In my code there is no loop in this "initialization" phase (for nr_calculated <= m_fullPeriod in my code)

and so only a constant amount of computation time is needed for every indicator value.

 
winloosewin:

I expressed myself unclear. Of course, your init() function is faster.

But with "initialization" I meant the calculation of the first "m_fullPeriod" indicator values.

This is done only after attaching the indicator to the chart or after changing the parameters.

In your code for every indicator value (with i <= m_fullPeriod) the following two loops must

be executed:

for(int k=0, w1=m_halfPeriod, w2=m_fullPeriod; w2>0 && i>=k; k++, w1--, w2--)

   .............

for(int k=0, w3=m_sqrtPeriod; w3>0 && i>=k; k++, w3--)

   ...............

In my code there is no loop in this "initialization" phase (for nr_calculated <= m_fullPeriod in my code)

and so only a constant amount of computation time is needed for every indicator value.

That (the initial summing) is done in a loop only for maximum hull period first bars - after that the calculation does all that without any loop and that can not be avoided (otherwise you are falling into initial values  approximation)

In any case (since those are classes) it is easily portable to mt5 and then you can test it in profiler. The comparisons (both used on same sample data and same conditions) - you can easily do the same tests - quite frankly I find that tool quite good, since it does not depend on our subjective opinion but is cold blooded counter and timer :)

I rest my case now. The purpose of my posting was to post one very simple way of using circular / ring buffers. Since that is done and since it seems that we have explained all that can be explained regarding that now, I leave to you guys to decide what ways you want to use in your own coding


 

I have not claimed that my code is generally faster than yours.

I have only claimed that in the "initialization" phase it is. And I leave you the right to say that your code is a bit faster after the initialization phase.

What the initialization concerns: If you choose for some reason a high value for "period" then

you can see that your indicator needs some perceptible time to be uasble after attaching it to a chart or after changing the parameters.

But I have never claimed that your initialization code would be bad and mine would be good. The initialization time of your indicator

is tolerable even for "reasonable" high period values.

I think it's not worth further disputing about this.

I have hoped that the reader of my comments sees that the motivation for writing my version of the code is also a bit because of theoretical interest - e.g. I

have told that in this application the small accumulation of numerical errors are not really a problem even after a longer time.

But I wanted to investigate - at first for myself - if it is possible to avoid accumulation of numerical errors - to a price of increasing the computation time

by maximal a constant factor.

 

I have found a bug in my code. It only occurs if "period" is very large (e.g. 50000) (due to an integer overflow).

I have a corrected version in the attachment.

I have an EA that indeed uses both smaller and larger periods. You may call iCustom() with a timeframe that is bigger than the one the

EA is attached to if you do not need the indicator be drawn on the chart. Then the "period" parameter could be respectively smaller.

But I prefer to leave the user the freedom whether to do so or just use the indicator with a higher "period" parameter.

The original code of mladen takes several minutes longer at the begin of the test of the EA in the strategy tester if "period" is set high

(e.g. 50000).

Files:
Reason: