English Deutsch 日本語
preview
Изучение Стандартной библиотеки MQL5 (Часть 5): Мультисигнальный советник

Изучение Стандартной библиотеки MQL5 (Часть 5): Мультисигнальный советник

MetaTrader 5Примеры |
45 3
Clemence Benjamin
Clemence Benjamin

Содержание



Введение

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

Возникает вопрос: если мастер настолько мощный, почему разработка советников по-прежнему остается сложной задачей? Ответ кроется в динамике рынка. Хотя мастер MQL5 генерирует профессиональную и согласованную структуру советника, основной проблемой остается сама торговая логика. Рыночные условия динамичны и разнообразны, а это означает, что одного набора статических правил часто недостаточно для долгосрочного выживания.

Для создания надежных советников мы должны сосредоточиться на сигналах. Разрабатывая разнообразную библиотеку сигналов и учась модифицировать существующие, мы можем создавать системы, которые адаптируются. Такой подход позволяет специализироваться; разработчик может сосредоточиться на совершенствовании одного модуля сигналов, внося свой вклад в более крупный, коллективный инструментарий.

Сегодня мы рассмотрим ограничение, связанное с использованием в одном советнике лишь небольшого числа сигналов. Мы создаем советника, который может содержать и управлять несколькими модулями торговых сигналов. Преимущество заключается в устойчивости: в условиях меняющегося рынка, если один сигнал перестанет работать, другие смогут продолжать генерировать торговые возможности. Такой мультистратегический подход позволяет советнику выживать там, где другие могут не справиться.

В рамках этого проекта я создам новый модуль сигналов на основе анализа Фибоначчи и объединю его со встроенными сигналами из библиотеки MQL5.

Также важно понимать, что в мультисигнальной системе не все сигналы используются в качестве основных триггеров для входа. Некоторые действуют как фильтры, уточняя и улучшая сделки, предлагаемые основными сигналами, тем самым создавая более совершенные стратегии.

Ниже я подробно объясню основные концепции этой разработки. После этого мы перейдем к этапу реализации, где основное внимание будет уделено коду, чтобы обеспечить функциональный и эффективный мультисигнальный советник.


Основные концепции разработки мультисигнальных советников

Для создания советника, способного по-настоящему адаптироваться к рынку, необходима смена мышления. Вместо одной жесткой стратегии мы создаем гибкую систему — "команду" торговых стратегий, работающих вместе. Стандартная библиотека MQL5 предоставляет идеальную основу для эффективной реализации этого процесса. Давайте разберем основные идеи, которые делают это таким мощным инструментом.

Модульное мышление

Основой этого подхода является модульность. Представьте себе каждую торговую стратегию — будь то пересечение скользящих средних, сигнал RSI или наш собственный паттерн Фибоначчи — как самодостаточный модуль. Каждый модуль является экспертом в своей области и содержит всю необходимую логику для принятия решений. Преимущество стандартной библиотеки MQL5 заключается в том, что она позволяет нам подключать эти модули к центральному советнику, который выступает в роли координатора стратегий. Это означает, что мы можем разрабатывать, тестировать и улучшать стратегии изолированно, а затем беспрепятственно добавлять их в нашу торговую систему, не переписывая ее ядро.

Как принимаются решения

Когда сигнальных модулей несколько, как между ними достигается консенсус? Вот здесь и вступает в игру элегантная система голосования и взвешивания. Каждый модуль не просто кричит "покупать" или "продавать"; он спокойно указывает свой уровень уверенности с помощью "веса" от 0 до 100.

Сильный, четкий сигнал может дать весомый голос с оценкой 80, в то время как более слабый может дать всего 10. Затем советник подсчитывает все голоса. Сделка исполняется только в том случае, если общий уровень уверенности превышает заданный порог. Эта система естественным образом отдает приоритет сигналам с высокой степенью уверенности и позволяет более слабым, дополняющим сигналам влиять на ситуацию, не действуя в одиночку.

Распределение ролей: триггеры и фильтры

Не все сигналы равноценны, и они не должны быть таковыми. В тонко настроенной системе мы назначаем им определенные роли:

Основные сигналы (триггеры): это ваши основные стратегии — те, которые предназначены для поиска возможностей. Они имеют высокий вес и и формируют основную массу торговых идей.

Сигналы-фильтры: они действуют как команда контроля качества. Например, фильтр волатильности может снизить общий вес в периоды хаоса на рынке. Временной фильтр может блокировать сделки вне определенных часов. Сами по себе они редко генерируют сделки, но могут накладывать вето на неудачные, что делает всю систему более надёжной.

Главное преимущество: встроенная адаптивность

Вся эта архитектура ведет к заветной цели автоматизированной торговли: адаптивности. Рынки развиваются, и стратегии, которые работали вчера, могут потерпеть неудачу сегодня. В советнике с одной стратегией это катастрофа. Но в системе с несколькими сигналами это управляемый риск.

Когда трендовый рынок переходит в диапазон, ваши сигналы следования за трендом могут затихнуть, но ваши сигналы возврата к среднему или сигналы на основе осциллятора могут компенсировать это. Советник не нужно переписывать; он естественным образом опирается на стратегии, которые работают в данный момент. Эта встроенная устойчивость позволяет советнику "выживать" и процветать в различных рыночных условиях.

FlowDigram

Концептуальная схема мультисигнального советника

Как устроен процесс работы системы:

  • Рыночные данные непрерывно поступают в нашу систему мультисигнального советника.
Несколько сигнальных модулей обрабатывают данные одновременно:
  1. Основные триггеры ищут возможности для входа в рынок.
  2. Сигналы-фильтры подтверждают и уточняют принятые решения.
  3. Все модули можно комбинировать (встроенные + пользовательские, как, например, наш модуль Фибоначчи).
  4. Система взвешивания собирает уровни уверенности всех активных сигналов.
  5. Модуль принятия решений оценивает, превышает ли общий уровень уверенности наш торговый порог.
  6. Управление рисками отвечает за определение размера позиции и контроль рисков.
  7. Открытие сделки происходит только тогда, когда все условия совпадают.

Визуализация ключевых преимуществ:

  1. Устойчивость: несколько сигнальных направлений означает, что если один из них перестанет работать, другие все равно смогут сработать.
  2. Адаптивность: различные сигналы доминируют в разных рыночных условиях.
  3. Специализация: каждый модуль фокусируется на том, что у него получается лучше всего.
  4. Профессиональная основа: стандартная библиотека MQL5 обеспечивает надежную инфраструктуру.

Такая архитектура создает то, что мы могли бы назвать "стратегическим разнообразием" — советник не зависит от какого-либо одного рыночного состояния или паттерна, что значительно повышает его способность адаптироваться и выживать по мере развития рынков. Используя мастер MQL5 для обработки сложного шаблонного служебного кода, мы можем сосредоточиться на самом важном: разработке и совершенствовании этой разнообразной команды сигналов. В следующей части мы применим это на практике, начиная с написания нашего модуля сигналов на основе уровней Фибоначчи и интеграции его со встроенными инструментами библиотеки.



Реализация

Создание профессионального торгового сигнала по Фибоначчи для мастера MQL5

Основа: Настройка структуры классов сигналов

Прежде чем углубиться в сложную логику, давайте подробнее рассмотрим "магические комментарии", благодаря которым наш сигнал появляется в мастере MQL5. Обратите внимание на блок начала/конца описания мастера — это не просто документация; это фактически метаданные, которые мастер MQL5 использует, чтобы показать наш сигнал в выпадающем списке. Заголовок — это то, что видят пользователи, ShortName становится внутренним идентификатором, а ссылка на страницу ведет к документации.

Наследуя от CExpertSignal, мы подключаемся к обширной инфраструктуре стандартной библиотеки MQL5. Это классический случай “стоять на плечах гигантов” — мы получаем управление рисками, определение размера позиции и исполнение сделок бесплатно, в то время как сосредотачиваемся исключительно на нашей торговой логике Фибоначчи. Защищенные переменные-члены, которые вы видите, — это наши параметры конфигурации, которые пользователи смогут настраивать в интерфейсе мастера MQL5.

//+------------------------------------------------------------------+
//|                                                  SignalFibonacci |
//|                                                   Copyright 2025 |
//|                                                 Clemence Benjamin|
//+------------------------------------------------------------------+
#ifndef SIGNAL_FIBONACCI_H
#define SIGNAL_FIBONACCI_H

#include <Expert\ExpertSignal.mqh>

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signals of Fibonacci Retracement Levels                    |
//| Type=SignalAdvanced                                              |
//| Name=Fibonacci Retracement                                       |
//| ShortName=Fib                                                    |
//| Class=CSignalFibonacci                                           |
//| Page=signal_fibonacci                                            |
//+------------------------------------------------------------------+
// wizard description end

//+------------------------------------------------------------------+
//| CSignalFibonacci class                                           |
//| Purpose: Complete Fibonacci-based trading signal module          |
//+------------------------------------------------------------------+
class CSignalFibonacci : public CExpertSignal
{
protected:
    // Configuration parameters
    int               m_depth;              // Lookback period for swing detection
    double            m_min_retracement;    // Minimum retracement percentage
    double            m_max_retracement;    // Maximum retracement percentage  
    double            m_weight_factor;      // Weight multiplier for confidence
    bool              m_use_as_filter;      // Use as filter instead of primary
    double            m_filter_weight;      // Weight when used as filter
    bool              m_combine_with_trend; // Only trade with trend
    double            m_tolerance;          // Price tolerance for levels
    
    // Pattern weights (0-100)
    int               m_pattern_0;          // Model 0 "price at strong Fib level (0.382/0.618)"
    int               m_pattern_1;          // Model 1 "price at medium Fib level (0.500)"
    int               m_pattern_2;          // Model 2 "price at weak Fib level (0.236/0.786)"
    int               m_pattern_3;          // Model 3 "Fib level with price action confirmation"
    
    // Internal state variables
    double            m_high_price;
    double            m_low_price;
    datetime          m_high_time;
    datetime          m_low_time;
    bool              m_uptrend;
    double            m_current_strength;
    ENUM_TIMEFRAMES   m_actual_period;      // Store the actual timeframe to use

Интеллектуальная настройка: предоставление пользователям контроля без лишних сложностей

Здесь мы определяем "панель управления" для своего сигнала по Фибоначчи. Каждый из этих простых методов-установщиков становится настраиваемым параметром в интерфейсе мастера MQL5. Когда пользователи выбирают наш сигнал, они видят ползунки и поля ввода для параметров Depth, MinRetracement и, что наиболее важно, весов паттерна.

Система весов паттерна (0-100) делает этот сигнал интеллектуальным. Представьте, что вы говорите системе: "Когда видишь цену на сильном уровне Фибоначчи 0,618, я хочу, чтобы система оценивала такой сигнал с уверенностью 80%, а на более слабом уровне 0,236 — только на 60%". Именно этот детальный контроль отличает любительские индикаторы от профессиональных торговых систем. Пользователи могут тестировать различные комбинации весов, чтобы найти то, что лучше всего подходит для их стиля торговли и рыночных условий.

public:
    // Parameter methods for Wizard
    void             Depth(int value)                { m_depth = value; }
    void             MinRetracement(double value)    { m_min_retracement = value; }
    void             MaxRetracement(double value)    { m_max_retracement = value; }
    void             WeightFactor(double value)      { m_weight_factor = value; }
    
    // Pattern weight methods
    void             Pattern_0(int value)            { m_pattern_0 = value; }
    void             Pattern_1(int value)            { m_pattern_1 = value; }

Ключевой модуль: поиск значимых точек рыночных колебаний

На этом этапе начинается настоящая детективная работа! Функция FindSwingPoints() — это наш метод для выявления значимых рыночных структур — пиков и впадин, определяющих тренды. Мы используем функции iHighest() и iLowest() для сканирования указанного количества баров (параметр m_depth) с целью поиска самых последних значимых максимумов и минимумов.

Полезный совет: параметр m_depth имеет решающее значение, поскольку рынки обладают разными "характерами" на разных таймфреймах. На 5-минутном графике анализ 50 баров может охватывать несколько часов, в то время как на дневном графике это может представлять данные за несколько месяцев. Этот параметр позволяет пользователям адаптировать наш сигнал к своему предпочтительному стилю торговли без изменения кода.

Обратите внимание, что мы также определяем направление тренда, сравнивая временные метки максимума и минимума — простой, но эффективный способ понять рыночный контекст. Это понимание тренда позже поможет нам различать уровни поддержки Фибоначчи (в восходящих трендах) и сопротивления (в нисходящих трендах).

bool CSignalFibonacci::FindSwingPoints(void)
{
    if(m_depth <= 0)
        return false;
        
    int highest_bar = iHighest(m_symbol.Name(), calc_period, MODE_HIGH, m_depth, 1);
    int lowest_bar = iLowest(m_symbol.Name(), calc_period, MODE_LOW, m_depth, 1);
    
    if(highest_bar == -1 || lowest_bar == -1)
        return false;
    
    m_high_price = iHigh(m_symbol.Name(), calc_period, highest_bar);
    m_low_price = iLow(m_symbol.Name(), calc_period, lowest_bar);
    // ... trend detection

Математика Фибоначчи: расчет точных уровней коррекции

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

В восходящем тренде мы измеряем коррекции вниз от максимума к минимуму. В нисходящем тренде мы измеряем коррекции вверх от минимума к максимуму. Это может показаться очевидным, но я видел много торговых систем, которые ошибаются в этом! В результате получаются точные ценовые уровни, где мы ожидаем, что рынок найдет поддержку или сопротивление.

Обратите внимание, что мы используем классические уровни Фибоначчи (0,236, 0,382, 0,500, 0,618, 0,786), которые представляют собой ключевые психологические и математические уровни, за которыми следят трейдеры по всему миру. Именно потому, что эти уровни известны всем участникам рынка, они часто становятся самореализующимися ориентирами.

double CSignalFibonacci::CalculateRetracementLevel(double level)
{
    double range = m_high_price - m_low_price;
    
    if(m_uptrend) {
        // Uptrend: calculate retracement from high to low
        return m_high_price - (range * level);
    } else {
        // Downtrend: calculate retracement from low to high  
        return m_low_price + (range * level);
    }
}

Интеллектуальное распознавание паттернов: классификация сетапов Фибоначчи

На этом этапе мы добавляем интеллект к нашему сигналу. Вместо того чтобы рассматривать все уровни Фибоначчи одинаково, мы классифицируем их по силе и присваиваем им различные типы паттернов. Уровни 0,382 и 0,618 считаются "золотыми" коррекциями Фибоначчи и получают наибольший вес (паттерн 0), в то время как уровень 0,500 психологически важен, но математически менее значим (паттерн 1).

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

Функция возвращает как результат true/false, так и тип паттерна через параметр-ссылку. Такая элегантная конструкция позволяет вызывающей функции знать не только то, ЧТО мы находимся на уровне Фибоначчи, но и КАКОЙ тип уровня и насколько он значим.

bool CSignalFibonacci::IsAtFibonacciLevel(double price, int &pattern)
{
    // Define Fibonacci levels and their pattern types
    struct FibLevel {
        double level;
        int pattern;
    };
    
    FibLevel levels[5] = {
        {0.236, 2},  // Weak level -> pattern 2
        {0.382, 0},  // Strong level -> pattern 0
        {0.500, 1},  // Medium level -> pattern 1
        {0.618, 0},  // Strong level -> pattern 0
        {0.786, 2}   // Weak level -> pattern 2
    };

Подтверждение по Price Action: поиск подтверждения бычьего разворота

Нахождение уровней Фибоначчи — это только половина дела; нам необходимо подтверждение того, что цена действительно реагирует на эти уровни. Эта функция ищет классические паттерны бычьих разворотов, которые дают нам уверенность в открытии длинных позиций.

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

Для паттерна Молот мы используем некоторые хитрые математические методы для определения свечей с небольшими телами и длинными нижними тенями. Ключевой момент — сравнение длины тени с длиной тела: у настоящего Молота нижняя тень как минимум вдвое больше размера тела. Это указывает на отбой от более низких уровней цен и потенциальный бычий разворот.

Эти подтверждающие паттерны превращают наш сигнал Фибоначчи из простого детектора уровней в более продвинутую торговую систему, которая ждет, пока цена "докажет", что уровень является значимым.

bool CSignalFibonacci::IsBullishReversal(void)
{
    double open1 = iOpen(m_symbol.Name(), calc_period, 1);
    double close1 = iClose(m_symbol.Name(), calc_period, 1);
    // ... get more price data
    
    // Bullish engulfing pattern
    if(close1 > open1 && open2 > close2 && close1 > open2 && open1 < close2) {
        return true;
    }
    
    // Hammer pattern detection
    double range1 = high1 - low1;
    double body1 = MathAbs(close1 - open1);
    double lower_wick = (open1 > close1) ? (close1 - low1) : (open1 - low1);
    
    if(lower_wick >= (2 * body1)) {
        return true;
    }
    
    return false;
}

Модуль принятия решений: генерация сигналов на открытие длинных позиций

На этом этапе все сходится воедино — метод LongCondition() является ключевым модулем, принимающим окончательные торговые решения. Обратите внимание, что он возвращает целое число от 0 до 100, представляющее уровень уверенности сигнала. Это стандартизированный интерфейс, который мастер MQL5 ожидает от всех сигналов.

Макрос IS_PATTERN_USAGE — это умная система, позволяющая пользователям включать или отключать определенные шаблоны в интерфейсе мастера. Возможно, они хотят торговать только на сильном уровне 0,618, игнорируя более слабые уровни — эта система предоставляет им такую ​​гибкость без изменений в коде.

Ключевая идея здесь заключается в том, как мы объединяем уровни Фибоначчи с подтверждением по Price Action. Если у нас есть и уровень Фибоначчи, и паттерн бычьего разворота, мы используем больший вес из паттерна 3 (Фибоначчи + поведение цены). Это создает иерархию качества сигнала, что делает наши торговые решения гораздо более продуманными.

int CSignalFibonacci::LongCondition(void)
{
    int result = 0;
    int pattern = -1;
    double current_price = m_symbol.Bid();
    
    if(IsAtFibonacciLevel(current_price, pattern)) {
        if(pattern >= 0) {
            if(IS_PATTERN_USAGE(pattern)) {
                result = (int)GetPatternWeight(pattern);
            }
            
            if(IS_PATTERN_USAGE(3) && IsBullishReversal()) {
                int pa_weight = (int)GetPatternWeight(3);
                if(pa_weight > result) result = pa_weight;
            }

Мы разработали полноценный модуль торговой логики, который понимает структуру рынка, определяет ключевые математические уровни Фибоначчи, ждет подтверждения со стороны цены и генерирует сигналы с учетом уровня уверенности. Истинная мощь проявляется при объединении этого сигнала с другими сигналами в мастере MQL5. Но прежде чем мы объединили его с другими сигналами для достижения своей цели, мы создали еще один тестовый советник, чтобы проверить, корректно ли работает эта идея. Вот визуализация тестера стратегий. Как обычно, чтобы запустить мастер MQL5, выберите New Document в Meta Editor или нажмите комбинацию клавиш Ctrl+N и выберите создание советника.

MQL5 Wizard enlisting the Fibonacci Signal

Выбор сигнала Фибоначчи с помощью мастера MQL5



Тестирование 1

На изображении ниже показано визуальное поведение советника, сгенерированного для тестирования нашего пользовательского сигнала Фибоначчи по паре USDJPY, M5.

Testing the Fibonacci Signal

Тестирование советника, сгенерированного мастером MQL5, по паре USDJPY, M5

Теперь, когда мы успешно протестировали наш сигнал Фибоначчи, мы готовы создать нечто действительно мощное — мультисигнальный советник, который будет работать не как простой робот, а скорее как команда профильных торговых аналитиков, работающих в идеальной гармонии. Представьте себе, что вы создаете свою собственную команду мечты, где каждый сигнал привносит уникальные знания в общую копилку.

Преимущество мастера MQL5 в том, что он берет на себя всю сложную инфраструктурную часть, позволяя нам сосредоточиться на действительно важном: создании интеллектуальной торговой логики. Вот как мы превратим наш тест с одним сигналом в более совершенную торговую систему.

Используя тот же подход, что и раньше в MetaEditor, нажмите Ctrl+N, чтобы открыть мастер MQL5, затем выберите Expert Advisor (generate). В разделе Signals добавьте следующие модули:

  • Сигнал Фибоначчи (Эксперт точного входа)
  • Осциллятор Accelerator (индикатор рыночной энергии)
  • Скользящая средняя (Специалист по трендам)
  • RSI (Аналитик импульса)

Итак, вот сгенерированный мастером MQL5 советник:

//+------------------------------------------------------------------+
//|                                          Multi-Signal Expert.mq5 |
//|                               Copyright 2025, Clemence Benjamin. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Clemence Benjamin."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Include                                                          |
//+------------------------------------------------------------------+
#include <Expert\Expert.mqh>
//--- available signals
#include <Expert\Signal\SignalFibonacci.mqh>
#include <Expert\Signal\SignalAC.mqh>
#include <Expert\Signal\SignalMA.mqh>
#include <Expert\Signal\SignalRSI.mqh>
//--- available trailing
#include <Expert\Trailing\TrailingParabolicSAR.mqh>
//--- available money management
#include <Expert\Money\MoneySizeOptimized.mqh>
//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
//--- inputs for expert
input string             Expert_Title                      ="Multi-Signal Expert"; // Document name
ulong                    Expert_MagicNumber                =-108721665;            //
bool                     Expert_EveryTick                  =false;                 //
//--- inputs for main signal
input int                Signal_ThresholdOpen              =10;                    // Signal threshold value to open [0...100]
input int                Signal_ThresholdClose             =10;                    // Signal threshold value to close [0...100]
input double             Signal_PriceLevel                 =0.0;                   // Price level to execute a deal
input double             Signal_StopLevel                  =50.0;                  // Stop Loss level (in points)
input double             Signal_TakeLevel                  =50.0;                  // Take Profit level (in points)
input int                Signal_Expiration                 =4;                     // Expiration of pending orders (in bars)
input double             Signal_Fib_Weight                 =1.0;                   // Fibonacci Retracement Weight [0...1.0]
input double             Signal_AC_Weight                  =1.0;                   // Accelerator Oscillator Weight [0...1.0]
input int                Signal_MA_PeriodMA                =12;                    // Moving Average(12,0,...) Period of averaging
input int                Signal_MA_Shift                   =0;                     // Moving Average(12,0,...) Time shift
input ENUM_MA_METHOD     Signal_MA_Method                  =MODE_SMA;              // Moving Average(12,0,...) Method of averaging
input ENUM_APPLIED_PRICE Signal_MA_Applied                 =PRICE_CLOSE;           // Moving Average(12,0,...) Prices series
input double             Signal_MA_Weight                  =1.0;                   // Moving Average(12,0,...) Weight [0...1.0]
input int                Signal_RSI_PeriodRSI              =8;                     // Relative Strength Index(8,...) Period of calculation
input ENUM_APPLIED_PRICE Signal_RSI_Applied                =PRICE_CLOSE;           // Relative Strength Index(8,...) Prices series
input double             Signal_RSI_Weight                 =1.0;                   // Relative Strength Index(8,...) Weight [0...1.0]
//--- inputs for trailing
input double             Trailing_ParabolicSAR_Step        =0.02;                  // Speed increment
input double             Trailing_ParabolicSAR_Maximum     =0.2;                   // Maximum rate
//--- inputs for money
input double             Money_SizeOptimized_DecreaseFactor=3.0;                   // Decrease factor
input double             Money_SizeOptimized_Percent       =10.0;                  // Percent
//+------------------------------------------------------------------+
//| Global expert object                                             |
//+------------------------------------------------------------------+
CExpert ExtExpert;
//+------------------------------------------------------------------+
//| Initialization function of the expert                            |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Initializing expert
   if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber))
     {
      //--- failed
      printf(__FUNCTION__+": error initializing expert");
      ExtExpert.Deinit();
      return(INIT_FAILED);
     }
//--- Creating signal
   CExpertSignal *signal=new CExpertSignal;
   if(signal==NULL)
     {
      //--- failed
      printf(__FUNCTION__+": error creating signal");
      ExtExpert.Deinit();
      return(INIT_FAILED);
     }
//---
   ExtExpert.InitSignal(signal);
   signal.ThresholdOpen(Signal_ThresholdOpen);
   signal.ThresholdClose(Signal_ThresholdClose);
   signal.PriceLevel(Signal_PriceLevel);
   signal.StopLevel(Signal_StopLevel);
   signal.TakeLevel(Signal_TakeLevel);
   signal.Expiration(Signal_Expiration);
//--- Creating filter CSignalFibonacci
   CSignalFibonacci *filter0=new CSignalFibonacci;
   if(filter0==NULL)
     {
      //--- failed
      printf(__FUNCTION__+": error creating filter0");
      ExtExpert.Deinit();
      return(INIT_FAILED);
     }
   signal.AddFilter(filter0);
//--- Set filter parameters
   filter0.Weight(Signal_Fib_Weight);
//--- Creating filter CSignalAC
   CSignalAC *filter1=new CSignalAC;
   if(filter1==NULL)
     {
      //--- failed
      printf(__FUNCTION__+": error creating filter1");
      ExtExpert.Deinit();
      return(INIT_FAILED);
     }
   signal.AddFilter(filter1);
//--- Set filter parameters
   filter1.Weight(Signal_AC_Weight);
//--- Creating filter CSignalMA
   CSignalMA *filter2=new CSignalMA;
   if(filter2==NULL)
     {
      //--- failed
      printf(__FUNCTION__+": error creating filter2");
      ExtExpert.Deinit();
      return(INIT_FAILED);
     }
   signal.AddFilter(filter2);
//--- Set filter parameters
   filter2.PeriodMA(Signal_MA_PeriodMA);
   filter2.Shift(Signal_MA_Shift);
   filter2.Method(Signal_MA_Method);
   filter2.Applied(Signal_MA_Applied);
   filter2.Weight(Signal_MA_Weight);
//--- Creating filter CSignalRSI
   CSignalRSI *filter3=new CSignalRSI;
   if(filter3==NULL)
     {
      //--- failed
      printf(__FUNCTION__+": error creating filter3");
      ExtExpert.Deinit();
      return(INIT_FAILED);
     }
   signal.AddFilter(filter3);
//--- Set filter parameters
   filter3.PeriodRSI(Signal_RSI_PeriodRSI);
   filter3.Applied(Signal_RSI_Applied);
   filter3.Weight(Signal_RSI_Weight);
//--- Creation of trailing object
   CTrailingPSAR *trailing=new CTrailingPSAR;
   if(trailing==NULL)
     {
      //--- failed
      printf(__FUNCTION__+": error creating trailing");
      ExtExpert.Deinit();
      return(INIT_FAILED);
     }
//--- Add trailing to expert (will be deleted automatically))
   if(!ExtExpert.InitTrailing(trailing))
     {
      //--- failed
      printf(__FUNCTION__+": error initializing trailing");
      ExtExpert.Deinit();
      return(INIT_FAILED);
     }
//--- Set trailing parameters
   trailing.Step(Trailing_ParabolicSAR_Step);
   trailing.Maximum(Trailing_ParabolicSAR_Maximum);
//--- Creation of money object
   CMoneySizeOptimized *money=new CMoneySizeOptimized;
   if(money==NULL)
     {
      //--- failed
      printf(__FUNCTION__+": error creating money");
      ExtExpert.Deinit();
      return(INIT_FAILED);
     }
//--- Add money to expert (will be deleted automatically))
   if(!ExtExpert.InitMoney(money))
     {
      //--- failed
      printf(__FUNCTION__+": error initializing money");
      ExtExpert.Deinit();
      return(INIT_FAILED);
     }
//--- Set money parameters
   money.DecreaseFactor(Money_SizeOptimized_DecreaseFactor);
   money.Percent(Money_SizeOptimized_Percent);
//--- Check all trading objects parameters
   if(!ExtExpert.ValidationSettings())
     {
      //--- failed
      ExtExpert.Deinit();
      return(INIT_FAILED);
     }
//--- Tuning of all necessary indicators
   if(!ExtExpert.InitIndicators())
     {
      //--- failed
      printf(__FUNCTION__+": error initializing indicators");
      ExtExpert.Deinit();
      return(INIT_FAILED);
     }
//--- ok
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Deinitialization function of the expert                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ExtExpert.Deinit();
  }
//+------------------------------------------------------------------+
//| "Tick" event handler function                                    |
//+------------------------------------------------------------------+
void OnTick()
  {
   ExtExpert.OnTick();
  }
//+------------------------------------------------------------------+
//| "Trade" event handler function                                   |
//+------------------------------------------------------------------+
void OnTrade()
  {
   ExtExpert.OnTrade();
  }
//+------------------------------------------------------------------+
//| "Timer" event handler function                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   ExtExpert.OnTimer();
  }
//+------------------------------------------------------------------+
    


Тестирование 2

После генерации советника я провел тест в тестере стратегий, чтобы понаблюдать за его работой. GIF-скриншот ниже показывает, как он вел себя на паре EURUSD, M5. Обратите внимание, что на данном этапе мы еще не добавили графики кривой эквити или другие подробные метрики тестирования, поскольку в настоящее время основное внимание уделяется только визуальной оценке работы. Под изображением я делюсь своими мыслями и критикой работы сгенерированного советника, поскольку мы готовимся доработать его и приблизить к нашим намеченным целям.

Testing the generated version of the Multiple Signal Expert

Тестирование сгенерированного мультисигнального советника

Критический анализ — в чем сгенерированный мастером советник не соответствует нашему видению

После анализа кода, сгенерированного мастером MQL5, становится ясно, что существует заметный разрыв между тем, что было сгенерировано, и тем мультисигнальным фреймворком, основанным на конфлюэнсе сигналов, который мы изначально задумывали. Мастер MQL5 дает нам полезную отправную точку, но в своем стандартном виде он остается простым агрегатором сигналов, а не продуманным модулем принятия решений, учитывающим иерархию. В этом разделе мы рассмотрим основные недостатки и опишем необходимые корректировки, чтобы приблизить советник к нашим проектным целям.

1. Восстановление осмысленной иерархии сигналов

По умолчанию сгенерированный советник присваивает всем сигналам вес 1,0. Это может быть удобно для быстрого тестирования, но полностью игнорирует тот факт, что наши сигналы не имеют одинаковой важности. В нашей концепции Фибоначчи является основным фактором принятия решений, в то время как скользящая средняя, RSI и Accelerator Oscillator играют вспомогательные роли.

Текущие автоматически сгенерированные входные параметры:

// Uniform weights (problematic)
input double Signal_Fib_Weight = 1.0;    // Should be 0.8 (80%)
input double Signal_AC_Weight  = 1.0;    // Should be 0.4 (40%)  
input double Signal_MA_Weight  = 1.0;    // Should be 0.6 (60%)
input double Signal_RSI_Weight = 1.0;    // Should be 0.5 (50%)

Равные веса сглаживают нашу иерархию, ослабляют влияние сигнала Фибоначчи и упускают возможность напрямую интегрировать наш торговый опыт в модель. Необходимо более стратегическое распределение:

// Strategic weight distribution
input double Signal_Fib_Weight = 0.8;    // Core signal – mathematical precision
input double Signal_MA_Weight  = 0.6;    // Trend context and alignment
input double Signal_RSI_Weight = 0.5;    // Momentum validation  
input double Signal_AC_Weight  = 0.4;    // Early energy/acceleration hint

Это простое изменение уже отдаляет нас от “плоской демократии” сигналов в сторону структурированной, основанной на намерениях системы.

2. Пороги открытия: от чрезмерной торговли к выборочным входам

Мастер также задает очень низкий порог открытия позиции. Это практически гарантирует, что советник будет совершать сделки при слабых комбинациях сигналов, особенно когда все веса установлены на 1,0.

// Extremely permissive configuration
input int Signal_ThresholdOpen = 10;     // Too low for serious use

При таком пороговом значении советник склонен к чрезмерной торговле: даже небольшие колебания в оценках сигналов становятся достаточным основанием для входа в сделку. Транзакционные издержки возрастают, требования к совпадению сигналов исчезают, и общее качество сделок страдает.

Для мультисигнальной системы, построенной на подтверждении, нам нужен гораздо более высокий бар для открытия сделок и более гибкое условие для их закрытия:

// Thresholds aligned with our confluence idea
input int Signal_ThresholdOpen  = 120;   // Strong confirmation required to open
input int Signal_ThresholdClose = 80;    // More relaxed exit behaviour

При такой структуре одного сильного сигнала Фибоначчи (80) плюс как минимум одного допустимого подтверждающего сигнала (например, 40) достаточно для оправдания сделки, в то время как отдельные незначительные показания больше не инициируют входы сами по себе.

3. Отсутствие механизма выявления конфлюенса: кластеризация по цене и времени

Еще один ключевой элемент, который не предоставляет сгенерированный советник, — это настоящий модуль анализа конфлюэнса. Наша разработка направлена на распознавание ситуаций, когда несколько сигналов совпадают как по цене, так и по времени, образуя зону с более высокой вероятностью срабатывания, в отличие от случаев, когда срабатывают отдельные индикаторы независимо друг от друга.

Концептуально нам нужен компонент, способный отвечать на такие вопросы, как: группируются ли эти сигналы в одной и той же ценовой области? Появляются ли они в одном и том же временном периоде? Минимальный интерфейс может выглядеть следующим образом:

// Price–time confluence skeleton
class CConfluenceEngine
  {
public:
   bool HasPriceTimeConfluence();
   int  CalculateConfluenceBonus();
   bool CheckSignalClustering();
  };

Это открывает возможности для добавления дополнительного “бонусного” веса, когда несколько сигналов перекрываются в узком диапазоне, повышая уверенность, когда рынок демонстрирует те редкие совпадающие условия, которые нас интересуют.

4. Статический размер лота против определения размера позиции на основе уверенности

Управление капиталом, сгенерированное мастером, по сути, статично. Оно применяет один и тот же процент риска независимо от того, слабые сигналы или исключительно сильные:

// Static risk usage
input double Money_SizeOptimized_Percent = 10.0; // Same for all setups

В рамках подхода, основанного на совпадении сигналов, это упущенная возможность. Сильные сетапы, подкрепленные несколькими совпадающими сигналами, должны разумно оправдывать большее распределение риска, чем пограничные условия. Лучший подход — определять размер позиции на основе общей уверенности в сигнале:

// Example of dynamic, confidence-based position sizing
double CalculateDynamicPositionSize(int total_confidence)
  {
   if(total_confidence >= 200) return BaseSize * 2.0;  // Exceptional confluence
   if(total_confidence >= 150) return BaseSize * 1.5;  // Strong setup  
   if(total_confidence >= 120) return BaseSize * 1.0;  // Standard setup
   if(total_confidence >= 100) return BaseSize * 0.7;  // Marginal but tradable
   return 0.0;                                         // No trade
  }

Это превращает наш механизм сигналов также в модуль управления рисками: более качественная информация приводит к более обоснованному распределению капитала.

5. Отсутствие осведомленности о рыночном режиме

Сгенерированный советник также рассматривает все рыночные условия как идентичные. Он не различает периоды затишья и волатильности, сильные тренды и нестабильные диапазоны. На практике наши сигналы ведут себя совершенно по-разному в зависимости от режима, и стратегия должна соответствующим образом адаптироваться.

Простым первым шагом является введение базовых проверок режима с использованием распространенных индикаторов, таких как ATR и ADX:

// Simple regime detection examples
bool IsHighVolatilityPeriod()
  {
   return (iATR(Symbol(), Period(), 14, 0) > high_vol_threshold);
  }

bool IsStrongTrendingMarket()
  {
   return (iADX(Symbol(), Period(), 14, PRICE_CLOSE, MODE_MAIN, 0) > 25);
  }

void AdjustStrategyForMarketConditions()
  {
   if(IsHighVolatilityPeriod())
     {
      // Example: tighten filters when volatility is elevated
      Signal_ThresholdOpen = 150;
     }
  }

Даже эти простые проверки могут предотвратить слепое применение советником одних и тех же правил во всех рыночных условиях.

6. От суммирования весов до осмысленного взаимодействия сигналов

В своей базовой форме мастер просто суммирует веса сигналов, не учитывая, как эти сигналы взаимодействуют. Это математически просто, но стратегически наивно:

// Naive aggregation
Total_Weight = Fib_Weight + MA_Weight + RSI_Weight + AC_Weight;

Наша цель более структурирована: Фибоначчи должны быть якорем, в то время как другие модули либо подтверждают, либо остаются нейтральными. Более выразительное взаимодействие может выглядеть так:

Здесь структура логики ясно показывает ситуацию: Фибоначчи лидирует, остальные подтверждают, и согласованность сигналов получает дополнительный вес.

// Interaction-aware weighting logic
double CalculateStrategicWeight()
  {
   double total = 0.0;

   // Base: Fibonacci direction
   total += Fib_Weight;

   // Trend confirmation
   if(MA_Confirms_Fib_Direction)
      total += MA_Weight;

   // Momentum validation
   if(RSI_Confirms_Fib_Setup)
      total += RSI_Weight;

   // Acceleration / early energy
   if(AC_Shows_Momentum_Acceleration)
      total += AC_Weight;

   // Extra boost when multiple modules agree
   if(Active_Signals >= 3)
      total += Confluence_Bonus;

   return total;
  }

7. Отсутствие цикла обучения: веса не адаптируются

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

Небольшой структуры отслеживания достаточно для начала:

// Basic performance tracking per signal
struct SignalPerformance
  {
   string name;
   int    successful_trades;
   int    total_trades;
   double success_rate;
  };

void UpdateSignalWeightsBasedOnPerformance()
  {
   // Placeholder: adjust weights according to success_rate
   // e.g. increase for strong performers, decrease for weak ones
  }

Даже если мы начнем с простой отчетности в первой версии, такая структура упрощает внедрение адаптивного поведения позже без перепроектирования советника с нуля.

8. Управление рисками связано с рынком и уровнем уверенности

Наконец, в настройках управления рисками по умолчанию в мастере используются фиксированные расстояния стоп-лосса и тейк-профита:

// Fixed levels for all conditions
input double Signal_StopLevel = 50.0;    // pips, independent of volatility
input double Signal_TakeLevel = 50.0;

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

// Example of dynamic, ATR-based risk management
double CalculateDynamicStopLoss(int signal_confidence,double volatility)
  {
   double base_stop = volatility * 2.0;  // ATR-driven base distance

   if(signal_confidence >= 200)
      return base_stop * 0.7;           // Tighter stops on very strong setups

   if(signal_confidence <= 100)
      return base_stop * 1.5;           // Wider stops for weaker conditions

   return base_stop;
  }

Таким образом, советник учитывает как текущее состояние рынка, так и силу лежащего в основе решения.

В совокупности эти наблюдения показывают, что мастер предоставляет нам удобный каркас, но не готовую архитектуру, которая нам нужна. Наши следующие шаги — постепенно заменить общие компоненты взвешенной иерархией, логикой конфлюенса, динамическим определением размера и адаптивным поведением риска, описанными выше, чтобы сгенерированный советник действительно отражал философию проектирования, с которой мы начали.



Заключение

В этом обсуждении мы заложили основу для разработки мультисигнального советника. Мы изучили один из самых популярных подходов технического анализа — Фибоначчи — и продемонстрировали, как перевести эту теорию в практический торговый сигнал. Наш первоначальный тест с мастером MQL5 позволил создать работающий советник, который может открывать сделки на основе пользовательского сигнала Фибоначчи. Как всегда, это не гарантирует прибыльности; эта часть зависит от того, насколько тщательно будут проведены исследования, тестирование и продуманная оптимизация. В своем темпе вы можете экспериментировать с предоставленными базовыми исходными файлами и искать комбинации параметров, соответствующие вашим торговым целям.

Когда мы расширили идею до мультисигнального советника, стало ясно, что мастер MQL5 — это лишь отправная точка. Сгенерированный по умолчанию код не определяет, как отдельные сигналы должны работать вместе в скоординированной команде. Нет встроенной логики, описывающей взаимосвязи между уровнями Фибоначчи, скользящей средней, RSI и Accelerator Oscillator — как они подтверждают, отменяют или усиливают друг друга. По этой причине дальнейшая разработка в MetaEditor необходима после генерации кода. Создать советник с несколькими сигналами несложно, но для обеспечения интеллектуального взаимодействия этих сигналов разработчику необходимо открыть исходный код и вручную уточнить логику.

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

Исходный файлОписание:
SignalFibonacci.mqhПользовательский модуль сигналов, который инкапсулирует торговую логику на основе уровней Фибоначчи и предоставляет ее мастеру MQL5 в качестве переиспользуемого сигнального компонента.
TestSignalFibonacci.mq5Это автономный тестовый советник, созданный с помощью мастера MQL5 для проверки того, что сигнал Фибоначчи компилируется, загружается корректно и может самостоятельно совершать сделки.
Multi-Signal Expert.mq5Сгенерированный мастером мультисигнальный советник, который объединяет сигналы Фибоначчи, скользящей средней, RSI и Accelerator Oscillator в качестве основы для нашего продвинутого мультисигнального фреймворка.

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/20289

Прикрепленные файлы |
SignalFibonacci.mqh (17.77 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (3)
prasad
prasad | 3 дек. 2025 в 13:12
Не могли бы вы, пожалуйста, поделиться настройками? Я использую настройки по умолчанию, и это приводит к огромным убыткам. Не могли бы вы, пожалуйста, поделиться настройками?
Stanislav Korotky
Stanislav Korotky | 13 дек. 2025 в 15:58
Для построения торговых стратегий, сочетающих несколько сигналов со сложными логическими условиями, настраиваемыми через входные параметры советника и не требующими перекомпиляции, пользователи могут воспользоваться модулем «Universal Signals» из кодовой базы.
Steven Glanz
Steven Glanz | 16 янв. 2026 в 16:28
Есть ли на рынке MQL5 какие-нибудь советники, основанные на этой модели?
Особенности написания Пользовательских Индикаторов Особенности написания Пользовательских Индикаторов
Написание пользовательских индикаторов в торговой системе MetaTrader 4
Возможности Мастера MQL5, которые вам нужно знать (Часть 85): Использование паттернов стохастического осциллятора и FrAMA с обучением на основе инференса β-VAE Возможности Мастера MQL5, которые вам нужно знать (Часть 85): Использование паттернов стохастического осциллятора и FrAMA с обучением на основе инференса β-VAE
Этот материал является продолжением части 84, в которой мы представили связку стохастического осциллятора (Stochastic) и фрактальной адаптивной скользящей средней (FrAMA). Теперь перейдем к обучению на основе инференса и проверим, удастся ли переломить неудачную динамику отстающих паттернов. Stochastic и FrAMA образуют взаимодополняющую связку индикаторов: один отвечает за моментум, другой – за тренд. Для обучения на основе инференса вновь используем β-VAE – вариационный автокодировщик с бета-параметром. Как и обычно, реализуем пользовательский класс сигнала для интеграции с Мастером MQL5.
Особенности написания экспертов Особенности написания экспертов
Написание и тестирование экспертов в торговой системе MetaTrader 4.
Создание торговых систем с искусственным интеллектом на MQL5 (Часть 6): Реализация поиска и удаления чатов Создание торговых систем с искусственным интеллектом на MQL5 (Часть 6): Реализация поиска и удаления чатов
В части 6 серии о торговых системах с ИИ на MQL5 мы добавляем в советник с интеграцией ChatGPT функции удаления чатов. Интерактивные кнопки удаления появятся на боковой панели, в малом и большом окнах истории, а также в новом окне поиска. Это поможет эффективно упорядочивать и управлять чатами, которые сохраняются между сеансами в зашифрованном виде, при этом поддерживая генерацию ИИ торговых сигналов по данным графика.