English Русский 中文 Deutsch 日本語 Português
preview
Redefiniendo los indicadores de MQL5 y MetaTrader 5

Redefiniendo los indicadores de MQL5 y MetaTrader 5

MetaTrader 5Indicadores |
152 1
Omega J Msigwa
Omega J Msigwa

Introducción

MQL5 ya no es un lenguaje de programación sencillo como solía ser para crear robots de trading simples. El lenguaje ha madurado hoy en día; ahora se pueden crear programas de negociación de mucha complejidad, implementarlos y probarlos de una manera mucho más robusta y conveniente.

Todos hemos utilizado indicadores "nativos" o "personalizados" en algún momento de nuestra trayectoria como operadores. MetaTrader5 tiene una interfaz sencilla para cargar y adjuntar el indicador al gráfico, lo que permite a los operadores (principalmente operadores manuales) analizar los mercados cómodamente utilizando indicadores; sin embargo, cuando se trata de trading algorítmico, lo que importa no es lo que se ve en el gráfico, sino los cálculos del indicador.

En el trading manual, por ejemplo, uno podría necesitar observar la línea del indicador de media móvil para detectar una tendencia si eso es lo que busca, pero en el trading algorítmico, podríamos buscar una tendencia positiva basándonos en si el precio de cierre está por encima o por debajo del valor de la media móvil calculada sobre un cierto número de barras.

Cuando se trata de trading algorítmico para utilizar un indicador determinado, por ejemplo una media móvil simple (Simple Moving Average, SMA) de período 20, hay que:

int sma_handle; //Declare an indicator handle
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   sma_handle = iMA(Symbol(), Period(), 20, 0, MODE_SMA, PRICE_CLOSE); //Initialize the indicator inside the OnInit function

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

   double sma_buffer[];
   CopyBuffer(sma_handle, 0, 0, 1, sma_buffer); //Copy the indicator buffers inside the Ontick function
  }

Este enfoque es práctico y funciona bien, por decir lo menos, pero resulta rudimentario y no nos ofrece la flexibilidad y el control necesarios para decidir qué información se puede transmitir al indicador para realizar cálculos inmediatos.

Basándose en este enfoque, se afirma que el indicador de media móvil (Moving Average, MA) solo debe aplicarse a una de las constantes de precio proporcionadas en la documentación.

ID

Descripción

PRICE_CLOSE

Precio de cierre

PRICE_OPEN

Precio de apertura

PRICE_HIGH

Precio máximo para el período

PRICE_LOW

Precio mínimo para el período

PRICE_MEDIAN

Precio medio, (máximo + mínimo)/2

PRICE_TYPICAL

Precio típico, (máximo + mínimo + cierre)/3

PRICE_WEIGHTED

Precio promedio, (máximo + mínimo + cierre + cierre)/4

Por no mencionar que estás limitado a los métodos/técnicas de suavizado descritos en la documentación.

ID

Descripción

MODE_SMA

Promedio simple

MODE_EMA

Promedio exponencial

MODE_SMMA

Promedio suavizado

MODE_LWMA

Promedio ponderado lineal

¿Qué ocurre cuando se desea probar algo fuera de lo común? Por ejemplo, si se desea calcular la media móvil de la diferencia entre los precios máximos y mínimos, esto resulta imposible con el enfoque actual, ya que estamos restringidos y limitados a lo que podemos hacer con los indicadores.

Entiendo que la mayoría de los indicadores son lo que son en función de cómo se definieron y derivaron matemáticamente, pero ¿no sería fantástico poder introducir diferentes datos y parámetros en los indicadores con el fin de observar nuevos patrones en el mercado?

Inspirado en la biblioteca Python Technical Analysis (TA-Lib), este innovador enfoque tiene como objetivo proporcionar a los operadores y desarrolladores de sistemas algorítmicos un mayor control sobre la información que se introduce en el indicador para realizar cálculos inmediatos.

En este artículo, implementaremos algunos indicadores (los más utilizados) utilizando este enfoque plug-and-play.

Agrupados por categorías.

Indicadores de tendencia

  • Indicador de media móvil simple
  • Indicador de media móvil exponencial
  • Bandas de Bollinger
  • El SAR parabólico
  • Desviación estándar

Osciladores

  • La convergencia/divergencia de la media móvil (Moving Average Convergence Divergence, MACD)
  • Índice de fuerza relativa (Relative Streng Index, RSI)
  • Osciladores estocásticos
  • Rango verdadero promedio (Average True Range, ATR)
  • Indicador de impulso (Momentum)

Bill Williams

  • Oscilador acelerador (Accelerator Oscillator, AC)
  • Oscilador Awesome (Awesome Oscillator, AO)


Indicador de media móvil simple (Simple Moving Average, SMA)

Este es uno de los indicadores técnicos más utilizados. Calcula el promedio de una serie de precios durante un período de tiempo determinado.

Dado por la fórmula.

Fórmula SMA

Donde:

  • son los precios (por ejemplo, los precios de cierre) durante periodos.
  •  es el período de la SMA.

Podemos implementar fácilmente esta fórmula en una función vectorizada.

Archivo: ta-lib.mqh

vector CTrendIndicators::SMA(const vector &price, uint period, uint shift = 0)
  {
   uint size = (uint)price.Size();

   if(!CheckShiftPeriod(size, period, shift))
      return price;

//---

   vector ma(size);
   ma.Fill(NaN);

   for(uint i = shift + period - 1; i < size; i++) //Loop through all the prices considering the period and shift
     {
      double sum = 0;
      for(uint j = i - period + 1; j <= i; j++)
         sum += price[j]; //sum of the prices

      ma[i] = sum / period; //divided by period to find the mean of that period
     }

   return ma;
  }

Así es como se calcula un indicador de media móvil simple, sin buffers desplegados, sin comprobación de errores MQL5 al cargar el indicador para un símbolo concreto, etc., lo cual puede resultar tedioso.

Este enfoque minimalista solo comprueba si los valores shift y period son correctos; si lo son, la función continúa con los cálculos del indicador y devuelve los valores calculados en forma de vector. Decidí utilizar el formato vectorial para obtener un mayor control y flexibilidad sobre el resultado final.

Dado que todas las funciones de nuestras clases Indicadores son estáticas, podemos acceder fácilmente a los valores de los indicadores en nuestros programas MQL5. Por ejemplo, en un script sencillo.

Archivo: Custom Indicators test script.mq5

#include <ta-lib.mqh>
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
     vector prices = {1,2,3,4,5,6,7,8,9,10};
     int period = 3;
     
     Print("SMA values: ", CTrendIndicators::SMA(prices, period)); 
  }

Resultados:

2025.01.21 09:57:35.727 Custom Indicators test script (EURUSD,H1)       SMA values: [nan,nan,2,3,4,5,6,7,8,9]

De esta manera, pudimos calcular el indicador de media móvil simple a partir de un vector de valores. Más adelante, analizaremos cómo representar gráficamente estos valores para obtener un indicador visual.


Indicador de media móvil exponencial (Exponential Moving Average, EMA)

La EMA se calcula como el promedio de una serie de precios durante un número específico de períodos, al igual que la SMA, pero otorga más peso a los precios recientes, lo que la hace más sensible a los cambios de precios en comparación con la media móvil simple (Simple Moving Average, SMA).

Dado por la fórmula.

 

Donde:

  •  es la EMA en el momento t.
  • Pt es el precio en el momento t.
  •  es la media móvil exponencial (EMA) del período anterior. 
  •  es el factor de suavizado (donde n es el periodo)

Podemos implementarlo en MQL5 de la siguiente manera:

Archivo: ta-lib.mqh

vector CTrendIndicators::EMA(const vector &price, uint period, uint shift = 0)
  {
   uint size = (uint)price.Size();

   if(!CheckShiftPeriod(size, period, shift))
      return price;

//---

   double alpha = 2.0 / (period + 1.0);    // Smoothing factor

   vector res(size);
   res.Fill(NaN);

// Initialize the EMA with the SMA of the first period

   vector sma = SMA(price, period, shift);
   res[period - 1 + shift] = sma[period - 1 + shift];

// Calculate EMA for the rest of the prices

   for(ulong i = period + shift; i < size; i++)
      res[i] = alpha * price[i] + (1 - alpha) * res[i - 1];

   return res;
  }

Podemos obtener los valores calculados del indicador de forma similar a como lo hicimos para la SMA.

Archivo: Custom Indicators test script.mq5 

void OnStart()
  {
     vector prices = {1,2,3,4,5,6,7,8,9,10};
     int period = 3;
     
     Print("EMA values: ", CTrendIndicators::EMA(prices, period));
  }

Resultados:

2025.01.21 10:19:54.291 Custom Indicators test script (EURUSD,H1)       EMA values: [nan,nan,2,3,4,5,6,7,8,9]

Hemos calculado los indicadores de media móvil simple (SMA) y media móvil exponencial (EMA) por separado, a diferencia de cómo se calculan dentro del indicador iMA integrado, que ofrece la opción de elegir el método de suavizado que prefiera.

Este enfoque separado requiere escribir líneas de código adicionales para implementar todos los métodos de suavizado de los indicadores de media móvil.

Las funciones para métodos de suavizado como MODE_SMMA (promedio suavizado) y MODE_LWMA (promedio ponderado lineal) aún no se han implementado en la biblioteca, ya que creo que no se utilizan tan comúnmente como sus homólogos (los métodos de suavizado SMA y EMA).


El indicador de Bandas de Bollinger

Se trata de un indicador de volatilidad compuesto por tres bandas.

  1. La banda media es una media móvil simple (SMA) de los precios de cierre durante un período específico.

  2. La banda superior es la banda media más un múltiplo de la desviación estándar de los precios de cierre durante el mismo período.

    La banda inferior es la banda media menos un múltiplo de la desviación estándar de los precios de cierre durante el mismo período.

    Donde:

    •  es normalmente 2 (el ajuste estándar para las Bandas de Bollinger),
    •  es el período para los cálculos de la media móvil simple (SMA) y la desviación estándar.

    Dado que este indicador tiene que devolver tres (3) valores unidimensionales (1D), conocidos como buffers cuando se utiliza el indicador integrado de Bandas de Bollinger, hagamos que esta función devuelva una estructura de 3 vectores.

    Archivo: ta-lib.mqh

    struct BB_res_struct
      {
       vector            upper_band;
       vector            lower_band;
       vector            middle_band;
      };
    BB_res_struct CTrendIndicators::BollingerBands(const vector &price, uint period, uint shift = 0, double k = 2.0)
      {
       uint size = (uint)price.Size();
    
       BB_res_struct res;
    
    //--- Check for valid parameters
       if(!CheckShiftPeriod(size, period, shift))
          return res;
    
    //--- Initialize vectors
    
       res.upper_band.Resize(size);
       res.lower_band.Resize(size);
    
       res.upper_band.Fill(NaN);
       res.lower_band.Fill(NaN);
    
    //--- Calculate the middle band (SMA)
    
       res.middle_band = SMA(price, period, shift);
    
    //--- Calculate the upper and lower bands
    
       for(uint i = shift + period - 1; i < size; i++)
         {
          double sum_squared_diff = 0;
          for(uint j = i - period + 1; j <= i; j++)
            {
             sum_squared_diff += MathPow(price[j] - res.middle_band[i], 2);
            }
    
          double std_dev = MathSqrt(sum_squared_diff / period);
    
          res.upper_band[i] = res.middle_band[i] + (k * std_dev);
          res.lower_band[i] = res.middle_band[i] - (k * std_dev);
         }
    
       return res;
      }

    A continuación, se explica cómo implementar fácilmente el indicador de Bandas de Bollinger y obtener sus valores.

    Archivo: Custom Indicators test script.mq5 

    void OnStart()
      {
         vector prices = {1,2,3,4,5,6,7,8,9,10};
         int period = 3;
         
         BB_res_struct bb;
         bb = CTrendIndicators::BollingerBands(prices,period,0,2);
         
         Print("BB upper: ",bb.upper_band);
         Print("BB middle: ",bb.middle_band);
         Print("BB lower: ",bb.lower_band);
      }

    Resultados:

    RL      0       11:39:21.000    Custom Indicators test script (EURUSD,H1)       BB upper: [nan,nan,3.632993161855452,4.632993161855453,5.632993161855453,6.632993161855453,7.632993161855453,8.632993161855453,9.632993161855453,10.63299316185545]
    RO      0       11:39:21.000    Custom Indicators test script (EURUSD,H1)       BB middle: [nan,nan,2,3,4,5,6,7,8,9]
    FF      0       11:39:21.000    Custom Indicators test script (EURUSD,H1)       BB lower: [nan,nan,0.3670068381445479,1.367006838144548,2.367006838144548,3.367006838144548,4.367006838144547,5.367006838144547,6.367006838144547,7.367006838144547]
    


    El SAR parabólico (Stop and Reverse)

    Se trata de un indicador que sigue las tendencias y se utiliza para identificar posibles reversiones en el mercado. Coloca puntos por encima o por debajo del precio en función de la dirección de la tendencia.

    Dado por la fórmula.

    Para tendencia alcista

    Para la tendencia bajista

    Donde:

    •  = El valor SAR del siguiente periodo
    •  = Factor de aceleración (comienza con un valor predeterminado, por ejemplo, 0,02, y aumenta en 0,02 cada vez que se alcanza un nuevo máximo/mínimo). Hasta un valor máximo de 0,2)
    •  = Punto extremo (máximo más alto en una tendencia alcista, mínimo más bajo en una tendencia bajista)

    Este indicador se puede implementar de la siguiente manera en MQL5.

    Archivo: ta-lib.mqh

    vector CTrendIndicators::ParabolicSAR(const vector &high,
                                          const vector &low,
                                          const vector &close,
                                          double step = 0.02,
                                          double max = 0.2)
      {
       uint size = (uint)close.Size();
       vector psar(size);
       psar.Fill(NaN);
    
    // Initialize variables
    
       double AF = step;    // Acceleration Factor
       double EP = high[0];      // Extreme Point
       double SAR = low[0];      // Initial SAR
       bool isUptrend = true;    // Assume uptrend at the start
    
    // Calculate Parabolic SAR
    
       for(uint i = 0; i < size; i++)
         {
          // Update SAR
          if(isUptrend)
             SAR = SAR + AF * (EP - SAR);
          else
             SAR = SAR + AF * (SAR - EP);
    
          // Determine if trend changes
          if(isUptrend && SAR > low[i])
            {
             // Switch to downtrend
             isUptrend = false;
             SAR = EP;            // Reset SAR to the most recent EP
             EP = low[i];         // Reset EP
             AF = step;      // Reset AF
            }
    
          else
             if(!isUptrend && SAR < high[i])
               {
                // Switch to uptrend
                isUptrend = true;
                SAR = EP;            // Reset SAR to the most recent EP
                EP = high[i];        // Reset EP
                AF = step;      // Reset AF
               }
    
          // Update EP and AF
          if(isUptrend)
            {
             if(high[i] > EP)
               {
                EP = high[i];
                AF = MathMin(AF + step, max);
               }
            }
          else
            {
             if(low[i] < EP)
               {
                EP = low[i];
                AF = MathMin(AF + step, max);
               }
            }
    
          // Store the SAR value
          psar[i] = SAR;
         }
    
       return psar;
      }

    A diferencia de los dos indicadores de seguimiento de tendencias anteriores, que pueden recibir un único vector como entrada de precio, el SAR parabólico tiene en cuenta tres (3) valores de precio (valores máximos, mínimos y de cierre). 

    Archivo: Custom Indicators test script.mq5

    void OnStart()
      {  
         vector close = {1,2,3,4,5,6,7,8,9,10};
         vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5};
         vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5};
         
         Print("Parabolic SAR values: ", CTrendIndicators::ParabolicSAR(high,low,close,0.02,0.2)); 
      }

    Resultados:

    2025.01.21 11:11:03.525 Custom Indicators test script (EURUSD,H1)       Parabolic SAR values: [1.5,0.5,0.54,0.6584000000000001,0.8888960000000001,1.25778432,1.782005888,2.46816518144,3.3126220560384,4.302602527072256]
    


    El indicador de desviación estándar

    Este indicador mide la cantidad de variación o dispersión del precio con respecto a su media. Este indicador se utiliza a menudo para evaluar la volatilidad del mercado.

    Un valor alto de la desviación estándar indica una alta volatilidad, mientras que un valor bajo de la desviación estándar indica una baja volatilidad.

    Dado por la fórmula.

    Donde:

    •  = Desviación estándar
    • n = Período
    •  = Precio
    •  = Media de los puntos de datos 

    Podemos implementar este indicador en MQL5 de la siguiente manera:

    Archivo: ta-lib.mqh

    vector CTrendIndicators::StandardDeviation(const vector &price, uint period, uint shift = 0)
      {
       uint size = (uint)price.Size();
    
    // Check if the period and shift are valid
       if(!CheckShiftPeriod(size, period, shift))
          return price;
    
    // Initialize standard deviation vector
       vector std_dev(size);
       std_dev.Fill(NaN);
    
    // Loop through the price data
       for(uint i = shift + period - 1; i < size; i++)
         {
          double sum = 0.0;
          double sum_sq_diff = 0.0;
    
          // Calculate mean
          for(uint j = i - period + 1; j <= i; j++)
             sum += price[j];
          double mean = sum / period;
    
          // Calculate squared differences
          for(uint j = i - period + 1; j <= i; j++)
             sum_sq_diff += MathPow(price[j] - mean, 2);
    
          // Calculate standard deviation
          std_dev[i] = MathSqrt(sum_sq_diff / period);
         }
    
       return std_dev;
      }
    

    Este es otro indicador sencillo que se puede llamar de la siguiente manera.

    Archivo: Custom Indicators test script.mq5

    void OnStart()
      {
         vector prices = {1,2,3,4,5,6,7,8,9,10};
         int period = 3;
        
         Print("Stddev values: ", CTrendIndicators::StandardDeviation(prices, period));
      }

    Resultados:

    2025.01.21 11:55:11.657 Custom Indicators test script (EURUSD,H1)       Stddev values: [nan,nan,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726,0.816496580927726]
    


    La convergencia/divergencia de la media móvil (Moving Average Convergence Divergence, MACD)

    Este oscilador muestra las relaciones entre dos medias móviles del precio de un valor. Se utiliza ampliamente como herramienta de análisis técnico.

    Dado por la fórmula.

    Línea principal del MACD

    Donde:

    •  = Media móvil exponencial con un período más corto (por ejemplo, 12)
    •  = Media móvil exponencial con un período más largo (por ejemplo, 26)


    Línea de señal

    Se trata de una EMA suavizada de la línea MACD, normalmente con un valor de período de 9.

    Histograma MACD

    Esta es la diferencia entre la línea MACD y la línea de señal.

    De forma similar a cómo devolvimos los valores calculados de múltiples Bandas de Bollinger, definimos una estructura para devolver los valores del histograma MACD, la línea principal y la línea de señal.

    Archivo: ta-lib.mqh 

    struct MACD_res_struct
      {
       vector            main;     // The MACD Line
       vector            signal;   // The Signal Line
       vector            histogram;    // The MACD Histogram
      };
    MACD_res_struct COscillatorIndicators::MACD(const vector &price, uint fast_ema = 12, uint slow_ema = 26, uint macd_sma = 9, uint shift = 0)
      {
       uint size = (uint)price.Size();
    
       MACD_res_struct res;
       if(!CheckShiftPeriod(size, slow_ema, shift))
          return res;
    
    //--- Calculate EMA(short), EMA(long), and MACD Line
    
       vector fast_ema_vector = CTrendIndicators::EMA(price, fast_ema, shift);
       vector slow_ema_vector = CTrendIndicators::EMA(price, slow_ema, shift);
    
       res.main.Resize(size);
       res.main.Fill(NaN);
    
       for(uint i = 0; i < size; i++)
          res.main[i] = fast_ema_vector[i] - slow_ema_vector[i];
    
    //--- Calculate Signal Line (SMA of MACD Line)
    
       res.signal = CTrendIndicators::SMA(price, macd_sma, shift);
    
    //--- Calculate MACD Histogram
    
       res.histogram.Resize(size);
       res.histogram.Fill(NaN);
    
       for(uint i = 0; i < size; i++)
          res.histogram[i] = res.main[i] - res.signal[i];
    
       return res;
      }

    Podemos obtener fácilmente los valores calculados del oscilador MACD dentro de un script de prueba de la siguiente manera.

    Archivo: Custom Indicators test script.mq5 

    void OnStart()
      {
         vector prices = {1,2,3,4,5,6,7,8,9,10};
    
         MACD_res_struct macd;
         
         macd = COscillatorIndicators::MACD(prices,2,3,4);
         
         Print("MACD main: ", macd.main); 
         Print("MACD signal: ", macd.signal); 
      }

    Resultados:

    RD      0       12:28:51.368    Custom Indicators test script (EURUSD,H1)       MACD main: [nan,nan,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5]
    HO      0       12:28:51.368    Custom Indicators test script (EURUSD,H1)       MACD signal: [nan,nan,nan,2.5,3.5,4.5,5.5,6.5,7.5,8.5]
    


    El indicador de fuerza relativa (Relative Strength Indicator, RSI)

    Se trata de un oscilador de impulso (momentum) que mide el gasto y la magnitud de los movimientos de precios. Oscila entre 0 y 100, y los operadores lo utilizan para identificar condiciones de sobrecompra y sobreventa en el mercado.

    Los cálculos del indicador RSI implican los siguientes pasos:

    01: Calcular las ganancias y pérdidas medias durante un periodo determinado.

    02: Cálculo de la fuerza relativa (Relative Strength, RS).

    03: Cálculo del RSI.

    Implementación en MQL5

    vector COscillatorIndicators::RSI(const vector &price, uint period, uint shift = 0)
      {
       uint size = (uint)price.Size();
    
    //--- Check for valid parameters
       if(!CheckShiftPeriod(size, period, shift))
          return price;
    
    //--- Initialize vectors
       vector rsi(size), gains(size), losses(size);
       rsi.Fill(NaN);
       gains.Fill(0.0);
       losses.Fill(0.0);
    
    //--- Calculate gains and losses
       for(uint i = shift + 1; i < size; i++)
         {
          double change = price[i] - price[i - 1];
          gains[i] = (change > 0) ? change : 0;
          losses[i] = (change < 0) ? -change : 0;
         }
    
    //--- Initialize first average gain and loss (simple average for the first period)
       double avg_gain = 0, avg_loss = 0;
       for(uint i = shift + 1; i < shift + 1 + period; i++)
         {
          avg_gain += gains[i];
          avg_loss += losses[i];
         }
       avg_gain /= period;
       avg_loss /= period;
    
    //--- Compute RSI for the rest of the periods
       for(uint i = shift + period; i < size; i++)
         {
          // Apply smoothing for average gain and loss
          avg_gain = ((avg_gain * (period - 1)) + gains[i]) / period;
          avg_loss = ((avg_loss * (period - 1)) + losses[i]) / period;
    
          // Calculate RSI
          double rs = (avg_loss == 0) ? 0 : avg_gain / avg_loss;
          rsi[i] = (avg_loss == 0) ? 100 : (100 - (100 / (1 + rs)));
         }
    
       return rsi;
      }

    A continuación se muestra cómo se pueden obtener los valores del indicador RSI.

    void OnStart()
      {
         vector prices = {1,2,3,4,5,6,7,8,9,10};
         int period = 3;
         
         Print("RSI values: ", COscillatorIndicators::RSI(prices,period)); 
      }

    Resultados:

    2025.01.21 12:51:29.640 Custom Indicators test script (EURUSD,H1)       RSI values: [nan,nan,nan,100,100,100,100,100,100,100]
    


    El indicador oscilador estocástico

    Se trata de un indicador de impulso (momentum) que compara el precio de cierre de un valor con su rango de precios durante un periodo determinado. 

    La fórmula para calcular este indicador consiste en:

    Línea %K

    Donde:

    •  es el precio de cierre actual.
    •  es el precio más bajo durante el período de referencia.
    •  es el precio más alto durante el período de referencia.

    Línea %D

    Esta es la media móvil de la línea %K, que suele utilizar una media móvil simple (SMA) de 3 períodos.

    A continuación se muestra cómo implementar este indicador en MQL5.

    Stochastic_struct COscillatorIndicators::StochasticOscillator(const vector &high, const vector &low, const vector &close, uint k_period = 5, uint d_period = 3, uint period = 3, uint shift = 0)
      {
       uint size = (uint)close.Size();
    
       Stochastic_struct res;
    
    // Check for valid parameters
       if(!CheckShiftPeriod(size, period, shift))
          return res;
    
    // Initialize vectors for %K and %D
       vector K(size), D(size);
       K.Fill(NaN);
       D.Fill(NaN);
    
    // Calculate %K
       for(uint i = shift + period - 1; i < size; i++)
         {
          double H_max = -DBL_MAX, L_min = DBL_MAX;
    
          // Find the highest high and the lowest low over the lookback period
          for(uint j = i - period + 1; j <= i; j++)
            {
             H_max = MathMax(H_max, high[j]);
             L_min = MathMin(L_min, low[j]);
            }
    
          // Calculate %K
          double K_value = (H_max - L_min != 0) ? ((close[i] - L_min) / (H_max - L_min)) * 100 : 0;
          K[i] = K_value;
         }
    
    // Smooth %K with a simple moving average (k_period)
       vector smoothedK(size);
       smoothedK.Fill(NaN);
    
       for(uint i = shift + k_period - 1; i < size; i++)
         {
          double sum = 0;
          for(uint j = i - k_period + 1; j <= i; j++)
            {
             sum += K[j];
            }
          smoothedK[i] = sum / k_period;
         }
    
    // Calculate %D (3-period moving average of %K)
    
       D = CTrendIndicators::SMA(smoothedK, period, shift);
    
       res.main = K;
       res.signal = D;
    
       return res;
      }
    

    Devolvemos la señal y la línea principal en una estructura.

    void OnStart()
      {  
         vector close = {1,2,3,4,5,6,7,8,9,10};
         vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5};
         vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5};
         
         Stochastic_struct stoch;
         stoch = COscillatorIndicators::StochasticOscillator(high,low,close,5,3,3);
         
         Print("Stoch main: ", stoch.main); 
         Print("Stoch signal: ", stoch.signal); 
      }


    El indicador del rango verdadero promedio (Average True Range, ATR)

    Este es un indicador útil para comprender la volatilidad del mercado. Mide el rango promedio entre los precios altos y bajos durante un período específico.

    Dado por la fórmula.

    01: Cálculo del rango real (True Range, TR)

    Donde:

    • H es el máximo del período actual.
    •  es el mínimo del período actual.
    •  es el cierre del período anterior.

    02: Cálculo del rango verdadero promedio (Average True Range, ATR).

    El ATR es la media móvil del rango real durante un período determinado.

     SMA es la media móvil simple.

    Podemos implementar este indicador en MQL5 de la siguiente manera.

    vector COscillatorIndicators::ATR(const vector &high, const vector &low, const vector &close, uint period = 14, uint shift = 0)
      {
       uint size = (uint)close.Size();
    
    // Check for valid parameters
       if(!CheckShiftPeriod(size, period, shift))
          return close;
    
    // Initialize the True Range (TR) and ATR vectors
       vector TR(size);
       TR.Fill(NaN);
    
    // Calculate the True Range for each period
       for(uint i = shift + 1; i < size; i++)
         {
          double H = high[i];
          double L = low[i];
          double C_prev = close[i - 1];
    
          // Calculate the three possible True Range values
          double TR1 = H - L;
          double TR2 = MathAbs(H - C_prev);
          double TR3 = MathAbs(L - C_prev);
    
          // True Range is the maximum of the three
          TR[i] = MathMax(TR1, MathMax(TR2, TR3));
         }
    
    //--- Smooth the True Range using a simple moving average (SMA) over the specified period
    
       return CTrendIndicators::SMA(TR, period, shift);
      }

    A continuación se muestra cómo podemos obtener los valores para este indicador.

    void OnStart()
      {  
         vector close = {1,2,3,4,5,6,7,8,9,10};
         vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5};
         vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5};
         
         Print("ATR values: ", COscillatorIndicators::ATR(high,low,close,3)); 
      }

    Resultados:

    2025.01.21 13:57:59.943 Custom Indicators test script (EURUSD,H1)       ATR values: [nan,nan,nan,1.5,1.5,1.5,1.5,1.5,1.5,1.5]
    


    El indicador de impulso (Momentum)

    Se trata de un indicador sencillo que se utiliza para medir la velocidad a la que se mueve el precio de un activo durante un periodo determinado. Ayuda a identificar tendencias y posibles cambios de tendencia.

    Dado por una fórmula simple.

    Donde:

    • Momentum(t) = Valor del impulso en el momento t
    • Price(t) = El precio actual
    • Price(t - n) = Precio hace n períodos
    • n = El período durante el cual se calcula el impulso

    Algunas variaciones para calcular el momento utilizan una relación.

    Vamos a implementar el indicador de impulso utilizando esta variación.

    Implementación en MQL5

    vector COscillatorIndicators::MomentumIndicator(const vector &price, uint period, uint shift = 0)
      {
       uint size = (uint)price.Size();
    
    // Check for valid input
       if(!CheckShiftPeriod(size, period, shift))
          return price;
    
    // Initialize the momentum vector
       vector momentum(size);
       momentum.Fill(NaN);
    
    // Calculate Momentum
       for(uint i = shift + period; i < size; i++)
         {
          //momentum[i] = price[i] - price[i - period]; // Momentum difference formula
    
          // using the ratio formula:
          momentum[i] = (price[i] / price[i - period]) * 100;
         }
    
       return momentum;
      }


    Indicador oscilador impresionante (Awesome Oscillator, AO)

    Este es un indicador de impulso (momentum) que calcula la diferencia entre dos medias móviles simples (Simple Moving Averages, SMA) del precio medio.

    Dado por la fórmula:

    Donde:

    •  = SMA con un período más corto (normalmente 5)
    •  = SMA con un período más largo (normalmente 34)

    A continuación se muestra la implementación en MQL5.

    vector CBillWilliamsIndicators::AwesomeOscillator(const vector &high, const vector &low, uint fast_period = 5, uint slow_period = 34, uint shift = 0)
      {
       uint size = (uint)high.Size();
       if(size != low.Size())
          return vector::Zeros(0); // Ensure high and low vectors are of the same size
    
       if(!CheckShiftPeriod(size, slow_period, shift))
          return vector::Zeros(0); // Validate shift and slow period
    
    // Initialize vectors
       vector ao(size), median_price(size);
       ao.Fill(NaN);
       median_price.Fill(NaN);
    
    // Calculate Median Price
       for(uint i = 0; i < size; i++)
          median_price[i] = (high[i] + low[i]) / 2;
    
    // Calculate Fast and Slow SMAs of the Median Price
       vector sma_fast = CTrendIndicators::SMA(median_price, fast_period, shift);
       vector sma_slow = CTrendIndicators::SMA(median_price, slow_period, shift);
    
    // Calculate AO
       for(uint i = 0; i < size; i++)
          ao[i] = sma_fast[i] - sma_slow[i];
    
       return ao;
      }

    Dado que tenemos vectores muy simples para precios altos y bajos, podemos establecer el período rápido en 3 y el período lento en 5.

    void OnStart()
      {  
         vector close = {1,2,3,4,5,6,7,8,9,10};
         vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5};
         vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5};
         
         Print("AO values: ", CBillWilliamsIndicators::AwesomeOscillator(high,low,3,5)); 
      }

    Resultados:

    2025.01.21 14:25:50.590 Custom Indicators test script (EURUSD,H1)       AO values: [nan,nan,nan,nan,1,1,1,1,1,1]
    


    Indicador oscilador acelerador (Accelerator Oscillator, AC)

    El oscilador acelerador (Accelerator Oscillator, AC) es una herramienta de análisis técnico que rastrea la velocidad de los cambios en el impulso (momentum) del precio. Muestra si la fuerza motriz del mercado se acelera o desacelera, lo que ayuda a los operadores a anticipar posibles reversiones.

    Se calcula como la diferencia entre el oscilador Awesome y la media móvil simple (SMA) de 5 períodos del AO (Awesome Oscillator).

    Dado por la siguiente fórmula.

    Podemos implementar este indicador en MQL5 de la siguiente manera.

    vector CBillWilliamsIndicators::AcceleratorOscillator(const vector &high,
          const vector &low,
          uint ao_period_fast = 5, // Fast period for AO
          uint ao_period_slow = 34, // Slow period for AO
          uint ac_period = 5 // Period for AC SMA
                                                         )
      {
       uint size = (uint)high.Size();
       if(size != low.Size())
          return vector::Zeros(0); // Ensure high and low vectors are of the same size
    
    
    // Validate shift and period
       if(!CheckShiftPeriod(size, ao_period_slow, 0))
          return vector::Zeros(0);
    
    // Calculate AO (Awesome Oscillator)
    
       vector ao = AwesomeOscillator(high, low, ao_period_fast, ao_period_slow);
    
    // Calculate AC (Accelerator Oscillator)
    
       vector ac(size);
       ac.Fill(NaN);
    
       vector ao_sma_ac = CTrendIndicators::SMA(ao, ac_period);
    
       for(uint i = 0; i < size; i++)
          ac[i] = ao[i] - ao_sma_ac[i];
    
       return ac;
      }

    Dado que el oscilador acelerador (Accelerator Oscillator, AC) es muy similar al oscilador impresionante (Awesome Oscillator, AO), podemos llamar a su función con argumentos similares.

    void OnStart()
      {  
         vector close = {1,2,3,4,5,6,7,8,9,10};
         vector high = {1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5};
         vector low = {0.5,1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5};
         
    //--- Bill williams indicator
    
         Print("AO values: ", CBillWilliamsIndicators::AwesomeOscillator(high,low,3,5)); 
         Print("AC values: ", CBillWilliamsIndicators::AcceleratorOscillator(high,low,3,5)); 
      }

    Resultados:

    MQ      0       14:40:36.296    Custom Indicators test script (EURUSD,H1)       AO values: [nan,nan,nan,nan,1,1,1,1,1,1]
    EL      0       14:40:36.296    Custom Indicators test script (EURUSD,H1)       AC values: [nan,nan,nan,nan,nan,nan,nan,nan,0,0]
    


    Recopilación simplificada de datos de indicadores

    Ahora que hemos visto cómo se han implementado algunos de los indicadores en la biblioteca, podemos intentar recopilar toda la información que queramos obtener del mercado y crear un indicador a partir de ella. Por ejemplo, voy a calcular la media móvil de los precios de apertura, máximo, mínimo y cierre.

    Comenzamos obteniendo los valores OHLC.

    int size = 1000;
    
    vector open, high, low, close;
    
    open.CopyRates(Symbol(), Period(), COPY_RATES_OPEN, 1, size);
    high.CopyRates(Symbol(), Period(), COPY_RATES_HIGH, 1, size);
    low.CopyRates(Symbol(), Period(), COPY_RATES_LOW, 1, size);
    close.CopyRates(Symbol(), Period(), COPY_RATES_CLOSE, 1, size);

    Comenzando con la media móvil simple del periodo 20 aplicada a los precios de apertura.

    vector sma_open = CTrendIndicators::SMA(open, 20); 

    Podemos recopilar sin esfuerzo diversos indicadores SMA para diferentes periodos y precios.

    vector sma_open = CTrendIndicators::SMA(open, 20); 
    vector sma_high = CTrendIndicators::SMA(high, 50);
    vector sma_low = CTrendIndicators::SMA(low, 100);
    vector sma_close = CTrendIndicators::SMA(close, 20);

    En lugar de eso, introduzcámoslos en una matriz y observémoslos todos juntos.

    matrix Indicators(size, 4);
        
    Indicators.Col(CTrendIndicators::SMA(open, 20), 0);
    Indicators.Col(CTrendIndicators::SMA(high, 50), 1);
    Indicators.Col(CTrendIndicators::SMA(low, 100), 2);
    Indicators.Col(CTrendIndicators::SMA(close, 20), 3);
        
    Print("Indicators matrix\n",Indicators);

    Resultados:

    NK      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0485715,1.0484514,nan,1.048488]
    LL      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0484425,1.0485544,nan,1.0484265]
    RP      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048381,1.0486754,nan,1.048299]
    QG      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0483055,1.0488004,nan,1.048152]
    KK      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0481585,1.0489198,nan,1.048296]
    HL      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048303,1.049033,nan,1.0485255]
    DS      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048533,1.0491756,nan,1.0487015]
    OK      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048658,1.0493158,1.0475226,1.0488295]
    KD      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0487895,1.0494628,1.047473,1.0488985]
    JR      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0488575,1.0494916,1.0474256,1.0489465]
    FR      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0489055,1.049475,1.0473723,1.0490045]
    LL      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048964,1.0494814,1.0473137,1.049052]
    HK      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0490075,1.0494728,1.0472494,1.0491065]
    CF      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.049062,1.0494618,1.0471845,1.049044]
    RE      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0489995,1.0494452,1.047114,1.048892]
    FQ      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048848,1.0494558,1.047044,1.0487065]
    CL      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0486625,1.0495002,1.0469762,1.0486305]
    DK      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.048586,1.0496014,1.0469234,1.048582]
    EE      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0485375,1.0496714,1.0468866,1.048646]
    RE      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0486015,1.0497982,1.046857200000001,1.04877]
    IP      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0487245,1.0498646,1.0468378,1.0490025]
    DO      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0489565,1.0499466,1.046833500000001,1.0492415]
    GN      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0491975,1.050113,1.046846700000001,1.0497525]
    CK      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0497085,1.0502838,1.046881000000001,1.0502025]
    IJ      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.050159,1.0503826,1.046898100000001,1.0506915]
    PF      0       18:30:25.100    Custom Indicators test script (EURUSD,H1)        [1.0506475,1.0504916,1.046935200000001,1.051158…]

    Supongamos que quiero medir el impulso de estas variables que tengo, creando un indicador de impulso basado en ellas.

    Indicators.Col(COscillatorIndicators::MomentumIndicator(open, 20), 4);
    Indicators.Col(COscillatorIndicators::MomentumIndicator(high, 50), 5);
    Indicators.Col(COscillatorIndicators::MomentumIndicator(low, 100), 6);
    Indicators.Col(COscillatorIndicators::MomentumIndicator(close, 20), 7);

    Resultados:

    IN      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0441885,nan,nan,1.0438975,99.43679181343492,nan,nan,99.44502817843157]
    LN      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0438975,1.0495116,nan,1.043593,99.44407828753189,nan,nan,99.41864350150351]
    QS      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0435925,1.0492638,nan,1.0433225,99.4176888931316,98.82473464044848,nan,99.4833645288208]
    HG      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0436275,1.049148199999999,nan,1.043363,100.0668474731655,99.45161810609009,nan,100.0773424743863]
    EH      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0436685,1.0490618,nan,1.043385,100.0782973197491,99.59030385797199,nan,100.0420047732697]
    KO      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0436925,1.0489454,nan,1.0434175,100.0458251389074,99.4479854313681,nan,100.0620536907626]
    JQ      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0437225,1.048834,nan,1.043484,100.0572803299347,99.47183265534476,nan,100.1270939444036]
    JE      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.043788,1.048718,nan,1.0435725,100.1251839535195,99.45010144680205,nan,100.1690625149243]
    LE      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.043877,1.048595199999999,nan,1.0435315,100.1700192943244,99.41799844546816,nan,99.92180198737388]
    MI      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0438365,1.048457,nan,1.0437085,99.92275488503829,99.34503611305946,nan,100.3389538390831]
    HN      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.044013,1.0483164,nan,1.044095,100.3379931060896,99.33386396801032,nan,100.7431263218612]
    KS      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0443985,1.048186,nan,1.044364,100.7411964891704,99.38227742565063,nan,100.5158345877638]
    EE      0       18:39:34.172    Custom Indicators test script (EURUSD,H1)        [1.0446665,1.0480502,nan,1.044532,100.5139219145509,99.35649569733499,nan,100.3225558712848…]


    Trazado de indicadores creados con funciones personalizadas

    Intentemos hacer visibles al ojo humano los cálculos de los indicadores obtenidos de esta biblioteca.

    A pesar de que este enfoque está orientado a la recopilación de datos más que a la visualización, visualicemos los cálculos del indicador en un indicador personalizado de MetaTrader 5.

    Visualización del indicador SMA (20).

    #property indicator_chart_window
    #property indicator_buffers 1
    #property indicator_plots 1
    
    #property indicator_color1 clrDodgerBlue
    #property indicator_type1 DRAW_LINE
    #property indicator_style1 STYLE_SOLID
    
    #include <ta-lib.mqh>
    
    input int period_ = 20; //SMA period
    
    double buffer[];
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- indicator buffers mapping
       
       SetIndexBuffer(0, buffer, INDICATOR_DATA);
       PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0);   
       
       PlotIndexSetString(0,PLOT_LABEL,"SMA("+string(period_)+")");
       PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,period_+1);
       
    //---
       return(INIT_SUCCEEDED);
      }
    //+------------------------------------------------------------------+
    //| Custom indicator iteration function                              |
    //+------------------------------------------------------------------+
    int OnCalculate(const int rates_total,
                    const int prev_calculated,
                    const datetime &time[],
                    const double &open[],
                    const double &high[],
                    const double &low[],
                    const double &close[],
                    const long &tick_volume[],
                    const long &volume[],
                    const int &spread[])
      {
    //---
    
       if (prev_calculated==0) //Initial indicator calculation, For Plotting the entire past 
         {        
           vector buffer_vector = CTrendIndicators::SMA(close, period_);
           
           VectorToArray(buffer_vector, buffer); //We assign the calculations into an array format
         }
        else //For plotting the current value
         {
           for (int i=prev_calculated-1; i<rates_total; i++) //Loop from the prev_calculated bars -1 to the total bars present 
            {
               double temp_close[]; //For storing temporary close values
               int size = period_*2; //We are going to copy an equivalent of period x 2 to leave a room for NaN values
               
               if (ArrayCopy(temp_close, close, 0, i - size, size) < 0)
                { 
                   printf("Failed to copy closing price values to a temporary array, err = %d",GetLastError());
                   continue;
                }
               
               vector indicator_values = CTrendIndicators::SMA(temp_close, period_); 
               ulong last_index = indicator_values.Size() - 1; //The last value in the vector is the recent calculated indicator value
               
               buffer[i] = indicator_values[last_index]; //Assing the last indicator value to the last value in the buffer
            }
         }
       
    //--- return value of prev_calculated for next call
       return(rates_total);
      }
    //+------------------------------------------------------------------+
    //|      A crude way to convert a vector into Array                  |
    //+------------------------------------------------------------------+
    template <typename T>
    void VectorToArray(const vector<T> &v, T &arr[])
     {
       ArrayResize(arr, (uint)v.Size());
       
       for (uint i=0; i<(uint)v.Size(); i++)
           arr[i] = v[i];
     }
    

    Resultados:

    SMA 20


    Reflexiones finales

    Este enfoque de colección personalizada de valores indicadores resulta más útil para la recopilación de datos que para cualquier otra tarea concreta, y es ideal para el análisis de datos y para los entusiastas que buscan formas innovadoras de recopilar datos indicadores con fines analíticos.

    A menudo me he visto en la necesidad de obtener rápidamente varios valores de indicadores sin tener que inicializar el indicador y realizar todas esas tareas tediosas que a menudo provocan errores en MetaTrader5. Con la creciente demanda de datos en MQL5, debido a su nueva capacidad para manejar sofisticados modelos de IA y ML, necesitamos formas diferentes y eficaces de extraer y visualizar los datos de los indicadores con fines de análisis y entrenamiento de ML.

    Nos vemos.


    Tabla de archivos adjuntos

    Nombre del archivo Descripción/Uso
    Include\ta-lib.mqh Librería MQL5 con todo el código de indicadores analizado en este artículo.
    Indicators\Trend Indicators Redefined.mq5  Un indicador que contiene un indicador de media móvil simple implementado con fines demostrativos. 
     Scripts\Custom Indicators test script.mq5 Un script sencillo creado para probar y depurar código de indicadores. 


    Fuentes y referencias

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

      Archivos adjuntos |
      Attachments.zip (7.42 KB)
      Zhuo Kai Chen
      Zhuo Kai Chen | 25 ene 2025 en 03:14
      Un artículo muy interesante. Me gusta el enfoque innovador que has introducido.
      Simulación de mercado (Parte 09): Sockets (III) Simulación de mercado (Parte 09): Sockets (III)
      Este artículo es la continuación del anterior. En él veremos cómo se implementará el Asesor Experto, centrándonos principalmente en cómo debe hacerse el código del servidor. El código del artículo anterior no es suficiente para que las cosas funcionen como deberían, por lo que es necesario profundizar en él. Por esta razón, es necesario que leas ambos artículos para comprender mejor lo que ocurrirá.
      Cómo funciones centenarias pueden actualizar nuestras estrategias comerciales Cómo funciones centenarias pueden actualizar nuestras estrategias comerciales
      En este artículo hablaremos de las funciones de Rademacher y Walsh. Asimismo, exploraremos formas de aplicar estas funciones para analizar series temporales financieras y estudiaremos diversas aplicaciones en el comercio.
      Análisis de todas las variantes del movimiento de precios en una computadora cuántica IBM Análisis de todas las variantes del movimiento de precios en una computadora cuántica IBM
      Hoy utilizaremos un computadora cuántica de IBM para descubrir todas las variantes del movimiento de los precios. ¿Le suena a ciencia ficción? ¡Bienvenido al mundo de la informática cuántica para el trading!
      Redes neuronales en el trading: Modelos bidimensionales del espacio de enlaces (Final) Redes neuronales en el trading: Modelos bidimensionales del espacio de enlaces (Final)
      Continuamos nuestra introducción al innovador framework Chimera, un modelo bidimensional de espacio de estados que utiliza tecnologías de redes neuronales para analizar series temporales multidimensionales. Este método proporciona una gran precisión de predicción con un bajo costo computacional.