English Deutsch 日本語
preview
Создание пользовательской системы определения рыночного режима на языке MQL5 (Часть 1): Индикатор

Создание пользовательской системы определения рыночного режима на языке MQL5 (Часть 1): Индикатор

MetaTrader 5Трейдинг |
531 5
Sahil Bagdi
Sahil Bagdi
  1. Введение
  2. Понимание рыночных режимов
  3. Создание статистической основы
  4. Внедрение детектора рыночного режима
  5. Создание пользовательского индикатора для визуализации режима
  6. Заключение


Введение

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

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

А что если бы существовал способ получше? Что если бы ваша торговая система могла объективно определять текущий рыночный режим и соответствующим образом адаптировать свою стратегию? Именно ее мы и создадим в этой статье — комплексную систему определения рыночного режима на языке MQL5, которая может классифицировать условия рынка по отдельным режимам и предоставлять основу для адаптивных торговых стратегий.

К моменту завершения этой серии статей у вас будет полностью реализованная система определения рыночного режима, которая включает в себя:
  1. Надежную статистическую основу для объективной классификации рынка
  2. Пользовательский класс Market Regime Detector (детектор режима рынка), который определяет трендовые условия, условия флэта и условия волатильного рынка
  3. Пользовательский индикатор, который визуализирует изменения режима непосредственно на ваших графиках
  4. Адаптивный советник, который автоматически выбирает подходящие стратегии в зависимости от текущего режима (Часть 2)
  5. Практические примеры внедрения и оптимизации системы под ваши конкретные торговые потребности (Часть 2)

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


Понимание рыночных режимов

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

Что такое рыночные режимы?

Рыночные режимы — это отдельные модели поведения рынка, характеризующиеся определенными статистическими свойствами движения цен. Хотя существуют различные способы классификации рыночных режимов, мы сосредоточимся на трех основных типах, которые наиболее актуальны для разработки торговой стратегии:
  1. Трендовые режимы. Рынки демонстрируют сильное направленное движение с минимальным возвратом к среднему значению. Цена имеет тенденцию совершать последовательные движения в одном направлении с небольшими откатами. По статистике, трендовые рынки демонстрируют положительную автокорреляцию по доходности, и это означает, что за движениями цен в одном направлении, вероятнее всего, последуют движения в том же направлении.
  2. Режимы флэта. Рынки колеблются между уровнями поддержки и сопротивления с ярко выраженными тенденциями к возврату к среднему значению. Цена имеет тенденцию отскакивать между определенными границами, а не выходить из них в каком-либо направлении. По статистике, флэтовые рынки демонстрируют отрицательную автокорреляцию по доходности, и это означает, что за восходящими движениями цены, вероятнее всего, последует нисходящее движение, и наоборот.
  3. Волатильные режимы. На рынках наблюдаются сильные, хаотичные движения цен с неясным направлением. Такие режимы часто возникают в периоды неопределенности, новостных событий или напряженности рыночной конъюнктуры. По статистике, волатильные режимы демонстрируют высокие значения стандартных отклонений в доходности с непредсказуемыми моделями автокорреляции.

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

Почему традиционные индикаторы не оправдывают ожиданий?

Большинство технических индикаторов были разработаны для определения конкретных ценовых моделей или условий, а не для классификации рыночных режимов. Например:
  • Скользящие средние и MACD могут помочь определить тенденции, но не различают трендовый и волатильный режимы.
  • Индикаторы RSI и стохастические осцилляторы хорошо работают на флэтовых рынках, но генерируют ложные сигналы в условиях трендового рынка.
  • Полосы Боллинджера приспосабливаются к волатильности, но не определяют явным образом переходы между режимами.
Эти ограничения создают существенный пробел в большинстве торговых систем. Не зная, каково текущее состояние рынка, трейдеры по сути применяют стратегии вслепую в надежде, что рыночные условия будут соответствовать их ожиданиям от стратегии.

Статистические основы определения режима

Для создания эффективную систему определения режима нам необходимо использовать статистические показатели, которые могут объективно классифицировать поведение рынка. Основные статистические концепции, которые мы будем использовать, включают в себя следующие:
  1. Автокорреляция измеряет корреляцию между временным рядом и его запаздывающей версией. Положительная автокорреляция указывает на трендовое поведение, в то время как отрицательная автокорреляция предполагает поведение, характерное для возврата к среднему значению (поведение флэта).
  2. Волатильность измеряет дисперсию доходности, обычно с использованием стандартного отклонения. Внезапное увеличение волатильности часто представляет собой сигнал о смене режима.
  3. Силу тренда можно количественно оценить с применением различных методов, включая абсолютное значение автокорреляции, наклон линейной регрессии или такие специализированные индикаторы, как ADX.

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


Создание статистической основы

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

Класс CStatistics

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

//+------------------------------------------------------------------+
//| Class for statistical calculations                               |
//+------------------------------------------------------------------+
class CStatistics
{
private:
    double      m_data[];           // Data array for calculations
    int         m_dataSize;         // Size of the data array
    bool        m_isSorted;         // Flag indicating if data is sorted
    double      m_sortedData[];     // Sorted copy of data for percentile calculations
    
public:
    // Constructor and destructor
    CStatistics();
    ~CStatistics();
    
    // Data management methods
    bool        SetData(const double &data[], int size);
    bool        AddData(double value);
    void        Clear();
    
    // Basic statistical methods
    double      Mean() const;
    double      StandardDeviation() const;
    double      Variance() const;
    
    // Range and extremes
    double      Min() const;
    double      Max() const;
    double      Range() const;
    
    // Time series specific methods
    double      Autocorrelation(int lag) const;
    double      TrendStrength() const;
    double      MeanReversionStrength() const;
    
    // Percentile calculations
    double      Percentile(double percentile);
    double      Median();
};

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

Конструктор и деструктор

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CStatistics::CStatistics()
{
    m_dataSize = 0;
    m_isSorted = false;
    ArrayResize(m_data, 0);
    ArrayResize(m_sortedData, 0);
}

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CStatistics::~CStatistics()
{
    Clear();
}

Конструктор и деструктор помогают при инициализации и деинициализации класса. Конструктор инициализирует переменные члены класса и массивы, а деструктор обеспечивает корректную очистку посредством вызова метода Clear(). Такая модель правильной инициализации и очистки имеет большое значение в языке MQL5 для предотвращения утечек памяти и обеспечения надежной работы.

Методы управления данными


Далее реализуем методы управления данными, которые позволяют нам устанавливать, добавлять и очищать данные:

bool CStatistics::SetData(const double &data[], int size)
{
    if(size <= 0)
        return false;
        
    m_dataSize = size;
    ArrayResize(m_data, size);
    
    for(int i = 0; i < size; i++)
        m_data[i] = data[i];
        
    m_isSorted = false;
    return true;
}

bool CStatistics::AddData(double value)
{
    m_dataSize++;
    ArrayResize(m_data, m_dataSize);
    m_data[m_dataSize - 1] = value;
    m_isSorted = false;
    return true;
}

void CStatistics::Clear()
{
    m_dataSize = 0;
    ArrayResize(m_data, 0);
    ArrayResize(m_sortedData, 0);
    m_isSorted = false;
}
                        

Метод SetData() позволяет заменить весь набор данных новым массивом, что полезно при обработке исторических данных о ценах. Метод AddData() добавляет к существующим данным одно значение, что удобно для постепенных обновлений по мере появления новых ценовых данных. Метод Clear() сбрасывает объект в исходное состояние, освобождая всю выделенную память.

Обратите внимание, как мы устанавливаем m_isSorted = false всякий раз, когда данные изменяются. Этот флаг помогает оптимизировать производительность, сортируя данные только в том случае, когда это необходимо для расчета процентилей.

Базовые статистические методы

Теперь реализуем базовые статистические методы для расчета среднего значения, стандартного отклонения и дисперсии:

double CStatistics::Mean() const
{
    if(m_dataSize <= 0)
        return 0.0;
        
    double sum = 0.0;
    for(int i = 0; i < m_dataSize; i++)
        sum += m_data[i];
        
    return sum / m_dataSize;
}

double CStatistics::StandardDeviation() const
{
    if(m_dataSize <= 1)
        return 0.0;
        
    double mean = Mean();
    double sum = 0.0;
    
    for(int i = 0; i < m_dataSize; i++)
        sum += MathPow(m_data[i] - mean, 2);
        
    return MathSqrt(sum / (m_dataSize - 1));
}

double CStatistics::Variance() const
{
    if(m_dataSize <= 1)
        return 0.0;
        
    double stdDev = StandardDeviation();
    return stdDev * stdDev;
}

Эти методы реализуют стандартные статистические формулы. Метод Mean() вычисляет среднее значение всех точек данных. Метод StandardDeviation() измеряет дисперсию точек данных вокруг среднего значения, что имеет решающее значение для выявления нестабильных рыночных режимов. Метод Variance() возвращает квадрат стандартного отклонения, предоставляя еще один показатель измерения дисперсии данных.

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

Методы диапазона и крайних значений

//+------------------------------------------------------------------+
//| Calculate minimum value in the data                              |
//+------------------------------------------------------------------+
double CStatistics::Min() const
{
    if(m_dataSize <= 0)
        return 0.0;
        
    double min = m_data[0];
    for(int i = 1; i < m_dataSize; i++)
        if(m_data[i] < min)
            min = m_data[i];
            
    return min;
}

//+------------------------------------------------------------------+
//| Calculate maximum value in the data                              |
//+------------------------------------------------------------------+
double CStatistics::Max() const
{
    if(m_dataSize <= 0)
        return 0.0;
        
    double max = m_data[0];
    for(int i = 1; i < m_dataSize; i++)
        if(m_data[i] > max)
            max = m_data[i];
            
    return max;
}

//+------------------------------------------------------------------+
//| Calculate range (max - min) of the data                          |
//+------------------------------------------------------------------+
double CStatistics::Range() const
{
    return Max() - Min();
}
                            

Эти методы предоставляют дополнительную информацию о распределении данных. Методы Min() и Max() находят наименьшее и наибольшее значения в наборе данных, а метод Range() вычисляет разницу между ними. Эти показатели могут быть полезны для определения ценовых границ на колеблющихся рынках.

Методы, характерные для временных рядов

Теперь реализуем характерные для временных рядов методы, которые имеют решающее значение для определения режима:

double CStatistics::Autocorrelation(int lag) const
{
    if(m_dataSize <= lag || lag <= 0)
        return 0.0;
        
    double mean = Mean();
    double numerator = 0.0;
    double denominator = 0.0;
    
    for(int i = 0; i < m_dataSize - lag; i++)
    {
        numerator += (m_data[i] - mean) * (m_data[i + lag] - mean);
    }
    
    for(int i = 0; i < m_dataSize; i++)
    {
        denominator += MathPow(m_data[i] - mean, 2);
    }
    
    if(denominator == 0.0)
        return 0.0;
        
    return numerator / denominator;
}

double CStatistics::TrendStrength() const
{
    // Use lag-1 autocorrelation as a measure of trend strength
    double ac1 = Autocorrelation(1);
    
    // Positive autocorrelation indicates trending behavior
    return ac1;
}

double CStatistics::MeanReversionStrength() const
{
    // Negative autocorrelation indicates mean-reverting behavior
    double ac1 = Autocorrelation(1);
    
    // Return the negative of autocorrelation, so positive values
    // indicate stronger mean reversion
    return -ac1;
}

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

Метод TrendStrength() автокорреляцию lag-1 (задержка на 1) в качестве прямого показателя силы тренда. Более высокие положительные значения указывают на более сильные тренды. Метод MeanReversionStrength() возвращает отрицательное значение автокорреляции, поэтому положительные значения указывают на более сильные тенденции возврата к среднему значению.

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

Расчеты процентилей

Наконец, займемся реализацией методов для вычисления процентилей и медианы:

double CStatistics::Percentile(double percentile)
{
    if(m_dataSize <= 0 || percentile < 0.0 || percentile > 100.0)
        return 0.0;
        
    // Sort data if needed
    if(!m_isSorted)
    {
        ArrayResize(m_sortedData, m_dataSize);
        for(int i = 0; i < m_dataSize; i++)
            m_sortedData[i] = m_data[i];
            
        ArraySort(m_sortedData);
        m_isSorted = true;
    }
    
    // Calculate position
    double position = (percentile / 100.0) * (m_dataSize - 1);
    int lowerIndex = (int)MathFloor(position);
    int upperIndex = (int)MathCeil(position);
    
    // Handle edge cases
    if(lowerIndex == upperIndex)
        return m_sortedData[lowerIndex];
        
    // Interpolate
    double fraction = position - lowerIndex;
    return m_sortedData[lowerIndex] + fraction * (m_sortedData[upperIndex] - m_sortedData[lowerIndex]);
}

double CStatistics::Median()
{
    return Percentile(50.0);
}

Метод Percentile() вычисляет значение, ниже которого находится заданный процент наблюдений. Сначала он сортирует данные (если они еще не отсортированы), а затем использует линейную интерполяцию для нахождения точного значения процентиля. Метод Median() — это удобная функция, которая возвращает 50-й процентиль, представляя тем самым среднее значение набора данных.

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

После завершения работы над классом CStatistics у нас появился мощный набор инструментов для анализа данных о ценах и определения рыночных режимов. В следующем разделе мы на этой основе создадим класс Market Regime Detector (детектор рыночного режима).


Внедрение детектора рыночного режима

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

Составление перечня рыночных режимов

Сначала определим типы рыночных режимов, которые будет идентифицировать наша система. Создадим отдельный файл, который назовем MarketRegimeEnum.mqh, чтобы гарантировать доступность определения enum для всех компонентов нашей системы:

// Define market regime types
enum ENUM_MARKET_REGIME
{
    REGIME_TRENDING_UP = 0,    // Trending up regime
    REGIME_TRENDING_DOWN = 1,  // Trending down regime
    REGIME_RANGING = 2,        // Ranging/sideways regime
    REGIME_VOLATILE = 3,       // Volatile/chaotic regime
    REGIME_UNDEFINED = 4       // Undefined regime (default) 
};

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

Класс CMarketRegimeDetector

Класс детектора рыночных режимов (Market Regime Detector) объединяет наши статистические инструменты с логикой классификации режимов. Рассмотрим его структуру:

class CMarketRegimeDetector
{
private:
    // Configuration
    int         m_lookbackPeriod;       // Period for calculations
    int         m_smoothingPeriod;      // Period for smoothing regime transitions
    double      m_trendThreshold;       // Threshold for trend detection
    double      m_volatilityThreshold;  // Threshold for volatility detection
    
    // Data buffers
    double      m_priceData[];          // Price data buffer
    double      m_returns[];            // Returns data buffer
    double      m_volatility[];         // Volatility buffer
    double      m_trendStrength[];      // Trend strength buffer
    double      m_regimeBuffer[];       // Regime classification buffer
    
    // Statistics objects
    CStatistics m_priceStats;           // Statistics for price data
    CStatistics m_returnsStats;         // Statistics for returns data
    CStatistics m_volatilityStats;      // Statistics for volatility data
    
    // Current state
    ENUM_MARKET_REGIME m_currentRegime; // Current detected regime
    
    // Helper methods
    void        CalculateReturns();
    void        CalculateVolatility();
    void        CalculateTrendStrength();
    ENUM_MARKET_REGIME DetermineRegime();
    
public:
    // Constructor and destructor
    CMarketRegimeDetector(int lookbackPeriod = 100, int smoothingPeriod = 10);
    ~CMarketRegimeDetector();
    
    // Configuration methods
    void        SetLookbackPeriod(int period);
    void        SetSmoothingPeriod(int period);
    void        SetTrendThreshold(double threshold);
    void        SetVolatilityThreshold(double threshold);
    
    // Processing methods
    bool        Initialize();
    bool        ProcessData(const double &price[], int size);
    
    // Access methods
    ENUM_MARKET_REGIME GetCurrentRegime() const { return m_currentRegime; }
    string      GetRegimeDescription() const;
    double      GetTrendStrength() const;
    double      GetVolatility() const;
    
    // Buffer access for indicators
    bool        GetRegimeBuffer(double &buffer[]) const;
    bool        GetTrendStrengthBuffer(double &buffer[]) const;
    bool        GetVolatilityBuffer(double &buffer[]) const;
};

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

Конструктор и деструктор

Для начала реализуем конструктор и деструктор:

CMarketRegimeDetector::CMarketRegimeDetector(int lookbackPeriod, int smoothingPeriod)
{
    // Set default parameters
    m_lookbackPeriod = (lookbackPeriod > 20) ? lookbackPeriod : 100;
    m_smoothingPeriod = (smoothingPeriod > 0) ? smoothingPeriod : 10;
    m_trendThreshold = 0.2;
    m_volatilityThreshold = 1.5;
    
    // Initialize current regime
    m_currentRegime = REGIME_UNDEFINED;
    
    // Initialize buffers
    ArrayResize(m_priceData, m_lookbackPeriod);
    ArrayResize(m_returns, m_lookbackPeriod - 1);
    ArrayResize(m_volatility, m_lookbackPeriod - 1);
    ArrayResize(m_trendStrength, m_lookbackPeriod - 1);
    ArrayResize(m_regimeBuffer, m_lookbackPeriod);
    
    // Initialize buffers with zeros
    ArrayInitialize(m_priceData, 0.0);
    ArrayInitialize(m_returns, 0.0);
    ArrayInitialize(m_volatility, 0.0);
    ArrayInitialize(m_trendStrength, 0.0);
    ArrayInitialize(m_regimeBuffer, (double)REGIME_UNDEFINED);
}

CMarketRegimeDetector::~CMarketRegimeDetector()
{
    // Free memory (not strictly necessary in MQL5, but good practice)
    ArrayFree(m_priceData);
    ArrayFree(m_returns);
    ArrayFree(m_volatility);
    ArrayFree(m_trendStrength);
    ArrayFree(m_regimeBuffer);
}

Конструктор инициализирует все переменные членов класса и массивы значениями по умолчанию. Он включает проверку параметров, чтобы обеспечить размер периода ретроспективного анализа не менее 20 баров (для обеспечения статистической значимости), а также обеспечить, чтобы период сглаживания был положительным. Деструктор освобождает память, выделенную для массивов, что является хорошей практикой, даже несмотря на реализованную в MQL5 автоматической сборки мусора.

Методы конфигурирования

Далее реализуем методы конфигурирования, позволяющие пользователям настраивать поведение детектора:

void CMarketRegimeDetector::SetLookbackPeriod(int period)
{
    if(period <= 20)
        return;
        
    m_lookbackPeriod = period;
    
    // Resize buffers
    ArrayResize(m_priceData, m_lookbackPeriod);
    ArrayResize(m_returns, m_lookbackPeriod - 1);
    ArrayResize(m_volatility, m_lookbackPeriod - 1);
    ArrayResize(m_trendStrength, m_lookbackPeriod - 1);
    ArrayResize(m_regimeBuffer, m_lookbackPeriod);
    
    // Re-initialize
    Initialize();
}

void CMarketRegimeDetector::SetSmoothingPeriod(int period)
{
    if(period <= 0)
        return;
        
    m_smoothingPeriod = period;
}

void CMarketRegimeDetector::SetTrendThreshold(double threshold)
{
    if(threshold <= 0.0)
        return;
        
    m_trendThreshold = threshold;
}

void CMarketRegimeDetector::SetVolatilityThreshold(double threshold)
{
    if(threshold <= 0.0)
        return;
        
    m_volatilityThreshold = threshold;
}

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

Методы инициализации и обработки

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

bool CMarketRegimeDetector::Initialize()
{
    // Initialize buffers with zeros
    ArrayInitialize(m_priceData, 0.0);
    ArrayInitialize(m_returns, 0.0);
    ArrayInitialize(m_volatility, 0.0);
    ArrayInitialize(m_trendStrength, 0.0);
    ArrayInitialize(m_regimeBuffer, (double)REGIME_UNDEFINED);
    
    // Reset current regime
    m_currentRegime = REGIME_UNDEFINED;
    
    return true;
}

bool CMarketRegimeDetector::ProcessData(const double &price[], int size)
{
    if(size < m_lookbackPeriod)
        return false;
        
    // Copy the most recent price data
    for(int i = 0; i < m_lookbackPeriod; i++)
        m_priceData[i] = price[size - m_lookbackPeriod + i];
        
    // Calculate returns, volatility, and trend strength
    CalculateReturns();
    CalculateVolatility();
    CalculateTrendStrength();
    
    // Determine the current market regime
    m_currentRegime = DetermineRegime();
    
    // Update regime buffer for indicator display
    for(int i = 0; i < m_lookbackPeriod - 1; i++)
        m_regimeBuffer[i] = m_regimeBuffer[i + 1];
        
    m_regimeBuffer[m_lookbackPeriod - 1] = (double)m_currentRegime;
    
    return true;
}

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

Методы вычислений

Реализуем методы вычислений, которые рассчитывают статистические показатели, используемые для определения режима:

void CMarketRegimeDetector::CalculateReturns()
{
    for(int i = 0; i < m_lookbackPeriod - 1; i++)
    {
        // Calculate percentage returns
        if(m_priceData[i] != 0.0)
            m_returns[i] = (m_priceData[i + 1] - m_priceData[i]) / m_priceData[i] * 100.0;
        else
            m_returns[i] = 0.0;
    }
    
    // Update returns statistics
    m_returnsStats.SetData(m_returns, m_lookbackPeriod - 1);
}

void CMarketRegimeDetector::CalculateVolatility()
{
    // Use a rolling window for volatility calculation
    int windowSize = MathMin(20, m_lookbackPeriod - 1);
    
    for(int i = 0; i < m_lookbackPeriod - 1; i++)
    {
        if(i < windowSize - 1)
        {
            m_volatility[i] = 0.0;
            continue;
        }
        
        double sum = 0.0;
        double mean = 0.0;
        
        // Calculate mean
        for(int j = 0; j < windowSize; j++)
            mean += m_returns[i - j];
            
        mean /= windowSize;
        
        // Calculate standard deviation
        for(int j = 0; j < windowSize; j++)
            sum += MathPow(m_returns[i - j] - mean, 2);
            
        m_volatility[i] = MathSqrt(sum / (windowSize - 1));
    }
    
    // Update volatility statistics
    m_volatilityStats.SetData(m_volatility, m_lookbackPeriod - 1);
}

void CMarketRegimeDetector::CalculateTrendStrength()
{
    // Use a rolling window for trend strength calculation
    int windowSize = MathMin(50, m_lookbackPeriod - 1);
    
    for(int i = 0; i < m_lookbackPeriod - 1; i++)
    {
        if(i < windowSize - 1)
        {
            m_trendStrength[i] = 0.0;
            continue;
        }
        
        double window[];
        ArrayResize(window, windowSize);
        
        // Copy data to window
        for(int j = 0; j < windowSize; j++)
            window[j] = m_returns[i - j];
            
        // Create temporary statistics object
        CStatistics tempStats;
        tempStats.SetData(window, windowSize);
        
        // Calculate trend strength using autocorrelation
        m_trendStrength[i] = tempStats.TrendStrength();
    }
    
    // Update price statistics
    m_priceStats.SetData(m_priceData, m_lookbackPeriod);
}
Эти методы вычисляют основные статистические показатели, которые используются для определения режима:
  1. Метод CalculateReturns() вычисляет доходность в процентах на основе ценовых данных, которые больше подходят для статистического анализа, чем необработанные данные.
  2. Метод CalculateVolatility() использует подход на основе скользящего окна для расчета стандартного отклонения доходности в каждый момент времени, предоставляя показатель волатильности рынка.
  3. Метод CalculateTrendStrength() тоже использует подход на основе скользящего окна, но он создает временный объект CStatistics для каждого окна и использует метод TrendStrength() для вычисления силы тренда на основе автокорреляции.

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

Классификация режимов

Сердцем нашей системы является метод DetermineRegime(), который классифицирует текущее состояние рынка на основе статистических показателей:

ENUM_MARKET_REGIME CMarketRegimeDetector::DetermineRegime()
{
    // Get the latest values
    double latestTrendStrength = m_trendStrength[m_lookbackPeriod - 2];
    double latestVolatility = m_volatility[m_lookbackPeriod - 2];
    
    // Get the average volatility for comparison
    double avgVolatility = 0.0;
    int count = 0;
    
    for(int i = m_lookbackPeriod - 22; i < m_lookbackPeriod - 2; i++)
    {
        if(i >= 0)
        {
            avgVolatility += m_volatility[i];
            count++;
        }
    }
    
    if(count > 0)
        avgVolatility /= count;
    else
        avgVolatility = latestVolatility;
    
    // Determine price direction
    double priceChange = m_priceData[m_lookbackPeriod - 1] - m_priceData[m_lookbackPeriod - m_smoothingPeriod - 1];
    
    // Classify the regime
    if(latestVolatility > avgVolatility * m_volatilityThreshold)
    {
        // Highly volatile market
        return REGIME_VOLATILE;
    }
    else if(MathAbs(latestTrendStrength) > m_trendThreshold)
    {
        // Trending market
        if(priceChange > 0)
            return REGIME_TRENDING_UP;
        else
            return REGIME_TRENDING_DOWN;
    }
    else
    {
        // Ranging market
        return REGIME_RANGING;
    }
}
Этот метод реализует иерархический подход к классификации:
  1. Во-первых, он проверяет, характеризуется ли рынок высокой волатильностью, сравнивая последний показатель волатильности со средней волатильностью за последние 20 баров. Если волатильность превышает пороговое значение, рынок классифицируется как волатильный.
  2. Если рынок не волатильный, он проверяет наличие значимого тренда, сравнивая абсолютную силу тренда с пороговым значением тренда. При обнаружении тренда он определяет его направление (вверх или вниз) на основе изменения цены за период сглаживания.
  3. Если ни волатильность, ни тренд не обнаружены, рынок классифицируется как находящийся в состоянии флэта.

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

Методы доступа

Наконец, реализуем методы доступа, которые предоставляют информацию о текущем режиме рынка:

string CMarketRegimeDetector::GetRegimeDescription() const
{
    switch(m_currentRegime)
    {
        case REGIME_TRENDING_UP:
            return "Trending Up";
            
        case REGIME_TRENDING_DOWN:
            return "Trending Down";
            
        case REGIME_RANGING:
            return "Ranging";
            
        case REGIME_VOLATILE:
            return "Volatile";
            
        default:
            return "Undefined";
    }
}

double CMarketRegimeDetector::GetTrendStrength() const
{
    if(m_lookbackPeriod <= 2)
        return 0.0;
        
    return m_trendStrength[m_lookbackPeriod - 2];
}

double CMarketRegimeDetector::GetVolatility() const
{
    if(m_lookbackPeriod <= 2)
        return 0.0;
        
    return m_volatility[m_lookbackPeriod - 2];
}

bool CMarketRegimeDetector::GetRegimeBuffer(double &buffer[]) const
{
    if(ArraySize(buffer) < m_lookbackPeriod)
        ArrayResize(buffer, m_lookbackPeriod);
        
    for(int i = 0; i < m_lookbackPeriod; i++)
        buffer[i] = m_regimeBuffer[i];
        
    return true;
}

bool CMarketRegimeDetector::GetTrendStrengthBuffer(double &buffer[]) const
{
    int size = m_lookbackPeriod - 1;
    
    if(ArraySize(buffer) < size)
        ArrayResize(buffer, size);
        
    for(int i = 0; i < size; i++)
        buffer[i] = m_trendStrength[i];
        
    return true;
}

bool CMarketRegimeDetector::GetVolatilityBuffer(double &buffer[]) const
{
    int size = m_lookbackPeriod - 1;
    
    if(ArraySize(buffer) < size)
        ArrayResize(buffer, size);
        
    for(int i = 0; i < size; i++)
        buffer[i] = m_volatility[i];
        
    return true;
}
Эти методы обеспечивают доступ к текущему режиму и его характеристикам:
  1. Метод GetRegimeDescription() возвращает понятное пользователю описание текущего режима.
  2. Методы GetTrendStrength() и GetVolatility() возвращают последние значения силы и волатильности рынка.
  3. Методы GetRegimeBuffer(), GetTrendStrengthBuffer() и GetVolatilityBuffer() копируют внутренние буферы во внешние массивы, что полезно для отображения индикатора.

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


Создание пользовательского индикатора для визуализации режима

Теперь, когда у нас есть класс Market Regime Detector, создадим пользовательский индикатор, который визуализирует выявленные режимы непосредственно на ценовом графике. Это предоставит трейдерам интуитивно понятный способ отслеживать изменения режима и соответствующим образом адаптировать свои стратегии.

Индикатор MarketRegimeIndicator

Наш пользовательский индикатор будет отображать текущий рыночный режим, силу тренда и волатильность прямо на графике. Вот реализация:
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   3

// Include the Market Regime Detector
#include "MarketRegimeEnum.mqh"
#include "MarketRegimeDetector.mqh"

// Indicator input parameters
input int      LookbackPeriod = 100;       // Lookback period for calculations
input int      SmoothingPeriod = 10;       // Smoothing period for regime transitions
input double   TrendThreshold = 0.2;       // Threshold for trend detection (0.1-0.5) 
input double   VolatilityThreshold = 1.5;  // Threshold for volatility detection (1.0-3.0)

// Indicator buffers
double RegimeBuffer[];        // Buffer for regime classification
double TrendStrengthBuffer[]; // Buffer for trend strength
double VolatilityBuffer[];    // Buffer for volatility

// Global variables
CMarketRegimeDetector *Detector = NULL;
Индикатор использует для хранения и отображения различных аспектов рыночных режимов три буфера:
  1. RegimeBuffer — сохраняет числовое представление текущего режима
  2. TrendStrengthBuffer — сохраняет значения силы тренда
  3. VolatilityBuffer — сохраняет значения волатильности

Инициализация индикатора

Функция OnInit() настраивает буферы индикатора и создает детектор рыночного режима (Market Regime Detector):

int OnInit()
{
    // Set indicator buffers
    SetIndexBuffer(0, RegimeBuffer, INDICATOR_DATA);
    SetIndexBuffer(1, TrendStrengthBuffer, INDICATOR_DATA);
    SetIndexBuffer(2, VolatilityBuffer, INDICATOR_DATA);
    
    // Set indicator labels
    PlotIndexSetString(0, PLOT_LABEL, "Market Regime");
    PlotIndexSetString(1, PLOT_LABEL, "Trend Strength");
    PlotIndexSetString(2, PLOT_LABEL, "Volatility");
    
    // Set indicator styles
    PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
    PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_LINE);
    PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_LINE);
    
    // Set line colors
    PlotIndexSetInteger(1, PLOT_LINE_COLOR, clrBlue);
    PlotIndexSetInteger(2, PLOT_LINE_COLOR, clrRed);
    
    // Set line styles
    PlotIndexSetInteger(1, PLOT_LINE_STYLE, STYLE_SOLID);
    PlotIndexSetInteger(2, PLOT_LINE_STYLE, STYLE_SOLID);
    
    // Set line widths
    PlotIndexSetInteger(1, PLOT_LINE_WIDTH, 1);
    PlotIndexSetInteger(2, PLOT_LINE_WIDTH, 1);
    
    // Create and initialize the Market Regime Detector
    Detector = new CMarketRegimeDetector(LookbackPeriod, SmoothingPeriod);
    if(Detector == NULL)
    {
        Print("Failed to create Market Regime Detector");
        return INIT_FAILED;
    }
    
    // Configure the detector
    Detector.SetTrendThreshold(TrendThreshold);
    Detector.SetVolatilityThreshold(VolatilityThreshold);
    Detector.Initialize();
    
    // Set indicator name
    IndicatorSetString(INDICATOR_SHORTNAME, "Market Regime Detector");
    
    return INIT_SUCCEEDED;
}
Эта функция выполняет несколько важных задач:
  1. Привязывает буферы индикатора к соответствующим массивам
  2. Задает визуальные свойства индикатора (метки, стили, цвета)
  3. Создает и конфигурирует детектор рыночного режима параметрами, заданными пользователем

Использование функции SetIndexBuffer() и различных функций PlotIndexSetXXX() является стандартной практикой при разработке индикаторов на языке MQL5. С помощью этих функций настраивается отображение индикатора на графике.

Расчет индикатора

Функция OnCalculate() обрабатывает ценовые данные и обновляет буферы индикатора:

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[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
    // Check if there's enough data
    if(rates_total < LookbackPeriod)
        return 0;
    
    // Process data with the detector
    if(!Detector.ProcessData(close, rates_total))
    {
        Print("Failed to process data with Market Regime Detector");
        return 0;
    }
    
    // Get the regime buffer
    Detector.GetRegimeBuffer(RegimeBuffer);
    
    // Get the trend strength buffer
    Detector.GetTrendStrengthBuffer(TrendStrengthBuffer);
    
    // Get the volatility buffer
    Detector.GetVolatilityBuffer(VolatilityBuffer);
    
    // Display current regime in the chart corner
    string regimeText = "Current Market Regime: " + Detector.GetRegimeDescription();
    string trendText = "Trend Strength: " + DoubleToString(Detector.GetTrendStrength(), 4);
    string volatilityText = "Volatility: " + DoubleToString(Detector.GetVolatility(), 4);
    
    Comment(regimeText + "\n" + trendText + "\n" + volatilityText);
    
    // Return the number of calculated bars
    return rates_total;
}
Эта функция:
  1. Проверяет, достаточно ли данных для вычислений
  2. Обрабатывает ценовые данные с помощью детектора рыночных режимов
  3. Возвращает режим, силу тренда и буферы волатильности
  4. Отображает в углу графика информацию о текущем режиме
  5. Возвращает количество рассчитанных баров

Функция OnCalculate() вызывается платформой всякий раз, когда доступны новые данные о ценах, или при прокрутке графика. Она отвечает за обновление буферов индикатора, которые затем отображаются на графике.

Очистка индикатора

Функция OnDeinit() обеспечивает корректную очистку при удалении индикатора:

void OnDeinit(const int reason)
{
    // Clean up
    if(Detector != NULL)
    {
        delete Detector;
        Detector = NULL;
    }
    
    // Clear the comment
    Comment("");
}

Эта функция удаляет объект Market Regime Detector, чтобы предотвратить утечки памяти, и очищает график от всех комментариев. Правильная очистка играет важную роль в программировании на языке MQL5, поскольку она позволяет гарантировать освобождение ресурсов, когда они больше не нужны.

Интерпретация индикатора

При использовании индикатора рыночного режима трейдерам следует обратить внимание на следующее:
  1. Линия режима. Эта линия представляет текущий рыночный режим. Числовые значения соответствуют различным режимам:
    • 0: Растущий тренд
    • 1: Нисходящий тренд
    • 2: Флэтовый рынок
    • 3: Волатильный рынок
    • 4: Режим не определен
  2. Линия силы тренда. Эта синяя линия показывает силу тренда. Более высокие положительные значения указывают на более сильные восходящие тренды, тогда как более низкие отрицательные значения указывают на более сильные нисходящие тренды. Значения, близкие к нулю, указывают на слабый тренд или его отсутствие.
  3. Линия волатильности. Эта красная линия показывает текущий уровень волатильности. Пики на этой линии часто предшествуют смене режима и могут сигнализировать о потенциальных торговых возможностях или рисках.
  4. Комментарий к графику. Индикатор отображает текущий режим, силу тренда и значения волатильности в верхнем левом углу графика в целях облегчения поиска.

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


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


Заключение

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

Путь от проблемы к решению

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

Нашим решением этой проблемы стало создание с нуля надежной системы определения рыночного режима (Market Regime Detection System). Мы начали с создания прочной статистической основы, внедрив такие ключевые показатели, как автокорреляция и волатильность, с помощью которых можно объективно классифицировать поведение рынка. Затем мы разработали комплексный класс детектора рыночных режимов (Market Regime Detector), который использует эти статистические показатели для выявления условий, характерных для трендового рынка, для флэтового рынка и для волатильного рынка.

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

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


Обзор файлов

Вот сводка всех файлов, созданных в рамках этой статьи:
Название файла Описание
MarketRegimeEnum.mqh
Определяет типы перечислений рыночных режимов, используемые во всей системе
CStatistics.mqh Класс статистических расчетов для определения рыночных режимов
MarketRegimeDetector.mqh Реализация определения основного рыночного режима
MarketRegimeIndicator.mq5 Пользовательский индикатор для визуализации режимов на графиках

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

Прикрепленные файлы |
CStatistics.mqh (9.28 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (5)
Robert Angers
Robert Angers | 27 апр. 2025 в 21:12
Ваш код не компилируется.... отсутствует IsStrongSignal(value) ...
Sahil Bagdi
Sahil Bagdi | 28 апр. 2025 в 06:19
Robert Angers #:
Ваш код не компилируется.... отсутствует IsStrongSignal(value) ...

На какой файл вы ссылаетесь?

Rau Heru
Rau Heru | 21 мая 2025 в 12:48

При попытке скомпилировать индикатор рыночного режима возникает 24 ошибки и 1 предупреждение:

'MarketRegimeIndicator.mq5' 1

файл 'C:\Users\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\Include\MarketRegimeEnum.mqh' не найден MarketRegimeIndicator.mq5 14 11

файл 'C:\Users\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\Include\MarketRegimeDetector.mqh' не найден MarketRegimeIndicator.mq5 15 11

'CMarketRegimeDetector' - неожиданная лексема, возможно, отсутствует тип? MarketRegimeIndicator.mq5 29 1

'*' - ожидается точка с запятой MarketRegimeIndicator.mq5 29 23

'Detector' - необъявленный идентификатор MarketRegimeIndicator.mq5 64 5

'CMarketRegimeDetector' - объявление без типа MarketRegimeIndicator.mq5 64 20

'CMarketRegimeDetector' - ожидается тип класса MarketRegimeIndicator.mq5 64 20

функция не определена MarketRegimeIndicator.mq5 64 20

'new' - выражение типа 'void' недопустимо MarketRegimeIndicator.mq5 64 16

'=' - использование недопустимой операции MarketRegimeIndicator.mq5 64 14

'Detector' - необъявленный идентификатор MarketRegimeIndicator.mq5 65 8

'==' - использование недопустимой операции MarketRegimeIndicator.mq5 65 17

'Detector' - необъявленный идентификатор MarketRegimeIndicator.mq5 72 5

'Detector' - незадекларированный идентификатор MarketRegimeIndicator.mq5 73 5

'Detector' - незадекларированный идентификатор MarketRegimeIndicator.mq5 74 5

'Detector' - незаявленный идентификатор MarketRegimeIndicator.mq5 101 9

';' - неожиданная лексема MarketRegimeIndicator.mq5 103 68

'(' - несбалансированная левая скобка MarketRegimeIndicator.mq5 101 7

найдено пустое управляемое утверждение MarketRegimeIndicator.mq5 103 68

'Detector' - необъявленный идентификатор MarketRegimeIndicator.mq5 133 8

'!=' - использование недопустимой операции MarketRegimeIndicator.mq5 133 17

'Detector' - необъявленный идентификатор MarketRegimeIndicator.mq5 135 16

'Detector' - ожидается указатель объекта MarketRegimeIndicator.mq5 135 16

'Detector' - необъявленный идентификатор MarketRegimeIndicator.mq5 136 9

'=' - недопустимое использование операции MarketRegimeIndicator.mq5 136 18

24 ошибки, 1 предупреждение 25 2


Rashid Umarov
Rashid Umarov | 21 мая 2025 в 13:02
Rau Heru #:

При попытке скомпилировать индикатор рыночного режима возникает 24 ошибки и 1 предупреждение:

'MarketRegimeIndicator.mq5' 1

файл 'C:\Users\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\Include\MarketRegimeEnum.mqh' не найден MarketRegimeIndicator.mq5 14 11

файл 'C:\Users\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\Include\MarketRegimeDetector.mqh' не найден MarketRegimeIndicator.mq5 15 11

Индикатор ищет эти файлы в папке C:\Users\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\Include\

#property copyright "Sahil Bagdi"
#property link      "https://www.mql5.com/ru/users/sahilbagdi"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   3

// Включить детектор рыночного режима
#include <MarketRegimeEnum.mqh>
#include <MarketRegimeDetector.mqh>
Yoshiteru Taneda
Yoshiteru Taneda | 17 июл. 2025 в 10:56
Sahil Bagdi #:

Какой файл вы имеете в виду?

MarketRegimeDetector.mqh

в строке 472

Я предполагаю, что вы имеете в виду

'IsStrongSignal' - необъявленный идентификатор MarketRegimeDetector.mqh 472 16

'strategySignal' - ожидается какой-то оператор MarketRegimeDetector.mqh 472 31

Алгоритм Бизона — Bison Algorithm (BIA) Алгоритм Бизона — Bison Algorithm (BIA)
Новый оптимизационный метод Bison Algorithm (BIA) — две стратегии, заимствованные из поведения бизонов, для непрерывных задач с одной целевой функцией. Ключевыми особенностями BIA являются два основополагающих принципа, заимствованных из поведения бизонов, это способность к динамичному перемещению и оборонительная стратегия.
Символьное уравнение прогнозирования цены с использованием SymPy Символьное уравнение прогнозирования цены с использованием SymPy
Статья описывает интересный подход к алготрейдингу, основанный на символьных математических уравнениях вместо традиционных "черных ящиков" машинного обучения. Автор показывает, как преобразовать непрозрачные нейросети в читаемые математические формулы через библиотеку SymPy и полиномиальную регрессию, что позволяет полностью понимать логику принятия торговых решений. Подход сочетает вычислительную мощь ML с прозрачностью классических методов, давая трейдеру возможность анализировать, корректировать и адаптировать модели в реальном времени.
Искусство ведения логов (Часть 3): Изучение обработчиков для сохранения логов Искусство ведения логов (Часть 3): Изучение обработчиков для сохранения логов
В этой статье мы разберем концепцию обработчиков в библиотеке логирования, поймем их работу, и создадим три начальные реализации: консоль, база данных и файл. Мы рассмотрим все: от базовой структуры обработчиков до практического тестирования, заложив основу для их дальнейшей полноценной реализации.
Скрытые марковские модели для прогнозирования волатильности с учетом тренда Скрытые марковские модели для прогнозирования волатильности с учетом тренда
Скрытые марковские модели (СММ) — это мощный статистический инструмент, позволяющий выявлять скрытые состояния рынка на основе анализа наблюдаемых ценовых движений. В трейдинге СММ позволяют улучшить прогнозирование волатильности и применяются при разработке трендовых стратегий, моделируя изменения рыночных режимов. В этой статье мы представим пошаговый процесс разработки стратегии следования за трендом, которая использует СММ в качестве фильтра для прогнозирования волатильности.