//+-------------------------------------------------------------------------------------+ //| VolatilityFlatAndTrend.mq4 | //| Scriptong | //| scriptong@mail.ru | //+-------------------------------------------------------------------------------------+ #property copyright "Scriptong" #property link "scriptong@mail.ru" #property indicator_chart_window // индикатор отображается в окне котировок #property indicator_buffers 6 // Количество индикаторных буферов - 6 #property indicator_color1 DodgerBlue #property indicator_color2 DodgerBlue #property indicator_color3 Red #property indicator_color4 Red #property indicator_color5 Blue #property indicator_color6 Red extern int ATRPeriod = 24; // период ATR double HighFlat[], // Индикаторный буфер, отображающий верхнюю границу ФЗ LowFlat[], // Индикаторный буфер, отображающий нижнюю границу ФЗ UpArr[], // Индикаторный буфер, отображающий сигналы к покупке DnArr[], // Индикаторный буфер, отображающий сигналы к продаже SignHigh[], // Индикаторный буфер, отображающий сигнальный уровень SignLow[]; // Индикаторный буфер, отображающий сигнальный уровень double FlatHigh, // Максимум формирующейся ФЗ FlatLow, // Минимум формирующейся ФЗ FlatSignHigh, // Максимум сформированного ФЗ с учетом сигнальной свечи FlatSignLow; // Минимум сформированного ФЗ с учетом сигнальной свечи datetime LastFlatBegin; // Время начала формирования последней ФЗ //+-------------------------------------------------------------------------------------+ //| Custom indicator initialization function | //+-------------------------------------------------------------------------------------+ int init() { SetIndexBuffer(0, HighFlat); // Индикаторный буфер, отображающий верхнюю границу ФЗ SetIndexStyle(0, DRAW_ARROW); // Индикатор отображается в виде значка SetIndexArrow(0, 167); SetIndexBuffer(1, LowFlat); // Индикаторный буфер, отображающий нижнюю границу ФЗ SetIndexStyle(1, DRAW_ARROW); // Индикатор отображается в виде значка SetIndexArrow(1, 167); SetIndexBuffer(2, SignHigh); // Индикаторный буфер, отображающий сигнальный уровень SetIndexStyle(2, DRAW_ARROW); // Индикатор отображается в виде значка SetIndexArrow(2, 167); SetIndexBuffer(3, SignLow); // Индикаторный буфер, отображающий сигнальный уровень SetIndexStyle(3, DRAW_ARROW); // Индикатор отображается в виде значка SetIndexArrow(3, 167); SetIndexBuffer(4, UpArr); // Индикаторный буфер, отображающий сигналы к покупке SetIndexStyle(4, DRAW_ARROW, STYLE_DOT, 2); // Индикатор отображается в виде стрелок SetIndexArrow(4, 241); // стрелка указывает вверх SetIndexBuffer(5, DnArr); // Индикаторный буфер, отображающий сигналы к продаже SetIndexStyle(5, DRAW_ARROW, STYLE_DOT, 2); // Индикатор отображается в виде стрелок SetIndexArrow(5, 242); // стрелка указывает вниз return(0); } //+-------------------------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+-------------------------------------------------------------------------------------+ int deinit() { return(0); } //+-------------------------------------------------------------------------------------+ //| Custom indicator iteration function | //+-------------------------------------------------------------------------------------+ int start() { // - 1 - =========================== Поиск начальной свечи цикла ======================== if (LastFlatBegin == 0) // Если это первый подход, то цикл проходит по всей истории int limit = Bars - 1; else // иначе отображаются бары от начала последней ФЗ limit = iBarShift(NULL, 0, LastFlatBegin); // - 1 - ================================= Окончание блока ============================== // - 2 - ======================== Вычисление значений индикаторных буферов ============== for (int i = limit; i > 0; i--) // Пересчитываются значения только новых свечей { HighFlat[i] = EMPTY_VALUE; // Пока границы канала не определены LowFlat[i] = EMPTY_VALUE; SignHigh[i] = EMPTY_VALUE; // Пока границы канала не определены SignLow[i] = EMPTY_VALUE; double ATR1 = iATR(NULL, 0, ATRPeriod, i); // Стандартный ATR double ATR2 = iATR(NULL, 0, ATRPeriod, i+1); // Стандартный ATR double Curr1 = High[i] - Low[i]; // Волатильность одной свечи double Curr2 = High[i+1] - Low[i+1]; // Волатильность одной свечи // - 2.1 - ============================ Найдено начало флэта =========================== if (Curr1 < ATR1 && Curr2 > ATR2) // Падение волатильности ниже среднего уровня { FlatHigh = High[i]; // Отмечаются начальные значения FlatLow = Low[i]; LastFlatBegin = Time[i]; // Фиксируется время начала ФЗ } // - 2.1 - ============================= Окончание блока =============================== // - 2.2 - ======================== Обнаружено продолжение флэта ======================= if (Curr1 < ATR1 && Curr2 < ATR2) // Волатильность продолжает находиться ниже { // среднего уровня FlatHigh = MathMax(High[i], FlatHigh); // Определяются экстремальные значения FlatLow = MathMin(Low[i], FlatLow); // - 2.2.1 - ==================== Отображение границ канала ========================= int B = iBarShift(NULL, 0, LastFlatBegin); // Поиск начального бара ФЗ for (int j = B; j > i; j--) { HighFlat[j] = FlatHigh; // Обновление границ LowFlat[j] = FlatLow; } // - 2.2.1 - =========================== Окончание блока ============================ } // - 2.2 - ============================= Окончание блока =============================== // - 2.3 - ========================= Обнаружено окончание флэта ======================== if (Curr1 > ATR1 && Curr2 < ATR2) // Рост волатильности выше среднего уровня { FlatSignHigh = MathMax(High[i], FlatHigh); // Флэт с учетом сигнальной свечи FlatSignLow = MathMin(Low[i], FlatLow); // - 2.3.1 - ======================== Генерация сигнала SELL ======================== if (Open[i] > Close[i] && // Сигнальная свеча бычья Close[i] < FlatHigh && // Закрылась внутри ФЗ Close[i] > (FlatHigh+FlatLow)/2) // Но выше середины ФЗ DnArr[i-1] = High[i-1] + ATR1; // Отображение стрелки вниз // - 2.3.1 - =========================== Окончание блока ============================ // - 2.3.2 - ======================== Генерация сигнала BUY ========================= if (Open[i] < Close[i] && // Сигнальная свеча медвежья Close[i] > FlatLow && // Закрылась внутри ФЗ Close[i] < (FlatHigh+FlatLow)/2) // Но ниже середины ФЗ UpArr[i-1] = Low[i-1] - ATR1; // Отображение стрелки вверх // - 2.3.2 - =========================== Окончание блока ============================ // - 2.3.3 - ==================== Отображение границ канала ========================= B = iBarShift(NULL, 0, LastFlatBegin); // Поиск начального бара ФЗ for (j = B; j > i; j--) { HighFlat[j] = FlatHigh; // Обновление границ LowFlat[j] = FlatLow; } SignHigh[i] = FlatSignHigh; SignLow[i] = FlatSignLow; // - 2.3.3 - =========================== Окончание блока ============================ } // - 2.3 - ============================= Окончание блока =============================== } // - 2 - ================================= Окончание блока ============================== return(0); }