iBars calculation is lagging when switching timeframe

 

Hi,

I wrote this simple ea to check for Donchain channels (free indicator in mt5) and moving average crossing and post alerts. The problem is once timeframe is changed manually for analysis, the OnInit() will rerun and variable barsTotal get refreshed to older smaller number. Then the iBar function inside OnTick() will re-calculated many times and multiple alerts posted indicating crossing occurred however with the same Close1 and Donchain values.

Is there a way to improve the code to avoid multiple false alerts and what am I missing? I can't find from forum anywhere how to resolve this. I just start learning mql5 coding from Youtube.


#property copyright "Copyright 2024, CCM"
#property link      ""
#property version   "1.00"
#include <Trade/Trade.mqh>

// Donchian Channels crossing

//+- Variables:  --------------------------------------------------------+
enum yn{
   Y,
   N,
};

input ENUM_TIMEFRAMES Timeframe = PERIOD_CURRENT;
input double Lots = 0.1;
input int TpPoints = 100;
input int SlPoints = 200;
input int TslPoints = 20;
input int TslTriggerPoints = 50;
input int AtrPeriods = 14;
input double atrFactor =1.5;
input string OrderComment = "Donchain trade";
input yn ShowVal = N;


//-Global VariablesP:
int Magic;
ENUM_TIMEFRAMES AtrTimeframe = PERIOD_D1;
int handleAtr;
int bars;
int barsTotal;
int barsTotalPrev;


string nameDc;
int handleDc;
string nameMa;
int handleMa;
int maPeriods;

MqlParam paramDc[];
MqlParam paramMa[];
ENUM_INDICATOR indicator_type;

CTrade trade;


//+- OnInit Initialization function  ------------------------------------+
int OnInit(){
   barsTotal = iBars(_Symbol,Timeframe);
   //handleMa = iMA(_Symbol,Timeframe,DcCandles,0,MODE_SMA,PRICE_CLOSE);
   handleAtr = iATR(_Symbol,AtrTimeframe,AtrPeriods);

   //-Set Magic value:
   MathSrand(GetTickCount()); 
   Magic = StringToInteger("-99" + IntegerToString(MathRand()%50));
   trade.SetExpertMagicNumber(Magic);
   
   //-Donchain handle:
   nameDc = ChartIndicatorName(0,0,0);
   handleDc = ChartIndicatorGet(0,0,nameDc);
   if(handleDc == INVALID_HANDLE) Print(__FUNCTION__," > Handle is invalid... Check the name (",nameDc,")!");
   
   //-Get Donchain properies:
   int paramsDc = IndicatorParameters(handleDc,indicator_type,paramDc);

   //-SMA handle:
   nameMa = ChartIndicatorName(0,0,1);
   handleMa = ChartIndicatorGet(0,0,nameMa);
   if(handleMa == INVALID_HANDLE) Print(__FUNCTION__," > Handle is invalid... Check the name (",nameMa,")!");

   //-Get SMA properies:
   int paramsMa = IndicatorParameters(handleMa,indicator_type,paramMa);
   Print(_Symbol,": OnInit Magic: ",Magic," nameDc :",nameDc," nameMa:",nameMa," Timeframe:",EnumToString(ENUM_TIMEFRAMES(Period())));

   return(INIT_SUCCEEDED);
}


//+- OnDenit deinitialization function  ---------------------------------+
void OnDeinit(const int reason){
   Comment(" ");
}


//+- OnTick Iteration Function  -----------------------------------------+
void OnTick(){
   //-Now Bid and Ask prices:
   double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);

   //-Trade: Open positions OR Pending orders:
   ENUM_TIMEFRAMES tickTimeframe = Period();
   bars = iBars(_Symbol,tickTimeframe);
   barsTotalPrev = barsTotal;
   
   if(barsTotal < bars){
      barsTotal = bars;
      
      //-SMA:
      double ma[];
      CopyBuffer(handleMa,MAIN_LINE,1,2,ma);
      maPeriods = paramMa[0].integer_value;

      //-ATR:
      double atr[];
      CopyBuffer(handleAtr,0,1,1,atr);
      
      //-Donchain:
      double dcHigher[];
      CopyBuffer(handleDc,0,1,2,dcHigher);
      double dcLower[];
      CopyBuffer(handleDc,2,1,2,dcLower);

      double dcHigh1 = dcHigher[1];
      double dcLow1 = dcLower[1];
      
      //-Alert of Donchain and SMA crossovers:
      double close1 = iClose(_Symbol,PERIOD_CURRENT,1);
      double close2 = iClose(_Symbol,PERIOD_CURRENT,2);

      if(close1 > dcHigh1 && close2 < dcHigh1){
         Alert(_Symbol,": Cross above Donchain Upper, close1: ",DoubleToString(close1,_Digits)," dcHigh1: ",DoubleToString(dcHigh1,_Digits)," Timeframe:",EnumToString(ENUM_TIMEFRAMES(tickTimeframe))," barsTotalPrev/Bars: ",barsTotalPrev,"/",bars);
         PlaySound("mixkit-interface-option-select-2573.wav");
      }else if(close1 < dcLow1 && close2 > dcLow1){
         Alert(_Symbol,": Cross below Donchain Lower, close1: ",DoubleToString(close1,_Digits)," dcLow1: ",DoubleToString(dcLow1,_Digits)," Timeframe:",EnumToString(ENUM_TIMEFRAMES(tickTimeframe))," barsTotalPrev/Bars: ",barsTotalPrev,"/",bars);
         PlaySound("mixkit-interface-option-select-2573.wav");
      }else if(close1 > ma[1] && close2 < ma[0]){
         Alert(_Symbol,": Cross above SMA. close1: ",DoubleToString(close1,_Digits)," SMA1: ",DoubleToString(ma[1],_Digits)," Timeframe:",EnumToString(ENUM_TIMEFRAMES(tickTimeframe))," barsTotalPrev/Bars: ",barsTotalPrev,"/",bars);
         PlaySound("alert.wav");
      }else if(close1 < ma[1] && close2 > ma[0]){
         Alert(_Symbol,": Cross below SMA. close1: ",DoubleToString(close1,_Digits)," SMA1: ",DoubleToString(ma[1],_Digits)," Timeframe:",EnumToString(ENUM_TIMEFRAMES(tickTimeframe))," barsTotalPrev/Bars: ",barsTotalPrev,"/",bars);
         PlaySound("alert.wav");
      }      
      
      //-Comments:
      if(ShowVal == Y){
         Comment("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
                 "\nATR(",AtrPeriods,"): ",DoubleToString(atr[0],_Digits),
                 "\nMA(",paramMa[0].integer_value,"): ",DoubleToString(ma[1],_Digits),
                 "\nbid: ",DoubleToString(bid,_Digits),
                 "\nask: ",DoubleToString(ask,_Digits),
                 "\nSpread: ",DoubleToString(ask - bid,_Digits),
                 "\nclose1: ",DoubleToString(close1,_Digits),
                 "\nclose2: ",DoubleToString(close2,_Digits),
                 "\ndcHigh1: ",DoubleToString(dcHigh1,_Digits),
                 "\ndcLow1: ",DoubleToString(dcLow1,_Digits),
                 "\nTimeframe: ",EnumToString(ENUM_TIMEFRAMES(tickTimeframe)),
                 "\nMagic: ",Magic);
      }else{
         Comment(" ");
      }
   }
}
//+------------------------------------------------------------------+
 

A picture is better than thousand words since my English is below par.

These are the multiple alerts generated with the same crossing value once timeframe is switched for example from D1 to H4, every time Tick refreshed, old history values of iBars() function are being output, which is wrong:


Files:
FalseAlerts.JPG  59 kb
 

I think I may have resolved the issue, although I not sure why is the case. It may have something to do with this thread:

https://www.mql5.com/en/forum/428139


So, I rearranged the code like this to handle the indicators at OnTick instead of at OnInit:

Clarification on previous thread: This issue only happens when switching from lower TF to higher TF for eg: from H4 to W1. Since the ea will need more time to load for chart in W1, not the other way around from D1 to H4 as previously stated.


#property copyright "Copyright 2024, CCM"
#property link      ""
#property version   "1.00"
#include <Trade/Trade.mqh>

// Donchian Channels crossing

//+- Variables:  --------------------------------------------------------+
enum yn{
   Y,
   N,
};

input ENUM_TIMEFRAMES Timeframe = PERIOD_CURRENT;
input double Lots = 0.1;
input int TpPoints = 100;
input int SlPoints = 200;
input int TslPoints = 20;
input int TslTriggerPoints = 50;
input int AtrPeriods = 14;
input double atrFactor =1.5;
input string OrderComment = "Donchain trade";
input yn ShowVal = N;


//-Global VariablesP:
int Magic;
ENUM_TIMEFRAMES AtrTimeframe = PERIOD_D1;
int handleAtr;
int bars;
int barsTotal;
int barsTotalPrev;


string nameDc;
int handleDc;
string nameMa;
int handleMa;
int maPeriods;

MqlParam paramDc[];
MqlParam paramMa[];
ENUM_INDICATOR indicator_type;

CTrade trade;


//+- OnInit Initialization function  ------------------------------------+
int OnInit(){
   barsTotal = iBars(_Symbol,Timeframe);
   //handleMa = iMA(_Symbol,Timeframe,DcCandles,0,MODE_SMA,PRICE_CLOSE);
   handleAtr = iATR(_Symbol,AtrTimeframe,AtrPeriods);

   //-Set Magic value:
   MathSrand(GetTickCount()); 
   Magic = StringToInteger("-99" + IntegerToString(MathRand()%50));
   trade.SetExpertMagicNumber(Magic);
   
   //-Donchain handle:
   nameDc = ChartIndicatorName(0,0,0);

   //-SMA handle:
   nameMa = ChartIndicatorName(0,0,1);
   Print(_Symbol,": OnInit Magic: ",Magic," nameDc :",nameDc," nameMa:",nameMa," Timeframe:",EnumToString(ENUM_TIMEFRAMES(Period())));

   return(INIT_SUCCEEDED);
}


//+- OnDenit deinitialization function  ---------------------------------+
void OnDeinit(const int reason){
   Comment(" ");
}


//+- OnTick Iteration Function  -----------------------------------------+
void OnTick(){
   //-Donchain handle:
   handleDc = ChartIndicatorGet(0,0,nameDc);
   if(handleDc == INVALID_HANDLE) Print(__FUNCTION__," > Handle is invalid... Check the name (",nameDc,")!");
   
   //-Get Donchain properies:
   int paramsDc = IndicatorParameters(handleDc,indicator_type,paramDc);

   //-SMA handle:
   handleMa = ChartIndicatorGet(0,0,nameMa);
   if(handleMa == INVALID_HANDLE) Print(__FUNCTION__," > Handle is invalid... Check the name (",nameMa,")!");

   //-Get SMA properies:
   int paramsMa = IndicatorParameters(handleMa,indicator_type,paramMa);

   //-Now Bid and Ask prices:
   double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
   double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);

   //-Trade: Open positions OR Pending orders:
   ENUM_TIMEFRAMES tickTimeframe = Period();
   bars = iBars(_Symbol,Timeframe);
   barsTotalPrev = barsTotal;
   
   if(barsTotal < bars){
      barsTotal = bars;
      
      //-SMA:
      double ma[];
      CopyBuffer(handleMa,MAIN_LINE,1,2,ma);
      maPeriods = paramMa[0].integer_value;

      //-ATR:
      double atr[];
      CopyBuffer(handleAtr,0,1,1,atr);
      
      //-Donchain:
      double dcHigher[];
      CopyBuffer(handleDc,0,1,2,dcHigher);
      double dcLower[];
      CopyBuffer(handleDc,2,1,2,dcLower);

      double dcHigh1 = dcHigher[1];
      double dcLow1 = dcLower[1];
      
      //-Alert of Donchain and SMA crossovers:
      double close1 = iClose(_Symbol,PERIOD_CURRENT,1);
      double close2 = iClose(_Symbol,PERIOD_CURRENT,2);

      if(close1 > dcHigh1 && close2 < dcHigh1){
         Alert(_Symbol,": Cross above Donchain Upper, close1: ",DoubleToString(close1,_Digits)," dcHigh1: ",DoubleToString(dcHigh1,_Digits)," Timeframe:",EnumToString(ENUM_TIMEFRAMES(tickTimeframe))," barsTotalPrev/Bars: ",barsTotalPrev,"/",bars);
         PlaySound("mixkit-interface-option-select-2573.wav");
      }else if(close1 < dcLow1 && close2 > dcLow1){
         Alert(_Symbol,": Cross below Donchain Lower, close1: ",DoubleToString(close1,_Digits)," dcLow1: ",DoubleToString(dcLow1,_Digits)," Timeframe:",EnumToString(ENUM_TIMEFRAMES(tickTimeframe))," barsTotalPrev/Bars: ",barsTotalPrev,"/",bars);
         PlaySound("mixkit-interface-option-select-2573.wav");
      }else if(close1 > ma[1] && close2 < ma[0]){
         Alert(_Symbol,": Cross above SMA. close1: ",DoubleToString(close1,_Digits)," SMA1: ",DoubleToString(ma[1],_Digits)," Timeframe:",EnumToString(ENUM_TIMEFRAMES(tickTimeframe))," barsTotalPrev/Bars: ",barsTotalPrev,"/",bars);
         PlaySound("alert.wav");
      }else if(close1 < ma[1] && close2 > ma[0]){
         Alert(_Symbol,": Cross below SMA. close1: ",DoubleToString(close1,_Digits)," SMA1: ",DoubleToString(ma[1],_Digits)," Timeframe:",EnumToString(ENUM_TIMEFRAMES(tickTimeframe))," barsTotalPrev/Bars: ",barsTotalPrev,"/",bars);
         PlaySound("alert.wav");
      }      
      
      //-Comments:
      if(ShowVal == Y){
         Comment("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
                 "\nATR(",AtrPeriods,"): ",DoubleToString(atr[0],_Digits),
                 "\nMA(",paramMa[0].integer_value,"): ",DoubleToString(ma[1],_Digits),
                 "\nbid: ",DoubleToString(bid,_Digits),
                 "\nask: ",DoubleToString(ask,_Digits),
                 "\nSpread: ",DoubleToString(ask - bid,_Digits),
                 "\nclose1: ",DoubleToString(close1,_Digits),
                 "\nclose2: ",DoubleToString(close2,_Digits),
                 "\ndcHigh1: ",DoubleToString(dcHigh1,_Digits),
                 "\ndcLow1: ",DoubleToString(dcLow1,_Digits),
                 "\nTimeframe: ",EnumToString(ENUM_TIMEFRAMES(tickTimeframe)),
                 "\nMagic: ",Magic);
      }else{
         Comment(" ");
      }
   }
}
//+------------------------------------------------------------------+
OnInit function processed before rates info is updated... how to fix?
OnInit function processed before rates info is updated... how to fix?
  • 2022.07.05
  • Jean Sebastien Paquet
  • www.mql5.com
Hi, Sometimes, when I manually change the symbol on a chart, there's a delay between the moment the chart loads from the saved cache and the moment...