MetaTrader 5 herunterladen

Orders, Positions und Abschlüsse in MetaTrader 5

15 Januar 2016, 11:21
MetaQuotes Software Corp.
0
697


Handelsbegriffe

Jeder Händler verfolgt als ultimatives Ziel mit den Mitteln von Handels-Operationen in Finanzmärkten Gewinne zu machen. Dieser Beitrag beschreibt die Begriffe und Vorgänge der MetaTrader 5 Handels-Plattform, deren Kenntnis zum angemessenen Verständnis der Funktionsweise von Handelsfunktionen der MQL5 Sprache notwendig ist

  • Orders — sind die Handels-Operations anfragen, die vom Handelsserver erhalten, und in Übereinstimmung mit den Anforderungen der MetaTrader 5 Plattform formuliert werden. Ist die Anfrage inkorrekt, erscheint sie nicht als Order auf der Handels-Plattform. Orders können sofortiger Ausführung sein, wie z.B. Kauf oder Verkauf eines gewissen Volumens zum aktuellen Marktkurs in einem spezifizierten Finanzinstrument. Eine weitere Art Orders sind ausstehende Orders, die den Auftrag beinhalten, eine Handels-Operation bei Vorhandensein einer gewissen Bedingung auszuführen. Ausstehende Orders können auch eine zeitliche Begrenzung ihrer Aktionen enthalten - nämlich ihr Ablaufdatum.

    Orders und Positions im MetaTrader 5 Terminal

    Die platzierten (ausstehenden) Orders, die auf die Bedingungen zu ihrer Ausführung oder Stornierung warten, sind im "Handels"-Tab im Terminal aufgeführt. Sie können verändert oder storniert werden. Die Platzierung, Stornierung und Veränderung von Orders erfolgt mit Hilfe der OrderSend() Funktion.  Wurde die Order storniert, erreicht sie ihr Ablaufdatum oder wurde ausgeführt, dann wird sie in die Order-History verschoben. Ausgeführte und stornierte Orders findet man im "History"-Tab des Client-Terminal. Orders aus der History können nicht mehr verändert werden.

  • Abschlüsse - sind das Ergebnis der Ausführung einer Order (ein Befehl den Abschluss zu machen). Jeder Abschluss basiert auf einer bestimmten Order. Doch kann eine einzige Order eine Reihe von Abschlüssen erzeugen. So kann z.B. die Order 10 Posten zu kaufen, durch mehrere aufeinander folgende Abschlüsse mit teilweisen Befüllungen ausgeführt werden. Abschlüsse werden stets in der Handels-History abgelegt und können nicht verändert werden. Im Terminal werden die Abschlüsse im "History"-Tab angezeigt

    Transaktionen im MetaTrader 5 Terminal

  • Positions sind die Kontrakte, die auf einem Finanzinstrument gekauft oder verkauft werdent Eine Long Position (Long) entsteht infolge von Käufen in Erwartung eines Kursanstiegs. Eine Short Position (Short) ist das Ergebnis des Verkaufs von Vermögen in Erwartung eines Kursverfalls. Für jeden Account und für jedes Finanzinstrument darf es nur eine Position geben. Für jedes Symbol, zu jeder x-beliebigen Zeit, darf nur eine offen Position geben - Long oder Short.

    Historische Orders im MetaTrader 5 Terminal

    Infolge einer neuen Handels-Operation in der gleichen Richtung kann das Volumen der Position ansteigen. D.h., das Volumen der Long Positions steigt nach jeden neuen Kauf (Kaufabschluss) an und schrumpft nach jedem Verkauf (Verkaufsabschluss). Die Position ist geschlossen, wenn das Volumen der Aktionen infolge der Handels-Operation gleich Null ist. Diese Aktion nennt man 'eine Position schließen'.

Hinweis: Aktive Orders und Positions werden immer im "Handels"-Tab angezeigt. Abschlüsse und Orders aus der History finden sich immer im "History"-Tab. Die aktive Order aus dem "Handels"-Tab darf nicht mit den historischen Orders aus dem "History"-Tab verwechselt werden.

 

Wie das Terminal die Handelsinformation vom Server erhält und speichert

Das Terminal speichert bei jeder Verbindung zum Handelsserver die Handels-History einer speziellen Basis, und erhält nur die fehlende History von Abschlüssen und abgeschlossenen Orders des Handels-Accounts. Der Grund dafür ist, den Traffic so gering wie möglich zu halten. Wird der MetaTrader 5 Client-Terminal geschlossen oder der aktuell aktive Account verändert, wird die gesamte History auf der Festplatte gespeichert und ab dem Zeitpunkt des nächsten Starts des Teminals erneut gelesen.

Alle Datenbanken werden verschlüsselt auf der Festplatte abgelegt; der Verschlüsselungscode hängt vom Computer ab, auf dem das Terminal installiert ist. Somit ist das Terminal vor unberechtigtem Datenzugriff im Falle des Kopierens geschützt.

Während der Verbindung zum Account lädt das Terminal die gespeicherte Account-Basis mit der Account-History und sendet eine Anfrage an den Handelsserver, seine eigene History-Datenbank mit der History des Accouts auf dem Handelsserver zu synchronisieren. Des Weiteren sendet der Handelsserver nach erfolgreicher Verbindung mit dem Account einen Bericht über die für den Account relevanten, ablaufenden Handelsereignisse an das Terminal.

Handelsereignisse sind die folgenden Veränderungen im Account

  • Ausstieg/Rücknahme und Saldo-Operationen;
  • Gebühren für Provisionen, Swaps (Tauschgeschäfte) und Steuern;
  • Platzierung, Löschung und Veränderung von Orders;
  • Ausführung von Abschlüssen auf Basis von Orders;
  • Öffnen und Schließen von Positions;
  • Änderungen im Volumen und der Richtung von Positions.

Sollte die Verbindung zum Handelsserver abreißen, versucht sich das Terminal in regelmäßigen Abständen wieder zu verbinden. Nach erneuter Verbindung mit dem Server, fordert das Terminal alle jüngsten Veränderungen in der Handels-History zur Aufrechterhaltung der Datenintegrität in seiner eigenen History-Datenbank an.

Die im "History"-Tab des Terminals angezeigte Handels-History stammt aus der Basis der Teminal-History; die im History-Terminal angezeigten Veränderungen des Zeitraums können den Bereich der in dieser Datenbank gespeicherten History, nur erhöhen. Eine Verringerung des Zeitraums der angezeigten History führt nicht zu einer tatsächlichen Entfernung der History aus der Basis des Terminals.

Installation des Intervalls der angezeigten Handels-History

Das bedeutete, dass die Installation eines kürzeren Intervalls der angezeigten History die Intensität der gespeicherten Handels-History nicht verringert. Doch wenn wir einen größeren Intervallbereich für eine Anzeige im "History"-Tab festlegen, sollte dies zu einer Anfrage vom Handelsserver nach einer fundierteren History führen, wenn die eigene Basis des Terminals die angefragten Daten für diesen Zeitraum noch nicht hat.

Die folgende Abbildung zeigt das generelle Interaktionsschema zwischen Terminal und dem MetaTrader 5 Handelsserver:


Während jedes Starts des Terminals, jedem erneuten Verbindungsaufbau zum Server nach einem Verbindungsfehler, einem Wechsel von einem Account zu einem anderen und der direkten Anfrage nach der fehlenden Handels-History sendet der Client-Terminal eine Synchronisierungs-Anfrage an seine eigene Handels-History Basis.

Der Handelsserver sendet nun seinerseits unabhängig und ohne Anfrage vom Terminal eine Client-Nachricht über die im Account stattfindenden Handelsereignisse: Veränderungen des Order- und Positions-Status, Ausführung von Abschlüssen auf Grundlage von Orders, anfallende Provisionsgebühren, sowie Saldo und die Entnahme von Geld usw.


Zugriff auf die Handels-History vom mql5-Programm

Das Terminal kann gleichzeitig mit einer Vielzahl von Indikatoren, Scripts und Expert Advisors arbeiten, und all diese Programme können die Informationen über den Handel verlangen, die sie benötigen: Order, Abschlüsse und Positions. Die direkte Arbeit des mql5- Programms mit der Datenbank des Terminals ist aufgrund allgemeiner Stabilitäts-, Sicherheits- und Leistungsüberlegungen ausgeschlossen.

Jedes mql5-Programm erhält für seine Arbeit auf Anfrage ein "Modell" der Handels-Umgebung in seinem Cache. Ein Cache ist ein bestimmter Bereich im Memory für raschen Datenzugriff. So muss z.B. vor Beginn der Verarbeitung einer Order, diese im Cache des mql5-Programms vorhanden sein. Jeder weitere Vorgang in Bezug auf diese Order, findet dann mit der 'Cache'-Kopie dieser Order statt.

Die Arbeit mit Positions, Abschlüssen und Orders aus der History findet auf ganz ähnliche Art statt. Die folgende Abbildung zeigt das generelle Schema zum Erhalt der Handelsinformation vom MQL5-Programm:


Bevor die Daten über die Handels-History für eine Verarbeitung des mql5-Programms zur Verfügung stehen, müssen sie zunächst von der Datenbank des Terminals verlangt werden. Nach der Anfrage werden die erhaltenen Daten in einen eignen Cache des mql5-Programms platziert. 

Hinweis: Die Daten im Cache werden nicht automatisch mit der Terminal-Datenbank synchronisiert und müssen daher regelmäßig aktualisiert werden, damit der angemessene Daten-Status im Cache auch gewährleistet ist.

Bei nicht korrekter Verwendung des Cache kann es ggf. zu unangenehmen Folgen kommen.

  • Werden die angefragten Daten nicht erhalten, bleibt das Cache leer und enthält die notwendigen Daten eben nicht. 
  • Müssen die Daten im Cache aktualisiert werden, doch ist eine Aktualisierung nicht angefragt worden, kann die Arbeit mit derartigen Daten zu unvorhersehbaren Ergebnissen führen. Sind z.B. die Daten zur aktuellen Position nicht aktualisiert, weiß das Programm nichts über die offene Position für ein gegebenes Symbol und über den entsprechend steigenden Verlust.

 

Die Funktion für die Arbeit mit dem Cache

Die Handels-History kann durchaus Tausende ausgeführter Order und Abschlüsse enthalten, die für die aktuelle Arbeit des mql5-Programms notwendig sind. Daher beruht die Arbeit mit dem Cache auf dem Anfrage-Prinzip: der Cache enthält immer die Information, die bei der letzten Verbindung zur Datenbank des Terminals geladen wurde. Wenn Sie also die komplette History der Orders und Abschlüsse brauchen, müssen Sie sie explizit durch Angabe des gewünschten Intervalls anfordern.

Für jede Art an Information wird ein unabhängiger Cache angelegt. Die Order-Daten befinden sich im Order-Cache, die Informationen zu Positions im Positions-Cache, und die Daten zu Abschlüssen und Orders sind in den entsprechenden Instanzen der History des Cache abgelegt.

Bevor Sie irgendwelche Informationen vom Cache anfordern können, muss es natürlich befüllt werden.

Hinweis: Jede Anfrage zur Befüllung des Cache löscht den bisherigen Inhalt - ungeachtet ob diese Anfrage ausgeführt wird oder nicht.


Die Handelsfunktionen können in zwei Kategorien unterteilt werden: die Funktionen zur Befüllung des Cache und die Funktionen zum Lesen der Informationen vom Cache.

 

Funktion zur Befüllung des Cache

Zur Bearbeitung der Handels-History muss sie zuerst im entsprechenden Cache enthalten sein und gefunden werden. Funktionen, die ein Cache bilden, können in zwei Untergruppen unterteilt werden:

Die Funktion zur Befüllung des Handels-Cache (aktive Order und Positions):

  • Die Funktion OrderSelect(ticket) -  kopiert die aktive Order nach ihrem Ticket (aus der Terminal-Basis) in den Cache der aktuellen Order für weitere Anfragen ihrer Eigenschaften mittels der OrderGetDouble(), OrderGetInteger() und OrderGetString() Funktionen.
  • Die Funktion OrderGetTicket(index) - kopiert, von der Terminal-Basis der aktiven Order, die aktive Order nach ihrem Index in der Order-Liste der Order-Terminal-Basis, in den Cache der aktuellen Order für weitere Anfragen ihrer Eigenschaften mittels der OrderGetDouble(), OrderGetInteger() und OrderGetString() Funktionen. Die Gesamtzahl der Order in der Terminal-Basis erhält man mit Hilfe der OrdersTotal() Funktion.
  • Die Funktion PositionSelect(symbol) - kopiert die offene Position nach Name des Symbols (aus der Terminal-Basis) in den Cache für weitere Anfragen ihrer Eigenschaften mittels der PositionGetDouble(),  PositionGetInteger() und PositionGetString() Funktionen.
  • Die Funktion PositionGetSymbol(index) - kopiert die offene Position nach ihrem Index in der Positions-Liste (aus der Terminal-Basis) der Terminal-Basis in den Cache für weitere Anfragen ihrer Eigenschaften mittels der PositionGetDouble(),  PositionGetInteger() und PositionGetString() Funktionen. Die Gesamtzahl der Order in der Terminal-Basis erhält man mit Hilfe der PositionsTotal() Funktion.

Die Funktion zur Befüllung des History-Cache:

  • Die Funktion HistoryOrderSelect(ticket) - kopiert die History nach ihrem Ticket in den Cache der History-Order (aus der Terminal-Basis) für weitere Aufrufe ihrer Eigenschaften mittels der HistoryOrderGetDouble(), HistoryOrderGetInteger() und HistoryOrderGetString() Funktionen.
  • Die Funktion HistoryDealSelect(ticket) - kopiert den Abschluss nach seinem Ticket in den Abschluss-Cache (aus der Terminal-Basis) für weitere Aufrufe seiner Eigenschaften mittels der HistoryDealGetDouble(), HistoryDealGetInteger()  und HistoryDealGetString() Funktionen.

Wir müssen hier die zwei Funktionen, die sich auf die im Cache vorhandene Handels-History im Allgemeinen auswirken, getrennt betrachten.

  • Die Funktion HistorySelect(start, end) - befüllt den History-Cache mit Abschlüssen und Orders für einen angegebenen Zeitintervall der Serverzeit. Die von HistoryDealsTotal() und HistoryOrdersTotal() gelieferten Werte hängen von den Ergebnissen der Ausführung dieser Funktion ab.
  • Die Funktion HistorySelectByPosition (position_ID) - befüllt den History-Cache mit Abschlüssen und Ordesr, die die angegebene Kennungsposition haben. Das Ergebnis der Ausführung dieser Funktion wirkt sich ebenfalls auf HistoryDealsTotal() und HistoryOrdersTotal() aus.


OrderSelect und OrderGetTicket

Die allgemeinen Funktionen OrderSelect(ticket) und OrderGetTicket() arbeiten genauso: sie befüllen den Cache der aktiven Order mit einer einzigen Order. Die Funktion OrderSelect(ticket) ist für den Fall gedacht, wenn eine Ticket-Order bereits im voraus bekannt ist. OrderGetTicket(), zusammen mit OrdersTotal(). ermöglichen die Untersuchung aller verfügbaren Orders in der Order-Terminal-Basis.

Nach einem Aufruf irgendeiner dieser Funktionen, enthält der Cache der aktiven Order die Information von nur einer Order, wenn die Order zuvor erfolgreich ausgewählt wurde. Andernfalls enthält dieser Cache keine Informationen. Das Ergebnis der Ausführung der Funktion OrdersTotal() verändert sich nie - es liefert immer die tatsächliche Anzahl der aktiven Order in der Terminal-Basis, egal ob der Cache voll ist oder nicht.

 

PositionSelect und PositionGetSymbol

Wie bei Orders auch, funktionieren diese zwei Funktionen für Positions genauso: sie befüllen den Positions-Cache mit einer einzelnen Position. Die Funktion PositionGetSymbol(index) verlangt die Anzahl in der Liste der Positions-Basis als einen Parameter, und die Funktion PositionSelect(symbol) befüllt den Cache auf Grundlage des Symbolnamen unter dem die Position eröffnet ist. Den Symbolnamen seinerseits erhält man mit Hilfe der Funktion PositionGetSymbol(index).

Nach Ausführen einer dieser Funktionen, enthält der Positions-Cache Daten zu nur einer Position, wenn die Funktion erfolgreich ausgeführt wurde. Ansonsten enthält dieser Cache keine Informationen. Das Ergebnis der Ausführung der Funktion PositionsTotal() hängt nicht davon ab, ob der Cache befüllt ist. Es liefert immer die tatsächliche Anzahl offener Positions in der Terminal-Basis für alle Symbole.

 

HistoryOrderSelect

HistoryOrderSelect(ticket) wählt die historische Order aus der Terminal-Basis nach ihrem Ticket in den Cache aus. Die Funktion wird dann verwendet, wenn das Ticket der erforderlichen Order im Voraus bekannt ist.

Wird sie erfolgreich ausgeführt, enthält der Cache eine einzelne Order und die HistoryOrdersTotal() Funktion liefert eine einzelne Einheit. Ansonsten bleibt der Cache der historischen Order leer und die HistoryOrdersTotal() Funktion liefert 0.


HistoryDealSelect

HistoryDealSelect(ticket) wählt den Abschluss aus der Terminal-Basis nach seinem Ticket. Die Funktion eird dann verwendet, wenn das Ticket des Abschlusses im Voraus bekannt ist.

Wird sie erfolgreich ausgeführt, enthält der Cache einen einzelnen Auftrag und die HistoryDealsTotal() Funktion liefert 1. Ansonsten bleibt der Cache des Abschlusses leer und die HistoryDealsTotal() Funktion liefert 0.

 

Die Funktion zum Abrufen von Informationen aus dem Cache

Vor der Anfrage nach Informationen zu Position-, Abschluss- oder Order-Eigenschaften, muss man den entsprechenden Cache des mql5-Programms natürlich aktualisieren. Und zwar deswegen, weil die angefragte Information ja bereits aktualisiert sein kann, was seinerseits bedeutet, dass die im Cache gespeicherte Kopie bereits veraltet ist.

  • Order
    Um Informationen zu aktiven Orders zu erhalten, muss sie zunächst in den Cache der aktiven Order einer der beiden folgenden Funktionen kopiert werden: OrderGetTicket() oder OrderSelect(). Die Eigenschaftswerte werden für die Order, die im Cache gespeichert ist, ausgegeben, wenn die entsprechenden Funktionen aufgerufen werden:
    1. OrderGetDouble(type_property)
    2. OrderGetInteger(type_property)
    3. OrderGetString(type_property)

Diese Funktionen erhalten all ihre Daten aus dem Cache. Daher wird empfohlen, wenn man exakte Order-Daten auch wirklich sicher erhalten will, die Funktion aufzurufen, die den Order-Cache befüllt.

  • Positions

    Um Informationen über eine Position zu bekommen, muss sie zuvor mit Hilfe einer der beiden Funktionen ausgewählt und in den Cache kopiert werden: PositionGetSymbol oder PositionSelect. Aus diesem Cache werden die Eigenschaftswerte für die Position ausgegeben, wenn die entsprechenden Funktionen aufgerufen werden:

    1. PositionGetDouble(type_property)
    2. PositionGetInteger(type_property)
    3. PositionGetString(type_property)

Da diese Funktionen all ihre Daten aus dem Cache erhalten, wird daher empfohlen, wenn man exakte Positions-Daten auch wirklich sicher erhalten will, die Funktion aufzurufen, die den Positions-Cache befüllt.

  • Historische Order

    Um Informationen über eine Order aus der History zu bekommen, muss zuvor der Cache der historischen Order mit Hilfe einer der drei Funktionen angelegt werden: HistorySelect(start, end), HistorySelectByPosition() oder HistoryOrderSelect(ticket). Ist die Implementierung erfolgreich, speichert der Cache die Anzahl der Order, die von der HistoryOrdersTotal() Funktion geliefert werden. Der Zugriff auf die Eigenschaften dieser Order erfolgt per jedem Element auf dem Ticket mit Hilfe der entsprechenden Funktionen:

    1. HistoryOrderGetDouble(ticket_order, type_property)
    2. HistoryOrderGetInteger(ticket_order, type_property)
    3. HistoryOrderGetString(ticket_order, type_property)

Das Ticket der historischen Order findet man mit Hilfe der HistoryOrderGetTicket(index) Funktion, und zwar per Index im Cache der historischen Order . Um exakte Order-Daten auch wirklich zu erhalten, wird empfohlen, die Funktion aufzurufen, die den Cache der historischen Order befüllt.

  • Abschlüsse

    Um Informationen über einen bestimmten Abschluss aus der History zu bekommen, muss zuvor der Abschluss-Cache mit Hilfe einer der drei Funktionen angelegt werden: HistorySelect(start, end), HistorySelectByPosition() oder HistoryDealSelect (ticket). Ist die Funktion erfolgreich implementiert, speichert der Cache die Anzahl der Abschlüsse, die von der HistoryDealsTotal() Funktion geliefert wird. Der Zugriff auf die Eigenschaften dieser Abschlüsse erfolgt auf Grundlage des Tickets, mit Hilfe der entsprechenden Funktionen:

    1. HistoryDealGetDouble(ticket_deals, type_property)
    2. HistoryDealGetInteger(ticket_deals, type_property)
    3. HistoryDealGetString(ticket_deals, type_property)

Das Ticket der Abschlüsse erhält man mit Hilfe der HistoryDealGetTicket(index) Funktion, per seinem Index im Abschluss-Cache. Will man exakte Abschluss-Daten auch wirklich bekommen, wird daher empfohlen, die Funktion aufzurufen, die den Abschluss-Cache befüllt.

Die Funktion zum Abrufen des Tickets aus der Cache-History

HistoryOrderGetTicket (index) liefert das Ticket der historischen Order, per ihrem Index aus dem Cache der historischen Order (nicht aus der Terminal-Basis!). Das erhaltene Ticket kann in der  HistoryOrderSelect (ticket) Funktion verwendet werden, die den Cache löscht und ihn bei Erfolg mit nur einer Order neu befüllt. Vergessen Sie nicht, dass der von HistoryOrdersTotal() gelieferte Wert von der Anzahl der Order im Cache abhängt.

HistoryDealGetTicket(index) liefert das Ticket des Abschlusses, per seinem Index aus dem Cache der Abschlüsse. Das erhaltene Ticket des Abschlusses kann in der  HistoryDealSelect (ticket) Funktion verwendet werden, die den Cache löscht und ihn bei Erfolg mit nur einem Abschluss neu befüllt. Der von der HistoryDealsTotal() Funktion gelieferte Wert hängt von der Anzahl der Abschlüsse im Cache ab.

Hinweis: Vor einem Aufrufen der HistoryOrderGetTicket (index) und HistoryDealGetTicket (Index) Funktionen, müssen der History-Cache in ausreichender Menge mit historischen Orders und Abschlüssen befüllt werden. Dies geht mit Hilfe einer der folgenden Funktionen: HistorySelect (Start, end), HistorySelectByPosition (Position_ID), HistoryOrderSelect (Ticket) und HistoryDealSelect (Ticket).

 

Information erhalten mit Hilfe aktiver Orders

Die Überprüfung der aktuell aktiven Orders ist ein Standardvorgang, der für den Erhalt von Informationen über eine bestimmte Order benötigt wird. Dies kann, wenn man ihr Ticket kennt, mit Hilfe der Funktion OrderSelect(ticket) gemacht werden.

bool selected=OrderSelect(ticket);
if(selected)
  {
   double price_open=OrderGetDouble(ORDER_PRICE_OPEN);
   datetime time_setup=OrderGetInteger(ORDER_TIME_SETUP);
   string symbol=OrderGetString(ORDER_SYMBOL);
   PrintFormat("Ордер #%d for %s was set at %s",ticket,symbol,TimeToString(time_setup));
  }
else
  {
   PrintFormat("Error selecting order with ticket %d. Error %d",ticket, GetLastError());
  }

Im obigen Beispiel wird davon ausgegangen, dass das Order-Ticket im Voraus bekannt ist und daher aus globaler Variable erhalten werden kann. Im Allgemeinen kennt man die Ticketinformation jedoch nicht. und daher muss hierzu die OrderGetTicket(index) Funktion verwendet werden, die zugleich eine Order auswählt und sie in den Cache platziert. Doch als Parameter muss nur die Ordernummer aus der Liste der aktuellen Orders spezifiziert werden. 

Der komplette Algorithmus zur Arbeit mit Orders (analog zu Abschlüssen und Positions) ist wie folgt:

  1. Erhalt der Gesamtzahl der Order mit Hilfe der OrdersTotal() Funktion;
  2. Organisation der Schleife durch Suche nach allen Order per Index in der Liste;
  3. Kopie jeder Order nacheinander in den Cache mittels der OrderGetTicket() Funktion;
  4. Erhalt der korrekten Order-Daten aus dem Cache mittels der OrderGetDouble(), OrderGetInteger() und OrderGetString() Funktionen. Ggf. noch Analyse der erhaltenen Daten und Einleitung entsprechender Maßnahmen.

Hier ist ein kurzes Beispiel eines derartigen Algorithmus:

input long my_magic=555;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- obtain the total number of orders
   int orders=OrdersTotal();
//--- scan the list of orders
   for(int i=0;i<orders;i++)
     {
      ResetLastError();
      //--- copy into the cache, the order by its number in the list
      ulong ticket=OrderGetTicket(i);
      if(ticket!=0)// if the order was successfully copied into the cache, work with it
        {
         double price_open  =OrderGetDouble(ORDER_PRICE_OPEN);
         datetime time_setup=OrderGetInteger(ORDER_TIME_SETUP);
         string symbol      =OrderGetString(ORDER_SYMBOL);
         long magic_number  =OrderGetInteger(ORDER_MAGIC);
         if(magic_number==my_magic)
           {
            //  process the order with the specified ORDER_MAGIC
           }
         PrintFormat("Order #%d for %s was set out %s, ORDER_MAGIC=%d",ticket,symbol,TimeToString(time_setup),magic_number);
        }
      else         // call OrderGetTicket() was completed unsuccessfully
        {
         PrintFormat("Error when obtaining an order from the list to the cache. Error code: %d",GetLastError());
        }
     }
  }

 

Informationen zu offenen Positions erhalten

Die konstante Überwachung offener Positions ist nicht nur ein Standardverfahren, sondern sollte auf jeden Fall in jede Instanz implementiert werden. Um Informationen zu bestimmten Positions zu erhalten, genügt es, den Namen des Instruments zu kennen, durch das sie geöffnet werden. Dies geschieht mit Hilfe der Funktion PositionSelect(symbol). In den Fällen, in denen der Expert Advisor nur auf einem Symbol arbeitet (auf dem Symbol des Charts, an das er angehängt ist), erhält man den Symbolnamen durch eine Symbol() Funktion oder von einer vorab festgelegten _Symbol Variable.

//--- we will look for the position by the symbol of the chart, on which the EA is working
   string symbol=Symbol();
//--- attempt to get the position
   bool selected=PositionSelect(symbol);
   if(selected) // if the position is selected
     {
      long pos_id            =PositionGetInteger(POSITION_IDENTIFIER);
      double price           =PositionGetDouble(POSITION_PRICE_OPEN);
      ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
      long pos_magic         =PositionGetInteger(POSITION_MAGIC);
      string comment         =PositionGetString(POSITION_COMMENT);
      PrintFormat("Position #%d by %s: POSITION_MAGIC=%d, price=%G, type=%s, commentary=%s",
                 pos_id, symbol, pos_magic, price,EnumToString(type), comment);
     }

   else        // if selecting the position was unsuccessful
     {
      PrintFormat("Unsuccessful selection of the position by the symbol %s. Error",symbol,GetLastError());
     }
  }

Generell erhält man die Information zum Symbol mit Hilfe der PositionGetSymbol (Index) Funktion, die eine Position auswählt und sie in den Cache platziert. Als Parameter muss der Index der Position in der Liste de offenen Positions spezifiziert werden. Dies macht man am besten mit einer Suche aller Positions in der Schleife.

Dies ist der allgemeine Algorithmus zur Arbeit mit Positions:

  1. Erhalt der Gesamtzahl der Positions mit Hilfe der PositionsTotal() Funktion;
  2. Organisation der Schleife durch Suche nach allen Positions per Index in der Liste;
  3. Kopie jeder Order nacheinander in den Cache mittels der PositionGetSymbol() Funktion;
  4. Erhalt der notwendigen Positions-Daten aus dem Cache mittels der PositionGetDouble(), PositionGetInteger() und PositionGetString() Funktionen. Ggf. noch Analyse der erhaltenen Daten und Einleitung entsprechender Maßnahmen.

Hier ist ein kurzes Beispiel eines derartigen Algorithmus:

#property script_show_inputs

input long my_magic=555;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- obtain the total number of positions
   int positions=PositionsTotal();
//--- scan the list of orders
   for(int i=0;i<positions;i++)
     {
      ResetLastError();
      //--- copy into the cache, the position by its number in the list
      string symbol=PositionGetSymbol(i); //  obtain the name of the symbol by which the position was opened
      if(symbol!="") // the position was copied into the cache, work with it
        {
         long pos_id            =PositionGetInteger(POSITION_IDENTIFIER);
         double price           =PositionGetDouble(POSITION_PRICE_OPEN);
         ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
         long pos_magic         =PositionGetInteger(POSITION_MAGIC);
         string comment         =PositionGetString(POSITION_COMMENT);
         if(pos_magic==my_magic)
           {
           //  process the position with a specified POSITION_MAGIC
           }
         PrintFormat("Position #%d by %s: POSITION_MAGIC=%d, price=%G, type=%s, commentary=%s",
                     pos_id,symbol,pos_magic,price,EnumToString(type),comment);
        }
      else           // call to PositionGetSymbol() was unsuccessful
        {
         PrintFormat("Error when receiving into the cache the position with index %d."+
                     " Error code: %d", i, GetLastError());
        }
     }
  }

Regeln zur Arbeit mit dem History-Cache

Der Code zur Arbeit mit dem History-Cache wird vom Programmierern oft so geschrieben, dass er nur dann reibungslos funktioniert, wenn das History 5-10 Abschlüsse und Orders enthält. Typisches Beispiel für einen falschen Ansatz ist, die gesamte Handels-History in den Cache zu laden und sie in einer Schleife zu bearbeiten und per aller Orders und Handel zu suchen:

//---
   datetime start=0;           // initial time set to 1970 year
   datetime end=TimeCurrent();  // the ending time set to the current server time
//--- request into the cache of the program the entire trading history
   HistorySelect(start,end);
//--- obtain the number of all of the orders in the history
   int history_orders=HistoryOrdersTotal();
//--- now scan through all of the orders
   for(int i=0;i<history_orders;i++)
     {
     //  processing each order in the history
     }   
 
    ...
       
//--- obtain the number of all deals in the history
   int deals=HistoryDealsTotal();
//--- now scan through all of the deals
   for(int i=0;i<deals;i++)
     {
     //  process each deal in the history
     }

Der Versuch, die gesamte Handels-History zu bearbeiten, erweist sich in den meisten Fällen als falsch. Sobald die Anzahl der bearbeiteten Abschlüsse/Orders ungefähr 1000 oder sogar 10000 erreicht, wird die Arbeit des Programms ganz erheblich verlangsamt.

Hinweis: Bitte beziehen Sie sich stets mit Vorsicht auf alle Fälle des Aufrufs der HistorySelect() Funktion! Gedankenloses und übermäßiges Laden der gesamten, vorhandenen Handels-History in den Cache des mql5-Programms wirkt sich nachteilig auf seine Leistung aus.

Dies ist insbesondere für das Testen wichtig: Der Benutzer stellt fest, das der Tester plötzlich 'nachdenklich' wird und im Client-Terminal nach den Ursachen dafür zu suchen beginnt. Daher sollte man immer zuerst über die Optimierung des Codes des mql5-Programms nachdenken (Expert Advisor und Indikatoren, die vom EA aufgerufen werden). Verlassen Sie sich bitte niemals auf die Tatsache, dass der Computer ein robustes Blechteil mit vielen Rechnerkernen ist.

Dies gilt ganz genauso, wenn der EA und der Indikator auch Online reibungslos arbeiten sollen. Ein sub-optimaler Programmcode kann die Arbeit selbst des stärksten Computer lähmen. 

Der korrekte Algorithmus für die Arbeit mit der Handels-History:

  1. Den Bedarf zur Abfrage der Handels-History in den Cache festlegen. Ist dies nicht notwendig, die folgenden Aktionen nicht ausführen.
  2. Die endgültigen Daten der Handels-History festlegen (vielleicht ist die Histoire zum jetzigen Zeitpunkt noch gar nicht nötig);
  3. Das Anfangsdatum der Handels-History berechnen, und dabei vom Enddatum aus beginnen. Meist benötigen EAs eine Handels-History, die nicht weiter als einen einzigen Tag oder eine Woche zurückreicht;
  4. Die Tickets der Abschlüsse und historischen Orders via ihrer bekannten Tickets erhalten, um an ihre Eigenschaften zu gelangen:
    • HistoryOrderGetDouble()
    • HistoryOrderGetInteger()
    • HistoryOrderGetString()
    • HistoryDealGetDouble()
    • HistoryDealGetInteger()
    • HistoryDealGetString()
  5. Sind die Tickets nicht bekannt, dann ggf. einen Zyklus via Sortierung organisieren;
  6. Das Ticket für jeden Abschluss/Order in der Schleife aus dem Cache der Handels-History via dem Index (HistoryOrderGetTicket(Index) und HistoryDealGetTicket(Index)) erhalten;
  7. Die notwendigen Order- und Abschlusseigenschaften per ihrem bekannten Ticket erhalten (vgl. Punkt 4).

Hier ist ein Beispiel für einen Code für diesen Algorithmus:

//--- the variable, which is set in true only during the change in the trading history
   bool TradeHistoryChanged=false;
//--- here we check for the changes in the history and put out the TradeHistoryChanged=true if needed
//... the needed code

//--- check  if there are changes in the trading history or not
   if(!TradeHistoryChanged) return;

//--- if the history has changed, then it makes sense to load it into the cache 
//--- the ending time set for the current server time
   datetime end=TimeCurrent();
//--- the beginning time is set to 3 days ago
   datetime start=end-3*PeriodSeconds(PERIOD_D1);
//--- request in the cache of the program, the trading history for the last 3 days
   HistorySelect(start,end);
//--- obtain the number of orders in the cache of the history
   int history_orders=HistoryOrdersTotal();
//--- now scan through the orders
   for(int i=0;i<history_orders;i++)
     {
      //--- obtain the ticket of the historical order
      ulong ticket=HistoryOrderGetTicket(i);
      //--- work with this order - receive its problems
      long order_magic=HistoryOrderGetInteger(ticket,ORDER_MAGIC);
      // obtain the rest of the properties for the order by the ticket
      // ...
     }

Die Grundidee, die dieses Beispiel zeigt, ist: zuerst muss verifiziert werden, ob Veränderungen in der Handels-History stattfinden. Eine der Optionen hierfür ist, innerhalb der OnTrade() Funktion, die globale Variable auf TradeHistoryChanged und den Wert auf true zu stellen, da das Ereignis Handels immer mit einer Art von Handelsereignis geliefert wird.

Hat sich die Handels-History nicht verändert, muss die sie nicht abermals in den Cache geladen werden. Das wäre nur eine CPU-Verschwendung. Logisch oder? Das muss ich nicht extra erklären. Hat sich die Handels-History verändert, laden wir nur ihren notwendigen Teil hoch und gehen jeden Abschluss/jede Order nur einmal durch. Unnötige Wiederholungszyklen bitte vermeiden.

Hinweis: Jede Anfrage an den Cache der kompletten Handels-History, die durch die Funktion HistorySelect() ausgeführt wird, und jeder Bearbeitungszyklus von Abschlüssen und Orders aus der History, müssen begründet sein. Ansonsten verschwenden Sie nur die Ressourcen Ihre Computers.

Beispiele für korrekte und inkorrekte Arbeit mit der Handels-History finden Sie im Anhang an diesen Beitrag, und zwar als WrongWorkWithHistory.mq5 und RightWorkWithHistory.mq5 Dateien.

 

Informationen aus der History per Orders erhalten

Die Arbeit mit historischen Orders funktioniert fast ganz genauso wie die mit aktiven Orders, allerdings mit einer Ausnahme: Wenn die Anzahl der aktiven Order im Cache des mql5-Programms nur maximal eine sein kann, hängen das Ergebnis HistoryOrdersTotal() und die Anzahl der historischen Order im Cache davon ab, wie viel Handels-History von der HistorySelect(start, end), HistorySelectByPosition() oder HistoryOrderSelection() Funktion geladen worden ist.

Hinweis: Ist die Handels-History nicht in den Cache des mql5-Programms durch einer der Funktionen HistorySelect(), HistorySelectByPosition() oder HistoryOrderSelect() geladen worden, dann kann nicht mit historischen Order und Abschlüssen gearbeitet werden. Achten Sie also darauf, die erforderliche History an Abschlüssen und Order anzufordern, bevor Sie die Daten zur Handels-History erhalten.

Wir bieten z.B. ein Script an, das nach der letzten Order am letzten Tag sucht und die entsprechenden Informationen anzeigt .

// --- determining the time intervals of the required trading history
   datetime end=TimeCurrent();                // current server time
   datetime start=end-PeriodSeconds(PERIOD_D1);// set the beginning for 24 hours ago
//--- request in the cache of the program the trading history for a day
   HistorySelect(start,end);
//--- receive the number of orders in the history
   int history_orders=HistoryOrdersTotal();
//--- obtain the ticket of the order, which has the last index in the list, from the history
   ulong order_ticket=HistoryOrderGetTicket(history_orders-1);
   if(order_ticket>0) // obtain in the cache the historical order, work with it
     {
      //--- order status
      ENUM_ORDER_STATE state=(ENUM_ORDER_STATE)HistoryOrderGetInteger(order_ticket,ORDER_STATE);
      long order_magic      =HistoryOrderGetInteger(order_ticket,ORDER_MAGIC);
      long pos_ID           =HistoryOrderGetInteger(order_ticket,ORDER_POSITION_ID);
      PrintFormat("Order #%d: ORDER_MAGIC=#%d, ORDER_STATE=%d, ORDER_POSITION_ID=%d",
                  order_ticket,order_magic,EnumToString(state),pos_ID);
     }
   else              // unsuccessful attempt to obtain the order
     {
      PrintFormat("In total, in the history of %d orders, we couldn't select the order"+
                  " with the index %d. Error %d",history_orders,history_orders-1,GetLastError());
     }
 

In eher allgemeineren Fällen muss Order-Schleife vom Cache durchgesehen und analysiert werden. Der allgemeine Algorithmus dazu lautet wie folgt:

  1. Festlegung der Zeitbereiche der ausreichenden History. Ist die History von der Funktion HistorySelect() geladen, ist es nicht ratsam, die gesamte Handels-History in den Cache zu laden;
  2. In den Programm-Cache bitte nur die Handels-History HistorySelect(), HistorySelectByPosition() oder HistoryOrderSelect (Ticket) Funktionen laden;
  3. Mit Hilfe von HistoryOrdersTotal(), die Gesamtzahl der Orders im Cache erhalten;
  4. Den Zyklus per Suche nach allen Order in der Liste nach ihrem Index organisieren;
  5. Mit Hilfe der HistoryOrderGetTicket() Funktion ein Ticket der Order im Cache erhalten;
  6. Mit Hilfe der HistoryOrderGetDouble(), HistoryOrderGetInteger() und HistoryOrderGetString() Funktionen die Daten der Order vom Cache erhalten. Ggf. noch Analyse der erhaltenen Daten und Einleitung entsprechender Maßnahmen.

Beispiel eines derartigen Algorithmus:

#property script_show_inputs

input long my_magic=999;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
// --- setting the time intervals of the required trading history
   datetime end=TimeCurrent();                // the current server time
   datetime start=end-PeriodSeconds(PERIOD_D1);// set the beginning for 24 hours ago
//--- request into the cache of the program the needed interval of the trading history
   HistorySelect(start,end);
//--- obtain the number of orders in history
   int history_orders=HistoryOrdersTotal();
//--- now scroll through all of the orders
   for(int i=0;i<history_orders;i++)
     {
      //--- obtain the ticket of the order by its number in the list
      ulong order_ticket=HistoryOrderGetTicket(i);
      if(order_ticket>0) //  obtain in the cache, the historical order, and work with it
        {
         //--- time of execution
         datetime time_done=HistoryOrderGetInteger(order_ticket,ORDER_TIME_DONE);
         long order_magic  =HistoryOrderGetInteger(order_ticket,ORDER_MAGIC);
         long pos_ID       =HistoryOrderGetInteger(order_ticket,ORDER_POSITION_ID);
         if(order_magic==my_magic)
           {
           //  process the position with the set ORDER_MAGIC
           }
         PrintFormat("Order #%d: ORDER_MAGIC=#%d, time_done %s, ORDER_POSITION_ID=%d",
                     order_ticket,order_magic,TimeToString(time_done),pos_ID);
        }
      else               // unsuccessful attempt to obtain the order from the history
        {
         PrintFormat("we were not able to select the order with the index %d. Error %d",
                     i,GetLastError());
        }
     }
  }
Hinweis: Bitte beziehen sich stets mit Vorsicht auf alle Fälle des Aufrufs der HistorySelect() Funktion! Gedankenloses und übermäßiges Laden der gesamten vorhandenen Handels-History in den Cache des mql5-Programms wirkt sich nachteilig auf seine Leistung aus.

 

Informationen zu Abschlüssen aus der History erhalten

Die Verarbeitung von Abschlüssen vollzieht sich auf die gleiche Art wie die Verarbeitung historischer Orders. Die Anzahl der Abschlüsse in der Handels-History und das Ergebnis der Ausführung von HistoryDealsTotal() hängen davon ab, wie viel Handels-History von der HistorySelect(start, end) oder HistorySelectByPosition() Funktion in den Cache geladen wurde.

Die Befüllung des Cache mit nur einem Abschluss per seinem Ticket geschieht mittels der HistoryDealSelect(ticket) Funktion.

// --- determining the time intervals of the required trading history
   datetime end=TimeCurrent();                // current sever time
   datetime start=end-PeriodSeconds(PERIOD_D1);// set the beginning for 24 hours ago
//--- request in the cache of the program the needed interval of the trading history
   HistorySelect(start,end);
//--- obtain the number of deals in history
   int deals=HistoryDealsTotal();
//--- obtain the ticket for the deal, which has the last index in the list
   ulong deal_ticket=HistoryDealGetTicket(deals-1);
   if(deal_ticket>0) // we obtained in the cache of the deal, and work with it
     {
      //--- the ticket order, based on which the deal was made
      ulong order     =HistoryDealGetInteger(deal_ticket,DEAL_ORDER);
      long order_magic=HistoryDealGetInteger(deal_ticket,DEAL_MAGIC);
      long pos_ID     =HistoryDealGetInteger(deal_ticket,DEAL_POSITION_ID);
      PrintFormat("Deal #%d for the order #%d with the ORDER_MAGIC=%d  that participated in the position",
                  deals-1,order,order_magic,pos_ID);
     }
   else              // unsuccessful attempt of obtaining a deal
     {
      PrintFormat("In total, in the history %d of deals, we couldn't select a deal"+
                  " with the index %d. Error %d",deals,deals-1,GetLastError());
     }

In eher allgemeineren Fällen müssen die Abschluss-Schleife vom Cache durchgesehen und analysiert werden. Der allgemeine Agorithmus ist wie folgt:

  1. Festlegung der Grenzten der ausreichenden History. Wenn die History durch die HistorySelect(start, end) Funktion lädt, ist es nicht ratsam, die gesamte Handels-History in den Cache zu laden;
  2. In den Programm-Cache bitte nur die Handels-History der Funktionen HistorySelect() oder HistorySelectByPosition() laden;
  3. Mit Hilfe der HistoryDealsTotal() Funktion die Gesamtzahl der Abschlüsse im Cache erhalten;
  4. Den Zyklus per Suche nach allen Abschlüssen per ihren Nummern in der Liste organisieren;
  5. Mit Hilfe von HistoryDealGetTicket(), das Ticket des nächsten Abschlusses im Cache festlegen;
  6. Mit Hilfe der HistoryDealGetDouble(), HistoryDealGetInteger() und HistoryDealGetString() Funktionen die Informationen zum Abschluss vom Cache erhalten. Ggf. noch Analyse der erhaltenen Daten und Einleitung entsprechender Maßnahmen.

Beispiel eines derartigen Algorithmus zur Gewinn- und Verlustberechnung:

input long my_magic=111;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
// --- determine the time intervals of the required trading history
   datetime end=TimeCurrent();                 // current server time
   datetime start=end-PeriodSeconds(PERIOD_D1);// set the beginning time to 24 hours ago

//--- request in the cache of the program the needed interval of the trading history
   HistorySelect(start,end);
//--- obtain the number of deals in the history
   int deals=HistoryDealsTotal();

   int returns=0;
   double profit=0;
   double loss=0;
//--- scan through all of the deals in the history
   for(int i=0;i<deals;i++)
     {
      //--- obtain the ticket of the deals by its index in the list
      ulong deal_ticket=HistoryDealGetTicket(i);
      if(deal_ticket>0) // obtain into the cache the deal, and work with it
        {
         string symbol             =HistoryDealGetString(deal_ticket,DEAL_SYMBOL);
         datetime time             =HistoryDealGetInteger(deal_ticket,DEAL_TIME);
         ulong order               =HistoryDealGetInteger(deal_ticket,DEAL_ORDER);
         long order_magic          =HistoryDealGetInteger(deal_ticket,DEAL_MAGIC);
         long pos_ID               =HistoryDealGetInteger(deal_ticket,DEAL_POSITION_ID);
         ENUM_DEAL_ENTRY entry_type=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal_ticket,DEAL_ENTRY);

         //--- process the deals with the indicated DEAL_MAGIC
         if(order_magic==my_magic)
           {
            //... necessary actions
           }

         //--- calculate the losses and profits with a fixed results
         if(entry_type==DEAL_ENTRY_OUT)
          {
            //--- increase the number of deals 
            returns++;
            //--- result of fixation
            double result=HistoryDealGetDouble(deal_ticket,DEAL_PROFIT);
            //--- input the positive results into the summarized profit
            if(result>0) profit+=result;
            //--- input the negative results into the summarized losses
            if(result<0) loss+=result;
           }
        }
      else // unsuccessful attempt to obtain a deal
        {
         PrintFormat("We couldn't select a deal, with the index %d. Error %d",
                     i,GetLastError());
        }
     }
   //--- output the results of the calculations
   PrintFormat("The total number of %d deals with a financial result. Profit=%.2f , Loss= %.2f",
               returns,profit,loss);
  }
Hinweis: Bitte beziehen sich stets mit Vorsicht auf alle Fälle des Aufrufs der HistorySelect() Funktion! Gedankenloses und übermäßiges Laden der gesamten vorhandenen Handels-History in den Cache des mql5-Programms wirkt sich nachteilig auf seine Leistung aus.

 

Abschlüsse im Cache der History durch Positionskennung erhalten (POSITION_IDENTIFIER) ???? obtaining what

Die HistorySelectByPosition (position_ID) Funktion befüllt, genauso wie die HistorySelect (start, end) Funktion, den Cache mit Abschlüssen und Orders aus der History, doch nur unter einer Bedingung: sie müssen die spezifizierte Positionskennung haben (POSITION_IDENTIFIER). Diese Positionskennung ist eine eindeutige Zahl, die automatisch jeder wieder eröffneten Position zugewiesen wird und sich für sie niemals ändert. Man muss also daran denken, dass eine Veränderung der Position (Verschiebung der Art der Position von POSITION_TYPE_BUY zu POSITION_TYPE_SELL) die Kennung dieser Position nicht ändert.

Jede offene Position ist das Ergebnis eines oder mehrerer Abschlüsse in diesem Instrument. Um daher die Positionsveränderungen während ihrer gesamten Zeit zu analysieren, wird jedem Abschluss und jeder Order, je nach dem wo der Abschluss getätigt wurde, eine entsprechende Kennung der Position zugewiesen, an der der Abschluss 'beteiligt' war. Wenn wir also die Kennung der aktuellen offenen Positions wissen, können wir die gesamte History rekonstruieren - und alle Order und Abschlüsse finden, die sie verändert haben.

Die HistorySelectByPosition(position_ID) Funktion erspart es dem Programmierer, keine eigenen Codes zum wiederholten Durchsuchen der gesamten Handels-History nach derartiger Information schreiben zu müssen. Ein typischer Algorithmus zur Arbeit mit dieser Funktion:

  1. die richtige Positionskennung erhalten;
  2. mit Hilfe der HistorySelectByPosition() Funktion im Cache der Handels-History alle Orders und Abschlüsse erhalten, die die gleiche Kennung wie aktuelle Position besitzen;
  3. die Handels-History gemäß dieses Algorithmus bearbeiten.

 

Fazit

Die gesamte Handels-Subsystem Plattform MetaTrader 5 ist ziemlich gut durchdacht und benutzerfreundlich angelegt. Darüber hinaus erlaubt uns die Vielzahl an Handelsfunktionen, jedes spezifische Problem auf maximal effiziente Weise zu lösen.

Doch selbst angesichts der Tatsache, dass uns die spezialisierten Handelsklassen aus der Standard-Bibliothek gestatten, uns nicht zu viel den Kopf über unzählige Nuancen zerbrechen und Programme auf einem hohen Niveau schreiben zu müssen, ohne in die Implementierung zu gehen, gestattet das Verständnis der Grundlagen die Erzeugung zuverlässiger und effizienter Expert Advisors für Handel.

Alle in diesem Beitrag gezeigten Beispiel sind in den Dateien im Anhang vorhanden.

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

Leitfaden zum Testen und Optimieren von Expert Advisors in MQL5 Leitfaden zum Testen und Optimieren von Expert Advisors in MQL5

Dieser Beitrag erklärt den schrittweisen Vorgang zur Identifizierung und Lösung von Fehlern im Code sowie alle Schritte für das Testen und die Optimierung der Expert Advisor Eingabeparameter. Sie lernen hier, wie Sie den Strategie-Tester des MetaTrader 5 Client-Terminals verwenden, um das beste Symbol und Set an Eingabeparameter für Ihren Expert Advisor zu finden.

Adaptive Handelssysteme und ihre Verwendung im MetaTrader 5 Client-Terminal Adaptive Handelssysteme und ihre Verwendung im MetaTrader 5 Client-Terminal

Dieser Beitrag möchte eine Variante eines adaptiven Systems vorstellen, die aus vielen Strategien besteht, von denen jede ihre eigenen "virtuellen" Handels-Operationen durchführt. Echter Handel wird in Übereinstimmung mit den Signalen der in diesem Augenblick gewinnbringendsten Strategie ausgeführt. Dank der Verwendung des Objekt-orientierten Ansatzes, der Klassen zur Arbeit mit Daten und der Handelsklassen der Standardbibliothek, macht die Architektur des Systems einen einfachen und aufrüstbaren Eindruck. Jetzt kann man leicht adaptive Systeme mit Hunderten von Handelsstrategien erzeugen und analysieren.

Handelsereignisse in MetaTrader 5 Handelsereignisse in MetaTrader 5

Eine Überwachung des aktuellen Status eines Handels-Account bedeutet offene Positions und Order kontrollieren zu können. Bevor ein Handelssignal zu einem Abschluss wird, sollte es vom Client-Terminal als Anfrage zum Handels-Server geschickt werden, wo es in eine Order-Warteschlange gestellt wird und auf seine Bearbeitung wartet. Eine Anfrage vom Handels-Server annehmen, sie löschen, wenn sie abläuft oder auf ihrer Grundlage einen Abschluss ausführen - alle diese Handlungen haben Handelsereignisse zur Folge, und der Handels-Server informiert das Terminal entsprechend darüber.

Die Grundlagen für Tests in MetaTrader 5 Die Grundlagen für Tests in MetaTrader 5

Worin unterscheiden sich die drei Testmethoden in MetaTrader 5, und worauf sollte man ganz besonders achten? Wir laufen Tests eines Expert Advisors, der gleichzeitig auf verschiedenen Finanzinstrumenten handelt, ab? Wann und wie werden Indikatorwerte während der Tests berechnet und wie werden die Ereignisse behandelt? Wie synchronisiert man Bars aus unterschiedlichen Instrumenten während der Tests im Mosud "nur offene Kurse"? Der vorliegende Artikel versucht all diese und weitere Fragen zu beantworten.