
Reimaginando las estrategias clásicas en MQL5 (Parte II): FTSE100 y bonos del Reino Unido (UK Gilts)
Existen potencialmente infinitas formas para que el inversor moderno integre la IA en sus estrategias comerciales. Es muy poco probable que cualquier inversor individual tenga tiempo suficiente para analizar cuidadosamente cada estrategia antes de decidir a cuál confiarle su capital. En esta serie de artículos, exploraremos el amplio panorama de posibles aplicaciones de la IA en el entorno comercial. Nuestro objetivo es ayudarle a identificar una estrategia que sea adecuada para su perfil de inversor particular.
Descripción general de la estrategia comercial
El Financial Times Stock Exchange 100 (FTSE100) es un índice mundialmente reconocido que sigue la evolución de las 100 mayores empresas que cotizan en la Bolsa de Londres (London Stock Exchange, LSE). El índice se creó en 1984 con un valor de 1000 puntos, y actualmente cotiza en torno a los 8000 puntos. Las empresas del índice se ponderan proporcionalmente a su capitalización bursátil, lo que significa que las grandes empresas tienen más influencia en el mercado que las pequeñas.
Todos los gobiernos del mundo desarrollado emiten pasivos denominados en su moneda nacional, y el gobierno del Reino Unido no es una excepción. El "gilt" es un instrumento de deuda del gobierno del Reino Unido, y también está listado en la Bolsa de Valores de Londres (LSE). Los gilts son valores de renta fija disponibles en dos tipos diferentes. El primer tipo es el "conventional guilt" (gilt convencional), que constituye la mayoría de las ventas de gilts. Este gilt convencional paga un cupón fijo al tenedor del gilt hasta su vencimiento, y al vencimiento, el cupón final y el principal se devuelven al inversor.
El segundo tipo de gilt es el "gilt vinculado al índice". Este gilt en particular no tiene una tasa de cupón fija; en su lugar, los pagos recibidos del bono pueden ajustarse para compensar al inversor por la inflación acumulada durante el periodo en que mantuvo el gilt. Estos gilts vinculados al índice no son tan populares como los gilts fijos debido a sus flujos de efectivo impredecibles.
Existe una relación inversa entre el rendimiento de un bono y la demanda de un bono. Siempre que un bono en particular tiene una gran demanda entre los inversores, el rendimiento asociado a ese bono cae; por el contrario, si el bono tiene un rendimiento pobre, su rendimiento aumentará en un intento de despertar el interés de los inversores.
Por lo general, cuando los mercados bursátiles tienen un desempeño desfavorable, los inversores tienden a retirar sus fondos del mercado bursátil riesgoso y, en cambio, a invertirlos en valores más seguros, como los bonos gubernamentales. Por el contrario, cuando los inversores recuperan la confianza en el mercado de valores, tienden a retirar sus fondos de los bonos gubernamentales seguros e invertirlos en el mercado de valores. La razón principal de este comportamiento radica en la dispersión de los rendimientos esperados. En promedio, el mercado de valores garantiza mayores retornos promedio que el mercado de bonos, lo que lo hace más atractivo. Sin embargo, el mercado de valores conlleva un riesgo intrínseco mayor, lo que hace que sus inversores sean bastante sensibles a las señales de debilidad.
Descripción general de la metodología
Creamos un Asesor Experto impulsado por IA para que aprenda sus propias reglas comerciales con respecto a los dos mercados. Normalmente, como inversores, nos inclinamos por las estrategias que nos atraen, sin embargo, al adoptar un enfoque de aprendizaje algorítmico, podemos estar seguros de que nuestro programa toma todas sus decisiones en función de los datos que hemos recopilado.
Los datos de series temporales financieras son notoriamente ruidosos. Cuando se trabaja con conjuntos de datos ruidosos, es bien sabido que los modelos más simples pueden funcionar tan bien como las redes neuronales. Por lo tanto, implementamos un modelo de regresión lineal desde cero en MQL5 utilizando la API de matrices y vectores. Estandarizamos y escalamos nuestros datos de entrada antes de ajustar nuestro modelo porque nuestros datos de entrada estaban en escalas diferentes; los símbolos Gilts y UK100 están en escalas diferentes. Empleamos la solución pseudoinversa para calcular los parámetros de nuestro modelo.
Además, guiamos nuestro modelo de IA utilizando análisis técnico, por lo tanto, nuestro sistema solo ingresará en una operación si nuestros indicadores técnicos también nos llevan a la misma conclusión. Por último, también utilizamos nuestro sistema de IA para ayudarnos a detectar posibles reversiones y también decidir cuándo cerrar nuestras posiciones. En nuestros artículos anteriores, cuando desarrollamos nuestros modelos lineales desde cero, uno de los usuarios comentó que la salida del modelo estaba más allá del rango aceptable. En este artículo, hemos intentado resolver ese problema incluyendo una columna para la intersección de nuestro modelo y estandarizando y escalando nuestros datos.
Implementación en MQL5
Para comenzar, primero creamos un script en MQL5 para tener una idea de cómo encajarán todas las piezas de nuestro Asesor Experto. Primero, tenemos que definir las entradas para nuestra aplicación. Necesitamos definir cuántos datos vamos a obtener y hasta qué punto en el futuro debemos pronosticar. Recuerde que cuanto más datos obtenga, más intensiva en términos computacionales será finalmente la aplicación. Por lo tanto, tratamos de lograr un equilibrio aquí permitiendo que el usuario final obtenga tantos datos como crea que sus recursos pueden manejar. Además, debemos tener presente que los regímenes de mercado cambian. Por lo tanto, es posible que no obtengamos ninguna mejora en el rendimiento al obtener todos los datos disponibles.
Últimamente, las cotizaciones del mercado se ofrecen de forma algorítmica, a diferencia del sistema de clamor abierto que lo precedió. Tal vez no tenga ningún valor estudiar las cotizaciones del mercado basándose en un comportamiento del mercado que probablemente no volveremos a ver. Por lo tanto, limitaremos nuestro enfoque únicamente a los datos recientes.
//+------------------------------------------------------------------+ //| UK100 Gilts.mq5 | //| Gamuchirai Zororo Ndawana | //| https://www.mql5.com/en/gamuchiraindawa | //+------------------------------------------------------------------+ #property copyright "Gamuchirai Zororo Ndawana" #property link "https://www.mql5.com/en/gamuchiraindawa" #property version "1.00" #property script_show_inputs //+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ input int fetch = 20; //How much data should we fetch? input int look_ahead = 20; //How far into the future should we forecast?
Ahora podemos comenzar a definir el corazón de nuestro script, primero definiremos las variables que necesitaremos a lo largo de nuestro script.
//+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- Global variables we will need inside our expert advisor matrix coefficients = matrix::Zeros(1,9); vector mean_values = vector::Zeros(8); vector std_values = vector::Zeros(8); vector intercept = vector::Ones(fetch); matrix input_matrix = matrix::Zeros(9,fetch); matrix gilts_data,uk100_data,target;
Ahora busquemos los datos que necesitamos. Observe que los datos de entrada están retrasados un número de pasos look_ahead y los datos de destino se obtienen antes que los datos de entrada.
//--- First we will fetch the market data gilts_data.CopyRates("UKGB_Z4",PERIOD_CURRENT,COPY_RATES_OHLC,1+look_ahead,fetch); uk100_data.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_OHLC,1+look_ahead,fetch); target.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_CLOSE,1,fetch);
Ahora necesitamos crear una matriz de entrada. La primera columna de nuestra matriz de entrada será el número uno, repetido tantas veces como la entrada obtenida. Esto se debe a que esta entrada de unos simplemente se supone que debe multiplicarse por nuestro cálculo del término de sesgo en nuestro modelo lineal. A partir de ahí, completamos los datos relacionados con los bonos del gobierno del Reino Unido y el FTSE 100.
//--- Fill in the input matrix input_matrix.Row(intercept,0); input_matrix.Row(gilts_data.Row(0),1); input_matrix.Row(gilts_data.Row(1),2); input_matrix.Row(gilts_data.Row(2),3); input_matrix.Row(gilts_data.Row(3),4); input_matrix.Row(uk100_data.Row(0),5); input_matrix.Row(uk100_data.Row(1),6); input_matrix.Row(uk100_data.Row(2),7); input_matrix.Row(uk100_data.Row(3),8);
Veamos los datos que hemos obtenido, para asegurarnos de que los datos tienen el tamaño correcto y que las matrices que tenemos son compatibles con las manipulaciones que estamos a punto de realizar. Tenga en cuenta que si nuestras matrices no tienen el tamaño adecuado, nuestros cálculos fallarán y devolverán errores durante la ejecución.
//--- Display the data fetched Print("Input matrix: "); Print("Rows: ",input_matrix.Rows()," Columns: ",input_matrix.Cols()); Print(input_matrix); Print("Target: "); Print("Rows: ",target.Rows()," Columns: ",target.Cols()); Print(target); Print("UK100: "); Print("Rows: ",uk100_data.Rows()," Columns: ",uk100_data.Cols()); Print(uk100_data); Print("GILTS: "); Print("Rows: ",gilts_data.Rows()," Columns: ",gilts_data.Cols()); Print(gilts_data);
Para escalar y normalizar nuestros datos de entrada, necesitamos calcular los valores de media y desviación estándar para cada columna con la que trabajamos. Cuando comencé a aprender aprendizaje automático, no estaba seguro de cuándo era necesario escalar y estandarizar los datos. Sin embargo, con el tiempo he aprendido una regla general: el escalamiento es necesario cuando las entradas están en escalas diferentes, así que, por ejemplo, nuestros datos del mercado de bonos del Estado están en el rango de 100, pero nuestros datos del mercado FTSE100 están en el rango de 8000, por lo tanto, el escalamiento aquí es necesario. Tenga en cuenta que nunca es necesario escalar el objetivo.
//--- Calculate the scaling values mean_values = input_matrix.Mean(1); std_values = input_matrix.Std(1); Print("Mean values: "); Print(mean_values); Print("Std values: "); Print(std_values);
Ahora, para normalizar nuestros datos de entrada, primero restamos la media de la columna y luego dividimos por la desviación estándar. Este paso de preprocesamiento ayuda a que nuestro modelo aprenda de manera efectiva y es fundamental realizarlo cuando las entradas del modelo están en diferentes escalas, como en nuestro caso.
//--- Normalizing and scaling our input data for(int i = 0; i < 8; i++) { //--- Extract the vector vector temp = input_matrix.Row(i + 1); //--- Scale the data temp = ((temp - mean_values[i+1]) / std_values[i+1]); //--- Write the data back input_matrix.Row(temp,i+1); } //--- Finished normalizing the data Print("Finished normalizing the data."); Print(input_matrix);
Calculemos ahora los parámetros de nuestro modelo, los coeficientes de nuestro modelo lineal. Podemos hacerlo realizando una multiplicación matricial de los datos de destino y la pseudoinversa de los datos de entrada, esto nos devolverá una matriz 1xn con 1 valor de coeficiente para cada columna de nuestra matriz. El signo de cada valor de coeficiente nos indica la pendiente, o si el objetivo aumenta o disminuye a medida que aumenta la variable de entrada.
//--- Now we can calculate our coefficient values coefficients = target.MatMul(input_matrix.PInv()); Print("Coefficient values"); Print(coefficients);
Para obtener un pronóstico de nuestro modelo, primero tenemos que obtener los valores de datos de entrada actuales, escalarlos y luego aplicar la fórmula de regresión lineal para obtener la predicción de nuestro modelo.
//--- Now we can obtain a forecast from our model gilts_data.CopyRates("UKGB_Z4",PERIOD_CURRENT,COPY_RATES_OHLC,0,1); uk100_data.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_OHLC,0,1); //--- Scale our inputs gilts_data[0,0] = ((gilts_data[0,0] - mean_values[1]) / std_values[1]); gilts_data[1,0] = ((gilts_data[1,0] - mean_values[2]) / std_values[2]); gilts_data[2,0] = ((gilts_data[2,0] - mean_values[3]) / std_values[3]); gilts_data[3,0] = ((gilts_data[3,0] - mean_values[4]) / std_values[4]); uk100_data[0,0] = ((uk100_data[0,0] - mean_values[5]) / std_values[5]); uk100_data[1,0] = ((uk100_data[1,0] - mean_values[6]) / std_values[6]); uk100_data[2,0] = ((uk100_data[2,0] - mean_values[7]) / std_values[7]); uk100_data[3,0] = ((uk100_data[3,0] - mean_values[8]) / std_values[8]); Print("Normalized inputs: "); Print(gilts_data); Print(uk100_data); double forecast = ( (1 * coefficients[0,0]) + (gilts_data[0,0] * coefficients[0,1]) + (gilts_data[1,0] * coefficients[0,2]) + (gilts_data[2,0] * coefficients[0,3]) + (gilts_data[3,0] * coefficients[0,4]) + (uk100_data[0,0] * coefficients[0,5]) + (gilts_data[1,0] * coefficients[0,6]) + (gilts_data[2,0] * coefficients[0,7]) + (gilts_data[3,0] * coefficients[0,8]) ); //--- Give our predictions Comment("Model forecast: ",forecast);
Figura 1: Nuestro script.
Figura 2: Entradas de nuestro script.
Figura 3: Nuestro modelo de previsión.
Construyendo nuestro asesor experto en MQL5
Ahora que hemos llegado hasta aquí, estamos listos para comenzar a construir nuestro Asesor Experto. Para comenzar a construir nuestra aplicación, primero importaremos la biblioteca comercial para que podamos administrar nuestras posiciones.
//+------------------------------------------------------------------+ //| UK100 Gilts.mq5 | //| Gamuchirai Zororo Ndawana | //| https://www.mql5.com/en/gamuchiraindawa | //+------------------------------------------------------------------+ #property copyright "Gamuchirai Zororo Ndawana" #property link "https://www.mql5.com/en/gamuchiraindawa" #property version "1.00" //+------------------------------------------------------------------+ //|Libraries we need | //+------------------------------------------------------------------+ #include <Trade/Trade.mqh> //Trade class CTrade Trade; //Initialize the class
Luego configuraremos las entradas para nuestra aplicación para que el usuario final pueda decidir cuántos datos obtener y hasta qué punto en el futuro debemos pronosticar.
//+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ input int fetch = 20; //How much data should we fetch? input int look_ahead = 20; //How far into the future should we forecast?
También necesitamos variables globales que se utilizarán en todo el programa.
//+------------------------------------------------------------------+ //| Global vairables | //+------------------------------------------------------------------+ matrix coefficients = matrix::Zeros(1,9); vector mean_values = vector::Zeros(8); vector std_values = vector::Zeros(8); vector intercept = vector::Ones(fetch); matrix input_matrix = matrix::Zeros(9,fetch); matrix gilts_data,uk100_data,target; double willr_buffer[],rsi_buffer[]; int willr_handler,rsi_handler; double forecast,bid,ask; int model_forecast = 0; int state = 0;
Definamos una función responsable de obtener nuestros datos de entrenamiento y obtener los valores de escala que necesitamos para estandarizar y escalar nuestros datos. Tenga en cuenta que utilizamos matrices en lugar de arreglos, esto se debe a que pretendemos aprovechar las funciones de matriz y vector especializadas incluidas en la API MQL5.
//+------------------------------------------------------------------+ //| Let us fetch our training data | //+------------------------------------------------------------------+ void fetch_training_data(void) { //--- First we will fetch the market data gilts_data.CopyRates("UKGB_Z4",PERIOD_CURRENT,COPY_RATES_OHLC,1+look_ahead,fetch); uk100_data.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_OHLC,1+look_ahead,fetch); target.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_CLOSE,1,fetch); //--- Fill in the input matrix input_matrix.Row(intercept,0); input_matrix.Row(gilts_data.Row(0),1); input_matrix.Row(gilts_data.Row(1),2); input_matrix.Row(gilts_data.Row(2),3); input_matrix.Row(gilts_data.Row(3),4); input_matrix.Row(uk100_data.Row(0),5); input_matrix.Row(uk100_data.Row(1),6); input_matrix.Row(uk100_data.Row(2),7); input_matrix.Row(uk100_data.Row(3),8); //--- Display the data fetched Print("Input matrix: "); Print("Rows: ",input_matrix.Rows()," Columns: ",input_matrix.Cols()); Print(input_matrix); Print("Target: "); Print("Rows: ",target.Rows()," Columns: ",target.Cols()); Print(target); Print("UK100: "); Print("Rows: ",uk100_data.Rows()," Columns: ",uk100_data.Cols()); Print(uk100_data); Print("GILTS: "); Print("Rows: ",gilts_data.Rows()," Columns: ",gilts_data.Cols()); Print(gilts_data); //--- Calculate the scaling values mean_values = input_matrix.Mean(1); std_values = input_matrix.Std(1); Print("Mean values: "); Print(mean_values); Print("Std values: "); Print(std_values); } //+------------------------------------------------------------------+
Ahora que tenemos nuestros valores de escala, definamos una función para escalar y estandarizar nuestros datos de entrada.
//+------------------------------------------------------------------+ //| Let us scale and standardize the training data | //+------------------------------------------------------------------+ void scale_training_data(void) { //--- Normalizing and scaling our input data for(int i = 0; i < 8; i++) { //--- Extract the vector vector temp = input_matrix.Row(i + 1); //--- Scale the data temp = ((temp - mean_values[i+1]) / std_values[i+1]); //--- Write the data back input_matrix.Row(temp,i+1); } //--- Finished normalizing the data Print("Finished normalizing the data."); Print(input_matrix); }
Una vez que nuestros datos de entrenamiento se hayan escalado y estandarizado, estamos listos para calcular los parámetros de nuestro modelo.
//+------------------------------------------------------------------+ //| Calculate coefficient values | //+------------------------------------------------------------------+ void calculate_coefficient_values(void) { //--- Now we can calculate our coefficient values coefficients = target.MatMul(input_matrix.PInv()); Print("Coefficient values"); Print(coefficients); }
También necesitamos una función responsable de obtener una predicción de nuestro modelo. Nuestro procedimiento es sencillo: primero obtendremos los datos del mercado, los escalaremos y, por último, aplicaremos la fórmula de regresión lineal para obtener una predicción.
//+------------------------------------------------------------------+ //| Fetch a forecast from our model | //+------------------------------------------------------------------+ void fetch_forecast(void) { //--- Now we can obtain a forecast from our model gilts_data.CopyRates("UKGB_Z4",PERIOD_CURRENT,COPY_RATES_OHLC,0,1); uk100_data.CopyRates("UK100",PERIOD_CURRENT,COPY_RATES_OHLC,0,1); //--- Scale our inputs gilts_data[0,0] = ((gilts_data[0,0] - mean_values[1]) / std_values[1]); gilts_data[1,0] = ((gilts_data[1,0] - mean_values[2]) / std_values[2]); gilts_data[2,0] = ((gilts_data[2,0] - mean_values[3]) / std_values[3]); gilts_data[3,0] = ((gilts_data[3,0] - mean_values[4]) / std_values[4]); uk100_data[0,0] = ((uk100_data[0,0] - mean_values[5]) / std_values[5]); uk100_data[1,0] = ((uk100_data[1,0] - mean_values[6]) / std_values[6]); uk100_data[2,0] = ((uk100_data[2,0] - mean_values[7]) / std_values[7]); uk100_data[3,0] = ((uk100_data[3,0] - mean_values[8]) / std_values[8]); Print("Normalized inputs: "); Print(gilts_data); Print(uk100_data); //--- Calculate the model's prediction forecast = ( (1 * coefficients[0,0]) + (gilts_data[0,0] * coefficients[0,1]) + (gilts_data[1,0] * coefficients[0,2]) + (gilts_data[2,0] * coefficients[0,3]) + (gilts_data[3,0] * coefficients[0,4]) + (uk100_data[0,0] * coefficients[0,5]) + (gilts_data[1,0] * coefficients[0,6]) + (gilts_data[2,0] * coefficients[0,7]) + (gilts_data[3,0] * coefficients[0,8]) ); //--- Store the model's prediction if(forecast < iClose("UK100",PERIOD_CURRENT,0)) { model_forecast = -1; } if(forecast > iClose("UK100",PERIOD_CURRENT,0)) { model_forecast = 1; } //--- Give the user feedback Comment("Model forecast: ",forecast); }
Por último, también necesitamos una función para obtener los datos actuales del mercado y los datos de los indicadores técnicos.
//+------------------------------------------------------------------+ //| This function will fetch current market data | //+------------------------------------------------------------------+ void update_market_data(void) { //--- Market prices bid = SymbolInfoDouble("UK100",SYMBOL_BID); ask = SymbolInfoDouble("UK100",SYMBOL_ASK); //--- Technical indicators CopyBuffer(rsi_handler,0,0,1,rsi_buffer); CopyBuffer(willr_handler,0,0,1,willr_buffer); }
También necesitamos 2 funciones que validarán la predicción de nuestro modelo de IA contra las lecturas de nuestros indicadores técnicos. Sólo queremos entrar en configuraciones de alta probabilidad cuando tanto nuestro análisis técnico como cuantitativo apunten en la misma dirección.
//+------------------------------------------------------------------+ //| This function will check if we have oppurtunities to buy | //+------------------------------------------------------------------+ void check_bullish_sentiment(void) { if((willr_buffer[0] > -20) && (rsi_buffer[0] > 70)) { Trade.Buy(0.2,"UK100",ask,ask-5,ask+5,"UK100 Gilts AI"); state = 1; } } //+------------------------------------------------------------------+ //| This function will check if we have oppurtunities to sell | //+------------------------------------------------------------------+ void check_bearish_sentiment(void) { if((willr_buffer[0] < -80) && (rsi_buffer[0] <370)) { Trade.Sell(0.2,"UK100",ask,ask-5,ask+5,"UK100 Gilts AI"); state = -1; } }
No sólo eso, sino que ahora estamos listos para comenzar a definir el procedimiento de inicialización para nuestro Asesor Experto. Primero, necesitamos obtener los datos de entrenamiento, desde allí necesitamos escalar y estandarizar nuestros datos de entrenamiento, luego, calcularemos nuestros valores de coeficiente y, finalmente, configuraremos nuestros indicadores técnicos y validaremos que nuestros indicadores técnicos sean válidos.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Fetch the training data fetch_training_data(); //--- Scale the training data scale_training_data(); //--- Calculate the coefficients calculate_coefficient_values(); //--- Setup the indicators rsi_handler = iRSI("UK100",PERIOD_CURRENT,20,PRICE_CLOSE); willr_handler = iWPR("UK100",PERIOD_CURRENT,30); //--- Validate the technical indicators if((rsi_handler == INVALID_HANDLE) || (willr_handler == INVALID_HANDLE)) { Comment("Failed to load indicators. ",GetLastError()); return(INIT_FAILED); } //--- Everything went well return(INIT_SUCCEEDED); }
Cada vez que nuestro Asesor Experto se elimine del gráfico, liberaremos los recursos que ya no utilizamos. Desconectaremos los indicadores que usamos en nuestro análisis técnico y, además, también eliminaremos nuestro Asesor Experto del gráfico.
//+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Free up the resoruces we don't need IndicatorRelease(willr_handler); IndicatorRelease(rsi_handler); ExpertRemove(); }
Finalmente, cada vez que recibamos precios actualizados, primero actualizaremos nuestros datos de mercado y luego obtendremos un pronóstico de nuestro modelo de IA. Si no tenemos posiciones abiertas, verificaremos si nuestros indicadores técnicos se alinean con nuestro modelo de IA antes de abrir nuestras posiciones. De lo contrario, si ya tenemos posiciones abiertas, verificaremos si nuestro modelo de IA está pronosticando una reversión contra nuestra posición abierta. Si nuestro modelo espera una reversión, cerraremos nuestras posiciones abiertas.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Fetch updated market data update_market_data(); //--- Fetch a forecast from our model fetch_forecast(); //--- Check for a position we can open if(PositionsTotal() == 0) { if(model_forecast == 1) { check_bullish_sentiment(); } else if(model_forecast == -1) { check_bearish_sentiment(); } } //--- Check for a reversal else if(PositionsTotal() > 0) { if(model_forecast != state) { Alert("Reversal detected by our AI system! Closing all positions now."); Trade.PositionClose("UK100"); } } } //+------------------------------------------------------------------+
Figura 4: Nuestro sistema de IA en acción.
Conclusión
En el artículo de hoy hemos demostrado cómo se puede construir un Asesor Experto guiado por IA en MQL5, la mayor ventaja de nuestro enfoque es que podemos cambiar el marco de tiempo sin tener que recalibrar nuestra aplicación, mientras que si implementáramos nuestra solución usando ONNX, necesitaríamos al menos 1 modelo ONNX para cada marco de tiempo que deseamos negociar. Nuestra solución actual se optimiza automáticamente y es capaz de funcionar en muchas condiciones diferentes.
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/15771





- 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