// --------------------------------------------------------------------------- // Зигзаг по экстремумам как у Л.Вильямса. // // Версия 2.0: Введена оптимизация последовательностей экстремумов. // // Версия 3.0: Введён режим "быстрой" работы по сформировавшимся барам. // Введена подсветка трёх уровней экстремумов - как в книге // Ларри Вильямса. // --------------------------------------------------------------------------- #property indicator_chart_window #property indicator_buffers 5 #property indicator_color1 SkyBlue #property indicator_color2 SkyBlue #property indicator_color3 Lime #property indicator_color4 Blue #property indicator_color5 Red #property indicator_width1 2 #property indicator_width2 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_l1[],buf_l2[],buf_l3[]; int maximum[],minimum[]; // Предел уровня, до которого ищем экстремумы. int max_level; // Инициализация. int init() { IndicatorShortName(StringConcatenate( "AZZX - LARRYZZ v3.0 (",ZZ_LINE_LEVEL,", ",FAST_MODE,")")); SetIndexBuffer(0,buf_zz1); SetIndexBuffer(1,buf_zz2); SetIndexBuffer(2,buf_l1); SetIndexBuffer(3,buf_l2); SetIndexBuffer(4,buf_l3); SetIndexStyle(0,DRAW_ZIGZAG); SetIndexStyle(1,DRAW_ZIGZAG); SetIndexStyle(2,DRAW_ARROW); SetIndexStyle(3,DRAW_ARROW); SetIndexStyle(4,DRAW_ARROW); SetIndexArrow(2,ARROW_CODE_L1); SetIndexArrow(3,ARROW_CODE_L2); SetIndexArrow(4,ARROW_CODE_L3); SetIndexEmptyValue(0,0); SetIndexEmptyValue(1,0); SetIndexEmptyValue(2,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_l1,0); ArrayInitialize(buf_l2,0); ArrayInitialize(buf_l3,0); for(i=limit-1; i>=0; i--) { if(maximum[i]>=ZZ_LINE_LEVEL) { for(j=i+1; 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=ZZ_LINE_LEVEL) { // Нормальная ситуация. break; } else if((minimum[i]>=ZZ_LINE_LEVEL) && (buf_zz2[i]>0)) { // Останется только один... if(Low[i]= 3) buf_l3[i] = High[i]; if(minimum[i] >= 3) buf_l3[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); } //+------------------------------------------------------------------+