Articles on MQL4
Moving Average

Moving Average


for example, forex

We have learnt how to create an indicator that draws symbols/arrows on crossing between two moving averages of different period. Now we’ll write an indicator that plots a simple moving average. A moving average is one of the most important indicators in the technical analysis; on its basis most of other indicators both standard and developed by traders themselves are created. A moving average is characterized by the period of calculation, the type of prices on which it is based and a shift. If we want to calculate a simple 3-period moving average based on the average closing prices, we add together closing prices for each of the last 3 periods (closing price today + closing price yesterday + closing price the day before yesterday) and then divide the total by the number of periods - in this case 3.
MA(3,Close)=(Close[0]+Close[1]+Close[2])/3.
We will use again the «Advisor Creation Wizard». We will create the parameters PeriodMA and ShiftMA.

 
 

Next step is to add index; the type and color we won’t change, then we press “Ready”.

 
 

We’ve got a standard template:

 
 

Now we’ll add to the block start() a part of the code from the indicator CrossMA-3, in order not to write again the loop and utility variables.

 
 


We know already how the for() loop works, now we can substitute the for() loop for the while()loop. We factor out the declaration of the variable i (int i=limit;) from for() before the loop, we insert the decrement operation (i--;) into the loop body, in the very end, and then we change the name of the for loop for while:

 
 

As we can see the while() loop has fully substituted the for() loop. Also the validity of the expression in the brackets is checked, and if it is fulfilled, the loop body is executed. It is important not to forget to insert in the loop the decrement operator of the counter i, otherwise we will get an infinite loop. The compiler will not be able to detect such error (as it is not syntactical, it is logical), and if this incorrect indicator (with an infinite loop) is used the terminal will simply hang up and stop to respond to the user’s actions. The only way out of such situation is to close the terminal forcibly from the task manager, open MetaEditor, correct the indicator and launch MetaTrader4 again. But in scripts you may use infinite loops.

 
 

Whether to use the while() loop or the for() loop depends on Your taste, though there are situations when the while() loop is preferable, for example, if it is necessary, moving from the current bar into the depth of history ( the bar index increases) to find a certain bar, which meets some condition. And it is necessary not to forget that the sought after bar may not be found, while the bar index will increase infinitely. And in order to avoid looping it is necessary to add checking if the index excesses of the number Bars. The example of such loop:

 
 

Now we have the loop, we only have to write the algorithm for calculation the sum based on the number of bars PeriodMA, i.e. something like that:

val=(Close[i]+Close[i+1]+Close[i+2]+… Close[i+n])/PeriodMA

What will n be equal to, if PeriodMA (the period of our moving average) is known? There are people who can easily calculate the needed formula mentally; I made mistakes for many times, when I tried to do it without the help of a paper and a pen, that’s why it will be safer to follow the induction method. It will take no more than a minute, while the correctness of the result is guaranteed.
Let’s take a particular case, n=5, as if we want to find the average for 5 bars. Then our formula is as follows:

Val=(Close[i]+Close[i+1]+Close[i+2]+Close[i+3]+Close[i+4])/5

or elsewise:

Val=(Close[i]+Close[i+1]+…+Close[i+PeriodMA-2]+Close[i+PeriodMA-1])/PeriodMA

Such mechanical addition can be easily inserted into the for() loop.

 
 

In this case we have used both types of loops; we have got a convenient visual partition of the algorithm for searching the bars of the chart and the algorithm for summing up prices. Now we will return to the beginning of the block start(). As we can see in the picture there is no reason to set a limiter of counting limit into the value Bars-1 when the indicator is called for the first time, there are no bars in the depth of history and there is nothing to average. If we for example want to calculate a 5-period moving average, we can start to calculate it only from the bar Bars-5 (See the article «What are charts? »).

 
 

That’s why for the first time when counted_bars is equal to zero it is logically to write:

 
 

The indicator of a simple moving average based on the closing prices is ready, but sometimes a temptation arouses to create a maximally optimized indicator and an attempt is made to improve that part of the block start(), where counted_bars is larger than zero, i.e. the primary calculation of the indicator has been made already. On the ground that after the first run of the indicator Bars hasn’t changed, the calculation of the indicator was made based on the number of bars from Bars-PeriodMA to zero (i.e. counted_bars is supposed to be equal approximately Bars-PeriodMA), we write the following:

 
 

As the aim is to calculate only on the zero bar it is possible to suppose that limit=0 and 0=Bars-counted_bars-PeriodMA. This implies that we presume that during the second launch of the indicator counted_bars+PeriodMA==Bars. In fact this is not so, and this is the second mistake of optimization, I call such indicator over optimized. The function IndicatorCounted() doesn’t return the number of bars, for which the calculation of values was made by this particular indicator, it returns the number of bars that haven’t changed since the last call of the indicator (the zero bar changed, otherwise the tick on which we are executing verification wouldn’t have come). That’s why if Bars=1000, then during the first call of the indicator IndicatorCounted() will return 0 (the indicator hasn’t been calculated yet), while during the second call IndicatorCounted() will return Bars-1. You can check it by yourself, having created an empty indicator (in which no calculations are made at all ) and having inserted in the block start() the call
Print("Bars=",Bars,"  counted_bars=",counted_bars);
If we don’t notice this mistake and the indicator remains over optimized then the following will happen (let Bars be equal to 1000, and PeriodMA will be equal to 5):
  1. for the first time the indicator is calculated correctly from the bar Bars-PeriodMA to the zero bar
  2. on the next tick the checking counted_bars will be greater than zero and the limiter of calculation will become equal to limit=1000-999-5= 1-5=-4
  3. a limiter less than zero enters the block while() (or for(), the type of cycle doesn’t matter) and check is performed while(-4>=0) , check fails and recalculation on the zero bar isn’t performed.

There are two ways to detect such mistake :
  1. to launch the indicator on a short-term time-frame and watch its behavior
  2. to run the advisor that contains the call of your indicator in the tester.
For this indicator the simplest way of verification is the first one. We compile the incorrect indicator and use it on EURUSD M15, and then we wait for half an hour until two new bars appear and we see the following picture.

 
 


Fortunately in this case when we work on-line the mistake in calculations of the indicator becomes evident quickly (the indicator isn’t drawn simply), but in more complicated cases the value of indicator simply drifts and it is not always possible to see it by eye.

You may download the indicators Simply MA.mq4 and Simply MA wrong.mq4 here.


Go to article «Moving Average (ending)».

+7 (495) 710-76-76
© 1998—2008 «Alpari»

close

Your Personal Area

For alpari.classic enter your account number (a letter and 4 figures) and the code word for the Personal Area.

For alpari.micro account: enter your login (6 figures) and the password for MT.

Open an account!Forgotten your password?