//+----------------------------------------------------------------------+
//|ZigZag с чилами Песавенто                                             |
//|----------------------------------------------------------------------+                                                                  |
//|ExtHidden - 0 - все линии скрыты. Обычный ZigZag.                     |
//|            1 - показывает все линии между фракталами, у которых      |
//|                процент восстановления >0.21 и <5.                    |
//|            2 - показывает только те  линии, где процент восстано-    |  
//|                вления равен числам Песавенто (и 0.866 для постро-    |
//|                ения паттернов Gartley)                               |
//|            3 - показывает числа, перечисленные в пункте 2            |
//|                и соответствующие линии                               |
//|            4 - показывает числа не Песавенто и соответствующие линии |
//|                                                                      |
//|                                                                      |
//|ExtFractal - количество фракталов (максимумов, минимумов),            |
//|             от которых идут линии к другим фракталам                 |
//|                                                                      |
//|ExtFractalEnd - количество фракталов, к которым идут линии            |
//|                дальше этого фрактала соединяющих линий не будет      |
//|                Если ExtFractalEnd=0 то последний фрактал равен       |
//|                максимальному числу фракталов.                        |
//|                Минимальное значение ExtFractalEnd=5                  |
//|                                                                      |
//|ExtDeltaType -    0 - выводятся проценты восстановления "как есть"    |
//|                  1 - расчет допуска (%-число Песавенто)<ExtDelta     |
//|                  2 - ((%-число Песавенто)/число Песавенто)<ExtDelta  |
//|                                                                      |
//|                                                                      |
//|ExtDelta - (допуск) отклонение в расчете. Задает величину             |
//|           потенциальной разворотной зоны.                            |
//|                  должно быть 0<ExtDelta<1                            |
//|                                                                      |
//|ExtFibo  - true - выводятся уровни Фибоначчи                          |
//|           false - не выводятся уровни Фибоначчи (относительно        |
//|                   предпоследнего колена ZigZag-a)                    |
//|                                                                      |
//+----------------------------------------------------------------------+
#property copyright "nen@.....ru"
#property link      "http://onix-trade.net/forum/index.php?act=post&do=reply_post&f=9&t=118"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
//---- indicator parameters
extern int ExtDepth=12;
extern int ExtHidden=1;
extern int ExtFractal=10;
extern int ExtFractalEnd=10;
extern double ExtDelta=0.04;
extern int ExtDeltaType=1;
extern bool ExtFibo=false;
extern color ExtLine=DarkBlue;
extern color ExtPesavento=Yellow;
extern color ExtGartley866=GreenYellow;
extern color ExtNotFibo=SlateGray;
extern int ExtDeviation=5;
extern int ExtBackstep=3;
//---- indicator buffers
// Массив для отрисовки ZigZag
double zz[];
// Массив минимумов черновой
double ExtMapBuffer[];
// Массив максимумов черновой
double ExtMapBuffer2[];

// Массив чисел Песавенто (Фибы и модифицированные Фибы)
double fi[]={0.382, 0.5, 0.618, 0.707, 0.786, 0.841, 0.886, 1.0, 1.128, 1.272, 1.414, 1.5, 1.618, 2.0, 2.414, 2.618, 4.0};
string fitxt[]={ ".382", "0.5", ".618", ".707", ".786", ".841", ".886", "1.0", "1.128", "1.272", "1.414", "1.5", "1.618", "2.0", "2.414", "2.618", "4.0" };
// Матрица для поиска исчезнувших баров afr - массив значений времени пяти последних фракталов + одна ячейка - признак инициализации
// afrl - минимумы, afrh - максимумы
int afr[]={0.0,0.0,0.0,0.0,0.0,0.0};
double afrl[]={0.0,0.0,0.0,0.0,0.0}, afrh[]={0.0,0.0,0.0,0.0,0.0};

double HL,HLp,kk,kj,Angle;
// LowPrim,HighPrim,LowLast,HighLast - значения минимумов и максимумов баров
double LowPrim,HighPrim,LowLast,HighLast;
// numLowPrim,numHighPrim,numLowLast,numHighLast -номера баров
int numLowPrim,numHighPrim,numLowLast,numHighLast,k,k1,k2,ki,countLow1,countHigh1,shift,shift1;
// Время свечи с первым от нулевого бара фракталом
int timeFr1,timeFr1new,timeFr2Low,timeFr2High;
// Количество линий, идущих от первого от нулевого бара фрактала к соседним фракталам
int countLineFr1;
// Счетчик фракталов
int countFr;
// Бар, до которого надо рисовать соединительные линии от нулевого бара
int countBarEnd=0;
// Бар, до которого надо пересчитывать от нулевого бара
int numBar=0;
// Номер объекта
int numOb;
//Mаксимум или минимум бара первого фрактала (и предыдущего фрактала)
double hFr1, lFr1, hFr2, lFr2;
// Флаги
// flagFrNew=true - образовался новый фрактал или первый фрактал сместился на другой бар. =false - по умолчанию.
// flagFr=true - последний фрактал максимум. false - последний фрактал минимум.
bool flagLow,flagHigh,flagFr,flagFrNew=false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   IndicatorBuffers(5);
//---- drawing settings
   SetIndexStyle(0,DRAW_SECTION);
//---- indicator buffers mapping
   SetIndexBuffer(0,zz);
   SetIndexBuffer(1,ExtMapBuffer);
   SetIndexBuffer(2,ExtMapBuffer2);
   SetIndexEmptyValue(0,0.0);
   ArraySetAsSeries(zz,true);
   ArraySetAsSeries(ExtMapBuffer,true);
   ArraySetAsSeries(ExtMapBuffer2,true);
//---- indicator short name
   IndicatorShortName("ZZ("+ExtDepth+")");
//---- initialization done
   return(0);
  }
//+------------------------------------------------------------------+
//| Деинициализация. Удаление всех трендовых линий и текстовых объектов
//+------------------------------------------------------------------+
int deinit(){ ObjectsDeleteAll(0,2); ObjectsDeleteAll(0,21); ObjectDelete("Fibo"); return(0);}
//********************************************************
int start()
  {
   int counted_bars=IndicatorCounted();

   if( counted_bars<0 )
   {
      Alert("Сбой расчета индикатора");
      return(-1);
   }

//  ZigZag из МТ. Начало.
   int    shift, back,lasthighpos,lastlowpos;
   double val,res;
   double curlow,curhigh,lasthigh,lastlow;

   for(shift=Bars-ExtDepth; shift>=0; shift--)
     {
      val=Low[Lowest(NULL,0,MODE_LOW,ExtDepth,shift)];
      if(val==lastlow) val=0.0;
      else 
        { 
         lastlow=val; 
         if((Low[shift]-val)>(ExtDeviation*Point)) val=0.0;
         else
           {
            for(back=1; back<=ExtBackstep; back++)
              {
               res=ExtMapBuffer[shift+back];
               if((res!=0)&&(res>val)) ExtMapBuffer[shift+back]=0.0; 
              }
           }
        } 
      ExtMapBuffer[shift]=val;
      //--- high
      val=High[Highest(NULL,0,MODE_HIGH,ExtDepth,shift)];
      if(val==lasthigh) val=0.0;
      else 
        {
         lasthigh=val;
         if((val-High[shift])>(ExtDeviation*Point)) val=0.0;
         else
           {
            for(back=1; back<=ExtBackstep; back++)
              {
               res=ExtMapBuffer2[shift+back];
               if((res!=0)&&(res<val)) ExtMapBuffer2[shift+back]=0.0; 
              } 
           }
        }
      ExtMapBuffer2[shift]=val;
     }

   // final cutting 
   lasthigh=-1; lasthighpos=-1;
   lastlow=-1;  lastlowpos=-1;

   for(shift=Bars-ExtDepth; shift>=0; shift--)
     {
      curlow=ExtMapBuffer[shift];
      curhigh=ExtMapBuffer2[shift];
      if((curlow==0)&&(curhigh==0)) continue;
      //---
      if(curhigh!=0)
        {
         if(lasthigh>0) 
           {
            if(lasthigh<curhigh) ExtMapBuffer2[lasthighpos]=0;
            else ExtMapBuffer2[shift]=0;
           }
         //---
         if(lasthigh<curhigh || lasthigh<0)
           {
            lasthigh=curhigh;
            lasthighpos=shift;
           }
         lastlow=-1;
        }
      //----
      if(curlow!=0)
        {
         if(lastlow>0)
           {
            if(lastlow>curlow) ExtMapBuffer[lastlowpos]=0;
            else ExtMapBuffer[shift]=0;
           }
         //---
         if((curlow<lastlow)||(lastlow<0))
           {
            lastlow=curlow;
            lastlowpos=shift;
           } 
         lasthigh=-1;
        }
     }
  
   countLow1=0;
   countHigh1=0;

   for(shift=Bars-1; shift>=0; shift--)
     {
      zz[shift]=ExtMapBuffer[shift];
      if(shift>=Bars-ExtDepth) {ExtMapBuffer2[shift]=0.0;ExtMapBuffer[shift]=0.0; zz[shift]=0.0;}
      else
        {
         res=ExtMapBuffer2[shift];
         if(res!=0.0) zz[shift]=res;
        }
        if (ExtMapBuffer[shift]>0.0) {countLow1++;}
        if (ExtMapBuffer2[shift]>0.0) {countHigh1++;}
     }
// ZigZag из МТ. Конец. Добавлен в ZigZag подсчет количества фракталав countLow1 и countHigh1.
// Далее идет "дооснастка" ZigZag-а.
    
      // Проверка правильности введенных внешних переменных
      if (countBarEnd==0)
        {
         if (ExtDelta<=0) ExtDelta=0.001;
         if (ExtDelta>1) ExtDelta=0.999;

         if (ExtHidden<0) ExtHidden=0;
         if (ExtHidden>4) ExtHidden=4;
 
         if (ExtDeltaType<0) ExtDeltaType=0;
         if (ExtDeltaType>3) ExtDeltaType=3;

         if (ExtFractalEnd>0)
           {
            if (ExtFractalEnd<5) ExtFractalEnd=5;

            if (countLow1>ExtFractalEnd) countLow1=ExtFractalEnd;
            if (countHigh1>ExtFractalEnd) countHigh1=ExtFractalEnd;
           }
        }

   if (flagFrNew)
     {
      countLow1=0;
      countHigh1=0;
      for(shift=0; shift<=numBar; shift++)
        {
         if (ExtMapBuffer[shift]>0.0) {countLow1++;}
         if (ExtMapBuffer2[shift]>0.0) {countHigh1++;}    
        }  
      counted_bars=3;
     }

   if (Bars - counted_bars>2 && ExtHidden>0)
     {

// Инициализация матрицы
      if (afr[5]<1)
        {
         k=0;
         for (shift=0; shift<Bars && k<5; shift++)
           {
            if (zz[shift]>0)
              {
               afr[k]=Time[shift];
               if (zz[shift]==ExtMapBuffer[shift]) {afrl[k]=Low[shift]; afrh[k]=0.0;}
               if (zz[shift]==ExtMapBuffer2[shift]) {afrh[k]=High[shift]; afrl[k]=0.0;}
               k++;
              }
           }
         afr[k]=1;

         if (ExtFibo)
           {
            if (afrl[1]>0) ObjectCreate("fibo",OBJ_FIBO,0,afr[2],afrh[2],afr[1],afrl[1]);
            else ObjectCreate("fibo",OBJ_FIBO,0,afr[2],afrl[2],afr[1],afrh[1]);
           }
        }
     for (shift=0; shift<Bars; shift++) // Поиск времени бара первого фрактала, считая от нулевого бара
       {
        if (zz[shift]>0.0) 
         {
          timeFr1=Time[shift];
          if (ExtMapBuffer[shift]==zz[shift]) {lFr1=Low[shift]; hFr1=0.0;}
          if (ExtMapBuffer2[shift]==zz[shift]) {hFr1=High[shift]; lFr1=0.0;}

          break;
         }
       }
      // Поиск номера бара, до которого будут рисоваться соединительные линии 
      if (countBarEnd==0)
        {
         if (ExtFractalEnd>0)
           {
            k=ExtFractalEnd;
            for (shift=0; shift<Bars && k>0; shift++) if (zz[shift]>0 && ExtMapBuffer2[shift]>0) {countBarEnd=shift; k--;}
           }
         else countBarEnd=Bars-3;
        }

//-----------1 Отрисовка максимумов. Начало.
//+--------------------------------------------------------------------------+
//| Вывод соединяющих линий и чисел Песавенто и 0.866 для максимумов ZigZag-a
//| Отрисовка идет от нулевого бара
//+--------------------------------------------------------------------------+

   numLowPrim=0; numLowLast=0;
   numHighPrim=0; numHighLast=0;

   LowPrim=0.0; LowLast=0.0;
   HighPrim=0.0; HighLast=0.0;
   
   flagHigh=false;
   Angle=-100;
   
   if (flagFrNew) countFr=1;
   else countFr=ExtFractal;
   
   for (k=0; (k<Bars-1 && countHigh1>0 && countFr>0); k++)
     {
      if (ExtMapBuffer[k]>0.0 && LowPrim==0.0 && HighPrim>0 && ExtMapBuffer[k]==zz[k]) {LowPrim=ExtMapBuffer[k]; numLowPrim=k;}
      if (ExtMapBuffer[k]>0.0 && ExtMapBuffer[k]<LowPrim && HighPrim>0 && ExtMapBuffer[k]==zz[k]) {LowPrim=ExtMapBuffer[k]; numLowPrim=k;}
      if (ExtMapBuffer2[k]>0.0 && ExtMapBuffer2[k]==zz[k])
        {
         if (HighPrim>0) 
           {
            if (HighLast>0) 
              {
               if (flagHigh)
                 {
                  if (ExtMapBuffer2[k]>HighLast) {HighLast=High[k]; numHighLast=k;}
                 }
               else
                 {
                  if (ExtMapBuffer2[k]>HighPrim) flagHigh=true;
                  HighLast=High[k];
                  numHighLast=k;
                 }
              }
            else {numHighLast=k; HighLast=High[k];}

              HL=High[numHighLast]-Low[numLowPrim];
              kj=(HighPrim-HighLast)*10000/(numHighLast-numHighPrim);
              if (HL>0 && (Angle>kj || Angle==-100))  // Проверка угла наклона линии
                {
                 Angle=kj;
                 // Создание линии и текстового объекта
                 HLp=High[numHighPrim]-Low[numLowPrim];
                 k1=MathCeil((numHighPrim+numHighLast)/2);
                 kj=HLp/HL;
 
                 if (kj>0.21 && kj<=5)
                   {
                    // Создание текстового объекта (числа Песавенто). % восстановления между максимумами
                    kk=kj;
                    k2=1;

                    if (ExtDeltaType==2) for (ki=16;ki>=0;ki--) {if (MathAbs((fi[ki]-kj)/fi[ki])<=ExtDelta) {kk=fi[ki]; k2=-1; break;}}
                    if (ExtDeltaType==1) for (ki=16;ki>=0;ki--) {if (MathAbs(fi[ki]-kj)<=ExtDelta) {kk=fi[ki]; k2=-1; break;}}

                    if (k2<0)
                      // процент восстановления числа Песавенто и 0.866
                      {
                      if (ExtHidden!=4 && ExtHidden>0)                  
                        {
                         ObjectCreate("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],OBJ_TEXT,0,Time[k1],MathAbs((High[numHighPrim]+High[numHighLast])/2));
                         if (kk==0.886) // Gartley
                           ObjectSetText("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],fitxt[ki],7,"Arial", ExtGartley866);
                         else
                           ObjectSetText("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],fitxt[ki],7,"Arial",ExtPesavento);
                        }
                       }
                    else
                      // процент восстановления (не Песавенто и 0.866)
                      {
                       if (ExtHidden==1 || ExtHidden==4)
                         {
                          ObjectCreate("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],OBJ_TEXT,0,Time[k1],MathAbs((High[numHighPrim]+High[numHighLast])/2));
                          ObjectSetText("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],""+DoubleToStr(kk,2),7,"Arial",ExtNotFibo);
                         }
                      }
                      if ((ExtHidden==2 && k2<0) || (ExtHidden!=0 && ExtHidden!=2))
                        {
                         ObjectCreate("ph" + Time[numHighPrim] + "_" + Time[numHighLast],OBJ_TREND,0,Time[numHighPrim],High[numHighPrim],Time[numHighLast],High[numHighLast]);
                         ObjectSet("ph" + Time[numHighPrim] + "_" + Time[numHighLast],OBJPROP_RAY,false);
                         ObjectSet("ph" + Time[numHighPrim] + "_" + Time[numHighLast],OBJPROP_STYLE,STYLE_DOT);
                         ObjectSet("ph" + Time[numHighPrim] + "_" + Time[numHighLast],OBJPROP_COLOR,ExtLine);
                        }
                   }
                }
           }
         else 
            {numHighPrim=k; HighPrim=High[k];}
        }
       // Переход на следующий фрактал
       if (k>countBarEnd) 
//       if (k>Bars-3) 
         {
          k=numHighPrim+1; countHigh1--; countFr--;
          numLowPrim=0; numLowLast=0;
          numHighPrim=0; numHighLast=0;

          LowPrim=0.0; LowLast=0.0;
          HighPrim=0.0; HighLast=0.0;
   
          flagHigh=false;
          Angle=-100;
         }
     }
//-----------1 Отрисовка максимумов. Конец.

//-----------2 Отрисовка минимумов. Начало.
//+-------------------------------------------------------------------------+
//| Вывод соединяющих линий и чисел Песавенто и 0.866 для минимумов ZigZag-a
//| Отрисовка идет от нулевого бара
//+-------------------------------------------------------------------------+

   numLowPrim=0; numLowLast=0;
   numHighPrim=0; numHighLast=0;

   LowPrim=0.0; LowLast=0.0;
   HighPrim=0.0; HighLast=0.0;
   
   flagLow=false; 
   Angle=-100;

   if (flagFrNew) countFr=1;
   else countFr=ExtFractal;

   for (k=0; (k<Bars && countLow1>0 && countFr>0); k++)
     {
      if (ExtMapBuffer2[k]>HighPrim && LowPrim>0) {HighPrim=High[k]; numHighPrim=k;}
      if (ExtMapBuffer[k]>0.0 && ExtMapBuffer[k]==zz[k]) 
        {
         if (LowPrim>0) 
           {
            if (LowLast>0) 
              {
               if (flagLow)
                 {
                  if (ExtMapBuffer[k]<LowLast) {LowLast=Low[k]; numLowLast=k;}
                 }
               else
                 {
                  if (ExtMapBuffer[k]<LowPrim) flagLow=true;
                  LowLast=Low[k];
                  numLowLast=k;
                 }
              }
            else {numLowLast=k; LowLast=Low[k];}
              // вывод соединяющих линий и процентов восстановления(чисел Песавенто)
              HL=High[numHighPrim]-Low[numLowLast];
              kj=(LowPrim-LowLast)*1000/(numLowLast-numLowPrim);
              if (HL>0 && (Angle<kj || Angle==-100))  // Проверка угла наклона линии
                {
                 Angle=kj;

                 HLp=High[numHighPrim]-Low[numLowPrim];
                 k1=MathCeil((numLowPrim+numLowLast)/2);
                 kj=HLp/HL;

                 if (kj>0.21 && kj<=5)
                   {
                    // Создание текстового объекта (числа Песавенто). % восстановления между минимумами
                    kk=kj;
                    k2=1;

                    if (ExtDeltaType==2) for (ki=16;ki>=0;ki--) {if (MathAbs((fi[ki]-kj)/fi[ki])<=ExtDelta) {kk=fi[ki]; k2=-1; break;}}
                    if (ExtDeltaType==1) for (ki=16;ki>=0;ki--) {if (MathAbs(fi[ki]-kj)<=ExtDelta) {kk=fi[ki]; k2=-1; break;}}

                    if (k2<0)
                    // процент восстановления числа Песавенто и 0.866
                      {
                       if (ExtHidden!=4 && ExtHidden>0)                  
                         {
                          ObjectCreate("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],OBJ_TEXT,0,Time[k1],MathAbs((Low[numLowPrim]+Low[numLowLast])/2));
                          if (kk==0.886) // Gartley
                            ObjectSetText("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],fitxt[ki],7,"Arial", ExtGartley866);
                          else
                            ObjectSetText("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],fitxt[ki],7,"Arial",ExtPesavento);
                         }
                      }
                    else 
                    // процент восстановления (не Песавенто и 0.866)
                      { 
                       if (ExtHidden==1 || ExtHidden==4)
                         ObjectCreate("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],OBJ_TEXT,0,Time[k1],MathAbs((Low[numLowPrim]+Low[numLowLast])/2));
                         ObjectSetText("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],""+DoubleToStr(kk,2),7,"Arial",ExtNotFibo);
                      }
                      if ((ExtHidden==2 && k2<0) || (ExtHidden!=0 && ExtHidden!=2))
                        {
                         ObjectCreate("pl" + Time[numLowPrim] + "_" + Time[numLowLast],OBJ_TREND,0,Time[numLowPrim],Low[numLowPrim],Time[numLowLast],Low[numLowLast]);
                         ObjectSet("pl" + Time[numLowPrim] + "_" + Time[numLowLast],OBJPROP_RAY,false);
                         ObjectSet("pl" + Time[numLowPrim] + "_" + Time[numLowLast],OBJPROP_STYLE,STYLE_DOT);
                         ObjectSet("pl" + Time[numLowPrim] + "_" + Time[numLowLast],OBJPROP_COLOR,ExtLine);
                        }
                   }
                }
           }
         else {numLowPrim=k; LowPrim=Low[k];}
        }
       // Переход на следующий фрактал
       if (k>countBarEnd) 
//       if (k>Bars-3) 
         {
          k=numLowPrim+1; countLow1--; countFr--;

          numLowPrim=0; numLowLast=0;
          numHighPrim=0; numHighLast=0;

          LowPrim=0.0; LowLast=0.0;
          HighPrim=0.0; HighLast=0.0;
  
          flagLow=false;
          Angle=-100;
         }
     }

  flagFrNew=false;
  numBar=0;
//-----------2 Отрисовка минимумов. Конец.
  }
else // counted_bars<=2 Проверка смещений фракталов.

// Проверка на разрешение вывода оснастки. Начало.
if (ExtHidden>0)
//
  {
//

// Коррекция соединяющих линий и чисел. Начало.

  {

   // Поиск времени бара первого фрактала, считая от нулевого бара
   for (shift1=0; shift1<Bars; shift1++) 
     {
      if (zz[shift1]>0.0) 
       {
        timeFr1new=Time[shift1];
        break;
       }
     }
   // Поиск бара, на котором был последний фрактал
   shift=iBarShift(Symbol(),Period(),timeFr1); 
  // Сравнение текущего значения фрактала с тем, который был ранее


  // Образовался новый фрактал
  if (timeFr1new!=timeFr1)
    {
     flagFrNew=true;
     if (shift>numBar) numBar=shift;
     afr[5]=0;
    }
  // Фрактал на максимуме сдвинулся на другой бар
  if (hFr1>0 && zz[shift]==0.0)
    {
     flagFrNew=true;
     if (shift>numBar) numBar=shift;
     afr[5]=0;
    }
  // Фрактал на минимуме сдвинулся на другой бар
  if (lFr1>0 && zz[shift]==0.0)
    {
     flagFrNew=true;
     if (shift>numBar) numBar=shift;
     afr[5]=0;
    }


//-----------3 Сместился минимум или максимум, но остался на том же баре. Начало.

//============= 1 сместился максимум. Начало.
if (hFr1-High[shift]!=0 && hFr1>0)
  {

   numLowPrim=0; numLowLast=0;
   numHighPrim=shift; numHighLast=0;

   LowPrim=0.0; LowLast=0.0;
   HighPrim=High[shift]; HighLast=0.0;
   
   flagHigh=false;
   Angle=-100;

   for (k=shift+1; k<Bars; k++)
     {

      if (ExtMapBuffer[k]>0.0 && LowPrim==0.0 && ExtMapBuffer[k]==zz[k]) {LowPrim=ExtMapBuffer[k]; numLowPrim=k;}
      if (ExtMapBuffer[k]>0.0 && ExtMapBuffer[k]<LowPrim && ExtMapBuffer[k]==zz[k]) {LowPrim=ExtMapBuffer[k]; numLowPrim=k;}
      if (ExtMapBuffer2[k]>0.0  && ExtMapBuffer2[k]==zz[k])
        {
         if (HighLast>0) 
           {
            if (flagHigh)
              {
               if (ExtMapBuffer2[k]>HighLast) {HighLast=High[k]; numHighLast=k;}
              }
            else
              {
               if (ExtMapBuffer2[k]>HighPrim) flagHigh=true;
               HighLast=High[k];
               numHighLast=k;
              }
           }
         else {numHighLast=k; HighLast=High[k];}
         HL=High[numHighLast]-Low[numLowPrim];
         kj=(HighPrim-HighLast)*10000/(numHighLast-numHighPrim);
         if (HL>0 && (Angle>kj || Angle==-100))  // Проверка угла наклона линии
           {
            Angle=kj;
// Создание линии
            HLp=High[numHighPrim]-Low[numLowPrim];
            k1=MathCeil((shift+numHighLast)/2);
            kj=HLp/HL;
// Поиск старой соединительной линии                 
            numOb=ObjectFind("ph" + Time[numHighPrim] + "_" + Time[numHighLast]);
            if (numOb>-1)
              {
               if (kj>0.21 && kj<=5)
                 {
                  // Перемещение объектов
                  ObjectMove("ph" + Time[numHighPrim] + "_" + Time[numHighLast],0,Time[numHighPrim],High[numHighPrim]);
                  ObjectMove("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],0,Time[k1],MathAbs((High[numHighPrim]+High[numHighLast])/2));

                  // Создание текстового объекта (числа Песавенто). % восстановления между максимумами
                  kk=kj;
                  k2=1;

                  if (ExtDeltaType==2) for (ki=16;ki>=0;ki--) {if (MathAbs((fi[ki]-kj)/fi[ki])<=ExtDelta) {kk=fi[ki]; k2=-1; break;}}
                  if (ExtDeltaType==1) for (ki=16;ki>=0;ki--) {if (MathAbs(fi[ki]-kj)<=ExtDelta) {kk=fi[ki]; k2=-1; break;}}

                  if (k2<0)
                    // процент восстановления число Песавенто
                    if (ExtHidden!=4 && ExtHidden>0)
                      {
                       if (kk==0.886)
                         ObjectSetText("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],fitxt[ki],7,"Arial", ExtGartley866);
                       else
                         ObjectSetText("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],fitxt[ki],7,"Arial",ExtPesavento);
                      }
                    else
                    // процент восстановления (не Песавенто)
                      if (ExtHidden==1 || ExtHidden==4)
                        ObjectSetText("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],""+DoubleToStr(kk,2),7,"Arial",ExtNotFibo);
                 }
               else
                 {
                  ObjectDelete("ph" + Time[numHighPrim] + "_" + Time[numHighLast]); 
                  ObjectDelete("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast]);
                 }
              }
            else
              {
//******* Прорисовка новой линии, если она появилась.
               if (kj>0.21 && kj<=5)
                 {
                  // Создание текстового объекта (числа Песавенто). % восстановления между максимумами
                  kk=kj;
                  k2=1;

                  if (ExtDeltaType==1) for (ki=16;ki>=0;ki--) {if (MathAbs(fi[ki]-kj)<=ExtDelta) {kk=fi[ki]; k2=-1; break;}}
                  if (ExtDeltaType==2) for (ki=16;ki>=0;ki--) {if (MathAbs((fi[ki]-kj)/fi[ki])<=ExtDelta) {kk=fi[ki]; k2=-1; break;}}

                  if (k2<0)
                    // процент восстановления числа Песавенто и 0.866
                    {
                     if (ExtHidden!=4 && ExtHidden>0)                  
                       {
                        ObjectCreate("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],OBJ_TEXT,0,Time[k1],MathAbs((High[numHighPrim]+High[numHighLast])/2));
                        if (kk==0.886) // Gartley
                          ObjectSetText("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],fitxt[ki],7,"Arial", ExtGartley866);
                        else
                          ObjectSetText("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],fitxt[ki],7,"Arial",ExtPesavento);
                       }
                    }
                  else
                    // процент восстановления (не Песавенто и 0.866)
                    {
                     if (ExtHidden==1 || ExtHidden==4)
                       {
                        ObjectCreate("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],OBJ_TEXT,0,Time[k1],MathAbs((High[numHighPrim]+High[numHighLast])/2));
                        ObjectSetText("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast],""+DoubleToStr(kk,2),7,"Arial",ExtNotFibo);
                       }
                    }
                  if ((ExtHidden==2 && k2<0) || (ExtHidden!=0 && ExtHidden!=2))
                    {
                     ObjectCreate("ph" + Time[numHighPrim] + "_" + Time[numHighLast],OBJ_TREND,0,Time[numHighPrim],High[numHighPrim],Time[numHighLast],High[numHighLast]);
                     ObjectSet("ph" + Time[numHighPrim] + "_" + Time[numHighLast],OBJPROP_RAY,false);
                     ObjectSet("ph" + Time[numHighPrim] + "_" + Time[numHighLast],OBJPROP_STYLE,STYLE_DOT);
                     ObjectSet("ph" + Time[numHighPrim] + "_" + Time[numHighLast],OBJPROP_COLOR,ExtLine);
                    }
                 }
//*******
               }
             }
        }
     }
     hFr1=High[shift];
     timeFr1=Time[shift];
   }
//============= 1 сместился максимум. Конец.
//
//============= 1 сместился минимум. Начало.
if (lFr1-Low[shift]!=0 && lFr1>0)
  {

   numLowPrim=0; numLowLast=0;
   numHighPrim=shift; numHighLast=0;

   LowPrim=Low[shift]; LowLast=0.0;
   HighPrim=0.0; HighLast=0.0;
   
   flagLow=false;
   Angle=-100;
   for (k=shift+1; k<Bars; k++)
     {
      if (ExtMapBuffer2[k]>HighPrim) {HighPrim=High[k]; numHighPrim=k;}
      if (ExtMapBuffer[k]>0.0 && ExtMapBuffer[k]==zz[k]) 
        {
         if (LowLast>0) 
           {
            if (flagLow)
              {
               if (ExtMapBuffer[k]<LowLast) {LowLast=Low[k]; numLowLast=k;}
              }
            else
              {
               if (ExtMapBuffer[k]<LowPrim) flagLow=true;
               LowLast=Low[k];
               numLowLast=k;
              }
           }
         else {numLowLast=k; LowLast=Low[k];}
         HL=High[numHighPrim]-Low[numLowLast];
         kj=(LowPrim-LowLast)*1000/(numLowLast-numLowPrim);
         if (HL>0 && (Angle<kj || Angle==-100))  // Проверка угла наклона линии
           {
            Angle=kj;

            HLp=High[numHighPrim]-Low[numLowPrim];
            k1=MathCeil((numLowPrim+numLowLast)/2);
            kj=HLp/HL;
// Поиск старой соединительной линии                 
            numOb=ObjectFind("pl" + Time[numLowPrim] + "_" + Time[numLowLast]);
            if (numOb>-1)
              {
               if (kj>0.21 && kj<=5)
                 {
                  // Перемещение объектов
                  ObjectMove("pl" + Time[numLowPrim] + "_" + Time[numLowLast],0,Time[numLowPrim],Low[numLowPrim]);
                  ObjectMove("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],0,Time[k1],MathAbs((Low[numLowPrim]+Low[numLowLast])/2));

                  // Создание текстового объекта (числа Песавенто). % восстановления между минимумами
                  kk=kj;
                  k2=1;

                  if (ExtDeltaType==2) for (ki=16;ki>=0;ki--) {if (MathAbs((fi[ki]-kj)/fi[ki])<=ExtDelta) {kk=fi[ki]; k2=-1; break;}}
                  if (ExtDeltaType==1) for (ki=16;ki>=0;ki--) {if (MathAbs(fi[ki]-kj)<=ExtDelta) {kk=fi[ki]; k2=-1; break;}}

                  if (k2<0)
                  // процент восстановления числа Песавенто и 0.866
                    {
                     if (ExtHidden!=4 && ExtHidden>0)                  
                       {
                        if (kk==0.886) // Gartley
                          ObjectSetText("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],fitxt[ki],7,"Arial", ExtGartley866);
                        else
                          ObjectSetText("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],fitxt[ki],7,"Arial",ExtPesavento);
                       }
                    }
                  else 
                    // процент восстановления (не Песавенто и 0.866)
                    if (ExtHidden==1 || ExtHidden==4)
                      ObjectSetText("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],""+DoubleToStr(kk,2),7,"Arial",ExtNotFibo);
                 }           
               else
                 {
                  ObjectDelete("pl" + Time[numLowPrim] + "_" + Time[numLowLast]); 
                  ObjectDelete("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast]);
                 }
              }  
            else
              {
//******* Прорисовка новой линии, если она появилась.
               if (kj>0.21 && kj<=5)
                 {
                  // Создание текстового объекта (числа Песавенто). % восстановления между минимумами
                  kk=kj;
                  k2=1;

                  if (ExtDeltaType==2) for (ki=16;ki>=0;ki--) {if (MathAbs((fi[ki]-kj)/fi[ki])<=ExtDelta) {kk=fi[ki]; k2=-1; break;}}
                  if (ExtDeltaType==1) for (ki=16;ki>=0;ki--) {if (MathAbs(fi[ki]-kj)<=ExtDelta) {kk=fi[ki]; k2=-1; break;}}

                  if (k2<0)
                    // процент восстановления числа Песавенто и 0.866
                    {
                     if (ExtHidden!=4 && ExtHidden>0)                  
                       {
                        ObjectCreate("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],OBJ_TEXT,0,Time[k1],MathAbs((Low[numLowPrim]+Low[numLowLast])/2));
                        if (kk==0.886) // Gartley
                          ObjectSetText("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],fitxt[ki],7,"Arial", ExtGartley866);
                        else
                          ObjectSetText("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],fitxt[ki],7,"Arial",ExtPesavento);
                       }
                    }
                  else 
                    // процент восстановления (не Песавенто и 0.866)
                    { 
                     if (ExtHidden==1 || ExtHidden==4)
                       ObjectCreate("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],OBJ_TEXT,0,Time[k1],MathAbs((Low[numLowPrim]+Low[numLowLast])/2));
                       ObjectSetText("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast],""+DoubleToStr(kk,2),7,"Arial",ExtNotFibo);
                    }
                    if ((ExtHidden==2 && k2<0) || (ExtHidden!=0 && ExtHidden!=2))
                      {
                       ObjectCreate("pl" + Time[numLowPrim] + "_" + Time[numLowLast],OBJ_TREND,0,Time[numLowPrim],Low[numLowPrim],Time[numLowLast],Low[numLowLast]);
                       ObjectSet("pl" + Time[numLowPrim] + "_" + Time[numLowLast],OBJPROP_RAY,false);
                       ObjectSet("pl" + Time[numLowPrim] + "_" + Time[numLowLast],OBJPROP_STYLE,STYLE_DOT);
                       ObjectSet("pl" + Time[numLowPrim] + "_" + Time[numLowLast],OBJPROP_COLOR,ExtLine);
                      }
                 }           
//*******
                }
             }
        }
     }
     lFr1=Low[shift];
     timeFr1=Time[shift];
   }
//============= 1 сместился минимум. Конец.
//-----------3 Сместился минимум или максимум, но остался на том же баре. Конец.


   // Поиск исчезнувших фракталов и удаление линий, исходящих от этих фракталов. Перезапись матрицы.
   for (k=0; k<5; k++)
     {
      
      if (afrl[k]>0)
        {
         // Поиск бара, на котором был этот фрактал
         shift=iBarShift(Symbol(),Period(),afr[k]); 
         if (zz[shift]==0)
           {
            if (shift>numBar) numBar=shift;

            afr[5]=0;
            numLowPrim=shift; numLowLast=0;LowLast=10000000;
            for (k1=shift+1; k1<Bars; k1++)
              {
               if (ExtMapBuffer[k1]<LowLast && ExtMapBuffer[k1]>0) 
                 {
                  LowLast=Low[k1]; numLowLast=k1;
                  numOb=ObjectFind("pl" + Time[numLowPrim] + "_" + Time[numLowLast]);
                  if (numOb>-1)
                    {
                     ObjectDelete("pl" + Time[numLowPrim] + "_" + Time[numLowLast]); 
                     ObjectDelete("pltxt" + Time[numLowPrim] + "_" + Time[numLowLast]);
                    }
                 }
              }
           }
        }

      if (afrh[k]>0)
        {
         // Поиск бара, на котором был этот фрактал
         shift=iBarShift(Symbol(),Period(),afr[k]); 
         if (zz[shift]==0)
           {
            if (shift>numBar) numBar=shift;

            afr[5]=0;
            numHighPrim=shift; numHighLast=0;HighLast=0.0;
            for (k1=shift+1; k1<Bars; k1++)
              {
               if (ExtMapBuffer2[k1]>HighLast) 
                 {
                  HighLast=High[k1]; numHighLast=k1;
                  numOb=ObjectFind("ph" + Time[numHighPrim] + "_" + Time[numHighLast]);
                  if (numOb>-1)
                    {
                     ObjectDelete("ph" + Time[numHighPrim] + "_" + Time[numHighLast]); 
                     ObjectDelete("phtxt" + Time[numHighPrim] + "_" + Time[numHighLast]);
                    }
                 }
              }

           }
        }

     }

   // Перезапись матрицы
   if (afr[5]<1)
     if (ExtFibo) ObjectDelete("Fibo");
     {
      k=0;
      for (shift=0; shift<Bars && k<5; shift++)
        {
         if (zz[shift]>0)
           {
            afr[k]=Time[shift];
            if (zz[shift]==ExtMapBuffer[shift]) {afrl[k]=Low[shift]; afrh[k]=0.0;}
            if (zz[shift]==ExtMapBuffer2[shift]) {afrh[k]=High[shift]; afrl[k]=0.0;}
            k++;
           }
        }
      afr[k]=1;
      if (ExtFibo)
        {
         if (afrl[1]>0) ObjectCreate("fibo",OBJ_FIBO,0,afr[2],afrh[2],afr[1],afrl[1]);
         else ObjectCreate("fibo",OBJ_FIBO,0,afr[2],afrl[2],afr[1],afrh[1]);
        }
     }

// Проверка на разрешение вывода оснастки. Конец.
//
  }
//


// Коррекция. Конец.
  }


// end
}

