English Русский 中文 Deutsch 日本語
preview
Creación de un sistema personalizado de detección de regímenes de mercado en MQL5 (Parte 1): Indicador

Creación de un sistema personalizado de detección de regímenes de mercado en MQL5 (Parte 1): Indicador

MetaTrader 5Trading |
24 5
Sahil Bagdi
Sahil Bagdi
  1. Introducción
  2. Comprensión de los regímenes de mercado
  3. Construyendo la base estadística
  4. Implementación del detector de régimen de mercado
  5. Creación de un indicador personalizado para la visualización del régimen
  6. Conclusión


Introducción

Los mercados financieros se encuentran en un estado constante de cambio, transitando períodos de fuertes tendencias, consolidación lateral y volatilidad caótica. Para los traders algorítmicos, esto representa un desafío importante: una estrategia que funciona excepcionalmente bien en mercados con tendencias a menudo fracasa miserablemente en condiciones de rango, mientras que los enfoques diseñados para baja volatilidad pueden hacer estallar las cuentas cuando la volatilidad aumenta. A pesar de esta realidad, la mayoría de los sistemas comerciales se construyen con el supuesto implícito de que el comportamiento del mercado se mantiene constante a lo largo del tiempo.

Esta desconexión fundamental entre la realidad del mercado y el diseño del sistema comercial conduce al patrón demasiado familiar de degradación del rendimiento de la estrategia. Un sistema funciona brillantemente durante las pruebas retrospectivas y la implementación inicial, solo para fallar cuando las condiciones del mercado inevitablemente cambian. El comerciante se enfrenta entonces a una difícil elección: abandonar la estrategia y empezar de nuevo, o soportar caídas mientras espera que las condiciones del mercado vuelvan a favorecer su enfoque.

¿Y si hubiera una manera mejor? ¿Qué pasaría si su sistema de trading pudiera identificar objetivamente el régimen actual del mercado y adaptar su estrategia en consecuencia? Esto es precisamente lo que construiremos en este artículo: un sistema integral de detección de regímenes de mercado en MQL5 que puede clasificar las condiciones del mercado en regímenes distintos y proporcionar un marco para estrategias comerciales adaptativas.

Al final de esta serie de artículos, tendrá una implementación completa de un Sistema de detección de régimen de mercado que incluye:
  1. Una base estadística sólida para la clasificación objetiva del mercado.
  2. Una clase de detector de régimen de mercado personalizada que identifica condiciones de mercado de tendencia, rango y volatilidad.
  3. Un indicador personalizado que visualiza los cambios de régimen directamente en sus gráficos.
  4. Un Asesor Experto adaptativo que selecciona automáticamente estrategias apropiadas según el régimen actual (Parte 2).
  5. Ejemplos prácticos de cómo implementar y optimizar el sistema para sus necesidades comerciales específicas (Parte 2).

Ya sea que sea un comerciante algorítmico experimentado que busca mejorar sus sistemas existentes o un recién llegado que busca construir estrategias más sólidas desde el principio, este sistema de detección de régimen de mercado le proporcionará herramientas poderosas para navegar por el panorama en constante cambio de los mercados financieros.


Comprensión de los regímenes de mercado

Antes de profundizar en los detalles de implementación, es fundamental comprender qué son los regímenes de mercado y por qué son importantes para los comerciantes. Los mercados no se comportan de manera uniforme a lo largo del tiempo; más bien, transitan entre distintos estados de comportamiento o "regímenes". Estos regímenes influyen significativamente en la fluctuación de los precios y, en consecuencia, en el rendimiento de las estrategias de trading.

¿Qué son los regímenes de mercado?

Los regímenes de mercado son patrones distintos de comportamiento del mercado caracterizados por propiedades estadísticas específicas de los movimientos de precios. Si bien existen varias formas de clasificar los regímenes de mercado, nos centraremos en tres tipos principales que son los más relevantes para el desarrollo de estrategias comerciales:
  1. Regímenes de tendencia: Los mercados exhiben un fuerte movimiento direccional con una reversión a la media mínima. El precio tiende a realizar movimientos consistentes en una dirección con retrocesos superficiales. Estadísticamente, los mercados en tendencia muestran una autocorrelación positiva en los retornos, lo que significa que es probable que los movimientos de precios en una dirección sean seguidos por movimientos en la misma dirección.
  2. Regímenes de alcance: Los mercados oscilan entre niveles de soporte y resistencia con fuertes tendencias de reversión a la media. El precio tiende a rebotar entre límites definidos en lugar de dispararse en cualquier dirección. Estadísticamente, los mercados con rangos muestran una autocorrelación negativa en los retornos, lo que significa que es probable que los movimientos ascendentes sean seguidos por movimientos descendentes y viceversa.
  3. Regímenes volátiles: Los mercados experimentan movimientos de precios grandes y erráticos con una dirección poco clara. Estos regímenes suelen ocurrir durante períodos de incertidumbre, acontecimientos noticiosos o tensión en el mercado. Estadísticamente, los regímenes volátiles muestran una alta desviación estándar en los retornos con patrones de autocorrelación impredecibles.

Comprender en qué régimen se encuentra actualmente el mercado proporciona un contexto crucial para las decisiones comerciales. Una estrategia optimizada para mercados con tendencias probablemente tendrá un desempeño deficiente en condiciones de rango, mientras que las estrategias de reversión a la media diseñadas para mercados con tendencias pueden ser desastrosas durante tendencias fuertes.

¿Por qué los indicadores tradicionales fallan?

La mayoría de los indicadores técnicos fueron diseñados para identificar patrones o condiciones de precios específicos en lugar de clasificar regímenes de mercado. Por ejemplo:
  • Los promedios móviles y el MACD pueden ayudar a identificar tendencias, pero no distinguen entre regímenes de tendencia y volátiles.
  • Los osciladores RSI y estocásticos funcionan bien en mercados con movimientos en rango, pero generan señales falsas en condiciones de tendencia.
  • Las Bandas de Bollinger se adaptan a la volatilidad pero no identifican explícitamente las transiciones de régimen.
Estas limitaciones crean una brecha importante en la mayoría de los sistemas comerciales. Sin conocer el régimen actual del mercado, los traders básicamente aplican estrategias a ciegas, esperando que las condiciones del mercado coincidan con los supuestos de su estrategia.

Fundamentos estadísticos de la detección de regímenes

Para construir un sistema eficaz de detección de regímenes, necesitamos aprovechar medidas estadísticas que puedan clasificar objetivamente el comportamiento del mercado. Los conceptos estadísticos clave que utilizaremos incluyen:
  1. Autocorrelación: Mide la correlación entre una serie temporal y una versión rezagada de la misma. La autocorrelación positiva indica un comportamiento de tendencia, mientras que la autocorrelación negativa sugiere un comportamiento de reversión a la media (rango).
  2. Volatilidad: Mide la dispersión de los rendimientos, normalmente utilizando la desviación estándar. Los aumentos repentinos de la volatilidad a menudo indican cambios de régimen.
  3. Fuerza de la tendencia: Se puede cuantificar utilizando varios métodos, incluido el valor absoluto de autocorrelación, la pendiente de la regresión lineal o indicadores especializados como ADX.

Al combinar estas medidas estadísticas, podemos crear un marco sólido para clasificar los regímenes de mercado de manera objetiva. En la siguiente sección, implementaremos estos conceptos en el código MQL5 para construir nuestro sistema de detección de régimen de mercado.


Construyendo la base estadística

En esta sección, implementaremos los componentes estadísticos principales necesarios para nuestro sistema de detección de régimen de mercado. Crearemos una clase CStatistics robusta que manejará todos los cálculos matemáticos necesarios para la clasificación del régimen.

La clase CStatistics

La base de nuestro sistema de detección de regímenes es una poderosa clase de estadísticas que puede realizar varios cálculos sobre datos de precios. Examinemos los componentes clave de esta clase:

//+------------------------------------------------------------------+
//| 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();
};

Esta clase proporciona un conjunto completo de funciones estadísticas que nos permitirán analizar datos de precios y determinar el régimen actual del mercado. Veamos algunos de los métodos clave en detalle.

Constructor y Destructor

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

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

El constructor y el destructor ayudan a inicializar y desinicializar la clase. El constructor inicializa las variables miembro y los arrays, mientras que el destructor garantiza una limpieza adecuada mediante la llamada al método Clear(). Este patrón de inicialización y limpieza adecuados es esencial en MQL5 para evitar pérdidas de memoria y garantizar un funcionamiento confiable.

Métodos de gestión de datos


A continuación, implementemos los métodos de gestión de datos que nos permiten configurar, agregar y borrar datos:

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;
}
                        

El método SetData() nos permite reemplazar todo el conjunto de datos con una nueva matriz, lo cual es útil al procesar datos de precios históricos. El método AddData() agrega un único valor a los datos existentes, lo que resulta útil para actualizaciones incrementales a medida que hay nuevos datos de precios disponibles. El método Clear() restablece el objeto a su estado inicial, liberando cualquier memoria asignada.

Observe cómo establecemos m_isSorted = false siempre que los datos cambian. Esta bandera nos ayuda a optimizar el rendimiento al ordenar los datos solo cuando es necesario para los cálculos de percentiles.

Métodos estadísticos básicos

Ahora, implementemos los métodos estadísticos básicos para calcular la media, la desviación estándar y la varianza:

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;
}

Estos métodos implementan fórmulas estadísticas estándar. El método Mean() calcula el promedio de todos los puntos de datos. El método StandardDeviation() mide la dispersión de los puntos de datos alrededor de la media, lo que es crucial para identificar regímenes de mercado volátiles. El método Variance() devuelve el cuadrado de la desviación estándar, proporcionando otra medida de dispersión de datos.

Observe cómo manejamos casos extremos, como conjuntos de datos vacíos o puntos de datos individuales, devolviendo cero. Este enfoque de programación defensiva evita errores cuando se trabaja con datos insuficientes.

Métodos de rango y extremos

//+------------------------------------------------------------------+
//| 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();
}
                            

Estos métodos proporcionan información adicional sobre la distribución de datos. Los métodos Min() y Max() encuentran los valores más pequeños y más grandes en el conjunto de datos, mientras que el método Range() calcula la diferencia entre ellos. Estas medidas pueden ser útiles para identificar límites de precios en mercados con cambios de precios.

Métodos específicos de series de tiempo

Ahora, implementemos los métodos específicos de series de tiempo que son cruciales para la detección del régimen:

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;
}

El método Autocorrelation() calcula la correlación entre la serie de datos y una versión rezagada de sí misma. Esta es una medida poderosa para distinguir entre mercados en tendencia y mercados en rango. La autocorrelación positiva (valores mayores que cero) indica un comportamiento de tendencia, mientras que la autocorrelación negativa (valores menores que cero) sugiere un comportamiento de reversión a la media o de rango.

El método TrendStrength() utiliza la autocorrelación de retardo 1 como medida directa de la fuerza de la tendencia. Los valores positivos más altos indican tendencias más fuertes. El método MeanReversionStrength() devuelve el negativo de la autocorrelación, por lo que los valores positivos indican tendencias de reversión a la media más fuertes.

Estos métodos forman la columna vertebral estadística de nuestro sistema de detección de regímenes y proporcionan medidas objetivas del comportamiento del mercado que utilizaremos para clasificar los regímenes.

Cálculos de percentiles

Por último, implementemos métodos para calcular percentiles y la media:

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);
}

El método Percentile() calcula el valor por debajo del cual cae un porcentaje determinado de observaciones. Primero ordena los datos (si aún no están ordenados) y luego utiliza la interpolación lineal para encontrar el valor percentil preciso. El método Median() es una función de conveniencia que devuelve el percentil 50, que representa el valor medio del conjunto de datos.

Tenga en cuenta la optimización con el indicador m_isSorted, que garantiza que solo ordenemos los datos una vez, incluso si calculamos múltiples percentiles. Este es un ejemplo de cómo una implementación cuidadosa puede mejorar el rendimiento en el código MQL5.

Con nuestra clase de CStatistics completada, ahora tenemos un poderoso conjunto de herramientas para analizar datos de precios y detectar regímenes de mercado. En la siguiente sección, nos basaremos en esta base para crear la clase Detector de régimen de mercado.


Implementación del detector de régimen de mercado

Ahora que tenemos nuestra base estadística en su lugar, podemos construir el componente central de nuestro sistema: el detector de régimen de mercado. Esta clase utilizará las medidas estadísticas que hemos implementado para clasificar las condiciones del mercado en regímenes específicos.

Enumeración del régimen de mercado

Primero, definamos los tipos de régimen de mercado que nuestro sistema identificará. Crearemos un archivo separado llamado MarketRegimeEnum.mqh para garantizar que la definición de enumeración esté disponible para todos los componentes de nuestro sistema:

// 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) 
};

Esta enumeración define los cinco posibles regímenes de mercado que nuestro sistema puede detectar. Utilizaremos estos valores a lo largo de nuestra implementación para representar el estado actual del mercado.

La clase CMarketRegimeDetector

La clase Detector de régimen de mercado combina nuestras herramientas estadísticas con la lógica de clasificación de regímenes. Examinemos su estructura:

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;
};

Esta clase encapsula toda la funcionalidad necesaria para detectar regímenes de mercado. Implementemos cada método en detalle.

Constructor y Destructor

Primero, implementemos el constructor y el destructor:

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);
}

El constructor inicializa todas las variables miembro y matrices con valores predeterminados. Incluye validación de parámetros para garantizar que el período de retrospección sea de al menos 20 barras (para significancia estadística) y que el período de suavizado sea positivo. El destructor libera la memoria asignada para las matrices, lo que es una buena práctica incluso aunque MQL5 tenga recolección de basura automática.

Métodos de configuración

A continuación, implementemos los métodos de configuración que permiten a los usuarios personalizar el comportamiento del detector:

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;
}

Estos métodos permiten a los usuarios personalizar los parámetros del detector para adaptarlos a sus instrumentos comerciales y marcos temporales específicos. El método SetLookbackPeriod() es particularmente importante ya que redimensiona todos los buffers internos para que coincidan con el nuevo período. Los otros métodos simplemente actualizan los parámetros correspondientes después de validar los valores de entrada.

Métodos de inicialización y procesamiento

Ahora, implementemos los métodos de inicialización y procesamiento de datos:

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;
}

El método Initialize() restablece todos los buffers y el régimen actual a sus valores predeterminados. El método ProcessData() es el corazón del detector, procesa nuevos datos de precios y actualiza la clasificación del régimen. Primero copia los datos de precios más recientes, luego calcula los rendimientos, la volatilidad y la fuerza de la tendencia y, finalmente, determina el régimen actual del mercado. También actualiza el buffer de régimen para la visualización del indicador, cambiando los valores para dejar espacio para el nuevo régimen.

Métodos de cálculo

Implementemos los métodos de cálculo que calculan las medidas estadísticas utilizadas para la detección del régimen:

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);
}
Estos métodos calculan las medidas estadísticas clave utilizadas para la detección del régimen:
  1. CalculateReturns() calcula retornos porcentuales a partir de los datos de precios, que son más adecuados para el análisis estadístico que los precios brutos.
  2. CalculateVolatility() utiliza un enfoque de ventana móvil para calcular la desviación estándar de los rendimientos en cada punto del tiempo, proporcionando una medida de la volatilidad del mercado.
  3. CalculateTrendStrength() también utiliza un enfoque de ventana móvil, pero crea un objeto CStatistics temporal para cada ventana y utiliza su método TrendStrength() para calcular la fuerza de la tendencia basada en la autocorrelación.

Estos cálculos de ventana móvil proporcionan una evaluación más precisa y ágil de las condiciones del mercado que el uso de todo el período retrospectivo para cada cálculo.

Clasificación del régimen

El corazón de nuestro sistema es el método DetermineRegime(), que clasifica el estado actual del mercado basándose en medidas estadísticas:

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;
    }
}
Este método implementa un enfoque de clasificación jerárquica:
  1. En primer lugar, verifica si el mercado es altamente volátil comparando la volatilidad más reciente con la volatilidad promedio de las últimas 20 barras. Si la volatilidad supera el umbral, el mercado se clasifica como volátil.
  2. Si el mercado no es volátil, verifica si hay una tendencia significativa comparando la fuerza absoluta de la tendencia con el umbral de tendencia. Si se detecta una tendencia, se determina la dirección (hacia arriba o hacia abajo) en función del cambio de precio durante el período de suavizado.
  3. Si no se detecta ni volatilidad ni tendencia, el mercado se clasifica como en rango.

Este enfoque jerárquico garantiza que la volatilidad tenga prioridad sobre la detección de tendencias, ya que las estrategias de seguimiento de tendencias son particularmente vulnerables en mercados volátiles.

Métodos de acceso

Por último, implementemos los métodos de acceso que proporcionan información sobre el régimen actual del mercado:

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;
}
Estos métodos permiten acceder al régimen actual y sus características:
  1. GetRegimeDescription() devuelve una descripción legible por humanos del régimen actual.
  2. GetTrendStrength() y GetVolatility() devuelven los últimos valores de fuerza de tendencia y volatilidad.
  3. GetRegimeBuffer(), GetTrendStrengthBuffer() y GetVolatilityBuffer() copian los buffers internos a matrices externas, lo que resulta útil para la visualización de indicadores.

Con nuestra clase CMarketRegimeDetector completa, ahora tenemos una herramienta poderosa para detectar regímenes de mercado. En la siguiente sección, crearemos un indicador personalizado que visualice estos regímenes directamente en el gráfico de precios.


Creación de un indicador personalizado para la visualización del régimen

Ahora que tenemos nuestra clase detector de régimen de mercado, creemos un indicador personalizado que visualice los regímenes detectados directamente en el gráfico de precios. Esto proporcionará a los operadores una forma intuitiva de ver los cambios de régimen y adaptar sus estrategias en consecuencia.

El indicador de régimen de mercado

Nuestro indicador personalizado mostrará el régimen actual del mercado, la fuerza de la tendencia y la volatilidad directamente en el gráfico. Aquí está la implementación:
#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;
El indicador utiliza tres buffers para almacenar y mostrar diferentes aspectos de los regímenes de mercado:
  1. RegimeBuffer: Almacena la representación numérica del régimen actual.
  2. TrendStrengthBuffer: Almacena los valores de fuerza de la tendencia.
  3. VolatilityBuffer: Almacena los valores de volatilidad.

Inicialización del indicador

La función OnInit() configura los buffers del indicador y crea el detector de régimen de mercado:

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;
}
Esta función realiza varias tareas importantes:
  1. Vincula los buffers indicadores a las matrices correspondientes.
  2. Establece las propiedades visuales del indicador (etiquetas, estilos, colores).
  3. Crea y configura el detector de régimen de mercado con los parámetros especificados por el usuario.

El uso de SetIndexBuffer() y varias funciones PlotIndexSetXXX() es una práctica estándar en el desarrollo de indicadores MQL5. Estas funciones configuran cómo se mostrará el indicador en el gráfico.

Cálculo del indicador

La función OnCalculate() procesa los datos de precios y actualiza los buffers del indicador:

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;
}
Esta función:
  1. Comprueba si hay suficientes datos para el cálculo.
  2. Procesa los datos de precios con el detector de régimen de mercado
  3. Recupera el régimen, la fuerza de la tendencia y los amortiguadores de volatilidad.
  4. Muestra la información del régimen actual en la esquina del gráfico.
  5. Devuelve el número de barras calculadas

La plataforma llama a la función OnCalculate() siempre que haya nuevos datos de precios disponibles o cuando se desplaza el gráfico. Es responsable de actualizar los buffers del indicador, que luego se muestran en el gráfico.

Limpieza de indicadores

La función OnDeinit() garantiza una limpieza adecuada cuando se elimina el indicador:

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

Esta función elimina el objeto Detector de régimen de mercado para evitar pérdidas de memoria y borra todos los comentarios del gráfico. Una limpieza adecuada es esencial en la programación MQL5 para garantizar que los recursos se liberen cuando ya no sean necesarios.

Interpretación del indicador

Al utilizar el indicador de régimen de mercado, los operadores deben prestar atención a lo siguiente:
  1. Línea de régimen: Esta línea representa el régimen actual del mercado. Los valores numéricos corresponden a diferentes regímenes:
    • 0: Tendencia al alza
    • 1: Tendencia a la baja
    • 2: Rango
    • 3: Volatilidad
    • 4: Indefinido
  2. Línea de fuerza de tendencia: Esta línea azul muestra la fuerza de la tendencia. Los valores positivos más altos indican tendencias alcistas más fuertes, mientras que los valores negativos más bajos indican tendencias bajistas más fuertes. Los valores cercanos a cero sugieren una tendencia débil o nula.
  3. Línea de volatilidad: Esta línea roja muestra el nivel de volatilidad actual. Los picos en esta línea a menudo preceden cambios de régimen y pueden indicar posibles oportunidades o riesgos comerciales.
  4. Comentario del gráfico: El indicador muestra el régimen actual, la fuerza de la tendencia y los valores de volatilidad en la esquina superior izquierda del gráfico para una fácil referencia.

Al monitorear estos elementos, los operadores pueden identificar rápidamente el régimen actual del mercado y ajustar sus estrategias en consecuencia. Por ejemplo, se deben emplear estrategias de seguimiento de tendencias durante regímenes de tendencias, mientras que las estrategias de reversión a la media son más apropiadas durante regímenes de rango. Durante regímenes volátiles, los traders podrían considerar reducir el tamaño de sus posiciones o mantenerse fuera del mercado por completo.


Aquí es donde podemos ver claramente que el mercado actual está oscilando, como también podemos observar claramente en el gráfico.


Conclusión

A lo largo de este artículo, nos hemos embarcado en un viaje para resolver uno de los problemas más desafiantes en el trading algorítmico: la adaptación a las condiciones cambiantes del mercado. Comenzamos reconociendo que los mercados no se comportan de manera uniforme a lo largo del tiempo, sino que transitan entre distintos estados de comportamiento o "regímenes". Esta perspectiva nos llevó a desarrollar un Sistema Integral de Detección de Regímenes de Mercado que puede identificar estas transiciones. En la siguiente sección, veremos cómo adaptar las estrategias de trading según nuestra detección de los regímenes.

El viaje del problema a la solución

Cuando comenzamos, identificamos una brecha crítica en la mayoría de los sistemas comerciales: la incapacidad de clasificar objetivamente las condiciones del mercado y adaptarnos a ellas. Los indicadores y estrategias tradicionales suelen estar optimizados para condiciones específicas del mercado, lo que genera un rendimiento inconsistente a medida que los mercados evolucionan. Este es el problema al que se enfrentan los traders a diario: las estrategias que funcionan brillantemente en un entorno de mercado pueden fallar espectacularmente en otro.

Nuestra solución a este problema fue construir un sistema de detección del régimen de mercado sólido desde cero. Comenzamos con una base estadística sólida, implementando medidas clave como la autocorrelación y la volatilidad que pueden clasificar objetivamente el comportamiento del mercado. Luego desarrollamos una clase integral de Detector de régimen de mercado que utiliza estas medidas estadísticas para identificar condiciones de mercado con tendencias, rangos y volatilidad.

Finalmente, para que este sistema sea práctico y accesible, creamos un indicador personalizado que visualiza los cambios de régimen directamente en el gráfico de precios, brindando a los operadores retroalimentación visual inmediata sobre las condiciones actuales del mercado. Luego demostramos cómo construir un Asesor Experto adaptativo que selecciona y aplica automáticamente diferentes estrategias comerciales según el régimen detectado.

Ahora, en la siguiente parte del artículo, exploraremos consideraciones prácticas para implementar y optimizar el sistema, incluida la optimización de parámetros, el manejo de la transición de régimen y la integración con los sistemas comerciales existentes. Estos conocimientos prácticos le ayudarán a implementar el Sistema de detección del régimen de mercado de forma eficaz en sus propias operaciones de forma automática. Mientras tanto, juega con el enfoque manual del indicador por ahora.


Descripción general del archivo

Aquí hay un resumen de todos los archivos creados en este artículo:
Nombre del archivo Descripción
MarketRegimeEnum.mqh
Define los tipos de enumeración del régimen de mercado utilizados en todo el sistema.
CStatistics.mqh Clase de cálculos estadísticos para la detección del régimen de mercado.
MarketRegimeDetector.mqh Implementación de la detección del régimen central del mercado.
MarketRegimeIndicator.mq5 Indicador personalizado para visualizar regímenes en gráficos.

Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/17737

Robert Angers
Robert Angers | 27 abr 2025 en 21:12
Su código no compila.... falta IsStrongSignal(valor) ...
Sahil Bagdi
Sahil Bagdi | 28 abr 2025 en 06:19
Robert Angers #:
Tu código no compila.... falta IsStrongSignal(valor) ...

¿A qué archivo se refiere?

Rau Heru
Rau Heru | 21 may 2025 en 12:48

El indicador de régimen de mercado tiene 24 errores y 1 advertencia cuando intento compilar.:

'MarketRegimeIndicator.mq5' 1

file 'C:\Users\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\IncludeMarketRegimeEnum.mqh' not found MarketRegimeIndicator.mq5 14 11

archivo 'C:\sers\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\IncludeMarketRegimeDetector.mqh' no encontrado MarketRegimeIndicator.mq5 15 11

CMarketRegimeDetector' - token inesperado, probablemente falta el tipo MarketRegimeIndicator.mq5 29 1

'*' - punto y coma esperado MarketRegimeIndicator.mq5 29 23

Detector" - identificador no declarado MarketRegimeIndicator.mq5 64 5

CMarketRegimeDetector" - declaración sin tipo MarketRegimeIndicator.mq5 64 20

CMarketRegimeDetector' - tipo de clase esperado MarketRegimeIndicator.mq5 64 20

función no definida MarketRegimeIndicator.mq5 64 20

new' - expresión de tipo 'void' es ilegal MarketRegimeIndicator.mq5 64 16

'=' - uso de operación ilegal MarketRegimeIndicator.mq5 64 14

Detector' - identificador no declarado MarketRegimeIndicator.mq5 65 8

'==' - uso de operación ilegal MarketRegimeIndicator.mq5 65 17

Detector" - identificador no declarado MarketRegimeIndicator.mq5 72 5

Detector" - identificador no declarado MarketRegimeIndicator.mq5 73 5

Detector" - identificador no declarado MarketRegimeIndicator.mq5 74 5

Detector" - identificador no declarado MarketRegimeIndicator.mq5 101 9

';' - token inesperado MarketRegimeIndicator.mq5 103 68

'(' - paréntesis izquierdo desequilibrado MarketRegimeIndicator.mq5 101 7

declaración controlada vacía encontrada MarketRegimeIndicator.mq5 103 68

Detector' - identificador no declarado MarketRegimeIndicator.mq5 133 8

'!=' - uso de operación ilegal MarketRegimeIndicator.mq5 133 17

Detector' - identificador no declarado MarketRegimeIndicator.mq5 135 16

Detector' - puntero de objeto esperado MarketRegimeIndicator.mq5 135 16

Detector' - identificador no declarado MarketRegimeIndicator.mq5 136 9

'=' - uso de operación ilegal MarketRegimeIndicator.mq5 136 18

24 errores, 1 advertencias 25 2


Rashid Umarov
Rashid Umarov | 21 may 2025 en 13:02
Rau Heru #:

El indicador de régimen de mercado tiene 24 errores y 1 advertencia cuando intento compilar.:

'MarketRegimeIndicator.mq5' 1

archivo 'C:\sers\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\IncludeMarketRegimeEnum.mqh' no encontrado MarketRegimeIndicator.mq5 14 11

archivo 'C:\sers\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\IncludeMarketRegimeDetector.mqh' no encontrado MarketRegimeIndicator.mq5 15 11

El indicador busca estos archivos en la carpeta C:\Users\rauma\AppData\Roaming\MetaQuotes\Terminal\10CE948A1DFC9A8C27E56E827008EBD4\MQL5\Include\

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

// Incluir el detector de regímenes de mercado
#include <MarketRegimeEnum.mqh>
#include <MarketRegimeDetector.mqh>
Yoshiteru Taneda
Yoshiteru Taneda | 17 jul 2025 en 10:56
Sahil Bagdi #:

¿A qué archivo se refiere?

MarketRegimeDetector.mqh

en la línea 472

Supongo que se refiere a

'IsStrongSignal' - identificador no declarado MarketRegimeDetector.mqh 472 16

'strategySignal' - algún operador esperado MarketRegimeDetector.mqh 472 31

Utilizando redes neuronales en MetaTrader Utilizando redes neuronales en MetaTrader
En el artículo se muestra la aplicación de las redes neuronales en los programas de MQL, usando la biblioteca de libre difusión FANN. Usando como ejemplo una estrategia que utiliza el indicador MACD se ha construido un experto que usa el filtrado con red neuronal de las operaciones. Dicho filtrado ha mejorado las características del sistema comercial.
Trading por pares: Trading algorítmico con optimización automática en la diferencia de puntuación Z Trading por pares: Trading algorítmico con optimización automática en la diferencia de puntuación Z
En este artículo, veremos qué es el trading por pares y cómo se realiza el comercio de correlaciones. También crearemos un asesor experto para automatizar el trading por pares y añadiremos la capacidad de optimizar automáticamente dicho algoritmo comercial a partir de los datos históricos. Además, como parte del proyecto, aprenderemos a calcular la divergencia de dos pares utilizando la puntuación z.
Particularidades del trabajo con números del tipo double en MQL4 Particularidades del trabajo con números del tipo double en MQL4
En estos apuntes hemos reunido consejos para resolver los errores más frecuentes al trabajar con números del tipo double en los programas en MQL4.
Redes neuronales en el trading: Actor—Director—Crítico (Final) Redes neuronales en el trading: Actor—Director—Crítico (Final)
El framework Actor—Director—Critic supone una evolución de la arquitectura clásica de aprendizaje de agentes. El artículo presenta la experiencia práctica de su aplicación y adaptación a las condiciones de los mercados financieros.