Построение модели для ограничения диапазона сигналов по тренду (Часть 6): Интеграция "всё в одном"
- Введение
- Основные разделы интеграции
- Объединение логики интеграции
- Функция Comment
- Тестирование функции комментариев
- Заключение
Введение
Наша сигнальная система неизменно демонстрировала исключительную эффективность на каждом этапе своего развития. Текущая цель — объединить существующие программы в единую унифицированную систему сигналов. Мы рассматривали интеграции двух предыдущих версий индикатора Trend Constraint в Части 5. Целью такого объединения является использование всей мощи программирования, что значительно снижает нагрузку на человека, позволяя компьютерам выполнять сложные, повторяющиеся задачи с невероятной скоростью.
Учитывая, что у нас есть две программы со схожей логикой, но разными функциями, процесс интеграции включает в себя больше, чем простое копирование и вставка исходного кода. Вместо этого мы стратегически сохраним определенные элементы, которые оказывают единообразное воздействие на обе программы, обеспечивая оптимальную функциональность. Этот процесс, который я называю слиянием, требует тщательного рассмотрения и точности.
В этой статье мы разберем разделы кода MQL5, где происходит интеграция, и обсудим ключевые строки, которые остаются глобальными на протяжении всего процесса слияния. Такой скрупулезный подход имеет решающее значение при объединении нескольких фрагментов кода для создания целостной и эффективной программы.
В подразделах Части 5 мы рассмотрели две основные интеграции:
- Интеграция Telegram с MetaTrader 5 для получения уведомлений.
- Интеграция WhatsApp с MetaTrader 5 для получения уведомлений.
Одна из проблем заключается в том, что наша интеграция выполняет задачи в командной строке, при этом окно скрыто, чтобы не мешать другим процессам на экране компьютера. В результате нет подтверждения того, были ли сигналы успешно отправлены в целевые платформы. Мы хотим, чтобы наша система комментировала в окне графика каждую успешную трансляцию сигнала или, по крайней мере, печатала ее в журнале платформы.
Давайте углубимся и обсудим дальнейшие идеи в следующих разделах этой статьи.
Наши основные разделы интеграции
Специально для этой статьи я выделил основные интересные моменты из кода. Для более подробного обсуждения, пожалуйста, вернитесь к Части 5. Ниже представлены программы, которые мы сравниваем, чтобы облегчить процесс слияния. Изучите их сходства и различия. Это поможет нам определить ключевые области, где требуется интеграция для бесперебойного и эффективного слияния.
- Интеграция 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); } } }
- Интеграция 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); } } }
Объединение логики интеграции
Чтобы создать единую программу, объединяющую WhatsApp и Telegram, с использованием двух предоставленных фрагментов кода, мы объединим логику каждого фрагмента в одну связную функцию. План следующий:
- Объединим глобальные переменные и объявления.
- Объединим функцию myAlert: Расширим функцию myAlert для обработки отправки сообщений в WhatsApp и Telegram.
- Настроим логику выполнения команд: Обеспечим выполнение обеих команд (WhatsApp и Telegram) в рамках одной и той же функции.
- Обеспечим соблюдение периода восстановления: Сохраним логику, которая гарантирует, что оповещения не будут отправляться слишком часто.
Для объединения объявлений и глобальных переменных оба фрагмента располагали объявлением ShellExecuteW и переменной периода восстановления, которые объединены в верхней части кода, чтобы избежать избыточности. Функция myAlert расширена и теперь включает логику для уведомлений WhatsApp и Telegram вместе с логикой, гарантирующей, что сообщения не будут отправляться слишком часто. Подводя итог, можно сказать, что для WhatsApp определяется путь к исполняемому файлу Python и скрипту WhatsApp, а также создается командная строка для выполнения скрипта отправки сообщений WhatsApp. Команда выполняется с помощью ShellExecuteW с проверкой результата для регистрации любых ошибок. Аналогично для Telegram определяется путь к исполняемому файлу Python и скрипту, а также создается командная строка для выполнения скрипта отправки сообщений Telegram. Команда выполняется с помощью ShellExecuteW с проверкой результата для регистрации любых ошибок.
Объединенная программа выглядит так:
//--- 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); } } }
Давайте разобьем код на разделы, чтобы объяснить его функциональные возможности:
#import "shell32.dll" int ShellExecuteW(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); #import
Этот раздел импортирует функцию ShellExecuteW из Windows-библиотеки shell32.dll. ShellExecuteW - это функция Windows API, которая выполняет операцию над указанным файлом. Импортируя эту функцию, код MQL5 может выполнять внешние команды или скрипты, такие как скрипты Python для отправки сообщений через WhatsApp и Telegram.
datetime last_alert_time; input int alert_cooldown_seconds = 60; // Cooldown period in seconds
Приведенный выше фрагмент кода создает глобальные переменные алгоритма интеграции.
- last_alert_time - глобальная переменная, в которой хранится метка времени последнего отправленного оповещения. Это помогает реализовать период ожидания между оповещениями.
- alert_cooldown_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.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); } } }
- Функция myAlert предназначена для отправки оповещений в зависимости от типа и сообщения. Она управляет периодом восстановления, создает оповещение и отправляет его в WhatsApp и Telegram с помощью внешних скриптов Python. Как видите, это самый большой раздел кода.
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;
- В этом разделе проверяется, меньше ли текущее время за вычетом времени последнего оповещения, чем период восстановления. Если да, оповещение не отправляется. Это предотвращает частые оповещения в течение короткого периода времени.
Чтобы убедиться, что наши скрипты работают, получаем следующие результаты в командной строке:
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
Выделенный текст — это положительный ответ командной строки, подтверждающий, что наши скрипты работают нормально. Очень важно правильно указать путь к файлу в основной программе.
С другой стороны, мы также получаем сигналы на наших социальных платформах. Ниже слева показано тестовое сообщение Telegram из командной строки, а справа — тестовое сообщение WhatsApp из командной строки. Теперь мы уверены, что наша программа работает нормально, и можем приступить к основной программе.
На иллюстрации выше показано соединение с песочницей, обеспечиваемое Twilio API, так как интеграция WhatsApp истекает в течение 72 часов. Необходимо повторно подключиться, отправив уникальное сообщение, чтобы повторно добавить его для получения сообщений API. В этом случае сообщение для повторного подключения будет "join so-cave". Чтобы получить бессрочную услугу, вы можете приобрести номер Twilio.
Давайте продолжим и объединим всё в одну программу, используя логику индикатора Trend Constraint. Рассмотрим индикатор 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); } //+------------------------------------------------------------------+
Мы обновили индикатор с V1.06 до V1.07. При компиляции мы не обнаружили никаких ошибок, и теперь наша программа работает на MetaTrader 5. Ниже приведены скриншоты тестовых сообщений, отправленных при запуске индикатора в MetaTrader 5: слева — Push-уведомления на мобильном устройстве на базе Android, в центре — тестовое уведомление Telegram, а справа — тестовое сообщение WhatsApp.
Функция Comment
Встроенная функция Comment в MQL5 используется для отображения пользовательских текстовых сообщений непосредственно на графике. Эта функция помогает нам обеспечивать визуальную обратную связь в режиме реального времени, отображая сообщения, которые могут постоянно обновляться во время выполнения индикатора или советника. Это необходимо для достижения следующих целей:
- Уведомление пользователя об успешном запуске индикатора.
- Подтверждение успешной отправки оповещений.
- Оповещение пользователя о сбоях в отправке оповещений.
Для внедрения этой функции мы сосредоточимся на трех областях кода:
int OnInit() { // Initialization code here Comment("Indicator successfully launched."); return INIT_SUCCEEDED; }
Цель приведенного выше фрагмента кода — уведомить нас об успешном запуске индикатора. При успешной инициализации индикатора функция Comment отображает сообщение Indicator successfully launched (индикатор успешно запущен) на графике.
if (result > 32) { Print("Successfully executed Python script. Result code: ", result); Comment("Success message sent: " + message); }
Мы получаем уведомление о том, что оповещение было успешно отправлено. После того как предупреждающее сообщение успешно отправлено с помощью функции myAlert, функция выводит сообщение Success message sent [message] (сообщение успешно отправлено) на графике, где [message] - содержание сообщения.
if (result <= 32) { int error_code = GetLastError(); Print("Failed to execute Python script. Error code: ", error_code); Comment("Failed to send message: " + message); }
Наконец, мы также хотим получать информацию о неудачной отправке. Этот фрагмент уведомляет нас о сбое в отправке оповещения. В этом случае отображается сообщение Failed to send message [message] (не удалось отправить сообщение) на графике, где [message] - содержание сообщения.
Чтобы использовать новые возможности, предоставляемые функцией Comment, я обновил программу до Trend Constraint V1.08. Стратегически интегрировав эту функцию в соответствующие разделы кода, мне удалось успешно обновить программу, обеспечив ее бесперебойную работу. Ниже вы найдете исходный код с выделенными измененными разделами, демонстрирующими внесенные улучшения.
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Тестирование функции комментариев
Реализация функции Comment в MQL5 — это простой способ повысить интерактивность и информативность торговых графиков. Интегрировав эту функцию, вы сможете предоставлять трейдерам важные обновления в режиме реального времени непосредственно на их графиках. Функция позволяет отображать динамические данные, такие как текущие цены, значения индикаторов и пользовательские сообщения, в понятной и краткой форме. В результате трейдеры могут принимать более обоснованные решения без необходимости переключения между несколькими окнами или внешними инструментами.
Простота и гибкость использования функции Comment делают ее бесценным инструментом для разработки более удобных и эффективных торговых алгоритмов. Благодаря добавлению контекстно-зависимой информации в режиме реального времени непосредственно в торговый интерфейс функция повышает ситуационную осведомленность и оптимизирует процесс торговли. Ниже показан успешный запуск Trend Constraint V1.07:
Заключение
В процессе разработки программного обеспечения инновации часто возникают в результате бесшовной интеграции существующих решений для создания более надежных и многофункциональных приложений. Мы рассмотрели процесс объединения двух программ в единое целое, демонстрирующий возможности объединения функций для повышения общей производительности и удобства использования.Мы начали с изучения основных функций двух отдельных программ, каждая из которых имеет свои уникальные сильные стороны. Тщательно проанализировав их кодовые базы и определив точки синергии, мы успешно объединили их в единую программу. Это слияние не только оптимизировало операции, но и сократило избыточность и потенциальные конфликты, проложив путь к более эффективному исполнению.
Включение функции Comment в MQL5-программе добавило новое измерение в наше комбинированное приложение. Используя надежную систему оповещений MQL5, мы реализовали функцию, которая позволяет отправлять уведомления в режиме реального времени по различным каналам, включая WhatsApp и Telegram. Это усовершенствование гарантирует, что пользователи всегда будут проинформированы о критических событиях, тем самым повышая скорость реагирования и принятия решений.
По мере нашего продвижения вперед потенциал для дальнейших улучшений остается огромным. Развивая существующие технологии и продуманно интегрируя новые функции, мы можем создавать мощные инструменты, которые повышают эффективность, улучшают взаимодействие с пользователями и в конечном итоге приводят к лучшим результатам.
Комментарии всегда приветствуются.
Вложение | Описание |
---|---|
Trend Constraint V1.07.mq5 | Интеграция двух платформ в одной программе. |
Trend Constraint V1.08.mq5 | Включение командной функции. |
Send_telegram_message.py | Скрипт для отправки сообщений в Telegram. |
send_whatsapp_message.py | Скрипт для отправки сообщений в WhatsApp. |
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/15143
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
можно проще и универсальнее. Общепринятая в большом мире практика - не изобретать велосипед, а использовать data-collector/router
например метрики и события через Socket() или WebRequest() отдавать в telegraf https://www.influxdata.com/time-series-platform/telegraf/
а он уже разрулит на всех(любых) получателей.
так и кода значительно меньше и работает стабильнее.
--
telegraf указан как пример, свободно всем доступный. Есть альтернативы как коммерческие так и открытые