Разработка инструментария для анализа Price Action (Часть 63): Автоматизация обнаружения восходящих и нисходящих клиньев на MQL5
Содержание
- Введение
- Структурные характеристики восходящих и нисходящих клиньев
- Реализация на MQL5
- Проверка и анализ поведения
- Заключение
Введение
Открыв график, в первую очередь обычно ищут структуру. Знакомые паттерны помогают выстроить ожидания, управлять риском и готовиться к входам с высокой вероятностью. Среди самых популярных ценовых структур – восходящие и нисходящие клинья, то есть формации сжатия, которые часто предшествуют расширению.
Однако сложность не в самом факте существования клиньев. Проблема в том, чтобы последовательно и объективно выявлять их. Многим трейдерам, особенно тем, кто еще только развивает навык чтения графика, трудно распознать корректную структуру клина. Даже опытные аналитики могут тратить много времени на построение, корректировку и проверку трендовых линий и все равно пропускать корректную формацию. Субъективное распознавание паттернов влечет задержки, непоследовательность и субъективную предвзятость.
Для решения этой задачи в статье представлен индикатор на языке MQL5, предназначенный для автоматического обнаружения и построения формаций восходящего и нисходящего клина прямо на графике. Система определяет опорные точки, проверяет сходимость границ по их наклонам, предотвращает структурные перекрытия и отслеживает условия пробоя или аннулирования паттерна, переводя геометрическую теорию в структурированную алгоритмическую логику.
В этой статье разберем все по шагам:
- Сначала рассмотрим структурные характеристики восходящих и нисходящих клиньев.
- Затем переведем эту теорию в практическую реализацию на языке MQL5.
- Далее проверим поведение системы в тестах.
- В завершение подведем итоги и отметим практические нюансы.
Начнем с того, как формируются клинья и почему они важны для анализа Price Action.
Структурные характеристики восходящих и нисходящих клиньев
Клин – это ценовая формация, образованная двумя сходящимися трендовыми линиями, которые удерживают движение рынка в постепенно сужающемся диапазоне. В отличие от горизонтальной консолидации, клин отражает направленное сжатие: цена продолжает формировать более высокие максимумы и более высокие минимумы (восходящий клин) или более низкие максимумы и более низкие минимумы (нисходящий клин), но размах движения между двумя границами со временем сокращается. Определяющий признак здесь – не просто наличие двух линий. Это измеримая сходимость структуры. Эта сходимость указывает на ослабление импульса и рост давления, которые часто предшествуют решающему пробою или структурному аннулированию.
Чтобы понять, как эту формацию можно перевести в алгоритмическую логику, разберем ее структурные компоненты по шагам.
1. Сжатие цены и сходящиеся трендовые линии
Клинья формируются в фазах контролируемого сжатия. Каждый последующий свинг остается в пределах двух линий, которые постепенно сходятся.
- Верхняя граница отражает давление сопротивления.
- Нижняя граница отражает давление поддержки.
По мере того как цена колеблется между этими границами, вертикальное расстояние между ними уменьшается. Это сжатие отражает снижение волатильности и уплотнение рыночной структуры. Сужение диапазона не случайно: оно сопровождает направленное движение, которое постепенно теряет способность к дальнейшему расширению. Именно сходимость отличает клин от параллельного канала. В канале границы остаются равноудаленными. В клине – нет.

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

В нисходящем клине:
- обе трендовые линии наклонены вниз;
- верхняя граница снижается быстрее, чем нижняя;
- сходимость происходит сверху.

Классификация определяется сравнением относительных наклонов двух границ. Сходимость становится математически очевидной, когда разность наклонов приводит к пересечению проецируемых линий в некоторой точке в будущем, которую обычно называют вершиной (апекс). Именно это соотношение наклонов превращает визуальный паттерн в измеримую геометрию.
4. Пробой или аннулирование паттерна
Как только сжатие достигает критической стадии, цена выходит из формации.
- Восходящий клин обычно завершается пробоем вниз.

- Нисходящий клин обычно завершается пробоем вверх.

Однако рынки не обязаны следовать ожиданиям. Когда цена совершает пробой в противоположную сторону, клин считается структурно недействительным (аннулируется). Этот результат не является шумом: он отражает сдвиг в динамике потока ордеров. Поэтому наблюдение за поведением после формирования паттерна принципиально важно. На момент обнаружения клин еще не завершен. Его корректность определяется тем, как цена реагирует на его границы.

Реализация на MQL5
Теперь, когда мы разобрались с теорией структуры клиньев, следующий шаг – перевести эту логику в надежную реализацию на языке MQL5, пригодную для рабочего применения. Цель здесь не в том, чтобы просто рисовать сходящиеся трендовые линии, а в том, чтобы построить дисциплинированный механизм обнаружения без перерисовки, который выявляет значимые точки свинга, математически проверяет сходимость границ, предотвращает структурные конфликты за счет продуманной проверки перекрытий и непрерывно отслеживает условия пробоя и аннулирования паттерна по мере изменения цены в реальном времени. Реализация организована как несколько взаимосвязанных слоев: входные параметры конфигурации, обнаружение опорных точек, распознавание клина, инкапсулированное управление паттернами, визуализация и событийно-ориентированный поток исполнения.
Система реализована так, чтобы ключевые опорные точки, границы клина и пробои наглядно отображались на графике и давали понятные ориентиры для торговых решений, а базовая модульная структура и отсутствие перерисовки обеспечивали надежность, эффективность и удобство сопровождения кода.
Входные параметры и настройка
Реализация начинается с четко организованного блока входных параметров, разделенного на логические группы, которые управляют как чувствительностью обнаружения, так и визуальным представлением. Эти параметры определяют, насколько строго алгоритм интерпретирует структуру рынка и как полученные формации отображаются на графике.
//+------------------------------------------------------------------+ //| Input parameters for Wedge Pattern indicator | //+------------------------------------------------------------------+ input group "Pattern Detection Rules" input int PivotLeft = 5; // Pivot Left input int PivotRight = 5; // Pivot Right input int MinTouches = 3; // Min. Touches per Line input group "Visual Design" input color RisingColor = clrRed; // Rising Wedge (Bearish) input color FallingColor = clrLime; // Falling Wedge (Bullish) input int MaxWedges = 20; // Max wedges displayed (oldest removed) input bool ExtendLines = true; // Extend wedge lines input int LineExtensionBars = 30; // Bars to extend (if ExtendLines=true) input ENUM_LINE_STYLE LineStyle = STYLE_SOLID; // Line style for wedge lines input int LineWidth = 1; // Line width (1-5) input bool ShowLabels = true; // Show pattern labels input int LabelFontSize = 8; // Label font size input bool LabelWithBackground = false; // Add background rectangle to labels input color LabelBgColor = clrBlack; // Label background color input double LabelBgOpacity = 0.7; // Background opacity (0.0-1.0)
Первая группа с именем Pattern Detection Rules содержит параметры PivotLeft, PivotRight и MinTouches. Параметры PivotLeft и PivotRight определяют, сколько баров с каждой стороны от рассматриваемой свечи нужно проверить, чтобы понять, является ли она максимумом либо минимумом свинга. Увеличение этих значений делает опорные точки более надежными и консервативными, так как требует более выраженных свингов, а уменьшение повышает отзывчивость, но увеличивает риск шума. Параметр MinTouches обеспечивает подтверждение структуры: перед признанием клина корректным требуется обнаружить минимальное число опорных точек на обеих границах, что исключает подтверждение слабых или преждевременных формаций.
Вторая группа с именем Visual Design управляет отображением на графике и поведением объектов. RisingColor и FallingColor позволяют отличать медвежьи восходящие клинья от бычьих нисходящих. MaxWedges ограничивает число видимых исторических формаций, автоматически удаляя самые старые структуры, чтобы не загромождать график. ExtendLines и LineExtensionBars определяют, будут ли линии границ продлеваться в будущее и насколько далеко. Дополнительные параметры оформления улучшают читаемость и внешний вид графика: ширина и стиль линий, видимость меток, размер шрифта, а также необязательные фоновые прямоугольники с регулируемой непрозрачностью. Эти параметры конфигурации позволяют полностью настраивать систему без изменения базовой логики обнаружения.
Обнаружение опорных точек и структурное подтверждение
После задания конфигурации процесс обнаружения начинается с выделения структурно значимых точек свинга. Построение клина опирается на чистые данные об опорных точках, а не на исходные ценовые колебания. Для этого в реализации вводится отдельный класс Pivot, который инкапсулирует индекс бара, временную метку и цену каждой опорной точки.
//+------------------------------------------------------------------+ //| Pivot point class | //+------------------------------------------------------------------+ class Pivot : public CObject { public: int index; datetime time; double price; Pivot(int idx,datetime t,double p) : index(idx),time(t),price(p) {} };
Этот объектно-ориентированный подход упрощает хранение данных, управление памятью и последующее обращение к структурным элементам. Вспомогательные функции IsPivotHigh() и IsPivotLow() оценивают каждый бар-кандидат, сравнивая его максимум или минимум с соседними барами в диапазоне, заданном PivotLeft и PivotRight. Поскольку опорные точки подтверждаются только после формирования достаточного числа окружающих баров, индикатор гарантирует, что границы клина будут задаваться только значимыми максимумами и минимумами свингов. Этот подход выделяет ценовые зоны, где поддержка и сопротивление остаются значимыми, обеспечивает более надежные сигналы обнаружения и предотвращает нестабильность результатов на истории.
//+------------------------------------------------------------------+ //| Check if bar at idx is a pivot high | //+------------------------------------------------------------------+ bool IsPivotHigh(int idx,const double &high[],int left,int right) { if(idx-left<0) return(false); double val=high[idx]; for(int i=idx-left; i<=idx+right; i++) { if(i==idx) continue; if(i>=ArraySize(high)) return(false); if(high[i]>=val) return(false); } return(true); } //+------------------------------------------------------------------+ //| Check if bar at idx is a pivot low | //+------------------------------------------------------------------+ bool IsPivotLow(int idx,const double &low[],int left,int right) { if(idx-left<0) return(false); double val=low[idx]; for(int i=idx-left; i<=idx+right; i++) { if(i==idx) continue; if(i>=ArraySize(low)) return(false); if(low[i]<=val) return(false); } return(true); }
Опорная точка максимума подтверждается только тогда, когда максимум бара превышает все соседние максимумы в своем окне проверки, тогда как опорная точка минимума должна быть ниже всех соседних минимумов. Важно, что опорные точки не подтверждаются сразу. Алгоритм откладывает проверку индекса-кандидата до тех пор, пока не сформируется требуемое число баров справа. Этот механизм поэтапного подтверждения гарантирует, что опорные точки не перерисовываются, поддерживает надежность структуры и не допускает исторической нестабильности в обнаруженных паттернах. Как при начальном сканировании истории, так и при последующих обновлениях внутри OnCalculate() подтвержденные опорные точки сохраняются в динамических контейнерах CArrayObj с автоматическим управлением памятью. Этот этап фильтрации преобразует исходные ценовые данные в стабильное представление рыночной структуры, формируя надежные опорные точки для построения границ.
Распознавание паттерна клина и геометрическая валидация
После подтверждения достаточного числа опорных точек следующий шаг состоит в том, чтобы определить, образует ли их конфигурация сходящуюся структуру, характерную для клина. Обнаружение запускается сразу при добавлении новой опорной точки функцией TryDetectWedge(). Наклон и сходимость границ определяют, является ли структура восходящим или нисходящим клином. Проецируя теоретическую вершину и отбраковывая перекрывающиеся формации либо те, в которых пересечение уже сформировалось, система показывает на графике только чистые, пригодные для интерпретации паттерны и при этом сохраняет точную геометрическую валидацию в коде.
//+------------------------------------------------------------------+ //| Try to detect a new wedge pattern from recent pivots | //+------------------------------------------------------------------+ void TryDetectWedge(int currentBar,const datetime &time[],const double &close[]) { int nHighs=pivotHighs.Total(); int nLows=pivotLows.Total(); if(nHighs<MinTouches || nLows<MinTouches) return; Pivot *p1h=dynamic_cast<Pivot*>(pivotHighs.At(nHighs-MinTouches)); Pivot *pNh=dynamic_cast<Pivot*>(pivotHighs.At(nHighs-1)); Pivot *p1l=dynamic_cast<Pivot*>(pivotLows.At(nLows-MinTouches)); Pivot *pNl=dynamic_cast<Pivot*>(pivotLows.At(nLows-1)); if(!p1h || !pNh || !p1l || !pNl) return; double upperSlope=(pNh.price-p1h.price)/(pNh.index-p1h.index+1e-10); double lowerSlope=(pNl.price-p1l.price)/(pNl.index-p1l.index+1e-10); int wedgeType=0; if(upperSlope>0 && lowerSlope>0 && lowerSlope>upperSlope) wedgeType=1; if(upperSlope<0 && lowerSlope<0 && upperSlope<lowerSlope) wedgeType=2; if(wedgeType==0) return; double apexX=(p1l.price-p1h.price+upperSlope*p1h.index-lowerSlope*p1l.index)/(upperSlope-lowerSlope+1e-10); if((int)MathRound(apexX)<=currentBar) return; bool isRising=(wedgeType==1); Wedge *w=new Wedge(isRising,p1h.index,p1h.time,p1h.price,pNh.index,pNh.time,pNh.price, p1l.index,p1l.time,p1l.price,pNl.index,pNl.time,pNl.price, upperSlope,lowerSlope,currentBar); if(OverlapsExistingWedge(w)) { delete w; return; } w.Draw(); wedges.Add(w); PruneOldWedges(); }
Эта базовая логика получает самые ранние и самые поздние опорные точки в пределах требуемого диапазона касаний. Эти точки задают потенциальные верхнюю и нижнюю границы клина. Наклоны этих границ рассчитываются напрямую по соответствующим парам опорных точек, что дает численную оценку угла и направления каждой трендовой линии. Этот шаг гарантирует, что алгоритм будет оценивать сходимость математически, а не опираться на приблизительную визуальную оценку. Классификация строго определяется наклонами: восходящий клин выявляется, когда обе границы имеют положительный наклон, а нижняя граница поднимается круче верхней; нисходящий клин – когда обе границы имеют отрицательный наклон, а верхняя снижается круче нижней.
Геометрическая проверка также проецирует теоретическую вершину (точку пересечения двух трендовых линий) и принимает формацию только в том случае, если эта вершина находится впереди текущего бара. Параллельные линии и структуры, в которых пересечение уже произошло, автоматически отбраковываются. Перед тем как принять новый клин, TryDetectWedge() вызывает OverlapsExistingWedge(), а та, в свою очередь, использует метод OverlapsWith() для точной побарной проверки перекрытия с каждым уже активным клином. Такая проверка перед созданием нового объекта клина поддерживает структурную согласованность на графике и не допускает появления нескольких конфликтующих паттернов.
Структура клина и механизм выявления
После того как формация проходит все геометрические проверки и проверки на перекрытие в TryDetectWedge(), система создает полноценный объект Wedge. Класс Wedge содержит всю необходимую информацию: начальные и конечные опорные точки для обеих границ, заранее вычисленные наклоны, тип клина (восходящий или нисходящий), бар формирования и флаги состояния во время выполнения. Уникальные имена объектов формируются по индексам опорных точек и времени формирования, что гарантирует уникальный идентификатор для каждого объекта клина и предотвращает конфликты имен на графике даже при быстром появлении нескольких формаций. Новые объекты клина добавляются в управляемый контейнер CArrayObj для контроля их жизненного цикла.
//+------------------------------------------------------------------+ //| Main Wedge pattern class | //+------------------------------------------------------------------+ class Wedge : public CObject { public: bool isRising; int upperStartIdx,upperEndIdx; double upperStartPrice,upperEndPrice; int lowerStartIdx,lowerEndIdx; double lowerStartPrice,lowerEndPrice; double upperSlope,lowerSlope; int formationBar; bool isBroken,isFailed; string upperLineName,lowerLineName; string labelName,labelBgName; double UpperPriceAt(int barIdx) const; double LowerPriceAt(int barIdx) const; void Draw(void); void Update(int currentBar,datetime currentTime,double currentClose); void Delete(void); };
Это гарантирует, что каждая формация отслеживается, может отображаться на графике и обновляется по мере развития ценового движения, поддерживая связь в реальном времени между логикой выявления и визуализацией.
Визуализация, идентификация объектов и динамический мониторинг состояния
После проверки и создания клина система переходит к его визуализации и дальнейшему мониторингу. Каждый объект Wedge содержит не только геометрические данные, но и визуальные идентификаторы, а также текущее состояние. Метод Draw() отвечает за отрисовку каждого клина на графике, создавая линии верхней и нижней границ, оформленные с заданным цветом, толщиной, стилем и при необходимости продлеваемые в будущее. Верхняя и нижняя границы оформляются и при необходимости продлеваются, чтобы структура клина легко считывалась визуально, а код при этом динамически управлял созданием и оформлением объектов.
//+------------------------------------------------------------------+ //| Draw wedge trendlines and optional label | //+------------------------------------------------------------------+ void Wedge::Draw(void) { color clr=isRising?RisingColor:FallingColor; //--- Upper trend line if(ExtendLines) { int upperExtIdx=upperEndIdx+LineExtensionBars; datetime upperExtTime=upperEndTime+PeriodSeconds(PERIOD_CURRENT)*LineExtensionBars; double upperExtPrice=UpperPriceAt(upperExtIdx); ObjectCreate(0,upperLineName,OBJ_TREND,0,upperStartTime,upperStartPrice,upperExtTime,upperExtPrice); } else ObjectCreate(0,upperLineName,OBJ_TREND,0,upperStartTime,upperStartPrice,upperEndTime,upperEndPrice); ObjectSetInteger(0,upperLineName,OBJPROP_COLOR,clr); ObjectSetInteger(0,upperLineName,OBJPROP_WIDTH,LineWidth); ObjectSetInteger(0,upperLineName,OBJPROP_STYLE,LineStyle); ObjectSetInteger(0,upperLineName,OBJPROP_RAY_RIGHT,false); //--- Lower trend line (identical logic) + label with formation date and optional background rectangle }
Метки формации отображают тип клина и дату; при необходимости можно добавить полупрозрачный фоновый прямоугольник для лучшей читаемости на перегруженных графиках. Динамический мониторинг состояния выполняет метод Update(), который на каждом новом баре оценивает взаимодействие с границами с помощью вспомогательных функций проекции UpperPriceAt() и LowerPriceAt(). Для выявления пробоя используется небольшой буфер волатильности, который отсекает шум и спред. Пробои и аннулирования паттерна отмечаются только после уверенного закрытия за пределами границ, поэтому сигналы на графике остаются осмысленными, а механизм обновления при этом обрабатывает только активные клинья.
//+------------------------------------------------------------------+ //| Update wedge status - check for breakout or failure | //+------------------------------------------------------------------+ void Wedge::Update(int currentBar,datetime currentTime,double currentClose) { if(isBroken || isFailed) return; double upperNow=UpperPriceAt(currentBar); double lowerNow=LowerPriceAt(currentBar); bool upperBreak=currentClose>upperNow+Point()*3; bool lowerBreak=currentClose<lowerNow-Point()*3; if((isRising && lowerBreak) || (!isRising && upperBreak)) { isBroken=true; //--- Update label to BREAKOUT } else if((isRising && upperBreak) || (!isRising && lowerBreak) || upperNow<=lowerNow) { isFailed=true; //--- Update label to FAILED } }
Вместе механизмы Draw(), Update() и PruneOldWedges() образуют надежный слой визуализации и мониторинга, который связывает структурное выявление с наглядной интерпретацией графика в реальном времени. Когда клин больше не нужен, метод Delete() аккуратно удаляет все связанные с ним графические объекты.
//+------------------------------------------------------------------+ //| Remove oldest wedges when limit is exceeded | //+------------------------------------------------------------------+ void PruneOldWedges(void) { while(wedges.Total()>MaxWedges) { Wedge *oldest=dynamic_cast<Wedge*>(wedges.At(0)); if(oldest) oldest.Delete(); wedges.Delete(0); } }
Событийно-ориентированный поток исполнения
Система выявления клиньев работает полностью в событийно-ориентированной модели MQL5, используя функции жизненного цикла платформы для повышения эффективности и надежности. Инициализация выполняется в функции OnInit(), где создаются контейнеры CArrayObj для опорных точек и клиньев с включенным автоматическим управлением памятью. Такая настройка обеспечивает безопасное создание и удаление объектов без утечек памяти. При удалении индикатора с графика вызывается функция OnDeinit(), которая удаляет все связанные с клиньями графические объекты и освобождает выделенную память, оставляя график в чистом состоянии.
Основная обработка выполняется в OnCalculate(). Во время первого цикла выполняется полный исторический проход по ценовому ряду: с помощью IsPivotHigh() и IsPivotLow() выявляются исходные опорные точки, а через TryDetectWedge() – все подходящие клинья. Инкрементальная обработка гарантирует, что при появлении новых баров сразу будут запускаться обнаружение новых формаций и обновление их статуса, при этом сохраняя производительность и одновременно давая надежную картину развития клиньев на графике.
//+------------------------------------------------------------------+ //| Main indicator calculation function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[]) { ArraySetAsSeries(time,false); ArraySetAsSeries(high,false); ArraySetAsSeries(low,false); ArraySetAsSeries(close,false); if(prev_calculated==0) { ObjectsDeleteAll(0,"WEDGE_"); pivotHighs.Clear(); pivotLows.Clear(); wedges.Clear(); int startBar=PivotRight; int endBar=rates_total-PivotRight-1; for(int i=startBar; i<=endBar; i++) { bool newPivot=false; if(IsPivotHigh(i,high,PivotLeft,PivotRight)) { pivotHighs.Add(new Pivot(i,time[i],high[i])); newPivot=true; } if(IsPivotLow(i,low,PivotLeft,PivotRight)) { pivotLows.Add(new Pivot(i,time[i],low[i])); newPivot=true; } if(newPivot) TryDetectWedge(i,time,close); } } int start=(prev_calculated>0)?prev_calculated-1:0; for(int i=start; i<rates_total; i++) { int possibleIdx=i-PivotRight; if(possibleIdx<0) continue; bool newPivot=false; if(IsPivotHigh(possibleIdx,high,PivotLeft,PivotRight)) { pivotHighs.Add(new Pivot(possibleIdx,time[possibleIdx],high[possibleIdx])); newPivot=true; } if(IsPivotLow(possibleIdx,low,PivotLeft,PivotRight)) { pivotLows.Add(new Pivot(possibleIdx,time[possibleIdx],low[possibleIdx])); newPivot=true; } if(newPivot) TryDetectWedge(possibleIdx,time,close); } if(rates_total>0) { int currentBar=rates_total-1; for(int j=0; j<wedges.Total(); j++) { Wedge *w=dynamic_cast<Wedge*>(wedges.At(j)); if(w) w.Update(currentBar,time[currentBar],close[currentBar]); } } PruneOldWedges(); return(rates_total); }
При последующих обновлениях система анализирует только недавно закрытые бары, что заметно повышает вычислительную эффективность. Новые подтвержденные опорные точки сразу запускают логику выявления клиньев. Одновременно все существующие клинья обновляются по последней цене закрытия через свои методы Update(), что позволяет в реальном времени оценивать условия пробоя или утраты корректности. Инкрементальный подход избавляет от лишних перерасчетов и при этом обеспечивает своевременную визуальную обратную связь по развивающимся паттернам. После каждого обновления вызывается PruneOldWedges(), что поддерживает оптимальную производительность и визуальную чистоту графика.
Итоги
Эта реализация на языке MQL5 превращает теоретическую структуру клина в дисциплинированный механизм выявления без перерисовки, построенный на математически подтвержденной сходимости. Система изолирует значимые опорные точки с помощью IsPivotHigh() и IsPivotLow(), вычисляет наклоны границ внутри TryDetectWedge(), проецирует точку вершины, предотвращает конфликты геометрического перекрытия через OverlapsWith() и динамически управляет статусом направленного пробоя через Update(), тем самым сохраняя согласованность структуры в реальных рыночных условиях. Объектно-ориентированная архитектура с Draw(), PruneOldWedges(), контролируемым жизненным циклом в OnInit()/OnDeinit() и настраиваемыми параметрами делает индикатор одновременно аналитически надежным и удобным для расширения в составе более широких торговых систем.
Проверка и анализ поведения
В этом разделе представлен процесс тестирования и проверки, используемый для оценки реальной эффективности и надежности индикатора клиньев. Именно здесь мы тонко настраиваем входные параметры под разные торговые условия, таймфреймы и рыночные режимы.
Индикатор был тщательно проверен на этапе разработки и оптимизации в начале 2026 года. Тестирование сочетало анализ выбранных исторических периодов с обширным форвард-тестированием на графиках в реальном времени. Для оценки поведения как во время волатильных фаз рынка, так и в трендовых условиях использовались основные инструменты, включая EURUSD, GBPUSD, USDJPY, AUDUSD и золото (XAUUSD), на таймфреймах от M15 до H4.
Следующая конфигурация использовалась как базовая:
//+------------------------------------------------------------------+ //| Default parameters used during validation | //+------------------------------------------------------------------+ input group "Pattern Detection Rules" input int PivotLeft = 5; // Pivot Left input int PivotRight = 5; // Pivot Right input int MinTouches = 3; // Min. Touches per Line input group "Visual Design" input color RisingColor = clrRed; // Rising Wedge (Bearish) input color FallingColor = clrLime; // Falling Wedge (Bullish) input int MaxWedges = 20; // Max wedges displayed (oldest removed) input bool ExtendLines = true; // Extend wedge lines
Примеры графиков в реальном времени наглядно показывают поведение индикатора:
- надежное выявление и классификация – система последовательно выявляет корректные восходящие и нисходящие клинья и правильно различает бычьи и медвежьи структуры на основе сравнения наклонов границ;
- своевременная фиксация пробоя – метод Update() с учетом направления точно помечает пробои и аннулирования паттерна четкими метками BREAKOUT и FAILED, помогая трейдеру быстро реагировать;
- визуальная чистота графика – логика предотвращения перекрытий (OverlapsWith() и OverlapsExistingWedge()) поддерживает визуальную чистоту графика даже при появлении нескольких потенциальных паттернов.
На изображении ниже показан типичный пример на графике EURUSD M30 в реальном времени, где видно несколько выявленных клиньев и последующие результаты пробоев.

Анимация ниже показывает работу механизма выявления клиньев в реальном времени на EURUSD M30. В этом примере акцент сделан на наблюдаемом поведении, а не на внутренней механике.
Сразу видны несколько ключевых особенностей:
- клинья появляются только после структурной зрелости;
- после подтверждения выявленные паттерны остаются стабильными;
- результаты пробоя отмечаются сразу в момент разрешения структуры.
На протяжении всей последовательности несколько клиньев формируются и разрешаются независимо друг от друга. Одни завершаются направленным расширением, тогда как другие теряют актуальность еще до развития движения. Каждый исход четко помечается в момент структурного разрешения, что позволяет сразу интерпретировать его без повторного анализа вручную. В записи также демонстрируется контроль жизненного цикла паттернов. По мере перехода цены в новые структурные фазы более ранние клинья корректно завершаются, не оставляя лишних артефактов и сохраняя визуальную чистоту графика во время продолжительной волатильности. Что важно, пример показывает, что система не предугадывает пробои – она реагирует только после того, как граничные условия действительно выполнены. Это гарантирует, что визуальные сигналы соответствуют реальным структурным событиям, а не проецируемым допущениям.
Таким образом, анимация служит практическим подтверждением того, что механизм в реальных условиях работает детерминированно, поддерживая стабильность, визуальную чистоту и отзывчивость по мере развития цены.

Демонстрация в реальном времени дополнительно подтверждает, что реализация не ограничивается теорией – она стабильно работает в динамических условиях, сохраняя структурную согласованность и давая практически значимую обратную связь по мере развития цены.
Заключение
Мы разработали и реализовали на языке MQL5 структурно дисциплинированный механизм выявления клиньев без перерисовки, который выходит далеко за рамки простой визуальной отрисовки паттернов. Система выявляет подтвержденные опорные структуры, математически проверяет сходимость границ, предотвращает структурные перекрытия с помощью продуманной фильтрации и отслеживает условия пробоя и аннулирования паттерна в рамках чистой объектно-ориентированной модели жизненного цикла.
Благодаря продуманным архитектурным решениям – включая инкапсулированные классы Pivot и Wedge, динамическое управление CArrayObj и строгие правила подтверждения – индикатор сохраняет детерминированное поведение в реальных рыночных условиях. Тестирование на разных инструментах и таймфреймах показало стабильное выявление, своевременное структурное разрешение и устойчивую визуальную чистоту графика без искажений, вызванных проекциями. Эту реализацию лучше использовать не как автономный механизм принятия решений, а как компонент структурного анализа в составе более широкой торговой системы. Трейдерам стоит проверить ее поведение в собственных рыночных условиях и использовать ее вместе с существующими стратегиями, моделями риска и инструментами подтверждения, чтобы усилить анализ Price Action с учетом рыночного контекста.
Так клиновидные формации превращаются из субъективных визуальных паттернов в объективно определенные структуры, учитывающие состояние паттерна, которые могут дополнять дисциплинированные торговые методологии.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/21518
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.
Почему MetaTrader 5 подходит для торговли с ИИ: MQL5 + Python + ONNX + AI Assistant как экосистема алготрейдинга
Моделирование рынка: Position View (I)
Торговые инструменты MQL5 (Часть 28): Полигональная заливка кривой-бабочки в MQL5
Нейросети в трейдинге: От рыночного шума к устойчивому торговому плану (Основные компоненты)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования