//+------------------------------------------------------------------+
//|                                              TL_by_Demark_v6.mq4 |
//| Построение линий тренда с учетом Подхода Т.Демарка        Genkov |
//|                                                     genkov@bk.ru |
//+------------------------------------------------------------------+
#property copyright "Genkov"
#property link      "genkov@bk.ru"
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Chartreuse
#property indicator_color2 Tomato
#property indicator_color3 Aqua
#property indicator_color4 Aqua

// ----- indicator_buffers
double   TrendUpBuffer[];
double   TrendDownBuffer[];
double   TrendLineBufferUp[];
double   TrendLineBufferDown[];
//------ input parameters
int      index_up_1,index_up_2,index_down_1,index_down_2;
double   V_up,V_down,Pr_up_Cl_1,Pr_down_Cl_1,Pr_Tr_up_0,Pr_Tr_down_0;
double   TD_up[50],TD_down[50],TDu1,TDu2,TDd1,TDd2,Pr_Tr_down_1,Pr_Tr_up_1;
datetime time_up_1,time_up_2,T_u1,T_u2,T_d1,T_d2,time_down_1,time_down_2;

 string   Time_down_1,Time_down_2,Time_up_1,Time_up_2; 
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_ARROW);        // тип, стиль линии индикатора      
   SetIndexArrow(0,236);               // значек для линии индикаторов
   SetIndexBuffer(0,TrendUpBuffer);    // обяъявление одномерного массива
   SetIndexEmptyValue(0,0.0);          // значение пустой величины для индикатора. 
   SetIndexStyle(1,DRAW_ARROW);
   SetIndexArrow(1,238);
   SetIndexBuffer(1,TrendDownBuffer);
   SetIndexEmptyValue(1,0.0);
   SetIndexStyle(2,DRAW_LINE);         
   SetIndexBuffer(2,TrendLineBufferUp);    // для восходящей линии
   SetIndexEmptyValue(2,0.0);           
   SetIndexStyle(3,DRAW_LINE);
   SetIndexBuffer(3,TrendLineBufferDown);  // для нисходящей линии
   SetIndexEmptyValue(3,0.0);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
    DelObj1();  
    DelObj2();
  return(0);
  }
  void DelObj1()
  {
  ObjectDelete("TrDdown"); // Удаление объекта с указанным именем. 
  }
  void DelObj2()
  {
  ObjectDelete("TrDup");
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
  int U=0,D=0;  // внутренние переменные обнуляются при каждом тике
   //=======================================================================+ 
   // ищем претендентов на опорные TD_точки: начинаем поиск со 2-го бара т.к.
   // потом потребуется сравнение с правым баром (не нулевым). Для Max точек
   // проверим условие #1(цена бара должна быть больше цен левого и правого баров)
   for(int i=2;i<24;i++) // 48 часов - 2-а дня  // i- индекс проверяемого бара
    {
     if(High[i]>High[i+1]&&High[i]>High[i-1]) 
      { 
      // проверим условие #2(Опорный ценовой максимум должен быть 
      // выше цены закрытия за два бара до регистрации <слева от Max>)
      if(High[i]>Close[i+2])  
       { 
        U++; // счетчик совпадений и #1-го и #2-го условий 
        if(U==1)
         {
         // цена Первой опорной точки при выполнении условий #1 и #2
         TD_up[1]=High[i];  
         index_up_1=i;                               // индекс Первой опорной точки
         Pr_up_Cl_1=Close[i-1]; // цена закрытия бара, следующего за опорной точкой
         time_up_1=iTime(NULL,0,index_up_1);          // время Первой опорной точки
        
         // это удобочитаемое время для контроля хода выполнения операторов
         Time_up_1=TimeToStr(time_up_1,TIME_DATE|TIME_MINUTES); 
         Print("  Up цена Первой опорной точки = ",TD_up[1]," инд= ",index_up_1,"  время = ",Time_up_1);
          }  
          if(U==2)
           { 
           // цена Второй опорной точки при выполнении условий #1 и #2
           TD_up[2]=High[i]; 
           index_up_2=i;            // индекс Второй опорной точки
           time_up_2=iTime(NULL,0,index_up_2);// время Второй опорной точки
           
           Time_up_2=TimeToStr(time_up_2,TIME_DATE|TIME_MINUTES); 
           Print("  Up цена Второй опорной точки = ",TD_up[2]," инд= ",index_up_2,"  время = ",Time_up_2);
           
           // условие нисходящего тренда (правая TD-точка должна быть ниже левой)
           if((U==2 && TD_up[1]<TD_up[2])==false) 
             {  
              Print(" Up Не выполнены условия Нисходящего тренда ");
              Print(" Up TD_up[1] = ",TD_up[1]," <  TD_up[2] = ",TD_up[2]);  
              U--; TD_up[2]=0.0; if(index_up_2>20) {time_up_1=0;}  continue; 
              }
             else
             { 
              Print(" Up выполнены условия Нисходящего тренда ");
              // расчет скорости падения TD_max по двум выявленным точкам
              V_up=(TD_up[2]-TD_up[1])/(index_up_2-index_up_1);//скорость(пипсы/бар)
              // расчетное значение TD линии на 1-ом баре правее Max
              Pr_Tr_up_1=TD_up[1]-V_up;
              // если от цены 1-й опорной точки отнять произведение скорости падения 
              // TD-линии на  кол-во  баров, получается  расчетная цена  нисходящего   
              Pr_Tr_up_0=TD_up[1]-(index_up_1*V_up);           // тренда на "0" баре 
              // проверим условие #3(для последнего опорного ценового максимума цена
              // закрытия  следующего ( справа ) бара должна  быть  ниже  расчетного
              //  значения падения TD-линии)
              if((Pr_up_Cl_1< Pr_Tr_up_1)==false)
               {
                Print(" Up Не выполнено условие истинности Нисходящего тренда!");
                i=index_up_1+2; TD_up[1]=0.0; TD_up[2]=0.0; time_up_1=0; 
                time_up_2=0; index_up_1=50; index_up_2=50; U=0; 
                TrendDownBuffer[index_up_1]=0.0; continue;
                }
             else
               { // если выполнено условие #3 - тренд истинен
               Print("  Up выполнены условия истинности Нисходящего тренда ");
               // запоминаем значения переменных для построения TD_Down линии 
                TDu1=TD_up[1];  // цена  1-ой точки
                T_u1=time_up_1; // время 1-ой точки
                TDu2=TD_up[2];  // цена  2-ой точки
                T_u2=time_up_2; // время 2-ой точки
                TrendDownBuffer[index_up_1]=TDu1+5*Point;// ставим стрелку вниз 
                // цены 10 баров трендовой линии влево от левой TD-точки
                for(int k=index_up_2;k<index_up_2+10;k++)
                TrendLineBufferDown[k]=Pr_Tr_up_0+k*V_up;
                Print("  Up выходим из цикла поиска пиков т.к.2-е TD-точки найдены");   
                break;      
                } 
               } 
              } 
             }  
            }
           }
     if(TD_up[2]==0.0) {time_up_1=0; Time_up_1=TimeToStr(time_up_1,TIME_DATE|TIME_MINUTES);} 
     Print(" После цикла Up   TD_up[2] = ",TD_up[2],"   time_up_1 = ",Time_up_1);
//==================================================================================+
   // для Min точек (впадин)   
   for(int j=2;j<24;j++) // 48 часов - 2-а дня  // j- индекс проверяемого бара
    { 
     // проверим условие #1 (цена бара должна быть меньше цен левого и правого баров) 
     if(Low[j]<Low[j+1]&&Low[j]<Low[j-1])
      {
       // проверим условие #2 (Опорный ценовой Минимум должен быть 
       // ниже цены закрытия за два бара до регистрации <слева от Min>)
       if(Low[j]<Close[j+2])
        { 
         D++;  // счетчик совпадений и #1-го и #2-го условий 
         if(D==1)
          { 
           TD_down[1]=Low[j]; 
           index_down_1=j;
           Pr_down_Cl_1=Close[j-1]; 
           time_down_1=iTime(NULL,0,j);
           
           Time_down_1=TimeToStr(time_down_1,TIME_DATE|TIME_MINUTES);            
           Print(" D цена Первой опорной точки ",TD_down[1]," ; индекс ",index_down_1,
           "  ; ",Time_down_1);           
           } 
           if(D==2)
            { 
             TD_down[2]=Low[j]; 
             index_down_2=j; 
             time_down_2=iTime(NULL,0,j);
             
             Time_down_2=TimeToStr(time_down_2,TIME_DATE|TIME_MINUTES);
             Print(" D цена Второй опорной точки ",TD_down[2]," индекс ",index_down_2,
                   "  время ",Time_down_2);             
             // условие восходящего тренда (правая Min точка должна быть выше левой)
             if((D==2 && TD_down[1]>TD_down[2])==false)
              {
              Print(" D TD_down[1] = ",TD_down[1]," > TD_down[2] = ",TD_down[2]);
		         Print(" D Не выполнены условие Восходящего тренда! "); 
		         D--;   TD_down[2]=0.0;  if(index_down_2>20) {time_down_1=0;}
		         continue; 
		         } 
		        else 
            { 
             Print(" D выполнены условия Восходящего тренда");            
             // расчет скорости подъема TD_min по двум выявленным точкам
             V_down=(TD_down[1]-TD_down[2])/(index_down_2-index_down_1);
             //расчетное значение линии на 1-ом баре правее Min
             Pr_Tr_down_1=TD_down[1]+V_down;
//             } 
             // проверим условие #3 (для последнего (справа) ценового минимума цена
             // закрытия следующего бара должна быть выше расчетного значения
             // скорости подъема TD-линии.
             if((Pr_down_Cl_1> Pr_Tr_down_1)==false)
              {
              Print(" D Не выполнены условие истинности Восходящего тренда! ");
              Print(" time_down_1 = ",Time_down_1,"   time_down_2 = ",Time_down_2); 
                i=index_down_1+2; TD_down[1]=0.0; TD_down[2]=0.0; time_down_1=0; 
                time_down_2=0; index_down_1=50; index_down_2=50; D=0; continue;
                }
             else
              { // выполнено условие #3 - тренд истинен
               Print("  D выполнены условия истинности Восходящего тренда ");
               Print(" time_down_1 = ",Time_down_1,"   time_down_2 = ",Time_down_2);
               TDd1=TD_down[1]; 
               T_d1=time_down_1; 
               TDd2=TD_down[2];  
               T_d2=time_down_2;
               // расчетная цена трендовой линии на "0" баре
               Pr_Tr_down_0=TD_down[1]+(index_down_1*V_down); 
               TrendUpBuffer[index_down_1]=TDd2-2*Point; // ставим стрелочку вверх 
               // цены 10 баров трендовой линии влево от Второй опорной точки
               for(int n=index_down_2;n<index_down_2+10;n++)
                TrendLineBufferUp[n]=Pr_Tr_down_0-n*V_down;
               Print("  D выходим из цикла поиска впадин т.к.2-е TD-точки найдены ");
               break;                   
               } 
              } 
             } 
            }
           } 
          }  
     if(TD_down[2]==0.0) {time_down_1=0; Time_down_1=TimeToStr(time_down_1,TIME_DATE|TIME_MINUTES);}
     Print(" После Down   TD_down[2] = ",TD_down[2],"   time_down_1 = ",Time_down_1);
// ----------------------------------------------------------------------------+
// отрисовка трендовых линий вправо от Второй опорной точки
// ----------------------------------------------------------------------------+
    if(TDu2==0.0) {time_down_1=0; TrendDownBuffer[index_down_1]=0.0;}
     else
    {    
     Print("  Up Рисуем  Нисходящую и выходим из цикла поиска пиков для TD-точек");
     Print("  Up time_down_1 = ",Time_down_1,"  >  time_up_1 = ",Time_up_1);
       DelObj1(); // предварительно удалив ранее имеющуюся линию
	    ObjectCreate("TrDdown",OBJ_TREND,0,T_u2,TDu2,T_u1,TDu1); 
     if(time_up_1<time_down_1) 
      {           // предшествующее направление тренда рисуется:
       ObjectSet("TrDdown",OBJPROP_COLOR,DeepPink);
       ObjectSet("TrDdown",OBJPROP_WIDTH,1);  // тонкой линией и 
       ObjectSet("TrDdown",OBJPROP_STYLE,STYLE_DOT);// пунктиром
       }
      else
       {                // самое последнее направление тренда рисуется:
        ObjectSet("TrDdown",OBJPROP_COLOR,DeepPink);
        ObjectSet("TrDdown",OBJPROP_WIDTH,1);           // более толстой
        ObjectSet("TrDdown",OBJPROP_STYLE,STYLE_SOLID); // сплошной линией
       }
      }
// -----------------------------
   if(TDd2==0.0) {time_up_1=0;  TrendUpBuffer[index_up_1]=0.0;}
      else
      {
      Print("  D Рисуем  Восходящую и выходим из цикла поиска впадин для TD-точек");
      Print("  D time_up_1 = ",Time_up_1,"  >  time_down_1 = ",Time_down_1);
        DelObj2(); // предварительно удалив, ранее имеющуюся линию
	     ObjectCreate("TrDup",OBJ_TREND,0,T_d2,TDd2,T_d1,TDd1);
//////	     TrendDownBuffer[index_down_1]=0.0; 
	   if(time_down_1<time_up_1)
	    {   
	     ObjectSet("TrDup",OBJPROP_COLOR,Yellow); 
	     ObjectSet("TrDup",OBJPROP_WIDTH,1); 
        ObjectSet("TrDup",OBJPROP_STYLE,STYLE_DOT);
        }
		 else
		  {
		  ObjectSet("TrDup",OBJPROP_COLOR,Lime); 
		  ObjectSet("TrDup",OBJPROP_WIDTH,2);  
		  ObjectSet("TrDup",OBJPROP_STYLE,STYLE_SOLID);
		  }
		 }
// ----------------------------------------------------------------------------+
   return(0);
  }
// ----------------------------------------------------------------------------+