Metadrader handling weirdly data read from different time frame

 

Hi,

I was optimizing an EA and noticed that with the same parameters, I had different results. I wanted to explain my case and benefit from your experience to move on with this. I firmly believe a limitation in how metatrader handles threads and loads data.

For a week, I did my investigations. It is related to reading indicator data from a higher timeframe. The metatrader 5 is sending/reading the wrong data randomly!

So, below is a simplified version of my code. I went through the forums and applied different approaches, like capturing the last error to check if anything related to the data loaded; I also forced loading the data using CheckLoadHistory shared in this forum; the load is correct, but again, the data reading is false. I did this in the EA and the Indicator. 

After multiple tests, I realized I always have this error randomly and with high probability when opening metatrader and starting a fresh new test or loading my CPU/RAM with other programs.

Take the code below, open metatrader, and run it for the first time. You will have the error, run it a second time, and there will be no more errors.

Any help is welcome.


My idea is simple: I get a swing high/low of a higher timeframe from zigzag to use as a TP.

When I have the error, the values are returned as follows: for example, it looks like LONG_MAX and LONG_MIN are involved. 

CK      0       10:14:52.985    Core 01 2023.07.18 04:30:00   TP Buy: 2.8768797628088834e+171
DO      0       10:14:52.985    Core 01 2023.07.18 04:30:00   TP Sell: 1.03984
PJ	0	10:14:52.985	Core 01	2023.07.18 10:10:00   TP Buy: 2.8768797628088834e+171
EQ	0	10:14:52.985	Core 01	2023.07.18 10:10:00   TP Sell: 1e-323

I have done a stress test, just an optimization on an int that is  not used in the logic, and when I load my PC I start having those errors, and it happens on a nonregular time. Example 3 occurrences over 500 tests.


My code is the following

#property copyright "Copyright 2024, Grap"
#property link      "https://www.google.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

#include <Trade.mqh>
input ENUM_TIMEFRAMES InpHighTimeFrameTP = 0;
input int stress = 1;

double ext = 0; 
int   mHandle;
double mBuffer[];
CTrade mTrade;
        
int OnInit()
  {
//---
   mHandle  = 0;
   ArraySetAsSeries(mBuffer,true);
   mHandle = iCustom(Symbol(),InpHighTimeFrameTP,"Examples\\ZigZag.ex5",8,5,3);
    
    if(mHandle == INVALID_HANDLE)
      {  
         return INIT_FAILED;
      }
   
   mTrade.MagicNumber(1);
   mTrade.FillType(ORDER_FILLING_IOC);
              
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   IndicatorRelease(mHandle);
   
  }

double GetValue(int index){
      
      int result = CopyBuffer(mHandle, 0, index, 1, mBuffer);
      if(result < 1 ) { return(0);}
      return(mBuffer[0]);
      
   }   
   
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
     if(!IsNewBar()) return;
      
      if(PositionsTotal() == 0)
        {   
            double TPbuy  = GetTP(SymbolInfoDouble(Symbol(),SYMBOL_BID), ORDER_TYPE_BUY);
            double TPSell = GetTP(SymbolInfoDouble(Symbol(),SYMBOL_BID), ORDER_TYPE_SELL);
            Print("TP Buy: ",TPbuy);
    	    Print("TP Sell: ",TPSell);
            

            mTrade.Buy(Symbol(),0.01,SymbolInfoDouble(Symbol(),SYMBOL_BID)-0.00100,TPbuy);
            mTrade.Sell(Symbol(),0.01,SymbolInfoDouble(Symbol(),SYMBOL_ASK)+0.00100,TPSell);
        }
  }
//+------------------------------------------------------------------+

double GetTP(double price,ENUM_ORDER_TYPE type, int startAt=2)
   { 
      double zigzag = -1;      
      int i=startAt;
      
      if(type == ORDER_TYPE_BUY)
         { 
            while(zigzag ==-1)
              {
                  ResetLastError();
                  double tempZ = GetValue(i);
                  if(GetLastError() !=0)
                    {
                        Print("ERROR: ",GetLastError());
                    }
                  if( tempZ == EMPTY_VALUE || tempZ == 0) 
                     { 
                       i++; 
                       continue;
                      }
                  
                  if(tempZ > price)
                     { 
                        zigzag = tempZ;
                     } 
                  i++;
              }         
         
         }

      if(type == ORDER_TYPE_SELL)
         { 
            while(zigzag ==-1)
              {
                  ResetLastError();
                  double tempZ = GetValue(i);
                                    if(GetLastError() !=0)
                    {
                        Print("ERROR: ",GetLastError());
                    }
                  if( tempZ == EMPTY_VALUE || tempZ == 0) 
                     { 
                       i++; 
                       continue;
                      }
                  
                  if(tempZ < price)
                     { 
                        zigzag = tempZ;
                     } 
                  i++;
              }         
         
         }
   
   return zigzag;
   
   }
   
   bool IsNewBar()
  {
   static bool result = false;

   static datetime previous_time = 0;
   datetime        current_time  =iTime(Symbol(), Period(), 0);
   result                       = false;
   if(previous_time != current_time)
     {
      previous_time = current_time;
      result        = true;
     }
   return (result);
  }
  
Documentation on MQL5: Timeseries and Indicators Access / Organizing Data Access
Documentation on MQL5: Timeseries and Indicators Access / Organizing Data Access
  • www.mql5.com
Organizing Data Access - Timeseries and Indicators Access - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 

@Moderators  @Community

Do you have any idea here? Should I send directly to MQL5 technical team via the service desk? 

Regards

Gege

 
if tempZ is Long max it is > price and if it is Long min it is < price . 
 
Lorentzos Roussos #:
if tempZ is Long max it is > price and if it is Long min it is < price . 
Hey

Thanks a lot for being interested in this

So you are suggesting eliminating tempz that are equal to long max and min, which is a good way, but this will not solve that I will have different results for the same parameters. 

Did you fave similar things before? 

Regards 
 
Are you running it on visual mode ? 
 
Lorentzos Roussos #:
Are you running it on visual mode ? 
No, didn't try to reproduce wth visual mode.
But when running not in visual, sometime the data are not read correctly :/ let me check if visual mode can reproduce this too
 
Grap the Trade #:
It is important to understand that any higher timeframes in MT5 (unlike MT4) are formed from the M1 timeframe.  That is, if you want to download the last 200 MN1 bars, then millions of M1 bars will be downloaded.  This is more than 100 MB of data.  Until all this data is loaded, anything can happen.
 
Nikolai Semko #:
It is important to understand that any higher timeframes in MT5 (unlike MT4) are formed from the M1 timeframe.  That is, if you want to download the last 200 MN1 bars, then millions of M1 bars will be downloaded.  This is more than 100 MB of data.  Until all this data is loaded, anything can happen.

Yes I agree with you :( unfortunately, this is leaving me with  no solution other than cutting out those backtests in order not to show any erroneous results , unless I found  another workaround for this

 
Grap the Trade #:

Yes I agree with you :( unfortunately, this is leaving me with  no solution other than cutting out those backtests in order not to show any erroneous results , unless I found  another workaround for this

Organize the download and control of data using a timer, and then you will be able to control the entire process.  In my trading systems, this is exactly what happens.  Only I download only M1 and ticks, the rest is formed from this data.  Therefore, my trading systems do not depend on the TimeFrames
 
Nikolai Semko #:
Organize the download and control of data using a timer, and then you will be able to control the entire process.  In my trading systems, this is exactly what happens.  Only I download only M1 and ticks, the rest is formed from this data.  Therefore, my trading systems do not depend on the TimeFrames
Thanks a lot for the support 🙂

Yes this is eventually a way to do it, I would appreciate if you can guide me toward some resources that I can read and apply, and I will also do my research on this.

Francky speaking this should be an automatic thing metatrader to handle, example other trading platform doesn't have this limitation it handles correctly, while in metatrader we need to handle inside the EA.

Thanks again Nikolai
 

Till today, I couldn't yet find a valid root cause, below the EA with default Trade.mqh used y mql5

#property copyright "Copyright 2024, Grap"
#property link      "https://www.google.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

#include <Trade\Trade.mqh>
input ENUM_TIMEFRAMES InpHighTimeFrameTP = 0;
input int stress = 1;

double ext = 0; 
int   mHandle;
double mBuffer[];
CTrade mTrade;
        
int OnInit()
  {
//---
   mTrade.SetExpertMagicNumber(1);
   
   mHandle  = 0;
   ArraySetAsSeries(mBuffer,true);
   mHandle = iCustom(Symbol(),InpHighTimeFrameTP,"Examples\\ZigZag.ex5",8,5,3);
    
    if(mHandle == INVALID_HANDLE)
      {  
         return INIT_FAILED;
      }
   
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   IndicatorRelease(mHandle);
   
  }

double GetValue(int index){
      
      int result = CopyBuffer(mHandle, 0, index, 1, mBuffer);
      if(result < 1 ) { return(0);}
      return(mBuffer[0]);
      
   }   
   
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
     if(!IsNewBar()) return;
      
      if(PositionsTotal() == 0)
        {   
            double TPbuy  = GetTP(SymbolInfoDouble(Symbol(),SYMBOL_BID), ORDER_TYPE_BUY);
            double TPSell = GetTP(SymbolInfoDouble(Symbol(),SYMBOL_BID), ORDER_TYPE_SELL);
            Print("TP Buy: ",TPbuy);
            Print("TP Sell: ",TPSell);
            
            ResetLastError();
            
            
            if(!mTrade.Buy(0.01,Symbol(),SymbolInfoDouble(Symbol(),SYMBOL_ASK),SymbolInfoDouble(Symbol(),SYMBOL_ASK)-0.00100,TPbuy)) Print(GetLastError());
            
            ResetLastError();
            if(!mTrade.Sell(0.01,Symbol(),SymbolInfoDouble(Symbol(),SYMBOL_BID),SymbolInfoDouble(Symbol(),SYMBOL_ASK)-0.00100,TPSell)) Print(GetLastError()); 
        }
  }
//+------------------------------------------------------------------+

double GetTP(double price,ENUM_ORDER_TYPE type, int startAt=2)
   { 
      double zigzag = -1;      
      int i=startAt;
      
      if(type == ORDER_TYPE_BUY)
         { 
            while(zigzag ==-1)
              {
                  ResetLastError();
                  double tempZ = GetValue(i);
                  if(GetLastError() !=0)
                    {
                        Print("ERROR: ",GetLastError());
                    }
                  if( tempZ == EMPTY_VALUE || tempZ == 0) 
                     { 
                       i++; 
                       continue;
                      }
                  
                  if(tempZ > price)
                     { 
                        zigzag = tempZ;
                     } 
                  i++;
              }         
         
         }

      if(type == ORDER_TYPE_SELL)
         { 
            while(zigzag ==-1)
              {
                  ResetLastError();
                  double tempZ = GetValue(i);
                                    if(GetLastError() !=0)
                    {
                        Print("ERROR: ",GetLastError());
                    }
                  if( tempZ == EMPTY_VALUE || tempZ == 0) 
                     { 
                       i++; 
                       continue;
                      }
                  
                  if(tempZ < price)
                     { 
                        zigzag = tempZ;
                     } 
                  i++;
              }         
         
         }
   
   return zigzag;
   
   }
   
   bool IsNewBar()
  {
   static bool result = false;

   static datetime previous_time = 0;
   datetime        current_time  =iTime(Symbol(), Period(), 0);
   result                       = false;
   if(previous_time != current_time)
     {
      previous_time = current_time;
      result        = true;
     }
   return (result);
  }
Reason: