Das MQL5-Kochbuch: Signaltöne für Handelsereignisse in MetaTrader 5
Einleitung
In diesem Beitrag betrachten wir, wie Sound-Dateien in die Datei des Expert Advisors hinzugefügt werden, um so Signaltöne zu Handelsereignissen hinzuzufügen. Die Tatsache, dass die Dateien eingearbeitet werden, bedeutet, dass die Sound-Dateien sich innerhalb des Expert Advisors befinden werden. Wenn Sie also die kompilierte Version des Expert Advisors (*.ex5) an einen anderen Benutzer übergeben, müssen Sie ihm die Sound-Dateien nicht separat zur Verfügung stellen und erklären, wo sie abzulegen sind.
Entwicklung
Für unsere Testzwecke nehmen wir den Expert Advisor aus dem vorhergehenden Beitrag "Das MQL5-Kochbuch: Speichern der Optimierungsergebnisse eines Expert Advisors auf Basis bestimmter Kriterien". Zur Vereinfachung habe ich alles entfernt, was für das aktuelle Thema nicht relevant ist.
Um mithilfe von MQL5-Ressourcen Signaltöne zu einem Handelsereignis hinzuzufügen, können wir die Funktionen Alert() und PlaySound() nutzen. Wenn Sie sich für die Funktion Alert() entscheiden, wird immer der gleiche Signalton abgespielt und ein Fenster mit der jeweiligen Nachricht geöffnet. Sie sehen die Funktion in Aktion im Beitrag "Das MQL5-Kochbuch: Verwendung unterschiedlicher Druckmodi".
Der Warnton kann in den Einstellungen des Terminals festgelegt werden: Tools -> Options oder Strg+O. Außerdem müssen wir in der Registerkarte Events die Option "Enable" aktivieren, um Signaltöne für Ereignisse zu aktiveren, und in der Dropdown-Liste der Warntöne die entsprechende Sound-Datei auswählen.
Abb. 1. Registerkarte "Events" in den Einstellungen des Terminals
Allerdings haben Sie auch die Möglichkeit, einen eigenen Signalton für jedes benutzerdefinierte Programmereignis festzulegen. Zu diesem Zweck nutzen wir die Funktion PlaySound().
Bevor wir Signaltöne zum Expert Advisor hinzufügen, erstellen wir einen Expert Advisor für unseren Testzwecke. Wir setzen die Idee um, beim Laden eines Expert Advisors im Diagramm ein Sound-Panel zu öffnen. Das Sound-Panel besteht aus grafischen Objekten, bspw. dem Button (OBJ_BUTTON). Jedem Button wird ein eigener Ton zugewiesen, der beim Anklicken des Buttons wiedergegeben wird.
Im Internet fand ich 25 verschiedene Sound-Dateien im Format *.wav (diese können am Ende des Beitrags heruntergeladen werden). Sie müssen in den Ordner MetaTrader 5\MQL5\Files\Sounds gelegt werden. Um die Arbeit mit Sound-Dateien zu üben, erstellen wir nun einen Expert Advisor mit dem MQL5 Wizard. Gleich am Anfang legen wir die Array-Größe basierend auf der Menge der Buttons im Sound-Panel fest (es wird insgesamt 26 Buttons geben).
//--- Array size #define ARRAY_SIZE 26
Dann müssen wir die Ordner und Dateinamen festlegen, die den Expert Advisor mit Ressourcen versorgen. Das geschieht mithilfe der Direktive #resource. Nach der Direktive geben wir den Ablageort der Dateien in Anführungszeichen an:
//--- Sound files #resource "\\Files\\Sounds\\alert.wav" #resource "\\Files\\Sounds\\AHOOGA.wav" #resource "\\Files\\Sounds\\APPLAUSE.wav" #resource "\\Files\\Sounds\\BONK.wav" #resource "\\Files\\Sounds\\CARBRAKE.wav" #resource "\\Files\\Sounds\\CASHREG.wav" #resource "\\Files\\Sounds\\CLAP.wav" #resource "\\Files\\Sounds\\CORKPOP.wav" #resource "\\Files\\Sounds\\DOG.wav" #resource "\\Files\\Sounds\\DRIVEBY.wav" #resource "\\Files\\Sounds\\DRUMROLL.wav" #resource "\\Files\\Sounds\\EXPLODE.wav" #resource "\\Files\\Sounds\\FINALBEL.wav" #resource "\\Files\\Sounds\\FROG.wav" #resource "\\Files\\Sounds\\GLASS.wav" #resource "\\Files\\Sounds\\GUNSHOT.wav" #resource "\\Files\\Sounds\\LASER.wav" #resource "\\Files\\Sounds\\LATNWHIS.wav" #resource "\\Files\\Sounds\\PIG.wav" #resource "\\Files\\Sounds\\RICOCHET.wav" #resource "\\Files\\Sounds\\RINGIN.wav" #resource "\\Files\\Sounds\\SIREN.wav" #resource "\\Files\\Sounds\\TRAIN.wav" #resource "\\Files\\Sounds\\UH_OH.wav" #resource "\\Files\\Sounds\\VERYGOOD.wav" #resource "\\Files\\Sounds\\WHOOSH.wav"
Jetzt müssen wir drei String-Arrays erstellen, die die Ablageorte der Ressourcendateien, die Namen der grafischen Objekte und den auf den grafischen Objekten angezeigten Text enthalten. Beachten Sie den doppelten Doppelpunkt beim Angeben der Dateiablageorte. Dabei handelt es sich um eine spezielle Angabe für den Aufruf der Ressource nach Namen.
//--- Sound file location string sound_paths[ARRAY_SIZE]= { "::Files\\Sounds\\alert.wav", "::Files\\Sounds\\AHOOGA.wav", "::Files\\Sounds\\APPLAUSE.wav", "::Files\\Sounds\\BONK.wav", "::Files\\Sounds\\CARBRAKE.wav", "::Files\\Sounds\\CASHREG.wav", "::Files\\Sounds\\CLAP.wav", "::Files\\Sounds\\CORKPOP.wav", "::Files\\Sounds\\DOG.wav", "::Files\\Sounds\\DRIVEBY.wav", "::Files\\Sounds\\DRUMROLL.wav", "::Files\\Sounds\\EXPLODE.wav", "::Files\\Sounds\\FINALBEL.wav", "::Files\\Sounds\\FROG.wav", "::Files\\Sounds\\GLASS.wav", "::Files\\Sounds\\GUNSHOT.wav", "::Files\\Sounds\\LASER.wav", "::Files\\Sounds\\LATNWHIS.wav", "::Files\\Sounds\\PIG.wav", "::Files\\Sounds\\RICOCHET.wav", "::Files\\Sounds\\RINGIN.wav", "::Files\\Sounds\\SIREN.wav", "::Files\\Sounds\\TRAIN.wav", "::Files\\Sounds\\UH_OH.wav", "::Files\\Sounds\\VERYGOOD.wav", "::Files\\Sounds\\WHOOSH.wav" }; //--- Names of graphical objects string sound_names[ARRAY_SIZE]= { "sound_button01","sound_button02", "sound_button03","sound_button04", "sound_button05","sound_button06", "sound_button07","sound_button08", "sound_button09","sound_button10", "sound_button11","sound_button12", "sound_button13","sound_button14", "sound_button15","sound_button16", "sound_button17","sound_button18", "sound_button19","sound_button20", "sound_button21","sound_button22", "sound_button23","sound_button24", "sound_button25","sound_button26" }; //--- Text displayed on graphical objects string sound_texts[ARRAY_SIZE]= { "ALERT","AHOOGA","APPLAUSE","BONK","CARBRAKE","CASHREG", "CLAP","CORKPOP","DOG","DRIVEBY","DRUMROLL","EXPLODE","FINALBEL", "FROG","GLASS","GUNSHOT","LASER","LATNWHIS","PIG", "RICOCHET","RINGIN","SIREN","TRAIN","UH_OH","VERYGOOD","WHOOSH" };
Schreiben wir die Funktion CreateButton(), die das grafische Objekt "Button" mit den festgelegten Eigenschaften in einem Diagramm erstellt:
//+------------------------------------------------------------------+ //| Creating the Button object | //+------------------------------------------------------------------+ void CreateButton(long chart_id, // chart id int sub_window, // window number string name, // object name string text, // displayed name ENUM_ANCHOR_POINT anchor, // anchor point ENUM_BASE_CORNER corner, // chart corner string font_name, // font int font_size, // font size color font_color, // font color color background_color, // background color color border_color, // border color int x_size, // width int y_size, // height int x_distance, // X-coordinate int y_distance, // Y-coordinate long z_order) // Z-order { //--- Creating an object if(ObjectCreate(chart_id,name,OBJ_BUTTON,sub_window,0,0)) { ObjectSetString(chart_id,name,OBJPROP_TEXT,text); // setting name ObjectSetString(chart_id,name,OBJPROP_FONT,font_name); // setting font ObjectSetInteger(chart_id,name,OBJPROP_COLOR,font_color); // setting font color ObjectSetInteger(chart_id,name,OBJPROP_BGCOLOR,background_color); // setting background color ObjectSetInteger(chart_id,name,OBJPROP_BORDER_COLOR,border_color); // setting border color ObjectSetInteger(chart_id,name,OBJPROP_ANCHOR,anchor); // setting anchor point ObjectSetInteger(chart_id,name,OBJPROP_CORNER,corner); // setting chart corner ObjectSetInteger(chart_id,name,OBJPROP_FONTSIZE,font_size); // setting font size ObjectSetInteger(chart_id,name,OBJPROP_XSIZE,x_size); // setting width X ObjectSetInteger(chart_id,name,OBJPROP_YSIZE,y_size); // setting height Y ObjectSetInteger(chart_id,name,OBJPROP_XDISTANCE,x_distance); // setting X-coordinate ObjectSetInteger(chart_id,name,OBJPROP_YDISTANCE,y_distance); // setting Y-coordinate ObjectSetInteger(chart_id,name,OBJPROP_SELECTABLE,false); // cannot select the object if FALSE ObjectSetInteger(chart_id,name,OBJPROP_STATE,false); // button state (clicked/unclicked) ObjectSetInteger(chart_id,name,OBJPROP_ZORDER,z_order); // higher/lower Z-order ObjectSetString(chart_id,name,OBJPROP_TOOLTIP,"\n"); // no tooltip if "\n" } }
Um es interessanter zu machen, wird die Farbe jedes Buttons zufällig gewählt. Dazu schreiben wir die einfache Funktion GetRandomColor():
//+------------------------------------------------------------------+ //| Returning a random color | //+------------------------------------------------------------------+ color GetRandomColor() { //--- Select a random color from 0 to 25 switch(MathRand()%26) { case 0 : return(clrOrange); break; case 1 : return(clrGold); break; case 2 : return(clrChocolate); break; case 3 : return(clrChartreuse); break; case 4 : return(clrLime); break; case 5 : return(clrSpringGreen); break; case 6 : return(clrMediumBlue); break; case 7 : return(clrDeepSkyBlue); break; case 8 : return(clrBlue); break; case 9 : return(clrSeaGreen); break; case 10 : return(clrRed); break; case 11 : return(clrSlateGray); break; case 12 : return(clrPeru); break; case 13 : return(clrBlueViolet); break; case 14 : return(clrIndianRed); break; case 15 : return(clrMediumOrchid); break; case 16 : return(clrCrimson); break; case 17 : return(clrMediumAquamarine); break; case 18 : return(clrDarkGray); break; case 19 : return(clrSandyBrown); break; case 20 : return(clrMediumSlateBlue); break; case 21 : return(clrTan); break; case 22 : return(clrDarkSalmon); break; case 23 : return(clrBurlyWood); break; case 24 : return(clrHotPink); break; case 25 : return(clrLightSteelBlue); break; //--- default : return(clrGold); } //--- return(clrGold); }
Schreiben wir nun die Funktion SetSoundPanel(), die das Sound-Panel zum Diagramm hinzufügt:
//+------------------------------------------------------------------+ //| Adding the sound panel to the chart | //+------------------------------------------------------------------+ void SetSoundPanel() { int column_count =0; // Column counter int x_dist =10; // Indent from the left side of the chart int y_dist =15; // Indent from the top of the chart int x_size =100; // Button width int y_size =20; // Button height color button_color =clrNONE; // Button color //--- Set the objects for(int i=0; i<ARRAY_SIZE; i++) { //--- Increase the column counter column_count++; //--- Get the button color button_color=GetRandomColor(); //--- Draw a button CreateButton(0,0,sound_names[i],sound_texts[i], ANCHOR_LEFT_UPPER,CORNER_LEFT_UPPER,"Arial",8, clrWhite,button_color,button_color,x_size,y_size,x_dist,y_dist,1); //--- If two buttons have already been set in the same row if(column_count==2) { x_dist=10; // Move the X-coordinate to the initial position y_dist+=20; // Set the Y-coordinate for the next row column_count=0; // Zero out the counter } else //--- Set the X-coordinate for the next button x_dist+=x_size; } //--- Refresh the chart ChartRedraw(0); }
Zum Entfernen des Panels aus dem Diagramm nutzen wir die nachfolgend aufgeführten Funktionen:
//+------------------------------------------------------------------+ //| Deleting the info panel | //+------------------------------------------------------------------+ void DeleteSoundPanel() { //--- Delete position properties and their values for(int i=0; i<ARRAY_SIZE; i++) DeleteObjectByName(name_sound_object[i]); //--- Redraw the chart ChartRedraw(); } //+------------------------------------------------------------------+ //| Deleting objects by name | //+------------------------------------------------------------------+ void DeleteObjectByName(string name) { //--- If the object is found if(ObjectFind(ChartID(),name)>=0) { //--- If an error occurred when deleting, print the relevant message if(!ObjectDelete(ChartID(),name)) Print("Error ("+IntegerToString(GetLastError())+") when deleting the object!"); } }
Beim Laden des Expert Advisors wird das Panel also aus der Funktion OnInit() im Diagramm eingerichtet und beim Entfernen des Expert Advisors durch die Funktion OnDeinit() aus dem Diagramm entfernt.
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void OnInit() { //--- Set the sound panel SetSoundPanel(); } //+------------------------------------------------------------------+ //| Deinitialization function of the expert advisor | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Delete the sound panel DeleteSoundPanel(); }
Nun müssen wir nur noch die Interaktion mit dem Panel implementieren, sodass der jeweilige Ton wiedergegeben wird, wenn ein bestimmter Button angeklickt wird. Um das Ganze noch fröhlicher zu gestalten, ändern wir die Farben der Buttons, wenn einer der Buttons im Sound-Panel gedrückt wird. Dazu benötigen wir die Funktion ChangeColorsOnSoundPanel(), deren Code unten aufgeführt ist:
//+------------------------------------------------------------------+ //| Changing colors on the sound panel | //+------------------------------------------------------------------+ void ChangeColorsOnSoundPanel() { color clr=clrNONE; // Button color //--- Iterate over all buttons in a loop and change their color for(int i=0; i<ARRAY_SIZE; i++) { //--- Get the new color clr=GetRandomColor(); //--- Set the border color ObjectSetInteger(0,sound_names[i],OBJPROP_BGCOLOR,clr); //--- Set the background color ObjectSetInteger(0,sound_names[i],OBJPROP_BORDER_COLOR,clr); //--- Unclicked button ObjectSetInteger(0,sound_names[i],OBJPROP_STATE,false); //--- Refresh the chart ChartRedraw(0); //--- Wait for 20 ms (lag) Sleep(20); } }
Und zu guter Letzt muss der folgende Code zur Funktion OnChartEvent() hinzugefügt werden:
//+------------------------------------------------------------------+ //| Event handler | //+------------------------------------------------------------------+ void OnChartEvent(const int id, // Event identifier const long& lparam, // Parameter of the event of type long const double& dparam, // Parameter of the event of type double const string& sparam) // Parameter of the event of type string { //--- If there was an event of left-clicking on the object if(id==CHARTEVENT_OBJECT_CLICK) { //--- If the object name contains "sound_button" if(StringFind(sparam,"sound_button",0)>=0) { //--- Play the sound based on the object name // 5019 - ERR_FILE_NOT_EXIST - The file does not exist if(!PlaySound(GetSoundPath(sparam))) Print("Error: ",GetLastError()); //--- Change colors of all buttons ChangeColorsOnSoundPanel(); } } }
Der markierte String im obigen Code bedeutet, dass der Ablageort der Sound-Datei mithilfe der benutzerdefinierten Funktion GetSoundPath() an die Funktion PlaySound() übergeben wird. Der Code der Funktion GetSoundPath() ist nachfolgend aufgeführt:
//+------------------------------------------------------------------+ //| Returning sound file location by the object name | //+------------------------------------------------------------------+ string GetSoundPath(string object_name) { //--- Iterate over all sound panel objects in a loop for(int i=0; i<ARRAY_SIZE; i++) { //--- If the name of the object clicked in the chart // matches one of those available on the panel, return the file location if(object_name==name_sound_object[i]) return(path_sound_object[i]); } //--- return(""); }
Nun ist alles fertig. Das Sound-Panel (das Programm kann aus den Anhängen dieses Beitrags heruntergeladen werden) wird eingerichtet, sobald der Expert Advisor an das Diagramm angehängt wird:
Abb. 2. Das Sound-Panel im Diagramm
Das Prinzip der Arbeit mit Sound-Dateien dürfte nun klar sein. Kehren wir zurück zu unserem Expert Advisor aus dem vorhergehenden Beitrag "Das MQL5-Kochbuch: Speichern der Optimierungsergebnisse eines Expert Advisors auf Basis bestimmter Kriterien" und entscheiden, welche Töne wir im Expert Advisor nutzen werden. Wir erstellen Resources.mqh und integrieren die Datei in die Hauptdatei des Expert Advisors.
//--- Include custom libraries #include "Include/Errors.mqh" #include "Include/Enums.mqh" #include "Include/Resources.mqh" #include "Include/TradeSignals.mqh" #include "Include/TradeFunctions.mqh" #include "Include/ToString.mqh" #include "Include/Auxiliary.mqh"
Wir wählen nun Dateien für die wichtigsten Handelsereignisse aus.
//--- Sound files #resource "\\Files\\Sounds\\AHOOGA.WAV" // Error #resource "\\Files\\Sounds\\CASHREG.WAV" // Position opening/position volume increase/pending order triggering #resource "\\Files\\Sounds\\WHOOSH.WAV" // Pending order/Stop Loss/Take Profit setting/modification #resource "\\Files\\Sounds\\VERYGOOD.WAV" // Position closing at profit #resource "\\Files\\Sounds\\DRIVEBY.WAV" // Position closing at loss //--- Sound file location string SoundError = "::Files\\Sounds\\AHOOGA.WAV"; string SoundOpenPosition = "::Files\\Sounds\\CASHREG.WAV"; string SoundAdjustOrder = "::Files\\Sounds\\WHOOSH.WAV"; string SoundCloseWithProfit= "::Files\\Sounds\\VERYGOOD.WAV"; string SoundCloseWithLoss = "::Files\\Sounds\\DRIVEBY.WAV";
Ich möchte auch erwähnen, dass Sie im Expert Advisor neben den als Ressourcen verwendeten Sound-Dateien auch Bilder im *.bmp-Format für das Interface, Textdateien und sogar Indikatoren speichern können. EAs für MetaTrader 5 werden jetzt als voll funktionsfähige Anwendungen betrachtet. Das ist sehr bequem, da Sie anstatt mehrerer Dateien nur eine übergeben müssen.
Also weiter. In den externen Parametern müssen wir den Parameter UseSound hinzufügen, um die Möglichkeit zu erhalten, Töne zu deaktivieren:
//--- External parameters of the Expert Advisor input int NumberOfBars =2; // Number of one-direction bars sinput double Lot =0.1; // Lot input double TakeProfit =100; // Take Profit input double StopLoss =50; // Stop Loss input double TrailingStop =10; // Trailing Stop input bool Reverse =true; // Position reversal sinput bool UseSound =true; // Sound notifications
In Include\Enums.mqh erstellen wir die Aufzählung ENUM_SOUNDS für Töne.
//--- Sounds enum ENUM_SOUNDS { SOUND_ERROR =0, // Error SOUND_OPEN_POSITION = 1, // Position opening/position volume increase/pending order triggering SOUND_ADJUST_ORDER = 2, // Stop Loss/Take Profit/pending order setting SOUND_CLOSE_WITH_PROFIT = 3, // Position closing at profit SOUND_CLOSE_WITH_LOSS = 4 // Position closing at loss };
Diese Identifikatoren werden für die benutzerdefinierte Funktion PlaySoundByID() benötigt.
//+------------------------------------------------------------------+ //| Playing sounds | //+------------------------------------------------------------------+ void PlaySoundByID(ENUM_SOUNDS id) { //--- If it is the real-time mode and sounds are enabled if(IsRealtime() && UseSound) { //--- Play the sound based on the identifier passed switch(id) { case SOUND_ERROR : PlaySound(SoundError); break; case SOUND_OPEN_POSITION : PlaySound(SoundOpenPosition); break; case SOUND_ADJUST_ORDER : PlaySound(SoundAdjustOrder); break; case SOUND_CLOSE_WITH_PROFIT : PlaySound(SoundCloseWithProfit); break; case SOUND_CLOSE_WITH_LOSS : PlaySound(SoundCloseWithLoss); break; } } }
Während Handelsoperationen, die durch den Expert Advisor durchgeführt werden, können Soundeffekte durch Aufrufen von PlaySoundByID() aus den entsprechenden Handelsfunktionen abgespielt werden. Sehen wir uns an, wie dies in der Funktion OpenPosition() umgesetzt wird:
//+------------------------------------------------------------------+ //| Opening a position | //+------------------------------------------------------------------+ void OpenPosition(double lot, ENUM_ORDER_TYPE order_type, double price, double sl, double tp, string comment) { //--- Set the magic number in the trading structure trade.SetExpertMagicNumber(0); //--- Set the slippage in points trade.SetDeviationInPoints(CorrectValueBySymbolDigits(10)); //--- The Instant Execution and Market Execution modes // *** Starting with build 803, Stop Loss and Take Profit *** // *** can be set upon opening a position in the SYMBOL_TRADE_EXECUTION_MARKET mode *** if(symb.execution_mode==SYMBOL_TRADE_EXECUTION_INSTANT || symb.execution_mode==SYMBOL_TRADE_EXECUTION_MARKET) { //--- If the position failed to open if(!trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,comment)) { //--- Play the error sound and print the relevant message PlaySoundByID(SOUND_ERROR); Print("Error opening the position: ",GetLastError()," - ",ErrorDescription(GetLastError())); } //--- Otherwise play the position opening sound else PlaySoundByID(SOUND_OPEN_POSITION); } }
Falls allerdings eine Position bei Stop Loss, Take Profit, manuell oder anderweitig geschlossen wird, muss dieses Ereignis in der Funktion OnTrade() überwacht werden. Dafür schreiben eine weitere Funktion, SoundNotification(), die die erforderlichen Prüfungen durchführt: Wenn die Historie der Abschlüsse einen neuen Abschluss mit dem Identifikator DEAL_ENTRY_OUT oder DEAL_ENTRY_INOUT für das aktuelle Symbol anzeigt (vollständige/teilweise Schließung der Position oder eine Umkehrung), prüft das Programm, ob dieser Abschluss einen Gewinn oder Verlust mit sich brachte, und spielt den jeweiligen Ton ab.
//+------------------------------------------------------------------+ //| Sound notification | //+------------------------------------------------------------------+ void SoundNotification() { //--- If it is the real-time mode and sounds are enabled if(IsRealtime() && UseSound) { ulong ticket =0; // Deal ticket int total =0; // Total deals static ulong last_ticket =0; // Last ticket prior to this check //--- Get the complete history if(!HistorySelect(0,TimeCurrent()+1000)) return; //--- Get the number of deals in the obtained list total=HistoryDealsTotal(); //--- In the obtained list, iterate over all deals from the last one to the first one for(int i=total-1; i>=0; i--) { //--- If the deal ticket by its position in the list has been obtained if((ticket=HistoryDealGetTicket(i))>0) { //--- get the symbol of the deal GetHistoryDealProperties(ticket,D_SYMBOL); //--- If the symbol of the deal and the current symbol are the same if(deal.symbol==_Symbol) { //--- get the direction of the deal GetHistoryDealProperties(ticket,D_ENTRY); //--- If it is position closing, volume decrease or reversal if(deal.entry==DEAL_ENTRY_OUT || deal.entry==DEAL_ENTRY_INOUT) { //--- If the ticket of the current deal from the list (the last deal for the symbol) is equal to the previous ticket // or this is the initialization of the ticket of the last deal if(ticket==last_ticket || last_ticket==0) { //--- Save the ticket and exit last_ticket=ticket; return; } //--- Get the result of the deal GetHistoryDealProperties(ticket,D_PROFIT); //--- In case of profit if(deal.profit>=0) { //--- Profit sound PlaySoundByID(SOUND_CLOSE_WITH_PROFIT); //--- Save the ticket number last_ticket=ticket; return; } //--- In case of loss if(deal.profit<0) { //--- Loss sound PlaySoundByID(SOUND_CLOSE_WITH_LOSS); //--- Save the ticket number last_ticket=ticket; return; } } } } } } }
Die Funktion SoundNotification() muss in den Funktionen OnInit() und OnTrade() platziert werden:
//+------------------------------------------------------------------+ //| Initialization | //+------------------------------------------------------------------+ int OnInit() { //--- Initialize the new bar CheckNewBar(); //--- Initialize tickets of the last deals for the symbol SoundNotification(); //--- Initialization completed successfully return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Monitoring trade events | //+------------------------------------------------------------------+ void OnTrade() { //--- Sound notification SoundNotification(); }
Der Signalton wurde ebenfalls am Ende der Funktion ModifyTrailingStop() beim Modifizieren der Trailing-Stop-Ebene hinzugefügt.
Fazit
Das ist alles. Alle Dateien für Testzwecke können aus den Anhängen dieses Beitrags heruntergeladen werden. Zum Thema Töne im Terminal möchte ich Ihre Aufmerksamkeit auf eine interessante Lösung lenken, die in der Code Base unter dem Namen CMIDI (von Integer) zur Verfügung steht: Sie ermöglicht Ihnen das Abspielen von MIDI-Dateien in MetaTrader 5. Viel Erfolg!
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/748
- 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.