//+------------------------------------------------------------------+
//|                                                 FractalLevel.mq4 |
//|                                   Copyright 2016, Parsegov Artem |
//|                     https://www.mql5.com/ru/users/lastevangelion |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Parsegov Artem"
#property link      "https://www.mql5.com/ru/users/lastevangelion"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 5
#define   count         5

int MaxBars = 500;
extern int Amplitude = 60;
double Delta ; 

double  Fractal[30][2];
double  Result[count];
double Level0[], Level1[], Level2[], Level3[], Level4[];
int n;
color  ColorLevel = DeepPink;



//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
    switch(Period())
      {
      case PERIOD_M1 :  Delta = 2;  break;
      case PERIOD_M5 :  Delta = 3;  break;
      case PERIOD_M15:  Delta = 5;  break;
      case PERIOD_M30:  Delta = 10; break;
      case PERIOD_H1 :  Delta = 15; break;
      case PERIOD_H4 :  Delta = 20; break;
      case PERIOD_D1 :  Delta = 30; break;
      case PERIOD_W1 :  Delta = 50; break;
      }
  
  MaxBars = MathMin(MaxBars, Bars-Amplitude);
   if(Digits==3 || Digits==5)                // проверка количества знаков
     {
      Delta*=10;
     }
     
   IndicatorShortName("FractalLevel");
   
   SetIndexBuffer(0, Level0);
   SetIndexLabel (0, "Level0"); 
   SetIndexStyle ( 0, DRAW_SECTION, STYLE_SOLID, 2, ColorLevel );
   SetIndexBuffer(1, Level1);
   SetIndexLabel (1, "Level1"); 
   SetIndexStyle (1, DRAW_LINE, STYLE_DASH, 1, ColorLevel );
   SetIndexBuffer(2, Level2);
   SetIndexLabel (2, "Level2"); 
   SetIndexStyle (2, DRAW_LINE, STYLE_DASH, 1, ColorLevel );
   SetIndexBuffer(3, Level3);
   SetIndexLabel (3, "Level3"); 
   SetIndexStyle (3, DRAW_LINE, STYLE_DASH, 1, ColorLevel );   
   SetIndexBuffer(4, Level4);
   SetIndexLabel (4, "Level4"); 
   SetIndexStyle (4, DRAW_LINE, STYLE_SOLID, 2, ColorLevel );    
   
   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[])
  {
  
   int  Counted_bars=IndicatorCounted(); // Количество просчитанных баров 
   int i= Bars-Counted_bars-1;           // Индекс первого непосчитанного
   if (i>MaxBars-1)                      // Если много баров то ..
      i=MaxBars-1;                       // ..рассчитывать заданное колич.
   while(i>=1)  {                        // Цикл по непосчитанным барам
   i --;  
   n = 5;
   

   
   Fractal[0][1] = Level0[i+1]; Fractal[0][0] = 1;
   Fractal[1][1] = Level1[i+1]; Fractal[1][0] = 1;
   Fractal[2][1] = Level2[i+1]; Fractal[2][0] = 1;
   Fractal[3][1] = Level3[i+1]; Fractal[3][0] = 1;
   Fractal[4][1] = Level4[i+1]; Fractal[4][0] = 1;             
   
  
  for (int j = i; j <=  i + Amplitude; j ++) {
      double fractals=iFractals(Symbol(),0,MODE_UPPER,j);
      if (fractals > 0 )
      if ( !FindMatchFractal(fractals) )  {
         Fractal[n][1] = fractals;
         Fractal[n][0] = 1;
         n ++;
         }

      fractals=iFractals(Symbol(),0,MODE_LOWER,j);
      if  (fractals > 0 )
      if ( !FindMatchFractal(fractals) )  {
         Fractal[n][1] = fractals;
         Fractal[n][0] = 1;
         n ++;
         }       
       
     
  } //for (int j = i; j <=  i + Amplitude; j ++) {
  ArraySort(Fractal,WHOLE_ARRAY,0,MODE_DESCEND);
 for (int k = 0 ; k < count ; k++) {
 Result[k] = Fractal[k][1];
 }  
 ArraySort(Result,WHOLE_ARRAY,0,MODE_ASCEND);

Level0[i] = Result[0];
Level1[i] = Result[1];
Level2[i] = Result[2];
Level3[i] = Result[3];
Level4[i] = Result[4]; 
 
  
  } //   for (int i = MaxBars - 1 - c; i >= workbar; i --) 
   return(rates_total);
  }


bool FindMatchFractal ( double fractals) {
bool Found = false;
for ( int k = 0; k < n; k ++) {
               if ( MathAbs(Fractal[k][1] - fractals) < Delta*Point ) {
               Fractal[k][0] ++;
               Found = true;
               }
            }
return(Found);
}