// --------------------------------------------------------------------------- // Построение экстремумов, описанных как "структура рынка" у Л.Вильямса. // На этот раз учёт внутренних дней сделан ПРАВИЛЬНО. // --------------------------------------------------------------------------- #property indicator_chart_window #property indicator_buffers 6 #property indicator_color1 Aqua #property indicator_color2 Blue #property indicator_color3 DeepPink #property indicator_color4 Aqua #property indicator_color5 Blue #property indicator_color6 DeepPink // Коды стрелок. #define ARROW_CODE_ST 0x6C #define ARROW_CODE_MT 0x6C #define ARROW_CODE_LT 0x6C // Глубина просматриваемой истории, 0 - вся история. extern int HISTORY_DEPTH = 16384; // Буферы индикатора. double buf_st_max[], buf_mt_max[], buf_lt_max[]; double buf_st_min[], buf_mt_min[], buf_lt_min[]; // Вспомогательные массивы для расчётов. int min[], max[]; // Отслеживание формирования баров. datetime last_bar = 0; // Инициализация. int init() { // Контроль параметров. if((HISTORY_DEPTH == 0) || (HISTORY_DEPTH > Bars)) { HISTORY_DEPTH = Bars; } IndicatorShortName(StringConcatenate( "AZZX - LARRY v2.0 (", HISTORY_DEPTH, ")")); IndicatorDigits(Digits); SetIndexBuffer(0, buf_st_max); SetIndexBuffer(1, buf_mt_max); SetIndexBuffer(2, buf_lt_max); SetIndexBuffer(3, buf_st_min); SetIndexBuffer(4, buf_mt_min); SetIndexBuffer(5, buf_lt_min); SetIndexStyle(0, DRAW_ARROW); SetIndexStyle(1, DRAW_ARROW); SetIndexStyle(2, DRAW_ARROW); SetIndexStyle(3, DRAW_ARROW); SetIndexStyle(4, DRAW_ARROW); SetIndexStyle(5, DRAW_ARROW); SetIndexArrow(0, ARROW_CODE_ST); SetIndexArrow(1, ARROW_CODE_MT); SetIndexArrow(2, ARROW_CODE_LT); SetIndexArrow(3, ARROW_CODE_ST); SetIndexArrow(4, ARROW_CODE_MT); SetIndexArrow(5, ARROW_CODE_LT); SetIndexEmptyValue(0, 0); SetIndexEmptyValue(1, 0); SetIndexEmptyValue(2, 0); SetIndexEmptyValue(3, 0); SetIndexEmptyValue(4, 0); SetIndexEmptyValue(5, 0); SetIndexLabel(0, "SHORT-TERM MAXIMUM"); SetIndexLabel(1, "MEDIUM-TERM MAXIMUM"); SetIndexLabel(2, "LONG-TERM MAXIMUM"); SetIndexLabel(3, "SHORT-TERM MINIMUM"); SetIndexLabel(4, "MEDIUM-TERM MINIMUM"); SetIndexLabel(5, "LONG-TERM MINIMUM"); ArrayResize(min, HISTORY_DEPTH); ArrayResize(max, HISTORY_DEPTH); return(0); } // Главный цикл. int start() { int i, l, r; // Работаем только по сформированным барам. // Также обрабатываем ситуацию обновления данных. if((last_bar == Time[0]) && (Bars == IndicatorCounted() + 1)) return(0); last_bar = Time[0]; // Инициализация массивов. ArrayInitialize(min, 0); ArrayInitialize(max, 0); // Поиск краткосрочных экстремумов. for(i = HISTORY_DEPTH - 2; i > 1; i--) { l = left_bar(i); r = right_bar(i); if((l > 0) && (r > 0)) { if(((Low[l] >= Low[i]) && (Low[r] > Low[i])) || ((Low[l] > Low[i]) && (Low[r] > Low[i]))) { min[i] = 1; } } if((l > 0) && (r > 0)) { if(((High[l] <= High[i]) && (High[r] < High[i])) || ((High[l] < High[i]) && (High[r] < High[i]))) { max[i] = 1; } } } // Поиск среднесрочных экстремумов. for(i = HISTORY_DEPTH - 2; i > 1; i--) { l = left_st_min(i); r = right_st_min(i); if((l > 0) && (r > 0)) { if(((Low[l] >= Low[i]) && (Low[r] > Low[i])) || ((Low[l] > Low[i]) && (Low[r] > Low[i]))) { min[i] = 2; } } l = left_st_max(i); r = right_st_max(i); if((l > 0) && (r > 0)) { if(((High[l] <= High[i]) && (High[r] < High[i])) || ((High[l] < High[i]) && (High[r] < High[i]))) { max[i] = 2; } } } // Поиск долгосрочных экстремумов. for(i = HISTORY_DEPTH - 2; i > 1; i--) { l = left_mt_min(i); r = right_mt_min(i); if((l > 0) && (r > 0)) { if(((Low[l] >= Low[i]) && (Low[r] > Low[i])) || ((Low[l] > Low[i]) && (Low[r] > Low[i]))) { min[i] = 3; } } l = left_mt_max(i); r = right_mt_max(i); if((l > 0) && (r > 0)) { if(((High[l] <= High[i]) && (High[r] < High[i])) || ((High[l] < High[i]) && (High[r] < High[i]))) { max[i] = 3; } } } // Отметка экстремумов. ArrayInitialize(buf_st_min, 0); ArrayInitialize(buf_mt_min, 0); ArrayInitialize(buf_lt_min, 0); ArrayInitialize(buf_st_max, 0); ArrayInitialize(buf_mt_max, 0); ArrayInitialize(buf_lt_max, 0); for(i = HISTORY_DEPTH - 1; i > 0; i--) { switch(min[i]) { case 1 : buf_st_min[i] = Low[i]; break; case 2 : buf_mt_min[i] = Low[i]; break; case 3 : buf_lt_min[i] = Low[i]; break; } switch(max[i]) { case 1 : buf_st_max[i] = High[i]; break; case 2 : buf_mt_max[i] = High[i]; break; case 3 : buf_lt_max[i] = High[i]; break; } } return(0); } // Проверка, что заданный бар - внутренний. bool is_internal(int bar) { return((High[bar] < High[bar + 1]) && (Low [bar] > Low [bar + 1])); } // Возвращает бар слева от заданного бара или -1. int left_bar(int bar) { int i; for(i = bar + 1; i < HISTORY_DEPTH - 2; i++) { if(is_internal(i) == false) { return(i); } } return(-1); } // Возвращает бар справа от заданного бара или -1. int right_bar(int bar) { int i; for(i = bar - 1; i > 0; i--) { if(is_internal(i) == false) { return(i); } } return(-1); } // Возвращает краткосрочный минимум слева от заданного бара, или -1. int left_st_min(int bar) { int i; for(i = bar + 1; i < HISTORY_DEPTH - 2; i++) { if(min[i] > 0) { return(i); } } return(-1); } // Возвращает краткосрочный минимум справа от заданного бара, или -1. int right_st_min(int bar) { int i; for(i = bar - 1; i > 0; i--) { if(min[i] > 0) { return(i); } } return(-1); } // Возвращает краткосрочный максимум слева от заданного бара, или -1. int left_st_max(int bar) { int i; for(i = bar + 1; i < HISTORY_DEPTH - 2; i++) { if(max[i] > 0) { return(i); } } return(-1); } // Возвращает краткосрочный максимум справа от заданного бара, или -1. int right_st_max(int bar) { int i; for(i = bar - 1; i > 0; i--) { if(max[i] > 0) { return(i); } } return(-1); } // Возвращает среднесрочный минимум слева от заданного бара, или -1. int left_mt_min(int bar) { int i; for(i = bar + 1; i < HISTORY_DEPTH - 2; i++) { if(min[i] > 1) { return(i); } } return(-1); } // Возвращает среднесрочный минимум справа от заданного бара, или -1. int right_mt_min(int bar) { int i; for(i = bar - 1; i > 0; i--) { if(min[i] > 1) { return(i); } } return(-1); } // Возвращает среднесрочный максимум слева от заданного бара, или -1. int left_mt_max(int bar) { int i; for(i = bar + 1; i < HISTORY_DEPTH - 2; i++) { if(max[i] > 1) { return(i); } } return(-1); } // Возвращает среднесрочный максимум справа от заданного бара, или -1. int right_mt_max(int bar) { int i; for(i = bar - 1; i > 0; i--) { if(max[i] > 1) { return(i); } } return(-1); }