English 中文 Español Deutsch 日本語 Português
Индикатор трендовых линий с учетом подхода Т.Демарка

Индикатор трендовых линий с учетом подхода Т.Демарка

MetaTrader 4Примеры | 19 февраля 2008, 09:16
5 665 23
Genkov
Genkov

Введение

Борьба покупателей-«быков» и продавцов-«медведей» наглядно иллюстрируется трендовыми линиями. Томас Демарк разработал методику объективного выбора двух точек для построения TD-линии тренда. (Более подробно о подходе Т. Демарка к техническому анализу можно посмотреть здесь).

Так как для трейдера, по мнению Т.Демарка, наиболее важным является последнее состояние рынка, то в предлагаемом варианте индикатора последнее направление тренда рисуется более толстой и сплошной линией, а для анализа текущего состояния не будет лишним знать и ближайшее предшествующее противоположное направление тренда, которое рисуется тонкой пунктирной линией.


Некоторые особенности кода предлагаемого индикатора в MQL 4

В индикаторе используются четыре буфера. Два буфера для кода стрелок, направления линии и два буфера для удлинения TD-линии в левую сторону.

Начальные десять баров (влево от второй TD-точки) отрисовываются буферами индикатора цветом «aqua».

#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[];

Инициализируем функции, управляющие расчетом и визуализацией индикатора

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);

Деинициализацию можно оставить по умолчанию пустой.

int deinit()
  {
  //  DelObj1();  
  //  DelObj2();
  return(0);
  }

Создаем функции удаления удаление объекта с указанным именем.

void DelObj1()
  {
  ObjectDelete("TrDdown"); // Удаление объекта с указанным именем. 
  }
  void DelObj2()
  {
  ObjectDelete("TrDup");
  }

Поиск опорных точек (для удобства) будем вести в отдельных циклах для пиков и для впадин. Поиск начинаем со 2-го бара, т.к. потом потребуется сравнение с правым (не нулевым) баром для выяснения истинности трендовой линии.

Проверим условие #1 (цена Max бара должна быть больше цен левого и правого баров).

for(int i=2;i<48;i++) // 48 часов - 2-а дня  // i- индекс проверяемого бара
    {
     if(High[i]>High[i+1]&&High[i]>High[i-1]) 
      {

Проверим условие #2 (Опорный ценовой максимум должен быть выше цены закрытия за два бара до регистрации).

При совпадении выполнения условий #1-го и #2-го ставим счетчик совпадений.

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-опорные точки, необходимо проверить условие нисходящего тренда, т.е. цена Первой опорной точки должна быть ниже цены Второй опорной точки.

// условие нисходящего тренда (правая TD-точка должна быть ниже левой)
           if((U==2 && TD_up[1]<TD_up[2])==false) 
             {  
              Print(" Up Не выполнены условия Нисходящего тренда "); 
              U--; TD_up[2]=0.0; index_up_2=0; time_up_2=0;  continue; 
              }

Если условие не выполнено, уменьшаем счетчик на единицу, обнуляем значения цены, индекса, времени и возвращаемся в начало цикла для поиска другой Второй опорной точки. Если условие выполнено, делаем расчет скорости падения TD-линии.

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-линии) – это условие истинности Нисходящего тренда.

// проверим условие #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; continue;
                }

Если не выполнено условие #3 истинности тренда, то поиск TD-точек приходится начинать с самого начала. Для этого необходимо обнулить все значения переменных полученные ранее, а поиск начинать с бара на два шага левее первого найденного значения Первой опорной точки.

Если условие истинности выполнено запоминаем значения переменных для построения трендовой линии.

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-тью значениями трендовой линии слева от Второй опорной точки:

// цены 10 баров трендовой линии влево от левой TD-точки
                for(int k=index_up_2;k<index_up_2+10;k++) 
                TrendLineBufferDown[k]=Pr_Tr_up_0+k*V_up;
                Print("  выходим из цикла поиска т.к.2-е TD-точки найдены");   
                break;      
                }

вставляем фигурные недостающие скобки

               } 
              } 
             }  
            } 
//==================================================================================+

При выполнении условия истинности будет нарисована трендовая линия слева от Второй опорной точки на 10 баров влево. Теперь осталось дорисовать эту линию вправо функцией ObjectCreate(). Для этого в конце программы есть блок отрисовки трендовых линий.

В этом блоке первые два оператора управляют толщиной (STYLE_SOLID) TD-линии при наличии только одной трендовой линии на данном этапе. Рисуем Нисходящую линию и выходим из цикла поиска пиков для TD-точек, предварительно удалив ранее имеющуюся линию.

Применяя выше перечисленные рассуждения, дописываем код для восходящей линии.

//==================================================================================+
   // для Min точек (впадин)   
   for(int j=2;j<48;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,
           " ; Close справа ",Pr_down_Cl_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 Не выполнены условие Восходящего тренда! "); 
                 D--;   TD_down[2]=0.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)
              {
                i=index_down_1+1; 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 выполнены условия истинности Восходящего тренда ");
               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;                   
               } 
              } 
             } 
            } 
           } 
          }
// ----------------------------------------------------------------------------+ 

Блок отрисовки трендовых линий построен так, что последняя по времени TD-линия отрисовывается жирной сплошной линией (STYLE_SOLID), а линия предшествовшая ей, но противоположного направления отрисовывается тонкой пунктирной линией (STYLE_DOT).

Может возникнуть такая ситуация, что тренд продолжительное время идет в одном направлении, при этом не будет найдена Вторая TD-точка тренда противоположного направления, а промежуточные значения цены, времени и индекса будут записываться в переменные. Чтобы эти промежуточные значения не отражались на построении трендовых линий, необходимо поставить фильтр условия отрисовки линий: например, если не найдена Вторая TD-точка, то значение цены будет равно "0", в тоже время значение индекса Первой точки будет зафиксировано, и если оно окажется меньше значения Первой TD-точки линии противоположного направления, то последняя трендовая линия, имеющая истинные параметры, может быть отрисована не тем стилем и не тем цветом. Именно поэтому и поставлен временной фильтр. Смотри прикрепленный файл.

// ----------------------------------------------------------------------------+
// отрисовка трендовых линий вправо от Второй опорной точки
// ----------------------------------------------------------------------------+
    if(TDd2==0.0)   index_down_1=50;
    if(TDu2==0.0)   index_up_1=50;
     else
    {    
    Print("  TDd2 = ",TDd2,"   index_up_1 = ",index_up_1,"  >  index_down_1 = ",index_down_1);
     Print("  Up Рисуем  Нисходящую и выходим из цикла поиска пиков для TD-точек");
       DelObj1(); // предварительно удалив ранее имеющуюся линию
        ObjectCreate("TrDdown",OBJ_TREND,0,T_u2,TDu2,T_u1,TDu1); 
     if(index_up_1>index_down_1) 
      {           // предшествующее направление тренда рисуется:
       ObjectSet("TrDdown",OBJPROP_COLOR,Yellow);
       ObjectSet("TrDdown",OBJPROP_WIDTH,1);  // тонкой линией и 
       ObjectSet("TrDdown",OBJPROP_STYLE,STYLE_DOT);// пунктиром
       }
      else
       {                // самое последнее направление тренда рисуется:
        ObjectSet("TrDdown",OBJPROP_COLOR,Yellow);
        ObjectSet("TrDdown",OBJPROP_WIDTH,2);           // более толстой
        ObjectSet("TrDdown",OBJPROP_STYLE,STYLE_SOLID); // сплошной линией
       }
      }
// -----------------------------
 
     if(TDd2==0.0)   index_down_1=50;
      else
      {
    Print("  TDd1 = ",TDd1,"   index_up_1 = ",index_up_1,"  <  index_down_1 = ",index_down_1);
      Print("  D Рисуем  Восходящую и выходим из цикла поиска впадин для TD-точек");
        DelObj2(); // предварительно удалив, ранее имеющуюся линию
         ObjectCreate("TrDup",OBJ_TREND,0,T_d2,TDd2,T_d1,TDd1); 
       if(index_up_1<index_down_1)
        {   
 
         ObjectSet("TrDup",OBJPROP_COLOR,Yellow); 
         ObjectSet("TrDup",OBJPROP_WIDTH,1); 
        ObjectSet("TrDup",OBJPROP_STYLE,STYLE_DOT);
        }
         else
          {
          ObjectSet("TrDup",OBJPROP_COLOR,Yellow); 
          ObjectSet("TrDup",OBJPROP_WIDTH,2);  
          ObjectSet("TrDup",OBJPROP_STYLE,STYLE_SOLID);
          }
         }
// ----------------------------------------------------------------------------+
   return(0);
  }

Примечание: практически все операторы "Print(...)" служат для визуального контроля хода выполнения программы, поэтому их можно "закомментировать", а также операторы типа string (TimeToStr()) нужны тоже для контроля.


Заключение

Хочу надеяться,что предложенный индикатор может быть использован не только начинающими трейдерами, но и бывалыми, как для работы на рынке, так и для анализа хода проводимых торгов.

Прикрепленные файлы |
TL_by_Demark_v6.mq4 (13.44 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (23)
[Удален] | 4 авг. 2008 в 12:53

А как Бы к авторам обратиться с вопросом, как Бы можно Было Бы сделать так что Бы у этого индикатора:

1. на 4-х часовых графиках можно было отобразить ещё и линии с дневного графика. И на оборот;

2. включить "отмотку времени" назад. Т.е. посмотреть как распологались уровни бар или два назад;

3. был такой режим назовём его "кино", что бы однажды нарисованная линия сохранялась до принудительного её удаления;

4. линии которые существуют менее 1 полного бара пульсировали.

Genkov
Genkov | 5 авг. 2008 в 16:48
YuriF:

А как Бы к авторам обратиться с вопросом, как Бы можно Было Бы сделать так что Бы у этого индикатора:

1. на 4-х часовых графиках можно было отобразить ещё и линии с дневного графика. И на оборот;

2. включить "отмотку времени" назад. Т.е. посмотреть как распологались уровни бар или два назад;

3. был такой режим назовём его "кино", что бы однажды нарисованная линия сохранялась до принудительного её удаления;

4. линии которые существуют менее 1 полного бара пульсировали.

А как Бы автору этого послания повежлиеве Бы сказать Бы, что Ваши вопросы не имеют отношения к упомянутому Вами индикатору.

А Вы как Бы хотитите (или хочите) Бы нечто другое типа Бы программ, решающих Бы Ваши как Бы вопросы.

И как Бы попросить Бы Вас Бы не задавать Бы больше Бы подобных Бы вопросов Бы.

А любой каприз за Ваши деньги - найдуться желающие написать любую программу. Поищите в Инете. Найдете. Только они люди серьезные!

[Удален] | 4 нояб. 2008 в 09:54

Вот что мне индикатор показал в день независимости! Наверное дело во мне?

Вячеслав
Вячеслав | 26 авг. 2009 в 23:49
Уважаемый автор! Я с интересом познакомился с Вашим индикатором. Он сильно уступает например такому Ind-TD-DeMark-3-1-new.ex4, который заменяет Эльваве последней серии на 200%. Ну может я не заметил каких то его положительных качеств. А было бы интересно об этом узнать...
[Удален] | 4 янв. 2010 в 17:21
Уважаемый автор, а есть ли разница какие котировки транслирует дилер - с 4 символами или с 5 ?
Охота за трендами Охота за трендами
В статье описан алгоритм наращивания объёма прибыльной сделки и представлена его реализация посредством MQL.
Комфортная пипсовка Комфортная пипсовка
В статье описан метод создания инструмента для комфортной пипсовки. Однако данный подход к открытию сделок может быть применим при любой торговле.
Эксперты на основе популярных торговых систем и алхимия оптимизации торгового робота Эксперты на основе популярных торговых систем и алхимия оптимизации торгового робота
В данной статье автор рассматривает алгоритмы реализации простейших торговых систем. Статья будет полезна начинающим трейдерам и начинающим экспертописателям
Использование платформы MetaTrader 4 для выявления благоприятных временных окон (паттернов времени) Использование платформы MetaTrader 4 для выявления благоприятных временных окон (паттернов времени)
Анализ паттернов времени может применяться для рынка Форекс с целью определения наилучшего времени для открытия сделок, а также периодов, когда не следует торговать вовсе. В данном случае мы используем торговую платформу MetaTrader 4 для анализа истории и оптимизации результатов, которые могут быть использованы в механических торговых системах.