/*
//----+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ 
//Version: Final, October 1, 2006                                    |
Editing:   Nikolay Kositsin  farria@mail.redcom.ru                   |
//----+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+ 
Этот вариант индикатора ZigZag, в отличие от оригинала, на каждом тике 
пересчитывается  только на  ещё  неподсчитанных барах и поэтому совсем 
не грузит компьютер.  Помимо этого в данном индикаторе отрисовка линии
происходит именно в стиле ZIGZAG,    и  поэтому  индикатор   корректно 
изображает одновременно две своих верщины(Хай и Лоу) на одном и том же 
баре!
Николай Косицин
//----+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
Depth - это  минимальное кол-во  баров, на котором  не  будет  второго 
максимума  (минимума)  меньше  (больше)  на  Deviation  пипсов,    чем 
предыдущего, то  есть  расходиться  ZigZag  может  всегда,  а сходится 
(либо сдвинуться  целиком) больше,  чем  на  Deviation,  ZigZag  может 
только после Depth  баров. Backstep - это минимальное количество баров 
между максимумами (минимумами).
//----+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
Индикатор  Зигзаг  —  ряд линий тренда, которые соединяют существенные
вершины   и   основания  на  ценовом  графике.  Параметр  минимального
изменения  цен определяет процент, на который цена должна переместить,
чтобы  сформировать  новую  "Зиг"  или  "Заг"  линию.  Этот  индикатор
отсеивает  изменения на анализируемом графике, величина которых меньше
заданной.   Таким   образом,   зигзаг   отражает  только  существенные
изменения.  Зигзаг  используется,  главным  образом,  для облегченного
восприятия  графиков,  так  как он показывает только наиболее значимые
изменения  и  развороты.  Также  с  его  помощью  можно выявлять Волны
Эллиота  и  различные  фигуры на графике. Важно усвоить, что последний
отрезок   индикатора   может   меняться  в  зависимости  от  изменений
анализируемых  данных.  Это  один  из немногих индикаторов, у которого
изменение  цены  бумаги  может вызвать изменение предыдущего значения.
Подобная  способность  корректировки  своих  значений  по  последующим
изменениям  цены делает Зигзаг прекрасным инструментом для анализа уже
произошедших  ценовых  изменений.  Поэтому не следует пытаться создать
торговую  систему  на  основе  Зигзага:  он лучше подходит для анализа
исторических данных, чем для прогнозирования.
 Copyright © 2005, MetaQuotes Software Corp.
 */
//+------------------------------------------------------------------+
//|                                                    ZigZag_NK.mq4 |
//|                      Copyright © 2005, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net/"
//---- отрисовка индикатора в основном окне
#property indicator_chart_window
//---- количество индикаторных буфферов
#property indicator_buffers  2
//---- цвет индикатора
#property indicator_color1 Aqua
#property indicator_color2 Aqua
//---- толщина индикаторной линии
#property indicator_width1 0
#property indicator_width2 0
//---- стиль  индикаторной линии
#property indicator_style1 1
#property indicator_style2 1
//---- ВХОДНЫЕ ПАРАМЕТРЫ ИНДИКАТОРА 
extern int ExtDepth=12;
extern int ExtDeviation=5;
extern int ExtBackstep=3;
//---- 
//---- индикаторные буфферы
double LowestBuffer[],HighestBuffer[];
//----+ Введение целых переменных памяти для пересчёта индикатора только на неподсчитанных барах
int    MaxBar,time2,LASTLOWPOS,LASTHIGHPOS,LHTIME,LLTIME,size;  
   //----+ Введение переменных памяти с плавающей точкой для пересчёта индикатора только на неподсчитанных барах
double LowestMEMORY[1],HighestMEMORY[1],LASTLOW0,LASTLOW1,LASTHIGH0,LASTHIGH1,LASTHIGHEST,LASTLOWEST;
//+------------------------------------------------------------------+
//| ZigZag initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---- два индикаторных буффера использован для счёта 
   SetIndexBuffer(0,LowestBuffer);
   SetIndexBuffer(1,HighestBuffer);
//---- Стиль исполнения графика виде ломанной ZigZag 
   SetIndexStyle(0,DRAW_ZIGZAG);
   SetIndexStyle(1,DRAW_ZIGZAG);
//---- установка значений индикатора, которые не будут видимы на графике
   SetIndexEmptyValue(0,0.0);
   SetIndexEmptyValue(1,0.0);
//---- имена для окон данных и лэйбы для субъокон
   SetIndexLabel(0,"Low" );
   SetIndexLabel(1,"High");
   IndicatorShortName("ZigZag (ExtDepth="+ExtDepth+", ExtDeviation="+ExtDeviation+", ExtBackstep="+ExtBackstep+" )");
//---- определение размеров временных буфферов 
   size=ExtBackstep+1;
//---- изменение размеров временных буфферов 
   if(ArrayResize(LowestMEMORY,size)!=size)return(-1);
   if(ArrayResize(HighestMEMORY,size)!=size)return(-1);
//---- завершение инициализации
   return(0);
  }
//+------------------------------------------------------------------+
//|  ZigZag iteration function                                       |
//+------------------------------------------------------------------+
int start()
  {
   //----+ проверка количества баров на достаточность для корректного расчёта индикатора
   if (Bars-1<ExtDepth)return(0);
   //----+ Введение целых переменных и получение уже подсчитанных баров
   int limit,iii,counted_bars=IndicatorCounted();
   //---- проверка на возможные ошибки
   if (counted_bars<0)return(-1);
   //---- последний подсчитанный бар должен быть пересчитан 
   if (counted_bars>0) counted_bars--;
   //----+ Введение переменных    
   int    bar,back,lasthighpos,lastlowpos;
   double curlow,curhigh,lasthigh0,lastlow0,lasthigh1,lastlow1,val,res;
   //---- определение номера самого старого бара, начиная с которого будет произедён полый пересчёт всех баров
   MaxBar=Bars-ExtDepth; 
   //---- определение номера стартового  бара в цикле, начиная с которого будет произодиться  пересчёт новых баров
   limit=Bars-counted_bars-1;
        
   //+--- восстановление значений переменных +======+
   int Tnew=Time[limit+1];
   if (limit<MaxBar)
    {
     if (Tnew==time2)
      {
       lastlow0=LASTLOW0;
       lasthigh0=LASTHIGH0;
       //+---
       lastlow1=LASTLOW1;
       lasthigh1=LASTHIGH1;
       //+---
       lastlowpos=iBarShift(NULL,0,LLTIME,true); 
       lasthighpos=iBarShift(NULL,0,LHTIME,true); 
       //+--- проверка переменных lasthighpos и lastlowpos на корректность для дальнейшего расчёта
       if ((lasthighpos<0)||(lastlowpos<0))
        {
         Print("Ошибка восстановления переменных!!! Потеряны значения переменных lasthighpos и lastlowpos");
         Print("Будет произведён пересчёт индикатора на всех барах!");
         return(-1);
        }
       //+---
       LowestBuffer[lastlowpos]=LASTLOWEST;
       HighestBuffer[lasthighpos]=LASTHIGHEST;
       //+---     
       for(iii=size-1; iii>=0; iii--)
        {
         LowestBuffer[iii+limit+1]=LowestMEMORY[iii];
         HighestBuffer[iii+limit+1]=HighestMEMORY[iii];
        }
       //+---    
      } 
     else 
      {
       if (Tnew>time2)
            Print("Ошибка восстановления переменных!!! Tnew>time2");
       else Print("Ошибка восстановления переменных!!! Tnew<time2");
       Print("Будет произведён пересчёт индикатора на всех барах!");
       return(-1);  
      }
    }
   //+--- +==========================================+
   
   //---- инициализация нуля
   if (limit>=MaxBar) 
     {
      for (bar=Bars-1; bar>=MaxBar;bar--)
       {
        LowestBuffer [bar]=0.0; 
        HighestBuffer[bar]=0.0; 
       }
      lastlow1=-1; 
      lasthigh1=-1; 
      lastlowpos=-1; 
      lasthighpos=-1;
      limit=MaxBar; 
     }
     
   //----+ ---------- <<< начало первого большого цикла >>> -----------+  
   for(bar=limit; bar>=0; bar--)
     {
      //+--- Сохранение значений переменных +=========+ 
      if (bar==1)
        {
         if(((limit==1)&&(time2==Time[2]))||(limit>1))
          {
           LASTLOW0=lastlow0;
           LASTHIGH0=lasthigh0;
           //+---
           for(iii=size-1; iii>=0; iii--)
            {
             LowestMEMORY[iii]=LowestBuffer[iii+2];
             HighestMEMORY[iii]=HighestBuffer[iii+2];
            }
          }
        }
      //+---+=========================================+     
  
      //--- low
      val=Low[Lowest(NULL,0,MODE_LOW,ExtDepth,bar)];
      if(val==lastlow0) val=0.0;
      else 
        { 
         lastlow0=val; 
         if((Low[bar]-val)>(ExtDeviation*Point))val=0.0;
         else
           {
            for(back=1; back<=ExtBackstep; back++)
              {
               res=LowestBuffer[bar+back];
               if((res!=0)&&(res>val))LowestBuffer[bar+back]=0.0; 
              }
           }
        } 
      LowestBuffer[bar]=val;
      //--- high
      val=High[Highest(NULL,0,MODE_HIGH,ExtDepth,bar)];
      if(val==lasthigh0) val=0.0;
      else 
        {
         lasthigh0=val;
         if((val-High[bar])>(ExtDeviation*Point))val=0.0;
         else
           {
            for(back=1; back<=ExtBackstep; back++)
              {
               res=HighestBuffer[bar+back];
               if((res!=0)&&(res<val))HighestBuffer[bar+back]=0.0; 
              } 
           }
        }
      HighestBuffer[bar]=val;
     }
    //----+ конец первого большого цикла 
   
   //----+ ---------- <<< начало второго большого цикла >>> -----------+  
   for(bar=limit; bar>=0; bar--)
     {
      //+--- Сохранение значений переменных +====+ 
      if (bar==1)
       {
        if(((limit==1)&&(time2==Time[2]))||(limit>1))
         {
          time2=Time [2];
          LASTLOW1=lastlow1;
          LASTHIGH1=lasthigh1;
          //+---
          LLTIME=Time[lastlowpos];
          LHTIME=Time[lasthighpos];
          //+---
          LASTLOWEST=LowestBuffer[lastlowpos];
          LASTHIGHEST=HighestBuffer[lasthighpos];
         }
       }
     //+---+====================================+     
     
      curlow=LowestBuffer[bar];
      curhigh=HighestBuffer[bar];
      //---
      if((curlow==0)&&(curhigh==0))continue;
      //---
      if(curhigh!=0)
        {
         if(lasthigh1>0) 
           {
            if(lasthigh1<curhigh)HighestBuffer[lasthighpos]=0;
            else HighestBuffer[bar]=0;
           }
         //---
         if(lasthigh1<curhigh || lasthigh1<0)
           {
            lasthigh1=curhigh;
            lasthighpos=bar;
           }
         lastlow1=-1;
        }
      //----
      if(curlow!=0)
        {
         if(lastlow1>0)
           {
            if(lastlow1>curlow) LowestBuffer[lastlowpos]=0;
            else LowestBuffer[bar]=0;
           }
         //---
         if((curlow<lastlow1)||(lastlow1<0))
           {
            lastlow1=curlow;
            lastlowpos=bar;
           } 
         lasthigh1=-1;
        }
     } 
   //----+ конец второго большого цикла 
   //+-----------------------------------------------------------------+ 
        
 //---- завершение вычислений значений индикатора
return(0);
}
//+---------------------------------------------------------------------------+

