
Creación de un modelo de restricción de tendencia de velas (Parte 6): Integración todo en uno
- Introducción
- Principales secciones de integración
- Combinación de la lógica de integración
- La función Comment
- Comprobación de los efectos de la función Comment
- Conclusión
Introducción
Nuestro sistema de señalización ha demostrado un rendimiento excepcional en todas las fases de su desarrollo. El objetivo actual es fusionar los programas existentes en un sistema de señalización único y unificado. Recuerde que las dos versiones anteriores del indicador Trend Constraint tenían cada una sus integraciones específicas en la Parte 5. Esta consolidación pretende aprovechar toda la potencia de la programación, que reduce considerablemente la carga de trabajo humano al permitir a los ordenadores ejecutar tareas complejas y repetitivas a velocidades increíbles.
Dado que tenemos dos programas con lógica similar pero características distintas, el proceso de integración implica algo más que copiar y pegar el código fuente. En su lugar, mantendremos estratégicamente ciertos elementos que tienen efectos coherentes en ambos programas, garantizando una funcionalidad óptima. Este proceso, al que me refiero como fusión, requiere una cuidadosa consideración y precisión.
En este artículo, desglosaremos las secciones de código MQL5 donde se produce la integración y discutiremos las líneas clave que permanecen globales durante todo el proceso de fusión. Este meticuloso enfoque es esencial a la hora de combinar múltiples fragmentos de código para crear un programa cohesionado y eficaz.
De la Parte 5 y sus subsecciones, teníamos dos grandes integraciones que resumir:
- Integración de Telegram en MetaTrader 5 para notificaciones.
- Integración de WhatsApp en MetaTrader 5 para notificaciones.
Uno de los retos es que nuestra integración realiza tareas en el símbolo del sistema con la ventana oculta para evitar interferir con otros procesos en la pantalla del ordenador. Como resultado, no hay confirmación de si las señales se han enviado con éxito a las plataformas de destino. Queremos que nuestro sistema comente en la ventana del gráfico cada señal emitida con éxito o, como mínimo, que la imprima en el diario de la plataforma.
Profundicemos y analicemos otros aspectos en las siguientes secciones de este artículo.
Nuestras principales secciones de integración
He extraído los principales puntos de interés del código específicamente para la discusión de este artículo. Si desea información más detallada, consulte la Parte 5. Estos son los programas que estamos comparando para facilitar el proceso de fusión. Eche un vistazo a cada programa y compare sus similitudes y diferencias. Esta comparación nos ayudará a identificar las áreas clave en las que es necesaria la integración, garantizando una fusión fluida y eficaz.
- Integración de Telegram:
/--- ShellExecuteW declaration ---------------------------------------------- #import "shell32.dll" int ShellExecuteW(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); #import //--- functions for telegram integration ----------------------------------------------- datetime last_alert_time; input int alert_cooldown_seconds = 60; // Cooldown period in seconds void myAlert(string type, string message) { datetime current_time = TimeCurrent(); if (current_time - last_alert_time < alert_cooldown_seconds) { // Skip alert if within cooldown period return; } last_alert_time = current_time; string full_message = type + " | Trend Constraint V1.05 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message; if (type == "print") { Print(message); } else if (type == "error") { Print(type + " | Trend Constraint V1.05 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message); } else if (type == "order") { // Add order alert handling if needed } else if (type == "modify") { // Add modify alert handling if needed } else if (type == "indicator") { if (Audible_Alerts) { Alert(full_message); } if (Push_Notifications) { SendNotification(full_message); } // Send to Telegram string python_path = "C:\\Users\\your_computer_name\\AppData\\Local\\Programs\\Python\\Python312\\python.exe"; string script_path = "C:\\Users\\your_computer_name\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\send_telegram_message.py"; string command = python_path + " \"" + script_path + "\" \"" + full_message + "\""; // Debugging: Print the command being executed Print("Executing command to send Telegram message: ", command); // Use cmd.exe to execute the command and then wait for 5 seconds string final_command = "/c " + command + " && timeout 5"; int result = ShellExecuteW(0, "open", "cmd.exe", final_command, NULL, 1); if (result <= 32) { int error_code = GetLastError(); Print("Failed to execute Python script. Error code: ", error_code); } else { Print("Successfully executed Python script. Result code: ", result); } } }
- Integración de WhatsApp:
//--- ShellExecuteW declaration ---------------------------------------------- #import "shell32.dll" int ShellExecuteW(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); #import //--- global variables ------------------------------------------------------ datetime last_alert_time; input int alert_cooldown_seconds = 60; // Cooldown period in seconds //--- myAlert function ------------------------------------------------------ void myAlert(string type, string message) { datetime current_time = TimeCurrent(); if (current_time - last_alert_time < alert_cooldown_seconds) { // Skip alert if within cooldown period return; } last_alert_time = current_time; string full_message = type + " | Trend Constraint V1.06 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message; if (type == "print") { Print(message); } else if (type == "error") { Print(type + " | Trend Constraint V1.06 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message); } else if (type == "order") { // Add order alert handling if needed } else if (type == "modify") { // Add modify alert handling if needed } else if (type == "indicator" || type == "info") { if (Audible_Alerts) { Alert(full_message); } if (Push_Notifications) { SendNotification(full_message); } // Send to WhatsApp string python_path = "C:\\Users\\Your_Computer_Name\\AppData\\Local\\Programs\\Python\\Python312\\python.exe"; string script_path = "C:\\Users\\Your_Computer_Name\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\send_whatsapp_message.py"; string command = python_path + " \"" + script_path + "\" \"" + full_message + "\""; // Debugging: Print the command being executed Print("Executing command to send WhatsApp message: ", command); // Use cmd.exe to execute the command and then wait for 5 seconds string final_command = "/c " + command + " && timeout 5"; int result = ShellExecuteW(0, "open", "cmd.exe", final_command, NULL, 1); if (result <= 32) { int error_code = GetLastError(); Print("Failed to execute Python script. Error code: ", error_code); } else { Print("Successfully executed Python script. Result code: ", result); } } }
Combinación de la lógica de integración
Para crear un único programa que integre tanto WhatsApp como Telegram utilizando los dos fragmentos de código proporcionados, combinaremos la lógica de cada fragmento en una función cohesionada. Este es el plan:
- Combinar variables globales y declaraciones: Consolidaremos las declaraciones y las variables globales.
- Fusionar la función myAlert : Extenderemos la función myAlert para gestionar el envío de mensajes tanto a WhatsApp como a Telegram.
- Ajustar la lógica de ejecución de comandos: Conseguiremos que ambos comandos (WhatsApp y Telegram) se ejecuten dentro de la misma función.
- Garantizar el mantenimiento del periodo de retardo: Mantendremos la lógica que garantiza que las alertas no se envíen con demasiada frecuencia.
Para combinar declaraciones y variables globales, ambos fragmentos tenían la declaración ShellExecuteW y una variable de periodo de enfriamiento, que se unifican en la parte superior del código para evitar redundancias. La función myAlert se amplía para incluir la lógica para las notificaciones de WhatsApp y Telegram, con una lógica de enfriamiento de alertas que garantiza que los mensajes no se envíen con demasiada frecuencia. En resumen, para WhatsApp, se define la ruta al ejecutable de Python y al script de WhatsApp, y se construye una cadena de comandos para ejecutar el script de envío de mensajes de WhatsApp. Este comando se ejecuta utilizando ShellExecuteW, con una comprobación del resultado para registrar cualquier error. De forma similar, para Telegram, se define la ruta al ejecutable de Python y al script de Telegram, se construye una cadena de comandos para ejecutar el script de envío de mensajes de Telegram, y se ejecuta el comando usando ShellExecuteW, con una comprobación de resultados para registrar cualquier error.
Este es el programa combinado:
//--- ShellExecuteW declaration ---------------------------------------------- #import "shell32.dll" int ShellExecuteW(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); #import //--- global variables ------------------------------------------------------ datetime last_alert_time; input int alert_cooldown_seconds = 60; // Cooldown period in seconds //--- myAlert function ------------------------------------------------------ void myAlert(string type, string message) { datetime current_time = TimeCurrent(); if (current_time - last_alert_time < alert_cooldown_seconds) { // Skip alert if within cooldown period return; } last_alert_time = current_time; string full_message = type + " | Trend Constraint V1.06 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message; if (type == "print") { Print(message); } else if (type == "error") { Print(type + " | Trend Constraint V1.06 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message); } else if (type == "order") { // Add order alert handling if needed } else if (type == "modify") { // Add modify alert handling if needed } else if (type == "indicator" || type == "info") { if (Audible_Alerts) { Alert(full_message); } if (Push_Notifications) { SendNotification(full_message); } // Send to WhatsApp string python_path = "C:\\Users\\Your_Computer_Name\\AppData\\Local\\Programs\\Python\\Python312\\python.exe"; string whatsapp_script_path = "C:\\Users\\Your_Computer_Name\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\send_whatsapp_message.py"; string whatsapp_command = python_path + " \"" + whatsapp_script_path + "\" \"" + full_message + "\""; // Debugging: Print the command being executed for WhatsApp Print("Executing command to send WhatsApp message: ", whatsapp_command); // Use cmd.exe to execute the command and then wait for 5 seconds string final_whatsapp_command = "/c " + whatsapp_command + " && timeout 5"; int whatsapp_result = ShellExecuteW(0, "open", "cmd.exe", final_whatsapp_command, NULL, 1); if (whatsapp_result <= 32) { int error_code = GetLastError(); Print("Failed to execute WhatsApp Python script. Error code: ", error_code); } else { Print("Successfully executed WhatsApp Python script. Result code: ", whatsapp_result); } // Send to Telegram string telegram_script_path = "C:\\Users\\Your_Computer_Name\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\send_telegram_message.py"; string telegram_command = python_path + " \"" + telegram_script_path + "\" \"" + full_message + "\""; // Debugging: Print the command being executed for Telegram Print("Executing command to send Telegram message: ", telegram_command); // Use cmd.exe to execute the command and then wait for 5 seconds string final_telegram_command = "/c " + telegram_command + " && timeout 5"; int telegram_result = ShellExecuteW(0, "open", "cmd.exe", final_telegram_command, NULL, 1); if (telegram_result <= 32) { int error_code = GetLastError(); Print("Failed to execute Telegram Python script. Error code: ", error_code); } else { Print("Successfully executed Telegram Python script. Result code: ", telegram_result); } } }
En esta fase vamos a dividir el código en secciones para explicar sus funcionalidades:
#import "shell32.dll" int ShellExecuteW(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); #import
Esta sección importa la función ShellExecuteW de la biblioteca de Windows shell32.dll. ShellExecuteW es una función de la API de Windows que realiza una operación en un archivo especificado. Al importar esta función, el código MQL5 puede ejecutar comandos o scripts externos, como los scripts de Python para enviar mensajes a través de WhatsApp y Telegram.
datetime last_alert_time; input int alert_cooldown_seconds = 60; // Cooldown period in seconds
El fragmento de código anterior crea las variables globales del algoritmo de integración.
- last_alert_time: Una variable global que almacena la marca de tiempo de la última alerta enviada. Esto ayuda a implementar un periodo de retardo entre alertas.
- alert_cooldown_seconds: Una variable de entrada (configurable por el usuario) que especifica el periodo de refresco en segundos. Determina la frecuencia de envío de las alertas para evitar el spam.
void myAlert(string type, string message) { datetime current_time = TimeCurrent(); if (current_time - last_alert_time < alert_cooldown_seconds) { // Skip alert if within cooldown period return; } last_alert_time = current_time; string full_message = type + " | Trend Constraint V1.06 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message; if (type == "print") { Print(message); } else if (type == "error") { Print(type + " | Trend Constraint V1.06 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message); } else if (type == "order") { // Add order alert handling if needed } else if (type == "modify") { // Add modify alert handling if needed } else if (type == "indicator" || type == "info") { if (Audible_Alerts) { Alert(full_message); } if (Push_Notifications) { SendNotification(full_message); } // Send to WhatsApp string python_path = "C:\\Users\\Your_Computer_Name\\AppData\\Local\\Programs\\Python\\Python312\\python.exe"; string whatsapp_script_path = "C:\\Users\\Your_Computer_Name\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\send_whatsapp_message.py"; string whatsapp_command = python_path + " \"" + whatsapp_script_path + "\" \"" + full_message + "\""; // Debugging: Print the command being executed for WhatsApp Print("Executing command to send WhatsApp message: ", whatsapp_command); // Use cmd.exe to execute the command and then wait for 5 seconds string final_whatsapp_command = "/c " + whatsapp_command + " && timeout 5"; int whatsapp_result = ShellExecuteW(0, "open", "cmd.exe", final_whatsapp_command, NULL, 1); if (whatsapp_result <= 32) { int error_code = GetLastError(); Print("Failed to execute WhatsApp Python script. Error code: ", error_code); } else { Print("Successfully executed WhatsApp Python script. Result code: ", whatsapp_result); } // Send to Telegram string telegram_script_path = "C:\\Users\\Your_Computer_Name\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\send_telegram_message.py"; string telegram_command = python_path + " \"" + telegram_script_path + "\" \"" + full_message + "\""; // Debugging: Print the command being executed for Telegram Print("Executing command to send Telegram message: ", telegram_command); // Use cmd.exe to execute the command and then wait for 5 seconds string final_telegram_command = "/c " + telegram_command + " && timeout 5"; int telegram_result = ShellExecuteW(0, "open", "cmd.exe", final_telegram_command, NULL, 1); if (telegram_result <= 32) { int error_code = GetLastError(); Print("Failed to execute Telegram Python script. Error code: ", error_code); } else { Print("Successfully executed Telegram Python script. Result code: ", telegram_result); } } }
- La función myAlert está diseñada para enviar alertas basadas en el tipo y el mensaje proporcionados. Gestiona el periodo de enfriamiento, construye el mensaje de alerta y lo envía tanto a WhatsApp como a Telegram utilizando scripts Python externos. Como puede ver, es la sección más grande del código.
datetime current_time = TimeCurrent(); if (current_time - last_alert_time < alert_cooldown_seconds) { // Skip alert if within cooldown period return; } last_alert_time = current_time;
- Esta sección comprueba si la hora actual menos la última hora de alerta es inferior al periodo de enfriamiento. Si es verdadero, omite el envío de la alerta. De este modo, se evitan las alertas frecuentes en un breve periodo de tiempo.
Para asegurarnos de que nuestros scripts funcionan, obtenemos los siguientes resultados en el símbolo del sistema:
C:\Users\Your_Computer_Name\AppData\Local\Programs\Python\Python312\Scripts>python send_telegram_message.py "Trend Constraint V1.07 testing" Message sent successfully! C:\Users\Your_Computer_Name\AppData\Local\Programs\Python\Python312\Scripts>python send_whatsapp_message.py "Trend Constraint V1.07 testing" Message sent successfully
El texto resaltado es la respuesta positiva del símbolo del sistema, que confirma que nuestros scripts funcionan correctamente. Es muy importante añadir correctamente la ruta del archivo en el programa principal.
Por otro lado, también recibimos las señales en nuestras plataformas sociales. Abajo, a la izquierda, hay una imagen que muestra un mensaje de prueba de Telegram desde el símbolo del sistema, y a la derecha, un mensaje de prueba de WhatsApp desde el símbolo del sistema. Ahora estamos seguros de que nuestro programa está funcionando bien, y podemos proceder a nuestro programa principal.
En la ilustración anterior, la conexión sandbox proporcionada por la API de Twilio para la integración de WhatsApp caduca en 72 horas. Es importante volver a conectarse enviando un mensaje único para volver a recibir mensajes de la API. En este caso, el mensaje para reconectarse es «join so-cave». Para adquirir un servicio que no caduque, puedes comprar un número Twilio.
Procedamos e integremos todo en un programa utilizando la lógica del indicador Trend Constraint. Esto nos lleva a Trend Constraint V1.07:
//+------------------------------------------------------------------+ //| Trend Constraint V1.07.mq5 | //| Copyright 2024, Clemence Benjamin | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Clemence Benjamin" #property link "https://www.mql5.com" #property version "1.07" #property description "A model that seeks to produce sell signals when D1 candle is Bearish only and buy signals when it is Bullish" //--- indicator settings #property indicator_chart_window #property indicator_buffers 6 #property indicator_plots 6 #property indicator_type1 DRAW_ARROW #property indicator_width1 5 #property indicator_color1 0xFF3C00 #property indicator_label1 "Buy" #property indicator_type2 DRAW_ARROW #property indicator_width2 5 #property indicator_color2 0x0000FF #property indicator_label2 "Sell" #property indicator_type3 DRAW_ARROW #property indicator_width3 2 #property indicator_color3 0xE8351A #property indicator_label3 "Buy Reversal" #property indicator_type4 DRAW_ARROW #property indicator_width4 2 #property indicator_color4 0x1A1AE8 #property indicator_label4 "Sell Reversal" #property indicator_type5 DRAW_LINE #property indicator_style5 STYLE_SOLID #property indicator_width5 2 #property indicator_color5 0xFFAA00 #property indicator_label5 "Buy" #property indicator_type6 DRAW_LINE #property indicator_style6 STYLE_SOLID #property indicator_width6 2 #property indicator_color6 0x0000FF #property indicator_label6 "Sell" #define PLOT_MAXIMUM_BARS_BACK 5000 #define OMIT_OLDEST_BARS 50 //--- indicator buffers double Buffer1[]; double Buffer2[]; double Buffer3[]; double Buffer4[]; double Buffer5[]; double Buffer6[]; input double Oversold = 30; input double Overbought = 70; input int Slow_MA_period = 200; input int Fast_MA_period = 100; datetime time_alert; //used when sending alert input bool Audible_Alerts = true; input bool Push_Notifications = true; double myPoint; //initialized in OnInit int RSI_handle; double RSI[]; double Open[]; double Close[]; int MA_handle; double MA[]; int MA_handle2; double MA2[]; int MA_handle3; double MA3[]; int MA_handle4; double MA4[]; double Low[]; double High[]; int MA_handle5; double MA5[]; int MA_handle6; double MA6[]; int MA_handle7; double MA7[]; //--- ShellExecuteW declaration ---------------------------------------------- #import "shell32.dll" int ShellExecuteW(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); #import //--- global variables ------------------------------------------------------ datetime last_alert_time; input int alert_cooldown_seconds = 60; // Cooldown period in seconds //--- myAlert function ------------------------------------------------------ void myAlert(string type, string message) { datetime current_time = TimeCurrent(); if (current_time - last_alert_time < alert_cooldown_seconds) { // Skip alert if within cooldown period return; } last_alert_time = current_time; string full_message = type + " | Trend Constraint V1.07 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message; if (type == "print") { Print(message); } else if (type == "error") { Print(type + " | Trend Constraint V1.07 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message); } else if (type == "order") { // Add order alert handling if needed } else if (type == "modify") { // Add modify alert handling if needed } else if (type == "indicator" || type == "info") { if (Audible_Alerts) { Alert(full_message); } if (Push_Notifications) { SendNotification(full_message); } // Send to WhatsApp //Replace your_computer_name with the your actual computer name. //Make sure the path to your python and scripts is correct. string python_path = "C:\\Users\\Your_Computer\\AppData\\Local\\Programs\\Python\\Python312\\python.exe"; string whatsapp_script_path = "C:\\Users\\Your_computer_name\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\send_whatsapp_message.py"; string whatsapp_command = python_path + " \"" + whatsapp_script_path + "\" \"" + full_message + "\""; // Debugging: Print the command being executed for WhatsApp Print("Executing command to send WhatsApp message: ", whatsapp_command); // Use cmd.exe to execute the command and then wait for 5 seconds string final_whatsapp_command = "/c " + whatsapp_command + " && timeout 5"; int whatsapp_result = ShellExecuteW(0, "open", "cmd.exe", final_whatsapp_command, NULL, 1); if (whatsapp_result <= 32) { int error_code = GetLastError(); Print("Failed to execute WhatsApp Python script. Error code: ", error_code); } else { Print("Successfully executed WhatsApp Python script. Result code: ", whatsapp_result); } // Send to Telegram string telegram_script_path = "C:\\Users\\protech\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\send_telegram_message.py"; string telegram_command = python_path + " \"" + telegram_script_path + "\" \"" + full_message + "\""; // Debugging: Print the command being executed for Telegram Print("Executing command to send Telegram message: ", telegram_command); // Use cmd.exe to execute the command and then wait for 5 seconds string final_telegram_command = "/c " + telegram_command + " && timeout 5"; int telegram_result = ShellExecuteW(0, "open", "cmd.exe", final_telegram_command, NULL, 1); if (telegram_result <= 32) { int error_code = GetLastError(); Print("Failed to execute Telegram Python script. Error code: ", error_code); } else { Print("Successfully executed Telegram Python script. Result code: ", telegram_result); } } } //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0, Buffer1); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(0, PLOT_ARROW, 241); SetIndexBuffer(1, Buffer2); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(1, PLOT_ARROW, 242); SetIndexBuffer(2, Buffer3); PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(2, PLOT_ARROW, 236); SetIndexBuffer(3, Buffer4); PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(3, PLOT_ARROW, 238); SetIndexBuffer(4, Buffer5); PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(4, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); SetIndexBuffer(5, Buffer6); PlotIndexSetDouble(5, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(5, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); // Send test message on launch myAlert("info", "Thank you for subscribing. You shall be receiving Trend Constraint signal alerts via Whatsapp."); //initialize myPoint myPoint = Point(); if(Digits() == 5 || Digits() == 3) { myPoint *= 10; } RSI_handle = iRSI(NULL, PERIOD_CURRENT, 14, PRICE_CLOSE); if(RSI_handle < 0) { Print("The creation of iRSI has failed: RSI_handle=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle = iMA(NULL, PERIOD_CURRENT, 7, 0, MODE_SMMA, PRICE_CLOSE); if(MA_handle < 0) { Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle2 = iMA(NULL, PERIOD_CURRENT, 400, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle2 < 0) { Print("The creation of iMA has failed: MA_handle2=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle3 = iMA(NULL, PERIOD_CURRENT, 100, 0, MODE_EMA, PRICE_CLOSE); if(MA_handle3 < 0) { Print("The creation of iMA has failed: MA_handle3=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle4 = iMA(NULL, PERIOD_CURRENT, 200, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle4 < 0) { Print("The creation of iMA has failed: MA_handle4=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle5 = iMA(NULL, PERIOD_CURRENT, Fast_MA_period, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle5 < 0) { Print("The creation of iMA has failed: MA_handle5=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle6 = iMA(NULL, PERIOD_CURRENT, Slow_MA_period, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle6 < 0) { Print("The creation of iMA has failed: MA_handle6=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle7 = iMA(NULL, PERIOD_CURRENT, 200, 0, MODE_EMA, PRICE_CLOSE); if(MA_handle7 < 0) { Print("The creation of iMA has failed: MA_handle7=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime& time[], const double& open[], const double& high[], const double& low[], const double& close[], const long& tick_volume[], const long& volume[], const int& spread[]) { int limit = rates_total - prev_calculated; //--- counting from 0 to rates_total ArraySetAsSeries(Buffer1, true); ArraySetAsSeries(Buffer2, true); ArraySetAsSeries(Buffer3, true); ArraySetAsSeries(Buffer4, true); ArraySetAsSeries(Buffer5, true); ArraySetAsSeries(Buffer6, true); //--- initial zero if(prev_calculated < 1) { ArrayInitialize(Buffer1, EMPTY_VALUE); ArrayInitialize(Buffer2, EMPTY_VALUE); ArrayInitialize(Buffer3, EMPTY_VALUE); ArrayInitialize(Buffer4, EMPTY_VALUE); ArrayInitialize(Buffer5, EMPTY_VALUE); ArrayInitialize(Buffer6, EMPTY_VALUE); } else limit++; datetime Time[]; datetime TimeShift[]; if(CopyTime(Symbol(), PERIOD_CURRENT, 0, rates_total, TimeShift) <= 0) return(rates_total); ArraySetAsSeries(TimeShift, true); int barshift_M1[]; ArrayResize(barshift_M1, rates_total); int barshift_D1[]; ArrayResize(barshift_D1, rates_total); for(int i = 0; i < rates_total; i++) { barshift_M1[i] = iBarShift(Symbol(), PERIOD_M1, TimeShift[i]); barshift_D1[i] = iBarShift(Symbol(), PERIOD_D1, TimeShift[i]); } if(BarsCalculated(RSI_handle) <= 0) return(0); if(CopyBuffer(RSI_handle, 0, 0, rates_total, RSI) <= 0) return(rates_total); ArraySetAsSeries(RSI, true); if(CopyOpen(Symbol(), PERIOD_M1, 0, rates_total, Open) <= 0) return(rates_total); ArraySetAsSeries(Open, true); if(CopyClose(Symbol(), PERIOD_D1, 0, rates_total, Close) <= 0) return(rates_total); ArraySetAsSeries(Close, true); if(BarsCalculated(MA_handle) <= 0) return(0); if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) <= 0) return(rates_total); ArraySetAsSeries(MA, true); if(BarsCalculated(MA_handle2) <= 0) return(0); if(CopyBuffer(MA_handle2, 0, 0, rates_total, MA2) <= 0) return(rates_total); ArraySetAsSeries(MA2, true); if(BarsCalculated(MA_handle3) <= 0) return(0); if(CopyBuffer(MA_handle3, 0, 0, rates_total, MA3) <= 0) return(rates_total); ArraySetAsSeries(MA3, true); if(BarsCalculated(MA_handle4) <= 0) return(0); if(CopyBuffer(MA_handle4, 0, 0, rates_total, MA4) <= 0) return(rates_total); ArraySetAsSeries(MA4, true); if(CopyLow(Symbol(), PERIOD_CURRENT, 0, rates_total, Low) <= 0) return(rates_total); ArraySetAsSeries(Low, true); if(CopyHigh(Symbol(), PERIOD_CURRENT, 0, rates_total, High) <= 0) return(rates_total); ArraySetAsSeries(High, true); if(BarsCalculated(MA_handle5) <= 0) return(0); if(CopyBuffer(MA_handle5, 0, 0, rates_total, MA5) <= 0) return(rates_total); ArraySetAsSeries(MA5, true); if(BarsCalculated(MA_handle6) <= 0) return(0); if(CopyBuffer(MA_handle6, 0, 0, rates_total, MA6) <= 0) return(rates_total); ArraySetAsSeries(MA6, true); if(BarsCalculated(MA_handle7) <= 0) return(0); if(CopyBuffer(MA_handle7, 0, 0, rates_total, MA7) <= 0) return(rates_total); ArraySetAsSeries(MA7, true); if(CopyTime(Symbol(), Period(), 0, rates_total, Time) <= 0) return(rates_total); ArraySetAsSeries(Time, true); //--- main loop for(int i = limit-1; i >= 0; i--) { if (i >= MathMin(PLOT_MAXIMUM_BARS_BACK-1, rates_total-1-OMIT_OLDEST_BARS)) continue; //omit some old rates to prevent "Array out of range" or slow calculation if(barshift_M1[i] < 0 || barshift_M1[i] >= rates_total) continue; if(barshift_D1[i] < 0 || barshift_D1[i] >= rates_total) continue; //Indicator Buffer 1 if(RSI[i] < Oversold && RSI[i+1] > Oversold //Relative Strength Index crosses below fixed value && Open[barshift_M1[i]] >= Close[1+barshift_D1[i]] //Candlestick Open >= Candlestick Close && MA[i] > MA2[i] //Moving Average > Moving Average && MA3[i] > MA4[i] //Moving Average > Moving Average ) { Buffer1[i] = Low[1+i]; //Set indicator value at Candlestick Low if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy"); //Alert on next bar open time_alert = Time[1]; } else { Buffer1[i] = EMPTY_VALUE; } //Indicator Buffer 2 if(RSI[i] > Overbought && RSI[i+1] < Overbought //Relative Strength Index crosses above fixed value && Open[barshift_M1[i]] <= Close[1+barshift_D1[i]] //Candlestick Open <= Candlestick Close && MA[i] < MA2[i] //Moving Average < Moving Average && MA3[i] < MA4[i] //Moving Average < Moving Average ) { Buffer2[i] = High[1+i]; //Set indicator value at Candlestick High if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell"); //Alert on next bar open time_alert = Time[1]; } else { Buffer2[i] = EMPTY_VALUE; } //Indicator Buffer 3 if(MA5[i] > MA6[i] && MA5[i+1] < MA6[i+1] //Moving Average crosses above Moving Average ) { Buffer3[i] = Low[i]; //Set indicator value at Candlestick Low if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy Reversal"); //Alert on next bar open time_alert = Time[1]; } else { Buffer3[i] = EMPTY_VALUE; } //Indicator Buffer 4 if(MA5[i] < MA6[i] && MA5[i+1] > MA6[i+1] //Moving Average crosses below Moving Average ) { Buffer4[i] = High[i]; //Set indicator value at Candlestick High if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell Reversal"); //Alert on next bar open time_alert = Time[1]; } else { Buffer4[i] = EMPTY_VALUE; } //Indicator Buffer 5, Alert muted by turning it into a comment if(MA3[i] > MA7[i] //Moving Average > Moving Average ) { Buffer5[i] = MA3[i]; //Set indicator value at Moving Average //if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy"); //Alert on next bar open //time_alert = Time[1]; } else { Buffer5[i] = EMPTY_VALUE; } //Indicator Buffer 6, Alert muted by turning it into a comment if(MA3[i] < MA7[i] //Moving Average < Moving Average ) { Buffer6[i] = MA3[i]; //Set indicator value at Moving Average //if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell"); //Alert on next bar open //time_alert = Time[1]; } else { Buffer6[i] = EMPTY_VALUE; } } return(rates_total); } //+------------------------------------------------------------------+
Si observó atentamente, actualizamos el indicador de V1.06 a V1.07. Después de compilar el programa, no encontramos errores, y nuestro programa está funcionando sin problemas en MetaTrader 5. A continuación se muestran imágenes de los mensajes de prueba enviados al lanzar el indicador en MT5: en el extremo izquierdo son notificaciones Push en MetaTrader 5 móvil Android, en el centro hay una notificación de prueba de Telegram, y a la derecha hay un mensaje de prueba de WhatsApp.
La función Comment
La función Comment de MQL5 es una función incorporada que se utiliza para mostrar mensajes de texto personalizados directamente en el gráfico. Esta función nos ayuda a proporcionar información visual en tiempo real mostrando mensajes que pueden actualizarse continuamente durante la ejecución de un indicador o un Asesor Experto. En este caso, nuestro objetivo es utilizarlo para lograr lo siguiente:
- Notificar al usuario el lanzamiento con éxito del indicador.
- Confirmación del envío correcto de los mensajes de alerta.
- Alertar al usuario de fallos en el envío de mensajes de alerta.
Nos centraremos en tres áreas del código para incorporar la función:
int OnInit() { // Initialization code here Comment("Indicator successfully launched."); return INIT_SUCCEEDED; }
El objetivo del fragmento de código anterior es notificarnos que el indicador se ha lanzado correctamente. Una vez inicializado correctamente el indicador, la función Comment muestra el mensaje «Indicator successfully launched» en el gráfico. Esto proporciona información inmediata de que el indicador está activo y funcionando.
if (result > 32) { Print("Successfully executed Python script. Result code: ", result); Comment("Success message sent: " + message); }
Sirve para informarnos de que se ha enviado correctamente un mensaje de alerta. Cuando se envía con éxito un mensaje de alerta utilizando la función myAlert, la función muestra el mensaje «Success message sent [message]» en el gráfico, donde [message] es el contenido real de la alerta. Esto nos confirma que la alerta se ha enviado correctamente.
if (result <= 32) { int error_code = GetLastError(); Print("Failed to execute Python script. Error code: ", error_code); Comment("Failed to send message: " + message); }
Por último, también queremos ser informados de un lanzamiento fallido y esto mejora la funcionalidad de nuestro programa. Este fragmento nos notifica un fallo en el envío de un mensaje de alerta. Si se produce un fallo en el envío de un mensaje de alerta, muestra el mensaje «Failed to send message [message]» en el gráfico, donde [message] es el contenido de la alerta prevista. Esto nos alerta del fallo, lo que les permite tomar medidas correctoras.
Para aprovechar las nuevas capacidades introducidas por la función Comment, he actualizado nuestro programa a Trend Constraint V1.08. Al integrar estratégicamente esta función en las secciones pertinentes del código, conseguí actualizar el programa, garantizando su buen funcionamiento. A continuación, encontrará el código fuente con las secciones modificadas resaltadas, mostrando las mejoras realizadas.
//+------------------------------------------------------------------+ //| Trend Constraint V1.08.mq5 | //| Copyright 2024, Clemence Benjamin | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property indicator_chart_window #property copyright "Copyright 2024, Clemence Benjamin" #property link "https://www.mql5.com" #property version "1.08" #property description "A model that seeks to produce sell signals when D1 candle is Bearish only and buy signals when it is Bullish" //--- indicator settings #property indicator_chart_window #property indicator_buffers 6 #property indicator_plots 6 #property indicator_type1 DRAW_ARROW #property indicator_width1 5 #property indicator_color1 0xFF3C00 #property indicator_label1 "Buy" #property indicator_type2 DRAW_ARROW #property indicator_width2 5 #property indicator_color2 0x0000FF #property indicator_label2 "Sell" #property indicator_type3 DRAW_ARROW #property indicator_width3 2 #property indicator_color3 0xE8351A #property indicator_label3 "Buy Reversal" #property indicator_type4 DRAW_ARROW #property indicator_width4 2 #property indicator_color4 0x1A1AE8 #property indicator_label4 "Sell Reversal" #property indicator_type5 DRAW_LINE #property indicator_style5 STYLE_SOLID #property indicator_width5 2 #property indicator_color5 0xFFAA00 #property indicator_label5 "Buy" #property indicator_type6 DRAW_LINE #property indicator_style6 STYLE_SOLID #property indicator_width6 2 #property indicator_color6 0x0000FF #property indicator_label6 "Sell" #define PLOT_MAXIMUM_BARS_BACK 5000 #define OMIT_OLDEST_BARS 50 //--- indicator buffers double Buffer1[]; double Buffer2[]; double Buffer3[]; double Buffer4[]; double Buffer5[]; double Buffer6[]; input double Oversold = 30; input double Overbought = 70; input int Slow_MA_period = 200; input int Fast_MA_period = 100; datetime time_alert; //used when sending alert input bool Audible_Alerts = true; input bool Push_Notifications = true; double myPoint; //initialized in OnInit int RSI_handle; double RSI[]; double Open[]; double Close[]; int MA_handle; double MA[]; int MA_handle2; double MA2[]; int MA_handle3; double MA3[]; int MA_handle4; double MA4[]; double Low[]; double High[]; int MA_handle5; double MA5[]; int MA_handle6; double MA6[]; int MA_handle7; double MA7[]; //--- ShellExecuteW declaration ---------------------------------------------- #import "shell32.dll" int ShellExecuteW(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); #import //--- global variables ------------------------------------------------------ datetime last_alert_time; input int alert_cooldown_seconds = 60; // Cooldown period in seconds //--- myAlert function ------------------------------------------------------ void myAlert(string type, string message) { datetime current_time = TimeCurrent(); if (current_time - last_alert_time < alert_cooldown_seconds) { // Skip alert if within cooldown period return; } last_alert_time = current_time; string full_message = type + " | Trend Constraint V1.08 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message; string comment = "Alert triggered by Trend Constraint V1.08 | Symbol: " + Symbol() + " | Period: " + IntegerToString(Period()) + " | Message: " + message; if (type == "print") { Print(message); } else if (type == "error") { Print(type + " | Trend Constraint V1.08 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message); } else if (type == "order") { // Add order alert handling if needed } else if (type == "modify") { // Add modify alert handling if needed } else if (type == "indicator" || type == "info") { if (Audible_Alerts) { Alert(full_message); } if (Push_Notifications) { SendNotification(full_message); } // Send to WhatsApp string python_path = "C:\\Users\\protech\\AppData\\Local\\Programs\\Python\\Python312\\python.exe"; string whatsapp_script_path = "C:\\Users\\protech\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\send_whatsapp_message.py"; string whatsapp_command = python_path + " \"" + whatsapp_script_path + "\" \"" + full_message + "\""; // Debugging: Print the command being executed for WhatsApp Print("Executing command to send WhatsApp message: ", whatsapp_command); // Use cmd.exe to execute the command and then wait for 5 seconds string final_whatsapp_command = "/c " + whatsapp_command + " && timeout 5"; int whatsapp_result = ShellExecuteW(0, "open", "cmd.exe", final_whatsapp_command, NULL, 0); if (whatsapp_result <= 32) { int error_code = GetLastError(); Print("Failed to execute WhatsApp Python script. Error code: ", error_code); Comment("Failed to send message: " + message); } else { Print("Successfully executed WhatsApp Python script. Result code: ", whatsapp_result); Comment("Success message sent: " + message); } // Send to Telegram string telegram_script_path = "C:\\Users\\protech\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\send_telegram_message.py"; string telegram_command = python_path + " \"" + telegram_script_path + "\" \"" + full_message + "\""; // Debugging: Print the command being executed for Telegram Print("Executing command to send Telegram message: ", telegram_command); // Use cmd.exe to execute the command and then wait for 5 seconds string final_telegram_command = "/c " + telegram_command + " && timeout 5"; int telegram_result = ShellExecuteW(0, "open", "cmd.exe", final_telegram_command, NULL, 0); if (telegram_result <= 32) { int error_code = GetLastError(); Print("Failed to execute Telegram Python script. Error code: ", error_code); Comment("Failed to send message: " + message); } else { Print("Successfully executed Telegram Python script. Result code: ", telegram_result); Comment("Success message sent: " + message); } } } //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0, Buffer1); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(0, PLOT_ARROW, 241); SetIndexBuffer(1, Buffer2); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(1, PLOT_ARROW, 242); SetIndexBuffer(2, Buffer3); PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(2, PLOT_ARROW, 236); SetIndexBuffer(3, Buffer4); PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(3, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(3, PLOT_ARROW, 238); SetIndexBuffer(4, Buffer5); PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(4, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); SetIndexBuffer(5, Buffer6); PlotIndexSetDouble(5, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(5, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); // Send test message on launch myAlert("info", "Thank you for subscribing. You shall be receiving Trend Constraint signal alerts via Whatsapp."); //initialize myPoint myPoint = Point(); if(Digits() == 5 || Digits() == 3) { myPoint *= 10; } RSI_handle = iRSI(NULL, PERIOD_CURRENT, 14, PRICE_CLOSE); if(RSI_handle < 0) { Print("The creation of iRSI has failed: RSI_handle=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle = iMA(NULL, PERIOD_CURRENT, 7, 0, MODE_SMMA, PRICE_CLOSE); if(MA_handle < 0) { Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle2 = iMA(NULL, PERIOD_CURRENT, 400, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle2 < 0) { Print("The creation of iMA has failed: MA_handle2=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle3 = iMA(NULL, PERIOD_CURRENT, 100, 0, MODE_EMA, PRICE_CLOSE); if(MA_handle3 < 0) { Print("The creation of iMA has failed: MA_handle3=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle4 = iMA(NULL, PERIOD_CURRENT, 200, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle4 < 0) { Print("The creation of iMA has failed: MA_handle4=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle5 = iMA(NULL, PERIOD_CURRENT, Fast_MA_period, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle5 < 0) { Print("The creation of iMA has failed: MA_handle5=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle6 = iMA(NULL, PERIOD_CURRENT, Slow_MA_period, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle6 < 0) { Print("The creation of iMA has failed: MA_handle6=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } MA_handle7 = iMA(NULL, PERIOD_CURRENT, 200, 0, MODE_EMA, PRICE_CLOSE); if(MA_handle7 < 0) { Print("The creation of iMA has failed: MA_handle7=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } Comment("Indicator successfully launched."); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime& time[], const double& open[], const double& high[], const double& low[], const double& close[], const long& tick_volume[], const long& volume[], const int& spread[]) { int limit = rates_total - prev_calculated; //--- counting from 0 to rates_total ArraySetAsSeries(Buffer1, true); ArraySetAsSeries(Buffer2, true); ArraySetAsSeries(Buffer3, true); ArraySetAsSeries(Buffer4, true); ArraySetAsSeries(Buffer5, true); ArraySetAsSeries(Buffer6, true); //--- initial zero if(prev_calculated < 1) { ArrayInitialize(Buffer1, EMPTY_VALUE); ArrayInitialize(Buffer2, EMPTY_VALUE); ArrayInitialize(Buffer3, EMPTY_VALUE); ArrayInitialize(Buffer4, EMPTY_VALUE); ArrayInitialize(Buffer5, EMPTY_VALUE); ArrayInitialize(Buffer6, EMPTY_VALUE); } else limit++; datetime Time[]; datetime TimeShift[]; if(CopyTime(Symbol(), PERIOD_CURRENT, 0, rates_total, TimeShift) <= 0) return(rates_total); ArraySetAsSeries(TimeShift, true); int barshift_M1[]; ArrayResize(barshift_M1, rates_total); int barshift_D1[]; ArrayResize(barshift_D1, rates_total); for(int i = 0; i < rates_total; i++) { barshift_M1[i] = iBarShift(Symbol(), PERIOD_M1, TimeShift[i]); barshift_D1[i] = iBarShift(Symbol(), PERIOD_D1, TimeShift[i]); } if(BarsCalculated(RSI_handle) <= 0) return(0); if(CopyBuffer(RSI_handle, 0, 0, rates_total, RSI) <= 0) return(rates_total); ArraySetAsSeries(RSI, true); if(CopyOpen(Symbol(), PERIOD_M1, 0, rates_total, Open) <= 0) return(rates_total); ArraySetAsSeries(Open, true); if(CopyClose(Symbol(), PERIOD_D1, 0, rates_total, Close) <= 0) return(rates_total); ArraySetAsSeries(Close, true); if(BarsCalculated(MA_handle) <= 0) return(0); if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) <= 0) return(rates_total); ArraySetAsSeries(MA, true); if(BarsCalculated(MA_handle2) <= 0) return(0); if(CopyBuffer(MA_handle2, 0, 0, rates_total, MA2) <= 0) return(rates_total); ArraySetAsSeries(MA2, true); if(BarsCalculated(MA_handle3) <= 0) return(0); if(CopyBuffer(MA_handle3, 0, 0, rates_total, MA3) <= 0) return(rates_total); ArraySetAsSeries(MA3, true); if(BarsCalculated(MA_handle4) <= 0) return(0); if(CopyBuffer(MA_handle4, 0, 0, rates_total, MA4) <= 0) return(rates_total); ArraySetAsSeries(MA4, true); if(CopyLow(Symbol(), PERIOD_CURRENT, 0, rates_total, Low) <= 0) return(rates_total); ArraySetAsSeries(Low, true); if(CopyHigh(Symbol(), PERIOD_CURRENT, 0, rates_total, High) <= 0) return(rates_total); ArraySetAsSeries(High, true); if(BarsCalculated(MA_handle5) <= 0) return(0); if(CopyBuffer(MA_handle5, 0, 0, rates_total, MA5) <= 0) return(rates_total); ArraySetAsSeries(MA5, true); if(BarsCalculated(MA_handle6) <= 0) return(0); if(CopyBuffer(MA_handle6, 0, 0, rates_total, MA6) <= 0) return(rates_total); ArraySetAsSeries(MA6, true); if(BarsCalculated(MA_handle7) <= 0) return(0); if(CopyBuffer(MA_handle7, 0, 0, rates_total, MA7) <= 0) return(rates_total); ArraySetAsSeries(MA7, true); if(CopyTime(Symbol(), Period(), 0, rates_total, Time) <= 0) return(rates_total); ArraySetAsSeries(Time, true); //--- main loop for(int i = limit-1; i >= 0; i--) { if (i >= MathMin(PLOT_MAXIMUM_BARS_BACK-1, rates_total-1-OMIT_OLDEST_BARS)) continue; //omit some old rates to prevent "Array out of range" or slow calculation if(barshift_M1[i] < 0 || barshift_M1[i] >= rates_total) continue; if(barshift_D1[i] < 0 || barshift_D1[i] >= rates_total) continue; //Indicator Buffer 1 if(RSI[i] < Oversold && RSI[i+1] > Oversold //Relative Strength Index crosses below fixed value && Open[barshift_M1[i]] >= Close[1+barshift_D1[i]] //Candlestick Open >= Candlestick Close && MA[i] > MA2[i] //Moving Average > Moving Average && MA3[i] > MA4[i] //Moving Average > Moving Average ) { Buffer1[i] = Low[1+i]; //Set indicator value at Candlestick Low if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy"); //Alert on next bar open time_alert = Time[1]; } else { Buffer1[i] = EMPTY_VALUE; } //Indicator Buffer 2 if(RSI[i] > Overbought && RSI[i+1] < Overbought //Relative Strength Index crosses above fixed value && Open[barshift_M1[i]] <= Close[1+barshift_D1[i]] //Candlestick Open <= Candlestick Close && MA[i] < MA2[i] //Moving Average < Moving Average && MA3[i] < MA4[i] //Moving Average < Moving Average ) { Buffer2[i] = High[1+i]; //Set indicator value at Candlestick High if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell"); //Alert on next bar open time_alert = Time[1]; } else { Buffer2[i] = EMPTY_VALUE; } //Indicator Buffer 3 if(MA5[i] > MA6[i] && MA5[i+1] < MA6[i+1] //Moving Average crosses above Moving Average ) { Buffer3[i] = Low[i]; //Set indicator value at Candlestick Low if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy Reversal"); //Alert on next bar open time_alert = Time[1]; } else { Buffer3[i] = EMPTY_VALUE; } //Indicator Buffer 4 if(MA5[i] < MA6[i] && MA5[i+1] > MA6[i+1] //Moving Average crosses below Moving Average ) { Buffer4[i] = High[i]; //Set indicator value at Candlestick High if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell Reversal"); //Alert on next bar open time_alert = Time[1]; } else { Buffer4[i] = EMPTY_VALUE; } //Indicator Buffer 5, Alert muted by turning it into a comment if(MA3[i] > MA7[i] //Moving Average > Moving Average ) { Buffer5[i] = MA3[i]; //Set indicator value at Moving Average //if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Buy"); //Alert on next bar open //time_alert = Time[1]; } else { Buffer5[i] = EMPTY_VALUE; } //Indicator Buffer 6, Alert muted by turning it into a comment if(MA3[i] < MA7[i] //Moving Average < Moving Average ) { Buffer6[i] = MA3[i]; //Set indicator value at Moving Average //if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Sell"); //Alert on next bar open //time_alert = Time[1]; } else { Buffer6[i] = EMPTY_VALUE; } } return(rates_total); } //+------------------------------------------------------------------+
Comprobación de los efectos de la función Comment
Implementar la función Comment en MQL5 es una forma sencilla de mejorar la interactividad y la forma de los gráficos de operaciones. Al integrar esta función, puede proporcionar a los operadores actualizaciones esenciales en tiempo real directamente en sus gráficos, mejorando su experiencia general de negociación. Esta función permite mostrar datos dinámicos, como precios actuales, valores de indicadores y mensajes personalizados, de forma clara y concisa. Como resultado, los operadores pueden tomar decisiones más informadas sin necesidad de cambiar entre varias ventanas o herramientas externas.
La facilidad de uso y la flexibilidad de la función Comment la convierten en una herramienta inestimable para desarrollar algoritmos de negociación más fáciles de usar y eficientes. Al incorporar información contextual en tiempo real directamente a la interfaz de negociación, la función mejora el conocimiento de la situación y agiliza el proceso de negociación, contribuyendo a una experiencia de usuario más eficaz y satisfactoria. He aquí una imagen que muestra el lanzamiento con éxito de Trend Constraint V1.07:
Conclusión
En el camino hacia el desarrollo de software, la innovación suele venir de la integración perfecta de soluciones existentes para crear aplicaciones más sólidas y con más funciones. Este artículo explora el proceso de fusión de dos programas en una sola unidad cohesiva, demostrando el poder de la combinación de funcionalidades para mejorar el rendimiento general y la experiencia del usuario.Empezamos por comprender las funciones básicas de los dos programas, cada uno con sus puntos fuertes. Analizando detenidamente sus bases de código e identificando puntos de sinergia, conseguimos fusionarlas en un programa unificado. Esta fusión no sólo agilizó las operaciones, sino que también redujo la redundancia y los posibles conflictos, allanando el camino para una ejecución más eficiente.
Además, la incorporación de la función Comment en el programa MQL5 añadió una nueva dimensión a nuestra aplicación combinada. Aprovechando el sólido sistema de alertas de MQL5, implementamos una función que permite recibir notificaciones en tiempo real a través de varios canales, incluidos WhatsApp y Telegram. Esta mejora garantiza que los usuarios estén siempre informados de los acontecimientos críticos, mejorando así la capacidad de respuesta y la toma de decisiones.
A medida que avanzamos, las posibilidades de nuevas mejoras y personalizaciones siguen siendo enormes, lo que invita a la mejora y la innovación continuas. Aprovechando las tecnologías existentes e integrando cuidadosamente nuevas funciones, podemos crear herramientas potentes que impulsen la eficiencia, mejoren la participación de los usuarios y, en última instancia, conduzcan a mejores resultados.
Vea los archivos adjuntos a continuación. Los comentarios y opiniones son siempre bienvenidos.
Adjunto | Descripción |
---|---|
Trend Constraint V1.07.mq5 | Integración de dos plataformas en un solo programa. |
Trend Constraint V1.08.mq5 | Incorporando la función de comando. |
Send_telegram_message.py | Script para enviar mensajes de Telegram. |
send_whatsapp_message.py | Script para enviar mensajes de WhatsApp. |
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/15143





- 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