
Ein System von Sprachbenachrichtigungen für Ereignisse und Signale im Handel
Inhaltsverzeichnis
- Einführung
- Entwicklung eines Sprachbenachrichtigungssystems
- Praktische Anwendung bei Indikatoren
- Praktische Anwendung im Handel durch Expert Advisor
- Praktische Anwendung in Quick Trading Tools
- Schlussfolgerung
Einführung
Das Handelsterminal MetaTrader 5 verfügt über Optionen, die die Verwendung von akustischen Hinweisen ermöglichen. Das System umfasst 11 Ereignisse, denen separate akustische Hinweise zugeordnet werden können. Es gibt jedoch noch viel mehr Situationen, in denen der Nutzer einen akustischen Hinweis erhalten muss, wie z.B. das Auftauchen eines Handelssystemsignals oder Aktionen des Experten-Beraters, einschließlich der Eröffnung, Schließung oder Änderung einer Position. Heutzutage spielen Sprachassistenten eine herausragende Rolle im menschlichen Leben, da wir häufig Navigatoren, Sprachsuche und Übersetzer einsetzen. Diese Idee könnte beim Handel im MetaTrader 5 Terminal eingesetzt werden. In diesem Artikel werde ich versuchen, ein einfaches und nutzerfreundliches System von Sprachbenachrichtigungen für verschiedene Handelsereignisse, Marktzustände oder durch Handelssignale erzeugte Signale zu entwickeln.
Entwicklung eines Sprachbenachrichtigungssystems
Bevor wir mit der Schaffung des Systems beginnen, möchte ich eine Anmerkung hinzufügen. Die Ereignisse, die ich für die Implementierung von Sprachbenachrichtigungen ausgewählt habe, dienen lediglich der Demonstration des Systems. Sollte dieser Satz nicht ausreichen, können Sie Ihre eigenen Ereignisse und die entsprechenden Sprachbenachrichtigungen hinzufügen. Nachdem Sie den Artikel gelesen haben, wird die Erweiterung und Anpassung des Systems sehr einfach sein, auch wenn Sie keine umfangreichen MQL5-Kenntnisse haben.
Dieses System ist als Klasse CSoundsLib in einer einzubindenden Datei implementiert. Öffnen Sie also den Ordner MQL5/Include und erstellen Sie einen Ordner mit dem Titel SoundsLib, in dem Sie die Datei SoundsLib.mqh anlegen sollten. Bevor wir die Klasse erstellen, möchten wir Ihnen zwei Enumerationen vorstellen, die weiterhin für die Arbeit mit Sprachhinweise verwendet werden sollen. Die erste ist LANGUAGE, die für die Sprachauswahl der Hinweise verwendet wird. Das System wird zwei Sprachen unterstützen: Englisch und Russisch.
//+------------------------------------------------------------------+ //| Enumeration for switching the notification language | //+------------------------------------------------------------------+ enum LANGUAGE { RUSSIAN, // Russian ENGLISH // English };
Die zweite Enumeration enthält die Reihe von Ereignissen, die ich zu Demonstrationszwecken ausgewählt habe. Im weiteren Verlauf des Artikels werde ich zeigen, wie sie in verschiedene vorgefertigte Systeme eingebettet werden können, darunter Indikatoren, Expert Advisor und dem Schnellhandels-Toolkits. Die Enumeration heißt MESSAGE:
//+------------------------------------------------------------------+ //| List of voice alerts | //+------------------------------------------------------------------+ enum MESSAGE { STATUS_ON, // Status of enabled voice alerts SIGNAL_BUY, // A Buy signal SIGNAL_SELL, // A Sell signal BUY_ORDER_SET, // A Buy order has been placed SELL_ORDER_SET, // A Sell order has been placed BUYLIMIT_ORDER_SET, // A Limit Buy order has been placed BUYSTOP_ORDER_SET, // A Stop Buy order has been placed SELLLIMIT_ORDER_SET, // A Limit Sell order has been placed SELLSTOP_ORDER_SET, // A Stop Sell order has been placed BUYLIMIT_ORDER_DELETE, // A Limit Buy order has been deleted BUYSTOP_ORDER_DELETE, // A Stop Buy order has been deleted SELLLIMIT_ORDER_DELETE, // A Limit Sell order has been deleted SELLSTOP_ORDER_DELETE, // A Stop Sell order has been deleted BUY_ORDER_CLOSE_PROFIT, // A Buy order has closed with a profit BUY_ORDER_CLOSE_LOSS, // A Buy order has closed with a loss SELL_ORDER_CLOSE_PROFIT, // A Sell order has closed with a profit SELL_ORDER_CLOSE_LOSS, // A Sell order has closed with a loss BUY_ORDER_CLOSE_TP, // A Buy order has been closed by Take Profit BUY_ORDER_CLOSE_SL, // A Buy order has been closed by Stop Loss SELL_ORDER_CLOSE_TP, // A Sell order has been closed by Take Profit SELL_ORDER_CLOSE_SL, // A Sell order has been closed by Stop Loss MARKET_CLOSE, // Market is closed AUTO_TRADING_ON, // Automated trading is allowed AUTO_TRADING_OFF, // Automated trading is prohibited };
Der Basissatz enthält 24 Hinweise. Die meisten von ihnen beziehen sich auf den Betrieb und den Status von offenen Positionen und Pending-Orders. Einige Hinweise werden für Benachrichtigungen im Handelsumfeld verwendet. Die letzten drei Benachrichtigungen beziehen sich auf häufige Ereignisse. Benachrichtigungen über den Status des aktivierten Sprachalarmsystems sowie Benachrichtigungen über das Auftauchen von Kauf- oder Verkaufssignalen sind praktisch, wenn man mit manuellen oder halbautomatischen Handelsexpertenberatern arbeitet oder wenn man Indikatoren verwendet, einschließlich einfacher und als Teil einer Handelsstrategie verfügbarer Indikatoren.
Nun wollen wir die Klasse CSoundsLib erstellen und die für die Arbeit erforderlichen Methoden hinzufügen.
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CSoundsLib { private: LANGUAGE m_language; bool m_activity_status; public: CSoundsLib(void); ~CSoundsLib(void); //--- Set the notification language void Language(LANGUAGE lang); //--- Set/get the status of the voice alerts system void IsActive(bool flag); bool IsActive(void); //--- Play the specified notification bool Message(MESSAGE msg); };
Der 'private' Teil verfügt über zwei Hinweise, m_language und m_activity_status, die für die folgenden Methoden Language() und IsActive() erforderlich sind. Sie werden also verwendet, um die Sprache der Sprachhinweise einzustellen und den Systemaktivitätsstatus zu erhalten/einzustellen. Hier ist die Implementierung der obigen Hinweise:
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CSoundsLib::Language(LANGUAGE lang) { m_language=lang; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CSoundsLib::IsActive(void) { return(m_activity_status); }
Eine andere Methode ist Message(). Sie spielt eine aus der Enumeration MESSAGE ausgewählte Benachrichtigung ab. Die Implementierung dieser Methode ist ebenfalls leicht verständlich:
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CSoundsLib::Message(MESSAGE msg) { if(!m_activity_status) return(false); string name=(m_language==RUSSIAN ? EnumToString(msg)+"_RU" : EnumToString(msg)+"_EN"); if(PlaySound("\\Files\\SoundsLib\\"+name+".wav")) return(true); else { if(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian") Print("Файл не найден"); else Print("File not found"); return(false); } }
Bitte beachten Sie die folgenden wichtigen Punkte — sie helfen Ihnen, das System durch Hinzufügen eigener Sprachbenachrichtigungen korrekt weiter auszubauen. Der erste Punkt ist der richtige Speicherort für Audiodateien: Standardmäßig befinden sie sich im Ordner MQL5/Files/SoundsLib. Sie sollten den Ordner SoundsLib erstellen. Stellen Sie zweitens sicher, dass Sie Eigennamen und Audiodateiformate in dem erstellten Ordner festlegen. Achten Sie auf diese Code-Zeilen: das Suffix _RU oder _EN wird hier an die Enumeration vom Typ MESSAGE angehängt. Aus diesem Grund bezieht sich der Dateiname, der zum Beispiel einem Kaufsignal Hinweise SIGNAL_BUY entspricht, auf zwei Audiodateien, SIGNAL_BUY _RU und SIGNAL_BUY_EN, für russische und englische Hinweise. Vergessen Sie auch nicht, dass die Systemfunktion PlaySound() nur eine Datei im *.WAV-Format abspielen kann, und daher werden die vollständigen Dateinamen mit Erweiterungen im Ordner SoundsLib wie folgt aussehen:
Abb.1 Vollständiger Name und Erweiterung der Audiodatei.
Daher haben wir 48 Audiodateien für unsere 24 Ereignisse in der Enumeration MESSAGE: zwei Dateien in verschiedenen Sprachen für jedes Ereignis. Als Nächstes werde ich meine eigene Methode zur Erstellung von Sprachhinweisen zeigen. Sie können jedoch jede bevorzugte Methode verwenden. Für diesen Artikel habe ich einen kostenlosen Dienst zur Umwandlung von Text in Sprache verwendet.
Abb.2 Dienst zur Umwandlung von Text in Sprache.
Dieser Dienst bietet eine gute Funktionalität zur Umsetzung der geforderten Aufgabe. Er ermöglicht sowohl die Auswahl der Sprache als auch der Typen mit dem gewünschten Format. Das WAV-Format wird jedoch für die englische Sprache nicht unterstützt. Hier können wir jeden Online-Konverter oder jede andere Software verwenden, um mp3 in wav zu konvertieren. Ich habe alle erforderlichen Dateien für das System vorbereitet und im Ordner MQL5\Files\SoundsLib mit dem richtigen Format und Namen entsprechend der Enumeration MESSAGE und den Sprachsuffixen gespeichert. Hier ist meine Ergebnisliste:
Abb.3 Vollständige Liste der Audiodateien für Sprachhinweise.
Unten finden Sie eine Schritt-für-Schritt-Anleitung, wie Sie Ihre eigenen Sprachbenachrichtigungen erstellen können.
Schritt 1. Fügen Sie Ihr Sprachereignis in das System ein.
Öffnen Sie die Datei SoundsLib.mqh und suchen Sie die Enumeration MESSAGE. Fügen Sie Ihr Ereignis mit einem aussagekräftigen Namen hinzu. Beispiel der Benennung sind in Abbildung 3 und im obigen Code dargestellt.
Schritt 2. Erstellen Sie eine Audiodatei für die Hinweise.
Gehen Sie zu dem Dienst (Sie können jeden beliebigen Dienst nutzen), konfigurieren Sie die erforderlichen Parameter (siehe Abbildung 2) und speichern Sie die Datei im WAV-Format unter MQL5\Files\SoundsLib mit dem Namen "Ihr Ereignisname in der Enumeration MESSAGE "+_RU(_EN) je nach Sprache. Wenn alle Schritte korrekt abgeschlossen sind, wird die neue Sounddatei mit dem neuen Ereignis verknüpft, das in Schritt 1 hinzugefügt wurde, und ist somit einsatzbereit.
Praktische Anwendung bei Indikatoren
Nun wollen wir anhand verschiedener Beispiele sehen, wie es funktioniert. Lassen Sie uns einen zusammengesetzten Indikator erstellen, der auf zwei Indikatorsignalen basiert, die in der nachstehenden Tabelle beschrieben sind:
Parameter | Beschreibung |
---|---|
Verwendeter Indikator | ADXCloud |
Verwendeter Indikator | ColorZerolagRVI |
Wahl des Zeitrahmens | Beide |
Kaufbedingungen | Die Fläche von ADXCloud ist grün, die Fläche von ColorZerolagRVI verändert sich von rot nach grün. |
Verkaufsbedingungen | Die Fläche von ADXCloud ist rot, die Fläche von ColorZerolagRVI verändert sich von grün nach rot. |
Die Beispiele für eine Eröffnung, die auf den Indikatorsignalen basieren, sind in Abbildung 4 dargestellt, sie sind recht einfach. Wir werden sie als Grundlage für die Erstellung eines zusammengesetzten Signalindikators verwenden, der Markteintrittspunkte als Pfeile im Chart anzeigt.
Abb.4 Eröffnungsbedingungen durch Indikatorsignale.
//+------------------------------------------------------------------+ //| Example.mq5 | //| Alex2356 | //| https://www.mql5.com/en/users/alex2356 | //+------------------------------------------------------------------+ #property copyright "Alex2356" #property link "https://www.mql5.com/en/users/alex2356" #property version "1.00" #property indicator_chart_window //--- two buffers are used for calculating and drawing the indicator #property indicator_buffers 2 //--- used graphic constructions #property indicator_plots 2 #property indicator_label1 "Buy Signal" #property indicator_type1 DRAW_ARROW //--- #property indicator_label2 "Sell Signal" #property indicator_type2 DRAW_ARROW //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ input group "ADX Cloud Parameters" input int ADXPeriod = 8; input double Alpha1 = 0.25; input double Alpha2 = 0.25; input group "RVI Color Parameters" input uint Smoothing = 15; //---- input double Weight1 = 0.05; input int RVI_period1 = 8; //---- input double Weight2 = 0.10; input int RVI_period2 = 21; //---- input double Weight3 = 0.16; input int RVI_period3 = 34; //---- input double Weight4 = 0.26; input int RVI_period4 = 55; //---- input double Weight5 = 0.43; input int RVI_period5 = 89; //--- double BuySignal[],SellSignal[],ADXCloud[],FastRVI[],SlowRVI[]; int ADX_Handle,RVI_Hadnle,min_rates_total; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- SetIndexBuffer(0,BuySignal,INDICATOR_DATA); SetIndexBuffer(1,SellSignal,INDICATOR_DATA); //--- PlotIndexSetInteger(0,PLOT_ARROW,233); PlotIndexSetInteger(1,PLOT_ARROW,234); //--- PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrDodgerBlue); PlotIndexSetInteger(1,PLOT_LINE_COLOR,clrCrimson); //--- ArraySetAsSeries(SellSignal,true); ArraySetAsSeries(BuySignal,true); PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE); PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,EMPTY_VALUE); PlotIndexSetInteger(0,PLOT_ARROW_SHIFT,20); PlotIndexSetInteger(1,PLOT_ARROW_SHIFT,-20); //--- ADX_Handle=iCustom(Symbol(),PERIOD_CURRENT,"adxcloud",ADXPeriod,Alpha1,Alpha2); if(ADX_Handle==INVALID_HANDLE) { Print(" Failed to create indicator handle"); return(INIT_FAILED); } //--- RVI_Hadnle=iCustom(Symbol(),PERIOD_CURRENT,"colorzerolagrvi", Smoothing, Weight1,RVI_period1, Weight2,RVI_period2, Weight3,RVI_period3, Weight4,RVI_period4, Weight5,RVI_period5 ); if(RVI_Hadnle==INVALID_HANDLE) { Print(" Failed to create indicator handle"); 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[]) { //--- c if(BarsCalculated(ADX_Handle)<rates_total || BarsCalculated(RVI_Hadnle)<rates_total || rates_total<min_rates_total) return(0); //--- int limit,to_copy,i; //--- ArraySetAsSeries(ADXCloud,true); ArraySetAsSeries(FastRVI,true); ArraySetAsSeries(SlowRVI,true); ArraySetAsSeries(high,true); ArraySetAsSeries(low,true); //--- if(prev_calculated>rates_total || prev_calculated<=0) limit=rates_total-2; else limit=rates_total-prev_calculated; to_copy=limit+2; //--- if(CopyBuffer(ADX_Handle,0,0,to_copy,ADXCloud)<=0) return(0); //--- if(CopyBuffer(RVI_Hadnle,0,0,to_copy,FastRVI)<=0) return(0); if(CopyBuffer(RVI_Hadnle,1,0,to_copy,SlowRVI)<=0) return(0); //--- for(i=limit-1; i>=0 && !IsStopped(); i--) { if(ADXCloud[i+1]>0 && FastRVI[i+1]>SlowRVI[i+1] && FastRVI[i+2]<SlowRVI[i+2]) { BuySignal[i]=low[i]; SellSignal[i]=EMPTY_VALUE; } else if(ADXCloud[i+1]<0 && FastRVI[i+1]<SlowRVI[i+1] && FastRVI[i+2]>SlowRVI[i+2]) { SellSignal[i]=high[i]; BuySignal[i]=EMPTY_VALUE; } else { BuySignal[i]=EMPTY_VALUE; SellSignal[i]=EMPTY_VALUE; } } //--- return value of prev_calculated for the next call return(rates_total); } //+------------------------------------------------------------------+
Die resultierende Implementierung ist in Abbildung 5 dargestellt. Jetzt müssen wir das System der Sprachbenachrichtigungen implementieren.
Abb.5 Ein Pfeilindikator, der auf zwei Indikatoren basiert.
Binden Sie zunächst die Datei SoundsLib.mqh mit dem Indikator ein:
#include <SoundsLib/SoundsLib.mqh>
Erstellen Sie eine Instanz der Klasse einer Sprachbenachrichtigung:
CSoundsLib Notify;
Stellen Sie in OnInit() Initialisierungsfunktion die Benachrichtigungssprache ein. Hier werde ich Englisch einstellen. Eigentlich ist Englisch standardmäßig eingestellt, so dass es nicht notwendig ist, es zusätzlich einzustellen. Hier machen wir es also zu Demonstrationszwecken.
Notify.Language(ENGLISH);
Da der Pfeilindikator nur Markteintrittspunkte oder Kauf-/Verkaufssignale anzeigt, werden wir zwei Sprachbenachrichtigungen aus der Enumeration MESSAGE verwenden:
SIGNAL_BUY, // A Buy signal SIGNAL_SELL, // A Sell signal
Wenn wir das Benachrichtigungssystem in einen Indikator einbetten, sollten Hinweise nicht in der gesamten Historie generiert werden, sondern nur auf dem aktuellen Balken. Ändern Sie also die Schleife für die Signalsuche wie folgt:
//--- for(i=limit-1; i>=0 && !IsStopped(); i--) { if(ADXCloud[i+1]>0 && FastRVI[i+1]>SlowRVI[i+1] && FastRVI[i+2]<SlowRVI[i+2]) { BuySignal[i]=low[i]; SellSignal[i]=EMPTY_VALUE; if(i==0) Notify.Message(SIGNAL_BUY); } else if(ADXCloud[i+1]<0 && FastRVI[i+1]<SlowRVI[i+1] && FastRVI[i+2]>SlowRVI[i+2]) { SellSignal[i]=high[i]; BuySignal[i]=EMPTY_VALUE; if(i==0) Notify.Message(SIGNAL_SELL); } else { BuySignal[i]=EMPTY_VALUE; SellSignal[i]=EMPTY_VALUE; } }
Hier prüfen wir, ob ein Signal auf dem Balken Null vorhanden ist, um den Nutzer des Terminals zu benachrichtigen.
Praktische Anwendung im Handel durch Expert Advisor
Im Allgemeinen reichen zwei Arten von Sprachhinweisen als Hinweise aus. Zusätzlich können Sie Hinweise implementieren, um über den in den überkauften Bereich eintretenden Wert für Oszillatoren, über Kanalausbrüche für Bollinger-Bänder usw. zu informieren. Viel mehr Hinweise können in Expert Advisors verwendet werden. Schaffen wir also einen Test-Handelsroboter, der nicht nur über ein Markteintrittssignal benachrichtigt, sondern auch weitere Aktionen kommentiert, z.B. welcher Positionstyp eröffnet wird. Lassen Sie uns zunächst die Markteintrittsstrategie für den Expert Advisor definieren.
Parameter | Beschreibung |
---|---|
Verwendeter Indikator | ColorStDev |
Verwendeter Indikator | Three Tirone levels |
Wahl des Zeitrahmens | Beide |
Kaufbedingungen | Das Histogramm von ColorStdDev ist rot (starker Trend), während der aktuelle Preis über dem oberen Tirone-Level liegen sollte. |
Verkaufsbedingungen | Das Histogramm von ColorStdDev ist rot (starker Trend), während der aktuelle Preis unter dem unteren Tirone-Level liegen sollte. |
Exit-Bedingungen | Take-Profit/Stop-Loss |
Markteintrittspunkte werden visuell dargestellt, wie in Abbildung 6.
Abb. 6 Beispiele für Markteintritte nach dieser Strategie.
Lassen Sie uns nun die Strategie für MetaTrader 5 umsetzen. Sprachliche Hinweise werden für einige Ereignisse verwendet.
//+------------------------------------------------------------------+ //| VoiceNotify.mq5 | //| Alex2356 | //| https://www.mql5.com/en/users/alex2356 | //+------------------------------------------------------------------+ #property copyright "Alex2356" #property link "https://www.mql5.com/en/users/alex2356" #property version "1.00" #include <SoundsLib/SoundsLib.mqh> #include <DoEasy25/Engine.mqh> //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ input uint InpStopLoss = 150; // Stop Loss, in pips input uint InpTakeProfit = 250; // Take Profit, in pips input double InpLot = 0.1; // Take Profit, in pips input ulong InpDeviation = 10; // Deviation input int InpMagic = 2356; // Magic number input LANGUAGE NotifyLanguage = ENGLISH; // Notification Language //--- ColorStDev indicator parameters input int StDevPeriod = 12; // Smoothing period StDev input ENUM_MA_METHOD MA_Method = MODE_EMA; // Histogram smoothing method input ENUM_APPLIED_PRICE applied_price = PRICE_CLOSE; // Applied price input int MaxTrendLevel = 90; // Maximum trend level input int MiddLeTrendLevel = 50; // Middle trend level input int FlatLevel = 20; // Flat level //--- Tirone Levels indicator parameters input int TironePeriod = 13; // Tirone Period //--- CEngine trade; CSoundsLib notify; int Handle1,Handle2; double stdev[],tirone_b[],tirone_s[]; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) notify.Message(AUTO_TRADING_OFF); //--- OnInitTrading(); //--- Get the handle of the ColorStDev indicator Handle1=iCustom(Symbol(),PERIOD_CURRENT,"ArticleVoiceNotify\\colorstddev", StDevPeriod, MA_Method, applied_price, MaxTrendLevel, MiddLeTrendLevel, FlatLevel ); if(Handle1==INVALID_HANDLE) { Print("Failed to get colorstddev handle"); Print("Handle = ",Handle1," error = ",GetLastError()); return(INIT_FAILED); } //--- Getting the handle of the Tirone Levels indicator Handle2=iCustom(Symbol(),PERIOD_CURRENT,"ArticleVoiceNotify\\tirone_levels_x3",TironePeriod,0); if(Handle2==INVALID_HANDLE) { Print("Failed to get Tirone Levels handle"); Print("Handle = ",Handle2," error = ",GetLastError()); return(INIT_FAILED); } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- If there are no market positions if(ExistPositions(Symbol(),-1,InpMagic)<1) { //--- Getting data for calculations if(!GetIndValue()) return; //--- Open an order if there is a buy signal if(BuySignal()) { notify.Message(SIGNAL_BUY); if(trade.OpenBuy(InpLot,Symbol(),InpMagic,InpStopLoss,InpTakeProfit)) { Sleep(1400); notify.Message(BUY_ORDER_SET); } } //--- Opening an order if there is a sell signal if(SellSignal()) { notify.Message(SIGNAL_SELL); if(trade.OpenSell(InpLot,Symbol(),InpMagic,InpStopLoss,InpTakeProfit)) { Sleep(1400); notify.Message(SELL_ORDER_SET); } } } } //+------------------------------------------------------------------+ //| Buy conditions | //+------------------------------------------------------------------+ bool BuySignal() { return(tirone_b[1]>iClose(Symbol(),PERIOD_CURRENT,1) && stdev[0]>FlatLevel)?true:false; } //+------------------------------------------------------------------+ //| Sell conditions | //+------------------------------------------------------------------+ bool SellSignal() { return(tirone_b[1]<iClose(Symbol(),PERIOD_CURRENT,1) && stdev[0]>FlatLevel)?true:false; } //+------------------------------------------------------------------+ //| Getting the current values of indicators | //+------------------------------------------------------------------+ bool GetIndValue() { return(CopyBuffer(Handle1,0,0,2,stdev)<=0 || CopyBuffer(Handle2,0,0,2,tirone_b)<=0 || CopyBuffer(Handle2,2,0,2,tirone_s)<=0 )?false:true; } //+----------------------------------------------------------------------------+ //| Returns the number of open orders | //+----------------------------------------------------------------------------+ //| Parameters: | //| op - operation (-1 - any position) | //| mn - MagicNumber (-1 - any magic number) | //+----------------------------------------------------------------------------+ int ExistPositions(string sy,int op=-1,int mn=-1) { int pos=0; uint total=PositionsTotal(); //--- for(uint i=0; i<total; i++) { if(SelectByIndex(i)) if(PositionGetString(POSITION_SYMBOL)==sy) if(op<0 || PositionGetInteger(POSITION_TYPE)==op) if(mn<0 || PositionGetInteger(POSITION_MAGIC)==mn) pos++; } return(pos); } //+------------------------------------------------------------------+ //| Select a position on the index | //+------------------------------------------------------------------+ bool SelectByIndex(const int index) { ENUM_ACCOUNT_MARGIN_MODE margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE); //--- if(margin_mode==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) { ulong ticket=PositionGetTicket(index); if(ticket==0) return(false); } else { string name=PositionGetSymbol(index); if(name=="") return(false); } //--- return(true); } //+------------------------------------------------------------------+ //| Trading Environment Initialization | //+------------------------------------------------------------------+ void OnInitTrading() { string array_used_symbols[]; //--- Fill in the array of used symbols CreateUsedSymbolsArray(SYMBOLS_MODE_CURRENT,"",array_used_symbols); //--- Set the type of the used symbol list in the symbol collection and fill in the list of symbol timeseries trade.SetUsedSymbols(array_used_symbols); //--- Pass all existing collections to the trading class trade.TradingOnInit(); trade.TradingSetMagic(InpMagic); trade.TradingSetLogLevel(LOG_LEVEL_ERROR_MSG); //--- Set synchronous passing of orders for all used symbols trade.TradingSetAsyncMode(false); //--- Set correct order expiration and filling types to all trading objects trade.TradingSetCorrectTypeExpiration(); trade.TradingSetCorrectTypeFilling(); } //+------------------------------------------------------------------+
Lassen Sie uns diesen Code im Hinblick auf die Verwendung von Sprachhinweisen genauer besprechen. Die Initialisierungsfunktion des Handelsroboters prüft, ob Handelssysteme im Terminal handeln dürfen. Wenn diese Option deaktiviert ist, wird ein entsprechender Sprachhinweis abgespielt, um den Nutzer zu benachrichtigen. Wenn in der Funktion OnTick() das gewünschte Handelssignal gefunden wird, wird der EA benachrichtigt, dass das gewünschte Kauf- oder Verkaufssignal gefunden wurde. Es wird versucht, eine Position entsprechend dem Signal zu eröffnen. Wenn dies erfolgreich ist, wird ein weiterer Sprachhinweis abgespielt, um den Nutzer zu benachrichtigen, dass eine Position platziert wurde.
Diese Hinweise sind viel effizienter, da der Nutzer möglicherweise einen Texthinweis auf der Registerkarte "Experten" im Terminal verpasst. Was Standard-Soundbenachrichtigungen betrifft, so ist die Bedeutung des Tons nicht immer klar, sie können bei Indikatoren und Expertenberatern unterschiedlich sein. Sprachbenachrichtigungen liefern die genauen Informationen und sind daher viel bequemer.
Praktische Anwendung in Quick Trading Tools
In meinen früheren Artikeln habe ich ein Toolkit für manuelle Händler entwickelt, die selbständig nach Markteinträgen suchen, Aufträge manuell erteilen, Positionen verwalten und schließen. Zu Demonstrationszwecken möchte ich diesem Toolkit ein System der Sprachbenachrichtigung hinzufügen. Dies wird auch zeigen, dass die Funktionen der Sprachbenachrichtigungen leicht zu jedem Tool hinzugefügt werden kann. Als Grundlage werde ich einen Anhang aus diesem Artikel verwenden. Lassen Sie uns zunächst eine Liste von Aktionen und Ereignissen definieren, für die wir Hinweise per Sprachbenachrichtigung hinzufügen werden.
- Erfolgreiche Eröffnung einer Kauf- oder Verkaufsposition.
- Erfolgreiche Platzierung von Pending Orders und deren Löschung.
- Überprüfung, ob ein Auftrag mit Hilfe eines Expert Advisors platziert werden kann.
Bevor wir mit der Integration von Sprachbenachrichtigungen beginnen, lassen Sie uns die entsprechende Bibliothek an dieses Projekt anschließen. Öffnen Sie Programm.mqh und fügen Sie ganz am Anfang Folgendes hinzu.
//+------------------------------------------------------------------+ //| Program.mqh | //| Alex2356 | //| https://www.mql5.com/en/users/alex2356/ | //+------------------------------------------------------------------+ #include <EasyAndFastGUI\WndEvents.mqh> #include <DoEasy25\Engine.mqh> #include "Defines.mqh" #include <SoundsLib/SoundsLib.mqh>
Gehen Sie in den 'private' Teil der Klasse CFastTrading und erstellen Sie eine Klassenvariable der Instanz CSoundsLib.
//---
CSoundsLib m_notify;
Legen Sie außerdem zwei neue Parameter im Toolkit fest, die das Aktivieren/Deaktivieren von Benachrichtigungen und die Auswahl der Sprache ermöglichen. Öffnen Sie SimpleTrading.mq5 und fügen Sie neue Parameter im EA-Abschnitt Eingabeparameter hinzu:
//+------------------------------------------------------------------+ //| Expert Advisor input parameters | //+------------------------------------------------------------------+ input int Inp_BaseFont = 10; // Base FontSize input color Caption = C'0,130,225'; // Caption Color input color Background = clrWhite; // Back color input LANG Language = ENGLISH; // Interface language input ulong MagicNumber = 1111; // Magic Number //--- input bool UseVoiceNotify = true; // Use Voice Notify input LANGUAGE NotifyLanguage = ENGLISH; // Notification Language
Um sie CSoundsLib der Klasseninstanz m_notify zu übergeben, erstellen Sie zwei Methoden im 'public' Teil der Basisklasse CFastTrading und implementieren Sie diese:
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CFastTrading::SetNotifyLanguage(LANGUAGE lang) { m_notify.Language(lang); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CFastTrading::UseVoiceNotify(bool state) { m_notify.IsActive(state); } //+------------------------------------------------------------------+
Implementieren Sie diese nun in der Funktion OnInit() in SimpleTrading.mq5 und übergeben Sie die Eingabeparameter an die neu erstellten Methoden.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- tick_counter=GetTickCount(); //--- Initialize class variables program.FontName("Trebuchet MS"); program.FontSize(Inp_BaseFont); program.BackgroundColor(Background); program.CaptionColor(Caption); program.SetLanguage(Language); program.SetMagicNumber(MagicNumber); program.UseVoiceNotify(UseVoiceNotify); program.SetNotifyLanguage(NotifyLanguage); //--- Set up the trading panel if(!program.CreateGUI()) { Print(__FUNCTION__," > Failed to create graphical interface!"); return(INIT_FAILED); } program.OnInitEvent(); //--- return(INIT_SUCCEEDED); }
So haben wir die wichtigsten Eingabeparameter des Sprachbenachrichtigungssystems festgelegt. Finden Sie nun Methoden zur Festlegung der Marktpositionen für Kauf und Verkauf. Dies sind die Methoden SetBuyOrder() und SetSellOrder() in der Basisklasse CFastTrading. Öffnen Sie den Hauptteil der Methode, die Kaufaufträge platziert, und suchen Sie den Teil, in dem geprüft wird, ob die Position erfolgreich eröffnet wurde. Fügen Sie dort die entsprechenden Hinweise BUY_ORDER_SET hinzu:
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CFastTrading::SetBuyOrder(int id,long lparam) { if((id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON && lparam==m_buy_execute.Id()) || (id==CHARTEVENT_KEYDOWN && lparam==KEY_B)) { //--- double lot; if(m_switch_button[0].IsPressed()) lot=LotPercent(Symbol(),ORDER_TYPE_BUY,SymbolInfoDouble(Symbol(),SYMBOL_ASK),StringToDouble(m_lot_edit[0].GetValue())); else lot=NormalizeLot(Symbol(),StringToDouble(m_lot_edit[0].GetValue())); if(m_switch_button[1].IsPressed() && m_switch_button[2].IsPressed()) { double tp=double(m_tp_edit[0].GetValue()); double sl=double(m_sl_edit[0].GetValue()); if(m_trade.OpenBuy(lot,Symbol(),m_magic_number,sl,tp)) { m_notify.Message(BUY_ORDER_SET); return(true); } } else if(!m_switch_button[1].IsPressed() && !m_switch_button[2].IsPressed()) { int tp=int(m_tp_edit[0].GetValue()); int sl=int(m_sl_edit[0].GetValue()); if(m_trade.OpenBuy(lot,Symbol(),m_magic_number,sl,tp)) { m_notify.Message(BUY_ORDER_SET); return(true); } } else if(m_switch_button[1].IsPressed() && !m_switch_button[2].IsPressed()) { double tp=double(m_tp_edit[0].GetValue()); int sl=int(m_sl_edit[0].GetValue()); if(m_trade.OpenBuy(lot,Symbol(),m_magic_number,sl,tp)) { m_notify.Message(BUY_ORDER_SET); return(true); } } else if(!m_switch_button[1].IsPressed() && m_switch_button[2].IsPressed()) { int tp=int(m_tp_edit[0].GetValue()); double sl=double(m_sl_edit[0].GetValue()); if(m_trade.OpenBuy(lot,Symbol(),m_magic_number,sl,tp)) { m_notify.Message(BUY_ORDER_SET); return(true); } } } return(false); }
Nehmen Sie die gleichen Änderungen für Methoden zur Eröffnung von Verkaufspositionen vor. Die zu verwendenden Hinweise lauten SELL_ORDER_SET:
bool CFastTrading::SetSellOrder(int id,long lparam) { if((id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON && lparam==m_sell_execute.Id()) || (id==CHARTEVENT_KEYDOWN && lparam==KEY_S)) { //--- double lot; if(m_switch_button[3].IsPressed()) lot=LotPercent(Symbol(),ORDER_TYPE_SELL,SymbolInfoDouble(Symbol(),SYMBOL_BID),StringToDouble(m_lot_edit[1].GetValue())); else lot=NormalizeLot(Symbol(),StringToDouble(m_lot_edit[1].GetValue())); //--- if(m_switch_button[4].IsPressed() && m_switch_button[5].IsPressed()) { double tp=double(m_tp_edit[1].GetValue()); double sl=double(m_sl_edit[1].GetValue()); if(m_trade.OpenSell(lot,Symbol(),m_magic_number,sl,tp)) { m_notify.Message(SELL_ORDER_SET); return(true); } } else if(!m_switch_button[4].IsPressed() && !m_switch_button[5].IsPressed()) { int tp=int(m_tp_edit[1].GetValue()); int sl=int(m_sl_edit[1].GetValue()); if(m_trade.OpenSell(lot,Symbol(),m_magic_number,sl,tp)) { m_notify.Message(SELL_ORDER_SET); return(true); } } else if(!m_switch_button[4].IsPressed() && m_switch_button[5].IsPressed()) { int tp=int(m_tp_edit[1].GetValue()); double sl=double(m_sl_edit[1].GetValue()); if(m_trade.OpenSell(lot,Symbol(),m_magic_number,sl,tp)) { m_notify.Message(SELL_ORDER_SET); return(true); } } else if(m_switch_button[4].IsPressed() && !m_switch_button[5].IsPressed()) { double tp=double(m_tp_edit[1].GetValue()); int sl=int(m_sl_edit[1].GetValue()); if(m_trade.OpenSell(lot,Symbol(),m_magic_number,sl,tp)) { m_notify.Message(SELL_ORDER_SET); return(true); } } } return(false); }
Kommen wir nun zu den Pending-Orders. Das Toolkit unterstützt vier Typen, jeder hat eine eigene Methode:
bool SetBuyStopOrder(int id,long lparam); bool SetSellStopOrder(int id,long lparam); bool SetBuyLimitOrder(int id,long lparam); bool SetSellLimitOrder(int id,long lparam);
Für jeden von ihnen sollte eine separate Sprachbenachrichtigung eingestellt werden. Hier ist ein Beispiel für eine BuyStop-Order, andere werden auf ähnliche Weise eingerichtet. Wie aus dem untenstehenden Code ersichtlich ist, wird die Benachrichtigung BUYSTOP_ORDER_SET verwendet.
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CFastTrading::SetBuyStopOrder(int id,long lparam) { if(!m_orders_windows[1].IsVisible()) return(false); if((id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON && lparam==m_buystop_execute.Id()) || (id==CHARTEVENT_KEYDOWN && lparam==KEY_1)) { //--- double lot; if(m_p_switch_button[0].IsPressed()) lot=LotPercent(Symbol(),ORDER_TYPE_BUY,SymbolInfoDouble(Symbol(),SYMBOL_ASK),StringToDouble(m_lot_edit[2].GetValue())); else lot=NormalizeLot(Symbol(),StringToDouble(m_lot_edit[2].GetValue())); //--- double pr=double(m_pr_edit[0].GetValue()); //--- if(m_p_switch_button[1].IsPressed() && m_p_switch_button[2].IsPressed()) { double tp=double(m_tp_edit[2].GetValue()); double sl=double(m_sl_edit[2].GetValue()); if(m_trade.PlaceBuyStop(lot,Symbol(),pr,sl,tp,m_magic_number)) { m_notify.Message(BUYSTOP_ORDER_SET); return(true); } } else if(!m_p_switch_button[1].IsPressed() && !m_p_switch_button[2].IsPressed()) { int tp=int(m_tp_edit[2].GetValue()); int sl=int(m_sl_edit[2].GetValue()); if(m_trade.PlaceBuyStop(lot,Symbol(),pr,sl,tp,m_magic_number)) { m_notify.Message(BUYSTOP_ORDER_SET); return(true); } } else if(m_p_switch_button[1].IsPressed() && !m_p_switch_button[2].IsPressed()) { double tp=double(m_tp_edit[2].GetValue()); int sl=int(m_sl_edit[2].GetValue()); if(m_trade.PlaceBuyStop(lot,Symbol(),pr,sl,tp,m_magic_number)) { m_notify.Message(BUYSTOP_ORDER_SET); return(true); } } else if(!m_p_switch_button[1].IsPressed() && m_p_switch_button[2].IsPressed()) { int tp=int(m_tp_edit[2].GetValue()); double sl=double(m_sl_edit[2].GetValue()); if(m_trade.PlaceBuyStop(lot,Symbol(),pr,sl,tp,m_magic_number)) { m_notify.Message(BUYSTOP_ORDER_SET); return(true); } } } return(false); }
Nun, wenn die Benachrichtigungen für erteilte Pending-Orders fertig sind, müssen wir Benachrichtigungen für das Löschen früher erteilter Orders hinzufügen. Die Methode RemoveOrder() bestimmt, welche der Pending-Orders in der Tabelle ausgewählt wird. Die ausgewählte Order kann dann geändert oder gelöscht werden. Dabei wird eine Order durch Klicken auf die Schaltfläche Delete gelöscht.
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CFastTrading::RemoveOrder(long lparam) { //--- Check the element ID if(lparam==m_small_button[3].Id()) { //--- Get index and symbol if(m_table_orders.SelectedItem()==WRONG_VALUE) return(false); int row=m_table_orders.SelectedItem(); ulong ticket=(ulong)m_table_orders.GetValue(0,row); //--- if(OrderSelect(ticket)) { string position_symbol=OrderGetString(ORDER_SYMBOL); // symbol ulong magic=OrderGetInteger(ORDER_MAGIC); // order MagicNumber ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); // order type if(type==ORDER_TYPE_BUY_STOP) m_notify.Message(BUYSTOP_ORDER_DELETE); else if(type==ORDER_TYPE_SELL_STOP) m_notify.Message(SELLSTOP_ORDER_DELETE); else if(type==ORDER_TYPE_BUY_LIMIT) m_notify.Message(BUYLIMIT_ORDER_DELETE); else if(type==ORDER_TYPE_SELL_LIMIT) m_notify.Message(SELLLIMIT_ORDER_DELETE); //--- declare the request and the result MqlTradeRequest request; MqlTradeResult result; //--- zeroing the request and result values ZeroMemory(request); ZeroMemory(result); //--- set the operation parameters request.action=TRADE_ACTION_REMOVE; // trading operation type request.order = ticket; // order ticket //--- sending a request bool res=true; for(int j=0; j<5; j++) { res=OrderSend(request,result); if(res && result.retcode==TRADE_RETCODE_DONE) return(true); else PrintFormat("OrderSend error %d",GetLastError()); // if unable to send the request, output the error code } } } //--- return(false); }
Lassen Sie uns die Modifikation im Hauptteil der Methode genauer besprechen. Nachdem wir das Ticket der ausgewählten Order definiert haben, erhalten wir die erforderlichen Daten, um eine Anforderung für deren Löschung festzulegen, indem wir die Struktur MqlTradeRequest ausfüllen und die Methode OrderSend() aufrufen. Um zu verstehen, welcher Typ einer Pending-Order in der Tabelle ausgewählt wurde, verwenden wir den Wert des Variablentyps. Legen Sie auf der Grundlage des Variablenwerts die entsprechende Sprachbenachrichtigung in der Methode Message() fest.
Die letzte zu implementierende Aufgabe besteht darin, eine Sprachbenachrichtigung hinzuzufügen, wenn der automatisierte Handel im MetaTrader 5-Terminal deaktiviert ist. Bei dem Toolkit handelt es sich eigentlich um einen Expert Advisor: Obwohl Nutzer Aufträge manuell erteilen, erkennen das Terminal und der Broker sie als automatisierten Handel. Um eine Prüfung hinzuzufügen, ob automatisierter Handel stattfindet, gehen Sie zu Basisklasse, finden Sie die Ereignisbehandlung durch OnEvent() -> im Bereich ON_END_CREATE_GUI und fügen Sie eine Prüfung mit der entsprechenden Sprachbenachrichtigung hinzu:
// --- GUI creation completion if(id==CHARTEVENT_CUSTOM+ON_END_CREATE_GUI) { //--- SetButtonParam(m_switch_button[0],LOT); SetButtonParam(m_switch_button[1],POINTS); SetButtonParam(m_switch_button[2],POINTS); SetButtonParam(m_switch_button[3],LOT); SetButtonParam(m_switch_button[4],POINTS); SetButtonParam(m_switch_button[5],POINTS); //--- SetButtonParam(m_p_switch_button[0],LOT); SetButtonParam(m_p_switch_button[1],POINTS); SetButtonParam(m_p_switch_button[2],POINTS); SetButtonParam(m_p_switch_button[3],LOT); SetButtonParam(m_p_switch_button[4],POINTS); SetButtonParam(m_p_switch_button[5],POINTS); SetButtonParam(m_p_switch_button[6],LOT); SetButtonParam(m_p_switch_button[7],POINTS); SetButtonParam(m_p_switch_button[8],POINTS); SetButtonParam(m_p_switch_button[9],LOT); SetButtonParam(m_p_switch_button[10],POINTS); SetButtonParam(m_p_switch_button[11],POINTS); //--- if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) m_notify.Message(AUTO_TRADING_OFF); }
Das Video unten zeigt, wie Sprachbenachrichtigungen im Schnellhandels-Toolkit funktionieren, in dem Hinweise für Marktpositionen und Pending-Orders verwendet werden.
Schlussfolgerung
Das angehängte Archiv enthält alle besprochenen Dateien, die sich in den entsprechenden Ordnern befinden. Für ihren ordnungsgemäßen Betrieb brauchen Sie nur den MQL5-Ordner im Terminalordner zu speichern. Um das Stammverzeichnis des Terminals, in dem sich der MQL5-Ordner befindet, zu öffnen, drücken Sie die Tastenkombination Strg+Umschalt+D im Terminal des MetaTrader 5 oder verwenden Sie das Kontextmenü, wie in Abb. 7 unten dargestellt.
Abb. 7. Öffnen des Ordners MQL5 im Stammordner von MetaTrader 5
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/8111





- 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.