Articles on MQL4
Indicator Optimisation

Indicator Optimisation


for example, forex

In spite of its small size the indicator we created has a serious disadvantage as it is resource-intensive. In tab «Experts» (where logs created by MQL-4 programs are seen) a lot of outputs of function Print() are seen (this is referred to the indicator CrossMA-2.mq4):

 
 


As function start() is called on every tick cycle for() is executed with each price change. If you have noticed, «Advisors Creation Wizard» has created a variable counted_bars (counted bars), let's consider its behaviour when the indicator works. I have added a new variable limit, and also printed out.

 
 


The indicator works the same way, the cycle starts counting from i=Bars-1 (limit=Bars-1). The work of the indicator may be improved by watching after the output Print() in block start().

 
 


When the indicator is run on the first call start() counted_bars is equal to zero, Bars is equal to 4413, limit is equal to 4412 (a unite less than Bars). On the second call counted_bars is already equal to 4412 and then it does not change on the current bar. So, the indicator values are calculated for the first time then on each tick they are recalculated uselessly instead of calculating an indicator value only on the zero bar which has not completed yet. Thus, having avoided such a calculation we will offload the computer's processor. Let's check this condition on the first call of counted_bars=0, if it is fulfilled then leave the limit as it is.

 
 


If the indicator has been already calculated we will count only on the zero bar. We get zero as Bars-counted_bars-1 (4413 – 4412 -1).

 
 


A new modernized indicator confirms our suppositions:

 
 


For the first time the indicator is calculated on 4413 bars and further calculations are done only for the zero bar. Let's see what happens when the current bar completes and a new one opens. For the newly created indicator it is better to insert the following line: Print("Bars=",Bars," limit=",limit," counted_bars=",counted_bars); Thus we see the first possible mistake, non-optimized algorithm of the indicator calculation. The second widely-spread mistake (overoptimization) will be considered later.

#property copyright "MetaQuotes"
#property link      "http://forum.alpari-idc.ru/viewtopic.php?t=48186"

#property indicator_chart_window #property indicator_buffers 2 #property indicator_color1 Blue #property indicator_color2 Red
//---- input parameters extern int LongPeriod=21; extern int ShortPeriod=13;
//---- buffers double ExtMapBuffer1[]; double ExtMapBuffer2[];
//----
int init() { Print("init() is executed");
SetIndexStyle(0,DRAW_ARROW); SetIndexArrow(0,241); SetIndexBuffer(0,ExtMapBuffer1);
SetIndexEmptyValue(0,0.0); SetIndexStyle(1,DRAW_ARROW); SetIndexArrow(1,242);
SetIndexBuffer(1,ExtMapBuffer2); SetIndexEmptyValue(1,0.0); return(0);
} //---- int deinit() { Print("deinit() is executed"); return(0);
} //----
int start() { int counted_bars=IndicatorCounted(); int limit; // calculations limiter
double maLongCur, maLongPrev, maShortCur, maShortPrev;
// let's declare utility variables where arrows price coordinates will be stored double value1,value2;

if (counted_bars==0) limit=Bars-1; // there are no calculated bars yet, it will calculate from the very beginning

if (counted_bars>0) limit=Bars-counted_bars-1; // let's subtract from the number of available bars the number of
//calculated bars and subtract one
Print("Bars=",Bars," limit=",limit," counted_bars=",counted_bars);

for(int i=limit;i>=0;i--) {
// let's zero utility variables value1=0.0; value2=0.0; maLongCur=iMA(NULL,0,LongPeriod,0,MODE_SMA,PRICE_CLOSE,i+1);// slow average on the previous bar
maLongPrev=iMA(NULL,0,LongPeriod,0,MODE_SMA,PRICE_CLOSE,i+2);// slow average two bars before
maShortCur=iMA(NULL,0,ShortPeriod,0,MODE_SMA,PRICE_CLOSE,i+1);// quick average two bars before
maShortPrev=iMA(NULL,0,ShortPeriod,0,MODE_SMA,PRICE_CLOSE,i+2);// quick average on the previous bar


//If there is a buy signal on the previous bar let's put a blue upward arrow // at the bar opening price if((maShortCur>maLongCur)&&(maShortPrev<maLongPrev)) { value1=Open[i];//let's remember the price of the blue arrow
} //If there is a sell signal on the previous bar let's put a red down arrow // at the bar opening price if((maShortCur<maLongCur)&&(maShortPrev>maLongPrev)) {
value2=Open[i];//let's remember the red arrow price }
ExtMapBuffer1[i]=value1;
ExtMapBuffer2[i]=value2; }
//---- return(0); }


It is very important to calculate the customer's indicator optimally. To prove it let's run the simplest expert, which does not open deals and only contains a call of our indicator on each new bar for one time only. I have created two indicators, one of which contains calls of the «correct», optimized indicator, the second one contains the calls of the «incorrect» indicator, the very first draft variant of our indicator. To call the customer's indicators function iCustom(Instrument, Time_frame, Indicator's_name, Customer's_indicator_parameters, Index_number, bar_number) is used. In fact, the first three and the last two parameters are checked, the other ones between them are considered to be the indicator's parameters and transferred to the customer's indicator directly. The compiler does not check the correctness of the transferred parameters as the customer's indicator is called dynamically. The call of our indicator looks the following way:
blueArrow=iCustom(NULL,0,"CrossMA-3",21,13,0,0);
redArrow=iCustom(NULL,0,"CrossMA-3",21,13,1,0);

The customer's indicator call without parameters will be equal to the call of the indicator with parameters by default (in our case 21 and 13), that is why such a record will be like the previous one:
 blueArrow=iCustom(NULL,0,"CrossMA-3",0,0);
   redArrow=iCustom(NULL,0,"CrossMA-3",1,0);


 
 


Parameters of the customer's indicator are also given in the indicator's characteristics:

 
 


I have created two advisors, one of them contains the optimized indicator call (CrossMA-3) with name TestCrossMA, the second one contains non-optimized indicator call (CrossMA-2) , it is named TestCrossMAwrong. Download them here . Store them in the folder /experts, compile and then open the «Strategy tester» in the terminal (Ctrl+R), put the necessary settings and press the «Start» button.

 
 


Note that the customer's indicator should be calculated effectively.

 
 


Go to article «Moving Average».

+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?