English Русский 中文 Español 日本語 Português
Cross-Plattform Expert Advisor: Stopps

Cross-Plattform Expert Advisor: Stopps

MetaTrader 5Beispiele | 12 Oktober 2017, 09:22
647 0
Enrico Lambino
Enrico Lambino

Inhaltsverzeichnis

  1. Einführung
  2. COrder
  3. CStop
  4. CStops
  5. COrderStop
  6. COrderStops
  7. Darstellung der Stopps auf dem Chart
  8. Prüfen der Stopps einer Position
  9. Beispiele
  10. Schlussfolgerung
  11. Die Programme dieses Artikels
  12. Die Dateien der Klassen dieses Artikels


Einführung

Wie in einem vorherigen Artikel besprochen, haben wir für einen plattformübergreifenden Experten Advisor eine Positionsverwaltung (COrderManager) erstellt, der die meisten Unterschiede zwischen MQL4 und MQL5 in Bezug auf den Ein- und Ausstieg von Positionen berücksichtigt. In beiden Versionen speichert der Expert Advisor die Informationen der Positionen im Speicher, indem er Instanzen von COrder erstellt. Die Container mit den dynamischen Pointern auf die Instanzen dieses Klassenobjekts stehen auch als Mitglieder der Klasse COrderManager (für aktuelle und historische Positionen) zur Verfügung.

Es ist möglich, dass die Positionsverwaltung die Stopps einer jeden Position direkt kontrolliert. Dies würde allerdings gewisse Einschränkungen mit sich bringen:

  • Wahrscheinlich müsste COrderManager erweitert werden, um die Handhabung der Stopps für jeden Position anzupassen.
  • Die existierenden Methoden des COrderManager befassen sich nur mit der Eröffnung der Hauptpositionen.

Der COrderManager könnte erweitert werden, so dass er die Stopps für jede Position einzeln handhabt. Dies beschränkt sich jedoch nicht nur auf die Platzierung der tatsächlichen Stopps, sondern auch andere Aufgaben im Zusammenhang mit der Kontrolle dieser Stopps, wie z. B. die Modifizierung und Überprüfung, ob der Markt bereits ein bestimmtes Preisniveau erreicht hat. Diese Funktionen würden COrderManager wesentlich komplexer machen, als er es derzeit ist, ganz zu schweigen von der zweifachen Implementierung.

Der Order-Manager beschäftigt sich nur mit der Eröffnung der Hauptpositionen, während einige Stopps den EA dazu verpflichten würden, andere Handelsoperationen durchzuführen, wie z. B. die Platzierung von Pending-Orders und das Schließen offener Positionen. Es wäre zwar möglich, dass der Order-Manager die Hauptpositionen selbstständig abwickeln kann, aber am besten sollte er sich aber auf die Eröffnung von Hauptpositionen konzentrieren und einem anderen Klassenobjekt die Stopps überlassen.

In diesem Artikel werden wir die Implementierung besprechen, bei der COrderManager (wie es derzeit der Fall ist) ausschließlich den Ein- und Ausstieg von Hauptpositionen handhabt, und die Stopps separat durch ein anderes Klassenobjekt (CStop) bearbeitet werden.

COrder

Wie wir aus einem früheren Artikel (siehe Cross-Plattform Expert Advisor: Orders) lesen konnten, wird nach erfolgreicher Positionseröffnung (entry) eine Instanz von COrder angelegt. Sowohl für MetaTrader 4 als auch für MetaTrader 5 können die Informationen über Stoploss und Takeprofit auf Seiten des Brokers gespeichert werden. Sollten die Stopps jedoch vor dem Broker verborgen bleiben oder mehrere Stopps involviert sein, sollten die Informationen über die meisten Stopps lokal gespeichert werden. Im letzteren Fall sollte also nach erfolgreicher Eröffnung einer Position zunächst die Instanz von COrder angelegt werden, gefolgt von einer neuen Instanz des Objektes mit deren verschiedenen Stoploss und Takeprofits. In einem früheren Artikel haben wir gezeigt, wie die Instanz von COrder beim Anlegen dem Order-Manager hinzugefügt werden, wie es auch die folgenden Abbildung zeigt:


Positionseröffnung

Die Stopps werden in gleicher Weise hinzugefügt. Dafür müssen wir nur eine neue Methode nach dem Erstellen der Instanz von COrder einfügen, und bevor sie in die Liste der offenen Positionen (COrders) eingetragen wird. Deshalb müssen wir die obige Abbildung nur geringfügig ändern, wie die folgende Abbildung zeigt:


Positionseröffnung - mit Stopps

Der allgemeine Vorgang des Erstellen eines Stopps zeigt das folgende Bild:

Der allgemeine Vorgang des Erstellen eines Stopps

Wie oben, in den beiden vorherigen Flussdiagrammen zu sehen ist, wird, sobald eine Position erfolgreich eröffnet wurde, eine neue Instanz von COrder angelegt, die diese repräsentiert. Danach werden die Instanzen COrderStop für jeden angegebenen Stoploss und jeden Takeprofit. Falls während der Initialisierung des Expert Advisors keine Instanz CStop deklariert wurde, wird dieser besondere Vorgang übersprungen. Wurden hingegen Instanzen von COrderStop erstellt, werden die Pointer auf diese Instanzen von dem vorher erstellten Objekt COrder gespeichert. Wir finden diesen Vorgang in der Methode Init() von COrder:

bool COrderBase::Init(COrders *orders,CStops *stops)
  {
   if(CheckPointer(orders))
      SetContainer(GetPointer(orders));
   if(CheckPointer(stops))
      CreateStops(GetPointer(stops));
   m_order_stops.SetContainer(GetPointer(this));
   return true;
  }

Beim Erstellen der Stopps für die Instanz COrder können wir sehen, dass die Methode CreateStops() aufgerufen wird, wie man unten sieht:

void COrderBase::CreateStops(CStops *stops)
  {
   if(!CheckPointer(stops))
      return;
   if(stops.Total()>0)
     {
      for(int i=0;i<stops.Total();i++)
        {
         CStop *stop=stops.At(i);
         if(CheckPointer(stop)==POINTER_INVALID)
            continue;
         m_order_stops.NewOrderStop(GetPointer(this),stop);
        }
     }
  }
Die Methode iteriert über alle verfügbaren Instanzen von CStop, jeweils mit einem Paar von Stoploss und Takeprofit. Jede dieser Instanzen von CStop wird an eine Instanz von COrderStops übergeben, die einfach ein Container für alle Stopps einer Position ist. Damit können wir die Hierarchie der Klassenobjekte wie folgt aufbauen:


Hierarchie der Stopps

Für jede Instanz von COrder gibt es ein Mitglied des Typs COrderStops. Diese Instanz von COrderStops ist der Container (eine Erweiterung von CArrayObj), die die Pointer auf die Instanzen von COrderStop enthält. Jede Instanz von COrderStop steht für einen Stopp (CStop) für ausschließlich dieser spezifischen Position (Instanz von COrder).

CStop

Wie bereits erwähnt, möchten wir eine bestimmte Stufe der Freiheit in der Art haben, wie die Stopps von jeder Position behandelt werden, ohne den Quellcode des Order-Managers ändern zu müssen. Dies wird größtenteils durch die Klasse CStop erreicht. Folgendes sollte die Klasse leisten:

  1. Definieren der Stoploss und Takeprofits
  2. Durchführen der benötigten Berechnungen für die Stopps
  3. Implementieren der Stoploss und Takeprofits der Hauptposition
  4. Prüfen, ob die Stopps erreicht wurden
  5. Ausgleichen der Unterschiede zwischen MQL4 und MQL5 bei der Implementierung der Stoploss und Takeprofits
  6. Definieren, wie die Stopps im Laufe der Zeit behandelt werden sollen (z. B. Breakeven, Trailing etc.)

Die Punkte 1-5 werden in diesem Artikel besprochen, während dem Punkt 6 ein eigener Artikel gewidmet sein wird.

Typen

In diesem Artikel werden drei Arten von Stopps behandelt:

  1. Brokerseitige Stopps – Stopps, die dem Broker zusammen mit dem Handelsauftrag übergeben werden
  2. Stopps als Pending-Orders – Stopps mittels Pending-Orders, die entweder teilweise oder ganz die jeweilige Position schließen (Metatrader 4, Metatrader 5 "hedging mode"), oder die Größe der Position vermindern (Metatrader 5 "netting mode").
  3. Virtuelle Stopps (Stealth Stop) – Stopps, die der Broker nicht kennt und die lokal durch den Expert Advisor verwaltet werden.

Im MetaTrader 4 sind die brokerseitigen Stopps, die Stoploss und Takeprofits, mit denen der Händler am meisten vertraut ist. Die sind die Preise oder Stopps, die zusammen mit der Handelsauftrag dem Broker geschickt werden. Der Metatrader 5 im "hedging mode" verwendet dieselbe Mechanik wie der Metatrader 4. Im "netting mode" andererseits wird eine Pending-Order als Stopp von CStop verwendet, da Stoploss und Takeprofit sich unterscheiden(angewendet auf die ganze Position des Symbols oder des Handelsinstrumentes).

Ein Stopp durch eine Pending-Order verwendet eben eine Pending-Order, um irgendwie einen brokerseitigen Stopp zu imitieren. Sobald eine Pending-Order ausgelöst wurde, wird der EA eine Handelsoperation ausführen (OrderCloseBy), um die bestehende Position durch das Volumen der gerade ausgelösten Pending-Order zu schließen. Dies gilt für die Metatrader 4 und Metatrader 5 im "hedging mode". Der Metatrader 5 im "netting mode" schließt einen Teil oder das ganze Volumen der offenen Position automatisch, da es je Symbol immer nur eine offene Position geben kann.

Hauptstopp

Der Hauptstopp ist der Stopp, der die ganze Position komplett schließt. Normalerweise ist dies der brokerseitige Stopp. Wenn brokerseitig entweder der Stoploss oder der Takeprofit ausgelöst werden, verschwindet die gesamte Position vom Markt, egal, ob der EA mit ihr weiterarbeiten wollte oder nicht. Wenn es jedoch mehrere Stopps gibt und keine brokerseitigen Stopps, wäre es womöglich eine schlechte Idee, wenn der EA entscheiden soll, welcher der Stopps der Hauptstopp ist. In diesem Falls muss der Programmierer entscheiden, welche Instanz von CStop der Hauptstopp sein soll. Das erweist sich für für manche Funktionen und Eigenschaften als besonders nützlich, die auf einem solchen Hauptstopp basieren, wie zum Beispiel das Geldmanagement. Da der Stoploss des Hauptstopps die gesamte Position schließt, repräsentiert er das maximale Risiko der Position. Und die Kenntnis über diese Situation erlaubt dem EA auf dieser Basis die Lotgröße zu berechnen.

Es ist erwähnenswert, dass, wenn ein Stopp als Hauptstopp ausgewählt wird, sein Volumen immer gleich dem anfänglichen Volumen der Hauptposition ist. Dies funktioniert gut mit den brokerseitigen und den virtuellen Stopps, aber nicht mit Stopps, die auf Pending-Orders basieren. Es gibt zwei Probleme, die zu dieser Lösung führen.

Der erste Grund ist, dass im MetaTrader 4 der Eröffnungspreis einer Pending-Order modifiziert werden kann, solange die Pending-Order noch nicht ausgelöst wird. Das ist im Metatrader 5 unmöglich, da eine klare Struktur der Handelsoperationen aufrechterhalten werden muss. Eine neue Pending-Order muss erteilt werden, und, wenn sie erfolgreich ist, sollte die alte gelöscht werden, und von da an sollte der Expert Advisor die neue Pending-Order als neuen Stopp verwenden.

Das zweite Problem ist die Möglichkeit, dass die alte Pending-Order ausgelöst wird, während die zweite, neue Pending-Order gerade an den Broker geschickt wird. Da der EA keine Kontrolle über das Auslösen der Pending-Orders hat (die hat der Broker), kann dies zu Problemen wie z. B. zu verwaisten Hauptpositionen oder einem Stopp führen, der ein höheres Volumen als das der eigentlichen Position schließen würde.

Um diese Probleme zu vermeiden, wäre der einfachere Ansatz, das Volumen der Pending-Orders bei der Eröffnung der Hauptposition zu verteilen, anstatt das Volumen der Pending-Orders während der gesamten Laufzeit des offenen Position dynamisch anzupassen. Dies setzt jedoch voraus, dass keine weiterer Pending-Order als Stopp existieren darf, wenn der Hauptstopp vom Typ Pending-Order ist.

Volumen

Für den Hauptstopp ist es nicht erforderlich, eine Lotgröße anzugeben, die das Volumen der Hauptposition vermindert, denn sobald sie ausgelöst wird, sollte die gesamte Position geschlossen werden. Bei den anderen Stopps muss jedoch das Volumen berücksichtigt werden, da sie in der Regel nur Anteile der Hauptposition schießen sollen. Es können vier verschiedene Typen unterschieden werden:

  1. Fix – feste Lotgröße
  2. Verbleibender Prozentsatz – offen bleibender Prozentsatz der Hauptposition
  3. Gesamter Prozentsatz – Prozentsatz der gesamten Lotgröße (Anfangsvolumen) der Hauptposition
  4. Verbleibend – das verbleibende Volumen der Hauptposition.

Eine feste Lotgröße ist die einfachste Form der Bestimmung des Volumens. Das würde jedoch nicht optimal funktionieren, wenn der Expert Advisor für jede Position dynamisch das Volumen berechnet, d.h. mit einem Geldmanagement. Dies ist nur dann ideal, wenn die Lotgröße über die ganze Zeit, die der Expert Advisor arbeitet, konstant bleibt.

"Verbleibender Prozentsatz" und "Verbleibend" werden am besten als virtuelle Hauptstopps verwendet. "Verbleibend" würde einen EA daran hindern verwaiste Positionen mit noch noch offenen Positionen zu erstellen oder eine Position mit einem Volumen größer als das des noch existierenden Volumens der Hauptposition zu schließen. "Verbleibende Prozentsatz" andererseits wird verwendet, wenn der Expert Advisor die Position nicht mit dem Anfangsvolumen sondern dem noch existierenden Volumen der Hauptposition schließen soll.

Der gesamte Prozentanteil kann für Stopps brokerseitig, virtuell oder mit Pending-Orders verwendet werden. Die Berechnungen für diese Vorgehensweise basiert auf dem Anfangsvolumen der Hauptposition.

One-Cancels-the-Other (OCO)

CStop verfügt immer über zwei Werte, von denen einer der Stoploss, der andere Takeprofit ist. Es ist jedoch auch nur ein einziger Stopp möglich (nur Takeprofit und ohne Stoploss oder umgekehrt), wenn dem anderen der Wert Null zugewiesen wird. Standardmäßig wird bei nur einen Stopp, wenn dieser ausgelöst wird, der andere geschlossen. Die einzige Ausnahme davon ist, wenn CStop der Hauptstopp ist.

Basisklasse

Der Code der Basisklasse CStop (CStopBase) ist unten angeführt:

class CStopBase : public CObject
  {
protected:
   //--- Stopps, Parameter   
   bool              m_active;
   bool              m_main;
   string            m_name;
   bool              m_oco;
   double            m_stoploss;
   string            m_stoploss_name;
   ENUM_STOP_TYPE    m_stop_type;
   double            m_takeprofit;
   string            m_takeprofit_name;
   int               m_delay;
   //--- Stopps, Parameter der Position
   ENUM_VOLUME_TYPE  m_volume_type;
   double            m_volume;
   int               m_magic;
   int               m_deviation;
   string            m_comment;
   //--- Stopps Parameter des Objektes
   bool              m_entry_visible;
   bool              m_stoploss_visible;
   bool              m_takeprofit_visible;
   color             m_entry_color;
   color             m_stoploss_color;
   color             m_takeprofit_color;
   ENUM_LINE_STYLE   m_entry_style;
   ENUM_LINE_STYLE   m_stoploss_style;
   ENUM_LINE_STYLE   m_takeprofit_style;
   //--- Objekte
   CSymbolManager   *m_symbol_man;
   CSymbolInfo      *m_symbol;
   CAccountInfo     *m_account;
   CTradeManager     m_trade_man;
   CExpertTradeX    *m_trade;
   CTrails          *m_trails;
   CEventAggregator *m_event_man;
   CStops           *m_stops;
public:
                     CStopBase(void);
                    ~CStopBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_STOP;}
   //--- Initialisierung
   virtual bool      Init(CSymbolManager*,CAccountInfo*,CEventAggregator*);
   virtual bool      InitAccount(CAccountInfo*);
   virtual bool      InitEvent(CEventAggregator*);
   virtual bool      InitSymbol(CSymbolManager*);
   virtual bool      InitTrade(void);
   virtual CStops   *GetContainer(void);
   virtual void      SetContainer(CStops*);
   virtual bool      Validate(void) const;
   //--- Abfragen und Ändern
   bool              Active(void);
   void              Active(const bool);
   bool              Broker(void) const;
   void              Comment(const string);
   string            Comment(void) const;
   void              Delay(int delay);
   int               Delay(void) const;
   void              SetDeviation(const int);
   int               SetDeviation(void) const;
   void              EntryColor(const color clr);
   void              EntryStyle(const ENUM_LINE_STYLE);
   void              EntryVisible(const bool);
   bool              EntryVisible(void) const;
   void              Magic(const int);
   int               Magic(void) const;
   void              Main(const bool);
   bool              Main(void) const;
   void              Name(const string);
   string            Name(void) const;
   void              OCO(const bool oco);
   bool              OCO(void) const;
   bool              Pending(void) const;
   void              StopLoss(const double);
   double            StopLoss(void) const;
   void              StopLossColor(const color);
   bool              StopLossCustom(void);
   void              StopLossName(const string);
   string            StopLossName(void) const;
   void              StopLossVisible(const bool);
   bool              StopLossVisible(void) const;
   void              StopLossStyle(const ENUM_LINE_STYLE);
   void              StopType(const ENUM_STOP_TYPE);
   ENUM_STOP_TYPE    StopType(void) const;
   string            SymbolName(void);
   void              TakeProfit(const double);
   double            TakeProfit(void) const;
   void              TakeProfitColor(const color);
   bool              TakeProfitCustom(void);
   void              TakeProfitName(const string);
   string            TakeProfitName(void) const;
   void              TakeProfitStyle(const ENUM_LINE_STYLE);
   void              TakeProfitVisible(const bool);
   bool              TakeProfitVisible(void) const;
   bool              Virtual(void) const;
   void              Volume(double);
   double            Volume(void) const;
   void              VolumeType(const ENUM_VOLUME_TYPE);
   ENUM_VOLUME_TYPE  VolumeType(void) const;
   //--- Stopps, Prüfung
   virtual bool      CheckStopLoss(COrder*,COrderStop*);
   virtual bool      CheckTakeProfit(COrder*,COrderStop*);
   virtual bool      CheckStopOrder(ENUM_STOP_MODE,COrder*,COrderStop*)=0;
   virtual bool      DeleteStopOrder(const ulong)=0;
   virtual bool      DeleteMarketStop(const ulong)=0;
   virtual bool      OrderModify(const ulong,const double);
   //--- Stopps, Erstellen des Objektes
   virtual CStopLine *CreateEntryObject(const long,const string,const int,const double);
   virtual CStopLine *CreateStopLossObject(const long,const string,const int,const double);
   virtual CStopLine *CreateTakeProfitObject(const long,const string,const int,const double);
   //--- Stopps, Preisberechnung   
   virtual bool      Refresh(const string);
   virtual double    StopLossCalculate(const string,const ENUM_ORDER_TYPE,const double);
   virtual double    StopLossCustom(const string,const ENUM_ORDER_TYPE,const double);
   virtual double    StopLossPrice(COrder*,COrderStop*);
   virtual double    StopLossTicks(const ENUM_ORDER_TYPE,const double);
   virtual double    TakeProfitCalculate(const string,const ENUM_ORDER_TYPE,const double);
   virtual double    TakeProfitCustom(const string,const ENUM_ORDER_TYPE,const double);
   virtual double    TakeProfitPrice(COrder*,COrderStop*);
   virtual double    TakeProfitTicks(const ENUM_ORDER_TYPE,const double);
   //--- Stopps, Trailing   
   virtual bool      Add(CTrails*);
   virtual double    CheckTrailing(const string,const ENUM_ORDER_TYPE,const double,const double,const ENUM_TRAIL_TARGET);
protected:
   //--- Objekt erstellen
   virtual CStopLine *CreateObject(const long,const string,const int,const double);
   //--- Stopps, Preisberechnung
   virtual double    LotSizeCalculate(COrder*,COrderStop*);
   //--- Stopps, Positionseröffnung   
   virtual bool      GetClosePrice(const string,const ENUM_ORDER_TYPE,double&);
   //--- Stopps, Position schließen
   virtual bool      CloseStop(COrder*,COrderStop*,const double)=0;
   //--- Deinitialisierung
   virtual void      Deinit(void);
   virtual void      DeinitSymbol(void);
   virtual void      DeinitTrade(void);
   virtual void      DeinitTrails(void);
  };

Für Stoploss und Takeprofits auf der Basis von Pips oder Points müssen wir uns zumindest an vier Methoden der Klasse erinnern:

  1. Der Typ Stopp (brokerseitig, per Pending-Order oder virtuell), mittels der Methode StopType()
  2. Der Typ Volumen verwendet zur Berechnung die Methode VolumeType()
  3. Stoploss in Points (wenn nötig) mittels der Methode Stoploss()
  4. Takeprofit in Points (wenn nötig) mittels der Methode Takeprofit()

Sie weisen den Mitgliedern der Klasse Werte zu, so dass wir sie nicht im einzelnen ausarbeiten müssen. Die meisten anderen Methoden werden von der Klasse nur für interne Berechnungen benötigt. Zu den wichtigsten dieser geschützten Methoden gehören die Methoden StoplossCalculate() und TakeprofitCalculate(), deren Code im Folgenden dargestellt ist:

double CStopBase::StopLossCalculate(const string symbol,const ENUM_ORDER_TYPE type,const double price)
  {   
   if(!Refresh(symbol))
      return 0;
   if(type==ORDER_TYPE_BUY || type==ORDER_TYPE_BUY_STOP || type==ORDER_TYPE_BUY_LIMIT)
      return price-m_stoploss*m_symbol.Point();
   else if(type==ORDER_TYPE_SELL || type==ORDER_TYPE_SELL_STOP || type==ORDER_TYPE_SELL_LIMIT)
      return price+m_stoploss*m_symbol.Point();
   return 0;
  }

double CStopBase::TakeProfitCalculate(const string symbol,const ENUM_ORDER_TYPE type,const double price)
  {
   if(!Refresh(symbol))
      return 0;
   if(type==ORDER_TYPE_BUY || type==ORDER_TYPE_BUY_STOP || type==ORDER_TYPE_BUY_LIMIT)
      return price+m_takeprofit*m_symbol.Point();
   else if(type==ORDER_TYPE_SELL || type==ORDER_TYPE_SELL_STOP || type==ORDER_TYPE_SELL_LIMIT)
      return price-m_takeprofit*m_symbol.Point();
   return 0;
  }

Beide Methoden haben drei Argumente, die sich alle auf die Hauptposition beziehen. Die Methoden aktualisieren zunächst mit der Methode Refresh() das Symbol, das einfach die Verwaltung der Symbole aktuell auf das übergebene Symbol konzentriert. Nach der Aktualisierung wird der Werte entweder des Stoploss oder des Takeprofits zurückgegeben, auf Basis des "point values", den die Instanz bei ihrer Initialisierung gespeichert hat.

CStops

Die Klasse CStops dient als Container für die Instanzen von CStop. Eine Instanz dieser Klasse muss dynamisch einem ihrer Mitglieder zum Order-Manager hinzugefügt werden, der folgende Code zeigt CStopsBase, die Basisklasse von CStops:

class CStopsBase : public CArrayObj
  {
protected:
   bool              m_active;
   CEventAggregator *m_event_man;
   CObject          *m_container;
public:
                     CStopsBase(void);
                    ~CStopsBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_STOPS;}
   //--- Initialisierung
   virtual bool      Init(CSymbolManager*,CAccountInfo*,CEventAggregator*);
   virtual CObject  *GetContainer(void);
   virtual void      SetContainer(CObject*);
   virtual bool      Validate(void) const;
   //--- Ändern und Abfragen
   virtual bool      Active(void) const;
   virtual void      Active(const bool);
   virtual CStop    *Main(void);
   //--- Wiederherstellung
   virtual bool      CreateElement(const int);
  };

Diese Klasse ist sehr ähnlich den anderen, in diesem Artikel beschrieben Containern.

COrderStop

COrderStop ist die Implementierung von CStop für eine spezielle Position. Für eine gegebene Position kann CStop maximal einen COrderStop erzeugen. Eine beliebige Anzahl von Instanzen von COrderStop kann sich jedoch dieselbe Instanz von CStop teilen. Wenn ein Expert Advisor also 3 verschiedene Instanzen von CStop hat, erwarten wir in der Regel, dass jede Instanz von COrder die gleiche Anzahl von Instanzen von COrderStop hat. Wenn der Expert Advisor 1000 Mal gehandelt hat, dann würde die Anzahl der angelegten Instanzen von COrderStop 1000 * 3 = 3000 betragen, während die Anzahl der angelegten Instanzen von CStop immer noch 3 betragen würde.

Die Definition von COrderStopBase, von der aus COrderStop gestartet wird, ist im folgenden Code dargestellt:

class COrderStopBase : public CObject
  {
protected:
   bool              m_active;
   //--- Stopp Parameter
   double            m_volume;
   CArrayDouble      m_stoploss;
   CArrayDouble      m_takeprofit;
   ulong             m_stoploss_ticket;
   ulong             m_takeprofit_ticket;
   bool              m_stoploss_closed;
   bool              m_takeprofit_closed;
   bool              m_closed;
   ENUM_STOP_TYPE    m_stop_type;
   string            m_stop_name;
   //--- Objekt der Hauptposition
   COrder           *m_order;
   //--- Stopp Objekt
   CStop            *m_stop;
   CStopLine        *m_objentry;
   CStopLine        *m_objsl;
   CStopLine        *m_objtp;
   COrderStops      *m_order_stops;
public:
                     COrderStopBase(void);
                    ~COrderStopBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_ORDERSTOP;}
   //--- Initialisierung
   virtual void      Init(COrder*,CStop*,COrderStops*);
   virtual COrderStops *GetContainer(void);
   virtual void      SetContainer(COrderStops*);
   virtual void      Show(bool);
   //--- Abfragen und Ändern  
   bool              Active(void) const;
   void              Active(bool active);
   string            EntryName(void) const;
   ulong             MainMagic(void) const;
   ulong             MainTicket(void) const;
   double            MainTicketPrice(void) const;
   ENUM_ORDER_TYPE   MainTicketType(void) const;
   COrder           *Order(void);
   void              Order(COrder*);
   CStop            *Stop(void);
   void              Stop(CStop*);
   bool              StopLoss(const double);
   double            StopLoss(void) const;
   double            StopLoss(const int);
   void              StopLossClosed(const bool);
   bool              StopLossClosed(void);
   double            StopLossLast(void) const;
   string            StopLossName(void) const;
   void              StopLossTicket(const ulong);
   ulong             StopLossTicket(void) const;
   void              StopName(const string);
   string            StopName(void) const;
   bool              TakeProfit(const double);
   double            TakeProfit(void) const;
   double            TakeProfit(const int);
   void              TakeProfitClosed(const bool);
   bool              TakeProfitClosed(void);
   double            TakeProfitLast(void) const;
   string            TakeProfitName(void) const;
   void              TakeProfitTicket(const ulong);
   ulong             TakeProfitTicket(void) const;
   void              Volume(const double);
   double            Volume(void) const;
   //--- Prüfen   
   virtual void      Check(double&)=0;
   virtual bool      Close(void);
   virtual bool      CheckTrailing(void);
   virtual bool      DeleteChartObject(const string);
   virtual bool      DeleteEntry(void);
   virtual bool      DeleteStopLines(void);
   virtual bool      DeleteStopLoss(void);
   virtual bool      DeleteTakeProfit(void);
   virtual bool      IsClosed(void);
   virtual bool      Update(void) {return true;}
   virtual void      UpdateVolume(double) {}
   //--- Deinitialisierung 
   virtual void      Deinit(void);
   //--- Wiederherstellung
   virtual bool      Save(const int);
   virtual bool      Load(const int);
   virtual void      Recreate(void);
protected:
   virtual bool      IsStopLossValid(const double) const;
   virtual bool      IsTakeProfitValid(const double) const;
   virtual bool      Modify(const double,const double);
   virtual bool      ModifyStops(const double,const double);
   virtual bool      ModifyStopLoss(const double) {return true;}
   virtual bool      ModifyTakeProfit(const double){return true;}
   virtual bool      UpdateOrderStop(const double,const double){return true;}
   virtual bool      MoveStopLoss(const double);
   virtual bool      MoveTakeProfit(const double);
  };

COrderStop befindet sich in COrderStops (siehe nächster Abschnitt), die sich wiederum in COrder enthalten ist. Bei der eigentlichen Entwicklung eines EA ist es nicht mehr notwendig, eine Instanz von COrderStop zu deklarieren. Diese wird von COrder automatisch auf Basis einer bestimmten Instanz von CStop angelegt.

COrderStops

class COrderStopsBase : public CArrayObj
  {
protected:
   bool              m_active;
   CArrayInt         m_types;
   COrder           *m_order;
public:
                     COrderStopsBase(void);
                    ~COrderStopsBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_ORDERSTOPS;}
   void              Active(bool);
   bool              Active(void) const;
   //--- Initialisierung
   virtual CObject *GetContainer(void);
   virtual void      SetContainer(COrder*);
   virtual bool      NewOrderStop(COrder*,CStop*)=0;
   //--- Prüfen
   virtual void      Check(double &volume);
   virtual bool      CheckNewTicket(COrderStop*);
   virtual bool      Close(void);
   virtual void      UpdateVolume(const double) {}
   //--- Ausblenden und Zeigen der Linien der Stopps
   virtual void      Show(const bool);
   //--- Wiederherstellung
   virtual bool      CreateElement(const int);
   virtual bool      Save(const int);
   virtual bool      Load(const int);
  };


So wie CStop schaut auch dies wie ein typischer Container aus. Er enthält jedoch einige Methoden, die die Methoden der Objekte spiegeln, deren Pointer er speichern soll (COrderStop).

Darstellung der Stopps auf dem Chart

CStopLine ist ein Mitglied der Klasse CStop, dessen primäre Aufgabe die grafische Darstellung der Stopps auf dem Chart ist. Es hat drei wichtige Funktionen für einem Expert Advisor:

  1. Anzeigen der Stopps bei der Initialisierung einer Instanz von COrder
  2. Aktualisieren der Stopps, falls einer oder beide Stopps geändert worden sind
  3. Entfernen der Stopps, sobald die Position vom Markt gelöscht worden ist

All diese Funktionen werde mittels der Klasse CStop implementiert.

Die Definition von CStopLineBase, von der sich CStopLine abgeleitet, ist unten angeführt:

class CStopLineBase : public CChartObjectHLine
  {
protected:
   bool              m_active;
   CStop            *m_stop;
public:
                     CStopLineBase(void);
                    ~CStopLineBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_STOPLINE;}
   virtual void      SetContainer(CStop*);
   virtual CStop    *GetContainer(void);
   bool              Active(void) const;
   void              Active(const bool);
   virtual bool      ChartObjectExists(void) const;
   virtual double    GetPrice(const int);
   virtual bool      Move(const double);
   virtual bool      SetStyle(const ENUM_LINE_STYLE);
   virtual bool      SetColor(const color);
  };

In älteren Versionen des MetaTrader 4 sind Stoploss und Takeprofit nicht durch Ziehen veränderbar. Die Stopps mussten entweder über das Auftragsfenster oder mit Hilfe von Expert Advisorn und Skripten angepasst werden. Die grafische Darstellung der Stopps kann jedoch nützlich sein, besonders wenn es sich um virtuelle handelt.

Prüfen der Stopps einer Position

Nachdem die Stopps erfolgreich für eine bestimmte Position erstellt wurden, wäre der nächste Schritt zu überprüfen, ob der Markt den Wert einer der Stopps erreicht hat. Bei brokerseitigen Stopps ist die Prüfung nicht notwendig, da vom Server die Position dann geschlossen wird. Bei virtuellen Stopps und Stopps, die auf Pending-Orders basieren, muss jedoch der Expert Advisor in den meisten Fällen das Schließen der Position selbst durchführen.

Bei virtuellen Stopps ist der Expert Advisor für die Überwachung der Marktbewegungen und die Überprüfung, ob der Markt einen bestimmten Stopp erreicht hat, allein verantwortlich. Die folgende Abbildung zeigt allgemein das Vorgehen. Sobald der Markt ein Stopp erreicht, führt der Expert Advisor die entsprechende Art des Schließens der Position durch.

Prüfen von OrderStop (virtuell)

Für Stopps und Pending-Orders ist der Vorgang etwas komplizierter. Ein ausgelöster Stopp würde zu einer Pending-Order führen, die ausgelöst wurde, d. h. zu einer Position wird. Das passiert automatisch auf Seiten des Brokers. So läge es in der Verantwortung des Expert Advisors zu erkennen, ob die gegebene Pending-Order noch schwebend ist oder bereits als reale Position im Markt existiert. Wurde die Pending-Order bereits ausgelöst, so ist der Expert Advisor für das Schließen der Hauptposition mit dem gerade ausgelösten Volumen der Pending-Order verantwortlich - ein Auftrag der Form "close-by".

Prüfen durch COrderStop (Stopp mittels Pending-Order)

In allen Fällen wird, sobald die Pending-Order als Stopp ausgelöst wurde, der Stopp als geschlossen gekennzeichnet. Das soll verhindern, dass ein Stopp mehrmals ausgeführt wird.

Beispiele

Example #1: Ein EA, der Heiken Ashi und Moving Average verwendet, mit einem einzigen Stopp (Hauptstopp)

Den meisten Expert Advisor reicht ein Stoploss und ein Takeprofit. Wir werden nun das Beispiel aus dem vorherigen Artikel (siehe Cross-Plattform Expert Advisor: Zeitfilter) erweitern, um dem Quellcode einen Stoploss und Takeprofit hinzuzufügen. Dazu erstellen wir zunächst eine neue Instanz des Containers (CStops). Dann erstellen wir eine Instanz von CStop, und übergeben dann dessen Pointer dem Container. Der Pointer auf den Container wird dann schließlich dem Order-Manager hinzugefügt. Der Code wird unten gezeigt:

int OnInit()
  {
//--- zusätzlicher Code

   CStops *stops=new CStops();

   CStop *main=new CStop("main");
   main.StopType(stop_type_main);
   main.VolumeType(VOLUME_TYPE_PERCENT_TOTAL);
   main.Main(true);
   main.StopLoss(stop_loss);
   main.TakeProfit(take_profit);
   stops.Add(GetPointer(main));
   
   order_manager.AddStops(GetPointer(stops));     
//--- zusätzlicher Code
  }

Die Testergebnisse der brokerseitigen Stopps im Metatrader 4 sind in der folgenden Tabelle aufgelistet. Es ist das, was Händler normalerweise erwarten, wenn ein Expert Advisor seinen Handel auf dieser Plattform ausführt.

# Zeit Typ Auftrag Größe Preis S / L T / P Gewinn Kontostand
1 2017.01.03 10:00 sell 1 0.30 1.04597 1.05097 1.04097
2 2017.01.03 11:34 t/p 1 0.30 1.04097 1.05097 1.04097 150.00 3150.00
3 2017.01.05 11:00 sell 2 0.30 1.05149 1.05649 1.04649
4 2017.01.05 17:28 s/l 2 0.30 1.05649 1.05649 1.04649 -150.00 3000.00

Stopps, die auf Pending-Orders basieren, werden wie bei standardmäßigen SL/TP im Voraus platziert, jedoch in Form von Pending-Orders. Sobald die Pending-Order ausgelöst wird, führt der Expert Advisor einen "close-by" durch und schließt den Hauptposition mit dem Volumen des ausgelösten Pending-Order. Anders als bei standardmäßigen sl/tp führt der Expert Advisor dies jedoch auf Seiten des Händlers durch. Dies wird nicht ausgeführt, es sei denn, die Handelsplattform ist online und der EA läuft auf einem Chart.

# Zeit Typ Auftrag Größe Preis S / L T / P Gewinn Kontostand
1 2017.01.03 10:00 sell 1 0.30 1.04597 0.00000 0.00000
2 2017.01.03 10:00 buy stop 2 0.30 1.05097 0.00000 0.00000
3 2017.01.03 10:00 buy limit 3 0.30 1.04097 0.00000 0.00000
4 2017.01.03 11:34 buy 3 0.30 1.04097 0.00000 0.00000
5 2017.01.03 11:34 close by 1 0.30 1.04097 0.00000 0.00000 150.00 3150.00
6 2017.01.03 11:34 close by 3 0.00 1.04097 0.00000 0.00000 0.00 3150.00
7 2017.01.03 11:34 delete 2 0.30 1.05097 0.00000 0.00000
8 2017.01.05 11:00 sell 4 0.30 1.05149 0.00000 0.00000
9 2017.01.05 11:00 buy stop 5 0.30 1.05649 0.00000 0.00000
10 2017.01.05 11:00 buy limit 6 0.30 1.04649 0.00000 0.00000
11 2017.01.05 17:28 buy 5 0.30 1.05649 0.00000 0.00000
12 2017.01.05 17:28 close by 4 0.30 1.05649 0.00000 0.00000 -150.00 3000.00
13 2017.01.05 17:28 close by 5 0.00 1.05649 0.00000 0.00000 0.00 3000.00
14 2017.01.05 17:28 delete 6 0.30 1.04649 0.00000 0.00000


Virtuelle Stopps senden nichts über die Stopps der Hauptposition. Der Broker wird erst informiert, wenn der EA einen Auftrag zum Schließen sendet. Die folgende Tabelle zeigt das Verhalten des EA bei virtuellen Stopps. Sobald hier der Preis eines Stopps erreicht wird, sendet der EA eine Auftrag an den Server, die Hauptposition zu schließen.

# Zeit Typ Auftrag Größe Preis S / L T / P Gewinn Kontostand
1 2017.01.03 10:00 sell 1 0.30 1.04597 0.00000 0.00000
2 2017.01.03 11:34 close 1 0.30 1.04097 0.00000 0.00000 150.00 3150.00
3 2017.01.05 11:00 sell 2 0.30 1.05149 0.00000 0.00000
4 2017.01.05 17:28 close 2 0.30 1.05649 0.00000 0.00000 -150.00 3000.00


Kommen wir nun zu MetaTrader 5. MetaTrader 5 im "hedging mode" zeigt Endergebnisse, die denen des MetaTrader 4 sehr ähnlich sind. Die folgende Tabelle zeigt die Ergebnisse der brokerseitigen Stopps. Hier sehen wir deutlich die Stoploss und Takeprofits der Hauptpositionen in den jeweiligen Spalten.













Aufträge
Eröffnungszeit Auftrag Symbol Typ Volumen Preis S / L T / P Zeit Status Kommentar
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597 1.05097 1.04097 2017.01.03 10:00:00 filled
2017.01.03 11:34:38 3 EURUSD buy 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell 0.30 / 0.30 1.05149 1.05649 1.04649 2017.01.05 11:00:00 filled
2017.01.05 17:28:37 5 EURUSD buy 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled sl 1.05649

Deals
Zeit Deal Symbol Typ Direction Volumen Preis Auftrag Commission Swap Gewinn Kontostand Kommentar
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.30 1.04097 3 0.00 0.00 150.00 3 150.00 tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell in 0.30 1.05149 4 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 5 EURUSD buy out 0.30 1.05649 5 0.00 0.00 -150.00 3 000.00 sl 1.05649

0.00 0.00 0.00 3 000.00

Im "hedging mode" arbeiten die Pending-Orders wie im Metatrader 4, so dass der EA ein Schließen der Form "close-by" durchführt, wenn die Pending-Order ausgelöste worden ist.














Aufträge
Eröffnungszeit Auftrag Symbol Typ Volumen Preis S / L T / P Zeit Status Kommentar
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 10:00:00 3 EURUSD buy stop 0.30 / 0.00 1.05097

2017.01.03 11:34:38 canceled
2017.01.03 10:00:00 4 EURUSD buy limit 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled
2017.01.03 11:34:38 5 EURUSD close by 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled close #2 by #4
2017.01.05 11:00:00 6 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 11:00:00 7 EURUSD buy stop 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled
2017.01.05 11:00:00 8 EURUSD buy limit 0.30 / 0.00 1.04649

2017.01.05 17:28:37 canceled
2017.01.05 17:28:37 9 EURUSD close by 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled close #6 by #7

Deals
Zeit Deal Symbol Typ Direction Volumen Preis Auftrag Commission Swap Gewinn Kontostand Kommentar
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy in 0.30 1.04097 4 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 4 EURUSD buy out by 0.30 1.04097 5 0.00 0.00 150.00 3 150.00 close #2 by #4
2017.01.03 11:34:38 5 EURUSD sell out by 0.30 1.04597 5 0.00 0.00 0.00 3 150.00 close #2 by #4
2017.01.05 11:00:00 6 EURUSD sell in 0.30 1.05149 6 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 7 EURUSD buy in 0.30 1.05649 7 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 9 EURUSD sell out by 0.30 1.05149 9 0.00 0.00 0.00 3 150.00 close #6 by #7
2017.01.05 17:28:37 8 EURUSD buy out by 0.30 1.05649 9 0.00 0.00 -150.00 3 000.00 close #6 by #7

0.00 0.00 0.00 3 000.00

Mit virtuellen Stopps sehen wir normalerweise kein Zeichen für "Close", wie es MetaTrader 4 anzeigt. Der Vorgang des Schießens wird durch eine Position in der Gegenrichtung der Hauptposition erreicht. In der Liste historischer Deals können wir aber erkennen, ob ein Kauf oder Verkauf, ein Ein- oder Ausstieg getätigt wurde.














Aufträge
Eröffnungszeit Auftrag Symbol Typ Volumen Preis S / L T / P Zeit Status Kommentar
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 11:34:38 3 EURUSD buy 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled
2017.01.05 11:00:00 4 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 17:28:37 5 EURUSD buy 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled

Deals
Zeit Deal Symbol Typ Direction Volumen Preis Auftrag Commission Swap Gewinn Kontostand Kommentar
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.30 1.04097 3 0.00 0.00 150.00 3 150.00
2017.01.05 11:00:00 4 EURUSD sell in 0.30 1.05149 4 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 5 EURUSD buy out 0.30 1.05649 5 0.00 0.00 -150.00 3 000.00

0.00 0.00 0.00 3 000.00

Da der MetaTrader 5 in diesem Modus globale Stoploss und Takeprofit verwendet (gilt für die gesamte Position), muss der EA Pending-Orders verwenden, damit die Positionen über eindeutige Stoploss und Takeprofit verfügen. Wie bereits erwähnt, werden im "hedging mode" brokerseitige Stopps als Stopps auf Basis von Pending-Orders verwendet, wie die folgende Tabelle zeigt:













Aufträge
Eröffnungszeit Auftrag Symbol Typ Volumen Preis S / L T / P Zeit Status Kommentar
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 10:00:00 3 EURUSD buy stop 0.30 / 0.00 1.05097

2017.01.03 11:34:38 canceled
2017.01.03 10:00:00 4 EURUSD buy limit 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled
2017.01.05 11:00:00 5 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 11:00:00 6 EURUSD buy stop 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled
2017.01.05 11:00:00 7 EURUSD buy limit 0.30 / 0.00 1.04649

2017.01.05 17:28:37 canceled

Deals
Zeit Deal Symbol Typ Direction Volumen Preis Auftrag Commission Swap Gewinn Kontostand Kommentar
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.30 1.04097 4 0.00 0.00 150.00 3 150.00
2017.01.05 11:00:00 4 EURUSD sell in 0.30 1.05149 5 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 5 EURUSD buy out 0.30 1.05649 6 0.00 0.00 -150.00 3 000.00

0.00 0.00 0.00 3 000.00

Die folgende Tabelle zeigt die Ergebnisse, wenn Stopps auf Pending-Orders basieren. Aus dem oben genannten Grund entspricht dies der vorigen Tabelle.













Aufträge
Eröffnungszeit Auftrag Symbol Typ Volumen Preis S / L T / P Zeit Status Kommentar
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 10:00:00 3 EURUSD buy stop 0.30 / 0.00 1.05097

2017.01.03 11:34:38 canceled
2017.01.03 10:00:00 4 EURUSD buy limit 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled
2017.01.05 11:00:00 5 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 11:00:00 6 EURUSD buy stop 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled
2017.01.05 11:00:00 7 EURUSD buy limit 0.30 / 0.00 1.04649

2017.01.05 17:28:37 canceled

Deals
Zeit Deal Symbol Typ Direction Volumen Preis Auftrag Commission Swap Gewinn Kontostand Kommentar
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.30 1.04097 4 0.00 0.00 150.00 3 150.00
2017.01.05 11:00:00 4 EURUSD sell in 0.30 1.05149 5 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 5 EURUSD buy out 0.30 1.05649 6 0.00 0.00 -150.00 3 000.00

0.00 0.00 0.00 3 000.00

Die folgende Tabelle zeigt die Verwendung virtueller Stopps im MetaTrader 5 im "netting mode". Die virtuellen Stopps im "netting mode" sehen zwar genauso aus wie im "hedging mode", aber die internen Abläufe sind unterschiedlich.














Aufträge
Eröffnungszeit Auftrag Symbol Typ Volumen Preis S / L T / P Zeit Status Kommentar
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 11:34:38 3 EURUSD buy 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled
2017.01.05 11:00:00 4 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 17:28:37 5 EURUSD buy 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled

Deals
Zeit Deal Symbol Typ Direction Volumen Preis Auftrag Commission Swap Gewinn Kontostand Kommentar
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.30 1.04097 3 0.00 0.00 150.00 3 150.00
2017.01.05 11:00:00 4 EURUSD sell in 0.30 1.05149 4 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 5 EURUSD buy out 0.30 1.05649 5 0.00 0.00 -150.00 3 000.00

0.00 0.00 0.00 3 000.00

Example #2: Ein EA, der Heiken Ashi und Moving Average mit drei Stopps verwendet

Komplexere Expert Advisor benötigen oft mehr als einen Stoploss und einen Takeprofit. Wir verwenden die gleiche Methode wie im vorherigen Beispiel, wenn wir zusätzliche Stopps hinzufügen, nämlich die Stopps mit den Namen "stop1" und "stop2":

int OnInit()
  {
//--- zusätzlicher Code
  
   CStops *stops=new CStops();

   CStop *main=new CStop("main");
   main.StopType(stop_type_main);
   main.VolumeType(VOLUME_TYPE_PERCENT_TOTAL);
   main.Main(true);
   main.StopLoss(stop_loss);
   main.TakeProfit(take_profit);
   stops.Add(GetPointer(main));
   
   CStop *stop1=new CStop("stop1");
   stop1.StopType(stop_type1);
   stop1.VolumeType(VOLUME_TYPE_PERCENT_TOTAL);
   stop1.Volume(0.35);
   stop1.StopLoss(stop_loss1);
   stop1.TakeProfit(take_profit1);
   stops.Add(GetPointer(stop1));
   
   CStop *stop2=new CStop("stop2");
   stop2.StopType(stop_type2);
   stop2.VolumeType(VOLUME_TYPE_PERCENT_TOTAL);
   stop2.Volume(0.35);
   stop2.StopLoss(stop_loss2);
   stop2.TakeProfit(take_profit2);
   stops.Add(GetPointer(stop2));
   
   order_manager.AddStops(GetPointer(stops));

//--- zusätzlicher Code
  }

Die folgende Tabelle zeigt die Ergebnisse eines Tests mit dem Metatrader 4:

# Zeit Typ Auftrag Größe Preis S / L T / P Gewinn Kontostand
1 2017.01.03 10:00 sell 1 0.30 1.04597 1.05097 1.04097
2 2017.01.03 10:00 buy stop 2 0.11 1.04847 0.00000 0.00000
3 2017.01.03 10:00 buy limit 3 0.11 1.04347 0.00000 0.00000
4 2017.01.03 10:21 buy 3 0.11 1.04347 0.00000 0.00000
5 2017.01.03 10:21 close by 1 0.11 1.04347 1.05097 1.04097 27.50 3027.50
6 2017.01.03 10:21 sell 4 0.19 1.04597 1.05097 1.04097
7 2017.01.03 10:21 close by 3 0.00 1.04347 0.00000 0.00000 0.00 3027.50
8 2017.01.03 10:21 delete 2 0.11 1.04847 0.00000 0.00000
9 2017.01.03 10:34 close 4 0.11 1.04247 1.05097 1.04097 38.50 3066.00
10 2017.01.03 10:34 sell 5 0.08 1.04597 1.05097 1.04097
11 2017.01.03 11:34 t/p 5 0.08 1.04097 1.05097 1.04097 40.00 3106.00
12 2017.01.05 11:00 sell 6 0.30 1.05149 1.05649 1.04649
13 2017.01.05 11:00 buy stop 7 0.11 1.05399 0.00000 0.00000
14 2017.01.05 11:00 buy limit 8 0.11 1.04899 0.00000 0.00000
15 2017.01.05 12:58 buy 8 0.11 1.04899 0.00000 0.00000
16 2017.01.05 12:58 close by 6 0.11 1.04899 1.05649 1.04649 27.50 3133.50
17 2017.01.05 12:58 sell 9 0.19 1.05149 1.05649 1.04649
18 2017.01.05 12:58 close by 8 0.00 1.04899 0.00000 0.00000 0.00 3133.50
19 2017.01.05 12:58 delete 7 0.11 1.05399 0.00000 0.00000
20 2017.01.05 16:00 close 9 0.19 1.05314 1.05649 1.04649 -31.35 3102.15
21 2017.01.05 16:00 buy 10 0.30 1.05314 1.04814 1.05814
22 2017.01.05 16:00 sell stop 11 0.11 1.05064 0.00000 0.00000
23 2017.01.05 16:00 sell limit 12 0.11 1.05564 0.00000 0.00000
24 2017.01.05 17:09 sell 12 0.11 1.05564 0.00000 0.00000
25 2017.01.05 17:09 close by 10 0.11 1.05564 1.04814 1.05814 27.50 3129.65
26 2017.01.05 17:09 buy 13 0.19 1.05314 1.04814 1.05814
27 2017.01.05 17:09 close by 12 0.00 1.05564 0.00000 0.00000 0.00 3129.65
28 2017.01.05 17:09 delete 11 0.11 1.05064 0.00000 0.00000
29 2017.01.05 17:28 close 13 0.11 1.05664 1.04814 1.05814 38.50 3168.15
30 2017.01.05 17:28 buy 14 0.08 1.05314 1.04814 1.05814
31 2017.01.05 17:40 t/p 14 0.08 1.05814 1.04814 1.05814 40.00 3208.15


Wie aus der obigen Tabelle ersichtlich, wurden für die erste Positionen alle drei Stopps ausgelöst. Für den virtuellen Stopp schloss die EA erwartungsgemäß einen Teil der Hauptposition. Für den Stopp mittels Pending-Order führte der EA unmittelbar nach Ausführung der Pending-Order ein Schließen der Form "close-by" durch und reduzierte mit seinem Volumen das der Hauptposition. Schließlich, durch den Hauptstopp, den brokerseitigen Stopp, wurde die Hauptposition mit dem verbliebenen Volumen von 0,08 Lot geschlossen.

Die folgende Tabelle zeigt die Ergebnisse eines Tests mit dem Metatrader 5 "hedging mode":














Aufträge
Eröffnungszeit Auftrag Symbol Typ Volumen Preis S / L T / P Zeit Status Kommentar
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597 1.05097 1.04097 2017.01.03 10:00:00 filled
2017.01.03 10:00:00 3 EURUSD buy stop 0.11 / 0.00 1.04847

2017.01.03 10:21:32 canceled
2017.01.03 10:00:00 4 EURUSD buy limit 0.11 / 0.11 1.04347

2017.01.03 10:21:32 filled
2017.01.03 10:21:32 5 EURUSD close by 0.11 / 0.11 1.04347

2017.01.03 10:21:32 filled close #2 by #4
2017.01.03 10:33:40 6 EURUSD buy 0.11 / 0.11 1.04247

2017.01.03 10:33:40 filled
2017.01.03 11:34:38 7 EURUSD buy 0.08 / 0.08 1.04097

2017.01.03 11:34:38 filled tp 1.04097
2017.01.05 11:00:00 8 EURUSD sell 0.30 / 0.30 1.05149 1.05649 1.04649 2017.01.05 11:00:00 filled
2017.01.05 11:00:00 9 EURUSD buy stop 0.11 / 0.00 1.05399

2017.01.05 12:58:27 canceled
2017.01.05 11:00:00 10 EURUSD buy limit 0.11 / 0.11 1.04899

2017.01.05 12:58:27 filled
2017.01.05 12:58:27 11 EURUSD close by 0.11 / 0.11 1.04896

2017.01.05 12:58:27 filled close #8 by #10
2017.01.05 16:00:00 12 EURUSD buy 0.19 / 0.19 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 13 EURUSD buy 0.30 / 0.30 1.05307 1.04807 1.05807 2017.01.05 16:00:00 filled
2017.01.05 16:00:00 14 EURUSD sell stop 0.11 / 0.00 1.05057

2017.01.05 17:09:40 canceled
2017.01.05 16:00:00 15 EURUSD sell limit 0.11 / 0.11 1.05557

2017.01.05 17:09:40 filled
2017.01.05 17:09:40 16 EURUSD close by 0.11 / 0.11 1.05557

2017.01.05 17:09:40 filled close #13 by #15
2017.01.05 17:28:47 17 EURUSD sell 0.11 / 0.11 1.05660

2017.01.05 17:28:47 filled
2017.01.05 17:29:15 18 EURUSD sell 0.08 / 0.08 1.05807

2017.01.05 17:29:15 filled tp 1.05807

Deals
Zeit Deal Symbol Typ Direction Volumen Preis Auftrag Commission Swap Gewinn Kontostand Kommentar
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 10:21:32 3 EURUSD buy in 0.11 1.04347 4 0.00 0.00 0.00 3 000.00
2017.01.03 10:21:32 4 EURUSD buy out by 0.11 1.04347 5 0.00 0.00 27.50 3 027.50 close #2 by #4
2017.01.03 10:21:32 5 EURUSD sell out by 0.11 1.04597 5 0.00 0.00 0.00 3 027.50 close #2 by #4
2017.01.03 10:33:40 6 EURUSD buy out 0.11 1.04247 6 0.00 0.00 38.50 3 066.00
2017.01.03 11:34:38 7 EURUSD buy out 0.08 1.04097 7 0.00 0.00 40.00 3 106.00 tp 1.04097
2017.01.05 11:00:00 8 EURUSD sell in 0.30 1.05149 8 0.00 0.00 0.00 3 106.00
2017.01.05 12:58:27 9 EURUSD buy in 0.11 1.04896 10 0.00 0.00 0.00 3 106.00
2017.01.05 12:58:27 10 EURUSD buy out by 0.11 1.04896 11 0.00 0.00 27.83 3 133.83 close #8 by #10
2017.01.05 12:58:27 11 EURUSD sell out by 0.11 1.05149 11 0.00 0.00 0.00 3 133.83 close #8 by #10
2017.01.05 16:00:00 12 EURUSD buy out 0.19 1.05307 12 0.00 0.00 -30.02 3 103.81
2017.01.05 16:00:00 13 EURUSD buy in 0.30 1.05307 13 0.00 0.00 0.00 3 103.81
2017.01.05 17:09:40 14 EURUSD sell in 0.11 1.05557 15 0.00 0.00 0.00 3 103.81
2017.01.05 17:09:40 16 EURUSD buy out by 0.11 1.05307 16 0.00 0.00 0.00 3 103.81 close #13 by #15
2017.01.05 17:09:40 15 EURUSD sell out by 0.11 1.05557 16 0.00 0.00 27.50 3 131.31 close #13 by #15
2017.01.05 17:28:47 17 EURUSD sell out 0.11 1.05660 17 0.00 0.00 38.83 3 170.14
2017.01.05 17:29:15 18 EURUSD sell out 0.08 1.05807 18 0.00 0.00 40.00 3 210.14 tp 1.05807

0.00 0.00 210.14 3 210.14

Wie aus der obigen Tabelle zeigt, arbeitet der EA irgendwie ähnlich wie der Metatrader 5 im "hedging mode". Die Vorgänge sind die gleichen wie im Metatrader 4 für alle drei Typen der Stopps.

Die folgende Tabelle zeigt die Ergebnisse eines Tests auf Metatrader 5 im "netting mode":














Aufträge
Eröffnungszeit Auftrag Symbol Typ Volumen Preis S / L T / P Zeit Status Kommentar
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 10:00:00 3 EURUSD buy stop 0.30 / 0.00 1.05097

2017.01.03 11:34:38 canceled
2017.01.03 10:00:00 4 EURUSD buy limit 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled
2017.01.03 10:00:00 5 EURUSD buy stop 0.11 / 0.00 1.04847

2017.01.03 10:21:32 canceled
2017.01.03 10:00:00 6 EURUSD buy limit 0.11 / 0.11 1.04347

2017.01.03 10:21:32 filled
2017.01.03 10:33:40 7 EURUSD buy 0.11 / 0.11 1.04247

2017.01.03 10:33:40 filled
2017.01.05 11:00:00 8 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 11:00:00 9 EURUSD buy stop 0.30 / 0.00 1.05649

2017.01.05 16:00:00 canceled
2017.01.05 11:00:00 10 EURUSD buy limit 0.30 / 0.00 1.04649

2017.01.05 16:00:00 canceled
2017.01.05 11:00:00 11 EURUSD buy stop 0.11 / 0.00 1.05399

2017.01.05 12:58:27 canceled
2017.01.05 11:00:00 12 EURUSD buy limit 0.11 / 0.11 1.04899

2017.01.05 12:58:27 filled
2017.01.05 16:00:00 13 EURUSD buy 0.19 / 0.19 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 14 EURUSD buy 0.30 / 0.30 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 15 EURUSD sell stop 0.30 / 0.00 1.04807

2017.01.05 17:29:15 canceled
2017.01.05 16:00:00 16 EURUSD sell limit 0.30 / 0.30 1.05807

2017.01.05 17:29:15 filled
2017.01.05 16:00:00 17 EURUSD sell stop 0.11 / 0.00 1.05057

2017.01.05 17:09:40 canceled
2017.01.05 16:00:00 18 EURUSD sell limit 0.11 / 0.11 1.05557

2017.01.05 17:09:40 filled
2017.01.05 17:28:47 19 EURUSD sell 0.11 / 0.11 1.05660

2017.01.05 17:28:47 filled

Deals
Zeit Deal Symbol Typ Direction Volumen Preis Auftrag Commission Swap Gewinn Kontostand Kommentar
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 5 EURUSD buy in/out 0.30 1.04097 4 0.00 0.00 40.00 3 040.00
2017.01.03 10:21:32 3 EURUSD buy out 0.11 1.04347 6 0.00 0.00 27.50 3 067.50
2017.01.03 10:33:40 4 EURUSD buy out 0.11 1.04247 7 0.00 0.00 38.50 3 106.00
2017.01.05 11:00:00 6 EURUSD sell in/out 0.30 1.05149 8 0.00 -0.61 231.44 3 336.83
2017.01.05 12:58:27 7 EURUSD buy in/out 0.11 1.04896 12 0.00 0.00 20.24 3 357.07
2017.01.05 16:00:00 8 EURUSD buy in 0.19 1.05307 13 0.00 0.00 0.00 3 357.07
2017.01.05 16:00:00 9 EURUSD buy in 0.30 1.05307 14 0.00 0.00 0.00 3 357.07
2017.01.05 17:29:15 12 EURUSD sell out 0.30 1.05807 16 0.00 0.00 157.11 3 514.18
2017.01.05 17:09:40 10 EURUSD sell out 0.11 1.05557 18 0.00 0.00 30.11 3 544.29
2017.01.05 17:28:47 11 EURUSD sell out 0.11 1.05660 19 0.00 0.00 41.44 3 585.73

0.00 -0.61 586.34 3 585.73

Hier zeigt sich ein Problem. Der Stopp am Ende schloss mit 0,30 Lot statt mit 0,08 Lot, wie in den beiden vorangegangenen Tests festgestellt wurde.

Wie bereits erwähnt, unterscheiden sich die standardmäßigen Stoploss und Takeprofits im MetaTrader 5, "netting mode", von denen der beiden vorherigen Versionen. So würde der EA den brokerseitigen Stopp in eine Pending-Order umwandeln. Mit dieser Einstellung verfügt der EA jedoch bereits über zwei Stopps auf der Basis von Pending-Orders und einer davon ist ein Hauptstopp. Wie bereits erwähnt, würde dies zu verwaisten Positionen führen. Der End- oder der Hauptstopp würde immer ein Volumen haben, das dem anfänglichen Volumen des Hauptposition entspricht. Da es auch noch andere Stopps gibt, kann es dazu führen, dass der Hauptstopp die Position mit einem Volumen größer als das noch existierende schließen will.

Um dies Problem zu lösen, könnte man den Hauptstopp virtuell setzen, anstatt einen brokerseitigen oder einen Stopp als Pending-Order zu erstellen. Mit dieser neuen Einstellung verfügt der EA nun über zwei virtuelle Stopps und einen Stopp, der auf einer Pending-Order basiert. Das Ergebnis eines Tests mit dieser neuen Einstellung wird unten angezeigt.














Aufträge
Eröffnungszeit Auftrag Symbol Typ Volumen Preis S / L T / P Zeit Status Kommentar
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 10:00:00 3 EURUSD buy stop 0.11 / 0.00 1.04847

2017.01.03 10:21:32 canceled
2017.01.03 10:00:00 4 EURUSD buy limit 0.11 / 0.11 1.04347

2017.01.03 10:21:32 filled
2017.01.03 10:33:40 5 EURUSD buy 0.11 / 0.11 1.04247

2017.01.03 10:33:40 filled
2017.01.03 11:34:38 6 EURUSD buy 0.08 / 0.08 1.04097

2017.01.03 11:34:38 filled
2017.01.05 11:00:00 7 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 11:00:00 8 EURUSD buy stop 0.11 / 0.00 1.05399

2017.01.05 12:58:27 canceled
2017.01.05 11:00:00 9 EURUSD buy limit 0.11 / 0.11 1.04899

2017.01.05 12:58:27 filled
2017.01.05 16:00:00 10 EURUSD buy 0.19 / 0.19 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 11 EURUSD buy 0.30 / 0.30 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 12 EURUSD sell stop 0.11 / 0.00 1.05057

2017.01.05 17:09:40 canceled
2017.01.05 16:00:00 13 EURUSD sell limit 0.11 / 0.11 1.05557

2017.01.05 17:09:40 filled
2017.01.05 17:28:47 14 EURUSD sell 0.11 / 0.11 1.05660

2017.01.05 17:28:47 filled
2017.01.05 17:29:15 15 EURUSD sell 0.08 / 0.08 1.05807

2017.01.05 17:29:15 filled

Deals
Zeit Deal Symbol Typ Direction Volumen Preis Auftrag Commission Swap Gewinn Kontostand Kommentar
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 10:21:32 3 EURUSD buy out 0.11 1.04347 4 0.00 0.00 27.50 3 027.50
2017.01.03 10:33:40 4 EURUSD buy out 0.11 1.04247 5 0.00 0.00 38.50 3 066.00
2017.01.03 11:34:38 5 EURUSD buy out 0.08 1.04097 6 0.00 0.00 40.00 3 106.00
2017.01.05 11:00:00 6 EURUSD sell in 0.30 1.05149 7 0.00 0.00 0.00 3 106.00
2017.01.05 12:58:27 7 EURUSD buy out 0.11 1.04896 9 0.00 0.00 27.83 3 133.83
2017.01.05 16:00:00 8 EURUSD buy out 0.19 1.05307 10 0.00 0.00 -30.02 3 103.81
2017.01.05 16:00:00 9 EURUSD buy in 0.30 1.05307 11 0.00 0.00 0.00 3 103.81
2017.01.05 17:09:40 10 EURUSD sell out 0.11 1.05557 13 0.00 0.00 27.50 3 131.31
2017.01.05 17:28:47 11 EURUSD sell out 0.11 1.05660 14 0.00 0.00 38.83 3 170.14
2017.01.05 17:29:15 12 EURUSD sell out 0.08 1.05807 15 0.00 0.00 40.00 3 210.14

0.00 0.00 210.14 3 210.14

Das Gesamtvolumen der Stopps gleicht nun dem Anfangsvolumen der Hauptposition.

Beispiel #3: Stopps mit Geldmanagement

In einem früheren Artikel (siehe Cross-Plattform Expert Advisor: Geldmanagement) wurde diskutiert, dass einige Methoden des Geldmanagements von Stopps abhängen (Takeprofit ist möglich, aber normalerweise wird Stoploss verwendet). Geldmanagementmethoden wie fixe Anteile, fixes Risiko, fixes Risiko je Point/Pip erfordern oft einen begrenzenden Stoploss. Wenn man diesen Wert nicht festlegt, bedeutet dies ein sehr großes oder gar unendliches Risiko, und so wäre auch das berechnete Volumen sehr groß. Um einen Expert Advisor zu zeigen, der die in diesem Artikel erwähnten Klassenobjekte mit Geldmanagement verwenden kann, werden wir die im ersten Beispiel noch kommentierten Codezeilen jetzt in die Kompilierung mit einbeziehen.

Zuerst entfernen wir die Kommentarzeichen der Codezeilen für die Geldmanagementmethoden, wie im Code unten gezeigt, innerhalb der Funktion OnInit():

int OnInit()
  {
//--- zusätzlicher Code
   order_manager=new COrderManager();
   money_manager= new CMoneys();
   CMoney *money_fixed=new CMoneyFixedLot(0.05);
   CMoney *money_ff=new CMoneyFixedFractional(5);
   CMoney *money_ratio=new CMoneyFixedRatio(0,0.1,1000);
   CMoney *money_riskperpoint=new CMoneyFixedRiskPerPoint(0.1);
   CMoney *money_risk=new CMoneyFixedRisk(100);

   money_manager.Add(money_fixed);
   money_manager.Add(money_ff);
   money_manager.Add(money_ratio);
   money_manager.Add(money_riskperpoint);
   money_manager.Add(money_risk);
   order_manager.AddMoneys(money_manager);
//--- zusätzlicher Code
  }

Am Anfang des Quellcodes deklarieren wir dann eine benutzerdefinierte Enumeration, so dass wir einen externen Parameter erstellen können, der es uns erlaubt, die Geldmanagementmethode auszuwählen, wie unten aufgeführt:

enum ENUM_MM_TYPE
  {
   MM_FIXED=0,
   MM_FIXED_FRACTIONAL,
   MM_FIXED_RATIO,
   MM_FIXED_RISK_PER_POINT,
   MM_FIXED_RISK
  };

Wir deklarieren eine neue Eingabeparameter für diese Enumeration:

input ENUM_MM_TYPE mm_type=MM_FIXED_FRACTIONAL;

Schließlich müssen wir diesen Parameter mit der tatsächliche Auswahl der Geldmanagementmethode in der Funktion OnTick() verknüpfen:

void OnTick()
  {
//---   
   manage_trades();
   if(symbol_info.RefreshRates())
     {
      signals.Check();
      if(signals.CheckOpenLong())
        {
         close_last();
         if(time_filters.Evaluate(TimeCurrent()))
           {
            Print("Entering buy trade..");
            money_manager.Selected((int)mm_type); //use mm_type, cast to 'int' type
            order_manager.TradeOpen(Symbol(),ORDER_TYPE_BUY,symbol_info.Ask());
           }
        }
      else if(signals.CheckOpenShort())
        {
         close_last();
         if(time_filters.Evaluate(TimeCurrent()))
           {
            Print("Entering sell trade..");
            money_manager.Selected((int)mm_type); //use mm_type, cast to 'int' type
            order_manager.TradeOpen(Symbol(),ORDER_TYPE_SELL,symbol_info.Bid());
           }
        }
     }
  }

Da die Geldmanagementmethoden nur rechnen, gibt es keine Kompatibilitätsprobleme zwischen MQL4 und MQL5. Die beiden vorangegangenen Beispiele haben bereits gezeigt, wie die Stopps auf den beiden Plattformen funktionieren. Die folgenden Tabellen zeigen die Ergebnisse der Tests mit MetaTrader 5 "hedging mode".

Die folgende Tabelle zeigt ein Testergebnis unter Verwendung des Geldmanagements des fixen Anteils. Die codierte Einstellung riskiert 5% des Kontostandes. Mit einem Anfangssaldo von $3000 erwarten wir einen Verlust von ca. $150, wenn die erste Position durch den Stoploss geschlossen wird. Da Stoploss und Takeprofit den gleichen Wert haben (500 Punkte), erwarten wir, dass die Position $150 gewinnt, wenn Takeprofit erreicht wird.














Aufträge
Eröffnungszeit Auftrag Symbol Typ Volumen Preis S / L T / P Zeit Status Kommentar
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597 1.05097 1.04097 2017.01.03 10:00:00 filled
2017.01.03 11:34:38 3 EURUSD buy 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell 0.32 / 0.32 1.05149 1.05649 1.04649 2017.01.05 11:00:00 filled
2017.01.05 16:00:00 5 EURUSD buy 0.32 / 0.32 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 6 EURUSD buy 0.31 / 0.31 1.05307 1.04807 1.05807 2017.01.05 16:00:00 filled
2017.01.05 17:29:15 7 EURUSD sell 0.31 / 0.31 1.05807

2017.01.05 17:29:15 filled tp 1.05807

Deals
Zeit Deal Symbol Typ Direction Volumen Preis Auftrag Commission Swap Gewinn Kontostand Kommentar
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.30 1.04097 3 0.00 0.00 150.00 3 150.00 tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell in 0.32 1.05149 4 0.00 0.00 0.00 3 150.00
2017.01.05 16:00:00 5 EURUSD buy out 0.32 1.05307 5 0.00 0.00 -50.56 3 099.44
2017.01.05 16:00:00 6 EURUSD buy in 0.31 1.05307 6 0.00 0.00 0.00 3 099.44
2017.01.05 17:29:15 7 EURUSD sell out 0.31 1.05807 7 0.00 0.00 155.00 3 254.44 tp 1.05807

0.00 0.00 254.44 3 254.44

Beachten Sie, dass das berechnete Volumen auch von der Genauigkeit des Brokers abhängt, die durch die Parameter minimales Lot und minimale Lotstep bestimmt werden. Wir können vom Expert Advisor nicht erwarten, dass er immer ganz genau den errechneten Wert verwenden kann. Unter den Randbedingungen kann es für den Expert Advisor notwendig sein, den Wert abzurunden. Dasselbe gilt auch für die anderen Methoden des Geldmanagements.

Bei einem Geldmanagement des fixen Risikos pro Point ist die kodierte Einstellung des Risikos $0,1 pro Point. Bei einer Einstellung von 500 Points für Stoploss und Takeprofit erwarten wir, dass der Gewinn/Verlust auf jeden Fall $50 beträgt.














Aufträge
Eröffnungszeit Auftrag Symbol Typ Volumen Preis S / L T / P Zeit Status Kommentar
2017.01.03 10:00:00 2 EURUSD sell 0.10 / 0.10 1.04597 1.05097 1.04097 2017.01.03 10:00:00 filled
2017.01.03 11:34:38 3 EURUSD buy 0.10 / 0.10 1.04097

2017.01.03 11:34:38 filled tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell 0.10 / 0.10 1.05149 1.05649 1.04649 2017.01.05 11:00:00 filled
2017.01.05 16:00:00 5 EURUSD buy 0.10 / 0.10 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 6 EURUSD buy 0.10 / 0.10 1.05307 1.04807 1.05807 2017.01.05 16:00:00 filled
2017.01.05 17:29:15 7 EURUSD sell 0.10 / 0.10 1.05807

2017.01.05 17:29:15 filled tp 1.05807

Deals
Zeit Deal Symbol Typ Direction Volumen Preis Auftrag Commission Swap Gewinn Kontostand Kommentar
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.10 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.10 1.04097 3 0.00 0.00 50.00 3 050.00 tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell in 0.10 1.05149 4 0.00 0.00 0.00 3 050.00
2017.01.05 16:00:00 5 EURUSD buy out 0.10 1.05307 5 0.00 0.00 -15.80 3 034.20
2017.01.05 16:00:00 6 EURUSD buy in 0.10 1.05307 6 0.00 0.00 0.00 3 034.20
2017.01.05 17:29:15 7 EURUSD sell out 0.10 1.05807 7 0.00 0.00 50.00 3 084.20 tp 1.05807

0.00 0.00 84.20 3 084.20

Für ein Geldmanagement des fixen Risikos wurde ein Risiko von $100 codiert. Die EA wiederum würde ein Volumen berechnen, dass zu dem festgelegten Risiko passt. Das Ergebnis ist unten dargestellt.














Aufträge
Eröffnungszeit Auftrag Symbol Typ Volumen Preis S / L T / P Zeit Status Kommentar
2017.01.03 10:00:00 2 EURUSD sell 0.20 / 0.20 1.04597 1.05097 1.04097 2017.01.03 10:00:00 filled
2017.01.03 11:34:38 3 EURUSD buy 0.20 / 0.20 1.04097

2017.01.03 11:34:38 filled tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell 0.20 / 0.20 1.05149 1.05649 1.04649 2017.01.05 11:00:00 filled
2017.01.05 16:00:00 5 EURUSD buy 0.20 / 0.20 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 6 EURUSD buy 0.20 / 0.20 1.05307 1.04807 1.05807 2017.01.05 16:00:00 filled
2017.01.05 17:29:15 7 EURUSD sell 0.20 / 0.20 1.05807

2017.01.05 17:29:15 filled tp 1.05807

Deals
Zeit Deal Symbol Typ Direction Volumen Preis Auftrag Commission Swap Gewinn Kontostand Kommentar
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.20 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.20 1.04097 3 0.00 0.00 100.00 3 100.00 tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell in 0.20 1.05149 4 0.00 0.00 0.00 3 100.00
2017.01.05 16:00:00 5 EURUSD buy out 0.20 1.05307 5 0.00 0.00 -31.60 3 068.40
2017.01.05 16:00:00 6 EURUSD buy in 0.20 1.05307 6 0.00 0.00 0.00 3 068.40
2017.01.05 17:29:15 7 EURUSD sell out 0.20 1.05807 7 0.00 0.00 100.00 3 168.40 tp 1.05807

0.00 0.00 168.40 3 168.40

Denken Sie immer daran, dass der Order-Manager immer die Hauptposition als diejenige betrachtet, die für das Geldmanagement verwendet wird. Wurde kein Hauptstopp deklariert, können die auf Stoploss basierenden Geldmanagementmethoden nicht verwendet werden, auch wenn andere Stopps vorhanden sind.

Schlussfolgerung

In diesem Artikel haben wir das Hinzufügen von Stopps in einem plattformübergreifenden Expert Advisor diskutiert. Beiden Handelsplattformen, obwohl sie viele parallele Funktionen haben, unterscheiden sich erheblich in der Art und Weise, wie Stopps implementiert werden. Dieser Artikel enthält eine Methode, mit der diese Unterschiede ausgeglichen werden können, damit ein Expert Advisor mit beiden Plattformen kompatibel ist.

Programme, die im diesem Artikel verwendet werden

#
Name
Typ
Beschreibung
1.
stops_ha_ma1.mqh
Header-Datei
Header-Datei, die der Expert Advisor im ersten Beispiel verwendet
2.
stops_ha_ma1.mq4 Expert Advisor
Quellcode, verwendet von MQL4-Expert Advisor im ersten Beispiel
3.
stops_ha_ma1.mq5 Expert Advisor Quellcode, verwendet von MQL5-Expert Advisor im ersten Beispiel
4.  stops_ha_ma2.mqh Header-Datei Header-Datei, die der Expert Advisor im zweiten Beispiel verwendet
5.  stops_ha_ma2.mq4 Expert Advisor
Quellcode, verwendet von MQL4-Expert Advisor im zweiten Beispiel
6.  stops_ha_ma2.mq5 Expert Advisor
Quellcode, verwendet von MQL5-Expert Advisor im zweiten Beispiel
7.  stops_ha_ma3.mqh Header-Datei Header-Datei, die der Expert Advisor im dritten Beispiel verwendet
8.  stops_ha_ma3.mq4 Expert Advisor
Quellcode, verwendet von MQL4-Expert Advisor im dritten Beispiel
9.  stops_ha_ma3.mq5 Expert Advisor
Quellcode, verwendet von MQL5-Expert Advisor im dritten Beispiel

Die Dateien der Klassen dieses Artikels

#
Name
Typ
Beschreibung
1.
MQLx\Base\Stop\StopBase.mqh
Header-Datei
CStop (base class)
2.
MQLx\MQL4\Stop\Stop.mqh Header-Datei CStop (MQL4 version)
3.
MQLx\MQL5\Stop\Stop.mqh Header-Datei CStop (MQL5 version)
4. MQLx\Base\Stop\StopsBase.mqh Header-Datei CStops (CStop container, base class)
5. MQLx\MQL4\Stop\Stops.mqh Header-Datei CStops (MQL4 version)
6. MQLx\MQL5\Stop\Stops.mqh Header-Datei CStops (MQL5 version)
7. MQLx\Base\Stop\StopLineBase.mqh Header-Datei CStopLine (graphical representation, base class)
8. MQLx\MQL4\Stop\StopLine.mqh Header-Datei CStopLine (MQL4 version)
9. MQLx\MQL5\Stop\StopLine.mqh Header-Datei CStopLine (MQL5 version)
10.  MQLx\Base\Order\OrderStopBase.mqh Header-Datei COrderStop (base class)
11.  MQLx\MQL4\Order\OrderStop.mqh Header-Datei COrderStop (MQL4 version)
12.  MQLx\MQL5\Order\OrderStop.mqh Header-Datei COrderStop (MQL5 version)
13.
 MQLx\Base\Order\OrderStopVirtualBase.mqh Header-Datei
COrderStopVirtual (virtual stop level, base class)
14.  MQLx\Base\Order\OrderStopVirtual.mqh Header-Datei
COrderStopVirtual (MQL4 version)
15.
 MQLx\Base\Order\OrderStopVirtual.mqh Header-Datei
COrderStopVirtual (MQL5 version)
16.  MQLx\Base\Order\OrderStopPendingBase.mqh Header-Datei
COrderStopPending (pending order stop level, base class)
17.  MQLx\Base\Order\OrderStopPending.mqh Header-Datei
COrderStopPending (MQL4 version)
18.
 MQLx\Base\Order\OrderStopPending.mqh Header-Datei
COrderStopPending (MQL5 version)
19.
 MQLx\Base\Order\OrderStopBroker.mqh Header-Datei
COrderStopBroker (broker-based stop level, base class)
20.  MQLx\Base\Order\OrderStopBroker.mqh Header-Datei
COrderStopBroker (MQL4 version)
21.  MQLx\Base\Order\OrderStopBroker.mqh Header-Datei
COrderStopBroker (MQL5 version)
22.  MQLx\Base\Order\OrderStopsBase.mqh Header-Datei
COrderStops (COrderStop container, base class)
23.  MQLx\Base\Order\OrderStops.mqh Header-Datei
COrderStops (MQL4 version)
24.  MQLx\Base\Order\OrderStops.mqh Header-Datei
COrderStops (MQL5 version)

Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/3620

Beigefügte Dateien |
tester.zip (1445.59 KB)
MQL5.zip (708.29 KB)
Risikobewertung durch die Abfolge von Positionen von Finanzanlagen Risikobewertung durch die Abfolge von Positionen von Finanzanlagen
Dieser Artikel beschreibt den Verwendung von Methoden der Wahrscheinlichkeitstheorie und der mathematischen Statistik für die Analyse von Handelssystemen.
Tiefe neuronale Netzwerke (Teil IV). Erstellen, trainieren und testen eines Modells des neuronalen Netzes Tiefe neuronale Netzwerke (Teil IV). Erstellen, trainieren und testen eines Modells des neuronalen Netzes
Dieser Artikel beschäftigt sich mit den neuen Fähigkeiten des Programmpaketes darch (v.0.12.0). Es enthält eine Beschreibung des Trainings eines tiefen neuronalen Netzes mit verschiedenen Datentypen, unterschiedlicher Struktur und Trainingsreihenfolge. Die Ergebnisse des Trainings sind enthalten.
Grafische Interfaces XI: Integration der graphischen Standardbibliothek (build 16) Grafische Interfaces XI: Integration der graphischen Standardbibliothek (build 16)
Eine neue Version der Grafikbibliothek zum Erstellen wissenschaftlicher Diagramme (die Klasse CGraphic) wurde vor Kurzen veröffentlicht. Mit dieser Aktualisierung der weiterentwickelten Bibliothek, um grafische Interfaces zu erstellen, wird eine Version mit neuem Steuerelemente zur Erstellung von Diagrammen eingeführt. Jetzt ist es noch einfacher, Daten verschiedener Typen zu visualisieren.
Tiefe neuronale Netzwerke (Teil III). Stichprobenauswahl und Verminderung der Dimensionen Tiefe neuronale Netzwerke (Teil III). Stichprobenauswahl und Verminderung der Dimensionen
Dieser Artikel ist eine Fortsetzung der Artikelreihe über tiefe neuronale Netze. Hierbei werden wir die Auswahl von Stichproben (Rauschunterdrückung), die Verminderung der Dimensionen der Eingangsdaten und die Aufteilung der Daten in die Datensätze train/val/test bei der Datenaufbereitung für das Training des neuronalen Netzes besprechen.