//+------------------------------------------------------------------+
//|                                               testIndicaotor.mq4 |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+

//| trying to avoid big load of indicator in MT4 ...

#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window

#property indicator_buffers 5
#property indicator_color1 clrLime
#property indicator_color2 clrMagenta
#property indicator_color3 clrYellow
#property indicator_color4 clrAqua
#property indicator_color5 clrYellow
#property indicator_width1 1
#property indicator_width2 1
#property indicator_width3 1
#property indicator_width4 1
#property indicator_width5 1


//+------------------------------------------------------------------+
input    int      lookbackcandles                  = 1000;
input    int      MA1period                        = 10;
input    int      MA2period                        = 20;
input    int      MA3period                        = 800;
input    double   refreshMins                      = 2.5;   // refresh in minutes

         double   MA1buffer[],MA2buffer[],MA3buffer[];
         double   upArrow[],dnArrow[];
         bool     isnewbar,isrefreshready,isatbeginning;
         datetime lastbartime,lastrefreshtime;
         int      refreshSeconds,limit;
         
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   
	SetIndexBuffer(0,MA1buffer);
	SetIndexBuffer(1,MA2buffer);	
	SetIndexBuffer(2,upArrow);	
	SetIndexBuffer(3,dnArrow);	
	SetIndexBuffer(4,MA3buffer);	
	//---
	SetIndexStyle(0,DRAW_LINE);	
	SetIndexStyle(1,DRAW_LINE);	
	SetIndexStyle(2,DRAW_ARROW);	
	SetIndexStyle(3,DRAW_ARROW);	
	SetIndexStyle(4,DRAW_LINE);	
	//---
	SetIndexArrow(2,221);
	SetIndexArrow(3,222);
	//---
   SetIndexLabel(0,"MA1");
   SetIndexLabel(1,"MA2");
   SetIndexLabel(2,"up signal");
   SetIndexLabel(3,"dn signal");
   SetIndexLabel(4,"MA3");
   
   IndicatorShortName("testIndicator");
   
   //-----------------------------------------
   isatbeginning     = true;
   lastbartime       = iTime(NULL,0,lookbackcandles);
   isnewbar          = true;
   isrefreshready    = true;
   lastrefreshtime   = iTime(NULL,0,lookbackcandles);
   refreshSeconds    = (int) (refreshMins*60);
   EventSetTimer(refreshSeconds);
   
//---
   return(INIT_SUCCEEDED);
  }
  
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---

  if (isatbeginning) {
      isatbeginning = false;
      DoInit();
  } // if

  int counted_bars   = IndicatorCounted();
  if (counted_bars<0) return(-1);
  if (counted_bars>0) counted_bars--;
  
  limit  = (int) MathMin(Bars,lookbackcandles)-counted_bars;
     
  if (iTime(NULL,0,0) > lastbartime) { // newbar
      lastbartime = iTime(NULL,0,0);
      isnewbar    = true;  
  } // if 
  else {
      isnewbar    = false;
  } // else
  
  if (TimeCurrent()>(lastrefreshtime+refreshSeconds)) {
      lastrefreshtime   = TimeCurrent();
      isrefreshready    = true;
  } // if
  else {
      isrefreshready    = false;  
  } // else 
   
  //----------------------------------------------
  if (isnewbar || isrefreshready) { // begin calculation ????
      DoFirstCalculation(limit);
      DoSecondCalculation(limit);
  } // if
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
  
  
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {

   limit  = (int) MathMin(Bars,lookbackcandles);
   DoFirstCalculation(limit);
   DoSecondCalculation(limit);
   
  }
  
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
 EventKillTimer();
}  
  
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   
  }
  
  
//+------------------------------------------------------------------+
void DoInit() {
   ArrayInitialize(MA1buffer,EMPTY_VALUE);
   ArrayInitialize(MA2buffer,EMPTY_VALUE);
   ArrayInitialize(upArrow,EMPTY_VALUE);
   ArrayInitialize(dnArrow,EMPTY_VALUE);
   ArrayInitialize(MA3buffer,EMPTY_VALUE);
} 
  
//+------------------------------------------------------------------+
void DoFirstCalculation(int Limit) {
   double   MA1priceCurrent, MA2priceCurrent;
   double   MA1pricePrevious, MA2pricePrevious;
   //---
   for (int i=Limit; i>=0; i--) {
      MA1priceCurrent   = iMA(NULL,0,MA1period,0,MODE_EMA,PRICE_CLOSE,i);
      MA2priceCurrent   = iMA(NULL,0,MA2period,2,MODE_EMA,PRICE_CLOSE,i);
      MA1pricePrevious  = iMA(NULL,0,MA1period,0,MODE_EMA,PRICE_CLOSE,i+1);
      MA2pricePrevious  = iMA(NULL,0,MA2period,2,MODE_EMA,PRICE_CLOSE,i+1);
   
      //---
      MA1buffer[i]      = MA1priceCurrent;
      MA2buffer[i]      = MA2priceCurrent;
   
      //---
      if ((MA1pricePrevious<=MA2pricePrevious)&&(MA1priceCurrent>MA2priceCurrent)) {
         upArrow[i]     = iLow(NULL,0,i);
      } // if//---
      if ((MA1pricePrevious>=MA2pricePrevious)&&(MA1priceCurrent<MA2priceCurrent)) {
         dnArrow[i]     = iHigh(NULL,0,i);
      } // if
   } // for
} 


//+------------------------------------------------------------------+
void DoSecondCalculation(int Limit) {
   
   //---
   for (int i=Limit; i>=0; i--) {
      MA3buffer[i]   = iMAOnArray(MA1buffer,0,MA3period,-10,MODE_EMA,i);  // ERROR ??? 
   } // for  
   
}

         
      
      
  
//+------------------------------------------------------------------+
