Bug when comparing two numbers. Different results for the same numbers.

 

I make an MA based simple Expert Advisor. Recently I noticed a skipping of entry point. I dug deeper and found a bug. 

EA enters the market at a crossing of slow and fast MA (please see the code below). In the beginning of each timeframe period EA compares the values of two MA's for the last closed candle an does the same for one candle before it. If relations are deffernt it opens a position. Very simple logic.

So I was wondered when it skipped an entry point. I decided to alert compare results, and found that in two different moments MQL gives different results for the same comparison of two numbers.

Look at the log screenshot. Marked values due to EA code should be the same.

Will be grateful for any feedback.

#property copyright "Copyright 2021."
#property link      ""
#property version   "1.00"
#include <Trade\Trade.mqh>

CTrade tradeObj;

int h_FastMA;
int h_SlowMA;

bool firstDeal = true;
int TP_Factor=2;

datetime sTime;
bool timerIsSet=false;

void trade() { 
      double fastBuffer[2];
      double slowBuffer[2];
      double priceBuffer[1];
      double SL, TP, currentPrice;
      
      CopyBuffer(h_FastMA, 0, 1, 2, fastBuffer);
      CopyBuffer(h_SlowMA, 0, 1, 2, slowBuffer); Alert("Fast last > Slow last: " + (fastBuffer[1] > slowBuffer[1]) + "   | Fast prev > Slow prev: " + (fastBuffer[0]>slowBuffer[0]));
      
      if(fastBuffer[1]>slowBuffer[1] && fastBuffer[0]<=slowBuffer[0]) {//Alert("BUY Signal   FAST: "+fastBuffer[1]+" SLOW: "+slowBuffer[1]);
         CopyLow(Symbol(), Period(), 2, 1, priceBuffer);
         currentPrice=SymbolInfoDouble(Symbol(), SYMBOL_ASK);
         SL=priceBuffer[0];
         TP=currentPrice+TP_Factor*(currentPrice-SL);
         
         if(SL>currentPrice) {
            SL=2*currentPrice-SL;
            TP=2*currentPrice-TP;
         }
         
         if(firstDeal) {
            tradeObj.PositionOpen(Symbol(), ORDER_TYPE_BUY, 0.1, SymbolInfoDouble(Symbol(),SYMBOL_ASK), 0, 0); 
            firstDeal=false;
         } else {  
            if(PositionsTotal()>0) {
               tradeObj.PositionClose(Symbol()); 
            }
            tradeObj.PositionOpen(Symbol(), ORDER_TYPE_BUY, 0.1, SymbolInfoDouble(Symbol(),SYMBOL_ASK), 0, 0);
         }
     } else if(fastBuffer[1]<=slowBuffer[1] && fastBuffer[0]>=slowBuffer[0]) {
         CopyHigh(Symbol(), Period(), 2, 1, priceBuffer);
         currentPrice=SymbolInfoDouble(Symbol(), SYMBOL_BID);
         SL=priceBuffer[0];
         TP=currentPrice+TP_Factor*(currentPrice-SL);
         
         if(SL<currentPrice) {
            SL=2*currentPrice-SL;
            TP=2*currentPrice-TP;
         }
         
         if(firstDeal) { 
            tradeObj.PositionOpen(Symbol(), ORDER_TYPE_SELL, 0.1, SymbolInfoDouble(Symbol(),SYMBOL_BID), 0, 0);
            firstDeal=false;
         } else { 
            if(PositionsTotal()>0) {
               tradeObj.PositionClose(Symbol()); 
            }
            tradeObj.PositionOpen(Symbol(), ORDER_TYPE_SELL, 0.1, SymbolInfoDouble(Symbol(),SYMBOL_BID), 0, 0);
         }
     }
  }
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   int fastPeriod=40;
   int slowPeriod=300;
   
   MqlParam params[];
   
//--- create iMA("EURUSD",PERIOD_M15,8,0,MODE_EMA,PRICE_CLOSE);
   ArrayResize(params,5);
//--- set ma_period
   params[0].type         =TYPE_INT;
   params[0].integer_value=fastPeriod;
//--- set ma_shift
   params[1].type         =TYPE_INT;
   params[1].integer_value=0;
//--- set ma_method
   params[2].type         =TYPE_INT;
   params[2].integer_value=MODE_EMA;
//--- set applied_price
   params[3].type         =TYPE_INT;
   params[3].integer_value=PRICE_CLOSE;

   h_FastMA=IndicatorCreate(Symbol(), Period(), IND_MA, 4, params);
   
   params[0].integer_value=slowPeriod;
   params[1].integer_value=300;
      
   h_SlowMA=IndicatorCreate(Symbol(), Period(), IND_MA, 4, params);
   
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   if(!timerIsSet) {
      sTime=TimeTradeServer();
      if(sTime % (Period()*60) >= 10 && sTime % (Period()*60) <= 20) {
         EventSetTimer(Period()*60);
         timerIsSet = true;
      }
   }
}
//+------------------------------------------------------------------+
void OnTimer() {
   trade();
}
Files:
 

1. Use

ArrayResize[fastBuffer,true];
ArrayResize[fslowBuffer,true];
ArrayResize[priceBuffer,true];

- Your code is hard to read


2. There is no technical data at all - at least you need to display not just a 'bool' comparison result, you need to display the numbers that you are comparing

 
Vladimir Karputov:

1. Use

- Your code is hard to read


2. There is no technical data at all - at least you need to display not just a 'bool' comparison result, you need to display the numbers that you are comparing

Thank you for diving into the problem. I found the answer.

The thing is the first tick doesn't appears at a timer event. When I set timer at last 10 seconds of trade period, error passed away.

Details:

I try to log MA1[1], MA2[1], MA1[0], MA2[0] numbers as you advised. At a moment log shows that theу are correspondingly equal. And I made a guess that in some moment when timer event occurs no ticks on current period is appeared. That's why the last closed bar is the same as for the previous timer event. Similarly for MA. Then MA1[1], MA2[1], MA1[0], MA2[0] are the same for two contiguous timer events. So first EA compares MA1 and MA2 twice before the crossing and we haven't conditions for start a position. And next EA compares MA1 and MA2 twice after the crossing. Thus it skips the signal. After setting timer at last 10 seconds of trade period problem disappeared.

I want to apologize for the fact that I thought it was an MT5 bug. And great thanks to you.
 
max-bad :

Thank you for diving into the problem. I found the answer.

The thing is the first tick doesn't appears at a timer event. When I set timer at last 10 seconds of trade period, error passed away.

Details:

I try to log MA1[1], MA2[1], MA1[0], MA2[0] numbers as you advised. At a moment log shows that theу are correspondingly equal. And I made a guess that in some moment when timer event occurs no ticks on current period is appeared. That's why the last closed bar is the same as for the previous timer event. Similarly for MA. Then MA1[1], MA2[1], MA1[0], MA2[0] are the same for two contiguous timer events. So first EA compares MA1 and MA2 twice before the crossing and we haven't conditions for start a position. And next EA compares MA1 and MA2 twice after the crossing. Thus it skips the signal. After setting timer at last 10 seconds of trade period problem disappeared.

I want to apologize for the fact that I thought it was an MT5 bug. And great thanks to you.

Why do you use a timer? You work in OnTick - and only when a new bar is born.

 
Vladimir Karputov:

Why do you use a timer? You work in OnTick - and only when a new bar is born.

Thanks. I'll do so!