Возможности Мастера MQL5, которые вам нужно знать (Часть 56): Фракталы Билла Вильямса
Введение
Фрактальный индикатор Билла Вильямса является одним из ключевых и важных индикатором. Он в первую очередь определяет точки разворота в поведении цены торгуемых символов. Основанный на концепции фракталов, повторяющийся паттерн из 5 столбцов часто обозначается как медвежий, если средний столбец из 5 имеет самый высокий максимум, или как бычий, если средний столбец имеет самый низкий минимум. Как и в предыдущих статьях серии, мы рассмотрим некоторые паттерны этого индикатора, которые могут быть использованы трейдерами.
Последовательные фракталы в одном направлении
Для нашего первого паттерна (паттерн 0), бычья формация определяется, когда серия бычьих фрактальных минимумов формируется на уровне или вблизи предыдущего минимума. Обычно это интерпретируется как обнаружение рынком поддержки в данной точке. Важно отметить, что под последовательными фрактальными минимумами подразумевается отсутствие фрактального максимума между ними. Это важный показатель, поскольку типичные паттерны представляют собой чередование фрактальных максимумов и фрактальных минимумов. Однако бычий тренд рассматривается как признак того, что разные покупатели выходят на рынок по схожим ценовым уровням, что подтверждает тезис о фазе накопления, предшествующей восходящему движению.
И наоборот, несколько последовательных максимумов медвежьих фракталов могут обозначать уровень сопротивления, который цена не в состоянии пробить. Такое резкое отторжение (или повторное отторжение на больших таймфреймах) часто указывает на сильное давление со стороны продавцов и вероятное продолжение или начало нисходящего тренда.
В MQL5 мы реализуем паттерн 0 следующим образом:
//+------------------------------------------------------------------+ //| Check for Pattern 0. | //+------------------------------------------------------------------+ bool CSignalFractals::IsPattern_0(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && FractalLow(X() + 1) != 0.0 && FractalLow(X()) != 0.0) { return(true); } else if(T == POSITION_TYPE_SELL && FractalHigh(X() + 1) != 0.0 && FractalHigh(X()) != 0.0) { return(true); } return(false); }
По умолчанию в набор встроенных индикаторов входит фрактальный индикатор Билла Уильямса. Также требуется некоторая корректировка, поскольку многие значения для буферов Upper/Highs и Lower/Lows при первом использовании дают значения NaN. Поэтому мы создаем модифицированную версию, вводя две функции - FractalHigh и FractalLow. Код обеих приведен ниже:
double FractalHigh(int ind) { // m_high.Refresh(-1); if(m_high.MaxIndex(ind, 5) == ind) { return(m_high.GetData(ind)); } return(0.0); }
double FractalLow(int ind) { // m_low.Refresh(-1); if(m_low.MinIndex(ind, 5) == ind) { return(m_low.GetData(ind)); } return(0.0); }
В pattern-0 мы просто вызываем функцию FractalLow на двух предыдущих последовательных барах при проверке бычьего сигнала или функцию FractalHigh на том же баре при поиске медвежьего паттерна. Читатель может настроить количество последовательных баров, увеличив его при необходимости сортировки ложных сигналов. Однако, как это часто бывает, для проверки надежности торговых стратегий требуется меньшее количество настроек в течение более длительных периодов. Все тесты паттернов этого индикатора мы проводим на символе GBPUSD, на 4-часовом таймфрейме за 2024 год, оптимизировав паттерны для 2023 года. Форвард-тест для паттерна 0 дает нам следующий результат.

Паттерн 0 указывает на сильное продолжение тренда. Это может помочь в повторном открытии позиций в рамках преобладающего тренда, если была произведена фиксация прибыли.
Прорыв фрактального тренда
Паттерн 1 (второй по счету) определяет свою бычью формацию, во-первых, медвежьим фракталом, который служил сопротивлением. Бычья формация возникает, когда цена, двигаясь против тренда, решительно пробивает этот фрактальный максимум. Этот прорыв интерпретируется как подавление покупателями продавцов, в результате чего прежний уровень сопротивления превращается в уровень поддержки, сигнализируя о развороте тренда. Это также может быть сильным продолжением тренда, если оно произойдет в рамках гораздо более широкого бычьего тренда, который стал менее очевидным на более коротких таймфреймах.
Медвежий вариант паттерна 1, как и следовало ожидать, будет зеркально противоположным. За бычьим фракталом последует пробитие ценой минимума фрактала. Этот прорыв рассматривается как признак того, что продавцы берут ситуацию под контроль и создают предпосылки для нисходящего тренда. В MQL5 паттерн реализуется следующим образом:
//+------------------------------------------------------------------+ //| Check for Pattern 1. | //+------------------------------------------------------------------+ bool CSignalFractals::IsPattern_1(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && FractalHigh(X() + 1) != 0.0 && Close(X()) > FractalHigh(X() + 1)) { return(true); } else if(T == POSITION_TYPE_SELL && FractalLow(X() + 1) != 0.0 && Close(X()) < FractalLow(X() + 1)) { return(true); } return(false); }
В приведенном выше коде мы проверяем наличие фрактальных точек на предыдущем баре, а затем сравниваем текущую цену закрытия с этой фрактальной ценой. Как следует из логики, фрактальный максимум (медвежий фрактал) имеет отношение к бычьему паттерну, а фрактальный минимум также важен для медвежьего паттерна.
Форвард-тест на 2024 год, основанный на оптимизации пороговых значений открытия и закрытия на 2023 год, дает нам следующий результат:

Паттерн 1 выделяется тем, что, в отличие от паттерна 0, который является продолжением, он может служить в качестве сигнала разворота. Поэтому всегда полезно использовать его в сочетании с другими индикаторами.
Внутренние фракталы (нижние максимумы, верхние минимумы)
Паттерн 2 является бычьим, когда бычьи фракталы (минимумы колебаний) образуются вблизи диапазона предыдущего, более широкого фрактала. В этом диапазоне ценовое движение часто сжимается, при этом нижние фракталы образуют почти прямую линию. Таким образом, если цена поднимется выше этого узкого диапазона, это подтвердит бычий тренд, поскольку покупатели будут выталкивать цену из зоны консолидации.
С другой стороны, если при медвежьей фрактальной формации максимумы колебаний образуют кластер в пределах ранее сформированного медвежьего фрактального диапазона, это также будет означать период неопределенности. Как только цена опустится ниже нижней границы этого диапазона и поддержка будет пробита, прорыв вниз подтвердит медвежье движение. Вот как это реализовано в MQL5:
//+------------------------------------------------------------------+ //| Check for Pattern 2. | //+------------------------------------------------------------------+ bool CSignalFractals::IsPattern_2(ENUM_POSITION_TYPE T) { CArrayDouble _buffer; if(T == POSITION_TYPE_BUY) { for(int i = 0; i < m_periods; i++) { if(FractalLow(X() + i) != 0.0) { _buffer.Add(FractalLow(X() + i)); } } if(_buffer[_buffer.Maximum(0, _buffer.Total())] - _buffer[_buffer.Minimum(0, _buffer.Total())] <= fabs(Close(X()) - Close(X() + 10))) { return(true); } } else if(T == POSITION_TYPE_SELL) { for(int i = 0; i < m_periods; i++) { if(FractalHigh(X() + i) != 0.0) { _buffer.Add(FractalHigh(X() + i)); } } if(_buffer[_buffer.Maximum(0, _buffer.Total())] - _buffer[_buffer.Minimum(0, _buffer.Total())] <= fabs(Close(X()) - Close(X() + 10))) { return(true); } } return(false); }
Реализация этого паттерна, согласно нашему подходу, требует использования стандартного класса для работы с массивами. Это связано с тем, что мы ищем фрактальные точки за фиксированный период времени, а количество полученных точек неопределенно. При этом нам также необходимо определить стандартное отклонение этих фрактальных точек.
Поскольку наш класс массивов не предоставляет функцию стандартного отклонения, как векторный тип данных, и поскольку он также требует больших вычислительных затрат, мы решили использовать диапазон этих точек. Чтобы понять, насколько сужен их диапазон, мы сравниваем его с величиной тренда в цене закрытия, и если он меньше, то это подтверждает наши предположения.
Строго говоря, это приблизительная оценка, поскольку легко заметить, что на трендовых рынках, когда величина изменения цены закрытия становится достаточно большой, любой набор фрактальных точек пройдет этот тест. Поэтому читателям может быть полезно внести изменения, например, сравнить диапазон фрактальных точек или их стандартное отклонение с абсолютным значением. Это значение можно скорректировать с помощью оптимизации.
Результаты форвард-теста после оптимизации нашего советника, созданного с помощью Мастера, на валютной паре USDJPY на 4-часовом таймфрейме следующие:

Паттерн 2 представляет собой паттерн сжатия, указывающий на потенциальный прорыв. На разных таймфреймах, когда внутри более крупных фракталов формируются меньшие, это обычно указывает на сжатие перед расширением.
Фрактальная дивергенция с учетом ценового движения
Расхождение с динамикой цен — это наш паттерн 3. В этом случае бычья дивергенция наблюдается, когда цена формирует более низкий минимум (что указывает на устойчивое нисходящее давление), однако соответствующие бычьи фракталы (минимумы колебаний) находятся выше минимумов предыдущего колебания. Это расхождение интерпретируется как бычий сигнал, поскольку, несмотря на падение цен, базовый уровень поддержки укрепляется, что указывает на скорый бычий разворот.
Медвежья дивергенция, с другой стороны, возникает, когда цена формирует более высокий максимум, в то время как медвежьи фрактальные максимумы находятся ниже предыдущих. Такая ситуация обычно сигнализирует о том, что, несмотря на рост цены, сопротивление оказывает давление на цену, что может быть предвестником потери покупательной способности и разворота в сторону снижения. Реализуем это в MQL5 следующим образом:
//+------------------------------------------------------------------+ //| Check for Pattern 3. | //+------------------------------------------------------------------+ bool CSignalFractals::IsPattern_3(ENUM_POSITION_TYPE T) { CArrayDouble _buffer; if(T == POSITION_TYPE_BUY) { for(int i = 0; i < m_periods; i++) { if(FractalLow(X() + i) != 0.0) { _buffer.Add(FractalLow(X() + i)); } if(_buffer.Total() >= 2) { break; } } if(_buffer[0] > _buffer[1] && Low(X()) < Low(X() + 1)) { return(true); } } else if(T == POSITION_TYPE_SELL) { for(int i = 0; i < m_periods; i++) { if(FractalHigh(X() + i) != 0.0) { _buffer.Add(FractalHigh(X() + i)); } if(_buffer.Total() >= 2) { break; } } if(_buffer[0] < _buffer[1] && High(X()) > High(X() + 1)) { return(true); } } return(false); }
Для реализации нашего паттерна 3 также необходимо использовать стандартный класс массивов, доступный в среде разработки MQL5. В основном это связано с причинами, уже упомянутыми в паттерне 2, однако в данном случае нам нужны только 2 фрактальные точки, а не их совокупность за период, заданный входным параметром m_periods. Как уже говорилось выше, для определения потенциального сигнала мы используем две фрактальные точки вместе с двумя крайними ценовыми точками.
Анализ результатов оптимизации с использованием аналогичных символов, таймфреймов и тестового периода, как и в предыдущих случаях, дает нам следующий отчет:

Противоположные фракталы-близнецы (зоны разворота)
Два противоположных фрактала образуют наш паттерн 4. Бычья формация для этого паттерна включает в себя два одинаково расположенных фрактала: бычий (на минимумах) и медвежий (на максимумах). Пересечение этих двух точек создает зону нерешительности. Когда цена отскакивает от бычьего фрактала и поднимается выше медвежьего фрактала, подтверждается бычий сигнал.
При медвежьей формации бычий фрактал сразу сменяется медвежьим фракталом. Если цена отскакивает от медвежьего (максимального) фрактала и опускается ниже бычьего фрактала, то подтверждается сигнал к продаже. Реализация в MQL5-коде:
//+------------------------------------------------------------------+ //| Check for Pattern 4. | //+------------------------------------------------------------------+ bool CSignalFractals::IsPattern_4(ENUM_POSITION_TYPE T) { bool _1 = (FractalHigh(X() + 1) != 0.0 && FractalLow(X() + 1) != 0.0); bool _2 = (FractalHigh(X() + 2) != 0.0 && FractalLow(X() + 2) != 0.0); if(_1 || _2) { if(T == POSITION_TYPE_BUY) { if((_1 && Close(X()) > FractalHigh(X() + 1)) || (_2 && Close(X()) > FractalHigh(X() + 2))) { return(true); } } else if(T == POSITION_TYPE_SELL) { if((_1 && Close(X()) < FractalLow(X() + 1)) || (_2 && Close(X()) < FractalLow(X() + 2))) { return(true); } } } return(false); }
В нашем коде используются две логические переменные для проверки наличия фрактального паттерна с двойным сечением. Мы решили использовать две логические переменные, потому что эффект от этого уникального паттерна может немного замедляться (но не отставать). Каждое значение обозначает либо последний завершенный бар, либо бар перед ним. Если паттерн обнаружен, мы просто проверяем, пробила ли цена закрытия какой-либо из своих ключевых уровней, как уже объяснялось выше.
После оптимизации форвард-тест паттерна дает нам следующие результаты:

Последовательное появление бычьих и медвежьих фракталов также указывает на еще один момент неопределенности на рынках. Таким образом, прорывы с обеих сторон используются в качестве сигналов для паттерна 4.
Фрактальное подтверждение максимумов и минимумов колебаний рынка.
Для паттерна 5 мы рассматриваем движение цены на протяжении ряда баров относительно фрактальных эталонов. Бычья формация определяется, когда формируется бычий фрактал (который часто является потенциальным уровнем поддержки), и последующее движение цены не пробивает этот уровень значительно ниже. Если цена продолжит отскакивать от этого уровня, это подтвердит тезис о том, что это зона бычьей поддержки.
И наоборот, медвежье колебание/формация формируется, если устанавливается фрактальный максимум, и после последующего движения цены она не превышает верхний предел фрактала. Аргумент здесь заключается в том, что постоянная неспособность пробить фрактал вверх усиливает его роль как зоны сопротивления и, следовательно, как сигнала медвежьих настроений. Реализуем это в MQL5 следующим образом:
//+------------------------------------------------------------------+ //| Check for Pattern 5. | //+------------------------------------------------------------------+ bool CSignalFractals::IsPattern_5(ENUM_POSITION_TYPE T) { vector _std; _std.Init(5); _std.Fill(0.0); if(T == POSITION_TYPE_BUY && FractalLow(X() + m_periods) != 0.0) { if(_std.CopyRates(m_symbol.Name(), m_period, 4, 0, m_periods) && _std.Std() <= fabs(Close(X()) - Close(X() + m_periods))) { return(true); } } else if(T == POSITION_TYPE_SELL && FractalHigh(X() + m_periods)) { if(_std.CopyRates(m_symbol.Name(), m_period, 2, 0, m_periods) && _std.Std() <= fabs(Close(X()) - Close(X() + m_periods))) { return(true); } } return(false); }
Приведенный выше код использует вектор не только для копирования буфера необходимых нам скоростей, но и для эффективного получения их стандартного отклонения. Мы сравниваем это отклонение с величиной преобладающего тренда в цене закрытия, как мы это делали с паттерном 2. Поэтому недостатки и предостережения, изложенные для паттерна 2, применимы и здесь, так что читатель может внести необходимые изменения в прилагаемый код.
После оптимизации с использованием аналогичных символов, окон и таймфрейма форвард-тест дал следующие результаты:

Ранее в этой серии я не проводил форвард-тесты, но поскольку тестовые окна очень узкие, теперь мы включаем их в стандартную практику. Я не буду приводить описания оптимизационных запусков в течение периода обучения, поскольку они займут слишком много места.
Колебания фрактального неудачного движения цены
Паттерн 6 фокусируется на "неспособности" цены пробить фрактальные уровни. Для оптимистично настроенных инвесторов после бычьего фрактального колебания, если цена пытается пробить еще более низкий уровень, и эта попытка терпит неудачу, то есть новый минимум отбивается быстрым разворотом вверх, это часто указывает на то, что продавцы исчерпали свои ресурсы и покупателям необходимо вмешаться.
Напротив, для медведей, когда формируется фрактальный максимум и цена пытается подняться выше фрактала, но терпит неудачу, эта "неудача в развороте" рассматривается как признак того, что продавцы контролируют ситуацию и что цена, вероятно, движется к нисходящему тренду. Реализация в MQL5:
//+------------------------------------------------------------------+ //| Check for Pattern 6. | //+------------------------------------------------------------------+ bool CSignalFractals::IsPattern_6(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && FractalLow(X() + 2) != 0.0) { if(Low(X() + 1) <= FractalLow(X() + 2) && Close(X()) >= High(X() + 2)) { return(true); } } else if(T == POSITION_TYPE_SELL && FractalHigh(X() + 2) != 0.0) { if(High(X() + 1) >= FractalHigh(X() + 2) && Close(X()) <= Low(X() + 2)) { return(true); } } return(false); }
Это один из самых простых паттернов в плане реализации в коде. Как уже говорилось выше, мы просто сравниваем предыдущие минимальные цены с фрактальным минимумом, предшествовавшим ему, а затем цену закрытия с максимальной ценой за два бара до этого на бычьем рынке. В случае медвежьего тренда мы поступаем наоборот. Читатель может сам решить, насколько глубоко он хочет погрузиться в историю.
После оптимизации, как это было в случае с паттернами 0-5 для пороговых значений открытия и закрытия этого паттерна, мы получаем следующий отчет:

Фрактальный максимум (или минимум), который не был превзойден последующими свечами, часто служит сигналом отскока. Это убедительный сигнал исчерпания тренда.
Фрактальное скопление вокруг скользящих средних
Наш восьмой паттерн (паттерн 7) сочетает фрактальный индикатор со скользящей средней. В бычьем сценарии, когда серия фрактальных минимумов группируется вблизи скользящей средней (например, 50-дневной скользящей средней), это рассматривается как признак того, что скользящая средняя выступает в качестве сильного уровня поддержки. Таким образом, эти фрактальные минимумы, как правило, предоставляют покупателям возможности для входа на рынок, и как только цена решительно преодолевает ближайший уровень сопротивления или даже саму скользящую среднюю, это подтверждает бычий тренд.
Аналогично, медвежья формация — это когда несколько фрактальных максимумов скапливаются вокруг скользящей средней, которая в данный момент выступает в качестве сопротивления. Повторяющийся отскок цены от этих уровней и решительное движение ниже уровня поддержки или скользящей средней подтверждают медвежий тренд. Реализация в MQL5:
//+------------------------------------------------------------------+ //| Check for Pattern 7. | //+------------------------------------------------------------------+ bool CSignalFractals::IsPattern_7(ENUM_POSITION_TYPE T) { CArrayDouble _buffer; if(T == POSITION_TYPE_BUY) { for(int i = 1; i < m_periods; i++) { if(FractalLow(X() + i) != 0.0) { _buffer.Add(fabs(FractalLow(X() + i) - MA(X() + i))); } } if(_buffer[_buffer.Maximum(0, _buffer.Total())] <= fabs(Close(X() + 1) - Close(X() + m_periods)) && Close(X() + 1) <= MA(X() + 1) && Close(X()) > MA(X())) { return(true); } } else if(T == POSITION_TYPE_SELL) { for(int i = 1; i < m_periods; i++) { if(FractalHigh(X() + i) != 0.0) { _buffer.Add(fabs(FractalHigh(X() + i) - MA(X() + i))); } } if(_buffer[_buffer.Maximum(0, _buffer.Total())] <= fabs(Close(X() + 1) - Close(X() + m_periods)) && Close(X() + 1) >= MA(X() + 1) && Close(X()) < MA(X())) { return(true); } } return(false); }
В паттерне 7, как и в паттернах 2 и 3, также используется класс массива, но на этот раз для регистрации величины разрыва между фрактальной точкой и скользящей средней. Как уже говорилось выше, мы ищем ситуации, в которых этот разрыв как можно меньше, и поэтому мы берем его максимальное значение из всех точек разрыва, которые попадают в буфер. Мы снова сравниваем этот показатель с преобладающим трендом, поэтому напоминаем читателю о необходимости внести корректировки, как уже упоминалось выше в отношении других паттернов, таких как паттерн 6.
Пошаговое выполнение алгоритма с использованием настроек ввода, оптимизированных для того же символа, что и в приведенных выше паттернах, дает нам следующий отчет:

Когда множество фракталов укрепляются вблизи скользящей средней, это указывает на наличие зоны разворота, а прорыв из кластера подтверждает продолжение тренда или разворот.
Паттерн фрактала-разрыва
Для паттерна 8 бычий сигнал возникает, когда бычий фрактальный минимум расположен вблизи ценового разрыва (обычно в условиях высокой волатильности или ценового движения, вызванного новостями). В этой ситуации зазор служит зоной поддержки. Наличие фрактала в этом промежутке интерпретируется как признак того, что покупатели рассматривают эту область как перспективную возможность. Как только разрыв будет "заполнен" или удержан, вероятно движение вверх.
Медвежья формация также возникает, когда медвежий фрактальный максимум появляется вблизи или в месте ценового разрыва, открывшегося вверх. В этом сценарии разрыв будет представлять собой уровень сопротивления. Наличие фрактала будет указывать на то, что продавцы защищают этот уровень, и если цена начнет нисходящий тренд, то медвежий тренд закрепится. Реализуем это в MQL5 следующим образом:
//+------------------------------------------------------------------+ //| Check for Pattern 8. | //+------------------------------------------------------------------+ bool CSignalFractals::IsPattern_8(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && FractalLow(X() + 2) != 0.0) { if(Low(X() + 1) > High(X() + 2) && Close(X()) >= High(X() + 2)) { return(true); } } else if(T == POSITION_TYPE_SELL && FractalHigh(X() + 2) != 0.0) { if(High(X() + 1) < Low(X() + 2) && Close(X()) <= Low(X() + 2)) { return(true); } } return(false); }
В паттерне 8 нас интересует лишь разница в цене, поэтому наша реализация, описанная выше, почти так же проста, как и для паттерна 6.
Ниже представлены результаты форвард-теста с аналогичными настройками тестовой среды, как и выше, для 4-часового таймфрейма USDJPY за 2023 год:

Совпадение ценовых разрывов и прорывов фракталов всегда усиливает движение цены. Однако подобное чаще встречается при выходе важных новостей.
Фрактальное выравнивание с уровнями Фибоначчи
В нашем окончательном варианте мы сочетаем фрактал с уровнями Фибоначчи. Бычий тренд формируется, когда нижний фрактал совпадает с ключевым уровнем коррекции Фибоначчи. Такое совпадение между уровнем поддержки, определенным с помощью фрактальной модели, и уровнем Фибоначчи действительно усиливает область поддержки. Таким образом, это двойное подтверждение служит надежным бычьим сигналом, если цена удержится на этом уровне. Как правило, это может быть сигналом к отскоку или продолжению тренда.
В медвежьей формации верхний фрактал совпадает с критическим уровнем коррекции Фибоначчи. Такое выравнивание усиливает сопротивление в этой точке. Если после этого цене не удастся пробить зону Фибоначчи и вместо этого она развернется вниз от этой зоны, это подтвердит медвежий сигнал. Обе настройки выглядят следующим образом на языке MQL5:
//+------------------------------------------------------------------+ //| Check for Pattern 9. | //+------------------------------------------------------------------+ bool CSignalFractals::IsPattern_9(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && FractalLow(X()) != 0.0) { if(Is_Fibo_Level(X())) { return(true); } } else if(T == POSITION_TYPE_SELL && FractalHigh(X()) != 0.0) { if(Is_Fibo_Level(X())) { return(true); } } return(false); }
Разработка кода для нашего окончательного варианта оказалась довольно сложной задачей, поскольку то, что всегда очевидно при ручной торговле, в автоматизации практически не имеет места. Как "отобразить" и маркировать уровни Фибоначчи? Для решения этой задачи мы разработали простую функцию, которую назвали Is_Fibo_Level(). Текст ее представлен ниже:
bool Is_Fibo_Level(int ind) { double _r=0.0; vector _h,_l; int _size = 3 * PeriodSeconds(PERIOD_MN1) / PeriodSeconds(m_period); _h.Init(_size); _l.Init(_size); if(_h.CopyRates(m_symbol.Name(),m_period,2,0,_size) && _l.CopyRates(m_symbol.Name(),m_period,4,0,_size)) { _r = _h.Max()-_l.Min(); if(_l.Min()-ATR(ind) <= Close(ind) && Close(ind) <= _l.Min()+ATR(ind)) { return(true); } else if(_l.Min()+(0.236*_r)-ATR(ind) <= Close(ind) && Close(ind) <= _l.Min()+(0.236*_r)+ATR(ind)) { return(true); } else if(_l.Min()+(0.382*_r)-ATR(ind) <= Close(ind) && Close(ind) <= _l.Min()+(0.382*_r)+ATR(ind)) { return(true); } else if(_l.Min()+(0.5*_r)-ATR(ind) <= Close(ind) && Close(ind) <= _l.Min()+(0.5*_r)+ATR(ind)) { return(true); } else if(_l.Min()+(0.618*_r)-ATR(ind) <= Close(ind) && Close(ind) <= _l.Min()+(0.618*_r)+ATR(ind)) { return(true); } else if(_h.Max()-ATR(ind) <= Close(ind) && Close(ind) <= _h.Max()+ATR(ind)) { return(true); } } return(false); }
Эта функция просто выбирает цены за последние 3 месяца — произвольный период, который, очевидно, не охватывает ключевые уровни цен так, как это было бы при ручной настройке. Как говорится, практика - критерий истины, поэтому, возможно, чрезмерное сосредоточение на том, как мы видим вещи при ручной работе, не обязательно приводит к улучшению результатов торговли. Именно поэтому мы разработали паттерн 9, в котором просто ищем совпадение между фрактальными точками и уровнями этой функции. Индикатор ATR также используется в очень упрощенном виде для определения ширины наших уровней, поэтому в случае, если в течение 3-месячного периода наблюдается низкая волатильность, неизбежно произойдет много наложений. Это может послужить отправной точкой для заинтересованного читателя при внесении изменений.
Форвард-тест дает нам следующие результаты:

Таким образом, данная модель подтверждает наличие ключевых зон разворота. В этой серии, рассматривая различные паттерны, мы также учитывали возможность использования не только одного паттерна, как это было в случае со всеми девятью паттернами выше, но и использования всех паттернов вместе.
Объединяем все паттерны
Прилагаемый код для всех наших 9 паттернов представлен в виде пользовательского класса сигналов. Мы используем этот класс в Мастере MQL5 для создания советников. Как это сделать, можно узнать здесь и здесь. Оптимизация отдельных паттернов и проведенные выше тестовые запуски основывались на присвоении картам входных параметров специального индекса, имеющего вид 2 в степени индекса шаблона. Таким образом, для паттерна 5 индекс был равен 2^5, что соответствует 32, для паттерна 7 он был равен 128 и так далее. Однако при торговле с использованием нескольких паттернов этот входной параметр служит скорее картой, чем указателем на конкретный паттерн. У нас 9 паттернов, поэтому максимальное значение нашего параметра для maps-used равно 2^9, что равно 512 минус один (поскольку мы начинаем отсчет с нуля).
Если мы оптимизируем комбинацию паттернов на основе стандартных пороговых значений открытия и закрытия, то оптимальные входные параметры будут следующими:

Тестовый запуск на обучающих данных дает следующий отчет:


Форвард-тест за 2024 год дает следующие результаты:


На мой взгляд, эти результаты подтверждают то, что подчеркивалось в предыдущих статьях, а именно: сочетание различных паттернов требует от трейдера глубоких знаний. Сочетание паттернов требует точности. Результаты оптимизационных запусков не дадут ответов. Выше мы рассмотрели отдельные паттерны, по которым мы провели форвард-тесты. Это результаты годичного тестирования, поэтому рекомендуются более длительные периоды тестирования, и, как всегда, прошлые результаты не гарантируют будущих. Также я хочу подчеркнуть необходимость целенаправленного подхода при выборе паттернов для сигнала в отличие от усреднения.
Важность таймфреймов
Интерпретация фракталов в значительной степени субъективна и зависит от используемого таймфрейма. Более крупные таймфреймы — H4, D1 и W1 — обеспечивают более сильные и надежные сигналы, поскольку они, как правило, отфильтровывают значительную часть рыночного шума. Фракталы на этих таймфреймах часто указывают на ключевые уровни поддержки и сопротивления, на которые обращают внимание институциональные инвесторы и долгосрочные трейдеры. Сигналы формируются очень медленно, что может не устраивать многих трейдеров, но когда они все же формируются, их надежность обычно высока.
С другой стороны, сигналы на более коротких таймфреймах, таких как M15, M20, M30, встречаются чаще, но могут быть менее надежными из-за краткосрочных колебаний цен. Они лучше всего подходят для скальпинговых стратегий, где быстрая реакция вознаграждается лучше. Однако, как правило, они более склонны к ложным срабатываниям и требуют дополнительных фильтров для повышения точности.
Также существуют промежуточные таймфреймы H1, H2, и в теории они должны представлять собой компромисс между двумя крайностями. Читателю предлагается проверить достоверность этого утверждения; однако, согласно передовой практике, они хорошо работают в сочетании с фракталами на более крупных таймфреймах.
Заключение
Фракталы, как правило, являются надежными инструментами на рынках с высокой ликвидностью и сильным институциональным интересом. Резкие скачки цен при малом торговом объеме неизбежно приводят к созданию ложных фракталов, которые быстро опровергаются. Именно поэтому анализ объема или исторические графики могут использоваться для повышения уверенности в решениях, основанных на фракталах.
При этом мы рассмотрели 9 отдельных паттернов этого "ключевого" индикатора, и хотя он имеет существенные недостатки на меньших таймфреймах, при осмотрительном использовании на больших таймфреймах он может дать интересные результаты, как мы смогли убедиться, проведя тестирование некоторых паттернов в течение года.
| Файл | Описание |
|---|---|
| SignalWZ_56.mqh | Файл класса сигналов |
| WZ_56.mq5 | Файл советника с включенными файлами |
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/17334
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Нейросети в трейдинге: Сеточная аппроксимация событийного потока как инструмент анализа ценовых паттернов (EEMFlow)
Знакомство с языком MQL5 (Часть 20): Введение в гармонические паттерны
Разработка инструментария для анализа движения цен (Часть 15): Введение в теорию четвертей (II) — советник Intrusion Detector
Алгоритм дендритных клеток — Dendritic Cell Algorithm (DCA)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования