Исходный код
Определение текущего состояния рынка — фундаментальная задача для любого квантового разработчика. Торговля трендовыми методами во флэте ведет к неминуемой просадке, равно как и контртрендовые сетки быстро уничтожают депозит при сильном направленном движении. Для решения этой проблемы мы объединим два классических индикатора: 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: Руководство.




