//+------------------------------------------------------------------+
//|                                          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=2;//  Минимальное расстояние между экстремумами (количество баров)
extern int       MaxLength=600;//   Максимальная разрешенная длина канала (количество баров)
extern double    PeakLevel=10.0;//  Высота пика, превысив которую он имеет право называться экстремумом (пункты)

//---- 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,"Peak");
//----
   PeakLevel*=Point;
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
int CheckBorders(int X1,int X2,int X3,double Y1,double Y2,double Y3){
int x,limit;
   if(X1>X2)limit=X1;else limit=X2;
   if(Y1>Y3&&Y2>Y3){// TOP TWO
   for(x=0;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=0;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(Y1<Y3&&Y2<Y3){// BOTTOM TWO
   for(x=0;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=0;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,posminmax,pos,pos1,pos2,limit;//,counted_bars=IndicatorCounted();
   double value;
   bool Flag;
   int TopPeaksPos[];
   int TopPeaksIndex;
   int BottomPeaksPos[];   
   int BottomPeaksIndex;   
//----   
     limit=MaxLength;if(limit>Bars-2)limit=Bars-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 LOOP   
   if(pos>RightLevel&&pos<limit-1)if(High[pos]>=High[pos-1]&&High[pos]>=High[pos+1]){// TOP PEAKS
   Flag=TRUE;
   for(pos1=pos-1;pos1>=RightLevel;pos1--){if(High[pos1]>High[pos]){Flag=FALSE;break;}
   if(High[pos1]<=High[pos]-PeakLevel)break;}
   if(Flag)if(pos1==RightLevel-1)Flag=FALSE;
               if(Flag)for(pos1=pos+1;pos1<limit;pos1++){if(High[pos1]>High[pos]){Flag=FALSE;break;}
   if(High[pos1]<=High[pos]-PeakLevel)break;}
   if(Flag)if(pos1==limit)Flag=FALSE;
   if(Flag){TopPeaksPos[TopPeaksIndex]=pos;TopPeaksIndex++;}
      }// TOP PEAKS
//----      
   if(pos>RightLevel&&pos<limit-1)if(Low[pos]<=Low[pos-1]&&Low[pos]<=Low[pos+1]){// BOTTOM PEAKS
   Flag=TRUE;  for(pos1=pos-1;pos1>=RightLevel;pos1--){if(Low[pos1]<Low[pos]){Flag=FALSE;break;}
   if(Low[pos1]>=Low[pos]+PeakLevel)break;}
   if(Flag)if(pos1==RightLevel-1)Flag=FALSE;
               if(Flag)for(pos1=pos+1;pos1<limit;pos1++){if(Low[pos1]<Low[pos]){Flag=FALSE;break;}
   if(Low[pos1]>=Low[pos]+PeakLevel)break;}
   if(Flag)if(pos1==limit)Flag=FALSE;
   if(Flag){BottomPeaksPos[BottomPeaksIndex]=pos;BottomPeaksIndex++;}
         }// BOTTOM PEAKS   
      }// MAIN LOOP
//----
     if(BottomPeaksIndex>TopPeaksIndex)limit=BottomPeaksIndex;else limit=TopPeaksIndex;
     for(pos=0;pos<limit;pos++){// SEEK LOOP
     if(pos<TopPeaksIndex&&pos<BottomPeaksIndex)if(TopPeaksPos[pos]<BottomPeaksPos[pos]){// TOP NEARLY     
     for(pos1=pos;pos1<TopPeaksIndex;pos1++){// SECOND POINT SEEK
     value=Low[BottomPeaksPos[pos]]+10000.0;posminmax=-1;
     for(pos2=pos;BottomPeaksPos[pos2]<=TopPeaksPos[pos1] && BottomPeaksPos[pos2]>=TopPeaksPos[pos];pos2++)
     if(value>Low[BottomPeaksPos[pos2]]){value=Low[BottomPeaksPos[pos2]];posminmax=pos2;}     
     if(posminmax>-1)if(TopPeaksPos[pos1]-TopPeaksPos[pos]>BetweenPeaks)if(CheckBorders(TopPeaksPos[pos],TopPeaksPos[pos1],BottomPeaksPos[posminmax],
     High[TopPeaksPos[pos]],High[TopPeaksPos[pos1]],Low[BottomPeaksPos[posminmax]])==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[posminmax]]+(0-BottomPeaksPos[posminmax])*
      (High[TopPeaksPos[pos1]]-High[TopPeaksPos[pos]])/(TopPeaksPos[pos1]-TopPeaksPos[pos]);
   ExtMapBuffer2[TopPeaksPos[pos1]] = Low[BottomPeaksPos[posminmax]]+(TopPeaksPos[pos1]-BottomPeaksPos[posminmax])*
      (High[TopPeaksPos[pos1]]-High[TopPeaksPos[pos]])/(TopPeaksPos[pos1]-TopPeaksPos[pos]);   
   ExtMapBuffer3[TopPeaksPos[pos]]=High[TopPeaksPos[pos]];ExtMapBuffer3[TopPeaksPos[pos1]]=High[TopPeaksPos[pos1]];
   ExtMapBuffer3[BottomPeaksPos[posminmax]]=Low[BottomPeaksPos[posminmax]];
     return (0);
      }// DRAWING     
         }// SECOND POINT SEEK     
     }else {// BOTTOM NEARLY
     for(pos1=pos;pos1<BottomPeaksIndex;pos1++){// SECOND POINT SEEK
     value=High[TopPeaksPos[pos]]-10000.0;posminmax=-1;
     for(pos2=pos;TopPeaksPos[pos2]<=BottomPeaksPos[pos1] && TopPeaksPos[pos2]>=BottomPeaksPos[pos];pos2++)
     if(value<High[TopPeaksPos[pos2]]){value=High[TopPeaksPos[pos2]];posminmax=pos2;}
     if(posminmax>-1)if(BottomPeaksPos[pos1]-BottomPeaksPos[pos]>BetweenPeaks)if(CheckBorders(BottomPeaksPos[pos],BottomPeaksPos[pos1],TopPeaksPos[posminmax],
     Low[BottomPeaksPos[pos]],Low[BottomPeaksPos[pos1]],High[TopPeaksPos[posminmax]])==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[posminmax]]+(0-TopPeaksPos[posminmax])*
      (Low[BottomPeaksPos[pos1]]-Low[BottomPeaksPos[pos]])/(BottomPeaksPos[pos1]-BottomPeaksPos[pos]);
   ExtMapBuffer2[BottomPeaksPos[pos1]] = High[TopPeaksPos[posminmax]]+(BottomPeaksPos[pos1]-TopPeaksPos[posminmax])*
      (Low[BottomPeaksPos[pos1]]-Low[BottomPeaksPos[pos]])/(BottomPeaksPos[pos1]-BottomPeaksPos[pos]);   
   ExtMapBuffer3[BottomPeaksPos[pos]]=Low[BottomPeaksPos[pos]];ExtMapBuffer3[BottomPeaksPos[pos1]]=Low[BottomPeaksPos[pos1]];
   ExtMapBuffer3[TopPeaksPos[posminmax]]=High[TopPeaksPos[posminmax]];
     return (0);
      }// DRAWING     
            }// SECOND POINT SEEK     
         }// BOTTOM NEARLY     
     }// SEEK LOOP
   return(0);
  }
//+------------------------------------------------------------------+