Entwicklung eines plattformübergreifenden Expert Advisors zur Festlegung von StopLoss und TakeProfit basierend auf den Risikoeinstellungen.

2 August 2019, 08:30
Roman Klymenko
0
262

Einführung

Wie Sie wahrscheinlich wissen, wird die Einhaltung der Geldmanagement-Regeln für jeden Handel sehr empfohlen. Das bedeutet, dass es nicht empfohlen wird, an einem Handel teilzunehmen, bei dem mehr als N% der Einlage verloren gehen können.

N wird vom Händler gewählt. Um dieser Regel gerecht zu werden, sollte man den Wert des Handelsloses korrekt berechnen.

Bei relevanten Meisterkursen zeigen die Vortragenden in der Regel eine fertige Excel-Datei, die für jedes Symbol relevante Berechnungsformeln für die Losgrößen enthält. Und so erhalten sie den gewünschten Wert der Losgröße, indem sie ihren Wert für StopLoss "einfach eingeben".

Ist das wirklich so "einfach"? Die Berechnung der Losgröße kann eine Minute oder länger dauern. Wenn Sie also die Losgröße endgültig festlegen, kann sich der Preis sehr weit vom vorgesehenen Einstiegspunkt entfernen. Darüber hinaus erfordert dies von Ihnen die Durchführung zusätzlicher Operationen. Ein weiterer Nachteil dieser Methode ist, dass manuelle Berechnungen oft die Wahrscheinlichkeit erhöhen, einen Fehler zu machen.

Also versuchen wir, diesen Prozess wirklich einfach zu gestalten. Zu diesem Zweck erstellen wir einen Expert Advisor, der die Kurse der Eröffnung- und Stop-Loss im visuellen Modus festlegt. Basierend auf diesen Parametern und Ihrem Risikowert setzt die EA die entsprechende Losgröße fest und eröffnet eine Position in die entsprechende Richtung.

Definition der Aufgabe

Wir haben die erste Aufgabe skizziert.

Eine weitere Aufgabe, die von unserem Expert Advisor übernommen wird, ist die Festlegung eines Take-Profit-Preises basierend auf dem gewünschten TP/SL-Verhältnis.

Gerchik und andere erfolgreiche Händler empfehlen, einen Take-Profit zu verwenden, der mindestens dem Dreifachen Ihres Stop-Loss entspricht. Das heißt, wenn Sie einen Stop-Loss von 40 Punkten verwenden, dann sollte Take-Profit mindestens 120 Punkte betragen. Wenn es nicht viele Chancen für den Preis gibt, dieses Niveau zu erreichen, sollten Sie besser auf den Einstieg in den Handel verzichten.

Für eine komfortablere statistische Berechnung ist es wünschenswert, das gleiche SL/TP-Verhältnis zu verwenden. Eröffnen Sie beispielsweise Positionen mit einem TP/SL-Verhältnis von 3 zu 1, 4 zu 1 usw. ein. Sie sollten das spezifische Verhältnis für sich selbst wählen, basierend auf Ihren Handelszielen.

Die Frage ist die folgende: Wie platziert man Take-Profit, ohne Zeit zu verschwenden? Ist Excel wirklich die einzig mögliche Lösung? Oder sollten wir versuchen, die ungefähre Position auf dem Chart zu erraten?

Diese Möglichkeit wird in den Einstellungen des Expert Advisors implementiert. Für die Eingabe des Verhältnisses Take-Profit zu Stop-Loss wird ein spezieller Parameter bereitgestellt. Der Wert von 4 bedeutet zum Beispiel, dass das Verhältnis 4 zu 1 ist. Das EA setzt dann den Take-Profit, der dem Vierfachen des Stop-Loss Wertes entspricht.

Expert Advisor Format. Bevor wir mit der EA-Entwicklung fortfahren, müssen wir uns für die Funktionsweise entscheiden. Das ist wahrscheinlich die schwierigste Aufgabe.

Ich habe einen ähnlichen EA über mehr als ein Jahr verwendet. Seit seiner Entstehung hat sich der EA stark verändert.

In der ersten Version wurde nach dem Start des EAs ein Dialogfenster angezeigt, in dem jeder der neuen Parameter für die Positionsöffnung geändert werden konnte. Diese Einstellungen wurden automatisch gespeichert und bei weiteren EA-Starts verwendet. Und das war der Hauptvorteil dieser Methode. Sehr oft konfiguriert man die gewünschten Einstellungen einmalig und verwenden sie auch in Zukunft.

Das Dialogfenster mit den Einstellungen hat jedoch einen großen Nachteil: Es nimmt fast den gesamten Fensterbereich des Charts ein. Die Preisbewegung kann aufgrund dieses Fensters nicht verfolgt werden. Da das Dialogfenster nach der ersten Einrichtung nicht mehr verwendet wird, behindert das Fenster die Chartansicht, ohne einen Nutzen zu bieten.

Hier ist ein Beispiel für ein Chart und ein Dialogfenster mit der Breite von 640 Pixel:

Die Version des Expert Advisors mit Dialogfenster

Abb. 1. Die Version des Expert Advisors mit Dialogfenster

Wie Sie sehen können, passt das Fenster nicht einmal vollständig auf den Bildschirm.

Um dieses Problem zu lösen, habe ich 2 weitere EA-Versionen erstellt.

In der ersten Version war das Einstellungsfenster standardmäßig ausgeblendet und kann durch Klicken auf die Schaltfläche Einstellungen geöffnet werden. Dieses EA ist noch für MetaTrader 5 Market verfügbar.

Die zweite Version hat kein Einstellungsfenster. Alle EA-Einstellungen sind in den Eingabeparametern angegeben. Dadurch entfällt die Verwendung eines Dialogfensters. Dies ist jedoch verbunden mit den Problemen:

  • der Notwendigkeit, den EA bei jedem Start neu zu konfigurieren,
  • der Notwendigkeit, bei jedem Start die Einstellungen aus einer SET-Datei hochzuladen,
  • der Notwendigkeit, die Standardeinstellungen im EA-Code zu ändern und neu zu kompilieren.

Als Programmierer hoffe ich, dass Sie sich für die dritte Option entscheiden würden. In diesem Artikel werden wir einen vereinfachten Klon der zweiten EA-Version erstellen. So sehen die EA-Operation aus:

Version des Expert Advisors ohne Dialogfeld

Abb. 2. Die Version des Expert Advisors ohne Dialogfeld

Eingabeparameter

Für ein besseres Verständnis des gesamten Arbeitsumfangs schauen wir uns die EA-Eingangsparameter an:

Die Eingabeparameter des Expert Advisors

Abb. 3. Die Eingabeparameter des Expert Advisors

Die Handelsaktivität wird durch den Stop-Loss bestimmt. Lassen Sie uns daher auf die ersten beiden Parameter achten: " Stop Loss type" und " Stop Loss value in $ or %".

Der Wert ist standardmäßig in Dollar eingestellt, was im Parameter "Stop Loss type" angegeben ist. Der Stop-Loss kann auch als Prozentsatz Ihres Guthabens eingestellt werden. Wenn der Stop-Loss als Prozentsatz ausgewählt wird, darf der angegebene Wert 5% der Einlage nicht überschreiten. Dies geschieht, um Fehler bei der Einstellung der EA-Parameter zu vermeiden.

Der Parameter "Stop Loss value in $ or %" gibt den Betrag an, den Sie sich im Falle eines Stop-Loss leisten können.

Stop Loss value in cents (keys 7 and 8). Ein weiterer Parameter im Zusammenhang mit Stop-Loss ist: "Stop Loss value in cents (keys 7 and 8)".

Als nächstes implementieren wir einen Satz von Tastenkombinationen, mit denen wir den gewünschten Stop-Loss mit einem Klick einstellen können. Wenn Sie beispielsweise immer einen Stop-Loss von 7 Cent im Handel verwenden, brauchen Sie nur die Taste 7 auf der Tastatur zu drücken, und der Stop-Loss wird auf den angegebenen Abstand zum aktuellen Kurs gesetzt. Wir werden das später im Detail besprechen.

Bitte beachten Sie, dass dieser Parameter nicht den Betrag bestimmt, den Sie im Falle eines Stop-Loss verlieren, sondern die Entfernung zwischen dem Eröffnungspreis und dem Preis für die Auslösung von Stop-Loss.

No deal entry if with min. lot the risk is greater than specified. Da der Wert der Losgröße bei Handelseröffnung automatisch basierend auf dem Parameter " Stop Loss Value in $ oder %" berechnet wird, kann es zu einer Situation kommen, in der die minimal zulässige Losgröße zu einem Risiko pro Trade führen würde, das höher als der ermittelte Wert ist.

In diesem Fall können Sie einen Handel mit der Mindestlosgröße abschließen und das Risiko ignorieren, oder Sie können die Positionseröffnung stornieren. In diesem Parameter wird das entsprechende Verhalten definiert.

Standardmäßig verhindert der EA den Markteintritt, falls ein erhöhtes Risiko vorliegt.

Cancel limit order after, hours. Zusätzlich zum Markteintritt unterstützt der EA die Platzierung von Limit-Orders auf Basis des angegebenen Preises. Dieser Parameter ermöglicht die Bestimmung der Laufzeit.

Die Laufzeit wird in Stunden angegeben. Wenn beispielsweise die Laufzeit auf 2 Stunden festgelegt ist und der Limit-Order nicht innerhalb von 2 Stunden ausgelöst wird, wird eine solche Order gelöscht.

Tale Profit multiplier. Wenn Sie mit einem bestimmten Verhältnis von Take-Profit zu Stop-Loss handeln, können Sie mit diesem Parameter die automatische Einstellung Take-Profit gemäß Ihrer Regel konfigurieren.

Der Standardwert ist 4. Das bedeutet, dass der Take-Profit auf einen solchen Preis festgelegt wird, dass der Gewinn im Falle von Take-Profit das Vierfache des möglichen Verlustes beträgt.

Andere Parameter. Sie können auch:

  • die Magicnummer für die EA-Orders ändern,
  • einen Kommentar zu Orders schreiben
  • die Sprache der Benutzeroberfläche auswählen: Englisch oder Russisch (Standard)

Funktion zum Öffnen von Positionen

Da wir einen plattformübergreifenden Expert Advisor schreiben, sollte er sowohl in MetaTrader 4 als auch in MetaTrader 5 funktionieren. Unterschiedliche EA-Versionen haben jedoch unterschiedliche Funktionen zur Positionsöffnung. Um den Einsatz des EAs auf beiden Plattformen zu ermöglichen, werden wir die bedingte Kompilierung verwenden.

Ich habe diese Art der Kompilierung bereits in meinen Artikeln erwähnt. Zum Beispiel im Artikel Entwicklung eines plattformübergreifenden Griders-EAs.

Kurz gesagt, der bedingte Kompilierungscode lautet wie folgt:

#ifdef __MQL5__ 
   //MQL5 code
#else 
   //MQL4 code
#endif 

In diesem Artikel werden wir die Möglichkeiten der bedingten Kompilierung dreimal nutzen, wobei es sich um die Funktion der Positionsöffnung handelt. Der Rest des Codes funktioniert sowohl in MetaTrader 4 als auch in MetaTrader 5.

Die Positionseröffnungsfunktion wurde bereits im Artikel Entwicklung eines plattformübergreifenden Grid-EAs entwickelt. Lassen Sie uns daher eine fertige Lösung verwenden. Wir müssen die Funktionsweise zur Festlegung der Laufzeit der Limit-Order erweitern:

// Possible order types for the position opening function
enum TypeOfPos
  {
   MY_BUY,
   MY_SELL,
   MY_BUYSTOP,
   MY_BUYLIMIT,
   MY_SELLSTOP,
   MY_SELLLIMIT,
   MY_BUYSLTP,
   MY_SELLSLTP,
  }; 

// Selecting deal filling type for MT5
#ifdef __MQL5__ 
   enum TypeOfFilling //Deal filling type
     {
      FOK,//ORDER_FILLING_FOK
      RETURN,// ORDER_FILLING_RETURN
      IOC,//ORDER_FILLING_IOC
     }; 
   input TypeOfFilling  useORDER_FILLING_RETURN=FOK; //Order filling mode
#endif 


/*
Position opening or limit order placing function
*/
bool pdxSendOrder(TypeOfPos mytype, double price, double sl, double tp, double volume, ulong position=0, string comment="", string sym="", datetime expiration=0){
      if( !StringLen(sym) ){
         sym=_Symbol;
      }
      int curDigits=(int) SymbolInfoInteger(sym, SYMBOL_DIGITS);
      if(sl>0){
         sl=NormalizeDouble(sl,curDigits);
      }
      if(tp>0){
         tp=NormalizeDouble(tp,curDigits);
      }
      if(price>0){
         price=NormalizeDouble(price,curDigits);
      }else{
         #ifdef __MQL5__ 
         #else
            MqlTick latest_price;
            SymbolInfoTick(sym,latest_price);
            if( mytype == MY_SELL ){
               price=latest_price.ask;
            }else if( mytype == MY_BUY ){
               price=latest_price.bid;
            }
         #endif 
      }
   #ifdef __MQL5__ 
      ENUM_TRADE_REQUEST_ACTIONS action=TRADE_ACTION_DEAL;
      ENUM_ORDER_TYPE type=ORDER_TYPE_BUY;
      switch(mytype){
         case MY_BUY:
            action=TRADE_ACTION_DEAL;
            type=ORDER_TYPE_BUY;
            break;
         case MY_BUYSLTP:
            action=TRADE_ACTION_SLTP;
            type=ORDER_TYPE_BUY;
            break;
         case MY_BUYSTOP:
            action=TRADE_ACTION_PENDING;
            type=ORDER_TYPE_BUY_STOP;
            break;
         case MY_BUYLIMIT:
            action=TRADE_ACTION_PENDING;
            type=ORDER_TYPE_BUY_LIMIT;
            break;
         case MY_SELL:
            action=TRADE_ACTION_DEAL;
            type=ORDER_TYPE_SELL;
            break;
         case MY_SELLSLTP:
            action=TRADE_ACTION_SLTP;
            type=ORDER_TYPE_SELL;
            break;
         case MY_SELLSTOP:
            action=TRADE_ACTION_PENDING;
            type=ORDER_TYPE_SELL_STOP;
            break;
         case MY_SELLLIMIT:
            action=TRADE_ACTION_PENDING;
            type=ORDER_TYPE_SELL_LIMIT;
            break;
      }
      
      MqlTradeRequest mrequest;
      MqlTradeResult mresult;
      ZeroMemory(mrequest);
      
      mrequest.action = action;
      mrequest.sl = sl;
      mrequest.tp = tp;
      mrequest.symbol = sym;
      if(expiration>0){
         mrequest.type_time = ORDER_TIME_SPECIFIED_DAY;
         mrequest.expiration = expiration;
      }
      if(position>0){
         mrequest.position = position;
      }
      if(StringLen(comment)){
         mrequest.comment=comment;
      }
      if(action!=TRADE_ACTION_SLTP){
         if(price>0){
            mrequest.price = price;
         }
         if(volume>0){
            mrequest.volume = volume;
         }
         mrequest.type = type;
         mrequest.magic = EA_Magic;
         switch(useORDER_FILLING_RETURN){
            case FOK:
               mrequest.type_filling = ORDER_FILLING_FOK;
               break;
            case RETURN:
               mrequest.type_filling = ORDER_FILLING_RETURN;
               break;
            case IOC:
               mrequest.type_filling = ORDER_FILLING_IOC;
               break;
         }
         mrequest.deviation=100;
      }
      if(OrderSend(mrequest,mresult)){
         if(mresult.retcode==10009 || mresult.retcode==10008){
            if(action!=TRADE_ACTION_SLTP){
               switch(type){
                  case ORDER_TYPE_BUY:
//                     Alert("Order Buy #:",mresult.order," sl",sl," tp",tp," p",price," !!");
                     break;
                  case ORDER_TYPE_SELL:
//                     Alert("Order Sell #:",mresult.order," sl",sl," tp",tp," p",price," !!");
                     break;
               }
            }else{
//               Alert("Order Modify SL #:",mresult.order," sl",sl," tp",tp," !!");
            }
            return true;
         }else{
            msgErr(GetLastError(), mresult.retcode);
         }
      }
   #else 
      int type=OP_BUY;
      switch(mytype){
         case MY_BUY:
            type=OP_BUY;
            break;
         case MY_BUYSTOP:
            type=OP_BUYSTOP;
            break;
         case MY_BUYLIMIT:
            type=OP_BUYLIMIT;
            break;
         case MY_SELL:
            type=OP_SELL;
            break;
         case MY_SELLSTOP:
            type=OP_SELLSTOP;
            break;
         case MY_SELLLIMIT:
            type=OP_SELLLIMIT;
            break;
      }
      
      if(OrderSend(sym, type, volume, price, 100, sl, tp, comment, EA_Magic, expiration)<0){
            msgErr(GetLastError());
      }else{
         switch(type){
            case OP_BUY:
               Alert("Order Buy sl",sl," tp",tp," p",price," !!");
               break;
            case OP_SELL:
               Alert("Order Sell sl",sl," tp",tp," p",price," !!");
               break;
            }
            return true;
      }
   
   #endif 
   return false;
}

In MetaTrader 5 sollte beim Öffnen einer Position die Art der Positionsfüllung gewählt werden. Fügen wir daher einen weiteren Eingabeparameter für MetaTrader 5 hinzu: " Order fill mode".

Verschiedene Broker unterstützen unterschiedliche Orderausführungsarten. Die beliebteste unter den Brokern ist ORDER_FILLING_FOK. Daher ist es standardmäßig ausgewählt. Wenn Ihr Broker diesen Modus nicht unterstützt, können Sie einen anderen gewünschten Modus auswählen.

EA-Lokalisierung

Ein weiterer Mechanismus, der zuvor unter Entwicklung eines plattformübergreifenden Grid-EAs beschrieben wurde, ist die Möglichkeit, Textnachrichten zu lokalisieren, die vom Expert Advisor erstellt wurden. Deshalb werden wir es nicht noch einmal berücksichtigen. Bitte lesen Sie den genannten Artikel für weitere Details zur Funktionsweise des EAs.

Programmierung der EA-Schnittstelle

In diesem Artikel werden wir die EA-Entwicklung nicht von Grund auf neu betrachten. Es wird auch davon ausgegangen, dass der Leser mindestens über die Grundkenntnisse in MQL verfügt.

In diesem Artikel werden wir uns ansehen, wie die wichtigsten EA-Teile implementiert sind. Dies hilft Ihnen, bei Bedarf zusätzliche Funktionen zu implementieren.

Beginnen wir mit der EA-Schnittstelle.

Die folgenden Oberflächenelemente werden beim EA-Start erstellt:

  • Ein Kommentar enthält den aktuellen Spread in Dollar, Punkten und Prozent des Preises sowie das Ende der Handelszeiten des Symbols;
  • wird eine horizontale Linie in der Spreizdistanz zum aktuellen Preis angezeigt, mit der der Stop-Loss platziert wird;
  • Die Schaltfläche "Show (0) open price line" wird hinzugefügt, der eine grüne horizontale Linie zum Eröffnungspreis der Order anzeigt;
  • eine weitere Schaltfläche wird benötigt, um eine Order mit den angegebenen Parameterwerten zu öffnen.

Um also eine Order mit den benötigten Parametern (die über die EA-Eingänge eingestellt werden) zu erstellen, ist es notwendig, die rote Linie auf den Preis zu verschieben, zu dem der Stop-Loss gesetzt werden soll.

Wird die rote Linie über den aktuellen Kurs bewegt, wird eine Short-Position eröffnet. Wird die rote Linie unter den aktuellen Kurs bewegt, wird eine Long-Position eröffnet.

Das Volumen der offenen Position wird automatisch berechnet, so dass wir im Falle eines Stop-Loss den Betrag verlieren würden, der dem in den EA-Parametern angegebenen Betrag entspricht. Alles, was wir tun müssen, ist, auf die Schaltfläche zum Öffnen der Position zu klicken. Danach wird eine Position zum Marktpreis eröffnet.

Wenn Sie eine Limit-Order platzieren möchten, sollten Sie zusätzlich auf "Show (0) open price line" klicken und die erscheinende grüne Linie auf den Preis verschieben, zu dem Sie eine Limit-Order eröffnen möchten. Die Art und Richtung der Limit-Order wird automatisch basierend auf den Positionen der Linien von Stop-Loss und Take-Profit bestimmt (d.h. Stop-Loss liegt über oder unter dem Eröffnungskurs).

Grundsätzlich ist es nicht notwendig, auf die Schaltfläche "Show (0) open price line" zu klicken. Sobald wir die rote Stop-Loss-Linie auf das gewünschte Niveau gebracht haben, wird die Schaltfläche automatisch gedrückt und eine grüne Linie auf dem Eröffnungspreis erscheint. Wenn wir diese Linie verschieben, setzt das eine Limit-Order. Wenn Sie die Linie dort belassen, wo sie ist, wird eine Marktposition eröffnet.

Wir haben das Funktionsprinzip analysiert. Nun können wir zur Programmierung übergehen.

Working with the chart comment. Die Standardfunktion Comment wird für die Arbeit mit Chart-Kommentaren verwendet. Daher müssen wir eine Zeichenkette vorbereiten, die über die Funktion Comment auf dem Chart angezeigt wird. Zu diesem Zweck erstellen wir eine benutzerdefinierte Funktion getmespread:

/*
   Showing data on spread and session closing time in a chart comment
*/
void getmespread(){
   string msg="";
   
   // Get spread in the symbol currency
   curSpread=lastme.ask-lastme.bid;
   
   // If the market is not closed, show spread info
   if( !isClosed ){
      if(curSpread>0){
         StringAdd(msg, langs.Label1_spread+": "+(string) DoubleToString(curSpread, (int) SymbolInfoInteger(_Symbol, SYMBOL_DIGITS))+" "+currencyS+" ("+DoubleToString(curSpread/curPoint, 0)+langs.lbl_point+")");
         StringAdd(msg, "; "+DoubleToString(((curSpread)/lastme.bid)*100, 3)+"%");
      }else{
         StringAdd(msg, langs.Label1_spread+": "+langs.lblNo);
      }
      StringAdd(msg, "; ");
   }
   
   // Show market closing time if we could determine it
   if(StringLen(time_info)){
      StringAdd(msg, "   "+time_info);
   }
      
   Comment(msg);
}

Die Funktion getmespread wird während der EA-Initialisierung (OnInit) und bei jedem neuen Tick (OnTick) aufgerufen.

In getmespread verwenden wir fünf globale EA-Variablen: lastme, isClosed, time_info, currencyS, curPoint.

Die Variable lastme speichert Daten zu den Preisen Ask, Bid und Last. Der Variableninhalt wird in den Funktionen OnInit und OnTick mit dem folgenden Befehl aktualisiert:

SymbolInfoTick(_Symbol,lastme);

Andere Variablen werden in der OnInit-Funktion initialisiert. isClosed und time_info werden wie folgt initialisiert:

  isClosed=false;
  // Get the current date
  TimeToStruct(TimeCurrent(), curDay);
  // Get symbol trading time for today
  if(SymbolInfoSessionTrade(_Symbol, (ENUM_DAY_OF_WEEK) curDay.day_of_week, 0, dfrom, dto)){
      time_info="";
      TimeToStruct(dto, curEndTime);
      TimeToStruct(dfrom, curStartTime);
         
         isEndTime=true;
         string tmpmsg="";
         tmp_val=curEndTime.hour;
         if(tmp_val<10){
            StringAdd(tmpmsg, "0");
         }
         StringAdd(tmpmsg, (string) tmp_val+":");
         tmp_val=curEndTime.min;
         if(tmp_val<10){
            StringAdd(tmpmsg, "0");
         }
         StringAdd(tmpmsg, (string) tmp_val);
         if(curEndTime.hour==curDay.hour){
            if(tmp_val>curDay.min){
            }else{
               isClosed=true;
            }
         }else{
            if(curEndTime.hour==0){
            }else{
               if( curEndTime.hour>1 && (curDay.hour>curEndTime.hour || curDay.hour==0)){
                  StringAdd(time_info, " ("+langs.lbl_close+")");
                  isClosed=true;
               }else if(curDay.hour<curStartTime.hour ){
                  StringAdd(time_info, " ("+langs.lbl_close+")");
                  isEndTime=false;
                  isClosed=true;
               }else if(curDay.hour==curStartTime.hour && curDay.min<curStartTime.min ){
                  StringAdd(time_info, " ("+langs.lbl_close+")");
                  isEndTime=false;
                  isClosed=true;
               }
            }
         }

         if(isEndTime){
            StringAdd(time_info, langs.lblshow_TIME+": "+tmpmsg+time_info);
         }else{
            StringAdd(time_info, langs.lblshow_TIME2+": "+tmpmsg+time_info);
         }
  }

Die Variable currencyS speichert die Währung, die für die Gewinnberechnung des aktuellen Finanzinstruments verwendet wird. Die Währung kann mit dem folgenden Befehl ermittelt werden:

currencyS=SymbolInfoString(_Symbol, SYMBOL_CURRENCY_PROFIT);

Die Punktgröße des Symbols wird in der Variablen curPoint gespeichert:

curPoint=SymbolInfoDouble(_Symbol, SYMBOL_POINT);

Stop Loss line. Beim Start des EAs wird nur eine Linie auf dem Chart angezeigt: die rote Linie für die Platzierung von Stop-Loss.

Ähnlich wie bei Schaltflächen wird die Linie in der Funktion OnInit gezeichnet. Bevor wir die Linie zeichnen, müssen wir prüfen, ob es bereits eine solche Linie auf dem Chart gibt. Wenn es eine Zeile gibt, legen wir keine neue Zeile und andere Oberflächenelemente an. Fügen wir stattdessen die folgenden Daten zu den globalen Variablen hinzu: den Preis des aktuellen Linienniveaus und den Preis der Linie des Eröffnungspreises (falls auf dem Chart vorhanden):

  // if there are Stop Loss and open price lines on the chart
  // add the appropriate prices to variables
  if(ObjectFind(0, exprefix+"_stop")>=0){
      draw_stop=ObjectGetDouble(0, exprefix+"_stop", OBJPROP_PRICE);
      if(ObjectFind(0, exprefix+"_open")>=0){
         draw_open=ObjectGetDouble(0, exprefix+"_open", OBJPROP_PRICE);
      }
  // otherwise create the entire Expert Advisor UI
  }else{
      draw_open=lastme.bid;
      draw_stop=draw_open-(SymbolInfoInteger(_Symbol, SYMBOL_SPREAD)*curPoint);
      ObjectCreate(0, exprefix+"_stop", OBJ_HLINE, 0, 0, draw_stop);
      ObjectSetInteger(0,exprefix+"_stop",OBJPROP_SELECTABLE,1);
      ObjectSetInteger(0,exprefix+"_stop",OBJPROP_SELECTED,1); 
      ObjectSetInteger(0,exprefix+"_stop",OBJPROP_STYLE,STYLE_DASHDOTDOT); 
      ObjectSetInteger(0,exprefix+"_stop",OBJPROP_ANCHOR,ANCHOR_TOP);

      // other UI elements
  }

Ist es generell möglich, dass ein Chart bereits UI-Elemente hat?

Wenn wir den Code, der beim Schließen des EAs alle erstellten Elemente der Benutzeroberfläche löscht, nicht implementieren, bleiben die entsprechenden Elemente definitiv auf dem Chart stehen. Selbst wenn dieser Code implementiert ist, kann ein Fehler im EA-Vorgang auftreten, wodurch der EA geschlossen wird, aber die erstellten Elemente auf dem Chart verbleiben. Überprüfen wir daher vor der Erstellung immer, ob ein solches Element im Chart vorhanden ist.

Deshalb haben wir eine rote Linie erstellt. Außerdem haben wir es so eingestellt, dass sie standardmäßig ausgewählt ist. Sie müssen also nicht auf die Zeile doppelklicken, um sie auszuwählen. Sie müssen sie nur auf den gewünschten Preis verschieben. Wenn man jedoch jetzt die rote Linie verschiebt, passiert nichts. Der Code, der die entsprechenden Aktionen durchführt, ist noch nicht implementiert.

Jede Interaktion mit den Oberflächenelementen wird in der Standardfunktion OnChartEvent durchgeführt. Das Verschieben von Oberflächenelementen erzeugt ein Ereignis mit der ID CHARTEVENT_OBJECT_DRAG. Um also Bewegung auf dem Chart zu implementieren, muss die Funktion OnChartEvent dieses Ereignis abfangen, prüfen, welches Element es aufgerufen hat, und, wenn das Element zum EA gehört, sollte der erforderliche Code ausgeführt werden:

void OnChartEvent(const int id,         // Ereignis-ID   
                  const long& lparam,   // Ereignisparameter vom Typ long
                  const double& dparam, // Ereignisparameter vom Typ double
                  const string& sparam) // Ereignisparameter vom Typ string
  { 
   switch(id){
      case CHARTEVENT_OBJECT_DRAG:
         if(sparam==exprefix+"_stop"){
            setstopbyline();
            showOpenLine();
            ObjectSetInteger(0,exprefix+"_openbtn",OBJPROP_STATE, true);
         }
         break;
   }
}

Nach dem Verschieben der roten Linie wird die Funktion setstopbyline gestartet, die sich den Stop-Loss-Level für die zukünftige Order merkt:

/*
"Remembers" the Stop Loss levels for the future order
*/
void setstopbyline(){
   // Receive the price in which the Stop Loss line is located
   double curprice=ObjectGetDouble(0, exprefix+"_stop", OBJPROP_PRICE);
   // If the price is different from the one in which the Stop Loss line was positioned at the EA launch,
   if(  curprice>0 && curprice != draw_stop ){
      double tmp_double=SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
      if( tmp_double>0 && tmp_double!=1 ){
         if(tmp_double<1){
            resval=DoubleToString(curprice/tmp_double, 8);
            if( StringFind(resval, ".00000000")>0 ){}else{
               curprice=MathFloor(curprice)+MathFloor((curprice-MathFloor(curprice))/tmp_double)*tmp_double;
            }
         }else{
            if( MathMod(curprice,tmp_double) ){
               curprice= MathFloor(curprice/tmp_double)*tmp_double;
            }
         }
      }
      draw_stop=STOPLOSS_PRICE=curprice;
                  
      updatebuttontext();
      ChartRedraw(0);
   }
}

Zusätzlich zur Funktion setstopbyline bewirkt das Verschieben der roten Linie das Erscheinen der offenen Preislinie auf dem Chart (die Funktion showOpenLine) und das Ändern des Schaltflächenstatus "Show (0) open price line".

Open line and button. Die Schaltfläche "Show (0) open price line" wird ebenfalls bei der EA-Initialisierung angelegt:

      if(ObjectFind(0, exprefix+"_openbtn")<0){
         ObjectCreate(0, exprefix+"_openbtn", OBJ_BUTTON, 0, 0, 0);
         ObjectSetInteger(0,exprefix+"_openbtn",OBJPROP_XDISTANCE,0); 
         ObjectSetInteger(0,exprefix+"_openbtn",OBJPROP_YDISTANCE,33); 
         ObjectSetString(0,exprefix+"_openbtn",OBJPROP_TEXT, langs.btnShowOpenLine); 
         ObjectSetInteger(0,exprefix+"_openbtn",OBJPROP_XSIZE,333); 
         ObjectSetInteger(0,exprefix+"_openbtn",OBJPROP_FONTSIZE, 8);
         ObjectSetInteger(0,exprefix+"_openbtn",OBJPROP_YSIZE,25); 
      }

Wie bereits erwähnt, wird jede Interaktion mit den Oberflächenelementen innerhalb der Standardfunktion OnChartEvent verarbeitet. Dazu gehört auch das Drücken von Tasten. Dafür ist das Ereignis mit der ID CHARTEVENT_OBJECT_CLICK verantwortlich. Wir müssen dieses Ereignis abfangen, die Ereignisquelle überprüfen und entsprechende Aktionen durchführen. Dazu fügen wir den zusätzlichen case im switch-Operator der Funktion OnChartEvent hinzu:

      case CHARTEVENT_OBJECT_CLICK:
         if (sparam==exprefix+"_openbtn"){
            updateOpenLine();
         }
         break;

Die Funktion updateOpenLine, die durch einen Klick auf den Button "Show (0) open price line" aufgerufen wird, ist ein kleiner Wrapper für den Hauptaufruf showOpenLine. Diese Funktion zeigt lediglich den Eröffnungspreis auf dem Chart an:

void showOpenLine(){
   if(ObjectFind(0, exprefix+"_open")<0){
      draw_open=lastme.bid;
      ObjectCreate(0, exprefix+"_open", OBJ_HLINE, 0, 0, draw_open);
      ObjectSetInteger(0,exprefix+"_open",OBJPROP_SELECTABLE,1);
      ObjectSetInteger(0,exprefix+"_open",OBJPROP_SELECTED,1); 
      ObjectSetInteger(0,exprefix+"_open",OBJPROP_STYLE,STYLE_DASHDOTDOT); 
      ObjectSetInteger(0,exprefix+"_open",OBJPROP_ANCHOR,ANCHOR_TOP); 
      ObjectSetInteger(0,exprefix+"_open",OBJPROP_COLOR,clrGreen);
   }
}

Nun müssen wir die Ereignisbehandlung wegen CHARTEVENT_OBJECT_DRAG neu schreiben, damit er auf die Bewegung der Stop-Loss-Linie und der Linie des Eröffnungspreises reagieren kann:

      case CHARTEVENT_OBJECT_DRAG:
         if(sparam==exprefix+"_stop"){
            setstopbyline();
            showOpenLine();
            ObjectSetInteger(0,exprefix+"_openbtn",OBJPROP_STATE, true);
         }else if(sparam==exprefix+"_open"){
               curprice=ObjectGetDouble(0, exprefix+"_open", OBJPROP_PRICE);
               if( curprice>0 && curprice != draw_open ){
                  double tmp_double=SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
                  if( tmp_double>0 && tmp_double!=1 ){
                     if(tmp_double<1){
                        resval=DoubleToString(curprice/tmp_double, 8);
                        if( StringFind(resval, ".00000000")>0 ){}else{
                           curprice=MathFloor(curprice)+MathFloor((curprice-MathFloor(curprice))/tmp_double)*tmp_double;
                        }
                     }else{
                        if( MathMod(curprice,tmp_double) ){
                           curprice= MathFloor(curprice/tmp_double)*tmp_double;
                        }
                     }
                  }
                  draw_open=open=OPEN_PRICE=curprice;
                  
                  updatebuttontext();
                  ObjectSetString(0,exprefix+"Edit3",OBJPROP_TEXT,0, (string) NormalizeDouble(draw_open, _Digits));
                  ChartRedraw(0);
               }
         }
         break;

Take Profit line. Zusätzlich zu den roten und grünen Linien müssen wir eine gestrichelte Linie implementieren. Sie erscheint, nachdem Sie die rote Stop-Loss-Linie auf das gewünschte Preisniveau gebracht haben. Die gestrichelte Linie zeigt den Preis des Take-Profit-Levels:

Die Linien von Stop-Loss, Eröffnungskurs und Take-Profit

Abb. 4. Die Linien von Stop-Loss, Eröffnungskurs und Take-Profit

Position open button. Die Schaltfläche "Position open button" wird ähnlich wie der Button "Show (0) open price line" dargestellt.

Das Ereignis CHARTEVENT_OBJECT_CLICK wird durch einen Klick auf diese Schaltfläche erzeugt. Die Verarbeitung dieses Ereignisses wurde früher besprochen. Durch Drücken der Schaltfläche "Position open button" wird die Funktion Startposition ausgeführt:

      case CHARTEVENT_OBJECT_CLICK:
         if (sparam==exprefix+"_send"){
            startPosition();
         }else if (sparam==exprefix+"_openbtn"){
            updateOpenLine();
         }
         break;

Löschen von Oberflächenelementen nach Abschluss des EA-Vorgangs. Vergessen wir nicht das ordnungsgemäße Löschen von Oberflächenelementen nach Abschluss des Vorgangs des Expert Advisors. Wenn wir dies nicht tun, werden alle Elemente auf dem Chart belassen.

Um alle Befehle während des EA-Vorgangs auszuführen, fügen wir sie innerhalb der Standardfunktion OnDeinit hinzu:

void OnDeinit(const int reason)
  {

     if(reason!=REASON_CHARTCHANGE){
        ObjectsDeleteAll(0, exprefix);
        Comment("");
     }
      
  }

Die Variable reason (Ursache) enthält Informationen über die Gründe für den Abschluss des EA-Vorgangs. Nun ist der einzige wichtige Grund für uns die Änderung des Zeitrahmens ( REASON_CHARTCHANGE). Standardmäßig führt eine Änderung des Zeitrahmens dazu, dass der EA-Betrieb abgeschlossen und neu gestartet wird. Dies ist kein akzeptables Verhalten für uns. Im Falle einer Änderung des Zeitrahmens werden alle eingestellten Stop-Loss- und Eröffnungspreis-Levels zurückgesetzt.

Daher sollten wir in OnDeinit prüfen, ob der Grund für den EA-Abschluss die Zeitrahmenänderung ist. Und nur wenn der Grund für das Schließen ein anderer ist, sollten wir alle Elemente löschen und den Kommentar im Chart löschen.

Implementierung von Shortcuts für den Expert Advisor

Wir haben überlegt, die Order mit der Maus aufzugeben. Manchmal kann jedoch eine schnelle Bedienung über Tasten sehr nützlich sein.

Das Drücken von Tastaturtasten bezieht sich auch auf die Interaktion mit den Oberflächenelementen des Expert Advisors. Es bezieht sich nämlich auf den gesamte Chart, auf dem der EA läuft. Die Tastenanschläge sollten in der Funktion OnChartEvent abgefangen werden.

Das Ereignis CHARTEVENT_KEYDOWN wird beim Drücken einer Taste erzeugt. Der Code der gedrückten Taste wird dem Parameter sparam hinzugefügt. Diese Daten reichen aus, um die Verarbeitung des Tastendrucks zu starten:

void OnChartEvent(const int id,         // Ereignis-ID   
                  const long& lparam,   // Ereignisparameter vom Typ long
                  const double& dparam, // Ereignisparameter vom Typ double
                  const string& sparam) // Ereignisparameter vom Typ string
  { 
   string text="";
   double curprice=0;
   switch(id){
      case CHARTEVENT_OBJECT_CLICK:
         // Pressing of buttons on the chart
         break;
      case CHARTEVENT_OBJECT_DRAG:
         // Moving lines
         break;
      case CHARTEVENT_KEYDOWN:
         switch((int) sparam){
            // Terminate EA operation without placing an order
            case 45: //x
               closeNotSave();
               break;
            // Place an order and complete EA operation
            case 31: //s
               startPosition();
               break;
            // Set minimum possible Stop Loss to open a Buy position
            case 22: //u
               setMinStopBuy();
               break;
            // Set minimum possible Stop Loss to open a Sell position
            case 38: //l
               setMinStopSell();
               break;
            // Cancel the set open price
            case 44: //z
               setZero();
               ChartRedraw();
               break;
            // Set Stop Loss at 0.2% from the current price to open a Long position
            case 3: //2
               set02StopBuy();
               break;
            // Set Stop Loss at 0.2% from the current price to open a Short position
            case 4: //3
               set02StopSell();
               break;
            // Set Stop Loss to 7 cents from the current price (the CENT_STOP parameter)
            // To open a Long position
            case 8: //7
               set7StopBuy();
               break;
            // Set Stop Loss to 7 cents from the current price (the CENT_STOP parameter)
            // To open a Short position
            case 9: //8
               set7StopSell();
               break;
         }
         break;
   }
}

Wenn wir also einen festen Stop-Loss in Höhe der minimal möglichen Größe, d.h. 0,2% oder in Cent, einstellen, dann müssen wir nicht einmal die Maus benutzen. Wir starten den EA, drücken die Taste " 2", um den Stop-Loss auf 0,2% vom Preis einer Kaufposition einzustellen, drücken die Taste "S" und eine entsprechende Position wird eröffnet.

Und wenn Sie MetaTrader 5 verwenden, dann können Sie den EA sogar über die Tastatur starten, indem Sie zugewiesene Hotkeys verwenden. Rufen Sie im Fenster Navigator Ihr EA-Kontextmenü auf, klicken Sie auf Set Hotkey und genießen Sie den schnellen Zugriff:

Hotkeys für Expertenberater zuweisen

Abb. 5. Hotkeys für Expertenberater zuweisen

Berechnung des geeigneten Handelsvolumens

Betrachten wir nun die Funktion zum Öffnen der Position Startposition. Sie enthält fast nichts Interessantes. Wir überprüfen einfach die Verfügbarkeit aller benötigten Daten: Stop-Loss, Eröffnungspreis der Position und die EA-Einstellungen. Danach berechnet die EA den Wert des Eröffnungsloses gemäß Ihren Risikoeinstellungen. Dann wird die zuvor genannte Funktion pdxSendOrder aufgerufen.

Das interessanteste von allen ist der Mechanismus zur Berechnung des Handelsvolumens.

Erstens müssen wir den potenziellen Verlust im Falle eines Stop-Loss mit dem kleinstmöglichen Volumen berechnen. Diese Funktionsimplementierung in MQL5 unterscheidet sich von der in MQL4.

MQL5 verfügt über eine spezielle Funktion OrderCalcProfit, die es ermöglicht, die Größe des potenziellen Gewinns zu berechnen, der erzielt werden kann, wenn der Symbolpreis das angegebene Niveau erreicht. Diese Funktion ermöglicht es, sowohl den potenziellen Gewinn als auch den potenziellen Verlust zu berechnen.

In MQL4 wird eine kompliziertere Verlustberechnungsformel verwendet.

Hier ist die resultierende Funktion:

double getMyProfit(double fPrice, double fSL, double fLot, bool forLong=true){
   double fProfit=0;
   
   fPrice=NormalizeDouble(fPrice,_Digits);
   fSL=NormalizeDouble(fSL,_Digits);
   #ifdef __MQL5__ 
      if( forLong ){
         if(OrderCalcProfit(ORDER_TYPE_BUY, _Symbol, fLot, fPrice, fSL, fProfit)){};
      }else{
         if(OrderCalcProfit(ORDER_TYPE_SELL, _Symbol, fLot, fPrice, fSL, fProfit)){};
      }
   #else
      if( forLong ){
         fProfit=(fPrice-fSL)*fLot* (1 / MarketInfo(_Symbol, MODE_POINT)) * MarketInfo(_Symbol, MODE_TICKVALUE);
      }else{
         fProfit=(fSL-fPrice)*fLot* (1 / MarketInfo(_Symbol, MODE_POINT)) * MarketInfo(_Symbol, MODE_TICKVALUE);
      }
   #endif 
   if( fProfit!=0 ){
      fProfit=MathAbs(fProfit);
   }
   
   return fProfit;
}

Damit haben wir die Verlusthöhe mit dem Mindestvolumen berechnet. Nun müssen wir das Handelsvolumen bestimmen, ohne dass der Verlust die spezifizierten Risikoeinstellungen überschreitet:

      profit=getMyProfit(open, STOPLOSS_PRICE, lot);
      if( profit!=0 ){
         // If loss with the minimum lot is less than your risks,
         // calculate appropriate deal volume
         if( profit<stopin_value ){
            // get the desired deal volume
            lot*=(stopin_value/profit);
            // adjust the volume if it does not correspond to the minimum allowed step
            // for this trading instrument
            if( SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP)==0.01 ){
               lot=(floor(lot*100))/100;
            }else if( SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP)==0.1 ){
               lot=(floor(lot*10))/10;
            }else{
               lot=floor(lot);
            }
         // If loss with the minimum lot is greater than your risks,
         // cancel position opening if this option is set in EA parameters
         }else if( profit>stopin_value && EXIT_IF_MORE ){
            Alert(langs.wrnEXIT_IF_MORE1+": "+(string) lot+" "+langs.wrnEXIT_IF_MORE2+": "+(string) profit+" "+AccountInfoString(ACCOUNT_CURRENCY)+" ("+(string) stopin_value+" "+AccountInfoString(ACCOUNT_CURRENCY)+")!");
            return;
         }
      }

Beschränkungen bei der Eröffnung

Der Expert Advisor überprüft bestimmte Bedingungen, um dann nicht zu handeln, wenn eine Eröffnung nicht erlaubt ist.

Beispielsweise prüft der EA bei der Initialisierung die minimal zulässige Losgröße für das aktuelle Symbol. Und wenn dieser Wert 0 ist, startet das EA nicht. Weil er nicht in der Lage sein wird, eine Position für ein solches Symbol zu öffnen:

   if(SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)==0){
      Alert(langs.wrnMinVolume);
      ExpertRemove();
   }

Er überprüft auch ob der Handel des Symbols erlaubt ist. Wenn er verboten ist oder nur das Schließen von zuvor eröffneten Positionen erlaubt ist, wird der EA nicht gestartet:

   if(SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE)==SYMBOL_TRADE_MODE_DISABLED || SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE)==SYMBOL_TRADE_MODE_CLOSEONLY ){
      Alert(langs.wrnOnlyClose);
      ExpertRemove();
   }

Beim Eröffnen einer Position überprüft der EA die Richtigkeit des Eröffnungspreises und des Stop-Loss-Levels. Wenn beispielsweise der Mindestabstand 0,25 beträgt und Ihr Stop-Loss aber auf 23,29 steht, wird der Broker Ihre Order nicht annehmen. Im Allgemeinen kann der EA den Preis automatisch auf einen geeigneten Wert anpassen (und der Stop-Loss wird auf 23,25 oder 23,5 gesetzt). Die Angabe eines ungültigen Preises ist daher nicht möglich. Es wird aber auch eine weitere Prüfung durchgeführt:

   if( SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE)>0 && SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE)!=1 ){
      resval=DoubleToString(STOPLOSS_PRICE/SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE), 8);
      if( StringFind(resval, ".00000000")>0 ){}else{
         Alert(langs.wrnSYMBOL_TRADE_TICK_SIZE+" "+(string) SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE)+"! "+langs.wrnSYMBOL_TRADE_TICK_SIZE_end);
         return;
      }
   }

Schlussfolgerungen

In diesem Artikel haben wir nur die grundlegenden Ordermöglichkeiten implementiert. Aber auch diese Möglichkeiten können für diejenigen, die Gerchik-Level oder andere Levels handeln, von großer Hilfe sein.

Ich hoffe, dass Sie dadurch die Verwendung von Excel-Tabellen vermeiden können. Dies wird Ihre Handelsgeschwindigkeit und Genauigkeit erhöhen. Und so kann Ihr Gewinn letztendlich wachsen.

Alle EA-Verbesserungen sind willkommen.

Wenn Sie nicht über genügend Programmierkenntnisse verfügen, aber eine bestimmte Funktionsweise benötigen, können Sie sich gerne an mich wenden. Dies kann jedoch eine gewisse Gebühr erfordern.

Bitte überprüfen Sie die Funktionsweise der erweiterten Versionen dieses Expert Advisors auf dem Markt:

Vielleicht ist Ihre gewünschte Funktionsweise bereits vorhanden.

Übersetzt aus dem Russischen von MetaQuotes Software Corp.
Originalartikel: https://www.mql5.com/ru/articles/6986

Beigefügte Dateien |
openWithRisk.ex5 (126.3 KB)
openWithRisk.ex4 (56.42 KB)
openWithRisk.mq5 (119.01 KB)
openWithRisk.mq4 (119.01 KB)
Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil IX): Kompatibilität mit MQL4 - Datenvorbereitung Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil IX): Kompatibilität mit MQL4 - Datenvorbereitung

In den vorherigen Artikeln haben wir begonnen, eine große plattformübergreifende Bibliothek zu erstellen, die die Entwicklung von Programmen für MetaTrader 5 und MetaTrader 4 Plattformen vereinfacht. Im achten Teil haben wir die Klasse zur Verfolgung von Ereignissen der Auftrags- und Positionsänderung implementiert. Hier werden wir die Bibliothek verbessern, indem wir die vollständige Kompatibilität mit MQL4 herstellen.

Entwicklung eines plattformübergreifenden Grider-EAs (Teil II): Kursspannenbasiertes Raster in Trendrichtung Entwicklung eines plattformübergreifenden Grider-EAs (Teil II): Kursspannenbasiertes Raster in Trendrichtung

In diesem Artikel werden wir einen Grider-EA für den Handel in einer Trendrichtung innerhalb einer Kursspanne entwickeln. Somit ist der EA vor allem für den Devisen- und Rohstoffmarkt geeignet. Nach den Tests zeigte unser Grider seit 2018 einen Gewinn. Leider gilt dies nicht für den Zeitraum 2014-2018.

Organisation einer Mailing-Kampagne mit den Google-Services Organisation einer Mailing-Kampagne mit den Google-Services

Ein Händler kann eine Mailing-Kampagne organisieren, um Geschäftsbeziehungen zu anderen Händlern, Abonnenten, Kunden oder Freunden zu pflegen. Außerdem kann es notwendig sein, Screenshots, Logs oder Berichte zu versenden. Dies sind vielleicht nicht die am häufigsten auftretenden Aufgaben, aber eine solche Möglichkeit ist eindeutig von Vorteil. Der Artikel beschäftigt sich mit der gleichzeitigen Nutzung mehrerer Google-Dienste, der Entwicklung einer geeigneten Assembly auf C# und der Integration mit MQL-Tools.

Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil X): Kompatibilität mit MQL4 - Ereignisse der Positionseröffnung und der Aktivierung von Pending-Orders Bibliothek für ein leichtes und schnelles Entwickeln vom Programmen für den MetaTrader (Teil X): Kompatibilität mit MQL4 - Ereignisse der Positionseröffnung und der Aktivierung von Pending-Orders

In den vorherigen Artikeln haben wir begonnen, eine große plattformübergreifende Bibliothek zu erstellen, die die Entwicklung von Programmen für MetaTrader 5 und MetaTrader 4 Plattformen vereinfacht. Im neunten Teil haben wir begonnen, die Bibliotheksklassen für die Arbeit mit MQL4 zu verbessern. Hier werden wir die Bibliothek weiter verbessern, um ihre volle Kompatibilität mit MQL4 zu gewährleisten.