English Русский 中文 Deutsch 日本語
preview
Características del Wizard MQL5 que debe conocer (Parte 57): Aprendizaje supervisado utilizando la media móvil y el oscilador estocástico

Características del Wizard MQL5 que debe conocer (Parte 57): Aprendizaje supervisado utilizando la media móvil y el oscilador estocástico

MetaTrader 5Sistemas comerciales |
39 2
Stephen Njuki
Stephen Njuki

Introducción

Continuamos nuestro análisis de patrones sencillos que se pueden implementar con los asesores expertos creados con el Asistente MQL5. El objetivo principal de esto es siempre experimentar o probar ideas. Para usarlo finalmente en una cuenta real se pueden emplear Asesores expertos creados manualmente, sobre todo después de haberlos probado durante más tiempo. En cambio, los Asesores expertos generados con el Asistente permiten hacer pruebas rápidas sin tener que escribir tanto código desde el inicio.

El aprendizaje automático está muy de moda en este momento, y hemos tratado algunos aspectos específicos del mismo en artículos anteriores de esta serie. Seguiremos tratando algunas de estas características más técnicas en este y en futuros artículos, aunque serán un tema secundario, ya que nos centraremos más en patrones de indicadores más conocidos y consolidados.

Además, en el contexto del aprendizaje automático, nuestros artículos tratarán las tres ramas principales del aprendizaje en artículos separados, en un ciclo. Para comenzar, analizaremos la supervisión o el aprendizaje supervisado y nuestros patrones indicadores surgirán de la combinación de un indicador de tendencia y un indicador de impulso. Analizaremos los indicadores de media móvil y estocástico.

En el aprendizaje supervisado, buscaremos implementar cada patrón en una red neuronal separada. Estos, como se argumenta en artículos recientes, están mejor codificados y entrenados en Python que en MQL5. Las ganancias de eficiencia son increíbles. Python también permite fácilmente realizar pruebas de validación cruzada luego de una sesión de entrenamiento, por lo que las realizaremos para cada patrón.

Si bien la validación cruzada se comparte en Python comparando el valor de pérdida de la ejecución de prueba con el valor de pérdida de la última época de entrenamiento, esto por sí solo, aunque importante, seguramente será insuficiente para evaluar la validación cruzada de los pesos y sesgos actuales de la red. 

Por lo tanto, realizaremos ejecuciones de simulación en el probador de estrategias de MetaTrader 5, con las redes ONNX exportadas. Para este artículo, los conjuntos de datos de precios o "x" e "y" que se envían a Python desde MetaTrader 5 para comenzar el entrenamiento serán para el año 2023, para el par EURJPY. Por lo tanto, la prueba forward (fuera de muestra) se realizará con el mismo símbolo utilizando los datos del año 2024. Estamos realizando nuestro análisis en el marco temporal diario.

La combinación de la media móvil (MA) con el oscilador estocástico puede generar una variedad de señales de trading. Para nuestros fines de prueba y exploración, solo tendremos en cuenta los 10 patrones de señal principales que los operadores pueden utilizar cuando se combinan estos indicadores.


Enfoque con tipos de aprendizaje automático

Una línea de aprendizaje automático puede considerarse como estas tres fases interconectadas: supervisión, refuerzo e inferencia. Repasemos las definiciones de cada uno.

Aprendizaje supervisado (también conocido como fase de entrenamiento): es cuando el modelo aprende patrones históricos basados en datos etiquetados (datos independientes o de entrada, a menudo etiquetados como x, y datos independientes para pronosticar, a menudo etiquetados como y). 

Por su parte, el aprendizaje por refuerzo (que puede considerarse como una fase de aprendizaje y optimización en uso) puede entenderse como una etapa en la que el modelo se perfecciona a sí mismo mediante la interacción con su entorno y la optimización de sus acciones para obtener recompensas a largo plazo (casi como la retrospección durante un forward fuera de muestra).

Y, por último, el aprendizaje por inferencia (también conocido como fase de aprendizaje no supervisado) sería cuando el modelo generaliza a partir del aprendizaje pasado y aplica lo aprendido a nuevos datos y nuevos problemas.

A modo meramente ilustrativo, veamos cómo se podrían vincular estas tres fases al abordar diferentes conjuntos de problemas. Consideraremos casos de sistemas de información meteorológica y previsión de series temporales financieras.

Supervisión:

El objetivo del aprendizaje supervisado es generar un modelo predictivo a partir de datos etiquetados. Este proceso implica la recopilación y el preprocesamiento de datos históricos. A continuación, se lleva a cabo la extracción de características, que podría considerarse como una forma de normalizar los datos históricos a un rango o formato que pueda introducirse en la red neuronal o el modelo de entrenamiento. Después de esto, el modelo se entrena en LSTM, XGBoost o transformadores utilizando datos etiquetados. El etiquetado consiste en marcar los datos independientes (datos precursores que se conocen y se utilizan para realizar previsiones) y los datos dependientes (los datos que queremos predecir) con etiquetas distintas. El objetivo inicial aquí es minimizar las pérdidas, reduciendo al máximo la diferencia entre lo previsto y lo real mediante el uso del descenso de gradiente.

En el aprendizaje supervisado, se puede utilizar la validación cruzada, y sus resultados pueden justificar el despliegue del modelo para su pleno uso. Sin embargo, con los tres pasos que estamos explorando aquí, la etapa final del aprendizaje supervisado sería la selección del modelo y el ajuste de hiperparámetros, donde, en esencia, la tasa de aprendizaje óptima y el tamaño del lote de entrenamiento se eligen en función de lo que funcionó mejor. Además, se elige la arquitectura con respecto a los tipos de activación e incluso los tamaños de capa si estas opciones se probaron en esta fase de entrenamiento.

Para ilustrar esto, en un sistema de pronóstico meteorológico: los datos serían temperatura, humedad o presión históricas; el modelo podría ser un bosque aleatorio o un modelo basado en CNN; y el resultado sería un sistema para predecir tendencias de temperatura. Con series temporales financieras, los datos de pronóstico serían precios históricos con ingeniería de características para obtener valores indicadores; el modelo podría ser LSTM; función de pérdida MSE; y el resultado sería un modelo entrenado que predice el próximo precio basándose en observaciones pasadas.

Refuerzo:

Luego de haber realizado un aprendizaje supervisado que se basa principalmente en datos históricos etiquetados, la pregunta entonces es: ¿el modelo podrá funcionar con datos en vivo o futuros? ¿O será capaz de adaptarse si las condiciones futuras cambian con respecto a las que fue entrenado? Para responder a esto, se utiliza el aprendizaje de refuerzo. Los modelos estáticos suelen tener dificultades en entornos dinámicos, por lo que el aprendizaje por refuerzo ayuda a optimizar el proceso de toma de decisiones en el futuro.

Por tanto, el objetivo del RL es mejorar las previsiones optimizando la toma de decisiones basada en la retroalimentación. Dicho de otro modo, una vez que tengamos, digamos, una red neuronal que pronostica cambios en los precios, procederíamos a desarrollar redes de políticas y valores que puedan usar estos cambios de precios como estados. We are thus in a position where we separate price changes from trader actions, with the introduction of states and actions.

Estos ejemplos son para pronósticos de series de tiempo financieras; si se tratara del clima como lo ilustramos arriba, entonces los estados y las acciones podrían ser la cantidad de lluvia y cuánto sembrar/plantar de un cultivo importante. Un resultado más tangible y deseado de la previsión de series de tiempo financieras suele ser las ganancias o pérdidas derivadas de las acciones adoptadas para seguir las previsiones de la red. Para nuestra ilustración del clima, estos podrían ser los rendimientos del cultivo principal.

El proceso RL, como vimos anteriormente, no solo implica entrenar y actualizar la red crítica para que podamos anticipar mejor nuestra posición de ganancias/pérdidas, sino que también proporciona deltas que afinan aún más los pesos y sesgos de la red de políticas.

El proceso de RL, para resumir, implica: Configuración del agente y el entorno donde se definen los estados, las acciones y las recompensas. Como se mencionó, estos fluirían o se determinarían a partir del modelo entrenado en la fase de supervisión (como se muestra con las ilustraciones anteriores). Luego también el aprendizaje de políticas, donde se optimiza una red de actores o un algoritmo equivalente para asignar estados a las acciones requeridas. También existe un mecanismo de optimización basado en recompensas que puede adoptar la forma de un algoritmo de valor o una red crítica que ajusta las predicciones en función de la rentabilidad a largo plazo. Y, por último, un agente que equilibra la exploración (probar diferentes configuraciones de políticas con el objetivo de aprender algo nuevo) contra la explotación (apegarse a lo que ha funcionado bien en el pasado).

Si podemos utilizar ejemplos para mostrar lo que sucede aquí con el pronóstico meteorológico y financiero como se mencionó anteriormente en la fase de supervisión; con la predicción meteorológica en la fase de supervisión, el modelo inicial predice las precipitaciones en función de la temperatura, la humedad, etc. y los resultados de las precipitaciones proyectadas que buscamos. Debido a que esta precipitación es un factor determinante para determinar si debemos sembrar nuestro cultivo, RL introduce un nivel de decisión de interpretación. La salida del pronóstico de lluvia se presenta en forma de estados. Si estos estados pronostican diferentes precipitaciones en distintas regiones o puntos en el tiempo, su interpretación para determinar si se debe plantar se puede optimizar en función de una recompensa, que en este caso sería el rendimiento del cultivo. El resultado de esto sería un modelo de pronóstico que mejora en respuesta a los cambios climáticos del mundo real. Entonces, si la fase de supervisión fue la escuela, entonces el refuerzo es la capacitación en el trabajo.

Para la previsión financiera, habríamos previsto los cambios de precios a partir del modelo en la etapa de supervisión, actuando como nuestro estado. Estos cambios pueden ser un vector multidimensional si, por ejemplo, abarcan más de un período de tiempo. Las acciones serían las tomadas por el comerciante o asesor experto, que son comprar, vender o ser neutral. En función de las acciones tomadas para cada estado (cambios de precios), mapearíamos entonces, mediante una red crítica o un algoritmo, los estados y las acciones a las ganancias esperadas para cada uno. Una vez hecho esto, la política (mapeo de estados a acciones) se puede actualizar gradualmente equilibrando la exploración con la explotación para interpretar mejor los resultados del modelo en la etapa de supervisión (resultados que presentamos como estados).

Sin embargo, esta capacitación en el trabajo implica que, por defecto, se lleva a cabo muy lentamente, porque los datos en vivo sólo llegan a un ritmo muy tibio. Entonces, si el entrenamiento supervisado cubrió un período histórico de 10 años, el entrenamiento de refuerzo por un período de 1 año, ¡en el papel también tomaría 1 año! Por lo tanto, esto hace necesaria una simulación o una clase de entorno más elaborada.

Al simular las condiciones de datos en vivo en un conjunto de datos históricos, no solo aceleramos el ritmo del aprendizaje de refuerzo, sino que también cubrimos muchos más datos que deberían proporcionarnos modelos más resistentes. 

Entonces, para la previsión de series financieras, esto significa que podemos hacer pruebas con los mismos datos que usamos en la supervisión, pero ahora optimizar las redes RL para obtener ganancias basando esto en las acciones tomadas dados los pronósticos de estado (o cambio de precio) realizados con la red en la etapa de supervisión. 

Inferencia:

Habiendo obtenido 2 modelos, uno para hacer los pronósticos básicos (en aprendizaje supervisado) y otro para interpretar y aplicar mejor estos pronósticos (en refuerzo), se nos presenta la 3ra fase, inferencia, donde en esencia tomamos este conocimiento y modelos y los aplicamos a un campo diferente o como sea el caso en nuestra situación un símbolo comercial diferente.

Esto también se conoce como generalizar sobre datos no vistos. La aplicación del conocimiento aprendido en situaciones del mundo real, refinándolo con el tiempo y detectando patrones invisibles sin utilizar etiquetas en los datos. Los gráficos y los autocodificadores juegan un papel muy importante en esta fase, al igual que la agrupación en clústeres. 

En estas tres fases, con cada progresión a la siguiente, las sobrecargas de cómputo disminuyen. Lo cual, en esencia, constituye la justificación de estas fases. Hasta ahora en esta serie se han analizado métodos que implican aprendizaje no supervisado, sin embargo es posible que vuelva a tratarlos pronto con la vista puesta en cómo pueden "continuar" a partir del aprendizaje de refuerzo. Aunque el aprendizaje por repetición se puede utilizar de forma autónoma para pronosticar, estas fases descritas intentan demostrar que puede ser más eficiente utilizarlo con otros modos de aprendizaje.

La combinación de la media móvil (MA) con el oscilador estocástico puede generar una variedad de señales de trading. Examinamos los 10 patrones de señales principales que se generan a partir de la combinación de estos indicadores que los operadores podrían utilizar.


Cruce de medias móviles + sobrecompra/sobreventa estocástica

Este patrón, que surge de la combinación de un indicador de seguimiento de tendencia (MA) y un oscilador de momento (el estocástico), tiende a proporcionar configuraciones de alta probabilidad. La señal de compra es un cruce alcista (donde la MA rápida cruza por encima de la MA rezagada) para confirmar una posible tendencia alcista, mientras que el oscilador estocástico está por debajo de 20. Esto generalmente sugiere que el activo está sobrevendido y que el precio está listo para revertirse. La señal de venta en el otro lado es un cruce bajista. Esto indica que la MA rápida cruza la MA rezagada desde arriba para ir por debajo de ella, lo que por sí mismo es potencialmente un indicador de tendencia bajista. Dado que esto también se supone que está respaldado por el estocástico por encima del nivel 80, una señal de condiciones de sobrecompra, forma una fuerte señal de venta. 

Con nuestro formato de clase de señal ligeramente modificado, donde usamos lecturas de indicadores como características para las redes, ahora tenemos una función de patrón individual que codificamos de la siguiente manera:

//+------------------------------------------------------------------+
//| Check for Pattern.                                               |
//+------------------------------------------------------------------+
double CSignal_MA_STO::IsPattern(int Index, ENUM_POSITION_TYPE T)
{  vectorf _x = Get(Index, m_time.GetData(X()), m_close, m_ma, m_ma_lag, m_sto);
   vectorf _y(1);
   _y.Fill(0.0);
   ResetLastError();
   if(!OnnxRun(m_handles[Index], ONNX_NO_CONVERSION, _x, _y))
   {  printf(__FUNCSIG__ + " failed to get y forecast, err: %i", GetLastError());
      return(double(_y[0]));
   }
   //printf(__FUNCSIG__+" y: "+DoubleToString(_y[0],2));
   if(T == POSITION_TYPE_BUY && _y[0] > 0.5f)
   {  _y[0] = 2.0f * (_y[0] - 0.5f);
   }
   else if(T == POSITION_TYPE_SELL && _y[0] < 0.5f)
   {  _y[0] = 2.0f * (0.5f - _y[0]);
   }
   return(double(_y[0]));
}

Incluimos un archivo '57_X.mqh' que tiene una función para recuperar valores promedio móviles y estocásticos que son entradas a nuestras redes. Estamos considerando hasta 10 patrones diferentes. Esto significa que utilizaremos hasta 10 redes diferentes. Por lo tanto, nuestra función en este archivo de inclusión, «Get», también devolverá hasta 10 conjuntos de datos diferentes, uno para cada red.

«Get» devuelve un vector flotante (vectorf) que podemos introducir fácilmente en una red ONNX. Esta misma función se puede utilizar como alternativa a la biblioteca de importación de MetaTrader 5 en Python, que requeriría normalizar el precio a un formato similar al que se proporciona aquí antes de que la red pueda aceptarlo como entrada. Nuestra red en Python será sencilla y se puede codificar de la siguiente manera:

class SimpleNeuralNetwork(nn.Module):
    def __init__(self):
        super(SimpleNeuralNetwork, self).__init__()
        self.fc1 = nn.Linear(feature_size, 256)  # Input layer to hidden layer 1
        self.fc2 = nn.Linear(256, 256) # Hidden layer 1 to hidden layer 2
        self.fc3 = nn.Linear(256, state_size)   # Hidden layer 2 to output layer
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x = self.sigmoid(self.fc1(x))  # Activation for hidden layer 1
        x = self.sigmoid(self.fc2(x))  # Activation for hidden layer 2
        x = self.fc3(x)              # Output layer (no activation)
        return x

Los parámetros «feature_size» y «state_size» son los tamaños de entrada y salida de nuestra red. El resultado será estándar en los 10 patrones, ya que nos fijaremos como objetivo un valor comprendido entre 0,0 y 1,0. Cualquier valor inferior a 0,5 se interpretará como un cambio negativo previsto, cualquier valor superior a 0,5 se interpretará como positivo y 0,5 se interpretará como estable.

Sin embargo, la configuración de las características no implicará tamaños vectoriales estándar para la entrada, ya que cada patrón puede tener un número diferente de condiciones. Para este patrón, el primero, son 4. Por lo tanto, asignamos el vector de entrada a la red dentro de la función «Get», de la siguiente manera.

if(Index == 0)
{  if(CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(M_LAG.Handle(), 0, T, 2, _ma_lag) >= 2 && CopyBuffer(S.Handle(), 0, T, 1, _sto_k) >= 1)
   {  _v[0] = ((_ma_lag[1] > _ma[1] && _ma_lag[0] < _ma[0]) ? 1.0f : 0.0f);
      _v[1] = ((_sto_k[0] <= 20.0) ? 1.0f : 0.0f);
      _v[2] = ((_sto_k[0] >= 80.0) ? 1.0f : 0.0f);
      _v[3] = ((_ma_lag[1] < _ma[1] && _ma_lag[0] > _ma[0]) ? 1.0f : 0.0f);
   }
}

Para desglosarlo, las condiciones para el patrón alcista son dos, una para cada indicador, y lo mismo se aplica al patrón bajista. Al establecer el vector de entrada, simplemente verificamos si se cumple cada una de las condiciones. Dada la naturaleza espejo o booleana de estas condiciones, el máximo que se puede cumplir en cualquier momento es 2.

Sin embargo, todo está detallado en el vector, ya que esto podría ser informativo para la red. Además, estas 4 condiciones en el caso del patrón 0 podrían dividirse en 6, ya que la primera condición toma 2 argumentos al igual que la cuarta. El lector puede experimentar con esto ya que esta fuente se adjunta al final del artículo.

Una ejecución de entrenamiento y prueba en Python registra los siguientes valores de pérdida para ambas ejecuciones:

Epoch 10/10, Train Loss: 0.2498
Test Loss: 0.2593

 El valor de pérdida de prueba es menor que el valor de pérdida inicial de la primera época (no indicado), pero aún mayor que el valor de pérdida de la décima época. Los datos de precios utilizados para el entrenamiento y la validación corresponden íntegramente al año 2023. Por lo tanto, intentamos avanzar hasta el año 2024 después de optimizar los umbrales de apertura, cierre y patrón adecuados para el patrón 0 en 2023. Esto nos da el siguiente informe.

r0

Caminamos, aunque sólo con largos trayectos. Es necesario entrenar con conjuntos de datos más grandes para ver si es posible lograr ese resultado también con operaciones a corto plazo. Además, esta caminata hacia adelante utiliza pesas de entrenamiento durante un período del 80% de 2023, no durante todo el año. Sin embargo, se aplicarán durante todo el año 2024.


El precio cruza la media móvil y el estocástico confirma la tendencia

Nuestro próximo patrón utiliza la lógica de cruce de precios de MA y la dirección estocástica para establecer sus condiciones largas y cortas. La señal de compra es cuando el precio cruza por encima de la media móvil y el estocástico %K cruza o está por encima del %D. Una señal de venta sería entonces que el precio cruce por debajo de la media móvil, con %K por debajo de %D.

Una vez importados y formateados los datos de precios para introducirlos en nuestra red, el vector de entrada sería similar al resultado de nuestra función «Get», tal y como se destaca a continuación:

else if(Index == 1)
{  if(C.GetData(T, 2, _c) >= 2 && CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2 && CopyBuffer(S.Handle(), 1, T, 2, _sto_d) >= 2)
   {  _v[0] = ((_c[1] < _ma[1] && _c[0] > _ma[0]) ? 1.0f : 0.0f);
      _v[1] = ((_sto_k[1] < _sto_d[1] && _sto_k[0] > _sto_d[0]) ? 1.0f : 0.0f);
      _v[2] = ((_sto_k[1] > _sto_d[1] && _sto_k[0] < _sto_d[0]) ? 1.0f : 0.0f);
      _v[3] = ((_c[1] > _ma[1] && _c[0] < _ma[0]) ? 1.0f : 0.0f);
   }
}

Estamos utilizando el tamaño 4, pero hay más de 4 condiciones en total ya que, como se mencionó anteriormente, algunas condiciones toman más de 1. En este caso, las 4 condiciones toman 2 argumentos, lo que significa que podríamos haber utilizado una entrada de tamaño 8 para la red.

El entrenamiento de la red se realiza mediante la función Train que aparece a continuación:

# Train function
def Train(model, train_loader, optimizer, loss_fn, epochs):
    device = T.device('cuda:0' if T.cuda.is_available() else 'cpu')
    model.to(device)

    for epoch in range(epochs):
        model.train()
        train_loss = 0.0
        
        for batch_idx, (data, target) in enumerate(tqdm(train_loader, desc=f"Epoch {epoch + 1}/{epochs} (Train)")):
            # Step 1: Ensure proper tensor dimensions
            data = data.view(-1, 1, feature_size)
            
            # Step 2: Verify dimensions
            expected_shape = [feature_size]
            actual_shape = list(data.shape[2:])
            if actual_shape != (expected_shape):
                raise RuntimeError(f"Invalid spatial dimensions after reshaping. Got {data.shape[2:]}, expected {[x_data.shape[1]]}")

            # Step 3: Move to device and forward pass
            data, target = data.to(device), target.to(device)
            optimizer.zero_grad()
            output = model(data)
            target = target.view(-1, 1, state_size)
            loss = loss_fn(output, target)
            
            # Step 4: Backpropagation
            loss.backward()
            optimizer.step()
            train_loss += loss.item()

        train_loss /= len(train_loader)
        print(f"Epoch {epoch + 1}/{epochs}, Train Loss: {train_loss:.4f}")

Train durante el año 2023 presenta los siguientes registros de funciones de pérdida:

Epoch 10/10, Train Loss: 0.2491
Test Loss: 0.2592

 Un forward hacia el año 2024 nos ofrece el siguiente informe:

r1

Tenemos una perspectiva prometedora, pero con un número de operaciones cortas algo escaso en comparación con las largas. Más entrenamiento debería resolver esto. Este patrón captura los primeros movimientos de tendencia, ya que el objetivo es que el precio cruce la media móvil, lo que podría indicar un cambio de tendencia y debería retrasarse menos de dos cruces de medias móviles, como vimos en el patrón 0. También filtra muchas falsas rupturas, ya que se utiliza el estocástico como confirmación, lo que ayuda a evitar operaciones prematuras.

Este patrón también tiene sus debilidades y limitaciones. En primer lugar, la naturaleza rezagada de la MA, especialmente cuando se utilizan períodos más largos, puede hacer que las entradas a las operaciones sean lentas. Usamos un período de 8 en el marco de tiempo diario de manera predeterminada, pero este es un parámetro optimizable para la clase de señal personalizada, por lo que los lectores pueden ajustarlo a lo que funcione. En segundo lugar, el oscilador estocástico es famoso por ser muy volátil, especialmente en mercados con fluctuaciones. Esto puede dar lugar a muchas confirmaciones falsas. Además, en situaciones en las que un activo ya tiene una tendencia fuerte, esperar un cruce de precios desde la media móvil podría dar lugar a que se pierdan muchas entradas tempranas.

En lo que se refiere a la optimización de los períodos del indicador, una MA corta en el rango de menos de 20 períodos seguramente reaccionará más rápido a los cambios de precios que, por ejemplo, un período más largo en el rango de 50 a 200. Por lo tanto, los usuarios deben tener en cuenta el marco temporal que utilizan para decidir si buscan reacciones rápidas o desean estabilidad y más certeza antes de aceptar los cambios.

De manera similar, para el estocástico, (5,3,3) proporciona configuraciones más rápidas, pero las señales generadas seguramente serán ruidosas. Se podrían considerar configuraciones más lentas, por ejemplo (14,5,5), más apropiadas, pero nuevamente, esto es algo que se debe tener en cuenta junto con el marco de tiempo que se está utilizando. En la clase de señal personalizada que utilizamos para estas pruebas, hemos empleado un periodo de indicador estándar para la media móvil y el oscilador estocástico. Estos son personalizables, pero a modo de ejemplo, si el periodo de nuestra media móvil es N, el oscilador estocástico será (N,3,3) y la media móvil lenta o rezagada será 2 x N.

Los picos de volumen también se pueden utilizar para confirmar aún más los cruces de MA o la fuerza de una ruptura. Los niveles de soporte y resistencia también se pueden utilizar para mejorar aún más la confiabilidad del patrón.


Pendiente de la media móvil + Confirmación de la tendencia estocástica

Este patrón se centra en la dirección de la tendencia mediante el uso de la pendiente de la media móvil (MA) mientras confirma el impulso con el estocástico. Una señal de compra es cuando el promedio móvil tiene una pendiente ascendente Y el estocástico está por encima de 50 y está aumentando. La señal de venta es la inversa. Con la media móvil inclinada hacia abajo, mientras que el estocástico estaría por debajo de 50 y cayendo. Así es como nuestra función «Get» recupera un vector de entrada que comprueba estas condiciones:

else if(Index == 2)
{  if(C.GetData(T, 2, _c) >= 2 && CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2)
   {  _v[0] = ((_ma[1] < _ma[0]) ? 1.0f : 0.0f);
      _v[1] = ((_sto_k[1] < _sto_k[0] && _sto_k[1] >= 50.0) ? 1.0f : 0.0f);
      _v[2] = ((_sto_k[1] > _sto_k[0] && _sto_k[1] <= 50.0) ? 1.0f : 0.0f);
      _v[3] = ((_ma[1] > _ma[0]) ? 1.0f : 0.0f);
   }
}

Este es el primer patrón de los 10 en los que utilizamos el segundo buffer estocástico, también conocido como %K. Siempre está retrasado respecto del búfer principal (%D) y su uso aquí ayuda a confirmar la pendiente de este oscilador. Una vez que los vectores de estos datos, a lo largo del año 2023 para EURJPY, se exportan a Python, entrenaremos la red simple que enumeramos anteriormente con la función "Entrenamiento" también mencionada anteriormente. Las pruebas o la validación cruzada se realizarían mediante una función muy similar a nuestra función «Train» anterior, a la que hemos denominado función «Test». Su listado en Python es el siguiente:

# Test function
def Test(model, test_loader, optimizer, loss_fn, epochs):
    device = T.device('cuda:0' if T.cuda.is_available() else 'cpu')
    model.to(device)
    
    with T.no_grad():
        test_loss = 0.0
        
        for batch_idx, (data, target) in enumerate(tqdm(test_loader, desc=f"Loss at {test_loss} in (Test)")):
            # Step 1: Ensure proper tensor dimensions
            data = data.view(-1, 1, feature_size)
            
            ...

            # Step 3: Move to device and forward pass
            data, target = data.to(device), target.to(device)
            optimizer.zero_grad()
            output = model(data)
            target = target.view(-1, 1, 1)
            #print(f"target: {target.shape}, plus output: {output.shape}")
            loss = loss_fn(output, target)
            test_loss += loss.item()

        test_loss /= len(test_loader)
        print(f"Test Loss: {test_loss:.4f}")

Los puntajes comparativos de pérdida de train y test están en línea con lo que se compartió anteriormente con los patrones 0 y 1 y, por lo tanto, no se publicarán aquí. Un forward hacia el año 2024 en el Probador de estrategias de MetaTrader nos presenta el siguiente informe:

r2

Nuestro patrón es capaz de dar un paso lateral, ya que solo están abiertas las posiciones largas. El entrenamiento con conjuntos de datos más grandes debería resolver este problema. Sin embargo, el patrón 2 es un buen filtro para mercados con distintos rangos de variación. La pendiente de la MA hace que ciertas operaciones se realicen solo cuando hay una tendencia clara. La confirmación de la fuerza de la tendencia la realiza luego el oscilador estocástico, ya que la posición relativa al umbral 50 valida el impulso en la tendencia predominante. En términos generales, también hay una reducción en el retraso, ya que no hay que esperar los cruces de medias móviles como ocurre con los patrones anteriores. Esto significa que este patrón es un buen augurio para la aceleración de la tendencia.

Sus principales debilidades incluyen una reacción lenta a los cambios de tendencia, ya que la pendiente de una media móvil puede tardar un tiempo en cambiar después de un cambio de tendencia. Además, el estocástico en estas situaciones puede ser propenso a dar señales tardías. Si ya hay una tendencia en juego, esperar a que el estocástico la confirme puede provocar que se pierdan entradas anticipadas. En general, este patrón tampoco es adecuado para mercados laterales dada su fuerte dependencia de las tendencias.

Combinarlo con filtros adicionales como el ADX (Average Directional Index) puede ayudar a confirmar tendencias fuertes. Además, verificar si hay rupturas o retrocesos de la acción del precio debería mejorar la precisión. Los casos de uso prácticos podrían incluir forex (que es lo que estamos probando aquí; o acciones, ya que este patrón puede ayudar a identificar tendencias de continuación después de pequeños retrocesos; o criptomonedas y materias primas, ya que es útil para capturar movimientos inducidos por el impulso en activos como el oro o Bitcoin.


Rebote de MA con divergencia estocástica

Este patrón funciona combinando el soporte/resistencia dinámicos de los rebotes de precios del promedio móvil con la divergencia del impulso del oscilador estocástico para identificar posibles reversiones antes de que sucedan. La señal de compra es cuando el precio rebota en una MA con pendiente ascendente (que en este caso actuaría como soporte) y el oscilador estocástico muestra una divergencia alcista de modo que el precio forma un mínimo más bajo mientras que el oscilador forma un mínimo más alto. 

La señal de venta es cuando el precio rechaza una MA con pendiente descendente que actúa como resistencia y el oscilador estocástico indica una divergencia bajista donde el precio marca un máximo más alto pero el estocástico marca un máximo más bajo. La implementación en MQL5 y la definición de la entrada a la red que procesa este patrón se maneja de la siguiente manera:

else if(Index == 3)
{  _v.Init(6);
   _v.Fill(0.0);
   if(C.GetData(T, 3, _c) >= 3 && CopyBuffer(M.Handle(), 0, T, 3, _ma) >= 3 && CopyBuffer(S.Handle(), 0, T, 3, _sto_k) >= 3)
   {  _v[0] = ((_c[2] > _c[1] && _c[1] < _c[0] &&  _c[0] < _c[2] && _ma[1] >= _c[1]) ? 1.0f : 0.0f);
      _v[1] = ((_sto_k[2] > _sto_k[1] && _sto_k[1] < _sto_k[0] && _sto_k[1] >= 40.0) ? 1.0f : 0.0f);
      _v[2] = ((_ma[2] > _ma[0]) ? 1.0f : 0.0f);
      _v[3] = ((_ma[2] < _ma[0]) ? 1.0f : 0.0f);
      _v[4] = ((_sto_k[2] < _sto_k[1] && _sto_k[1] > _sto_k[0] && _sto_k[1] <= 60.0) ? 1.0f : 0.0f);
      _v[5] = ((_c[2] < _c[1] && _c[1] > _c[0] &&  _c[0] > _c[2] && _ma[1] <= _c[1]) ? 1.0f : 0.0f);
   }
}

Las puntuaciones de la función de pérdida de validación de entrenamiento y prueba (train y test)no son muy diferentes de los registros de los primeros 2 patrones, cuyos registros fueron compartidos. La función de pérdida de prueba es menor que la función de pérdida del entrenamiento en la primera época, pero todavía es menor que la función de pérdida en la décima época. El informe forward walk del año 2024, después del entrenamiento del año 2023, es el siguiente:

r3

Un forward walk positivo siempre es una buena señal, siempre que se abran posiciones largas y cortas de manera equilibrada. Este no es el caso aquí. Sin embargo, el patrón 3 es bueno para detectar reversiones tempranas, ya que la divergencia estocástica suele indicar reversiones de tendencia antes de que el precio reaccione. También evita seguir la tendencia, de modo que, en lugar de entrar tarde, los operadores entran cerca del nivel dinámico de soporte/resistencia. También funciona bien en mercados con tendencia, ya que el rebote de la media móvil confirmaría la tendencia, mientras que la divergencia advierte del agotamiento.

Las debilidades y limitaciones son sus señales falsas cuando los mercados tienen una tendencia fuerte. Esto se debe a que en estas situaciones la divergencia por sí sola a menudo no es suficiente para producir una reversión. Además, el efecto MA rezagado desde el rebote de la MA puede no siempre alinearse perfectamente con el momento de la divergencia y el requisito de confirmación para mejorar la precisión también son desventajas.

El patrón 3 se puede optimizar al combinarlo con patrones de velas (como barras pin o barras envolventes) en el nivel de MA para fortalecer la configuración. Los picos de volumen también pueden complementarse para confirmar la divergencia.


MA actuando como soporte/resistencia dinámico + cruce estocástico

Nuestra estrategia patrón-4 es una combinación de seguimiento de tendencias (cuando se utiliza la media móvil (MA) para la dirección, así como para el soporte/resistencia) y confirmación del impulso (que se realiza verificando los cruces estocásticos) para generar señales de compra y venta utilizables.

La señal de compra es cuando el precio se mantiene por encima de una MA con pendiente ascendente y el estocástico %K cruza por encima del %D. Este patrón alcista ayuda a garantizar una serie de requisitos previos clave para una posición larga. En primer lugar, sirve como confirmación de tendencia, ya que una MA con pendiente ascendente garantiza que las operaciones realizadas estén alineadas con la dirección predominante del mercado.

En segundo lugar, el cruce del estocástico proporciona una entrada sincronizada con el impulso. Esto se debe a que un cambio en el impulso a menudo confirma una renovada presión de compra. Se evitan entradas prematuras desde cualquier toque de MA, ya que el cruce estocástico garantiza que haya impulso antes de comprar. Por tanto se reducen las señales falsas. Una posible desventaja es que puede perderse las rupturas tempranas, ya que espera ambas condiciones, lo que da como resultado entradas ligeramente retrasadas.

La señal de venta es cuando el precio se mantiene por debajo de una media móvil con pendiente descendente y el estocástico %K cruza por debajo del %D. De manera similar, al igual que su contraparte alcista, proporciona una confirmación de tendencia, es una entrada o salida basada en el impulso, no hay entradas prematuras y se filtran las señales débiles. La desventaja potencial es que en mercados volátiles el precio puede romper la media móvil antes de reanudar el descenso. Esto es particularmente clave porque para la mayoría de los símbolos comerciales, sus descensos tienden a ser más volátiles que sus tendencias alcistas. Implementamos esto de la siguiente manera en MQL5:

else if(Index == 4)
{  if(C.GetData(T, 2, _c) >= 2 && CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2 && CopyBuffer(S.Handle(), 1, T, 2, _sto_d) >= 2)
   {  _v[0] = ((_sto_k[1] < _sto_d[1] && _sto_k[0] > _sto_d[0]) ? 1.0f : 0.0f);
      _v[1] = ((_ma[1] < _c[1] && _ma[0] < _c[0] && _ma[1] < _ma[0]) ? 1.0f : 0.0f);
      _v[2] = ((_ma[1] > _c[1] && _ma[0] > _c[0] && _ma[1] > _ma[0]) ? 1.0f : 0.0f);
      _v[3] = ((_sto_k[1] > _sto_d[1] && _sto_k[0] < _sto_d[0]) ? 1.0f : 0.0f);
    }
}

Procesamos el vector de entrada a la red y este patrón en una dimensión de tamaño 4. Como se muestra en los patrones anteriores, este vector se puede hacer más explícito al tener cada uno de los argumentos dentro de una condición delineada como parte de las entradas. Un forward walk por la red entrenada solo con el patrón 4 nos da los siguientes resultados:

r4

Este patrón debería funcionar bien en mercados que siguen tendencias, pero seguramente tendrá dificultades en escenarios de rango limitado. Si bien tenemos un forward walk favorable, es importante realizar pruebas en conjuntos de datos más grandes para garantizar que podamos realizar operaciones tanto largas como cortas, no solo largas como se informó anteriormente.


Reversión estocástica de sobrecompra/sobreventa cerca de la media móvil

El patrón 5 combina el seguimiento de tendencias con la MA como soporte/resistencia dinámico y la reversión del impulso con el estocástico. La señal de compra es cuando el estocástico cruza por encima del umbral 20 mientras el precio está respaldado por la media móvil (MA). Este patrón proporciona una validación de soporte dinámico, ya que la MA actúa como una zona de soporte, garantizando que el precio rebote dentro de una tendencia alcista existente. El cruce estocástico por encima de 20 también indica que el impulso bajista se está debilitando y los compradores están entrando al mercado. El uso de dos indicadores no sólo evita entradas prematuras, sino que también es una configuración de alta probabilidad. La desventaja potencial es que en tendencias bajistas fuertes, el precio puede mantenerse temporalmente en la media móvil antes de caer.

La señal de venta es cuando el estocástico cruza por debajo de 80 mientras el precio está cerca de la resistencia de una media móvil con pendiente descendente. Esto también actúa como una validación de resistencia dinámica, ya que la MA funciona como una zona de resistencia que sirve como prueba de que el precio no ha logrado subir más. La confirmación de reversión de sobrecompra indica que el impulso alcista está menguando y que los vendedores están entrando. Una vez más, el uso del indicador dual evita salidas/entradas prematuras y también filtra retrocesos débiles. Una posible desventaja de la señal bajista del patrón 5 es que, en tendencias bajistas fuertes, el precio puede consolidarse por encima de la media móvil antes de caer, lo que podría llevar a salidas tardías o a perder pips.

Implementamos esto de la siguiente manera en MQL5:

else if(Index == 5)
{  if(C.GetData(T, 3, _c) >= 3 && CopyBuffer(M.Handle(), 0, T, 3, _ma) >= 3 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2)
   {  _v[0] = ((_sto_k[1] < 20.0 && _sto_k[0] > 20.0) ? 1.0f : 0.0f);
      _v[1] = ((_c[2] > _c[1] && _c[1] < _c[0] && _c[1] >= _ma[1]) ? 1.0f : 0.0f);
      _v[2] = ((_c[2] < _c[1] && _c[1] > _c[0] && _c[1] <= _ma[1]) ? 1.0f : 0.0f);
      _v[3] = ((_sto_k[1] > 80.0 && _sto_k[0] < 80.0) ? 1.0f : 0.0f);
   }
}

Nuestras implementaciones de patrones MQL5 para este artículo tienen como objetivo establecer o definir un vector de entrada para una red neuronal. Definimos estos vectores de entrada como simplemente una colección de 0 y 1, donde 1 es si se cumple una condición particular, larga o corta. Los índices para condiciones largas y cortas están separados, lo que técnicamente significa que no es posible tener un vector de entrada que esté lleno de 1, ya que las condiciones largas y cortas siempre se reflejan entre sí.

Además, la condición en cada índice se puede detallar o alargar aún más haciendo que cada uno de los argumentos de la condición ocupe su propio índice. Esto conduciría a vectores de entrada mucho más largos, pero no lo hemos explorado. Ya que estamos haciendo pruebas y entrenando para el año 2023, este es el forward walk para el año 2024. Nos da el siguiente informe:

r5

Ahora podemos seguir adelante con el patrón 5, con una salvedad. ¡Solo se realizaron operaciones largas! Esto se debe principalmente al entrenamiento con conjuntos de datos limitados o pequeños, de modo que los resultados de la red se sesgan hacia esa pequeña muestra. El entrenamiento con conjuntos de datos más grandes debería solucionar este problema.


Cruce dorado / Cruce de la muerte + Confirmación estocástica

El patrón 6 utiliza la Cruce dorado / Cruce de la muerte, donde la media móvil de período más corto cruza la media móvil rezagada y el impulso también se verifica cuando el estocástico cruza el nivel 50. La señal de compra es la Cruce dorado de la media móvil de período más corto cruzando de abajo hacia arriba la media móvil de período más largo, mientras que el estocástico está por encima de 50 y en ascenso. La señal de venta es la Cruce de la muerte, con la media móvil de período más corto cruzando la de período más largo desde arriba para cerrar por debajo de ella, mientras que el estocástico está por debajo de 50 y cayendo. Configuramos las entradas para la red del patrón 6 de la siguiente manera:

else if(Index == 6)
{  if(CopyBuffer(M.Handle(), 0, T, 2, _ma_lag) >= 2 && CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2 && CopyBuffer(S.Handle(), 0, T, 2, _sto_d) >= 2)
   {  _v[0] = ((_ma_lag[1] > _ma[1] && _ma_lag[0] < _ma[0]) ? 1.0f : 0.0f);
      _v[1] = ((50.0 <= _sto_d[0] && _sto_k[0] > _sto_d[0]) ? 1.0f : 0.0f);
      _v[2] = ((50.0 >= _sto_d[0] && _sto_k[0] < _sto_d[0]) ? 1.0f : 0.0f);
      _v[3] = ((_ma_lag[1] > _ma[1] && _ma_lag[0] < _ma[0]) ? 1.0f : 0.0f);
   }
}

En nuestra fuente utilizada, el identificador «_ma» es la media móvil de período más corto, a la que en nuestro entrenamiento hemos asignado el período 8. El promedio de período más largo utiliza el identificador «_ma_lag» y su período es el doble que el más corto, con una longitud de 16. Un forward walk del año 2024 tras el entrenamiento del año 2023 nos ofrece este informe:

r6

El patrón 6 falla no solo en cuanto a rentabilidad, sino también en cuanto al equilibrio entre posiciones largas y cortas. Sin embargo, esto puede llevarse más allá con una formación y unas pruebas exhaustivas antes de descartarlo.


Reversión extrema estocástica + confirmación de la tendencia de la media móvil

El patrón 7 utiliza la inflexión estocástica en niveles extremos junto con la posición relativa del precio con respecto a la media móvil para definir sus señales de entrada. La señal de compra se produce cuando el estocástico está por debajo de 10 y comienza a subir, mientras que el precio se encuentra por encima de una media móvil ascendente. La señal de venta es una caída por debajo de 90 cuando el precio se encuentra por debajo de una media móvil descendente. Lo mapeamos de la siguiente manera a una red desde MQL5:

else if(Index == 7)
{  if(C.GetData(T, 2, _c) >= 2 && CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(S.Handle(), 0, T, 3, _sto_k) >= 3)
   {  _v[0] = ((_ma[0] > _ma[1] && _c[0] > _ma[0]) ? 1.0f : 0.0f);
      _v[1] = ((_sto_k[0] > _sto_k[1] && _sto_k[1] < _sto_k[2] && _sto_k[2] <= 10.0) ? 1.0f : 0.0f);
      _v[2] = ((_sto_k[0] < _sto_k[1] && _sto_k[1] > _sto_k[2] && _sto_k[2] >= 90.0) ? 1.0f : 0.0f);
      _v[3] = ((_ma[0] < _ma[1] && _c[0] < _ma[0]) ? 1.0f : 0.0f);
   }
}

Aquí utilizamos estrictamente el indicador %K para el estocástico y lo único que hacemos es comprobar si se produce un giro en forma de n para las condiciones alcistas o una reversión en forma de u para las bajistas cuando se alcanzan niveles extremos. Un forward walk nos da el siguiente informe:

r7

A partir de nuestros resultados anteriores, este patrón tampoco puede avanzar un año basándose en las pruebas del año anterior. Y solo realiza operaciones bajistas. Realizar operaciones unilaterales en un forward walk puede ser preocupante. Dado que nuestro resultado es un valor flotante escalar en el rango 0,0-1,0, esto significa que todas las previsiones fueron inferiores a 0,5. Para corregir esto es importante realizar pruebas y entrenamiento en conjuntos de datos más grandes.


Ruptura estocástica con confirmación de media móvil

Nuestro penúltimo patrón, el patrón 8, combina el umbral estocástico 50 con los cruces del precio y la media móvil. Una señal de compra se produce cuando hay un repunte en el impulso, tal y como indica el oscilador estocástico al cruzar el umbral de 50 desde abajo y cerrar por encima de él, mientras que, simultáneamente, el precio cruza la media móvil de forma similar para cerrar también por encima de ella. La venta es lo inverso, con el oscilador cruzando por debajo de 50 mientras el precio rompe el soporte de la MA. Este seguramente será un patrón que no genere muchas transacciones, si lo aplicamos de manera similar a lo que estábamos haciendo en artículos anteriores. Sin embargo, ahora estamos comprobando por separado las condiciones MA y estocásticas para las señales alcistas y bajistas. Esto se hace de la siguiente manera en MQL5:

else if(Index == 8)
{  if(C.GetData(T, 2, _c) >= 2 && CopyBuffer(M.Handle(), 0, T, 2, _ma) >= 2 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2 && CopyBuffer(S.Handle(), 1, T, 2, _sto_d) >= 2)
   {  _v[0] = ((_c[1] < _ma[1] && _c[0] > _ma[0]) ? 1.0f : 0.0f);
      _v[1] = ((_sto_k[1] < 50.0 && _sto_k[0] > 50.0) ? 1.0f : 0.0f);
      _v[2] = ((_sto_k[1] > 50.0 && _sto_k[0] < 50.0) ? 1.0f : 0.0f);
      _v[3] = ((_c[1] > _ma[1] && _c[0] < _ma[0]) ? 1.0f : 0.0f);
   }
}

Ahora, nuestro vector de entrada para la red del patrón 8 tiene más probabilidades de tener o registrar al menos una de las condiciones alcistas o bajistas, lo que ayuda con el entrenamiento, pero también con la adaptabilidad a la hora de implementar la red. Esto se debe a que, además de procesar ambos indicadores, ofrecería previsiones si solo uno de ellos registrara los patrones objetivo. Un forward walk nos da lo siguiente:

r8

Parece que este patrón es capaz de caminar, lo cual es alentador. Cabe mencionar aquí algunas advertencias importantes. En primer lugar, estas pruebas se realizan con objetivos de precio (take-profits) y sin stop loss. Es cierto, el stop loss nunca garantiza el precio de salida, pero es necesario contar con alguna estrategia para hacer frente a las operaciones fallidas. En segundo lugar, entrenamos con los datos del año anterior y realizamos las pruebas con los del año siguiente, lo que supone un periodo de prueba relativamente corto. A menudo se prefieren periodos de prueba más largos con datos de brókeres de buena calidad.


Compresión de la media móvil con ruptura estocástica

Nuestro patrón final, el 9, aprovecha la compresión de la media móvil para detectar condiciones de baja volatilidad junto con el impulso estocástico para sincronizar las rupturas de estas condiciones. La señal de compra se produce cuando dos medias móviles, una de periodo más corto y otra de periodo más largo, se comprimen juntas durante un periodo prolongado, tras lo cual se registra un repunte del impulso, según el estocástico, que se mueve bruscamente por encima de 50. Una señal bajista también registra las mismas condiciones, con la primera diferencia de que la compresión alcista tiene la media móvil más corta por encima de la media móvil más larga, mientras que para la señal de venta esto se invierte, y el estocástico para la venta cae bruscamente por debajo del nivel 50 (en lugar de subir).

Recuperamos el vector de entrada de red de MQL5 de la siguiente manera:

else if(Index == 9)
{  if(CopyBuffer(M.Handle(), 0, T, 3, _ma) >= 3 && CopyBuffer(M_LAG.Handle(), 0, T, 3, _ma_lag) >= 3 && CopyBuffer(S.Handle(), 0, T, 2, _sto_k) >= 2)
   {  _v[0] = ((_ma_lag[0] < _ma[0] && fabs(fabs(_ma_lag[2] - _ma[2]) - fabs(_ma_lag[0] - _ma[0])) <= fabs(_ma[2] - _ma[0])) ? 1.0f : 0.0f);
      _v[1] = ((_sto_k[1] <= 45.0 && _sto_k[0] >= 55.0) ? 1.0f : 0.0f);
      _v[2] = ((_sto_k[1] >= 55.0 && _sto_k[0] <= 45.0) ? 1.0f : 0.0f);
      _v[3] = ((_ma_lag[0] > _ma[0] && fabs(fabs(_ma_lag[2] - _ma[2]) - fabs(_ma_lag[0] - _ma[0])) <= fabs(_ma[2] - _ma[0])) ? 1.0f : 0.0f);
   }
}

Y los resultados de su avance son los siguientes:

r9

El patrón 9 tampoco parece tener consistencia, a pesar de poder realizar operaciones tanto largas como cortas. Sobre una base de ponderación igual, no se debería estudiar más, ya que tenemos algunos patrones arriba que tuvieron recorridos favorables, pero esta decisión depende del comerciante y de cuántas pruebas más esté dispuesto a hacer.


Conclusión

No hemos entrado en combinar patrones ni en seleccionar diferentes patrones para llegar a un sistema unificado. Esto es algo que seguramente será peligroso, como hemos observado en artículos anteriores, especialmente el último. El uso de múltiples patrones a la vez requiere que el operador esté familiarizado con ellos, ya que pueden anularse mutuamente. Si se utilizan números mágicos en el seguimiento, esto podría ayudar, pero aún así podrían seguir existiendo dificultades con los límites de margen. En la siguiente parte, veremos cómo el aprendizaje por refuerzo puede aprovechar lo que hemos aprendido hasta ahora.

Archivo Descripción
57_0.onnx Patrón 0 (Red)
57_1.onnx
Patrón 1
57_2.onnx
Patrón 2
57_3.onnx
Patrón 3
57_4.onnx
Patrón 4
57_5.onnx
Patrón 5
57_6.onnx
Patrón 6
57_7.onnx
Patrón 7
57_8.onnx
Patrón 8
57_9.onnx
Patrón 9
SignalWZ_57.mqh Archivo de clase de señal
57_X.mqh Archivo de señal para procesar entradas de red
wz_57.mq5 Incluido para mostrar los archivos utilizados en el ensamblaje del Asesor experto


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

Archivos adjuntos |
57_X.mqh (6.58 KB)
57_0.onnx (263.83 KB)
57_1.onnx (263.83 KB)
57_2.onnx (263.83 KB)
57_3.onnx (265.83 KB)
57_4.onnx (263.83 KB)
57_5.onnx (263.83 KB)
57_6.onnx (263.83 KB)
57_7.onnx (263.83 KB)
57_8.onnx (263.83 KB)
57_9.onnx (263.83 KB)
wz_57.mq5 (7.93 KB)
SignalWZ_57.mqh (16.11 KB)
Dariusz Pawel Toczko
Dariusz Pawel Toczko | 14 mar 2025 en 18:12
Hola, falta un archivo adjunto SignalWZ_57.mqh
Anil Varma
Anil Varma | 17 mar 2025 en 05:11
Dariusz Pawel Toczko #:
Hola, falta un archivo adjunto SignalWZ_57.mqh

Yeah I also faced the same problem of missing SignalWZ_57.mqh file.

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.
Creación de un Panel de administración de operaciones en MQL5 (Parte IX): Organización del código (III): Módulo de comunicación Creación de un Panel de administración de operaciones en MQL5 (Parte IX): Organización del código (III): Módulo de comunicación
Únase a nosotros para profundizar en los últimos avances en el diseño de la interfaz MQL5, mientras presentamos el panel de comunicaciones rediseñado y continuamos nuestra serie sobre la creación del nuevo Panel de administración utilizando los principios de la modularización. Desarrollaremos la clase CommunicationsDialog paso a paso, explicando detalladamente cómo heredarla de la clase Dialog. Además, aprovecharemos las matrices y la clase ListView en nuestro desarrollo. Obtenga información útil para mejorar sus habilidades de desarrollo en MQL5: ¡lea el artículo y participe en el debate en la sección de comentarios!
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.
Aprendizaje automático y Data Science (Parte 34): Descomposición de series temporales, desglosando el mercado bursátil hasta su núcleo Aprendizaje automático y Data Science (Parte 34): Descomposición de series temporales, desglosando el mercado bursátil hasta su núcleo
En un mundo repleto de datos ruidosos e impredecibles, identificar patrones significativos puede resultar complicado. En este artículo, exploraremos la descomposición estacional, una potente técnica analítica que ayuda a separar los datos en sus componentes clave: tendencia, patrones estacionales y ruido. Al desglosar los datos de esta manera, podemos descubrir información oculta y trabajar con datos más claros y fáciles de interpretar.