The cross between two ma is being detected a candle late

 

Hello everyone, the title says it all. I'm trying to develop an EA that detects two moving averages crossover and open a trade at that point of intersection. All is going well except that the trade is happening some two or three candles late as seen on the graph (I've attached a photo of that). The point of intersection itself is detected late.


//+------------------------------------------------------------------+
//|                                                     question.mq5 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Trade/Trade.mqh>
#include <Trade\AccountInfo.mqh>
#include <Trade/SymbolInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Indicators\Trend.mqh>

CTrade trade;
CAccountInfo account;
CSymbolInfo symbolInfo;
CPositionInfo positionInfo;

CiMA slowIma;
CiMA fastIma;

datetime timestamp = 0;
int operationNumber = 0;

int OnInit()
  {
   if(!slowIma.Create(_Symbol, _Period, 40, 0, MODE_SMMA, PRICE_MEDIAN))
      return INIT_FAILED;
   slowIma.Redrawer(true);
   if(!fastIma.Create(_Symbol, _Period, 10, 0, MODE_SMA, PRICE_CLOSE))
      return INIT_FAILED;
   fastIma.Redrawer(true);
   return (INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   datetime currentTime = iTime(Symbol(), Period(), 0);
   if(timestamp == currentTime)
      return;
   timestamp = currentTime;
   if(!symbolInfo.RefreshRates())
      return;
   if(operationNumber < 5)
     {
      switch(didCross())
        {
         case crossFromBelow:
            Print("Cross from below");
            openDeal();
            break;
        }
     }
  }
enum CrossType
  {
   crossFromBelow,
   crossFromAbove,
   noCrossing,
  };
CrossType didCross()
  {
   fastIma.Refresh();
   slowIma.Refresh();

   double initialFastMa = fastIma.Main(
1 );
   double finalFastMa = fastIma.Main(
0 );
   double initialSlowMa = slowIma.Main(
1 );
   double finalSlowMa = slowIma.Main(
0 );
   bool currentSlowAboveFast = finalSlowMa > finalFastMa,
        prevSlowAboveFast = initialSlowMa > initialFastMa, crossed = currentSlowAboveFast != prevSlowAboveFast;
   if(crossed)
     {
      return currentSlowAboveFast ? crossFromAbove : crossFromBelow;
     }
   return noCrossing;
  }
//+------------------------------------------------------------------+
void openDeal()
  {
   if(trade.BuyStop(0.02, symbolInfo.Ask(), NULL,  NormalizeDouble(slowIma.Main(0), Digits()),  symbolInfo.Ask() + 50 * _Point))
     {
      operationNumber++;
      Print("Buy oparation number: ", operationNumber, " succeeded with\nPrice: ",  symbolInfo.Ask(), "\nMA value of: ", slowIma.Main(0));
     }
   else
     {
      Print("Buy oparation failed, Return code: ", trade.ResultRetcode(), ". Code descriptino: ", trade.ResultRetcodeDescription(), "oneMa: ", slowIma.Main(0));
     }
  }
//+------------------------------------------------------------------+
 

If you use bars zero and one, you might see multiple crosses as price moves up and down. You might see a cross and uncross leading to a false trade.

If you use bars one and two, price has definitely crossed.

You use zero and one but only look at the start of a new bar. That means the difference between the open and the previous bar's close. Of course, you are delayed a bar.