
Ejemplo de nuevo Indicador y LSTM condicional
Introducción
En el dinámico mundo de los mercados financieros, los comerciantes y analistas siempre están buscando formas nuevas y creativas de obtener una ventaja sobre sus competidores. Este artículo examina un nuevo método de comercio automatizado que combina las habilidades de predicción del aprendizaje profundo con la fortaleza del análisis técnico convencional. Buscamos desarrollar una técnica de trading estable y flexible que pueda manejar las complejidades de los mercados contemporáneos, fusionando un modelo neuronal complejo de tipo LSTM Condicional (Conditional Long Short-Term Memory) con un indicador técnico propietario, el Momentum Ajustado por Volatilidad (Volatility Adjusted Momentum, VAM).
La industria financiera ha utilizado durante mucho tiempo indicadores técnicos para detectar tendencias y posibles oportunidades comerciales. A pesar de su importancia, estos indicadores con frecuencia no logran captar plenamente las complejidades de la dinámica del mercado, en particular durante períodos de extrema volatilidad o cambios abruptos. Sin embargo, las arquitecturas de aprendizaje profundo como LSTM, en particular, han demostrado un potencial sorprendente en los modelos de aprendizaje automático para el reconocimiento y la predicción de patrones en datos complicados y dependientes del tiempo. Sin embargo, estos modelos no siempre ofrecen la interpretabilidad y el conocimiento específico del dominio que ofrece el análisis técnico convencional.
Nuestra estrategia pretende cerrar esta brecha fusionando las ventajas de ambos enfoques. Este artículo presenta una nueva herramienta denominada indicador Volatility Adjusted Momentum (VAM), que intenta medir el impulso del mercado teniendo en cuenta la volatilidad subyacente. En comparación con los indicadores de impulso convencionales, este ofrece una imagen más detallada de la dinámica del mercado. El VAM tiene como objetivo proporcionar señales más confiables en una variedad de escenarios de mercado, desde tranquilos hasta tormentosos, teniendo en cuenta la volatilidad.
Para mejorar el indicador VAM, utilizamos un modelo LSTM condicional, que es un tipo de red neuronal recurrente diseñada para procesar datos secuenciales con datos contextuales adicionales. Debido a que está entrenado utilizando datos de precios históricos e indicadores técnicos, este modelo puede identificar vínculos de mercado intrincados y no lineales que las técnicas de análisis convencionales podrían pasar por alto. Debido a la característica "condicional" del LSTM, el modelo puede tener en cuenta más variables de mercado, lo que podría generar pronósticos más precisos y conscientes del contexto.
El Asesor Experto (EA), un sistema de trading automático especialmente diseñado que combina el indicador VAM con pronósticos del modelo LSTM Condicional, es el cerebro detrás de nuestra estrategia. Utilizando las señales de ambos componentes, este Asesor Experto (Expert Advisor, EA) se integra en la conocida plataforma MetaTrader 5 para ayudar a los operadores a tomar decisiones bien informadas. Además, cuenta con capacidades de gestión dinámica de riesgos que modifican los niveles de take-profit y stop-loss en respuesta a las fluctuaciones del mercado.
En esta publicación examinaremos los fundamentos teóricos de los modelos de indicadores LSTM condicional y VAM, ofreciendo información sobre sus respectivas ventajas y formas en que funcionan mejor juntos. Repasaremos cada paso de la creación y puesta en práctica del EA, incluida la configuración de los datos, el entrenamiento del modelo y su integración en el entorno de MetaTrader 5. Además, mostraremos los resultados de una optimización integral y pruebas retrospectivas, contrastando la efectividad de la técnica solo VAM con el método combinado VAM y LSTM condicional.
Hablaremos sobre las dificultades y los factores involucrados en la fusión de métodos de aprendizaje automático de vanguardia con el análisis técnico convencional mientras investigamos esta novedosa estrategia comercial. Buscamos ofrecer una descripción completa de los elementos prácticos necesarios para implementar un sistema de este tipo, incluyendo todo, desde la calidad de los datos y la interpretabilidad del modelo hasta las demandas computacionales de ejecutar modelos complicados en situaciones comerciales en tiempo real.
Al finalizar este ensayo, los lectores comprenderán a fondo cómo se pueden utilizar técnicas de aprendizaje automático de vanguardia para ampliar el análisis técnico tradicional y, potencialmente, mejorar los resultados comerciales. Esta investigación sobre VAM y LSTM condicional en el trading automatizado ofrece información reveladora sobre el futuro del trading algorítmico, independientemente de su experiencia como trader, científico de datos o investigador que investiga los límites de las finanzas cuantitativas.
Momentum ajustado por volatilidad (Volatility Adjusted Momentum, VAM)
El concepto central detrás del VAM es tener en cuenta la volatilidad del mercado al evaluar el impulso. Calcula la diferencia entre el precio actual y un precio pasado (momentum) y luego la divide por el producto de la volatilidad y la raíz cuadrada del período de momentum. Este valor, escalado por un factor, indica la fortaleza del impulso ajustado a la volatilidad reciente del mercado.
Modelo de aprendizaje profundo
El artículo utiliza un modelo LSTM condicional, un tipo de red neuronal recurrente (Recurrent Neural Network, RNN) adecuada para datos de series de tiempo financieras. Este modelo toma datos de precios históricos e indicadores técnicos (como el MACD utilizado aquí) como entrada y predice movimientos de precios futuros. La ventaja de los LSTM condicionales radica en su capacidad de capturar relaciones complejas entre varios factores del mercado.
El Asesor Experto (Expert Advisor, EA)
En el artículo se describe la creación de un EA que combina las predicciones del modelo de aprendizaje profundo con VAM. A continuación se muestra un resumen de las principales características:
- Inicialización: El EA carga y configura los parámetros de entrada y salida para el modelo de aprendizaje profundo ONNX preentrenado.
- Adquisición y normalización de datos: El EA recopila lecturas MACD y datos de precios anteriores. Antes de introducir estas variables en el modelo de aprendizaje profundo, las normaliza.
- Cálculo del VAM: Utilizando datos de precios históricos y actuales, el EA calcula el indicador VAM.
- Lógica de trading y predicción: El EA extrae una predicción de precios del modelo de aprendizaje profundo.
- El EA inicia una operación de compra si VAM es alto y la predicción apunta a un aumento de precio.
- Por el contrario, el EA abre una operación de venta si el VAM es bajo y la predicción muestra una caída en el precio.
Al determinar dinámicamente los niveles de stop-loss y take-profit según el rango verdadero promedio (Average True Range, ATR), el EA gestiona el riesgo.
Resultados:
El artículo menciona los resultados de backtesting para el EA usando el VAM con y sin la estrategia LSTM condicional.
Vamos a crear un nuevo indicador (VAM)
¿Qué pasa si creamos un nuevo indicador, por ejemplo este?
// Calcular Momentum double momentum = close_price - iClose(NULL, 0, momentum_period); // Calcular Volatilidad double volatility = iMA(NULL, 0, volatility_period, 0, MODE_SMA, PRICE_CLOSE); // Calcular VAM double vam =( momentum / (volatility * MathSqrt(momentum_period)))*10000;
Utilizaremos el Momentum y la Volatilidad, para crear un nuevo indicador, este indicador se llamará VAM.
El impulso se divide por el producto de la raíz cuadrada del período del impulso y la volatilidad.
Para fines de escala, el resultado se multiplica por 10.000.
Al tener en cuenta la volatilidad, el indicador VAM busca cuantificar el impulso. Intenta igualar el impulso en una variedad de condiciones de mercado dividiendo el impulso por la volatilidad. La raíz cuadrada del denominador del período de impulso ayuda a estandarizar el indicador a lo largo de varios períodos de tiempo.
Un valor VAM positivo indica un impulso ascendente, mientras que un valor negativo indica un impulso descendente. La magnitud del VAM representa la fuerza del impulso, ajustada a la volatilidad reciente del mercado.
Este indicador se puede utilizar para identificar posibles cambios de tendencia o para medir la fortaleza de las tendencias actuales del mercado teniendo en cuenta la volatilidad del mercado.
Con solo este indicador, podemos crear un EA y comprobar si es rentable o no.
La estrategia sería así:
void OnTick() { int bars = iBars(NULL, 0); if(bars < MathMax(momentum_period, MathMax(volatility_period, (vam_period))))//, MathMax(ma_long_period, rsi_period))))) return; double close_price = iClose(NULL, 0, 0); // Calcular Momentum double momentum = close_price - iClose(NULL, 0, momentum_period); // Calcular Volatilidad double volatility = iMA(NULL, 0, volatility_period, 0, MODE_SMA, PRICE_CLOSE); // Calcular VAM double vam =( momentum / (volatility * MathSqrt(momentum_period)))*10000; double atr = iATR(_Symbol,PERIOD_CURRENT,14)*_Point; double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double slPriceBuy = NormalizeDouble(Bid - slmul*atr,_Digits); double tpPriceBuy = NormalizeDouble(Ask + tpmul*atr,_Digits); double slPriceSell = NormalizeDouble(Ask + slmul*atr,_Digits); double tpPriceSell = NormalizeDouble(Bid - tpmul*atr,_Digits); // Señales if(vam > VAMTHRESH)// && ma_short > ma_long)// && rsi < 70 && ma_short > ma_long ) { // Comprar trade.Buy(lot_size,_Symbol, Ask, slPriceBuy, tpPriceBuy, " BUY EA "); } else if(vam < -VAMTHRESH)// && ma_short < ma_long)// rsi > 30 && ma_short < ma_long ) { // Vender trade.Sell(lot_size,_Symbol, Bid, slPriceSell, tpPriceSell, " SELL EA "); } }
La función iBars(NULL, 0) produce la cantidad total de barras accesibles para el símbolo y período de tiempo dados.
bars int: el número total de barras, o el valor devuelto, se almacena en la variable barras.
MathMax: Esta función devuelve el valor máximo de los números suministrados. En este caso, se utiliza anidado para determinar el máximo a lo largo de múltiples períodos de tiempo.
Las variables momentum_period, volatility_period, vam_period, ma_long_period y rsi_period, previamente establecidas, indican los intervalos de diversos indicadores o cómputos.
If: La condición determina si el número total de compases es inferior a la suma de los tiempos asignados.
Si la condición «if» es verdadera (es decir, no hay suficientes barras), la función se detiene inmediatamente y el resto del código no se ejecuta.
Resultados del VAM
Los resultados son así (después de una optimización rápida, no lo terminé):
Esto parece bueno, para una estrategia simple y un indicador simple.
Veamos qué podríamos lograr si usáramos un modelo de Deep Learning para esto (pero hoy vamos a usar algo diferente), vamos a hacer un modelo de deep learning con algunos indicadores, para ver cuál se ajusta mejor.
Modelos de aprendizaje profundo
Exportaremos este modelo en ONNX pero primero compararemos cuál es mejor.
Para hacer todo esto utilizaremos Google Colab (para no consumir recursos de nuestro PC) con su script en Python que viene adjunto.
Como esto es una web de MQL5, no explicaré el código Python.
Hay dos scripts py, el primero es un script py con todos los indicadores usados, y el segundo es el mismo script, pero con solo el indicador MACD (porque en el primer script suponiamos que MACD tiene un buen porcentaje de aciertos y R2, con errores bajos.
Los resultados gráficos del primer script son los siguientes:
Una vez que decidimos usar MACD, preparamos el script y ajustamos las fechas para el primero de enero de 2024 (para que podamos realizar pruebas retrospectivas de los resultados en MQL5 desde el 1/1/2024 en adelante).
Los resultados del segundo script fueron los siguientes (muy similares).
etc... (puedes hacerlo tú mismo y comprobar los resultados con Colab).
El script de Python es para Colab, primero debes ejecutar la primera celda, y cuando todas las bibliotecas estén instaladas, ejecutar la segunda celda, aceptarla para guardar los modelos y gráficos en tu Drive, y simplemente esperar hasta que esté listo.
Los datos se obtienen de MQL5, porque MetaTrader no está instalado en Colab (los valores deberían ser similares).
Como puedes ver en el segundo grupo de imágenes, el modelo MACD tiene una tasa de acierto realmente buena, por eso lo elegimos.
LSTM condicional
Una versión mejorada de la red neuronal convencional de memoria a largo plazo se denomina LSTM condicional. Al añadir más datos contextuales o situaciones al proceso predictivo de la arquitectura LSTM, lo mejora. Dado que son tantos los factores que pueden afectar a las variaciones de precios en los mercados financieros, resulta especialmente interesante para la predicción de mercados financieros.Un instrumento eficaz en el campo de la predicción bursátil o de divisas es una máquina de regresión logística condicional. Permite que el modelo tenga en cuenta una variedad de indicadores de mercado y variables externas, además de datos de precios pasados. Esto podría incluir datos de sentimiento, indicadores económicos más generales e indicadores técnicos como RSI o promedios móviles. El modelo busca proporcionar una visión más completa de la dinámica del mercado integrando estos numerosos datos.
El conocimiento del contexto es uno de los principales beneficios de utilizar LSTM condicional para la predicción financiera. Los mercados financieros son sistemas complejos que se ven afectados por una amplia gama de variables. Debido a que el LSTM condicional puede combinar varios indicadores, puede revelar correlaciones complejas entre numerosas dinámicas del mercado. Su capacidad para gestionar tanto características estáticas como datos de series temporales lo hace ideal para los mercados financieros, donde las tendencias pasadas y las circunstancias presentes son igualmente importantes.
Además, los LSTM condicionales son excelentes para capturar dependencias a largo plazo en datos de series temporales, al igual que los LSTM convencionales. Esto resulta especialmente útil en los mercados financieros, donde pueden surgir patrones a largo plazo. El modelo puede detectar patrones que modelos más simples podrían pasar por alto debido a su capacidad de retener información pertinente en secuencias extendidas.
Sin embargo, existen ciertas dificultades en el uso del LSTM condicional para la predicción financiera. Aunque la mayor complejidad del modelo puede tener ventajas, también presenta desafíos. El sobreajuste se vuelve cada vez más probable a medida que el entrenamiento se vuelve más complicado, particularmente cuando se trabaja con conjuntos de datos más pequeños. Esta complejidad genera unos costes informáticos más elevados, lo que puede ser un factor importante en las aplicaciones comerciales en tiempo real.
La calidad y la relevancia de los datos se vuelven aún más cruciales con los LSTM condicionales. El modelo requiere no solo datos de precios, sino también datos de indicadores relevantes y de alta calidad. Garantizar datos consistentes y precisos en todas estas dimensiones puede ser un desafío en el cambiante y a veces opaco mundo de los mercados financieros.
También es importante considerar la naturaleza fundamental de los mercados financieros al evaluar el potencial de los LSTM condicionales. Los mercados se ven influenciados por eventos impredecibles y el comportamiento humano, lo cual puede limitar la eficacia de cualquier modelo predictivo, por sofisticado que sea. El modelo puede ser excelente para identificar patrones en datos históricos, pero puede tener dificultades cuando se enfrenta a condiciones de mercado sin precedentes o a grandes shocks económicos.
Otro problema con los LSTM condicionales, como con muchos modelos de aprendizaje profundo, es la interpretabilidad. Si bien pueden generar pronósticos precisos, puede ser difícil comprender el razonamiento detrás de ellos. Su aspecto de «caja negra» puede plantear problemas en las aplicaciones financieras, donde la transparencia y la transparencia suelen ser esenciales.
Por último, si bien los LSTM condicionales ofrecen oportunidades interesantes para la predicción de acciones y divisas basada en indicadores, es importante abordarlos de manera reflexiva. Su capacidad para incluir datos complejos y multifacéticos puede dar lugar a pronósticos más precisos y matizados. Sin embargo, deberían utilizarse como un componente de un enfoque analítico más amplio y cuidadosamente pensado debido a las dificultades que presentan la creciente complejidad, los requisitos de datos y la imprevisibilidad intrínseca de los mercados financieros. una comprensión profunda de los límites del modelo en situaciones prácticas y pruebas retrospectivas exhaustivas. La aplicación de técnicas tan avanzadas en el ámbito de alto riesgo del trading financiero requiere pruebas retrospectivas exhaustivas y conocimiento de las limitaciones del modelo en entornos prácticos.
El modelo (tal como está hecho en el script py), se ve así:
y sus entradas y salidas deberían verse así:
Código EA
El objetivo principal de este Asesor Experto (EA) es automatizar decisiones de trading basadas en una combinación de indicadores técnicos y predicciones de un modelo de aprendizaje profundo (ONNX). El EA utiliza el indicador Volatility Adjusted Momentum (VAM) y MACD (Moving Average Convergence Divergence), junto con predicciones de precios realizadas por un modelo de aprendizaje automático. Ejecuta operaciones en función de la combinación de estos elementos.
El EA comienza definiendo varias propiedades y bibliotecas. Se incluye la clase `CTrade` para la ejecución de transacciones y otros encabezados para funciones estadísticas y gestión de matrices. Se definen parámetros de entrada para el cálculo de VAM y la ejecución comercial, como `momentum_period`, `volatility_period` y `vam_period`, que se utilizan para controlar la lógica para calcular el impulso y la volatilidad. Aquí también se definen parámetros comerciales como `lot_size` y multiplicadores para stop loss (`slmul`) y take profit (`tpmul`), lo que proporciona flexibilidad al comportamiento del EA. Además, se incluyen constantes que definen los parámetros del modelo ONNX como `BATCH_SIZE`, `SEQUENCE_LENGTH` y otros para administrar cómo se pasan los datos al modelo de aprendizaje profundo.
//+------------------------------------------------------------------+ //| VAM + DL(MACD) EA | //| Copyright 2024, Javier Santiago Gaston de Iriarte Cabrera | //| https://www.mql5.com/en/users/jsgaston/news | //+------------------------------------------------------------------+ #property copyright "Javier Santiago Gaston de Iriarte Cabrera" #property link "https://www.mql5.com/en/users/jsgaston/news" #property version "1.01" #include <Trade\Trade.mqh> #include <Math\Stat\Math.mqh> #include <Arrays\ArrayFloat.mqh> CTrade trade; // Inputs input int momentum_period = 13; input int volatility_period = 7; input int vam_period = 9; input double lot_size = 0.01; input int slippage = 3; input double VAMTHRESH = 9.0; input int slmul = 2; input int tpmul = 4; // ONNX model parameters #define BATCH_SIZE 1 #define SEQUENCE_LENGTH 30 #define INPUT_FEATURES 3 #define CONDITION_FEATURES 2 #define HIDDEN_DIM 128 #define NUM_LAYERS 2 float input_x[][SEQUENCE_LENGTH][INPUT_FEATURES]; float input_condition[][CONDITION_FEATURES]; float h0[][BATCH_SIZE][HIDDEN_DIM]; float c0[][BATCH_SIZE][HIDDEN_DIM]; #define PRICE_UP 0 #define PRICE_SAME 1 #define PRICE_DOWN 2 long ExtHandle = INVALID_HANDLE; int ExtPredictedClass = -1; datetime ExtNextBar = 0; datetime ExtNextDay = 0; float ExtMin = 0.0; float ExtMax = 1.0; // Initialize to 1.0 to prevent division by zero float predicted_last; #resource "/Files/stock_prediction_model_MACD.onnx" as uchar ExtModel[]
La función de inicialización `OnInit()` es crucial ya que carga el modelo ONNX desde un recurso binario (`stock_prediction_model_MACD.onnx`), configurando las formas de entrada y salida del modelo. La entrada al modelo ONNX consiste en datos de precios históricos, valores MACD y estados ocultos y de celda inicializados (`h0`, `c0`) para las capas recurrentes del modelo. Si el modelo se carga correctamente, la función también inicializa valores de precio mínimo y máximo (`ExtMin` y `ExtMax`), que se utilizarán para normalizar los datos de entrada al modelo ONNX. Si ocurre algún error durante la carga del modelo, devuelve `INIT_FAILED`, deteniendo efectivamente el funcionamiento del EA.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { Print("BATCH_SIZE: ", BATCH_SIZE, ", CONDITION_FEATURES: ", CONDITION_FEATURES); ExtHandle = OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(ExtHandle == INVALID_HANDLE) { Print("OnnxCreateFromBuffer error ", GetLastError()); return(INIT_FAILED); } // Set input shapes long input_shape[] = {BATCH_SIZE, SEQUENCE_LENGTH, INPUT_FEATURES}; if(!OnnxSetInputShape(ExtHandle, ONNX_DEFAULT, input_shape)) { Print("OnnxSetInputShape for input_x error ", GetLastError()); return(INIT_FAILED); } long condition_shape[] = {BATCH_SIZE,CONDITION_FEATURES}; if(!OnnxSetInputShape(ExtHandle, 1, condition_shape)) { Print("OnnxSetInputShape for input_condition error ", GetLastError()); return(INIT_FAILED); } long h0_shape[] = {NUM_LAYERS, BATCH_SIZE, HIDDEN_DIM}; if(!OnnxSetInputShape(ExtHandle, 2, h0_shape)) { Print("OnnxSetInputShape for h0 error ", GetLastError()); return(INIT_FAILED); } long c0_shape[] = {NUM_LAYERS, BATCH_SIZE, HIDDEN_DIM}; if(!OnnxSetInputShape(ExtHandle, 3, c0_shape)) { Print("OnnxSetInputShape for c0 error ", GetLastError()); return(INIT_FAILED); } const long output_shape[] = {1,1}; if(!OnnxSetOutputShape(ExtHandle,0,output_shape)) { Print("OnnxSetOutputShape error ",GetLastError()); return(INIT_FAILED); } // Initialize ExtMin and ExtMax GetMinMax(); Print("Initializing EA with VAM and ONNX integration"); return(INIT_SUCCEEDED); }
La función `OnTick()` es la lógica central que se ejecuta en cada tick de precio. Comienza verificando si es un nuevo día y actualiza los precios mínimos y máximos en consecuencia usando `GetMinMax()`. El siguiente bloque asegura que la función solo continúe cuando haya una nueva barra de precios disponible. Luego, el EA actualiza las variables `ExtMin` y `ExtMax` a los valores de precio más recientes. El corazón de esta función es la combinación del cálculo VAM y la predicción ONNX. El VAM se calcula tomando la diferencia de precio (momentum) y dividiéndola por el producto de la volatilidad y la raíz cuadrada del `momentum_period`, escalado por 10000. Si el VAM supera un umbral (`VAMTHRESH`), indica una fuerte tendencia en el mercado, lo que señala una posible operación.
Luego, el EA combina la predicción y los resultados del VAM. Si VAM es alto (mayor que `VAMTHRESH`) y el modelo ONNX predice un aumento de precio, el EA abre una operación de compra con un stop loss calculado y toma de ganancias en función del rango verdadero promedio (ATR). De manera similar, si VAM es bajo (por debajo de "VAMTHRESH" negativo) y el modelo ONNX predice una disminución del precio, el EA abre una operación de venta. Estas operaciones se ejecutan utilizando la clase `CTrade`, que interactúa con las funciones comerciales de la plataforma MetaTrader 5.
En términos de gestión de riesgos, los niveles de stop loss y take profit se calculan dinámicamente en función del ATR del activo. Esto garantiza que la estrategia se ajuste a la volatilidad del mercado, proporcionando salidas comerciales más adaptables dependiendo de las condiciones actuales del mercado.void OnTick() { // Check for new day and update ExtMin and ExtMax if(TimeCurrent() >= ExtNextDay) { GetMinMax(); ExtNextDay = TimeCurrent() - TimeCurrent() % PeriodSeconds(PERIOD_D1) + PeriodSeconds(PERIOD_D1); } // Check for new bar if(TimeCurrent() < ExtNextBar) return; ExtNextBar = TimeCurrent() - TimeCurrent() % PeriodSeconds() + PeriodSeconds(); // Update ExtMin and ExtMax double close = iClose(_Symbol, _Period, 0); if(ExtMin > close) ExtMin = (float)close; if(ExtMax < close) ExtMax = (float)close; int bars = iBars(_Symbol, PERIOD_CURRENT); if(bars < MathMax(momentum_period, MathMax(volatility_period, MathMax(vam_period, SEQUENCE_LENGTH)))) return; // Calculate VAM double momentum = close - iClose(_Symbol, PERIOD_CURRENT, momentum_period); double volatility = iStdDev(_Symbol, PERIOD_CURRENT, volatility_period, 0, MODE_SMA, PRICE_CLOSE); double vam = (momentum / (volatility * MathSqrt(momentum_period))) * 10000; Print("VAM ", vam); // Get ONNX prediction int result=GetPrediction(); // Trading logic combining VAM and ONNX prediction double atr = iATR(_Symbol, PERIOD_CURRENT, 14)*_Point; double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double slPriceBuy = NormalizeDouble(Bid - slmul * atr, _Digits); double tpPriceBuy = NormalizeDouble(Ask + tpmul * atr, _Digits); double slPriceSell = NormalizeDouble(Ask + slmul * atr, _Digits); double tpPriceSell = NormalizeDouble(Bid - tpmul * atr, _Digits); //Print(result); if(vam > VAMTHRESH && result == 0) { trade.Buy(lot_size, _Symbol, Ask, slPriceBuy, tpPriceBuy, "BUY VAM+ONNX"); } else if(vam < -VAMTHRESH && result == 2) { trade.Sell(lot_size, _Symbol, Bid, slPriceSell, tpPriceSell, "SELL VAM+ONNX"); } }
La predicción del modelo ONNX se obtiene llamando a `GetPrediction()`. La entrada al modelo se prepara mediante la función `PrepareInputs()`, que reúne los precios de cierre históricos y los datos MACD, los normaliza utilizando el rango de precios (`ExtMin` y `ExtMax`) y llena las matrices de entrada esperadas por el modelo. Establece los datos para la secuencia de precios de entrada (`input_x`) y las condiciones basadas en MACD (`input_condition`) mientras restablece los estados ocultos (`h0`, `c0`). Una vez que la entrada está lista, el modelo se ejecuta mediante la función `OnnxRun()`, que calcula el precio previsto. La diferencia entre el precio previsto y el último precio previsto se utiliza para determinar si el modelo espera que el precio suba, baje o permanezca igual. Si el cambio en la predicción es demasiado pequeño, el modelo no sugiere movimiento (el precio permanece igual).
void PrepareInputs() { ArrayResize(input_x, BATCH_SIZE); ArrayResize(input_condition, BATCH_SIZE); ArrayResize(h0, NUM_LAYERS); ArrayResize(c0, NUM_LAYERS); for(int i = 0; i < SEQUENCE_LENGTH; i++) { input_x[0][i][0] = (float)((iClose(_Symbol, PERIOD_CURRENT, i) - ExtMin) / (ExtMax - ExtMin)); double macd_main[], macd_signal[]; int macd_handle = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE); CopyBuffer(macd_handle, 0, i, 1, macd_main); CopyBuffer(macd_handle, 1, i, 1, macd_signal); input_x[0][i][1] = (float)((macd_main[0] - ExtMin) / (ExtMax - ExtMin)); input_x[0][i][2] = (float)((macd_signal[0] - ExtMin) / (ExtMax - ExtMin)); } double macd_main2[], macd_signal2[]; int macd_handle2 = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE); CopyBuffer(macd_handle2, 0, 0, 1, macd_main2); CopyBuffer(macd_handle2, 1, 0, 1, macd_signal2); input_condition[0][0] = (float)macd_main2[0]; input_condition[0][1] = (float)macd_signal2[0]; ArrayInitialize(h0, 0.0f); ArrayInitialize(c0, 0.0f); } //+------------------------------------------------------------------+ //| Get prediction from ONNX model | //+------------------------------------------------------------------+ int GetPrediction() { PrepareInputs(); float output_data[]; ArrayResize(output_data, 1); // Run the ONNX model if(!OnnxRun(ExtHandle, ONNX_NO_CONVERSION, input_x, input_condition, h0, c0, output_data)) { Print("OnnxRun error: ", GetLastError()); return ExtPredictedClass = -1; } float predicted=output_data[0]*(ExtMax-ExtMin)+ExtMin; Print("Predicted last ", predicted_last); Print("Predicted ",predicted); float last_close = (float)iClose(_Symbol, PERIOD_CURRENT, 0); Print("last close ",last_close); float delta = predicted_last - predicted; predicted_last=predicted; Print("Delta ",delta); if(MathAbs(delta) <= 0.00001) ExtPredictedClass = PRICE_SAME; else if(delta < 0) ExtPredictedClass = PRICE_UP; else ExtPredictedClass = PRICE_DOWN; Print(ExtPredictedClass); return ExtPredictedClass; }
La función `GetMinMax()` es responsable de establecer los valores de precio mínimo (`ExtMin`) y máximo (`ExtMax`) durante el último día de datos. Estos valores se utilizan para normalizar las entradas antes de pasarlas al modelo ONNX, lo que garantiza que el modelo reciba entradas en un rango consistente. Si el EA no puede recuperar los datos de precios necesarios, adopta de forma predeterminada un rango seguro para evitar la división por cero.
void GetMinMax() { double close[]; int copied = CopyClose(_Symbol, PERIOD_D1, 0, SEQUENCE_LENGTH, close); if(copied > 0) { ExtMin = (float)MathMin(close); ExtMax = (float)MathMax(close); } else { Print("Failed to copy price data. Error: ", GetLastError()); ExtMin = 0; ExtMax = 1; // Prevent division by zero } }
Por último, el EA incluye una función de desinicialización `OnDeinit()` que libera el identificador del modelo ONNX cuando se elimina el EA, lo que garantiza que la memoria se administre correctamente y evita fugas de recursos.
void OnDeinit(const int reason) { if(ExtHandle != INVALID_HANDLE) { OnnxRelease(ExtHandle); ExtHandle = INVALID_HANDLE; } }
En resumen, este EA combina análisis técnico (a través de VAM y MACD) con predicciones de aprendizaje automático de un modelo ONNX para tomar decisiones comerciales automatizadas e informadas. El análisis técnico ayuda a detectar tendencias, mientras que el modelo de aprendizaje automático pronostica el movimiento de precios, lo que resulta en una estrategia híbrida.
Resultados
Después de la optimización
Conclusión
Este artículo examina la integración del aprendizaje profundo, específicamente los modelos LSTM condicionales, con el indicador de momento ajustado por volatilidad (VAM) para mejorar los sistemas de comercio automatizado. Al combinar las capacidades predictivas de LSTM y el análisis de impulso sensible a la volatilidad de VAM, la estrategia apunta a capturar la dinámica compleja del mercado. Implementado en MetaTrader 5, este sistema genera señales comerciales y adapta la gestión de riesgos de forma dinámica.
Las pruebas retrospectivas muestran mejores resultados al combinar LSTM con VAM. A pesar de desafíos como el sobreajuste y las exigencias computacionales, el estudio sugiere que la integración del aprendizaje profundo con el análisis técnico puede mejorar significativamente las estrategias de trading algorítmico.
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/15956
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.





- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso
Hola Javier
Gracias por la respuesta.
He encontrado el problema. Has nombrado "stock_prediction_model_MACD.onnx" en EA pero los archivos zip lo tienen nombrado como stock_prediction_model_MACD_Signal.onnx
También he notado el uso inadecuado de la manija del indicador (error!!!) en el código. Usted ha utilizado
En MQL5, los valores del indicador se derivan usando CopyBuffer y el indicador handle, que has usado en
Por favor, ¿puedes explicar por qué se ha usado handle de forma diferente a double variable para obtener los valores en el primer caso?Saludos y buen fin de semana.
Tienes toda la razón.
Cometí un error, gracias por aclararlo.
Tienes que usar copybuffer y handle.
Hola Javier
Gracias por este gran artículo, el bot utiliza son riesgo para recompensar la relación de 135:20 que hace que sea arriesgado. cuando trato de una relación adecuada como 1:2 o 1:3 es un bot loosing .Any sugerencias sobre cómo puedo mke mejor con el riesgo adecuado para recompensar la relación
Hola Javier
Gracias por este gran artículo, el bot utiliza son riesgo para recompensar la relación de 135:20 que hace que sea arriesgado. cuando trato de una relación adecuada como 1:2 o 1:3 es un bot loosing .Any sugerencias sobre cómo puedo mke mejor whith derecho riesgo para recompensar la relación
Hola, creo que no he sido demasiado explícito y he expresado que este ejemplo sólo sirve para mostrar que se puede utilizar LSTM con algo más que OHLC. Simplemente no utilices este ejemplo para operar.
Hola Javier
¿como me aseguro del valor de este param VAMTHRESH?
Corrección: Cambiar a índice + tamaño_ventana - 1 para que las condiciones utilicen sólo los últimos datos disponibles.
Impacto: Los resultados reales serán ~48-52% de aciertos, no 80-90%. Estos resultados no son negociables en mercados reales.