//+------------------------------------------------------------------+
//|                                                  FractalsMod.mq4 |
//|                                                    Manel Sanchon |
//|                          modded CPU hog 2021                     |
//+------------------------------------------------------------------+
#property copyright "Manel Sanchon"
#property link      ""
#property strict

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 clrRed
#property indicator_width1 0
#property indicator_color2 clrBlue
#property indicator_width2 0
//---- input parameters
extern int leftbars      = 10;
extern int rightbars     = 10;
extern int shift         = 0;
extern bool debug        = false;

//---- buffers
double ExtUpperBuffer[];
double ExtLowerBuffer[];
string msg = "";
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
 {
   int initSucceeded = INIT_SUCCEEDED;
   if( Bars < (MathMax(leftbars,rightbars)+1) )  //  enough bars to run?
    {
      initSucceeded = INIT_FAILED;
      msg = StringConcatenate(__FUNCTION__," not enough bars, ", IntegerToString((MathMax(leftbars,rightbars)+1))," required, ",IntegerToString(Bars)," found.");
      Print(msg); Comment(msg);
    }
   //---- indicator buffers mapping  
   SetIndexBuffer(0,ExtUpperBuffer);
   SetIndexBuffer(1,ExtLowerBuffer);
   //---- drawing settings
   SetIndexStyle(0,DRAW_ARROW);
   SetIndexArrow(0,167);
   SetIndexStyle(1,DRAW_ARROW);
   SetIndexArrow(1,167);
   //----
   SetIndexEmptyValue(0,0.0);
   SetIndexEmptyValue(1,0.0);
   //---- name for DataWindow
   SetIndexLabel(0,"Fractal Up");
   SetIndexLabel(1,"Fractal Down");
   //---- initialization done   
   return(initSucceeded);
 }
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
 {
   ObjectDelete(0,"Fractal Up");
   ObjectDelete(1,"Fractal Down");
   if( (reason != REASON_INITFAILED) && (StringLen(msg) > 0) )
      Comment("");
 }
//+------------------------------------------------------------------+
//| 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[])
 {
   int startBar;
   if( prev_calculated < 1 ) // starting at the beginning
    {
      startBar = rates_total - (leftbars+1);
    }
   else  // new quote has arrived
    {
      startBar = prev_calculated - (leftbars+1);
    }
   //
   runIndicator(startBar, leftbars, rightbars);
   //
   return(rates_total);
 }
//+------------------------------------------------------------------+
void runIndicator(const int& startBar, const int& searchLeft, const int& searchRight)
 {
 
 	static datetime candle_time;
	if(Time[0]==candle_time)
	return;
	
   double Higher,Lower;
   int   countup=0;
   int   countdown=0;
   for(int Count=startBar; Count>=0; Count--)
    {
      int j, k;
      for(j=1; j <= searchLeft; j++)
       {
         if( Count+j < startBar )
          {
            if(High[Count] >= High[Count+j])
               countup++;
            if(Low[Count]<= Low[Count+j])
               countdown++;
          }
       }
      for(k=1; k <= searchRight; k++)
       {
         if( Count-k >= 0 )
          {
            if( High[Count] >= High[Count-k] )
               countup++;
            if( Low[Count] <= Low[Count-k] )
               countdown++;
          }
       }
      //
      if(countup==searchLeft+searchRight)
       {
         Higher = High[Count];
         if(debug)
          {
            msg = StringConcatenate("Higher Count: ",IntegerToString(Count),", CountUp: ",IntegerToString(countup),", CountDown: ",IntegerToString(countdown),"\n",
            "searchLeft: ",IntegerToString(searchLeft),",      searchRight: ",IntegerToString(searchRight),",    Fractal Bar: ",TimeToStr(Time[Count],TIME_DATE|TIME_MINUTES),"\n",
            "SearchLeft: ",TimeToStr(Time[Count+j],TIME_DATE|TIME_MINUTES),",      SearchRight: ",TimeToStr(Time[Count+k],TIME_DATE|TIME_MINUTES));
            Comment(msg);
          }
       }
      else 
         Higher = ExtUpperBuffer[Count-shift+1];
      //
      if(countdown==searchLeft+searchRight)
       {
         Lower = Low[Count];
         if(debug)
          {
            msg = StringConcatenate("Lower Count: ",IntegerToString(Count),", CountUp: ",IntegerToString(countup),", CountDown: ",IntegerToString(countdown),"\n",
            "searchLeft: ",IntegerToString(searchLeft),",      searchRight: ",IntegerToString(searchRight),",     Bar: ",TimeToStr(Time[Count],TIME_DATE|TIME_MINUTES),"\n",
            "SearchLeft: ",TimeToStr(Time[Count+j],TIME_DATE|TIME_MINUTES),",      SearchRight: ",TimeToStr(Time[Count+k],TIME_DATE|TIME_MINUTES));
            Comment(msg);
          }
       }
      else
         Lower=ExtLowerBuffer[Count-shift+1];
      //
      ExtUpperBuffer[Count-shift] = Higher;
      ExtLowerBuffer[Count-shift] = Lower;
      countup=0;
      countdown=0;
    }
    
    candle_time=Time[0];
 }
//+------------------------------------------------------------------+