Разработка инструментария для анализа Price Action (Часть 59): Выявление точных пробоев при фрактальной консолидации с помощью геометрической асимметрии
Содержание
- Введение
- Обзор стратегии и торговая логика
- Реализация на языке MQL5 и структура кода
- Тестирование и результаты
- Заключение
Введение
Настоящие возможности для пробоя относятся к самым прибыльным, но и к самым трудноуловимым сетапам в торговле по Price Action. Рынки нередко выходят из консолидации с убедительным импульсом, но вскоре после этого останавливаются или разворачиваются. Во многих случаях такие неудачи возникают потому, что пробою не хватает внутренней структуры или устойчивого направленного давления. Следовательно, главная задача состоит не в том, чтобы находить диапазоны, а в том, чтобы распознавать консолидации, действительно подготавливающие устойчивое развитие тренда.
В Части 58 рассматривалось, как внутренний дисбаланс и направленный уклон формируются в динамике цены перед расширением, а пробои трактовались как результат постепенных структурных сдвигов, а не изолированных или случайных событий. Непосредственно развивая эту основу, статья описывает методику Geometric Asymmetry (GA) Breakout – систему с четкими правилами для оценки того, действительно ли консолидация завершается направленным движением. Подход GA оценивает внутреннее поведение цены по структуре свингов, построенной по фракталам, и по геометрическим соотношениям, чтобы выявлять формирование направленности еще до пробоя какой-либо границы.
За счет акцента на структурной целостности, пропорциональном дисбалансе и многоуровневом подтверждении этот подход отсекает ложные расширения и нацелен на фильтрацию ложных расширений и формирование более надежных сигналов перехода от диапазона к тренду.
Обзор стратегии и торговая логика
В этой стратегии выявление пробоя рассматривается как структурная и геометрическая задача, а не как событие, связанное только с волатильностью. Цена рассматривается как последовательность свингов, формирующих ограниченные структуры, в которых дисбаланс можно объективно измерить еще до расширения. Стратегия пробоя геометрической асимметрии оценивает консолидацию не только по ее границам, но и по пропорциональным соотношениям между ее внутренними ценовыми отрезками. Направленный уклон выводится из измеримой асимметрии по расстоянию, наклону и времени, что позволяет заранее распознавать пробои на основе структурного подтверждения, а не реактивных сигналов.
Эту стратегию отличает фокус на внутренней структуре цены. Вместо опоры только на расширение волатильности или пробои диапазона стратегия оценивает поведение цены внутри консолидации, чтобы определить, какая сторона постепенно начинает доминировать.
Базовая рыночная механика
Основная концепция
Продолжительная консолидация с определенными геометрическими признаками часто предшествует выраженному ценовому расширению. Когда цена сжимается в четко заданную структуру, например прямоугольник или сужающуюся формацию, а последний свинг становится непропорционально доминирующим, это указывает на то, что одна из сторон рынка начинает перехватывать контроль. Такой дисбаланс обычно реализуется через направленный пробой.

На диаграмме выше показан диапазон консолидации, внутри которого цена колеблется в четко заданных границах, формируя структурный контекст, в котором до пробоя могут развиваться внутренний дисбаланс и направленный уклон.
Ключевые рыночные проявления, которые учитывает стратегия:
- накопление импульса – постепенное нарастание давления внутри ограниченных ценовых границ;
- сжатие волатильности – снижение амплитуды ценовых свингов перед расширением;
- направленный выход из консолидации – структурный дисбаланс, указывающий на наиболее вероятное направление пробоя.
Многоуровневая логика принятия решений
Геометрическая асимметрия (GA) описывает дисбаланс в пропорциональном поведении цены внутри диапазона консолидации. Вместо того чтобы сосредотачиваться только на пробоях границ, GA оценивает, как цена проходит внутри диапазона, сравнивая относительную длину, наклон и продолжительность последовательных отрезков свинга.
Когда один внутренний отрезок становится непропорционально доминирующим, это указывает на неравномерное направленное давление, формирующееся внутри консолидации на скрытом уровне. Таким образом, GA отражает направленность до пробоя, а не подтверждение тренда, и оценивается только после того, как сформированы корректный диапазон и объективная структура свингов. На следующей диаграмме показано, как советник оценивает структуру внутри диапазона и геометрический дисбаланс в подтвержденном диапазоне консолидации перед отслеживанием подтверждения пробоя.

Точки свинга (HH, HL, LL) определяются по фракталам Билла Вильямса и используются как входные данные для геометрического анализа. Подробное рассмотрение теории фракталов и их реализации уже дано в одной из предыдущих статей этой серии, поэтому здесь оно не повторяется.
- Фаза 1. Структурная основа (фрактальный каркас)
Если выявлены три последовательных чередующихся фрактала, структура считается корректной. Если это условие не выполняется, последовательность отбраковывается, и система продолжает отслеживать появление новых фракталов.
На этом этапе формируется структурная основа стратегии. Требование чередования точек свинга (high–low–high или low–high–low) позволяет выделять значимые развороты и одновременно отсеивать незначительные колебания. Это обеспечивает опору последующего анализа на значимое поведение цены, а не на краткосрочный шум.
- Фаза 2. Оценка диапазона (подтверждение консолидации)
Этот этап подтверждает, что выявленная структура представляет собой реальную консолидацию, а не случайное уплотнение цены. Нормализация на основе ATR позволяет стратегии адаптироваться к изменяющимся условиям волатильности, сохраняя при этом единые критерии оценки. Исключаются структуры, которые слишком широки, слишком кратковременны или больше не подтверждаются ценой.
- Фаза 3. Геометрический анализ (выявление направленного уклона)
На этом этапе вводится ключевое преимущество стратегии: выявление направленного доминирования еще до пробоя.
Оценка расстояния:
Оценка наклона:
Если наклон последнего отрезка свинга превышает наклон предыдущего в заданной пропорции, это добавляет один голос в пользу направленного уклона.
Оценка сжатия по времени:
Если последний отрезок свинга формируется быстрее предыдущего в пределах заданного порога сжатия по времени, он добавляет один голос в пользу направленного уклона.
Правило подтверждения:
Использование нескольких пропорциональных критериев исключает зависимость от какого-то одного фактора. Направленность подтверждается только тогда, когда совпадают несколько независимых характеристик.
- Фаза 4. Фиксация паттерна (подтверждение сетапа)
Как только геометрические условия выполнены, структура переходит в зафиксированное состояние наблюдения.
Критерии фиксации:
- подтвержденный направленный уклон;
- последний свинг завершается рядом с соответствующей границей;
- величина свинга остается пропорциональной диапазону;
- отсутствуют конфликтующие активные сетапы.
Свойства зафиксированного паттерна:
- направление – бычье при перевесе в пользу восходящей направленности, медвежье – в пользу нисходящей;
- опорные уровни – фиксированные максимум и минимум диапазона;
- окно наблюдения – ограничено параметром InpMaxLockBars;
- состояние – ведется активное наблюдение для подтверждения пробоя.
Фиксация структуры предотвращает перерисовку и сохраняет аналитическую целостность.
- Фаза 5. Выявление пробоя (генерация сигнала)

Советник выдает сигнал BUY только после того, как зафиксирован корректный диапазон GA, внутренняя геометрическая асимметрия подтверждает бычью направленность, а цена закрывается выше GA Range High. Сигнал SELL формируется по той же логике и появляется, когда цена закрывается ниже GA Range Low после подтвержденной внутренней медвежьей направленности.
Логика исполнения
- Бычий сетап
Сигнал BUY генерируется, когда цена уверенно закрывается выше установленного максимума диапазона с учетом буфера пробоя.
- Медвежий сетап
Сигнал SELL генерируется, когда цена уверенно закрывается ниже установленного минимума диапазона с учетом буфера пробоя.
Буфер пробоя (InpBreakBufferPts) отфильтровывает неглубокие выходы за границу и при этом позволяет своевременно участвовать в реальных расширениях. Сигналы генерируются только по закрытии свечи, что повышает согласованность и снижает число ложных срабатываний.
Контроль риска и дисциплина сигналов
Избирательность – один из базовых принципов этой стратегии. Стратегия не форсирует входы: для этого требуется согласование между структурой, волатильностью и геометрией. Минимальное расстояние между сигналами предотвращает повторные срабатывания в одной и той же зоне, особенно в условиях рваного рынка. Это помогает сохранять терпение и сосредотачивает внимание на более качественных возможностях.
Интерпретация с учетом контекста
Сигналы представляют собой подтверждение, а не прогноз. Они наиболее эффективны, когда рассматриваются в более широком контексте, наряду со структурой старшего таймфрейма, динамикой сессии или ключевыми опорными уровнями. Система работает как инструмент поддержки принятия решений, оставляя исполнение и управление рисками полностью под контролем трейдера.
Адаптивность для разных рынков и таймфреймов
Поскольку логика основана на пропорциональных соотношениях, а не на фиксированных значениях, стратегия хорошо адаптируется к разным инструментам и таймфреймам. Настраиваемые параметры позволяют тонко подстраивать модель без изменения базовой методологии. Такой баланс между последовательностью и гибкостью обеспечивает устойчивую работу в разных рыночных условиях. Поскольку каждый сигнал опирается на качество консолидации и направленный дисбаланс, стратегия Geometric Asymmetry Breakout обеспечивает дисциплинированную основу для выявления высоковероятных переходов от баланса к расширению.
В совокупности эти компоненты позволяют стратегии отслеживать условия пробоя от структурной причины к направленному следствию.

Реализация на языке MQL5 и структура кода
В этом разделе представлен подробный обзор того, как стратегия пробоя геометрической асимметрии реализована на языке MQL5. В основе кодовой базы лежит модульная архитектура с акцентом на понятность, производительность и широкие возможности настройки. Каждый компонент отвечает за конкретный аспект системы, благодаря чему формируется хорошо организованная структура, в которой легко ориентироваться и которую легко отлаживать и расширять. Такая архитектура упрощает дальнейшую доработку и адаптацию, делая систему подходящей для трейдеров с разными стилями и предпочтениями.
Обзор архитектуры
В основе этой реализации лежит модульная архитектура, разделяющая разные функциональные задачи на независимые блоки. Такое разделение позволяет разрабатывать, тестировать и сопровождать каждый модуль по отдельности, что повышает общую надежность системы. Ключевые модули включают выявление фракталов, оценку консолидации, проверку асимметрии, генерацию сигналов входа и управление паттернами. Такое четкое разделение ответственности делает код более управляемым, особенно при доработке или расширении системы по мере изменения рыночных условий.
Основу системы составляют настраиваемые пользователем входные параметры, критически важные для ее гибкости. Эти параметры позволяют адаптировать стратегию к конкретным активам, таймфреймам и индивидуальной толерантности к риску. Например, InpMaxScanBars ограничивает количество анализируемых исторических баров, что ускоряет вычисления. Другие параметры, такие как InpRangeATRMax и InpRangeATRMaxSoft, фильтруют потенциальные зоны по размеру, чтобы учитывались только значимые консолидации. Параметры проверки асимметрии – InpLenRatioMin для преимущества по расстоянию, InpSlopeRatioMin для крутизны движения и InpTimeCompressionMax для скорости движения – критически важны для выявления реальных всплесков импульса.
//====================== INPUTS ===================================== input int InpMaxScanBars = 900; input int InpATRPeriod = 14; input double InpRangeATRMax = 2.00; input int InpRangeMinBarsHard = 8; input bool InpEnableSoftRangeBars = true; input int InpRangeMinBarsSoft = 4; input double InpRangeATRMaxSoft = 1.60; input int InpRangeTestLookback = 50; input double InpRangeSideZonePct = 0.35; input double InpLenRatioMin = 1.35; input double InpSlopeRatioMin = 1.15; input double InpTimeCompressionMax = 0.95; input int InpMinGeometryVotes = 2; input double InpMaxLegVsRange = 1.50; input int InpMaxLegBars = 50; input double InpLegEndNearBoundaryPct = 0.50; input int InpBreakLookbackBars = 150; input double InpBreakBufferPts = 5.0; input int InpMaxLockBars = 30; input int InpArrowOffsetPoints = 15; input int InpArrowLabelOffset = 30; input int InpMinBarsBetweenSignals = 5; input bool InpShowSwings = true; input bool InpShowLegs = true; input bool InpShowTriangle = true; input bool InpShowLabels = true; input bool InpShowRangeLines = true; input bool InpShowCandidateRangeRect = true; input bool InpShowLockedRangeRects = true; input bool InpShowArrows = true; input bool InpShowDebug = true; // Arrow code and style input int InpArrowUpCode = 233; input int InpArrowDownCode = 234; input int InpArrowSize = 3; input color InpArrowColorUp = clrLime; input color InpArrowColorDown = clrRed; input bool InpShowArrowLabels = true; input int InpArrowLabelFontSize = 9; input string InpArrowLabelFont = "Arial"; // Alert settings input bool InpEnableAlerts = true; input bool InpAlertOnPatternLock = true; input bool InpAlertOnBreakout = true; input string InpAlertSoundPattern = "alert.wav"; input string InpAlertSoundBreakout = "alert2.wav"; input bool InpAlertPopup = true; input bool InpAlertNotification = true; input bool InpAlertEmail = false;
Дополнительные параметры включают буфер входа (InpBreakBufferPts) для предотвращения ложных срабатываний из-за небольших теней, максимальную длительность фиксации (InpMaxLockBars) для исключения нескольких сигналов по одному и тому же паттерну, а также минимальное число баров между сигналами (InpMinBarsBetweenSignals) для предотвращения переторговки. Переключатели отображения свингов, отрезков, треугольников, диапазонов, меток и стрелок позволяют настраивать визуальную подачу сигналов. Режимы оповещений можно настроить так, чтобы они включали звуки, всплывающие окна, push-уведомления и электронные письма, благодаря чему трейдер будет получать информацию о сигналах независимо от устройства и условий работы.
Выявление паттернов – нахождение поворотных точек
Процесс начинается с надежного выявления экстремумов свинга, которые служат основой для потенциальных зон. Функции IsFractalHigh() и IsFractalLow() реализуют строгое правило Билла Вильямса для пяти баров: максимум (или минимум) считается таковым только в том случае, если он выше максимумов (или ниже минимумов) двух соседних баров. Этот фильтр отбраковывает незначительные колебания и оставляет только структурные развороты, значимые для рынка. Строгое соблюдение этого правила позволяет отсекать ложные сигналы, вызванные рыночным шумом.
// Check if the bar at index i is a fractal high based on Bill Williams' five-bar rule bool IsFractalHigh(int i) { if(i<3 || i+2>=BarsTotal()) return false; double h = iHigh(_Symbol, _Period, i); return h > iHigh(_Symbol, _Period, i-1) && h > iHigh(_Symbol, _Period, i+1) && h > iHigh(_Symbol, _Period, i-2) && h > iHigh(_Symbol, _Period, i+2); } // Check if the bar at index i is a fractal low bool IsFractalLow(int i) { if(i<3 || i+2>=BarsTotal()) return false; double l = iLow(_Symbol, _Period, i); return l < iLow(_Symbol, _Period, i-1) && l < iLow(_Symbol, _Period, i+1) && l < iLow(_Symbol, _Period, i-2) && l < iLow(_Symbol, _Period, i+2); }
На этой основе GetLast3AlternatingFractals() эффективно ищет в недавних данных последнюю серию из трех чередующихся противоположных фракталов. При этом приоритет отдается наиболее выраженным отклонениям – тем, которые сильнее всего отличаются от окружающих баров, – чтобы динамически уточнять экстремумы. Этот процесс формирует устойчивую к шуму основу для последующего анализа, благодаря чему выявленные зоны опираются на значимые рыночные свинги, а не на незначительные колебания.
// Retrieve the most recent sequence of three opposing fractals for pattern detection bool GetLast3AlternatingFractals( int &p0, double &pr0, bool &h0, int &p1, double &pr1, bool &h1, int &p2, double &pr2, bool &h2) { int n=0, idx[3]; double pr[3]; bool hi[3]; int maxBars = MathMin(InpMaxScanBars, BarsTotal() - 3); for(int i=3; i<maxBars; i++) { double price; bool isH; if(!GetFractalPoint(i, price, isH)) { // Additional check for prominent fractals if(i >= 4 && i+3 < BarsTotal()) { double hh = iHigh(_Symbol, _Period, i); double ll = iLow(_Symbol, _Period, i); if(hh >= iHigh(_Symbol, _Period, i-1) && hh >= iHigh(_Symbol, _Period, i+1) && hh >= iHigh(_Symbol, _Period, i-2) && hh >= iHigh(_Symbol, _Period, i+2)) { price = hh; isH = true; } else if(ll <= iLow(_Symbol, _Period, i-1) && ll <= iLow(_Symbol, _Period, i+1) && ll <= iLow(_Symbol, _Period, i-2) && ll <= iLow(_Symbol, _Period, i+2)) { price = ll; isH = false; } else continue; } else continue; } // Store the most recent opposing fractals if(n==0) { idx[0]=i; pr[0]=price; hi[0]=isH; n=1; } else if(hi[n-1]==isH) { // Update if current fractal is more extreme if(isH && price>pr[n-1]) { idx[n-1]=i; pr[n-1]=price; } if(!isH && price<pr[n-1]) { idx[n-1]=i; pr[n-1]=price; } } else if(n<3) { idx[n]=i; pr[n]=price; hi[n]=isH; n++; } if(n>=3) break; } if(n<3) return false; p0=idx[0]; pr0=pr[0]; h0=hi[0]; p1=idx[1]; pr1=pr[1]; h1=hi[1]; p2=idx[2]; pr2=pr[2]; h2=hi[2]; return true; }
Определение границ консолидации
После того как ключевые фракталы определены, функции CalcRangeHigh() и CalcRangeLow() анализируют бары между ними, чтобы определить реальные верхнюю и нижнюю границы потенциальной зоны консолидации. Эти границы критически важны для определения зоны, в которой может произойти пробой.
// Calculate the highest high between two bars double CalcRangeHigh(int leftBar, int rightBar) { int from = MathMin(leftBar, rightBar); int to = MathMax(leftBar, rightBar); int bars = to - from + 1; int idx = iHighest(_Symbol, _Period, MODE_HIGH, bars, from); return (idx >= 0) ? iHigh(_Symbol, _Period, idx) : iHigh(_Symbol, _Period, from); } // Calculate the lowest low between two bars double CalcRangeLow(int leftBar, int rightBar) { int from = MathMin(leftBar, rightBar); int to = MathMax(leftBar, rightBar); int bars = to - from + 1; int idx = iLowest(_Symbol, _Period, MODE_LOW, bars, from); return (idx >= 0) ? iLow(_Symbol, _Period, idx) : iLow(_Symbol, _Period, from); }
Однако исходные границы требуют проверки. Функция RangeQualifies() применяет строгие критерии: зона должна сохраняться в течение минимального времени, как по жесткому, так и по мягкому порогу, ее высота должна быть соразмерна ATR, а для подтверждения нужны недавние касания цены у границ. Отбраковываются зоны, которые слишком мелкие, слишком кратковременные или больше не подтверждаются ценой. Такая фильтрация помогает сосредоточиться на ситуациях с реальным потенциалом пробоя и снижает вероятность ложных срабатываний из-за незначительного рыночного шума или несущественных консолидаций.
// Check if the range qualifies based on duration, ATR, and proximity bool RangeQualifies(int p2, int p1, double hi, double lo, string &whyFail, bool &usedSoft) { whyFail=""; usedSoft=false; int barsSpan = MathAbs(p2 - p1); if(barsSpan < InpRangeMinBarsSoft) { whyFail="rangeBars"; return false; } double atr; if(!GetATR(atr)) { whyFail="atr"; return false; } double height = MathAbs(hi - lo); double atrCap = InpRangeATRMax; if(barsSpan < InpRangeMinBarsHard) { if(!InpEnableSoftRangeBars) { whyFail="rangeBars"; return false; } usedSoft=true; atrCap = InpRangeATRMaxSoft; } if(height > atr * atrCap) { whyFail= usedSoft ? "rangeATR_soft" : "rangeATR"; return false; } // Check proximity to recent high/low double zonePct = MathMax(0.08, MathMin(InpRangeSideZonePct, 0.70)); double zone = height * zonePct; bool nearHigh=false, nearLow=false; int look = MathMin(InpRangeTestLookback, BarsTotal() - 5); for(int i=1; i<=look; i++) { double h = iHigh(_Symbol, _Period, i); double l = iLow(_Symbol, _Period, i); if(h >= hi - zone) nearHigh=true; if(l <= lo + zone) nearLow=true; if(nearHigh || nearLow) break; } if(!nearHigh && !nearLow) { whyFail="sideZones"; return false; } return true; }
Выявление дисбаланса импульса – геометрическая проверка
Зоны, прошедшие первичную фильтрацию, переходят к геометрической проверке. Функция GeometryAsymmetryInsideRangeOK() выполняет детальный анализ последних отрезков движения внутри зоны. При этом вычисляются соотношения, такие как LengthRatio для доминирования по расстоянию, SlopeRatio для крутизны и TimeRatio для скорости движения. Эти соотношения помогают определить, было ли последнее движение резко ускоренным, а это ключевой признак накопления импульса.
// Validate the shape and acceleration of the move within the zone bool GeometryAsymmetryInsideRangeOK( int p0,double pr0,int p1,double pr1,int p2,double pr2, double rangeHigh,double rangeLow, double &lenRatio,double &slopeRatio,double &timeRatio,int &votes,int &dir, string &whyFail) { whyFail=""; votes=0; double lenPrev = MathAbs(pr1 - pr2); double lenLast = MathAbs(pr0 - pr1); dir = (pr0 > pr1 ? +1 : -1); double tol = (rangeHigh - rangeLow) * 0.10; if(pr0 > rangeHigh+tol || pr0 < rangeLow-tol || pr1 > rangeHigh+tol || pr1 < rangeLow-tol) { if(pr0 > rangeHigh+tol && pr1 > rangeHigh+tol) { whyFail="notInsideRange"; return false; } if(pr0 < rangeLow-tol && pr1 < rangeLow-tol) { whyFail="notInsideRange"; return false; } } datetime t0 = iTime(_Symbol, _Period, p0); datetime t1 = iTime(_Symbol, _Period, p1); datetime t2 = iTime(_Symbol, _Period, p2); long dtPrevL = (long)t1 - (long)t2; long dtLastL = (long)t0 - (long)t1; double dtPrev = MathAbs((double)dtPrevL); double dtLast = MathAbs((double)dtLastL); if(dtPrev <= 0 || dtLast <= 0) { whyFail="dt"; return false; } lenRatio = lenLast / MathMax(1e-10, lenPrev); slopeRatio = (lenLast / dtLast) / MathMax(1e-10, (lenPrev / dtPrev)); timeRatio = dtLast / MathMax(1e-10, dtPrev); // Voting on pattern strength if(lenRatio >= InpLenRatioMin) votes++; if(slopeRatio >= InpSlopeRatioMin) votes++; if(timeRatio <= InpTimeCompressionMax) votes++; if(votes < InpMinGeometryVotes) { if(lenRatio >= InpLenRatioMin * 1.2 || slopeRatio >= InpSlopeRatioMin * 1.2) votes = InpMinGeometryVotes; else { whyFail="votes"; return false; } } return true; }
Система голосования InpMinGeometryVotes требует выполнения нескольких критериев для подтверждения паттерна. Дополнительные защитные проверки, такие как близость конечной точки к границе и пропорциональное соотношение между отрезками, помогают исключать чрезмерно большие или оторванные от структуры движения, не отражающие реального накопления импульса. Такая тщательная проверка позволяет отличать значимый импульс от просто симметричных или нерешительных движений, которые часто приводят к ложным пробоям. Это заметно повышает надежность формируемых сигналов.
Мониторинг пробоев и генерация сигналов входа
// Check recent candles for breakouts and trigger signals void CheckAllBreakouts() { double buffer = InpBreakBufferPts * _Point; for(int i=0; i<ArraySize(g_lockedPatterns); i++) { if(!g_lockedPatterns[i].active) continue; for(int bar=1; bar<=InpBreakLookbackBars; bar++) { datetime barTime = iTime(_Symbol, _Period, bar); if(barTime <= g_lockedPatterns[i].startTime) continue; double close = iClose(_Symbol, _Period, bar); double high = iHigh(_Symbol, _Period, bar); double low = iLow(_Symbol, _Period, bar); if(g_lockedPatterns[i].dir > 0) { if(close > g_lockedPatterns[i].high + buffer || high > g_lockedPatterns[i].high + buffer) { double breakoutPrice = MathMax(g_lockedPatterns[i].high + buffer, MathMin(close, high)); string uid = "BUY_" + g_lockedPatterns[i].key + "_" + Ts(barTime); CreatePermanentArrow(uid, barTime, breakoutPrice, true); if(InpShowDebug) Print("Buy breakout at ", DoubleToString(breakoutPrice,_Digits)); RemoveLockedPattern(i); g_lastSignalBar = barTime; break; } } else if(g_lockedPatterns[i].dir < 0) { if(close < g_lockedPatterns[i].low - buffer || low < g_lockedPatterns[i].low - buffer) { double breakoutPrice = MathMin(g_lockedPatterns[i].low - buffer, MathMax(close, low)); string uid = "SELL_" + g_lockedPatterns[i].key + "_" + Ts(barTime); CreatePermanentArrow(uid, barTime, breakoutPrice, false); if(InpShowDebug) Print("Sell breakout at ", DoubleToString(breakoutPrice,_Digits)); RemoveLockedPattern(i); g_lastSignalBar = barTime; break; } } } } }
Когда паттерн демонстрирует выраженную асимметрию, система переходит к отслеживанию пробоя. Функция CheckAllBreakouts() проверяет последние свечи на предмет уверенных пробоев установленных границ диапазона и учитывает буфер входа (InpBreakBufferPts), чтобы не реагировать на небольшие всплески. Когда происходит подтвержденный пробой, CreatePermanentArrow() размещает на графике постоянные визуальные метки – стрелки, зоны и подписи, – обеспечивая наглядное подтверждение.
// Create an arrow marker on the chart for breakouts void CreatePermanentArrow(const string uid, const datetime t, const double price, const bool bullish) { if(!InpShowArrows) return; string name = PFX_AR + "PERM_" + uid + "_" + Ts(t); if(ObjectFind(0, name) >=0) return; // Already exists int anchor = bullish ? ANCHOR_BOTTOM : ANCHOR_TOP; double arrowPrice = bullish ? (price - InpArrowOffsetPoints * _Point) : (price + InpArrowOffsetPoints * _Point); if(!ObjectCreate(0, name, OBJ_ARROW, 0, t, arrowPrice)) { if(InpShowDebug) Print("Failed to create arrow: ", GetLastError()); return; } ObjectSetInteger(0, name, OBJPROP_ARROWCODE, bullish ? InpArrowUpCode : InpArrowDownCode); ObjectSetInteger(0, name, OBJPROP_COLOR, bullish ? InpArrowColorUp : InpArrowColorDown); ObjectSetInteger(0, name, OBJPROP_WIDTH, InpArrowSize); ObjectSetInteger(0, name, OBJPROP_ANCHOR, anchor); // Add label if enabled if(InpShowArrowLabels) { string lbl = name + "_LBL"; double lblPrice = arrowPrice + (InpArrowLabelOffset * _Point * (bullish ? 1 : -1)); if(ObjectCreate(0, lbl, OBJ_TEXT, 0, t, lblPrice)) { ObjectSetString(0, lbl, OBJPROP_TEXT, bullish ? "BUY" : "SELL"); ObjectSetInteger(0, lbl, OBJPROP_COLOR, bullish ? InpArrowColorUp : InpArrowColorDown); ObjectSetInteger(0, lbl, OBJPROP_FONTSIZE, InpArrowLabelFontSize); ObjectSetString(0, lbl, OBJPROP_FONT, InpArrowLabelFont); ObjectSetInteger(0, lbl, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER); } } }
Одновременно с этим PlayAlert() управляет многоканальными уведомлениями – звуками, всплывающими окнами, push-уведомлениями и электронными письмами, – чтобы информация о пробоях надежно и своевременно доходила до трейдера независимо от устройства и условий работы. Каждый сетап фиксируется на короткий период (InpMaxLockBars), чтобы исключить несколько сигналов по одному и тому же паттерну, а затем паттерн автоматически снимается с наблюдения после истечения срока или при пробое. Такой процесс поддерживает порядок на графике и удерживает фокус на текущих сигналах с высокой вероятностью.
Управление жизненным циклом паттерна и контроль шума
// Check if enough bars have passed since last signal to avoid overtrading bool CooldownOK() { if(g_lastSignalBar == 0) return true; int barsSince = iBarShift(_Symbol, _Period, g_lastSignalBar, true); return (barsSince >= InpMinBarsBetweenSignals); }
Чтобы дополнительно снизить число ложных срабатываний и избежать переторговки, в системе предусмотрены механизмы подавления шума. Функция CooldownOK() обеспечивает минимальное число баров между сигналами, снижая влияние рыночной турбулентности. Процедура UpdateLockedPatterns() обновляет таймеры активных паттернов и автоматически снимает с наблюдения те, что достигли предельного возраста или уже отработали.
// Update active pattern timers and expire patterns that have reached max lock bars void UpdateLockedPatterns() { datetime currentTime = iTime(_Symbol, _Period, 0); for(int i=0; i<ArraySize(g_lockedPatterns); i++) { if(!g_lockedPatterns[i].active) continue; g_lockedPatterns[i].lockBars++; // optionally, update visual rectangle for active patterns if(g_lockedPatterns[i].rectName != "" && InpShowLockedRangeRects) UpdateLockedRangeRectangle(g_lockedPatterns[i].rectName, currentTime, g_lockedPatterns[i].high, g_lockedPatterns[i].low); // Expire patterns that have reached max lock bars if(g_lockedPatterns[i].lockBars > InpMaxLockBars) { if(InpShowDebug) Print("Pattern expired after ", g_lockedPatterns[i].lockBars, " bars"); RemoveLockedPattern(i); } } }
Эти механизмы формируют дисциплинированную торговую среду, уменьшают число ложных срабатываний и обеспечивают генерацию сигналов только тогда, когда структура рынка указывает на реальную возможность. Такой дисциплинированный подход помогает не реагировать на незначительные рыночные колебания или рваный рынок и вместо этого сосредоточиваться на сетапах с высокой вероятностью.
Основной цикл выполнения – OnTick()
Весь анализ, принятие решений и генерация сигналов сосредоточены в функции OnTick(). Она выполняется только при закрытии каждого нового бара, что оптимизирует расход ресурсов и обеспечивает стабильность. Внутри OnTick() последовательно обновляются состояния существующих паттернов, выполняется поиск новых фракталов, оцениваются потенциальные зоны, проводится геометрическая проверка, отслеживаются пробои и обновляются визуальные наложения.
// Main routine called on each new tick; runs at bar close void OnTick() { // Only proceed at bar close datetime closed = iTime(_Symbol, _Period, 1); if(closed == 0 || closed == g_lastClosedBar) return; g_lastClosedBar = closed; // Update pattern timers and expire old patterns UpdateLockedPatterns(); // Check for breakout signals CheckAllBreakouts(); // Limit number of active patterns if(GetActivePatternCount() >= g_maxSimultaneousLocks) { if(InpShowDebug) Print("Max active patterns reached"); return; } // Enforce cooldown to prevent overtrading if(!CooldownOK()) { if(InpShowDebug) { int sinceBars = iBarShift(_Symbol, _Period, g_lastSignalBar, true); Print("Cooldown active: ", sinceBars, "/", InpMinBarsBetweenSignals, " bars since last signal"); } return; } // Proceed with fractal detection and pattern analysis // (Insert fractal detection, range evaluation, geometric validation, etc.) // ... }
Такой структурированный пайплайн обеспечивает надежную работу в реальном времени даже на волатильных и быстро движущихся рынках. Визуальные наложения – цветные точки для фракталов, трендовые линии для отрезков, зоны для консолидаций и стрелки для пробоев – динамически создаются или обновляются по текущим рыночным данным. Такая визуальная обратная связь дает наглядное интуитивное представление о структуре рынка и возможных торговых сигналах.
Управление ресурсами и стабильность системы
Эффективное управление ресурсами критически важно для долгосрочной стабильности системы. В процессе выполнения OnInit() хэндл индикатора ATR создается и затем кэшируется для повторного использования. В процессе выполнения OnDeinit() этот хэндл освобождается, чтобы избежать утечек памяти. Графические объекты, такие как трендовые линии, зоны и стрелки, получают системные имена с едиными префиксами и уникальными идентификаторами, что упрощает их обновление и удаление.
// On initialization, acquire indicator handles and prepare environment int OnInit() { g_atrHandle = iATR(_Symbol, _Period, InpATRPeriod); if(g_atrHandle == INVALID_HANDLE) { Print("Failed to create ATR handle. Error=", GetLastError()); return INIT_FAILED; } // Resize pattern lock array for simultaneous patterns ArrayResize(g_lockedPatterns, g_maxSimultaneousLocks); for(int i=0; i< g_maxSimultaneousLocks; i++) g_lockedPatterns[i].active = false; // Clean up previous graphical objects DeleteByPrefix(PFX_SW); DeleteByPrefix(PFX_DOT); DeleteByPrefix(PFX_LN); DeleteByPrefix(PFX_TX); DeleteByPrefix(PFX_TRI); ObjectDelete(0, OBJ_CAND); // Initialize variables g_lastClosedBar = 0; g_lastSignalBar = 0; g_arrowCounter = 0; // Print startup info Print("System initialized successfully"); return INIT_SUCCEEDED; }
Массивы для поддержки нескольких паттернов динамически меняют размер, что позволяет обрабатывать сложные сценарии с перекрывающимися сетапами или несколькими инструментами без потери производительности. Корректные процедуры очистки и дисциплинированная работа с памятью обеспечивают стабильность системы на длительных интервалах, на разных символах и в разных рыночных условиях.
// On deinitialization, release indicator handles and clean up objects void OnDeinit(const int reason) { if(g_atrHandle != INVALID_HANDLE) IndicatorRelease(g_atrHandle); // Remove graphical objects DeleteByPrefix(PFX_SW); DeleteByPrefix(PFX_DOT); DeleteByPrefix(PFX_LN); DeleteByPrefix(PFX_TX); DeleteByPrefix(PFX_TRI); ObjectDelete(0, OBJ_CAND); // Output stats Print("Deinitialization complete"); Print("Total patterns processed: ", g_totalPatterns); Print("Breakouts: ", g_totalBreakouts, " (Buy: ", g_buyBreakouts, ", Sell: ", g_sellBreakouts, ")"); Print("Patterns expired: ", g_patternsExpired); }
Заключительные замечания
Эта реализация демонстрирует профессиональный уровень инженерной проработки на языке MQL5. Сочетая выявление фракталов, строгую фильтрацию зон и детальную геометрическую проверку, система преобразует тонкие структурные дисбалансы в надежные сигналы, пригодные для практического применения. Визуальные наложения, алерты и управление жизненным циклом паттернов формируют целостную торговую среду, в которой функциональность сочетается с ясностью.
Модульная архитектура упрощает настройку: можно уточнять пороги, добавлять фильтры и улучшать визуальную подачу по мере необходимости. Такая гибкость позволяет системе адаптироваться к меняющимся рынкам и индивидуальным стилям торговли. Таким образом, стратегия Geometric Asymmetry Breakout представляет собой масштабируемую и устойчивую систему, которая помогает уверенно и точно работать на сложных, динамичных рынках.
Тестирование и результаты
Чтобы любой инструмент был действительно эффективным и стабильно давал положительные результаты, необходимо тщательно тестировать его в разных рыночных условиях и на разных таймфреймах. В этом разделе я привожу результаты проведенных тестов и показываю, в каких условиях инструмент работал наиболее эффективно. После обширного тестирования на нескольких валютных парах выявилась четкая закономерность в эффективности. Инструмент оказался наиболее эффективным на основных высоколиквидных парах, причем самые сильные и стабильные результаты были получены на EURUSD на таймфрейме H1.
Ниже показана диаграмма из Тестера стратегий с тестовым прогоном на EURUSD (H1), где инструмент продемонстрировал наиболее сильные и практически полезные результаты.
Это не означает, что инструмент работает только при этих конкретных условиях. Наблюдаемая эффективность во многом зависит от порогов, заданных входными параметрами, и фильтров сигналов, применявшихся во время тестирования. Разные инструменты обладают разными характеристиками – одни более волатильны, другие менее, а некоторые отличаются более глубокой ликвидностью. Поэтому калибровка параметров играла при тестировании ключевую роль. Параметры подстраивались под поведение каждой пары и каждого таймфрейма, а не применялись единообразно. Если входные параметры согласованы с волатильностью, ликвидностью и структурными особенностями рынка, инструмент показывает стабильную эффективность не только на EURUSD на H1, но и на других инструментах.
Также был проведен тест на AUDUSD, который тоже дал положительные и стабильные результаты. Этот тест выполнялся в визуальном режиме Тестера стратегий, что позволяло подробно наблюдать, как советник определяет диапазоны консолидации, формирует внутреннюю направленность и генерирует сигналы пробоя в реальном времени.

Как видно на визуализации, советник корректно определил диапазон GA, подтвердил внутреннюю геометрическую асимметрию и выдал корректный сигнал только после закрытия цены за пределами зафиксированной границы диапазона. Этот тест дополнительно подтверждает, что инструмент надежно работает не только на одном инструменте при условии, что входные параметры и фильтры корректно согласованы с волатильностью и структурой рынка.
Заключение
В этой статье рассматривалась система Geometric Asymmetry (GA) Breakout – структурированный подход на основе четких правил для выявления значимых переходов от диапазона к тренду. Сочетая выявление фрактальной структуры, подтверждение консолидации, анализ геометрического дисбаланса и строгое подтверждение пробоя, этот метод опирается прежде всего на рыночный контекст и подтверждение, а не на прогнозирование.
Тестирование на нескольких валютных парах и таймфреймах показало, что эффективность в значительной степени зависит от того, насколько точно входные параметры согласованы с волатильностью, ликвидностью и структурным поведением каждого рынка. Результаты, полученные на основных парах, таких как EURUSD (H1) и AUDUSD, показывают способность системы выявлять реальные расширения и отсекать сигналы, вызванные шумом или кратковременными ценовыми колебаниями. Сила подхода GA – в его дисциплине. Сигналы генерируются только после того, как сформирован корректный диапазон консолидации, внутренняя направленность объективно выявлена по асимметрии, а цена уверенно закрывается за рассчитанной границей. Такая последовательная фильтрация снижает число ложных пробоев и позволяет сигналам отражать реальную готовность рынка к направленному движению.
Geometric Asymmetry представляет собой систему поддержки принятия решений и генерации сигналов, а не полностью автоматизированную торговую систему. Ее модульная структура позволяет уточнять пороги, настраивать фильтры и адаптировать параметры к разным инструментам без изменения базовой логики. Такая гибкость делает систему GA практичным и устойчивым инструментом для трейдеров, которым нужен структурированный и прозрачный метод анализа пробоев в меняющихся рыночных условиях.
Стратегию Geometric Asymmetry, как и любой аналитический инструмент, не следует применять в реальной торговле без тщательного тестирования. Рекомендуется проводить развернутое форвард-тестирование на демо-счетах, подстраивать параметры под выбранные инструменты и таймфреймы и постоянно соблюдать адекватное управление рисками. Прошлые результаты, включая результаты тестирования на исторических данных, не гарантируют результатов в будущем.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/21197
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Разработка торговой стратегии: Метод Triple Sine для возврата к среднему
Переосмысливаем классические стратегии (Часть 19): Подробный разбор стратегий на пересечении скользящих средних
Разработка инструментария для анализа Price Action (Часть 60): Объективное построение трендовых линий по свингам для структурного анализа
Разработка инструментария для анализа Price Action (Часть 58): Модуль анализа сжатия диапазона и классификации зрелости
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования