Скрипт определения фазы рынка (Флэт/Тренд) на MQL5: ADX + Bollinger Bands

Скрипт определения фазы рынка (Флэт/Тренд) на MQL5: ADX + Bollinger Bands MQL4 / MQL5 (MetaTrader)
Пошаговое руководство по созданию MQL5-скрипта для точного определения фазы рынка (флэт или тренд) с помощью комбинации индикаторов ADX и Bollinger Bands.
Суть: Скрипт на MQL5 комбинирует показания силы тренда ADX и динамической волатильности Bollinger Bands (через расчет Bandwidth и его SMA) для математически точной классификации текущего состояния рынка на флэт, тренд или переходную фазу.

Исходный код

Определение текущего состояния рынка — фундаментальная задача для любого квантового разработчика. Торговля трендовыми методами во флэте ведет к неминуемой просадке, равно как и контртрендовые сетки быстро уничтожают депозит при сильном направленном движении. Для решения этой проблемы мы объединим два классических индикатора: Average Directional Index (ADX) для измерения силы направленного движения и Bollinger Bands (BB) для оценки динамической волатильности.

Для тех, кто хочет полностью исключить временной шум при определении фаз, отличным решением станет использование альтернативных графиков. О том, как их реализовать, читайте в статье Как создать кастомный график Ренко в MetaTrader 5.

Ниже представлен готовый к использованию скрипт для MetaTrader 5. Он рассчитывает ширину полос Боллинджера (Bandwidth), сглаживает ее с помощью простой скользящей средней (SMA) для определения периодов сжатия волатильности и сопоставляет эти данные с показаниями индикатора ADX.

//+------------------------------------------------------------------+
//|                                            MarketPhaseDetect.mq5 |
//|                                  Copyright 2024, Quant Developer |
//|                                             https://finfluct.com |
//+------------------------------------------------------------------+
#property copyright "Quant Developer"
#property link      "https://finfluct.com"
#property version   "1.00"
#property script_show_inputs

//--- Input parameters
input group "--- ADX Settings ---"
input int            InpADXPeriod   = 14;       // ADX Period
input double         InpADXThreshold= 25.0;     // ADX Trend Threshold

input group "--- Bollinger Bands Settings ---"
input int            InpBBPeriod    = 20;       // BB Period
input double         InpBBDeviation = 2.0;      // BB Deviation
input ENUM_APPLIED_PRICE InpBBPrice = PRICE_CLOSE; // BB Applied Price

input group "--- Filter Settings ---"
input int            InpBBSmaPeriod = 50;       // BB Bandwidth SMA Period

//--- Enums
enum ENUM_MARKET_PHASE
{
   PHASE_FLAT,
   PHASE_TREND,
   PHASE_UNCERTAIN
};

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   string symbol = _Symbol;
   ENUM_TIMEFRAMES timeframe = _Period;

   int adxHandle = iADX(symbol, timeframe, InpADXPeriod);
   int bbHandle = iBands(symbol, timeframe, InpBBPeriod, 0, InpBBDeviation, InpBBPrice);

   if(adxHandle == INVALID_HANDLE || bbHandle == INVALID_HANDLE)
   {
      Print("Ошибка создания индикаторов.");
      return;
   }

   double adxValues[];
   double bbUpper[];
   double bbLower[];
   double bbMiddle[];

   ArraySetAsSeries(adxValues, true);
   ArraySetAsSeries(bbUpper, true);
   ArraySetAsSeries(bbLower, true);
   ArraySetAsSeries(bbMiddle, true);

   int copyCount = InpBBSmaPeriod + 5;
   if(CopyBuffer(adxHandle, MAIN_LINE, 0, copyCount, adxValues) < copyCount ||
      CopyBuffer(bbHandle, UPPER_BAND, 0, copyCount, bbUpper) < copyCount ||
      CopyBuffer(bbHandle, LOWER_BAND, 0, copyCount, bbLower) < copyCount ||
      CopyBuffer(bbHandle, BASE_LINE, 0, copyCount, bbMiddle) < copyCount)
   {
      Print("Ошибка копирования данных индикаторов.");
      IndicatorRelease(adxHandle);
      IndicatorRelease(bbHandle);
      return;
   }

   double bandwidth[];
   ArrayResize(bandwidth, copyCount);
   for(int i = 0; i < copyCount; i++)
   {
      if(bbMiddle[i] != 0)
         bandwidth[i] = (bbUpper[i] - bbLower[i]) / bbMiddle[i];
      else
         bandwidth[i] = 0;
   }

   double sum = 0;
   for(int i = 0; i < InpBBSmaPeriod; i++)
   {
      sum += bandwidth[i];
   }
   double avgBandwidth = sum / InpBBSmaPeriod;

   double currentADX = adxValues[0];
   double currentBandwidth = bandwidth[0];

   ENUM_MARKET_PHASE phase = PHASE_UNCERTAIN;
   string phaseStr = "Неопределенность";

   if(currentADX < InpADXThreshold && currentBandwidth < avgBandwidth)
   {
      phase = PHASE_FLAT;
      phaseStr = "ФЛЭТ (Низкая волатильность, слабый тренд)";
   }
   else if(currentADX >= InpADXThreshold && currentBandwidth >= avgBandwidth)
   {
      phase = PHASE_TREND;
      phaseStr = "ТРЕНД (Высокая волатильность, сильный тренд)";
   }
   else if(currentADX >= InpADXThreshold && currentBandwidth < avgBandwidth)
   {
      phase = PHASE_TREND;
      phaseStr = "ТРЕНД (Дивергенция: Сильный тренд при сжатии полос)";
   }
   else if(currentADX < InpADXThreshold && currentBandwidth >= avgBandwidth)
   {
      phase = PHASE_FLAT;
      phaseStr = "ФЛЭТ (Ложный прорыв / Расширение без тренда)";
   }

   string output = StringFormat(
      "=== Анализ фазы рынка ===\nИнструмент: %s (%s)\nТекущий ADX: %.2f (Порог: %.2f)\nТекущий Bandwidth: %.5f\nСредний Bandwidth (%d): %.5f\nОпределенная фаза: %s",
      symbol, EnumToString(timeframe), currentADX, InpADXThreshold, currentBandwidth, InpBBSmaPeriod, avgBandwidth, phaseStr
   );

   Comment(output);
   Print(output);

   IndicatorRelease(adxHandle);
   IndicatorRelease(bbHandle);
}

Если вам требуется максимальная производительность при расчете сложных фазовых паттернов на больших исторических данных, рекомендуем изучить руководство Как вызвать C++ DLL в MQL5: Ускорение расчетов для Квантов.

Разбор параметров

  • InpADXPeriod: Период усреднения технического индикатора ADX. Стандартное значение — 14.
  • InpADXThreshold: Пороговое значение ADX, выше которого фаза классифицируется как трендовая (обычно от 20 до 25).
  • InpBBPeriod: Период средней линии Bollinger Bands для оценки волатильности.
  • InpBBDeviation: Количество стандартных отклонений для построения границ полос Боллинджера.
  • InpBBPrice: Цена, используемая для расчета полос Боллинджера (по умолчанию PRICE_CLOSE).
  • InpBBSmaPeriod: Период скользящей средней, рассчитываемой по значению ширины полос (Bandwidth), для динамического определения сжатия/расширения рынка.

Как запустить

Для запуска скрипта выполните следующие шаги:

1. Откройте MetaTrader 5 и нажмите F4 для запуска редактора MetaEditor.

2. Создайте новый скрипт (Файл -> Новый -> Скрипт) и назовите его, например, MarketPhaseDetector.

3. Скопируйте представленный выше код и вставьте его в редактор, полностью заменив шаблонный код.

4. Нажмите F7 для компиляции кода. Убедитесь, что в логе компилятора нет ошибок.

5. Вернитесь в терминал MetaTrader 5, найдите скрипт в окне ‘Навигатор’ в разделе ‘Скрипты’ и перетащите его на активный график.

После того как фаза тренда успешно определена и позиция открыта, важно правильно сопровождать сделку. Для этого отлично подойдет наш материал Трейлинг-стоп по фракталам Билла Вильямса в MQL5: Руководство.

Оцените статью
FinFluct