//+------------------------------------------------------------------+
//|                                          Barishpoltz Channel.mq4 |
//|                                                        SaiborEye |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "SaiborEye"
#property link      ""
 /*
Вариант индикатора, использующего фракталы  при  построении  и  отображение 
скользящих    каналов    Баришпольца.     Данный     релиз     предназначен 
для прикладной оценки возможности отказа от ручного построения, выявления и 
коррекции слабых мест,  предложения  по  вводу  дополнительных   параметров
 */
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Gold
#property indicator_color2 Coral
#property indicator_color3 Aquamarine
//---- input parameters
extern int RightLevel    = 3;     //    Отступ от правой границы графика (Номер бара, 0 - последний, не сформировавшийся)
extern int BetweenPeaks  = 4;      //  Минимальное расстояние между экстремумами (количество баров)
extern int MaxLength     = 600;    //   Максимальная разрешенная длина канала (количество баров)

//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_SECTION);
   SetIndexBuffer(0,ExtMapBuffer1);
   SetIndexEmptyValue(0,0.0);
   SetIndexLabel(0,"Top Border");
   
   SetIndexStyle(1,DRAW_SECTION);
   SetIndexBuffer(1,ExtMapBuffer2);
   SetIndexEmptyValue(1,0.0);
   SetIndexLabel(1,"Bottom Border");
   
   SetIndexStyle(2,DRAW_ARROW,STYLE_SOLID,3);
   SetIndexBuffer(2,ExtMapBuffer3);
   SetIndexEmptyValue(2,0.0);
   SetIndexArrow(2,159);
   SetIndexLabel(2,"Fractal");
//----
   
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
int CheckBorders(int X1, int X2, int X3, double Y1, double Y2, double Y3, bool TwoTop)
{
  int x, limit;
  if (X1>X2)
    limit=X1;
  else
    limit=X2;
  
  if (limit>2)
    limit=2;
    
  if(TwoTop)
    {// TOP TWO
    for(x=RightLevel; x<limit; x++)
      {// LINE LOOP-1   
      if(Y2+(x*1.0-X2*1.0)*(Y1-Y2)/(X1*1.0-X2*1.0)<High[x])
        return (1);
      }// LINE LOOP-1
      
    for(x=RightLevel; x<limit; x++)
      {// LINE LOOP-2
      if(Y3+(x*1.0-X3*1.0)*(Y1-Y2)/(X1*1.0-X2*1.0)>Low[x])
        return (-1);
      }// LINE LOOP-2
    return (0);
    }// TOP TWO
    
  if(!TwoTop)
    {// BOTTOM TWO
    for(x=RightLevel; x<limit; x++)
      {// LINE LOOP-3   
      if(Y2+(x*1.0-X2*1.0)*(Y1-Y2)/(X1*1.0-X2*1.0)>Low[x])
        return (-1);
      }// LINE LOOP-3
      
    for(x=RightLevel;x<limit;x++)
      {// LINE LOOP-4
      if(Y3+(x*1.0-X3*1.0)*(Y1-Y2)/(X1*1.0-X2*1.0)<High[x])
        return (1);
      }// LINE LOOP-4
    return (0);   
    }// BOTTOM TWO
    
   return (-1);}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
  int PosX1[2],PosX2,pos,pos1,pos2,limit;
  double value;
  bool Flag;
  int TopPeaksPos[];
  int TopPeaksIndex;
  int BottomPeaksPos[];   
  int BottomPeaksIndex;   
//----   
  limit=MaxLength;
  if (limit>Bars-2)
    limit=Bars-2;
    
  if(RightLevel<2)
    RightLevel=2;
    
  ArrayResize(TopPeaksPos,limit);
  ArrayResize(BottomPeaksPos,limit);     
  
  TopPeaksIndex=0;
  BottomPeaksIndex=0;
  
  ArrayInitialize(ExtMapBuffer1,0.0);
  ArrayInitialize(ExtMapBuffer2,0.0);
  ArrayInitialize(ExtMapBuffer3,0.0);
//----
  for(pos=RightLevel; pos<limit; pos++)
    {// MAIN SEEK LOOP
    if (High[pos]>High[pos-1] && High[pos]>High[pos-2])
      {
      if(High[pos]>High[pos+1]&&High[pos]>High[pos+2])
        {
        TopPeaksPos[TopPeaksIndex]=pos;
        TopPeaksIndex++;
        }
      }
        
    if (Low[pos]<Low[pos-1] && Low[pos]<Low[pos-2])
      {
      if(Low[pos]<Low[pos+1]&&Low[pos]<Low[pos+2])
        {
        BottomPeaksPos[BottomPeaksIndex]=pos;
        BottomPeaksIndex++;
        }
      }
    }// MAIN SEEK LOOP
//----
  if (BottomPeaksIndex<TopPeaksIndex)
    limit=BottomPeaksIndex;
  else 
    limit=TopPeaksIndex;
 
  for (pos=0; pos<limit; pos++)
    {// SEEK LOOP
    if (TopPeaksPos[pos]<BottomPeaksPos[pos])
      {// TOP NEARLY     
      for(pos1=pos; pos1<TopPeaksIndex; pos1++)
        {// SECOND POINT SEEK     
        for(pos2=0; pos2<BottomPeaksIndex; pos2++)
          {
          if(BottomPeaksPos[pos2]<=TopPeaksPos[pos1])
            {
            if(BottomPeaksPos[pos2]>=TopPeaksPos[pos])
              {
              if(TopPeaksPos[pos1]-TopPeaksPos[pos]>BetweenPeaks)
                {
                if(CheckBorders(TopPeaksPos[pos], TopPeaksPos[pos1], BottomPeaksPos[pos2], High[TopPeaksPos[pos]], High[TopPeaksPos[pos1]], Low[BottomPeaksPos[pos2]], TRUE)==0)
                  {// DRAWING     
                  ExtMapBuffer1[0] = (0-TopPeaksPos[pos])*(High[TopPeaksPos[pos1]]-High[TopPeaksPos[pos]])/(TopPeaksPos[pos1]-TopPeaksPos[pos])+High[TopPeaksPos[pos]];
                  ExtMapBuffer1[TopPeaksPos[pos1]] = High[TopPeaksPos[pos1]];   
                  ExtMapBuffer2[0] = Low[BottomPeaksPos[pos2]]+(0-BottomPeaksPos[pos2])*(High[TopPeaksPos[pos1]]-High[TopPeaksPos[pos]])/(TopPeaksPos[pos1]-TopPeaksPos[pos]);
                  ExtMapBuffer2[TopPeaksPos[pos1]] = Low[BottomPeaksPos[pos2]]+(TopPeaksPos[pos1]-BottomPeaksPos[pos2])*(High[TopPeaksPos[pos1]]-High[TopPeaksPos[pos]])/(TopPeaksPos[pos1]-TopPeaksPos[pos]);   
                  ExtMapBuffer3[TopPeaksPos[pos]] = High[TopPeaksPos[pos]];
                  ExtMapBuffer3[TopPeaksPos[pos1]] = High[TopPeaksPos[pos1]];
                  ExtMapBuffer3[BottomPeaksPos[pos2]] = Low[BottomPeaksPos[pos2]];
                  return (0);
                  }// DRAWING     
                }
              }
            }
          }        
        }// SECOND POINT SEEK     
      }
    else 
      {// BOTTOM NEARLY
      for(pos1=pos; pos1<BottomPeaksIndex; pos1++)
        {// SECOND POINT SEEK     
        for(pos2=0; pos2<TopPeaksIndex; pos2++)
          {
          if(TopPeaksPos[pos2]<=BottomPeaksPos[pos1])
            {
            if(TopPeaksPos[pos2]>=BottomPeaksPos[pos])
              {
              if(BottomPeaksPos[pos1]-BottomPeaksPos[pos]>BetweenPeaks)
                {
                if(CheckBorders(BottomPeaksPos[pos], BottomPeaksPos[pos1], TopPeaksPos[pos2], Low[BottomPeaksPos[pos]], Low[BottomPeaksPos[pos1]], High[TopPeaksPos[pos2]], FALSE)==0)
                  {// DRAWING
                  ExtMapBuffer1[0] = (0-BottomPeaksPos[pos])*(Low[BottomPeaksPos[pos1]]-Low[BottomPeaksPos[pos]])/(BottomPeaksPos[pos1]-BottomPeaksPos[pos])+Low[BottomPeaksPos[pos]];
                  ExtMapBuffer1[BottomPeaksPos[pos1]] = Low[BottomPeaksPos[pos1]];   
                  ExtMapBuffer2[0] = High[TopPeaksPos[pos2]]+(0-TopPeaksPos[pos2])*(Low[BottomPeaksPos[pos1]]-Low[BottomPeaksPos[pos]])/(BottomPeaksPos[pos1]-BottomPeaksPos[pos]);
                  ExtMapBuffer2[BottomPeaksPos[pos1]] = High[TopPeaksPos[pos2]]+(BottomPeaksPos[pos1]-TopPeaksPos[pos2])*(Low[BottomPeaksPos[pos1]]-Low[BottomPeaksPos[pos]])/(BottomPeaksPos[pos1]-BottomPeaksPos[pos]);   
                  ExtMapBuffer3[BottomPeaksPos[pos]] = Low[BottomPeaksPos[pos]];ExtMapBuffer3[BottomPeaksPos[pos1]]=Low[BottomPeaksPos[pos1]];
                  ExtMapBuffer3[TopPeaksPos[pos2]] = High[TopPeaksPos[pos2]];
                  return (0);
                  }// DRAWING     
                }
              }
            }
          }        
        }// SECOND POINT SEEK     
      }// BOTTOM NEARLY     
    }// SEEK LOOP
  
  return(0);
  }
//+------------------------------------------------------------------+