English Русский 中文 Español 日本語 Português 한국어 Français Italiano Türkçe
Entwicklung eines Expert Advisor für den Handel von Grund auf

Entwicklung eines Expert Advisor für den Handel von Grund auf

MetaTrader 5Handel | 28 Februar 2022, 10:04
847 0
Daniel Jose
Daniel Jose

Einführung

Die Zahl der neuen Nutzer auf dem Finanzmarkt steigt. Viele von ihnen wissen vielleicht nicht einmal, wie das Auftragssystem funktioniert. Es gibt aber auch die Nutzer, die wirklich wissen wollen, was passiert. Sie versuchen zu verstehen, wie das Ganze funktioniert, um die Situation zu kontrollieren.

Natürlich bietet der MetaTrader 5 ein hohes Maß an Kontrolle über die Handelspositionen. Allerdings kann es für weniger erfahrene Nutzer ziemlich schwierig und riskant sein, Aufträge nur manuell zu erteilen. Wenn jemand mit Terminkontrakten handeln möchte und nur sehr wenig Zeit hat, um einen Auftrag zu erteilen, kann sich ein solcher Handel in einen Albtraum verwandeln, weil man alle Felder rechtzeitig und korrekt ausfüllen muss, was jedoch Zeit kostet, und so kann man gute Gelegenheiten verpassen oder sogar Geld verlieren, wenn etwas falsch ausgefüllt wird.

Wie wäre es nun, wenn wir einen Expert Advisor (EA, Handelsroboter) verwenden würden, um die Dinge zu vereinfachen? In diesem Fall können Sie einige Details angeben, z. B. den Hebel oder wie viel Sie sich leisten können, zu verlieren, und wie viel Sie verdienen möchten (in Geldwerten und nicht in nicht ganz klaren "Punkten" oder "Pips"). Verwenden Sie dann den Mauszeiger auf dem Chart, um anzuzeigen, wo Sie in den Markt einsteigen wollen, und geben Sie an, ob Sie kaufen oder verkaufen wollen...


Planung

Der schwierigste Teil bei der Erstellung von etwas ist es, herauszufinden, wie die Dinge funktionieren sollen. Die Idee sollte sehr klar formuliert werden, sodass wir nur den minimal erforderlichen Code erstellen müssen, denn je komplexer der zu erstellende Code ist, desto größer ist die Möglichkeit von Laufzeitfehlern. In diesem Sinne habe ich versucht, den Code recht einfach zu gestalten, aber dennoch das Maximum der Möglichkeiten von MetaTrader 5 zu nutzen. Die Plattform ist sehr zuverlässig, sie wird ständig getestet und daher kann es auf der Plattformseite keine Fehler geben.

Der Code wird OOP (objektorientierte Programmierung) verwendet. Dieser Ansatz ermöglicht die Isolierung des Codes und erleichtert seine Wartung und zukünftige Entwicklung, falls wir neue Funktionen hinzufügen und Verbesserungen vornehmen wollen.

Obwohl der in diesem Artikel besprochene EA für den Handel an der B3 (brasilianische Börse) und speziell für den Handel mit Futures (Mini Index und Mini Dollar) entwickelt wurde, kann er mit minimalen Änderungen auf alle Märkte erweitert werden. Um die Dinge zu vereinfachen und um die Handelsaktiva nicht aufzulisten oder zu überprüfen, werden wir die folgende Enumeration verwenden:

enum eTypeSymbolFast {WIN, WDO, OTHER};


Wenn Sie einen anderen Vermögenswert handeln möchten, der eine besondere Funktion verwendet, fügen Sie ihn der Enumeration hinzu. Dies erfordert ebenfalls kleine Änderungen im Code, aber mit der Aufzählung wird dies viel einfacher sein, da sie auch die Möglichkeit von Fehlern reduziert. Ein interessanter Teil des Codes ist die Funktion AdjustPrice:

   double AdjustPrice(const double arg)
     {
      double v0, v1;
      if(m_Infos.TypeSymbol == OTHER)
         return arg;
      v0 = (m_Infos.TypeSymbol == WDO ? round(arg * 10.0) : round(arg));
      v1 = fmod(round(v0), 5.0);
      v0 -= ((v1 != 0) || (v1 != 5) ? v1 : 0);
      return (m_Infos.TypeSymbol == WDO ? v0 / 10.0 : v0);
     };

Diese Funktion passt den im Preis zu verwendenden Wert an, um die Linien an genauen Punkten des Charts zu positionieren. Warum können wir nicht einfach eine Linie in den Chart einfügen? Das liegt daran, dass bei einigen Vermögenswerten bestimmte Abstände zwischen den Kursen bestehen. Bei WDO (Mini Dollar) beträgt dieser Schritt nur 0,5 Punkte. Bei WIN (Mini-Index) beträgt dieser Schritt 5 Punkte, und bei Aktien sind es 0,01 Punkte. Mit anderen Worten: Die Punktwerte sind für die verschiedenen Vermögenswerte unterschiedlich. Dadurch wird der Preis an den korrekten Tick-Wert angepasst, sodass ein korrekter Wert in der Order verwendet wird, andernfalls kann eine falsch ausgefüllte Order vom Server zurückgewiesen werden.

Ohne diese Funktion könnte es schwierig sein, die korrekten Werte zu ermitteln, die in einem Auftrag verwendet werden sollen. Somit besteht die Möglichkeit, dass der Server meldet, dass der Auftrag nicht korrekt ausgefüllt wurde, und seine Ausführung verhindert. Kommen wir nun zu der Funktion, die das Herzstück des Expert Advisors ist: CreateOrderPendent. Die Funktion ist wie folgt:

   ulong CreateOrderPendent(const bool IsBuy, const double Volume, const double Price, const double Take, const double Stop, const bool DayTrade = true)
     {
      double last = SymbolInfoDouble(m_szSymbol, SYMBOL_LAST);
      ZeroMemory(TradeRequest);
      ZeroMemory(TradeResult);
      TradeRequest.action        = TRADE_ACTION_PENDING;
      TradeRequest.symbol        = m_szSymbol;
      TradeRequest.volume        = Volume;
      TradeRequest.type          = (IsBuy ? (last >= Price ? ORDER_TYPE_BUY_LIMIT : ORDER_TYPE_BUY_STOP) : (last < Price ? ORDER_TYPE_SELL_LIMIT : ORDER_TYPE_SELL_STOP));
      TradeRequest.price         = NormalizeDouble(Price, m_Infos.nDigits);
      TradeRequest.sl            = NormalizeDouble(Stop, m_Infos.nDigits);
      TradeRequest.tp            = NormalizeDouble(Take, m_Infos.nDigits);
      TradeRequest.type_time     = (DayTrade ? ORDER_TIME_DAY : ORDER_TIME_GTC);
      TradeRequest.stoplimit     = 0;
      TradeRequest.expiration    = 0;
      TradeRequest.type_filling  = ORDER_FILLING_RETURN;
      TradeRequest.deviation     = 1000;
      TradeRequest.comment       = "Order Generated by Experts Advisor.";
      if(!OrderSend(TradeRequest, TradeResult))
        {
         MessageBox(StringFormat("Error Number: %d", TradeResult.retcode), "Nano EA");
         return 0;
        };
      return TradeResult.order;
     };

Diese Funktion ist sehr einfach und ist sicher gestaltet. Wir erstellen hier eine OCO-Auftrag (One Cancels the Other, einer storniert den anderen), die an den Handelsserver gesendet wird. Bitte beachten Sie, dass wir LIMIT oder STOP Aufträge, also schwebende Aufträge (engl. pending orders) verwenden. Der Grund dafür ist, dass diese Art von Aufträgen einfacher ist und ihre Ausführung auch bei plötzlichen Kursbewegungen garantiert ist.

Welcher Auftragstyp zu verwenden ist, hängt vom Ausführungspreis und dem aktuellen Kurs des Handelsinstruments ab sowie davon, ob Sie eine Kauf- oder Verkaufsposition eingehen. Dies wird in der folgenden Zeile umgesetzt:

TradeRequest.type = (IsBuy ? (last >= Price ? ORDER_TYPE_BUY_LIMIT : ORDER_TYPE_BUY_STOP) : (last < Price ? ORDER_TYPE_SELL_LIMIT : ORDER_TYPE_SELL_STOP));

Es ist auch möglich, eine CROSS ORDER zu erstellen, indem man ein Handelsinstrument in der folgenden Zeile angibt:

TradeRequest.symbol = m_szSymbol;

In diesem Fall müssen Sie jedoch auch etwas Code hinzufügen, um offene oder schwebende Aufträge über das CROSS ORDER-System abzuwickeln, da Sie einen "falschen" Chart haben werden. Lassen Sie uns ein Beispiel betrachten. Sie können sich auf dem vollständigen Index-Chart (IND) befinden und mit dem Mini-Index (WIN) handeln, aber MetaTrader 5 zeigt die offene oder schwebende WIN-Order nicht an, wenn Sie sie auf dem IND-Chart verwenden. Daher ist es notwendig, einen Code hinzuzufügen, um die Aufträge sichtbar zu machen. Dies kann durch das Lesen von Positionswerten und deren Darstellung als Linien im Chart geschehen. Dies ist sehr nützlich, wenn Sie handeln und den Handelsverlauf des Symbols verfolgen. Wenn Sie z.B. CROSS ORDER verwenden, können Sie WIN (Mini Index) auf dem WIN$-Chart (dem Mini Index History Chart) handeln.

Achten Sie bitte auf die folgenden Codezeilen:

      TradeRequest.price         = NormalizeDouble(Price, m_Infos.nDigits);
      TradeRequest.sl            = NormalizeDouble(Stop, m_Infos.nDigits);
      TradeRequest.tp            = NormalizeDouble(Take, m_Infos.nDigits);

Mit diesen 3 Zeilen werden die OCO-Order-Stop-Levels und der Preis für die Positionseröffnung erstellt. Wenn Sie mit kurzfristigen Aufträgen handeln, die nur wenige Sekunden dauern, ist es nicht ratsam, den Handel ohne OCO-Aufträge einzugehen, da die Volatilität dazu führen kann, dass der Preis von einem Punkt zum anderen springt, ohne eine klare Richtung zu haben. Wenn Sie OCO verwenden, kümmert sich der Handelsserver selbst um unsere Position. Der OCO-Auftrag wird wie folgt aussehen.

Im Bearbeitungsfenster sieht der gleiche Auftrag wie folgt aus:

Sobald Sie alle erforderlichen Felder ausgefüllt haben, wird der Server die Order verarbeiten. Sobald er entweder Max Profit oder Max Loss erreicht, schließt das System den Auftrag. Wenn Sie jedoch weder Max Profit noch Max Loss angeben, kann der Auftrag offen bleiben, bis ein anderes Ereignis eintritt. Wenn der Auftragstyp auf Day Trade (Tageshandel) eingestellt ist, schließt das System den Auftrag am Ende des Handelstages. Andernfalls bleibt die Position offen, bis Sie sie manuell schließen oder bis keine Mittel mehr vorhanden sind, um die Position offen zu halten.

Einige Expert Advisor-Systeme verwenden Aufträge zur Schließung von Positionen: Sobald eine Position geöffnet ist, wird ein entgegengesetzter Auftrag zur Schließung der Position zum angegebenen Zeitpunkt und mit demselben Volumen gesendet. In manchen Szenarien kann dies jedoch nicht funktionieren, denn wenn der Vermögenswert während der Sitzung aus irgendeinem Grund versteigert wird, kann der ausstehende Auftrag storniert werden und sollte ersetzt werden. Dies würde die EA-Operation verkomplizieren, da Sie Überprüfungen hinzufügen müssten, welche Aufträge aktiv sind und welche nicht, und wenn etwas falsch ist, würde der EA einen Auftrag nach dem anderen senden, ohne irgendwelche Kriterien.

   void Initilize(int nContracts, int FinanceTake, int FinanceStop, color cp, color ct, color cs, bool b1)
     {
      string sz0 = StringSubstr(m_szSymbol = _Symbol, 0, 3);
      double v1 = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE) / SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
      m_Infos.Id = ChartID();
      m_Infos.TypeSymbol = ((sz0 == "WDO") || (sz0 == "DOL") ? WDO : ((sz0 == "WIN") || (sz0 == "IND") ? WIN : OTHER));
      m_Infos.nDigits = (int) SymbolInfoInteger(m_szSymbol, SYMBOL_DIGITS);
      m_Infos.Volume = nContracts * (m_VolMinimal = SymbolInfoDouble(m_szSymbol, SYMBOL_VOLUME_MIN));
      m_Infos.TakeProfit = AdjustPrice(FinanceTake * v1 / m_Infos.Volume);
      m_Infos.StopLoss = AdjustPrice(FinanceStop * v1 / m_Infos.Volume);
      m_Infos.IsDayTrade = b1;
      CreateHLine(m_Infos.szHLinePrice, m_Infos.cPrice = cp);
      CreateHLine(m_Infos.szHLineTake, m_Infos.cTake = ct);
      CreateHLine(m_Infos.szHLineStop, m_Infos.cStop = cs);
      ChartSetInteger(m_Infos.Id, CHART_COLOR_VOLUME, m_Infos.cPrice);
      ChartSetInteger(m_Infos.Id, CHART_COLOR_STOP_LEVEL, m_Infos.cStop);
     };

Die obige Funktion ist für die Initiierung der vom Nutzer angegebenen EA-Daten zuständig - sie erstellt einen OCO-Auftrag. Wir müssen in dieser Routine nur die folgende Änderung vornehmen.

m_Infos.TypeSymbol = ((sz0 == "WDO") || (sz0 == "DOL") ? WDO : ((sz0 == "WIN") || (sz0 == "IND") ? WIN : OTHER));

Hier fügen wir den Handelssymboltyp zusätzlich zu den aktuellen hinzu, falls Sie etwas Bestimmtes benötigen.

      m_Infos.Volume = nContracts * (m_VolMinimal = SymbolInfoDouble(m_szSymbol, SYMBOL_VOLUME_MIN));
      m_Infos.TakeProfit = AdjustPrice(FinanceTake * v1 / m_Infos.Volume);
      m_Infos.StopLoss = AdjustPrice(FinanceStop * v1 / m_Infos.Volume);

Die drei obigen Zeilen nehmen die erforderlichen Anpassungen für die korrekte Ordererstellung vor. nContracts ist ein Leverage-Faktor, verwenden Sie Werte wie 1, 2, 3 usw. Mit anderen Worten, Sie brauchen das Mindestvolumen des Symbols, das gehandelt werden soll, nicht zu kennen. Sie müssen lediglich den Hebelfaktor für dieses Mindestvolumen angeben. Wenn das erforderliche Mindestvolumen beispielsweise 5 Kontrakte beträgt und Sie den Hebelfaktor 3 angeben, eröffnet das System einen Auftrag mit 15 Kontrakten. Die beiden anderen Zeilen setzen entsprechend Take Profit und Stop Loss, basierend auf den vom Nutzer angegebenen Parametern. Die Level werden mit dem Auftragsvolumen angepasst: wenn der Auftrag steigt, sinkt der Level und umgekehrt. Mit diesem Code müssen Sie keine Berechnungen anstellen, um eine Position zu erstellen - der EA berechnet alles selbst: Sie weisen den EA an, welches Finanzinstrument mit welchem Hebelfaktor gehandelt werden soll, wie viel Geld Sie verdienen wollen und bereit sind zu verlieren, und der EA wird eine entsprechende Order für Sie platzieren.

   inline void MoveTo(int X, int Y, uint Key)
     {
      int w = 0;
      datetime dt;
      bool bEClick, bKeyBuy, bKeySell;
      double take = 0, stop = 0, price;
      bEClick  = (Key & 0x01) == 0x01;    //Left mouse button click
      bKeyBuy  = (Key & 0x04) == 0x04;    //Pressed SHIFT
      bKeySell = (Key & 0x08) == 0x08;    //Pressed CTRL
      ChartXYToTimePrice(m_Infos.Id, X, Y, w, dt, price);
      ObjectMove(m_Infos.Id, m_Infos.szHLinePrice, 0, 0, price = (bKeyBuy != bKeySell ? AdjustPrice(price) : 0));
      ObjectMove(m_Infos.Id, m_Infos.szHLineTake, 0, 0, take = price + (m_Infos.TakeProfit * (bKeyBuy ? 1 : -1)));
      ObjectMove(m_Infos.Id, m_Infos.szHLineStop, 0, 0, stop = price + (m_Infos.StopLoss * (bKeyBuy ? -1 : 1)));
      if((bEClick) && (bKeyBuy != bKeySell))
         CreateOrderPendent(bKeyBuy, m_Infos.Volume, price, take, stop, m_Infos.IsDayTrade);
      ObjectSetInteger(m_Infos.Id, m_Infos.szHLinePrice, OBJPROP_COLOR, (bKeyBuy != bKeySell ? m_Infos.cPrice : clrNONE));
      ObjectSetInteger(m_Infos.Id, m_Infos.szHLineTake, OBJPROP_COLOR, (take > 0 ? m_Infos.cTake : clrNONE));
      ObjectSetInteger(m_Infos.Id, m_Infos.szHLineStop, OBJPROP_COLOR, (stop > 0 ? m_Infos.cStop : clrNONE));
     };

Der obige Code zeigt die zu erstellenden Aufträge an. Er verwendet die Mausbewegung, um zu zeigen, wo der Auftrag platziert werden soll. Sie möchten dem EA jedoch mitteilen, ob Sie kaufen (SHIFT drücken und halten) oder verkaufen (STRG drücken und halten) möchten. Sobald Sie auf die linke Maustaste klicken, wird an dieser Stelle ein schwebender Auftrag erstellt.

Wenn Sie weitere Daten benötigen, z. B. den Break-Even-Punkt (Gewinnschwelle), fügen Sie das entsprechende Objekt zum Code hinzu.

Jetzt haben wir einen ganzen EA, der funktioniert und OCO-Aufträge erstellen kann. Aber noch ist hier nicht alles perfekt...


Problem mit OCO-Aufträgen

OCO-Aufträge haben ein Problem, das nicht die Schuld des MetaTrader 5-Systems oder des Handelsservers ist. Es hängt mit der Volatilität selbst zusammen, die ständig auf dem Markt vorhanden ist. Theoretisch sollte sich der Preis linear und ohne Rückschläge bewegen, aber manchmal haben wir eine hohe Volatilität, die zu Lücken innerhalb einer Kerze führt. Wenn diese Lücken an dem Punkt auftreten, an dem sich der Preis der Stop-Loss- oder Take-Profit-Order befindet, werden diese Punkte nicht ausgelöst und die Position wird daher nicht geschlossen. Es kann auch vorkommen, dass, wenn der Nutzer diese Punkte verschiebt, der Preis außerhalb des Korridors liegt, der durch den Stop Loss und den Take Profit gebildet wird. In diesem Fall wird der Auftrag ebenfalls nicht geschlossen. Dies ist eine sehr gefährliche Situation, die nicht vorhersehbar ist. Als Programmierer müssen Sie einen entsprechenden Mechanismus vorsehen, um mögliche Schäden zu minimieren.

Um den Preis zu aktualisieren und zu versuchen, ihn innerhalb des Korridors zu halten, werden wir zwei Unterfunktionen verwenden. Die erste lautet wie folgt:

   void UpdatePosition(void)
     {
      for(int i0 = PositionsTotal() - 1; i0 >= 0; i0--)
         if(PositionGetSymbol(i0) == m_szSymbol)
           {
            m_Take      = PositionGetDouble(POSITION_TP);
            m_Stop      = PositionGetDouble(POSITION_SL);
            m_IsBuy     = PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY;
            m_Volume    = PositionGetDouble(POSITION_VOLUME);
            m_Ticket    = PositionGetInteger(POSITION_TICKET);
           }
     };

Sie wird in OnTrade aufgerufen - die Funktion, die von MetaTrader 5 bei jeder Positionsänderung aufgerufen wird. Das nächste Unterprogramm, das verwendet wird, wird von OnTick aufgerufen. Es prüft und stellt sicher, dass der Preis innerhalb des Korridors oder innerhalb der Grenzen der OCO-Order liegt. Sie sieht wie folgt aus:

   inline bool CheckPosition(const double price = 0, const int factor = 0)
     {
      double last;
      if(m_Ticket == 0)
         return false;
      last = SymbolInfoDouble(m_szSymbol, SYMBOL_LAST);
      if(m_IsBuy)
        {
         if((last > m_Take) || (last < m_Stop))
            return ClosePosition();
         if((price > 0) && (price >= last))
            return ClosePosition(factor);
        }
      else
        {
         if((last < m_Take) || (last > m_Stop))
            return ClosePosition();
         if((price > 0) && (price <= last))
            return ClosePosition(factor);
        }
      return false;
     };

Dieses Codefragment ist von entscheidender Bedeutung, da es bei jeder Tick-Änderung ausgeführt wird. Daher muss es so einfach wie möglich sein, damit die Berechnungen und Tests so effizient wie möglich durchgeführt werden. Bitte beachten Sie, dass wir, während wir den Preis innerhalb des Korridors halten, auch etwas Interessantes prüfen, das auf Wunsch entfernt werden kann. Ich werde diesen zusätzlichen Test im nächsten Abschnitt erläutern. Innerhalb dieser Unterfunktion haben wir den folgenden Funktionsaufruf:

   bool ClosePosition(const int arg = 0)
     {
      double v1 = arg * m_VolMinimal;
      if(!PositionSelectByTicket(m_Ticket))
         return false;
      ZeroMemory(TradeRequest);
      ZeroMemory(TradeResult);
      TradeRequest.action     = TRADE_ACTION_DEAL;
      TradeRequest.type       = (m_IsBuy ? ORDER_TYPE_SELL : ORDER_TYPE_BUY);
      TradeRequest.price      = SymbolInfoDouble(m_szSymbol, (m_IsBuy ? SYMBOL_BID : SYMBOL_ASK));
      TradeRequest.position   = m_Ticket;
      TradeRequest.symbol     = m_szSymbol;
      TradeRequest.volume     = ((v1 == 0) || (v1 > m_Volume) ? m_Volume : v1);
      TradeRequest.deviation  = 1000;
      if(!OrderSend(TradeRequest, TradeResult))
        {
         MessageBox(StringFormat("Error Number: %d", TradeResult.retcode), "Nano EA");
         return false;
        }
      else
         m_Ticket = 0;
      return true;
     };

Die Funktion schließt das angegebene Volumen und fungiert als ein Schutz. Vergessen Sie jedoch nicht, dass Sie verbunden sein müssen, da die Funktion im MetaTrader 5 Client-Terminal ausgeführt wird - wenn die Verbindung zum Server unterbrochen ist, ist diese Funktion völlig nutzlos.

Wenn wir uns die letzten beiden Codes ansehen, sehen wir, dass wir das gegebene Volumen an einem bestimmten Punkt beenden können. Auf diese Weise können wir entweder eine Teilschließung vornehmen oder unser Risiko reduzieren. Lassen Sie uns herausfinden, wie wir diese Funktion verwenden können.


Arbeiten mit Teilaufträgen


Teilaufträge sind etwas, das viele Händler mögen und nutzen. Der Expert Advisor ermöglicht das Arbeiten mit Teilschließungen, aber ich werde nicht zeigen, wie man einen solchen Code implementiert, da Teilaufträge Gegenstand eines separaten Problems sein sollten. Wenn Sie jedoch die Arbeit mit partiellen Schließungen implementieren möchten, rufen Sie einfach die Funktion CheckPosition auf und geben den Preis, zu dem die Order ausgeführt werden soll, sowie das Volumen an, während der EA den Rest erledigt.

Ich sage, dass Teilaufträge ein Sonderfall sind, weil sie sehr individuell sind und es schwierig ist, eine allgemeine Lösung zu finden, die alle zufrieden stellt. Die Verwendung eines dynamischen Arrays wäre hier nicht geeignet, wie Sie vielleicht vermuten - es wird für Daytrading nur funktionieren, wenn Sie den EA nicht schließen. Wenn Sie den EA aus irgendeinem Grund schließen müssen, wird die Array-Lösung nicht funktionieren. Sie müssen dann ein Speichermedium verwenden, bei dem die Datenformatierung davon abhängt, was Sie mit diesen Daten machen wollen.

Wie auch immer, Sie sollten partielle Schließungen mit Positionseröffnungsaufträgen so weit wie möglich vermeiden, da das Risiko, Kopfschmerzen zu bekommen, sehr groß ist. Lassen Sie mich das erklären: Nehmen wir an, Sie haben eine Kaufposition mit einem Hebel von 3 und möchten mit 2 einen Gewinn erzielen, während Sie immer noch eine Position mit einem Hebel von 1 haben. Dies kann durch den Verkauf von 2x Leverage erreicht werden. Wenn Ihr EA jedoch einen Markt-Verkaufsauftrag sendet, kann es passieren, dass die Volatilität dazu führt, dass der Preis steigt und Ihren Take Profit trifft, bevor der Verkaufsauftrag tatsächlich ausgeführt wird. In diesem Fall wird der EA eine neue Verkaufsposition in die unerwünschte Richtung eröffnen. Optional können Sie ein Verkaufslimit oder Verkaufsstopp senden, um die Position um den 2x-Hebel zu reduzieren. Dies könnte eine angemessene Lösung sein. Aber was ist, wenn ein weiterer Auftrag gesendet wird, bevor der Preis den Teilpunkt erreicht - Sie können eine sehr unangenehme Überraschung erleben: die offene Position wird gestoppt und wenig später wird der Auftrag wieder eröffnet und erhöht die Verluste. Wenn die Volatilität stärker wird, wird die Situation die gleiche sein, wie wir oben erwähnt haben.

Meiner Meinung nach ist die beste Option für die Erstellung von Teilaufträgen die Nachahmung des Versands von Aufträgen zum Marktpreis. Aber Sie sollten sehr vorsichtig sein, um das offene Volumen nicht zu überschreiten. In diesem EA habe ich es genau so gemacht. Wenn Sie möchten, können Sie auch andere Methoden für Teilschließungen implementieren.


Schlussfolgerung

Die Erstellung eines Expert Advisors für den Handel ist nicht so trivial, wie manche Leute denken. Im Vergleich zu einigen anderen Problemen, mit denen wir bei der Programmierung oft konfrontiert werden, ist es recht einfach, etwas zu erstellen, das stabil und zuverlässig genug ist, um Ihr Geld zu riskieren, was jedoch oft eine schwierige Aufgabe ist. In diesem Artikel habe ich einen Vorschlag gemacht, der denjenigen das Leben erleichtern kann, die mit dem MetaTrader 5 beginnen und nicht über die notwendigen Kenntnisse zur Programmierung eines EA verfügen. Dies ist ein guter Anfang, da dieser EA keine Orders eröffnet, sondern nur dabei hilft, Orders auf eine zuverlässigere Art und Weise zu eröffnen. Sobald die Order platziert ist, hat der EA nichts weiter zu tun, und der MetaTrader 5 beginnt weiter zu arbeiten, abgesehen von den oben erwähnten Codefragmenten.

Der in diesem Artikel vorgestellte Expert Advisor kann auf verschiedene Weise verbessert werden, um mit Parametersätzen zu arbeiten, aber dies würde mehr Code erfordern, der ihn unabhängiger von MetaTrader 5 machen würde.

Der große Erfolg dieses EA besteht darin, dass er den MetaTrader 5 selbst nutzt, um Aktionen auszuführen, die nicht in seinem Code enthalten sind, und deshalb ist er äußerst stabil und zuverlässig.





Übersetzt aus dem Portugiesischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/pt/articles/10085

Beigefügte Dateien |
EA_Nano_rvl_1.1.mq5 (23.44 KB)
Grafiken in der DoEasy-Bibliothek (Teil 92): Speicherklasse der grafischen Standardobjekte. Änderungsverlauf der Objekteigenschaften Grafiken in der DoEasy-Bibliothek (Teil 92): Speicherklasse der grafischen Standardobjekte. Änderungsverlauf der Objekteigenschaften
In diesem Artikel werde ich die Speicherklasse der grafischen Standardobjekte erstellen, die es dem Objekt ermöglicht, seine Zustände zu speichern, wenn seine Eigenschaften geändert werden. Dies wiederum ermöglicht den Rücksprung zu vorherigen Zuständen des grafischen Objekts.
Eine Analyse der Gründe für das Scheitern von Expert Advisors Eine Analyse der Gründe für das Scheitern von Expert Advisors
Dieser Artikel stellt eine Analyse von Währungsdaten vor, um besser zu verstehen, warum Expert Advisors in einigen Zeiträumen eine gute und in anderen Zeiträumen eine schlechte Performance aufweisen können.
Visuelle Auswertung der Optimierungsergebnisse Visuelle Auswertung der Optimierungsergebnisse
In diesem Artikel geht es um die Erstellung von Diagrammen aller Optimierungsdurchläufe und um die Auswahl des optimalen nutzerdefinierten Kriteriums. Wir werden auch sehen, wie man eine gewünschte Lösung mit wenig MQL5-Kenntnissen erstellen kann, indem man die auf der Website veröffentlichten Artikel und Forumskommentare verwendet.
Lernen Sie, wie man ein Handelssystem mit Hilfe der Bollinger Bänder entwickelt Lernen Sie, wie man ein Handelssystem mit Hilfe der Bollinger Bänder entwickelt
In diesem Artikel lernen wir die Bollinger Bänder kennen, einen der beliebtesten Indikatoren in der Handelswelt. Wir werden die technische Analyse betrachten und sehen, wie man ein algorithmisches Handelssystem auf der Grundlage des Bollinger Bänder Indikators entwickelt.