Missing Ticks when processing multiple iCustom indicatorus with CopyBuffer

 

Hi, I am relatively new to MT5 and having my first attempt to write an experimental EA after reading the tutorials and examples here.

I am trying to initialize multiple instance of a customed indicator with different trend period using iCustom(), and trying to process the indicator value using BufferCopy() at each tick within OnTick().

It seems to work with 1 instance of the indicator, but as soon as I added addition instances of the indicators (with different parameters), I noticed I start to miss ticks and in particulare see far less ticks (like 1 tick per half minute vs the normal 50+ tick per minute I see at on seperate screen at the same moment) being processed in the debug log even with just 2 indicators and gradually got worst as I add more. 

Below is the code for my test EA

I know it is by design that MT5 will miss ticks when busy processing OnTick(), but with the OnTick() processing took approx. 0.2sec for processing 6 iCustom indicators, it seem excessively that it is only picking up ticks every 30 second-ish. 

Is there something I am doing wrong or I should be careful when processing multiple iCustom indicators to minimized tick being missed?


Many thanks in advance,
Anthony


//+------------------------------------------------------------------+
//|                                             TestEA.mq5 |
//|                                             Anthony |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Anthony"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

const int normDigits = 5;
const int numBuffer = 2;
const int numBufferCopy = 3;
const string sIndicator = "Market\\TestIndicator.ex5";

input int Trend_Period_Start = 5;
input int Trend_Period_End = 10;

double Buy_0[3];	
double Sell_0[3];
double Buy_1[3];	
double Sell_1[3];
double Buy_2[3];	
double Sell_2[3];
double Buy_3[3];	
double Sell_3[3];
double Buy_4[3];	
double Sell_4[3];
double Buy_5[3];	
double Sell_5[3];

int OnInit(){

// Initiate indicators between a range of pre-defined trend periods
   ResetLastError();
   
   indicatorNum = Trend_Period_End - Trend_Period_Start + 1; 
   for (int i=0; i < indicatorNum; i++){
      
      ArrayResize(indicatorhandle, ArraySize(indicatorhandle)+1, 0);
      
      indicatorhandle[i] = iCustom(
         NULL,                                              // Current symbol
         0,                                                    // Current timeframe
         sIndicator,                                       // EA ex5 Path
         Trend_Period_Start + i,                    // Trend Period
         0                                                    // Timeseries Shift =0
      );
      
      Print("Indicator Handle(", i, ") = ", indicatorhandle[i], "; size = ", ArraySize(indicatorhandle), ";  error = ",GetLastError());
   }

   return(INIT_SUCCEEDED);
}

void OnTick(){
   Print ("Ontick: Starting processing"); // Debug message to track time for processing onTick()
   double result [6][2][3]; // Static array to hold up to 6 test iCustom indicators (with different trend periods), 2 indicator buffers on each iCustom indicator and 3 last buffer value
   
   IndicatorProcessor(indicatorhandle, result); // Call sub-routine to process each of the 6 test iCustom indicators

   for(int _i = 0; _i < Trend_Period_End - Trend_Period_Start +1; _i++) {
   
      // Log message for debugging
      Print (
         "; Buy: ", result[_i][0][0], "|", result[_i][0][1], "|", result[_i][0][2], 
         "; Sell: ", result[_i][1][0], "|", result[_i][1][1], "|", result[_i][1][2]
      );
   }
   
   Print("Ontick: Completes"); // // Debug message to track time for processing onTick()
}

void IndicatorProcessor(int& _handle[], double& _result[][][]){
   

   // Calling CopyBuffer for each of the 6 iCustom indicators and 2 indicator buffers (i.e. buy and sell values)
   // Check on the first CopyBuffer if we have sufficient bars
   // TODO: Find a way to make it more elegent than hard-coding CopyBuffer() 

   if (CopyBuffer(_handle[0],0,0,numBufferCopy,Buy_0) < 3) return;  
   CopyBuffer(_handle[0],3,0,numBufferCopy,Sell_0);
   
   CopyBuffer(_handle[1],0,0,numBufferCopy,Buy_1);
   CopyBuffer(_handle[1],3,0,numBufferCopy,Sell_1);
   
   CopyBuffer(_handle[2],0,0,numBufferCopy,Buy_2);
   CopyBuffer(_handle[2],3,0,numBufferCopy,Sell_2);
   
   CopyBuffer(_handle[3],0,0,numBufferCopy,Buy_3);
   CopyBuffer(_handle[3],3,0,numBufferCopy,Sell_3);
   
   CopyBuffer(_handle[4],0,0,numBufferCopy,Buy_4);
   CopyBuffer(_handle[4],3,0,numBufferCopy,Sell_4);
   
   CopyBuffer(_handle[5],0,0,numBufferCopy,Buy_5);
   CopyBuffer(_handle[5],3,0,numBufferCopy,Sell_5);
   

  // Putting normalized output from CopyBuffer into results [][][] for easier debugging/logging
  // TODO: Implement processing logic here
  for (int _j = 0; _j < numBufferCopy; _j++){
      _result[0][0][_j]= Buy_0[_j] == EMPTY_VALUE ? 0 : NormalizeDouble(Buy_0[_j], normDigits);
      _result[0][1][_j]= Sell_0[_j] == EMPTY_VALUE ? 0 : NormalizeDouble(Sell_0[_j], normDigits);
      
      _result[1][0][_j]= Buy_1[_j] == EMPTY_VALUE ? 0 : NormalizeDouble(Buy_1[_j], normDigits);
      _result[1][1][_j]= Sell_1[_j] == EMPTY_VALUE ? 0 : NormalizeDouble(Sell_1[_j], normDigits);
      
      _result[2][0][_j]= Buy_2[_j] == EMPTY_VALUE ? 0 : NormalizeDouble(Buy_2[_j], normDigits);
      _result[2][1][_j]= Sell_2[_j] == EMPTY_VALUE ? 0 : NormalizeDouble(Sell_3[_j], normDigits);
      
      _result[3][0][_j]= Buy_3[_j] == EMPTY_VALUE ? 0 : NormalizeDouble(Buy_3[_j], normDigits);
      _result[3][1][_j]= Sell_3[_j] == EMPTY_VALUE ? 0 : NormalizeDouble(Sell_3[_j], normDigits);
      
      _result[4][0][_j]= Buy_4[_j] == EMPTY_VALUE ? 0 : NormalizeDouble(Buy_4[_j], normDigits);
      _result[4][1][_j]= Sell_4[_j] == EMPTY_VALUE ? 0 : NormalizeDouble(Sell_4[_j], normDigits);
      
      _result[5][0][_j]= Buy_5[_j] == EMPTY_VALUE ? 0 : NormalizeDouble(Buy_5[_j], normDigits);
      _result[5][1][_j]= Sell_5[_j] == EMPTY_VALUE ? 0 : NormalizeDouble(Sell_5[_j], normDigits);
   }
   
}
 

the Editor has a profiler to find where a program looses time and where it can be improved:


Beside that learn to use the debugger: https://www.metatrader5.com/en/metaeditor/help/development/debug

Code debugging - Developing programs - MetaEditor Help
  • www.metatrader5.com
MetaEditor has a built-in debugger allowing you to check a program execution step by step (by individual functions). Place breakpoints in the code...
 
  1. What is numBufferCopy? Don't post code that will not even compile.
  2. Perhaps it is your indicator. Code it properly so it only recomputes bar zero (after the initial run).
              How to do your lookbacks correctly. (2016)
              3 Methods of Indicators Acceleration by the Example of the Linear Regression - MQL5 Articles. (2011)
    Or, reduce Tools → Options (control+O) → Charts → Max bars in chart to something reasonable (like 1K.)

 
Carl Schreiber #:

the Editor has a profiler to find where a program looses time and where it can be improved:


Beside that learn to use the debugger: https://www.metatrader5.com/en/metaeditor/help/development/debug

I try the profile and it seems to be spending 91% of the time on the first CopyBuffer() call.

I tried putting a breakpoint either side of the first CopyBuffer() call but wasn't sure what to look for - it looks as if it is copying the buffer as intended and it is not particularly slow (it clocked 0.1 sec in the run just now)

William Roeder #:
  1. What is numBufferCopy? Don't post code that will not even compile.
  2. Perhaps it is your indicator. Code it properly so it only recomputes bar zero (after the initial run).
              How to do your lookbacks correctly. (2016)
              3 Methods of Indicators Acceleration by the Example of the Linear Regression - MQL5 Articles. (2011)
    Or, reduce Tools → Options (control+O) → Charts → Max bars in chart to something reasonable (like 1K.)

My apologies - I missed out a bunch of variable declarations at the top of the EA and have included them back now.

 
Your topic has been moved to the section: Expert Advisors and Automated Trading — In the future, please consider which section is most appropriate for your query.
MQL5 forum: Expert Advisors and Automated Trading
MQL5 forum: Expert Advisors and Automated Trading
  • www.mql5.com
How to create an Expert Advisor (a trading robot) for Forex trading
 

" I try the profile and it seems to be spending 91% of the time on the first CopyBuffer() call."

Then it seems that the problem is the indicator!

Maybe you should read:

Tips from a professional programmer (Part  I): Code storing, debugging and compiling. Working with projects and logs
https://www.mql5.com/en/articles/9266
Tips from a professional programmer (Part II): Storing and exchanging parameters between an Expert Advisor, scripts and external programs
https://www.mql5.com/en/articles/9327
Tips from a professional programmer (Part III): Logging. Connecting to the Seq log collection and analysis system
https://www.mql5.com/en/articles/10475

Also study the indicators on your pc in .....\MQL5\Indicators\Examples\ ...

Tips from a professional programmer (Part I): Code storing, debugging and compiling. Working with projects and logs
Tips from a professional programmer (Part I): Code storing, debugging and compiling. Working with projects and logs
  • www.mql5.com
These are some tips from a professional programmer about methods, techniques and auxiliary tools which can make programming easier.