Behebung von Barrierefreiheitsproblemen bei MQL5-Handelswerkzeugen (Teil II): Einen Expert Advisor per Pythons Text-to-Speech sprachfähig machen
Inhalt:
Einführung
In Spielfilmen haben wir schon gesehen, wie Roboter sprechen, und das wirkt ganz natürlich – die Sprache macht die Interaktion zwischen einem Menschen und seinem Roboterbegleiter intuitiv. Der Benutzer kann allein durch Zuhören leicht nachvollziehen, was die Maschine gerade tut. Heute wollen wir eine große Lücke zwischen einem Trader und seinem EA-Begleiter schließen. Die Unterstützung, die diese Systeme bisher bieten, ist unglaublich, wirkt aber oft etwas starr: ein Piepton, ein Pop-up-Fenster oder ein schriftlicher Protokolleintrag. Wenn wir über bestehende Grenzen hinausdenken wollen, müssen wir die Effizienz und Zugänglichkeit unserer derzeitigen und zukünftigen Systeme verbessern.
Barrierefreiheit bleibt bei vielen Trading-Tools eine Herausforderung, unabhängig davon, ob man sehbehindert ist oder nicht. Nicht jeder hat die Zeit, ständig die Protokolle oder das Journal zu öffnen, um nachzusehen, was der EA gerade tut oder getan hat. Manchmal ist es weitaus effizienter, wenn das System wichtige Ereignisse einfach ansagt. Es gibt zwar Lösungen, doch diese sind meist unflexibel – vorab aufgezeichnete WAV-Dateien, die sich nicht an veränderte Marktbedingungen anpassen lassen. Am 11. November 2020 veröffentlichte Alexander Fedosov einen Artikel über Sprachbenachrichtigungen in MQL5, der sehr ausführlich ist. Eine Herausforderung, die bei dieser Lösung jedoch weiterhin besteht, ist ihre Starrheit: Jeder Ton muss im Voraus vorbereitet werden, und der EA kann nichts sagen, was nicht zuvor aufgezeichnet wurde. Heute werden wir die TTS-Technologie nutzen, damit unser EA dynamisch über unterschiedliche Marktsituationen spricht, was uns deutlich mehr Flexibilität verschafft.
Fassen wir die wichtigsten Vorteile dieses Entwicklungsansatzes zusammen
- Sparen Sie Entwicklungszeit, indem Sie die TTS-Technologie nutzen, anstatt Audio-Ressourcen (WAV-Dateien) zu erstellen.
- Die starre Sprachausgabe reduzieren, um Warnmeldungen dynamisch und kontextbezogen zu gestalten.
- Der EA kann mithilfe von Sprachausgabe weitaus detailliertere Warnmeldungen ausgeben als nur eine einfache interne Warnmeldung.
- Ebnet den Weg für eine erweiterte Interaktion zwischen dem Nutzer und dem EA (z. B. Sprachbestätigung, gesprochene Zusammenfassungen).
Hier ist das Flussdiagramm, das die Funktionsweise und das Konzept hinter dieser Entwicklung veranschaulicht:

Abb. 1. Ablauf der Sprachausgabe
Das obige Diagramm veranschaulicht die elegante Einfachheit unseres Ansatzes. Der Expert Advisor, der in MetaTrader 5 läuft, fungiert als das Gehirn, das Marktereignisse erkennt – sei es ein Crossover, das Erreichen eines Take-Profit-Kurses oder eine Margin-Warnung. Anstatt eine statische WAV-Datei abzuspielen, erstellt es eine dynamische Textnachricht, die Echtzeitdaten wie den aktuellen Kurs, die Symbolnamen, die genaue Uhrzeit oder beliebige, weitere Variablen enthält. Diese Textnachricht wird dann über eine HTTP-POST-Anfrage (unter Verwendung der WebRequest-Funktion von MQL5) an einen lokalen Python-Server gesendet, der auf demselben Rechner läuft. Der Python-Server, der gewissermaßen als Stimme fungiert, empfängt den Text, verarbeitet ihn mithilfe einer Text-to-Speech-Engine und gibt ihn sofort über die Lautsprecher aus. Der gesamte Vorgang dauert nur wenige Millisekunden, doch das Ergebnis ist ein Handelsbegleiter, der Ihnen genau dann, wenn es darauf ankommt, alles, was Sie wissen müssen, in leicht verständlicher Sprache erklärt.
Was diese Architektur so leistungsfähig macht, ist die Trennung der Zuständigkeiten. Der EA konzentriert sich auf das, was er am besten kann – den Markt zu beobachten, Handelslogik auszuführen und aussagekräftige Signale zu generieren. Der Python-Server übernimmt die komplexe Aufgabe der Sprachsynthese, die weit über die nativen Fähigkeiten von MQL5 hinausgeht. Indem wir diese beiden Technologien über eine einfache HTTP-Schnittstelle miteinander verbinden, profitieren wir von den Vorteilen beider Welten: der engen Integration von MQL5 in das Handelsterminal und dem umfangreiche Ökosystem an Bibliotheken von Python, darunter leistungsstarke TTS-Engines. Zudem ist dieses Konzept vollständig lokal – es werden keinerlei Daten von Ihrem Computer übertragen, was Datenschutz und Sicherheit gewährleistet und gleichzeitig Verzögerungen verhindert.
Nachdem wir das Konzept nun verstanden haben, ist es an der Zeit, die Ärmel hochzukrempeln und es umzusetzen. Der folgende Abschnitt zur Umsetzung führt Sie Schritt für Schritt durch den gesamten Prozess: Zunächst richten Sie die Python-Umgebung ein und erstellen den TTS-Server; anschließend entwickeln Sie den MQL5 Expert Advisor mit einer wiederverwendbaren Speak()-Funktion; und schließlich aktivieren Sie WebRequest und konfigurieren MetaTrader 5 für die lokale HTTP-Kommunikation. Anschließend werden wir uns den vollständigen EA zum Crossover von gleitenden Durchschnitten ansehen, der alle Elemente vereint und über einen Testmodus zur sofortigen Überprüfung verfügt. Abschließend werden wir die Testergebnisse durchgehen, die Behebung häufiger Probleme besprechen und mit Ideen abschließen, wie man auf dieser Grundlage noch weiter vorankommen kann.
Ganz gleich, ob Sie ein erfahrener MQL5-Entwickler sind oder gerade erst anfangen – dieser Artikel stellt Ihnen ein leistungsstarkes neues Tool vor, mit dem Sie Ihre EAs kommunikativer, zugänglicher und intelligenter gestalten können. Beginnen wir.
Umsetzung
In diesem Abschnitt werden wir das gesamte System Schritt für Schritt aufbauen. Zunächst richten wir den Python-TTS-Server ein, der auf eingehende Nachrichten wartet. Anschließend entwickeln wir den MQL5-Expert Advisor, der die Funktion WebRequest nutzt, um diese Nachrichten zu versenden. Wir verwenden einen EA, da WebRequest nicht aus einem Indikator heraus aufgerufen werden kann. Der Beispiel-EA basiert auf einer einfachen Crossover-Strategie mit gleitenden Durchschnitten, um das Konzept zu veranschaulichen, aber Sie können die Funktion Speak() problemlos an jeden Ihrer bestehenden EAs anpassen.
Einrichten der Python-Umgebung
Sie benötigen Python (Version 3.7 oder höher). Öffnen Sie ein Terminal und installieren Sie die erforderlichen Bibliotheken:
pip install flask pyttsx3
Flask wird als unser schlanker Webserver dienen, und pyttsx3 bietet eine Offline-Text-to-Speech-Funktion unter Verwendung der auf Ihrem System installierten Stimmen.
Einrichten des TTS-Servers
Wir werden ein Python-Skript schreiben, das einen Flask-Server auf dem localhost, Port 5000, ausführt. Es akzeptiert POST-Anfragen mit einem JSON-Body, der den vorzusprechenden Text enthält. Da mehrere Nachrichten in schneller Folge eintreffen können (z. B. eine Begrüßungsnachricht, auf die unmittelbar eine Testnachricht folgt), müssen wir Probleme mit Threads vermeiden. Der Server nutzt eine Warteschlange und einen einzelnen Worker-Thread, um die Nachrichten nacheinander zu verarbeiten. Jede Nachricht erstellt eine neue Instanz der pyttsx3-Engine, um den Fehler run loop already started zu vermeiden, der frühere Versuche beeinträchtigt hat.
Der Python-TTS-Server
Der Server fungiert als Brücke zwischen unserem MQL5-Expert Advisor und der Windows-Text-to-Speech-Engine. Er lauscht auf HTTP-POST-Anfragen, nimmt eingehende Nachrichten entgegen, legt sie in eine Warteschlange und verarbeitet sie nacheinander mithilfe eines Hintergrund-Threads. Dieses Konzept stellt sicher, dass selbst wenn mehrere Benachrichtigungen kurz hintereinander eingehen, diese nacheinander angesagt werden, ohne dass es zu Überschneidungen oder Abstürzen kommt.
1. Erforderliche Module importieren
Zunächst importieren wir die erforderlichen Python-Bibliotheken. Flask ist ein schlankes Web-Framework zur Verarbeitung von HTTP-Anfragen. Queue stellt uns eine threadsichere FIFO-Warteschlange zur Verwaltung eingehender Nachrichten zur Verfügung. Durch die Verwendung von Threads können wir die Sprachsynthese in einem Hintergrund-Thread ausführen, sodass der Webserver niemals blockiert wird. Mit Subprocess werden PowerShell-Befehle ausgeführt, und shlex unterstützt die sichere Verarbeitung von Befehlszeilenargumenten (auch wenn dies hier nicht unbedingt erforderlich ist, wird es der Vollständigkeit halber erwähnt).
Python-Code
from flask import Flask, request, jsonify import queue import threading import subprocess import shlex
2. Initialisierung der Flask-Anwendung und der Nachrichtenwarteschlange
Wir erstellen die Flask-App-Instanz und eine globale message_queue. Diese Warteschlange enthält die Textzeichenfolgen, die vorgelesen werden sollen. Der Produzent (HTTP-Endpunkt) stellt Nachrichten in die Warteschlange ein, und der Konsument (Worker-Thread) entnimmt sie und verarbeitet sie. Dadurch werden die eingehenden Anfragen von der eigentlichen Sprachsynthese entkoppelt, wodurch Verzögerungen oder Blockierungen des Webservers verhindert werden.
Python-Code
app = Flask(__name__) message_queue = queue.Queue()
3. Die PowerShell-Sprachfunktion
Diese Funktion ist dafür zuständig, eine Textzeichenfolge mithilfe der in Windows integrierten Funktionen in hörbare Sprache umzuwandeln. Zunächst müssen wir alle doppelten Anführungszeichen im Text „escapen“, da der PowerShell-Befehl in einfache Anführungszeichen gesetzt wird. Der PowerShell-Befehl lädt die System.Speech-Assembly, erstellt ein SpeechSynthesizer-Objekt und ruft dessen Speak-Methode auf. Anschließend führen wir diesen Befehl im Hintergrund mit subprocess.run() aus und erfassen dabei die Ausgabe (die wir allerdings ignorieren). Durch die direkte Verwendung von PowerShell lassen sich die Threading-Probleme und die Instabilität vermeiden, auf die wir bei pyttsx3 gestoßen sind.
Python-Code
def powershell_speak(text): """Speak text using PowerShell's built-in speech synthesis.""" # Escape double quotes inside the text text = text.replace('"', '`"') # Build PowerShell command ps_command = f"Add-Type -AssemblyName System.Speech; $synth = New-Object System.Speech.Synthesis.SpeechSynthesizer; $synth.Speak('{text}')" # Run PowerShell silently subprocess.run(["powershell", "-Command", ps_command], capture_output=True)
4. Der Hintergrund-Worker-Thread
Der Worker-Thread führt eine Endlosschleife aus. Er wartet darauf, dass eine Nachricht in der Warteschlange erscheint (.get() blockiert, bis etwas verfügbar ist). Sobald eine Nachricht abgerufen wurde, wird eine Bestätigung auf der Konsole ausgegeben (zur Fehlersuche) und anschließend wird die Funktion powershell_speak() aufgerufen, um den Text tatsächlich vorzulesen. Sollte während der Sprachsynthese eine Ausnahme auftreten, wird diese abgefangen und ausgegeben, die Schleife läuft jedoch weiter. Schließlich signalisiert .task_done(), dass die Nachricht verarbeitet wurde, was nützlich ist, falls wir einmal darauf warten möchten, dass sich die Warteschlange leert.
Python-Code
def tts_worker(): while True: text = message_queue.get() print(f"Speaking: {text}") try: powershell_speak(text) except Exception as e: print(f"TTS error: {e}") message_queue.task_done()
5. Den Worker-Thread starten
Wir erstellen einen neuen Daemon-Thread, der die Funktion tts_worker ausführt. Das Flag daemon=True bedeutet, dass der Thread automatisch beendet wird, wenn das Hauptprogramm beendet wird. Das ist wichtig, weil wir so den Server mit Strg+C anhalten können, ohne dass verwaiste Threads zurückbleiben.
Python-Code
# Start worker thread threading.Thread(target=tts_worker, daemon=True).start()
6. Der HTTP-Endpunkt zum Empfangen von Nachrichten
Diese Flask-Route verarbeitet POST-Anfragen an den Pfad /speak. Wenn eine Anfrage eingeht, extrahiert das Programm die JSON-Daten und prüft, ob ein Textfeld vorhanden ist. Fehlt das Feld, wird ein 400-Fehler zurückgegeben. Andernfalls wird der Text in die Nachrichtenwarteschlange gestellt und sofort eine Erfolgsmeldung zurückgegeben ({"status": "ok"}). Da die eigentliche Sprachausgabe im Hintergrund-Thread erfolgt, arbeitet der Endpunkt sehr schnell und hält den EA nicht auf.
Python-Code
@app.route('/speak', methods=['POST']) def handle_speak(): data = request.get_json() if not data or 'text' not in data: return jsonify({'error': 'Missing text'}), 400 text = data['text'] message_queue.put(text) return jsonify({'status': 'ok'})
7. Den Server laufen lassen
Zum Schluss starten wir den Flask-Entwicklungsserver. Wir binden den Server an 127.0.0.1 (localhost) auf Port 5000. Die Option threaded=False stellt sicher, dass Flask selbst keine zusätzlichen Threads erstellt, wodurch unser Threading-Modell einfach und vorhersehbar bleibt. Dieser Server ist ausschließlich für den lokalen Gebrauch vorgesehen, daher ist der Entwicklungsserver völlig ausreichend.
Python-Code
if __name__ == '__main__': app.run(host='127.0.0.1', port=5000, threaded=False)
Vorbereitung auf der EA-Seite
Im MetaEditor erstellen wir einen neuen Expert Advisor. Die Kernfunktion ist Speak(), die eine JSON-Nutzlast erstellt und diese über WebRequest versendet. Wir müssen sicherstellen, dass die URL http://127.0.0.1:5000/speak zur Liste der zugelassenen URLs im MetaTrader 5-Terminal hinzugefügt wird (Extras → Optionen → Expert Advisors → WebRequest für aufgeführte URLs zulassen).

Abb. 2. Einrichten der Serververbindung
Entwicklung des Crossover-EA mit Testmodus
Um das System sofort zu demonstrieren, haben wir einen Eingabeparameter „TestMode“ hinzugefügt. Wenn dieser Modus aktiviert ist, gibt der EA bei jeder neuen Bar, die das aktuelle Symbol enthält, eine Testmeldung mit den Geld- und Briefkursen sowie der Serverzeit aus. Dies belegt, dass der EA auf Live-Daten zugreifen kann und dass die TTS-Pipeline funktioniert, ohne auf ein Crossover-Signal warten zu müssen. Die Crossover-Logik selbst nutzt zwei gleitende Durchschnitte und einen ATR-Wert als Kontext; wenn ein Crossover auftritt, gibt der EA eine detaillierte Meldung aus, die die Signalrichtung, den Kurs und den ATR-Wert enthält.
Der Expert Advisor (EA) setzt eine klassische Crossover-Strategie mit gleitenden Durchschnitten um und bietet zusätzlich die Möglichkeit, dynamische Nachrichten über einen lokalen Python-TTS-Server vorzulesen. Er umfasst einen Testmodus zur sofortigen Überprüfung, optionalen Handel sowie eine robuste Fehlerbehandlung für WebRequest. Der Code ist übersichtlich strukturiert und lässt sich leicht an Ihre eigenen Strategien anpassen.
1. EA-Kopfzeile und Metadaten
Der EA beginnt mit den üblichen MQL5-Metadaten: Copyright, Link, Version und einer kurzen Beschreibung. Diese Informationen werden im Navigator angezeigt und erscheinen, sobald der EA an ein Chart angehängt ist. In der Beschreibung wird ausdrücklich darauf hingewiesen, dass dieser EA sprachfähig ist und über einen Testmodus verfügt.
//+------------------------------------------------------------------+ //| MA_Crossover_TTS_EA.mq5 | //| Copyright 2025, Clemence Benjamin | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Clemence Benjamin" #property link "https://www.mql5.com" #property version "1.10" #property description "Voice‑enabled MA Crossover EA with Test Mode"
2. Die Eingabeparameter
Alle vom Benutzer konfigurierbaren Optionen werden als Eingabeparameter bereitgestellt. Die erste Gruppe definiert die Handelslogik: schnelle und langsame MA-Perioden, eine ATR-Periode als Kontext sowie die Berechnungsmethode. Die zweite Gruppe regelt Sprachansagen und das Handelsverhalten: Aktivierung der Sprachausgabe, Aktivierung des eigentlichen Handels, Losgröße und eine eindeutige Magic Number. Schließlich ermöglicht der TestMode dem EA, bei jedem neuen Bar eine Testmeldung auszugeben – was für eine sofortige Überprüfung von unschätzbarem Wert ist, ohne auf einen Crossover warten zu müssen.
// --- Input Parameters --- input int FastMAPeriod = 9; // Fast MA Period input int SlowMAPeriod = 21; // Slow MA Period input int ATRPeriod = 14; // ATR Period input ENUM_MA_METHOD MaMethod = MODE_EMA; // MA Method input ENUM_APPLIED_PRICE PriceType = PRICE_CLOSE; // Price type input bool EnableVoiceAlerts = true; // Enable spoken alerts input bool EnableTrading = false; // Set true to actually place trades input double LotSize = 0.01; // Only used if trading enabled input int MagicNumber = 20250225; // Unique EA identifier input bool TestMode = false; // If true, speak test info on every new bar
3. Globale Variablen
Globale Variablen dienen dazu, Indikator-Handles zu speichern und den Status von Bars und Signalen über mehrere Ticks hinweg zu verfolgen. fastMA_handle, slowMA_handle und atr_handle enthalten die Handles für die technischen Indikatoren. lastBarTime speichert den Eröffnungszeitpunkt der zuletzt verarbeiteten Bar, wodurch wir neue Bars erkennen können. lastSignalBar verhindert, dass der EA doppelte Signale für dieselbe Bar ausgibt.
// --- Global Variables --- int fastMA_handle, slowMA_handle, atr_handle; datetime lastBarTime = 0; // For new bar detection ulong lastSignalBar = 0; // Prevent repeated signals on same bar
4. Initialisierung – OnInit()
In der Funktion OnInit() erstellen wir die Indikator-Handles für den schnellen MA, den langsamen MA und den ATR. Sollte die Erstellung eines Handles fehlschlagen, gibt der EA den Wert INIT_FAILED zurück und gibt eine Fehlermeldung aus. Wenn Sprachausgaben aktiviert sind, senden wir umgehend eine Willkommensnachricht an den TTS-Server, um zu bestätigen, dass die Pipeline von Anfang an funktioniert.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Create indicator handles fastMA_handle = iMA(_Symbol, _Period, FastMAPeriod, 0, MaMethod, PriceType); slowMA_handle = iMA(_Symbol, _Period, SlowMAPeriod, 0, MaMethod, PriceType); atr_handle = iATR(_Symbol, _Period, ATRPeriod); if(fastMA_handle == INVALID_HANDLE || slowMA_handle == INVALID_HANDLE || atr_handle == INVALID_HANDLE) { Print("Failed to create indicator handles"); return INIT_FAILED; } // Welcome message (optional) if(EnableVoiceAlerts) Speak("Moving average crossover expert advisor started on " + _Symbol); return INIT_SUCCEEDED; }
5. OnDeinit()
Wenn der EA aus dem Chart entfernt wird, müssen wir alle Indikator-Handles freigeben, um Systemressourcen freizugeben. Dies geschieht in OnDeinit() mithilfe von IndicatorRelease() für jedes Handle. Dies ist eine bewährte Vorgehensweise, um Speicherlecks zu vermeiden.
//+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Release handles if(fastMA_handle != INVALID_HANDLE) IndicatorRelease(fastMA_handle); if(slowMA_handle != INVALID_HANDLE) IndicatorRelease(slowMA_handle); if(atr_handle != INVALID_HANDLE) IndicatorRelease(atr_handle); }
6. Erkennen der neuen Bar und Testmodus
Die Funktion OnTick() wird bei jedem Tick aufgerufen. Zunächst muss festgestellt werden, ob sich eine neue Bar gebildet hat. Dazu vergleichen wir die Eröffnungszeit der aktuellen Bar (iTime(_Symbol, _Period, 0)) mit der zuvor gespeicherten lastBarTime. Sind sie identisch, beenden wir den Vorgang sofort – dadurch wird die Verarbeitung auf einmal pro Bar beschränkt, was effizient ist und übermäßige WebRequest-Aufrufe verhindert.
Wird eine neue Bar erkannt, aktualisieren wir lastBarTime, und sofern der Testmodus und die Sprachausgaben aktiviert sind, rufen wir SpeakTestInfo() auf, um das aktuelle Symbol, den Geld- und Briefkurs sowie die Serverzeit anzusagen. Dadurch erhält man sofort eine Rückmeldung, dass der EA aktiv ist und die TTS-Verbindung funktioniert.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // --- New bar detection --- datetime currentBarTime = iTime(_Symbol, _Period, 0); if(currentBarTime == lastBarTime) return; // Same bar, nothing to do lastBarTime = currentBarTime; // --- Test Mode: speak current info on every new bar --- if(TestMode && EnableVoiceAlerts) SpeakTestInfo(); // ... (crossover detection continues) ... }
7. Abrufen von Indikatorwerten zur Crossover-Erkennung
Nach der Verarbeitung der neuen Bar rufen wir die Werte für den schnellen MA, den langsamen MA und den ATR für die vorherige Bar (Index 1) und die vorherige Bar (Index 2) ab. Wir legen die Arrays als Zeitreihe fest, sodass der Index 0 den aktuellsten Daten entspricht. Wir kopieren zwei Werte für die gleitenden Durchschnitte und einen für den ATR. Sollte ein CopyBuffer-Aufruf fehlschlagen, brechen wir den Vorgang vorzeitig ab. Außerdem rufen wir den Schlusskurs der aktuellen (neu eröffneten) Bar ab, um ihn in der Sprachansage zu verwenden.
// --- Fetch indicator values for the previous (just closed) bar and the bar before that --- double fast[], slow[], atr[]; ArraySetAsSeries(fast, true); ArraySetAsSeries(slow, true); ArraySetAsSeries(atr, true); if(CopyBuffer(fastMA_handle, 0, 1, 2, fast) < 2) return; if(CopyBuffer(slowMA_handle, 0, 1, 2, slow) < 2) return; if(CopyBuffer(atr_handle, 0, 1, 1, atr) < 1) return; double currentClose = iClose(_Symbol, _Period, 0); // price of the newly opened bar
8. Erkennung von Überkreuzungen und Signalverarbeitung
Wir vergleichen die Werte des schnellen und des langsamen gleitenden Durchschnitts, um einen Crossover zu erkennen. Wenn der schnelle gleitende Durchschnitt den langsamen gleitenden Durchschnitt nach oben kreuzt (lag zuvor unterhalb der vorherigen Bar und befindet sich nun darüber), setzen wir das Signal auf KAUF. Wenn er nach unten durchbricht, setzen wir das Signal auf VERKAUF. Wird ein Signal erkannt, stellen wir zunächst mithilfe von lastSignalBar sicher, dass es sich nicht um ein Duplikat derselben Bar handelt.
Wenn ein gültiges Signal auftritt, erstellen wir eine detaillierte Sprachansage, die die Signalrichtung, das Symbol, den Kurs und den ATR-Wert enthält. Diese Nachricht wird über die Funktion Speak() an den TTS-Server gesendet. Wenn der Handel aktiviert ist, rufen wir außerdem PlaceTrade() auf, um eine Marktorder auszuführen. Dieser modulare Ansatz sorgt dafür, dass der Code übersichtlich und leicht zu warten bleibt.
// --- Crossover detection --- string signal = ""; if(fast[1] < slow[1] && fast[0] > slow[0]) signal = "BUY"; else if(fast[1] > slow[1] && fast[0] < slow[0]) signal = "SELL"; if(signal != "") { // Avoid duplicate signals on same bar if(lastSignalBar == currentBarTime) return; lastSignalBar = currentBarTime; // --- Voice Alert --- if(EnableVoiceAlerts) { string message = StringFormat( "%s signal on %s at price %.*f. ATR is %.*f.", signal, _Symbol, _Digits, currentClose, _Digits, atr[0] ); Speak(message); } // --- Trading (optional) --- if(EnableTrading) { PlaceTrade(signal); } } }
9. Informationen zum Testmodus – SpeakTestInfo()
Diese Hilfsfunktion wird aufgerufen, wenn der Testmodus aktiviert ist. Es ruft die aktuellen Geld- und Briefkurse mithilfe von SymbolInfoDouble() ab, ermittelt die aktuelle Serverzeit mit TimeCurrent(), formatiert die Zeit als lesbare Zeichenkette und erstellt eine Testnachricht. Die Nachricht wird dann über Speak() an den TTS-Server gesendet. Diese Funktion belegt, dass der EA auf Live-Marktdaten zugreifen und diese in Sprache umwandeln kann.
//+------------------------------------------------------------------+ //| Speak test information (symbol, price, time) | //+------------------------------------------------------------------+ void SpeakTestInfo() { double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); datetime now = TimeCurrent(); string timeStr = TimeToString(now, TIME_DATE|TIME_MINUTES|TIME_SECONDS); string message = StringFormat( "Test on %s: Bid %.*f, Ask %.*f at %s", _Symbol, _Digits, bid, _Digits, ask, timeStr ); Speak(message); }
10. Kernfunktion für Sprache – Speak()
Die Funktion Speak() ist das Herzstück der Sprachintegration. Sie erstellt eine JSON-Nutzlast, die den Nachrichtentext enthält, ersetzt alle doppelten Anführungszeichen (um die Gültigkeit des JSON zu gewährleisten) und sendet mithilfe von WebRequest() eine HTTP-POST-Anfrage an den lokalen TTS-Server.
Wir haben eine Zeitüberschreitung von 3 Sekunden festgelegt – ausreichend Zeit für eine lokale Verbindung. Wenn WebRequest den Wert -1 zurückgibt, erfassen wir den Fehlercode mit GetLastError() und geben ihn aus. Häufige Fehler sind 4060 (URL in den MetaTrader 5-Einstellungen nicht zulässig) und 4062 (Verbindung abgelehnt, Server läuft nicht). Indem bei einem Fehler der Wert false zurückgegeben wird, kann der aufrufende Code entscheiden, wie mit dem Fehler umgegangen werden soll. Diese Funktion kann direkt in jeden anderen EA kopiert werden, um eine Sprachfunktion hinzuzufügen.
//+------------------------------------------------------------------+ //| Send text to TTS server via WebRequest | //+------------------------------------------------------------------+ bool Speak(string message) { // The TTS server must be running: python tts_server.py string url = "http://127.0.0.1:5000/speak"; string headers = "Content-Type: application/json\r\n"; // Escape double quotes in message (if any) StringReplace(message, "\"", "\\\""); // Build JSON payload string data = "{\"text\":\"" + message + "\"}"; char post_data[]; char result_data[]; string result_headers; ArrayResize(post_data, StringToCharArray(data, post_data, 0, WHOLE_ARRAY) - 1); int timeout = 3000; // 3 seconds int res = WebRequest("POST", url, headers, timeout, post_data, result_data, result_headers); if(res == -1) { int err = GetLastError(); Print("WebRequest error: ", err, " - Message: ", message); // Common errors: // 4060 - URL not allowed in MT5 options // 4062 - Connection refused (server not running) return false; } return true; }
11. Optionaler Handel – PlaceTrade()
Wenn der Nutzer den Handel aktiviert, führt diese Funktion eine Marktorder aus. Es füllt eine MqlTradeRequest-Struktur mit den erforderlichen Angaben: Aktion, Symbol, Volumen, Magic Number und Abweichung. Der Preis richtet sich nach dem aktuellen Briefkurs bei einer Kauforder bzw. dem Geldkurs bei einer Verkaufsorder.
Nachdem wir die Order mit OrderSend() gesendet haben, überprüfen wir das Ergebnis. Wenn der Befehl fehlschlägt, geben wir den Rückgabecode aus und sprechen, sofern Sprachausgaben aktiviert sind, eine Fehlermeldung aus. Wenn die Order erfolgreich ausgeführt wird, geben wir eine Bestätigung aus, die die Orderart und den Ausführungskurs enthält. Dies zeigt, wie dasselbe Sprachsystem für Meldungen nach dem Handel genutzt werden kann.
//+------------------------------------------------------------------+ //| Place a market order (optional) | //+------------------------------------------------------------------+ void PlaceTrade(string signal) { MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = LotSize; request.magic = MagicNumber; request.deviation = 10; if(signal == "BUY") { request.type = ORDER_TYPE_BUY; request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); } else if(signal == "SELL") { request.type = ORDER_TYPE_SELL; request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID); } else return; if(!OrderSend(request, result)) { Print("OrderSend failed: ", result.retcode); if(EnableVoiceAlerts) Speak("Trade failed, check terminal."); } else { if(EnableVoiceAlerts) { string msg = StringFormat( "%s order placed at %.*f", signal, _Digits, request.price ); Speak(msg); } } } //+------------------------------------------------------------------+
WebRequest aktivieren und ausführen
Bevor Sie den EA an ein Chart anhängen, starten Sie den Python-Server in einem Terminal: python tts_server.py. Stellen Sie anschließend in MetaTrader 5 sicher, dass die URL zugelassen ist. Fügen Sie den EA mit den Einstellungen TestMode=true und EnableVoiceAlerts=true in ein beliebiges Chart ein (z. B. EURUSD M1). Sie sollten jede Minute eine Testmeldung hören (nur zum schnellen Testen; deaktivieren Sie diese Funktion, um zu vermeiden, dass bei jeder Bar ein Alarm ausgelöst wird). Sollte es zu einem Crossover kommen, werden Sie auch diese Sprachmeldung hören.
Tests
Video-Demonstration: Die drei Fenster zeigen den Python-TTS-Server (Eingabeaufforderung), das MetaTrader 5-Terminal mit dem EA auf XAUUSDmicro sowie den MetaEditor während der Neukompilierung. Bei der Initialisierung spricht der EA eine Testnachricht mit dynamischen Geld- und Briefkursen sowie der Serverzeit aus und belegt damit, dass die TTS-Pipeline sofort funktioniert. Das Video demonstriert den EA außerdem anhand eines synthetischen Boom-900-Index, bei dem er dieselben dynamischen Informationen einwandfrei ansagt – was die Kompatibilität mit jedem Handelsinstrument bestätigt. Trotz der für Crossover-Signale typischen Wartezeit vermittelt der EA mehrere Funktionen effizient: Er meldet das Auftreten von gleitenden Durchschnitts-Crossovers in Echtzeit, führt Trades aus, sofern diese Funktion aktiviert ist, und gibt in Echtzeit gesprochene Rückmeldungen zur Marktlage.
Wir haben das System ausgiebig auf einem Demokonto mit XAUUSDmicro auf einem 1-Minuten-Chart getestet. Die anfängliche Version, die basiert auf pyttsx3 und einer gemeinsam genutzten Engine basierte, schlug nach der zweiten Nachricht mit der Fehlermeldung „run loop already started“ fehl. Der Wechsel zu einem warteschlangenbasierten Worker, der pro Nachricht eine neue Engine erstellt, hat die Abstürze behoben, doch nach einigen Nachrichten brach die Sprachausgabe ab – nur die Konsole zeigte an, dass weiterhin Nachrichten empfangen wurden. Dies deutete auf ein grundlegendes Problem mit der pyttsx3-Engine unter Windows hin.
Die finale robuste Implementierung verwendet jedoch PowerShell für die integrierte Sprachsynthese. Der Python-Server führt nun für jede Nachricht einen kurzen PowerShell-Befehl aus, der System.Speech.Synthesis.SpeechSynthesizer aufruft. Dieser Ansatz ist absolut zuverlässig: Jede Nachricht wird deutlich und nacheinander wiedergegeben, ohne Abstürze und ohne Stummschaltung. Das Serverprotokoll zeigt, dass jede Anfrage verarbeitet wird, und der Lautsprecher gibt jede Testnachricht und jeden Crossover-Alarm einwandfrei wieder.
Außerdem haben wir überprüft, ob die WebRequest-Fehlercodes korrekt gemeldet werden. Wenn der Server nicht läuft, gibt MetaTrader 5 den Fehler 4062 zurück (Verbindung abgelehnt). Wenn die URL nicht zulässig ist, wird der Fehler 4060 angezeigt. Beides lässt sich leicht diagnostizieren und beheben.
Der Testmodus erwies sich als unschätzbar wertvoll für sofortiges Feedback – schon wenige Sekunden nach dem Anbringen des EAs hörten wir: „Test on XAUUSDmicro: Bid … Ask … at …,“ was bestätigte, dass der Datenabruf, die JSON-Formatierung und die TTS-Pipeline alle einwandfrei funktionierten. Nach einigen Minuten kam es zu einem echten Crossover, und der EA meldete: „BUY signal on XAUUSDmicro at price … ATR is….“ Das gesamte System funktionierte über mehrere Instrumente hinweg einwandfrei, darunter auch synthetische Indizes wie der Boom-900-Index, was zeigt, dass dieser sprachfähige Ansatz universell auf jedes Handelspaar anwendbar ist.
Schlussfolgerung
Wir haben erfolgreich ein sprachunterstütztes Handelssystem entwickelt, bei dem wir Python, MQL5 und Text-to-Speech-Technologie zum Einsatz gebracht haben. Der EA kann nun mithilfe eines lokalen Python-TTS-Servers alle dynamischen Informationen – Preise, Signale, Kontostatus – in Echtzeit ansagen. Die wichtigsten Erfolge sind:
- Vorab aufgenommene Sounddateien werden überflüssig – der EA kann alles sagen;
- die Überwindung von Threading-Problemen mit einem queuebasierten Worker und schließlich die Einführung einer absolut zuverlässigen PowerShell-Lösung;
- Bereitstellung einer wiederverwendbaren Speak()-Funktion, die in jeden MQL5-EA integriert werden kann; und
- Demonstration des Konzepts anhand eines voll funktionsfähigen EAs mit gleitendem Durchschnitt, der seine Signale ankündigt und zudem bei jeder Bar Testinformationen ansagen kann.
- Bleiben Sie auf dem Laufenden, ohne auf den Bildschirm zu starren – alle wichtigen Informationen werden akustisch übermittelt, sodass Sie nicht ständig vor dem Terminal sitzen müssen und dennoch über die Marktentwicklungen auf dem Laufenden bleiben.
- Echte Barrierefreiheit ermöglichen – voll audiofähig nutzbare Lösungen für sehbehinderte Trader können nun Marktinformationen in Echtzeit über gesprochene Benachrichtigungen erfassen, was ihnen den Weg zu unabhängigem Handel ebnet.
- Meistern Sie das Multitasking – Ihre Ohren werden zu einem zusätzlichen Informationskanal. Ganz gleich, ob Sie Charts analysieren, Nachrichten lesen oder gerade nicht an Ihrem Schreibtisch sitzen – der EA hält Sie per Sprachausgabe auf dem Laufenden.
- Machen Sie Schluss mit starren Audiobeschränkungen – kein Suchen oder Aufnehmen von WAV-Dateien mehr. Ihr EA kann jeden Preis, zu jeder Zeit und jede Variable angeben – sofort und dynamisch.
Mit Blick auf die Zukunft eröffnet diese Grundlage zahlreiche Möglichkeiten. Wir können den Python-Server so erweitern, dass er weitere Parameter (Stimmenauswahl, Sprechgeschwindigkeit, Lautstärke) akzeptiert oder Audio an entfernte Geräte streamt. Wir können den EA mit MCP-Servern integrieren, um Sprachbefehle in beide Richtungen zu ermöglichen – der Trader spricht mit dem EA, und der EA antwortet ihm. Die gleiche Technik lässt sich nutzen, um gesprochene Zusammenfassungen der täglichen Leistung oder Risikowarnungen zu erstellen oder sogar Schlagzeilen vorzulesen.
Was kommt als Nächstes? Wir haben eine Einwegkommunikation realisiert – der EA spricht zu Ihnen. Der nächste Schritt ist die bidirektionale Sprachinteraktion, bei der Sie mit Ihrem EA sprechen können und dieser Ihre Befehle versteht und ausführt. Stellen Sie sich vor, Sie sagen „Close all losing positions“ (alle Verlustpositionen schließen) oder „Increase lot size to 0.5“ (Lotgröße auf 0,5 erhöhen) und Ihr EA reagiert sofort darauf. Das ist keine Science-Fiction – es ist die natürliche Weiterentwicklung der zugänglichen Handelstechnologie.
Verpassen Sie nicht den nächsten Artikel dieser Reihe, in dem wir weitere Geheimnisse der Barrierefreiheit mithilfe von Spracherkennung und TTS-Technologien lüften werden. Die Zukunft des Handels ist sprachfähig, und Sie haben gerade den ersten Schritt getan.
Ich hoffe, dieser Artikel inspiriert Sie dazu, Ihre eigenen EAs zugänglicher und interaktiver zu gestalten. Der vollständige Quellcode ist unten aufgeführt, und wir empfehlen Ihnen, ihn an Ihre eigenen Handelsstrategien anzupassen. Viel Spaß beim Programmieren, und mögen Ihre EAs weise sprechen!
| Quelldateiname | Typ | Version | Beschreibung |
|---|---|---|---|
| tts_server.py | Python-Server-Skript | 1 | Ein auf Flask basierender TTS-Server, der Text über HTTP empfängt und mithilfe der in PowerShell integrierten Sprachsynthese vorliest. |
| MA_Crossover_TTS_EA.mq5 | Expert Advisor | 1.10 | sprachfähige MA-Crossover-EA mit Testmodus; sendet dynamische Benachrichtigungen (Signale, Kurse, Zeit) an den TTS-Server. |
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/21387
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
Larry Williams’ Marktgeheimnisse (Teil 12): Kontextbezogener Handel von „Smash Day“-Umkehrungen
Erstellen benutzerdefinierter Indikatoren in MQL5 (Teil 7): Hybride Time-Price-Opportunity-(TPO)-Marktprofile für die Analyse von Handelssitzungen
Erstellen benutzerdefinierter Indikatoren in MQL5 (Teil 8): Integration von Volumendaten für eine tiefere Marktprofilanalyse
Neurostrukturelle Trading-Engine – NSTE (Teil I): Aufbau eines prop-firm-tauglichen Multi-Account-Systems
- 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.