You could read out the iMA values one by one into two buffers, say IMA_P2 (for period/2) and IMA_P1. Upon initialisation it's quite a big chunk, but later on it will be only one additional value that needs to be added to the arrays for every time frame switch.
Question remains, how to detect a time frame switch according to _tf (assuming for simplicity that _tf is always the same.) MQL5 has BarsCalculated(ind_handle) but in MQL4 there's only IndicatorCounted(), and I think that one works inside indicators only.
However once you got the buffers, the first For loop - which is apparently the workhorse - should be much faster:
for( _index = _arraySize-1; _index >= 0; _index-- ) vector[_index]= 2 * IMA_P2[_index] - IMA_P1[_index];
You could read out the iMA values one by one into two buffers, say IMA_P2 (for period/2) and IMA_P1. Upon initialisation it's quite a big chunk, but later on it will be only one additional value that needs to be added to the arrays for every time frame switch.
Question remains, how to detect a time frame switch according to _tf (assuming for simplicity that _tf is always the same.) MQL5 has BarsCalculated(ind_handle) but in MQL4 there's only IndicatorCounted(), and I think that one works inside indicators only.
However once you got the buffers, the first For loop - which is apparently the workhorse - should be much faster:
Thanks for the reply.
I am not completely sure what do you mean because everytime I call the HMA function it would calculate everything again.
I can think of one way to calculate the HMA when there is a new bar by evaluating when a new bar opens using iTime()
Fernando Morales:
1. I am not completely sure what do you mean because everytime I call the HMA function it would calculate everything again.
2. I can think of one way to calculate the HMA when there is a new bar by evaluating when a new bar opens using iTime()
1. Yes, every call to HMA would calculate everything again. But the difference now is that all iMA values have been cached into arrays IMA_P1 and IMA_P2. This saves two calls to the iMA function per loop iteration.
2. Right, you could detect a shift in the timeframe _tf by observing iTime(NULL,_tf,0) and on change calculate the values for the new bars. Good idea!
I think it can be done. What's now required is:
-
Declaration of IMA_P1 and IMA_P2 as double[] dynamic arrays
- OnInit(): Calculate the number of bars you want to go into the past, for simplicity say it's 100. For (i<100), read iMA(NULL,_tf,_period/2,i) into IMA_P2 and iMA(NULL,_tf,_period,i) into IMA_P1. Remember iTime(NULL,_tf,0).
- OnTick(): if iTime(NULL,_tf,0) differs from last return value, read new iMA values into IMA_P2 and IMA_P1 (resize and shift before).
- HMA(): Replace loop body as suggested earlier:
for( _index = _arraySize-1; _index >= 0; _index-- ) vector[_index]= 2 * IMA_P2[_index] - IMA_P1[_index];
1. Yes, every call to HMA would calculate everything again. But the difference now is that all iMA values have been cached into arrays IMA_P1 and IMA_P2. This saves two calls to the iMA function per loop iteration.
2. Right, you could detect a shift in the timeframe _tf by observing iTime(NULL,_tf,0) and on change calculate the values for the new bars. Good idea!
I think it can be done. What's now required is:
-
Declaration of IMA_P1 and IMA_P2 as double[] dynamic arrays
- OnInit(): Calculate the number of bars you want to go into the past, for simplicity say it's 100. For (i<100), read iMA(NULL,_tf,_period/2,i) into IMA_P2 and iMA(NULL,_tf,_period,i) into IMA_P1. Remember iTime(NULL,_tf,0).
- OnTick(): if iTime(NULL,_tf,0) differs from last return value, read new iMA values into IMA_P2 and IMA_P1 (resize and shift before).
- HMA(): Replace loop body as suggested earlier:
Thanks again for your inputs.
From what I understood from your suggestion I updated the code. Not working at this moment but I want to confirm that I got it right.
int OnInit() { CacheMAs(); return(INIT_SUCCEEDED); } void OnTick() { if ( !IsNewBar(PERIOD_M15) ) return; CacheMAs(); } double HMA( int _period, double& _MA1[], double& _MA2[], int _shift ) { int _index = 0; int p = (int)MathSqrt(_period); double vector[]; double ExtMapBuffer[]; if ( Bars < MAarraySize ) Alert("Not enough bars in the chart. Minimum expected is ", MAarraySize); ArrayResize( vector, MAarraySize ); ArraySetAsSeries(vector,true); ArrayResize( ExtMapBuffer, MAarraySize ); ArraySetAsSeries(ExtMapBuffer,true); for( _index = MAarraySize-1; _index >= 0; _index-- ) vector[_index]= 2 * _MA1[_index] - _MA2[_index]; for( _index = 0; _index < MAarraySize - _period; _index++) ExtMapBuffer[_index] = iMAOnArray( vector,0, p, 0, MODE_LWMA, _index ); return( ExtMapBuffer[_shift] ); } double IMA1fastA[], IMA1fastB[]; double IMA2fastA[], IMA2fastB[]; double IMA1slowA[], IMA1slowB[]; double IMA2slowA[], IMA2slowB[]; int MAarraySize = HMAperiod_slow_1 * HMAperiod_slow_2; void CacheMAs() { ArrayResize( IMA1fastA, MAarraySize ); ArrayResize( IMA1fastB, MAarraySize ); ArrayResize( IMA2fastA, MAarraySize ); ArrayResize( IMA2fastB, MAarraySize ); ArrayResize( IMA1slowA, MAarraySize ); ArrayResize( IMA1slowB, MAarraySize ); ArrayResize( IMA2slowA, MAarraySize ); ArrayResize( IMA2slowB, MAarraySize ); ArraySetAsSeries( IMA1fastA, true ); ArraySetAsSeries( IMA1fastB, true ); ArraySetAsSeries( IMA2fastA, true ); ArraySetAsSeries( IMA2fastB, true ); ArraySetAsSeries( IMA1slowA, true ); ArraySetAsSeries( IMA1slowB, true ); ArraySetAsSeries( IMA2slowA, true ); ArraySetAsSeries( IMA2slowB, true ); for( int i = MAarraySize-1; i >= 0; i-- ) { IMA1fastA[i] = iMA( NULL, HMA_TF_1, HMAperiod_fast_1/2, 0, MODE_LWMA, PRICE_TYPICAL, i ); IMA1fastB[i] = iMA( NULL, HMA_TF_1, HMAperiod_fast_1, 0, MODE_LWMA, PRICE_TYPICAL, i ); IMA2fastA[i] = iMA( NULL, HMA_TF_2, HMAperiod_fast_2/2, 0, MODE_LWMA, PRICE_TYPICAL, i ); IMA2fastB[i] = iMA( NULL, HMA_TF_2, HMAperiod_fast_2, 0, MODE_LWMA, PRICE_TYPICAL, i ); IMA1slowA[i] = iMA( NULL, HMA_TF_1, HMAperiod_slow_1/2, 0, MODE_LWMA, PRICE_TYPICAL, i ); IMA1slowB[i] = iMA( NULL, HMA_TF_1, HMAperiod_slow_1, 0, MODE_LWMA, PRICE_TYPICAL, i ); IMA2slowA[i] = iMA( NULL, HMA_TF_2, HMAperiod_slow_2/2, 0, MODE_LWMA, PRICE_TYPICAL, i ); IMA2slowB[i] = iMA( NULL, HMA_TF_2, HMAperiod_slow_2, 0, MODE_LWMA, PRICE_TYPICAL, i ); } }

- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Wanting to include the Hull MA in an EA, I tried using the iCustom() call using the attached HMA indicator. This way it slows down the backtesting process very noticeably. Then I decided to adapt the indicator to create a function but the performance does not improve much. This function is called 4 times on each tick because the EA evaluates the crossover.
If possible, Does anyone have any ideas on how to improve the performance using this HMA function? Thanks in advance.