// --------------------------------------------------------------------------- // Зигзаг по экстремумам как у Л.Вильямса. // // Версия 2.0: Введена оптимизация последовательностей экстремумов. // // Версия 3.0: Введён режим "быстрой" работы по сформировавшимся барам. // Введена подсветка трёх уровней экстремумов - как в книге // Ларри Вильямса. // // Версия с исправлениями AlexSTAL. // --------------------------------------------------------------------------- #property indicator_chart_window #property indicator_buffers 8 #property indicator_color1 SkyBlue #property indicator_color2 SkyBlue #property indicator_color3 Lime #property indicator_color4 Blue #property indicator_color5 Red #property indicator_color6 Lime #property indicator_color7 Blue #property indicator_color8 Red #property indicator_width1 2 #property indicator_width2 2 #property indicator_width3 2 #property indicator_width4 2 #property indicator_width5 2 #property indicator_width6 2 #property indicator_width7 2 #property indicator_width8 2 // Коды стрелок. #define ARROW_CODE_L1 0x9F #define ARROW_CODE_L2 0x77 #define ARROW_CODE_L3 0x6C // Параметры индикатора. extern int ZZ_LINE_LEVEL = 2; // Уровень прочерчиваемых линий. extern bool FAST_MODE = true; // Режим работы по сформировавшимся барам. // Буферы индикатора. double buf_zz1[],buf_zz2[],buf_l1up[],buf_l2up[],buf_l3up[],buf_l1down[],buf_l2down[],buf_l3down[]; int maximum[],minimum[]; // Предел уровня, до которого ищем экстремумы. int max_level; // Инициализация. int init() { IndicatorShortName(StringConcatenate("AZZX - LARRYZZ v3.0 / Modified by AlexSTAL (", ZZ_LINE_LEVEL,", ",FAST_MODE,")")); SetIndexBuffer(0,buf_zz1); SetIndexBuffer(1,buf_zz2); SetIndexBuffer(2,buf_l1up); SetIndexBuffer(3,buf_l2up); SetIndexBuffer(4,buf_l3up); SetIndexBuffer(5,buf_l1down); SetIndexBuffer(6,buf_l2down); SetIndexBuffer(7,buf_l3down); SetIndexStyle(0,DRAW_ZIGZAG); SetIndexStyle(1,DRAW_ZIGZAG); SetIndexStyle(2,DRAW_ARROW); SetIndexStyle(3,DRAW_ARROW); SetIndexStyle(4,DRAW_ARROW); SetIndexStyle(5,DRAW_ARROW); SetIndexStyle(6,DRAW_ARROW); SetIndexStyle(7,DRAW_ARROW); SetIndexArrow(2,ARROW_CODE_L1); SetIndexArrow(3,ARROW_CODE_L2); SetIndexArrow(4,ARROW_CODE_L3); SetIndexArrow(5,ARROW_CODE_L1); SetIndexArrow(6,ARROW_CODE_L2); SetIndexArrow(7,ARROW_CODE_L3); SetIndexEmptyValue(0,0); SetIndexEmptyValue(1,0); ArrayResize(maximum,Bars); ArrayResize(minimum,Bars); if(ZZ_LINE_LEVEL>3) { max_level=ZZ_LINE_LEVEL; } else { max_level=3; } return(0); } // Главный цикл. int start() { int i,j; // Поддержка быстрого режима работы. if((FAST_MODE==true) && (Bars-IndicatorCounted()==1)) return(0); int counted_bars = IndicatorCounted(); if(counted_bars < 0) return(-1); if(counted_bars > 0) counted_bars--; int limit = Bars - counted_bars; if(counted_bars==0) limit-=1+1; ArrayResize(maximum,limit); ArrayResize(minimum,limit); // Поиск экстремумов. ArrayInitialize(maximum,0); ArrayInitialize(minimum,0); for(i=1; i<=max_level; i++) pass(i,limit); // Построение индикаторов. ArrayInitialize(buf_zz1,0); ArrayInitialize(buf_zz2,0); ArrayInitialize(buf_l1up,0); ArrayInitialize(buf_l2up,0); ArrayInitialize(buf_l3up,0); ArrayInitialize(buf_l1down,0); ArrayInitialize(buf_l2down,0); ArrayInitialize(buf_l3down,0); for(i=limit-1; i>=0; i--) { if(maximum[i] >= ZZ_LINE_LEVEL) { for(j = i + 1; j < limit; j++) { buf_zz1[i]=High[i]; if(minimum[j]>=ZZ_LINE_LEVEL) { // Нормальная ситуация. break; } else if((maximum[i]>=ZZ_LINE_LEVEL) && (buf_zz1[i]>0)) { // Останется только один... if(High[i]>High[j]) { buf_zz1[j]=0; } else { buf_zz1[i]=0; } } } } if(minimum[i] >= ZZ_LINE_LEVEL) { for(j = i + 1; j < limit; j++) { buf_zz2[i]=Low[i]; if(maximum[j]>=ZZ_LINE_LEVEL) { // Нормальная ситуация. break; } else if((minimum[i]>=ZZ_LINE_LEVEL) && (buf_zz2[i]>0)) { // Останется только один... if(Low[i]= 3) buf_l3up[i] = High[i]; if(minimum[i] >= 3) buf_l3down[i] = Low [i]; } return(0); } // Проход по уровню. // Возвращает true, если были найдены экстремумы заданного уровня. bool pass(int level,int lim) { return(pass_maximum(level,lim) || pass_minimum(level,lim)); } // Поиск меньшего или равного максимума слева. // В случае неудачи возвращает заведомо большое число. double find_left_maximum(int bar, int lim) { int i,level=maximum[bar]; for(i=bar+1; i=level) { return(High[i]); } } // Дошли до конца истории. return(High[bar]+1); } // Поиск меньшего или равного максимума справа. // В случае неудачи возвращает заведомо большое число. double find_right_maximum(int bar) { int i,level=maximum[bar]; for(i=bar-1; i>= 0; i--) { if(maximum[i]>= level) { return(High[i]); } } // Дошли до начала истории. return(High[bar]+1); } // Проход по максимумам для уровня. // Возвращает true, если были найдены максимумы. bool pass_maximum(int level,int lim) { int i,limit=lim-2,prev=level-1,result=false; for(i = 1; i=level) { return(Low[i]); } } // Дошли до конца истории. return(Low[bar]-1); } // Поиск меньшего или равного минимума справа. // В случае неудачи возвращает заведомо меньшее число. double find_right_minimum(int bar) { int i,level=minimum[bar]; for(i=bar-1; i>= 0; i--) { if(minimum[i]>= level) { return(Low[i]); } } // Дошли до начала истории. return(Low[bar]-1); } // Проход по минимумам для уровня. // Возвращает true, если были найдены минимумы. bool pass_minimum(int level,int lim) { int i,limit=lim-2,prev=level-1,result=false; for(i = 1; i=Low[i] && r>Low[i]) || (l>Low[i] && r>=Low[i])) { minimum[i] = level; result = true; } } } return(result); } //+------------------------------------------------------------------+