Индикатор трендовых линий с учетом подхода Т.Демарка
Введение
Борьба покупателей-«быков» и продавцов-«медведей» наглядно иллюстрируется трендовыми линиями. Томас Демарк разработал методику объективного выбора двух точек для построения 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()) нужны тоже для контроля.
Заключение
Хочу надеяться,что предложенный индикатор может быть использован не только начинающими трейдерами, но и бывалыми, как для работы на рынке, так и для анализа хода проводимых торгов.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
А как Бы к авторам обратиться с вопросом, как Бы можно Было Бы сделать так что Бы у этого индикатора:
1. на 4-х часовых графиках можно было отобразить ещё и линии с дневного графика. И на оборот;
2. включить "отмотку времени" назад. Т.е. посмотреть как распологались уровни бар или два назад;
3. был такой режим назовём его "кино", что бы однажды нарисованная линия сохранялась до принудительного её удаления;
4. линии которые существуют менее 1 полного бара пульсировали.
А как Бы к авторам обратиться с вопросом, как Бы можно Было Бы сделать так что Бы у этого индикатора:
1. на 4-х часовых графиках можно было отобразить ещё и линии с дневного графика. И на оборот;
2. включить "отмотку времени" назад. Т.е. посмотреть как распологались уровни бар или два назад;
3. был такой режим назовём его "кино", что бы однажды нарисованная линия сохранялась до принудительного её удаления;
4. линии которые существуют менее 1 полного бара пульсировали.
А как Бы автору этого послания повежлиеве Бы сказать Бы, что Ваши вопросы не имеют отношения к упомянутому Вами индикатору.
А Вы как Бы хотитите (или хочите) Бы нечто другое типа Бы программ, решающих Бы Ваши как Бы вопросы.
И как Бы попросить Бы Вас Бы не задавать Бы больше Бы подобных Бы вопросов Бы.
А любой каприз за Ваши деньги - найдуться желающие написать любую программу. Поищите в Инете. Найдете. Только они люди серьезные!
Вот что мне индикатор показал в день независимости! Наверное дело во мне?