![Aufbau des Kerzenmodells Trend-Constraint (Teil 5): Nachrichtensystem (Teil II)](https://c.mql5.com/2/82/Building_A_Candlestick_Trend_Constraint_Model_Part_5_Next-7iSmtcwWt-transformed_600x314.jpg)
Aufbau des Kerzenmodells Trend-Constraint (Teil 5): Nachrichtensystem (Teil II)
Inhalt
- Einführung
- Integration von Telegram in Trend Constraint
- Die Telegram BOT API verstehen
- Installation der Telegram-Python-Module unter Windows
- Das Python-Skript send_telegram_messages verstehen
- Konfigurieren des Trend Constraint Indicator für Telegramm
- Endgültiger Code
- Fehlerbehandlung
- Ergebnisse der Tests
- Schlussfolgerung
Einführung
Im vorigen Artikel haben wir den Integrationsprozess kurz vorgestellt. Durch die Aufteilung in Unterabschnitte wollten wir das Verständnis des Prozesses Schritt für Schritt vereinfachen. Eine solide Grundlage ist von entscheidender Bedeutung, und wir hoffen, dass die von uns gelegte Basis solide ist, wenn wir uns eingehender damit befassen, dass diese Integrationen nahtlos funktionieren, insbesondere innerhalb unseres Trend Constraint-Modells. Letztendlich ist es unser Ziel, bis zum Abschluss des Projekts Benachrichtigungen sowohl auf Telegram als auch auf WhatsApp bequem zu empfangen. So können wir sicherstellen, dass wir über Indikatoren auf dem Laufenden bleiben und keine Signale verpassen, während wir uns gleichzeitig mit Freunden und Familie in den sozialen Medien austauschen. Die Weitergabe von Signalen direkt auf der sozialen Plattform wird mühelos sein, sodass man nicht mehr zwischen den Anwendungen wechseln muss.
Ziel dieses Artikels ist es, uns umfassend durch die einzelnen Schritte zu führen, bis wir die gewünschten Ergebnisse erzielen. Mit dem im vorangegangenen Artikel erworbenen Grundwissen ist nun alles klar. Ich werde jede einzelne Codezeile des integrierten Programms erläutern. Es gibt vier Schlüsselkomponenten in diesem Projekt, die im Zusammenhang mit der Telegrammintegration stehen und die konsequent beachtet werden müssen.
- Telegram Bot API.
- Python-Skript.
- Dedizierter Server für das Hosting des Skripts bei der Bearbeitung von Webanfragen.
- Unser Indikatorprogramm ist für Telegramm konfiguriert.
Dies ist ein grundlegender Überblick über die am Hauptintegrationsprozess beteiligten Komponenten. Ich habe zwar speziell Telegram und WhatsApp erwähnt, aber es sei darauf hingewiesen, dass auch andere Social-Media-Plattformen integriert werden können, sofern eine Programmiersprache zur Verfügung steht, die diesen Prozess erleichtert. Da wir die Bedeutung der Sprachkompatibilität bei der Programmierung erkannt haben, haben wir Python und MQL5 in ein einziges Projekt integriert. Dies unterstreicht den Vorteil, mit verschiedenen Sprachen wie Python, C++, ONNX und C# vertraut zu sein. Dieses Wissen kann MQL5-Programmierern bei der Entwicklung von Funktionalitäten innerhalb der Plattform und der Integration mit anderen sozialen APIs sehr helfen.
Die praktische Integration von Telegram wird uns zum dritten Unterabschnitt von Teil 5 der Artikelserie führen, in dem WhatsApp weiter integriert wird, wobei eine ähnliche Struktur wie bei Telegram verfolgt wird, aber eine Nachrichten-API anstelle der Bot-API verwendet wird. Auf der Grundlage des von uns geschaffenen Fundaments wird diese Aufgabe leichter sein, da wir nun die Grundsätze im Kopf haben.
Integration von Telegram in Trend Constraint
Fahren wir mit unserem bedeutenden Projekt fort: An diesem Punkt machen wir praktisch dort weiter, wo wir aufgehört haben. Nach meinen Recherchen gibt es mehrere Methoden, um dies zu erreichen, solange die Codelogik verstanden wird. Ich habe mich jedoch für eine Methode entschieden, die die Verwendung eines Python-Skripts und der Funktion ShellExecuteW beinhaltet, um die Interaktion zwischen einem MetaTrader 5-Indikator und dem Telegram-Telebot zu erleichtern. Ich werde auf diese Aspekte noch näher eingehen. Dieser Ansatz hat den Vorteil, dass er für diejenigen, die mit Python und MQL5 vertraut sind, relativ einfach zu handhaben ist. Es sind keine umfangreichen Änderungen am MQL5-Indikator erforderlich. Der einzige Nachteil ist, dass es externe Abhängigkeiten wie Python-Skripte und Bibliotheken benötigt.
Ziel ist es, die Zugänglichkeit von MetaTrader 5-Signalen auf Telegram für ein breiteres Publikum zu verbessern und das einfache Teilen und Weiterleiten durch die Implementierung von Telebots zu erleichtern.
In einem früheren Artikel (Teil I) habe ich die Integrationsmethode besprochen, die die Funktion WebRequest verwendet. Bei der Überprüfung der MQL5-Dokumentation wurde jedoch festgestellt, dass diese Methode nicht ideal für die Integration von Indikatoren ist, aber gut mit Robotern funktioniert.
Bei der Verwendung von Shell-DLL-Dateien ist Vorsicht geboten, da sie bei der Verwendung mit nicht vertrauenswürdigen Anwendungen ernsthafte Risiken bergen können. Es ist von entscheidender Bedeutung, dass Sie die Funktionsweise dieser Systeme auf Ihrem Computer vollständig verstehen und ihnen vertrauen, um Angriffe und Hackerangriffe zu verhindern.
Die Telegram BOT API verstehen
Ich gehe davon aus, dass Sie bereits ein aktiver Telegram-Nutzer sind. Das Projekt erfordert mehr Personalisierung und Privatsphäre, einschließlich Details, die ich für mich behalten werde. Folgen Sie den Anweisungen, um Ihren Telegram-Bot mit einem einzigartigen Namen zu erstellen, wie ich es mit @Botfather getan habe. Ich habe den Bot Trend Constraint genannt, mit dem Nutzernamen @trend_constraint_bot. Sie können Ihren eigenen Bot auf ähnliche Weise mit einem eindeutigen Namen erstellen. Hier ist eine kurze Übersicht, wie Sie mit Botfather beginnen können. Folgen Sie den Anweisungen von Botfather, um den Vorgang abzuschließen. Danach erhalten Sie ein Bot-Token für den Zugriff auf die Bot-API. Danach können Sie eine Unterhaltung mit dem Bot beginnen, ihn zu einer Gruppe oder einem Kanal hinzufügen, um mit dem Chat zu beginnen. Jeder Chat hat eine eindeutige ID, die der Bot zur Interaktion mit einem bestimmten Nutzer verwendet. Dieser Chat wird auch verwendet, um Signale vom MetaTrader 5 Indikator an einen Telegram-Nutzer weiterzuleiten.
Nachdem ich alles eingestellt hatte, besuchte ich die Bot-API mit dem Chrome-Browser. Erinnern Sie sich an das Bot-Token, das Sie vom BotFather erhalten haben, und verwenden Sie den Link zu API https://api.telegram.org/bot<Ihr Bot-Token>/getUpdates. Ersetzen Sie das hervorgehobene Text durch Ihren Bot-Token, damit es funktioniert.
Typisches Beispiel hier: https://api.telegram.org/bot9004946256:shTUYuq52f8CHLt8BLdYGHYJi2QM6H3donA/getUpdates
Anmerkung: Das hervorgehobene API-Token wurde zu Schulungszwecken zufällig generiert. Bitte verwenden Sie die von @BotFather bereitgestellte Version für Ihren Roboter. Stellen Sie sicher, dass Sie einen Chat mit dem Bot führen, damit die API anzeigt, was wir wollen. Aktualisieren Sie auch die Registerkarte des API-Browsers, damit neue Chat-Aktualisierungen angezeigt werden können. Aktivieren Sie das Kontrollkästchen Pretty-Print auf der API-Browser-Registerkarte, um ein übersichtliches Layout zu erhalten.
Die API wird einen JSON-Code für die laufende Kommunikation mit dem Bot anzeigen. Definieren wir zunächst JSON (JavaScript Object Notation) als ein einfaches Datenaustauschformat, das für Menschen leicht zu lesen und zu schreiben und für Maschinen leicht zu parsen und zu generieren ist. Es wird häufig für die Übertragung von Daten in Webanwendungen (z. B. zwischen einem Server und einem Client) und für die Konfiguration von Anwendungen und Datenspeichern verwendet. Es ist durch Objekte und Arrays strukturiert.
Nachfolgend sehen Sie ein API JSON, das nach dem Senden einer „Hey“-Nachricht an den Bot angezeigt wurde:
{ "ok": true, "result": [ { "update_id": 464310132, "message": { "message_id": 12, "from": { "id": 7049213628, "is_bot": false, "first_name": "Clemence", "last_name": "Benjamin", "username": "benjc_trade_advisor", "language_code": "en" }, "chat": { "id": 7049213628, "first_name": "Clemence", "last_name": "Benjamin", "username": "benjc_trade_advisor", "type": "private" }, "date": 1719044625, "text": "hey" }
Hier finden Sie eine ausführliche Erläuterung des JSON-Codes:
Top-Level-Struktur:
- OK: Dies ist ein boolescher Wert, der den Erfolg der API-Anfrage angibt. In diesem Fall ist sie wahr, was bedeutet, dass die Anfrage erfolgreich war.
- result: Dies ist ein Array, das ein oder mehrere Update-Objekte enthält. In diesem Beispiel gibt es ein Update-Objekt.
Jedes Element im Ergebnisfeld stellt eine Aktualisierung dar. Hier haben wir eine einzige Aktualisierung:
- update_id: Dies ist ein eindeutiger Bezeichner für die Aktualisierung. Es hilft, den Überblick über die Aktualisierungen zu behalten und sicherzustellen, dass keine verpasst oder mehrfach verarbeitet werden. In diesem Fall lautet die update_id
- 464310132.
Das Nachrichten-Objekt
Dieses Objekt enthält Informationen über die Nachricht, die die Aktualisierung ausgelöst hat:
- message_id: Dies ist ein eindeutiger Bezeichner für die Nachricht innerhalb des Chats. Hier sind es 12.
- from: Dieses Objekt enthält Informationen über den Absender der Nachricht:
- id: Der eindeutige Bezeichner für den Nutzer, der die Nachricht gesendet hat. Hier ist er 7049213628.
- is_bot: Dieser boolesche Wert zeigt an, ob der Absender ein Bot ist. In diesem Fall ist sie falsch, was bedeutet, dass der Absender ein Mensch ist.
- first_name: Den Vornamen des Absenders, also Clemence.
- last_name: Der Nachname des Absenders, d.h. Benjamin.
- language_code: Der Sprachcode, der die Spracheinstellungen des Absenders angibt. Hier ist er en für Englisch.
- chat: Dieses Objekt enthält Informationen über den Chat, in dem die Nachricht gesendet wurde.
- id: Der eindeutige Bezeichner für den Chat. Da es sich um einen privaten Chat handelt, entspricht er der ID des Nutzers ( 7049213628 ).
- first_name: Den Vornamen des Chat-Teilnehmers, also Clemence.
- last_name: Der Nachname des Chat-Teilnehmers, d.h. Benjamin.
- type: Die Art des Chats. Hier ist er privat, d. h. es handelt sich um einen persönlichen Chat zwischen dem Nutzer und dem Bot.
- date: Das Datum und die Uhrzeit, zu der die Nachricht gesendet wurde, dargestellt als Unix-Zeitstempel (Sekunden seit dem 1. Januar 1970). In diesem Fall lautet der Zeitstempel 1719044625.
- text: Der eigentliche Textinhalt der Nachricht, nämlich „hey“.
Ich habe beschlossen, den Chat-Abschnitt des JSON beiseite zu legen, damit wir uns auf den wichtigsten Teil konzentrieren können, nämlich die Chat-ID, die wir in unserem Indikatorprogramm benötigen. Sehen Sie sich den JSON-Ausschnitt unten an:
"chat": { "id": 7049213628, "first_name": "Clemence", "last_name": "Benjamin", "username": "benjc_trade_advisor", "type": "private" }
Das Objekt „chat“ enthält detaillierte Informationen über den Chat, in dem die Nachricht gesendet wurde, einschließlich der eindeutigen Kennung des Chats, des Vor- und Nachnamens der Teilnehmer und der Art des Chats. In diesem Fall handelt es sich um einen privaten Chat mit einem Nutzer namens Clemence Benjamin. Schauen wir uns eine detaillierte Erklärung des Objekts „chat“ an:
id:
- Beschreibung: Dies ist der eindeutige Bezeichner für den Chat.
- Wert: 7049213628
- Bedeutung: Im Rahmen privater Chats entspricht diese ID in der Regel der Nutzer-ID des Chat-Teilnehmers.
first_name:
- Beschreibung: Der Vorname des Teilnehmers im Chat.
- Wert: Clemence
- Bedeutung: Dies hilft, den Nutzer anhand seines Vornamens im Chat zu identifizieren.
last_name:
- Beschreibung: Der Nachname des Teilnehmers im Chat.
- Wert: Benjamin
- Bedeutung: Dies ergänzt den Vornamen, um den Nutzer im Chat vollständig zu identifizieren.
„username“
- Beschreibung: Das ist der Schlüssel,
- Wert: „benjc_trade_advisor“
- Bedeutung: Diese Zeile gibt an, dass der mit dem Objekt (z. B. einem Nutzer, Bot oder Chat) verbundene Nutzername „benjc_trade_advisor“ lautet. Dieser Nutzername wird normalerweise verwendet, um die Entität in einem erkennbaren Format innerhalb von Anwendungen oder Systemen zu identifizieren, die die JSON-Daten verwenden.
type:
- Beschreibung: Die Art des Chats.
- Wert: privat
- Bedeutung: Zeigt an, dass es sich bei diesem Chat um ein persönliches Gespräch zwischen dem Nutzer und dem Bot handelt (im Gegensatz zu einem Gruppenchat oder einem Kanal).
Zusammenfassung:
Ziel des oben genannten Abschnitts war es, einen funktionierenden Telegram-Bot zu entwickeln und das Bot-Token und die Chat-ID zu erwerben, beides entscheidende Elemente für das Hauptprojekt. Wir haben uns in die API vertieft, um ein besseres Verständnis der einzelnen Komponenten zu erlangen. Wenn wir das Bot-Token und die Chat-ID haben, können wir mit dem Integrationsprozess fortfahren, bei dem wir auch verschiedene Programmiersprachen erkunden werden.
Installation der Telegram-Python-Module unter Windows
Wir müssen Python auf Ihrem Computer installiert haben. Vergewissern Sie sich, dass Ihr Computer über einen Internetzugang verfügt. Sie können es von Python.org herunterladen. Ich habe diese Anleitung praktisch auf einem Windows-Computer erstellt. Auf Mac, Linux und anderen Frameworks kann es anders aussehen. Wenn die Python-Installation abgeschlossen ist, ist der nächste Schritt die Installation der Python-Telegram-API-Module, damit die Python-Skripte für Telegram gut laufen. Öffnen Sie die cmd.exe (Eingabeaufforderung) und führen Sie den unten stehenden Codeausschnitt aus. Kopieren Sie den Code und fügen Sie ihn in die Windows-Eingabeaufforderung ein. Drücken Sie die Eingabetaste auf der Tastatur, damit der Code heruntergeladen wird, und warten Sie kurz, bis die Installation des Moduls abgeschlossen ist.
pip install pyTelegramBotAPI
Nachfolgend sehen Sie einen Ausschnitt der Eingabeaufforderung als Screenshot.
Wenn Sie fertig sind, können Sie das Fenster schließen und den Computer neu starten.
Nach Abschluss dieses Schritts ist Ihr Computer nun gut vorbereitet, um die Python-Skripte für die Interaktion mit der Telegram Bot API auszuführen. In der folgenden Phase werden wir den Code genau untersuchen, um unser System für die Aufgabe einzurichten.
Das Python-Skript send_telegram_messages verstehen
Schauen wir uns den Aufbau des Skripts an. Und dann werde ich den endgültigen Code in einem Schnipsel wiedergeben. Die Datei sollte den Namen send_telegram_message.py tragen
Das Skript beginnt mit dem Import der erforderlichen Module wie folgt:
- import telebot: Importiert das Telebot-Modul, das die Funktionen bereitstellt, die für die Interaktion mit der Telegram Bot API benötigt werden.
- import sys: Importiert das Modul sys, das es dem Skript ermöglicht, Befehlszeilenargumente zu verwenden.
import telebot import sys
Wir fahren fort mit der Deklaration des API_TOKEN und der Chat-ID:
- API_TOKEN: Diese Variable speichert das API-Token des Bots, das zur Authentifizierung des Bots bei den Telegram-Servern verwendet wird.
- CHAT_ID: Ein eindeutiger Wert für die Identität jedes Chats entweder zwischen dem Nutzer und dem Telebot oder zwischen dem Kanal und den Gruppen.
API_TOKEN = '9004946256:shTUYuq52f8CHLt8BLdYGHYJi2QM6H3donA' #Replace the API TOKEN with your bot tokrn from @BotFather CHAT_ID = '7049213628' #Replace the ID with your actual Chat ID from the telebot API
Wir müssen das Objekt TeleBot mit dem bereitgestellten API-Token initialisieren, um die Interaktion mit der Telegram Bot API zu ermöglichen.
bot = telebot.TeleBot(API_TOKEN)
Der nächste Python-Codeausschnitt definiert eine Funktion zum Senden einer Nachricht über Telegram, als Fehlerbehandlung von Ausnahmen im Zusammenhang mit der API und dem System.
def send_telegram_message(message): try: bot.send_message(CHAT_ID, message) print("Message sent successfully!") except telebot.apihelper.ApiTelegramException as e: print(f"Failed to send message: {e}") except Exception as e: print(f"An error occurred: {e}")
Der letzte Teil des Codes ist eine Bedingung, die sicherstellt, dass dieser Codeblock nur ausgeführt wird, wenn das Skript direkt ausgeführt wird, nicht wenn es als Modul importiert wird. Es ruft die Nachricht aus den Befehlszeilenargumenten ab oder setzt eine Standardnachricht, wenn keine Argumente angegeben werden.
if __name__ == "__main__": message = sys.argv[1] if len(sys.argv) > 1 else "Test message" send_telegram_message(message)
Zusammengefasst haben wir unseren endgültigen Code, speichern Sie die Datei als send_telegram_message.py und in Ihrem Python-Skripte-Ordner. Ich habe festgestellt, dass der Zugriff auf den Skriptordner gut funktioniert.
import telebot import sys API_TOKEN = '9004946256:shTUYuq52f8CHLt8BLdYGHYJi2QM6H3donA'#Replace with your API_TOKEN given by BotFather CHAT_ID = '7049213628' #Replace with your CHAT_ID bot = telebot.TeleBot(API_TOKEN) def send_telegram_message(message): try: bot.send_message(CHAT_ID, message) print("Message sent successfully!") except telebot.apihelper.ApiTelegramException as e: print(f"Failed to send message: {e}") except Exception as e: print(f"An error occurred: {e}") if __name__ == "__main__": message = sys.argv[1] if len(sys.argv) > 1 else "Test message" send_telegram_message(message)
Der nächste wichtige Schritt ist die Einrichtung des MQL5-Indikators zum Aufruf des Python-Skripts.
Konfigurieren des Trend Constraint Indicator für Telegramm
Hier müssen wir die Funktion myAlert im MQL5-Indikator ändern, um das Python-Skript mit der Funktion ShellExecuteW aufzurufen. Diese Funktion führt das Python-Skript aus und übergibt die Warnmeldung als Argument.
Hier ist, wie wir es in Trend Constraint ändern, habe ich die beiden Code-Schnipsel vor der Änderung und nach der Änderung enthalten:
Vor der Modifizierung:
void myAlert(string type, string message) { if(type == "print") Print(message); else if(type == "error") { Print(type+" | Trend Constraint V1.05 @ "+Symbol()+","+IntegerToString(Period())+" | "+message); } else if(type == "order") { } else if(type == "modify") { } else if(type == "indicator") { if(Audible_Alerts) Alert(type+" | Trend Constraint V1.05 @ "+Symbol()+","+IntegerToString(Period())+" | "+message); if(Push_Notifications) SendNotification(type+" | Trend Constraint V1.05 @ "+Symbol()+","+IntegerToString(Period())+" | "+message); } }
Nach der Änderung:
//--- ShellExecuteW declaration ---------------------------------------------- #import "shell32.dll" int ShellExecuteW(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); #import datetime last_alert_time; input int alert_cooldown_seconds = 60; // Cooldown period in seconds, this helps to avoid instant continuous alerting depending on indicator conditions //Modify the myAlert Function for telegram notification 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.04 @ " + Symbol() + "," + IntegerToString(Period()) + " | " + message; if (type == "print") { Print(message); } else if (type == "error") { Print(type + " | Trend Constraint V1.04 @ " + 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\\Pro_tech\\AppData\\Local\\Programs\\Python\\Python312\\python.exe"; string script_path = "C:\\Users\\Pro_tech\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\send_telegram_message.py"; string command = python_path + " \"" + script_path + "\" \"" + full_message + "\""; 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); } } } //--- End of Telegram Integration functions ---------------------------------------
Ich werde kurz erklären, was die Änderung bewirkt.
Zunächst müssen wir die Funktion ShellExecuteW aus der Windows-Bibliothek shell32.dll importieren, damit das MQL5-Programm externe Befehle ausführen kann, in diesem Fall das Skript send_telegram_message.py. Ohne die Deklaration der Funktion ShellExecuteW wird das Programm nicht funktionieren. Wir haben auch die Abklingzeit eingeführt, um die ständige sofortige Ausführung von cmd.exe aufgrund einiger falsch konfigurierter Indikatorbedingungen zu verhindern. In meinem Fall gab es, wie im vorherigen Artikel erwähnt, eine Alarmbedingung in Puffer 5 und 6 des Trend Constraints V1.04, die mehrere Signalwarnungen in kurzer Zeit verursachte. Das Ergebnis war noch schlimmer, als ich die Telegram-Funktion integrierte, die cmd.exe wurde mehrmals auf einmal gestartet und der Computer fror ein. Um dies zu vermeiden, durfte ich den Indikator nur ohne myAlert() zeichnen lassen. Mit anderen Worten: Ich habe ihn stummgeschaltet, indem ich sie in Kommentare umgewandelt habe, denn Kommentare werden im Programm bekanntlich nicht ausgeführt.
//--- ShellExecuteW declaration ---------------------------------------------- #import "shell32.dll" int ShellExecuteW(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); #import
Der andere entscheidende Teil des Codes ist:
// Send to Telegram string python_path = "C:\\Users\\Pro_tech\\AppData\\Local\\Programs\\Python\\Python312\\python.exe"; string script_path = "C:\\Users\\Pro_tech\\AppData\\Local\\Programs\\Python\\Python312\\Scripts\\send_telegram_message.py"; string command = python_path + " \"" + script_path + "\" \"" + full_message + "\"";
Der obige Code konstruiert einen Befehl zur Ausführung eines Python-Skripts aus einem MetaTrader 5-Indikatorprogramm heraus, wobei die Pfade zum Python-Interpreter und zum Skript sowie die zu sendende Nachricht angegeben werden. Den hervorgehobenen Text müssen Sie je nach Computer durch einen eigenen Text für den Pfad ersetzen. Dies habe ich als Beispiel von meinem Computer aus gegeben.
Endgültiger Code
Nachdem wir alles erklärt und erfolgreich integriert haben, haben wir nun eine neue Funktion und wir aktualisieren auf Trend Constraint V1.05
//+------------------------------------------------------------------+ //| Trend Constraint V1.05.mq5 | //| Copyright 2024, Clemence Benjamin | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Clemence Benjamin" #property link "https://www.mql5.com" #property version "1.05" #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 //--- 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 //Remember to replace the storages path with your actual path. string python_path = "C:\\Users\\Pro_tech\\AppData\\Local\\Programs\\Python\\Python312\\python.exe"; string script_path = "C:\\Users\\Pro_tech\\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); } } } //+------------------------------------------------------------------+ //| 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)); //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); } //+------------------------------------------------------------------+
Fehlerbehandlung
Failed to send message: A request to the Telegram API was unsuccessful. Error code: 401. Description: Unauthorized
Meinen Tests zufolge wurde der obige Fehlercode durch einen dysfunktionalen API_TOKEN verursacht, wie der, den wir zuvor als Beispiel verwendet haben. Sie müssen einen funktionierenden API_TOKEN-Wert verwenden. Die meisten der Fehler löschte ich, um zu einem sauberen Arbeitscode für diesen Leitfaden zu kommen, Sie könnten jedoch Fehler beim Bearbeiten oder Ändern Ihres Codes machen, daher müssen Sie sorgfältig jeden Schritt kontrollieren, den Sie machen.
Ergebnisse der Tests
Nachdem ich den Indikator zum Chart hinzugefügt hatte, aktivierte ich die Option DLL zulassen, damit unser Indikator Skripte über die Eingabeaufforderung ausführen kann. Das animierte Bild zeigt, wie der Indikator hinzugefügt wird und wie er im Chart erscheint.
Sie können testen, ob das Skript funktioniert, indem Sie die Datei in ihrem Pfad über die Eingabeaufforderung ausführen (siehe Abbildung unten). Geben Sie bei geöffneter Eingabeaufforderung in den Ordner mit Ihrem Skript python send_telegram_message.py ein. Eine erfolgreich gesendete Nachricht und die Antwort zeigen, dass das Skript funktioniert und die Testnachricht wird ebenfalls an den Chat weitergeleitet.
Das Ergebnisbild unten zeigt den Beginn einer Konversation mit dem Bot, die es uns ermöglicht hat, die Chat-ID in der Bot-API zu erhalten. Es zeigt auch das eingehende Signal, das der Bot von Trend Constraint V1.05 sendet. Die Signale kamen sofort an, da sie in der MetaTrader 5 Plattform generiert wurden.
Schlussfolgerung
Wir haben Telegramm erfolgreich in unser Modell integriert. Trend Constraint V1.05 wurde erheblich weiterentwickelt und ist nun in der Lage, Signale intern und extern weiterzuleiten, wovon Händler weltweit mit Telegram-Zugang profitieren. Die Signalübertragung erfolgt schnell und ohne Verzögerungen aufgrund der effizienten Ausführung des Algorithmus. Das System ist auf einen bestimmten Indikator innerhalb der Plattform ausgerichtet, sodass andere Funktionen nicht beeinträchtigt werden. Die Signale werden sicher und direkt an eine bestimmte ID übertragen. Diese Systeme können für einen kontinuierlichen Betrieb auf einem Virtual Private Server gehostet werden und bieten den Nutzern eine stabile Signalversorgung. Bei solchen Projekten können während der Entwicklung Fehler auftreten, aber ich freue mich, dass ich sie erfolgreich beheben konnte.
Ich hoffe, dieses Projekt hat Sie in irgendeiner Weise inspiriert. Wenn Sie an einem Projekt arbeiten und bei dieser Art der Integration auf Probleme gestoßen sind, können Sie uns Ihre Gedanken im untenstehenden Diskussionsbereich mitteilen. Im Anhang finden Sie die Quelldateien, die Sie für Ihre Projekte abändern und mit Hilfe der Kommentare, die zu Lehrzwecken bereitgestellt werden, einige Ideen erkunden können. Als Nächstes planen wir die Integration einer weiteren beliebten sozialen Plattform, WhatsApp.
Anhänge | Beschreibung |
---|---|
send_telegram_message.py | Das Skript, mit dem der Indikator Benachrichtigungen an Telegram weitergibt, enthält API_Token und Chat ID |
Trend Constraint V1.05.mq5 | Der Quellcode des Hauptprogramms des MQL5-Indikators |
Telebot_API.txt | Telegram Bot API Struktur |
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/14968
![Erstellung von Zeitreihenvorhersagen mit neuronalen LSTM-Netzen: Normalisierung des Preises und Tokenisierung der Zeit](https://c.mql5.com/2/82/Creating_Time_Series_Predictions_using_LSTM_Neural_Networks___LOGO.png)
![Datenwissenschaft und maschinelles Lernen (Teil 24): Zeitreihenprognose im Forex mit regulären AI-Modellen](https://c.mql5.com/2/81/Data_Science_and_Machine_Learning_Part_24__LOGO.png)
![Entwicklung einer Zone Recovery Martingale Strategie in MQL5](https://c.mql5.com/2/82/Developing_Zone_Recovery_Martingale_strategy_in_MQL5__LOGO.png)
![Integrieren Sie Ihr eigenes LLM in EA (Teil 4): Trainieren Sie Ihr eigenes LLM mit GPU](https://c.mql5.com/2/82/Integrate_Your_Own_LLM_into_EA_Part_4____LOGO.png)
![MQL5 - Sprache von Handelsstrategien, eingebaut ins Kundenterminal MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.