MetaTrader 5 herunterladen

Der Einsatz von MQL5 Standard Library Handelsklassen beim Schreiben eines Expert Advisors

9 März 2016, 11:33
Samuel Olowoyo
0
716

Einleitung

Das neue MQL5 Programm besitzt eine Menge eingebauter Standardklassen-Libraries, mit deren Hilfe Trader und Entwickler MQL5 Expert Advisors, Indikatoren und Skripts sehr leicht weiterentwickeln können.

Diese Klassen-Libraries sind im \Include\ Ordner, innerhalb des MQL5 Ordners im MetaTrader 5 Client-Terminal Ordner zu finden. Die Klassen-Libraries sind in vier Kategorien unterteilt – Arrays, ChartObjekte, Charts, Dateien, Indikators, Strings und Handelsklassen.

Dieser Beitrag beschreibt en detail wie man die eingebauten Handelsklassen zum Schreiben eines Expert Advisors verwenden kann. Der Expert Advisor beruht dabei auf einer Strategie, die das Schließen und Ändern von geöffneten Positions umfasst, sobald eine vorgeschriebene Bedingung erfüllt ist.

Wenn Sie bereits eine Vorstellung davon haben, was Klassen sind und wie man mit ihnen arbeitet, dann finden Sie hier eine andere Welt an Möglichkeiten, die Ihnen die neue MQL5 Programmiersprache bietet.

Sollten Sie allerdings ein kompletter Neuling bzgl. MQL5 sein, dann empfehle ich Ihnen zunächst diese beiden Beiträge zu lesen: Schrittweiser Leitfaden zum Schreiben eines Expert Advisors MQL5 für Anfänger, Einen Expert Advisor mit Hilfe des MQL5 Objekt-orientierten Programmierungsansatzes schreiben. Oder jeden anderen Beitrag, der Ihnen eine ausreichende Einführung in die neue MQL5 Sprache bietet. Zu diesem Thema sind eine Menge Beiträge verfasst worden, die Ihnen alle das erforderliche Grundlagenwissen vermitteln werden.


1. Handelsklassen

Der Ordner 'Handelsklassen' umfasst verschiedene Klassen, die jedem Trader, der einen EA für seinen persönlichen Gebrauch entwickeln oder jedem Programmierer, der bei der Entwicklung seines Expert Advisors (EA) das Rad nicht neu erfinden will, die Arbeit erheblich erleichtern werden.

Wenn Sie eine Klasse verwenden,müssen Sie die internen Abläufe der Klasse (also, wie sie das erreicht, was der Entwickler sagt, dass sie es kann) nicht kennen - Sie müssen sich einzig und allein darauf konzentrieren, wie diese Klasse zur Lösung Ihres Problems angewendet werden kann. Deshalb erleichtert die Verwendung einer eingebauten Klassen-Library jedermann, der Klassen verwenden will, die Arbeit ganz enorm. In diesem Beitrag sehen wir uns die wichtigsten Klassen an, die im Laufe der Entwicklung eines Expert Advisors gebraucht werden.

Dabei werden wir uns nicht bei den internen Details dieser Klassen aufhalten, sondern ausführlich besprechen, was die Klasse leisten kann und wie wir sie dazu bringen können, unseren Auftrag auszuführen - nämlich die Entwicklung eines sehr ertragreichen EAs. Doch gehen wir Schritt für Schritt vor.

1.1 Die СAccountInfo Klasse

Die CAccountInfo ist eine Klasse, die dem Benutzer den Zugriff auf alle Account-Eigenschaften oder Informationen für den aktuell offenen Handels-Account im Client-Terminal erleichtert.

Zum besseren Verständnis sehen wir uns jetzt die wichtigsten Mitgliedsfunktionen dieser Klasse an, die wir wahrscheinlich für unseren EA brauchen. Bevor wir eine Klasse verwenden können, müssen wir zunächst ein Objekt dieser Klasse erzeugen. Um also die CAccountInfo Klasse verwenden zu können, müssen wir ein Objekt dieser Klasse erzeugen.

Nennen wir es myaccount:

//--- The AccountInfo Class Object
CAccountInfo myaccount;

Beachten Sie bitte, dass zur Erzeugung eines Objekts einer Klasse, der Name der Klasse gefolgt von dem Namen, den Sie dem Objekt geben möchten, angewendet werden muss.

Wir können nun das myaccount Objekt dazu nutzen, um auf die public Mitgliedsfunktionen der CAccountInfo Klasse zuzugreifen.

Methode Beschreibung Anwendungsbeispiel
myaccount.Login()

Diese Funktion wird eingesetzt, wenn Sie die Account-Nummer für den aktuell offenen Handel im Terminal erhalten möchten.

// returns account number, example 7770
long accountno = myaccount.Login()
myaccount.TradeModeDescription() Diese Funktion wird eingesetzt, wenn Sie die Beschreibung des Handels-Modus für den aktuell aktiven Account im Terminal erhalten möchten.
// returns Demo trading account, 
// or Real trading account or Contest trading account
string  acc_trading_mode = myaccount.TradeModeDescription();
myaccount.Leverage()

Diese Funktion wird eingesetzt, wenn Sie die Beschreibung des Handels-Modus für den aktuell aktiven Account im Terminal erhalten möchten.

// returns leverage given to the active account
long acc_leverage = myaccount.Leverage(); 
myaccount.TradeAllowed()

Diese Funktion wird eingesetzt, wenn Sie prüfen wollen, ob der Handel auf dem aktiven Account im Terminal erlaubt ist. Ist der Handel nicht erlaubt, kann der Account nicht handeln.

if (myaccount.TradeAllowed())
{
    // trade is allowed
}
else
{
  // trade is not allowed
}
myaccount.TradeExpert() Diese Funktion wird eingesetzt, wenn Sie prüfen wollen, ob Expert Advisors für den aktuell aktiven Account im Terminal Handel durchführen dürfen.
if (myaccount.TradeExpert())
{
   // Expert Advisor trade is allowed
}
else
{
   // Expert Advisor trade is not allowed
}
myaccount.Balance() Diese Funktion gibt Ihnen den Account-Saldo für den aktiven Account im Terminal.
// returns account balance in the deposit currency
double acс_balance =  myaccount.Balance();
myaccount.Profit()

Diese Funktion wird eingesetzt, wenn Sie den aktuellen Gewinn des aktiven Accounts im Terminal erhalten möchten.

// returns account profit in deposit currency
double acс_profit =  myaccount.Profit();
myaccount.FreeMargin()

Diese Funktion wird eingesetzt, wenn Sie die freie Marge des aktiven Accounts im Terminal erhalten möchten.

// returns free margin for active account
double acс_free_margin = myaccount.FreeMargin();
myaccount.Currency()

Diese Funktion wird eingesetzt, wenn Sie die Depot-Währung für den aktiven Account im Terminal erhalten möchten.

string acс_currency = myaccount.Currency();
myaccount.OrderProfitCheck(const string symbol, ENUM_ORDER_TYPE trade_operation, double volume, double price_open, double price_close) Diese Funktion holt sich den abgeschätzten Gewinn, auf Grundlage der übertragenen Parameter. Die Eingabeparameter sind: Symbol, Art der Handelsoperation, Volumen und Eröffnungs-/Schlusskurse.
double op_profit=myaccount.OrderProfitCheck(_Symbol,ORDER_TYPE_BUY,
1.0,1.2950,1.3235);
Print("The amount of Profit for deal buy EURUSD",
      "at 1.2950 and sell at 1.3235 is: ",op_profit);
myaccount.MarginCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double volume,double price) Diese Funktion wird eingesetzt, um die zur Eröffnung einer Order nötige Marge zu erhalten. Diese Funktion besitzt vier Eingabeparameter: das Symbol (Währungspaar), Art der Order, die zu handelnden Posten (oder Menge) und de Order-Preis. Diese Funktion ist zum Platzieren eines Handels sehr wichtig.
// depending on the type of position to open - in our case buy
double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK); 
double margin_req=myaccount.MarginCheck(_Symbol,ORDER_TYPE_BUY,LOT,price);
myaccount.FreeMarginCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double volume,double price) Diese Funktion wird eingesetzt, wenn Sie die Höhe der, beim Platzieren einer Order, in diesem aktiven Account noch übrigen freien Marge erhalten möchten. Sie besitzt vier Eingabeparameter: das Symbol (Währungspaar), Art der Order, die zu handelnden Posten (oder Menge) und den Order-Preis.
double acс_fm=myaccount.FreeMarginCheck(_Symbol,ORDER_TYPE_BUY,LOT,price);
myaccount.MaxLotCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double price)

Diese Funktion wird eingesetzt, wenn Sie den für die Platzierung einer Order für den aktiven Account im Terminal größtmöglichen Posten erhalten möchten. Sie besitzt drei Eingabeparameter: das Symbol, Art der Order und den Eröffnungskurs der Order.

double max_lot=myaccount.MaxLotCheck(_Symbol,ORDER_TYPE_BUY,price);

1.2 Die СSymbolInfo Klasse

Die CSymbolInfoKlasse erleichtert jedem Benutzer den raschen Zugriff auf alle Eigenschaften des aktuellen Symbols.

Um sie verwenden zu können, müssen wir zunächst ein Objekt der Klasse erzeugen, das wir in unserem Beispiel hier mysymbol nennen.

// the CSymbolInfo Class object CSymbolInfo mysymbol;

Sehen wir uns mal den Großteil der Funktionen dieser Klasse an, die beim Schreiben unseres Expert Advisors zum Einsatz kommen könnten:

Methode Beschreibung Anwendungsbeispiel
mysymbol.Name(string name)

Diese Funktion wird zur Einrichtung des Symbols für das Klassen-Objekt benutzt. Sie nimmt den Symbolnamen als Eingabeparameter.

// set the symbol name for our CSymbolInfo class Object
mysymbol.Name(_Symbol);
mysymbol.Refresh() Diese Funktion wird zur Aktualisierung aller Symboldaten benutzt.. Sie wird zudem automatisch aufgerufen, sobald Sie einen neuen Symbolnamen für die Klasse setzen.
mysymbol.Refresh();
mysmbol.RefreshRates() Diese Funktion wird zur Überprüfung der letzten Quoten-Daten benutzt Sie liefert'true' bei Erfolg und 'false' bei Fehlschlag und isr eine sehr nüzluiche Funktion, die Sie unbedingt brauchen.
//--- Get the last price quote using the CSymbolInfo 
// class object function
   if (!mysymbol.RefreshRates())
   {
      // error getting latest price quotes 
   }
mysymbol.IsSynchronized()

Diese Funktion wird zur Überprüfung benutzt, ob die aktuellen Daten des gesetzten Symbols im Terminal mit den Server-Daten synchronisiert sind. Sie liefert 'true' bei Datensynchronisierung und 'false' wenn nicht.

// check if symbol data are synchronized with server
  if (!mysymbol.IsSynchronized())
   {
     // error! Symbol data aren't synchronized with server
   }
mysymbol.VolumeHigh()

Diese Funktion wird dazu benutzt, das Maximalvolumen des Tages für das eingerichtete Symbol zu bekommen.

long max_vol = mysymbol.VolumeHigh();
mysymbol.VolumeLow()

Diese Funktion wird dazu benutzt, das Minimalvolumen des Tages für das eingerichtete Symbol zu bekommen.

long min_vol = mysymbol.VolumeLow();
mysymbol.Time()

Diese Funktion wird dazu benutzt, die Uhrzeit der letzten Kursquote für das eingerichtete Symbol zu bekommen.

datetime qtime = mysymbol.Time();
mysymbol.Spread() Diese Funktion wird dazu benutzt, den aktuellen Spread-Wert (Differenz zw. Brief- und Geldkurs) (in Punkten) für das eingerichtete Symbol zu bekommen.
int spread = mysymbol.Spread();
mysymbol.StopsLevel() Diese Funktion wird dazu benutzt, das Minimallevel (in Punkten) zum aktuellen Schlusskurs zu bekommen, für das Stop Loss für das eingerichtete Symbol platziert werden kann. eine sehr wichtige Funktion, wenn Sie die Anwendung eines nachziehenden Stops oder eine Veränderung der Order/Position erwägen.
int stp_level = mysymbol.StopsLevel();
mysymbol.FreezeLevel() Diese Funktion wird dazu benutzt, den Abstand (in Punkten) zum Einfrieren der Handelsoperation für das eingerichtete Symbol zu bekommen.
int frz_level = mysymbol.FreezeLevel();
mysymbol.Bid()

Diese Funktion wird dazu benutzt, den aktuellen GELDkurs für das eingerichtete Symbol zu bekommen.

double bid =  mysymbol.Bid();
mysymbol.BidHigh() Diese Funktion wird dazu benutzt, den maximalen/höchsten GELDkurs für den Tag zu bekommen.
double max_bid = mysymbol.BidHigh();
mysymbol.BidLow() Diese Funktion wird dazu benutzt, den minimalen/niedrigsten GELDkurs für den Tag für das eingerichtete Symbol zu bekommen.
double min_bid = mysymbol.BidLow();
msymbol.Ask() Diese Funktion wird dazu benutzt, den aktuellen BRIEFkurs für das eingerichtete Symbol zu bekommen.
double ask = mysymbol.Ask();
mysymbol.AskHigh() Diese Funktion wird dazu benutzt, den maximalen/höchsten BRIEFkurs für den Tag für das eingerichtete Symbol zu bekommen.
double max_ask = mysymbol.AskHigh();
mysymbol.AskLow() Diese Funktion wird dazu benutzt, den minimalen/niedrigsten BRIEFkurs für den Tag für das eingerichtete Symbol zu bekommen.
double min_ask = mysymbol.AskLow();
mysymbol.CurrencyBase() Diese Funktion wird dazu benutzt, die Basiswährung für das eingerichtete Symbol zu bekommen.
// returns "USD" for USDJPY or USDCAD
string base_currency = mysymbol.CurrencyBase();
mysymbol.ContractSize() Diese Funktion wird dazu benutzt, den Betrag für die Kontraktgröße für einen Handel des eingerichteten Symbols zu bekommen.
double cont_size =  mysymbol.ContractSize();
mysymbol.Digits() Diese Funktion wird dazu benutzt, die Anzahl der Ziffern nach der Dezimalstelle für das eingerichtete Symbol zu bekommen.
int s_digits = mysymbol.Digits();
mysymbol.Point() Diese Funktion wird dazu benutzt, den Wert eines der Punkte für das eingerichtete Symbol zu bekommen.
double s_point =  mysymbol.Point();
mysymbol.LotsMin() Diese Funktion wird dazu benutzt, das zum Schließen eines Abschlusses für das Symbol erforderliche Minimalvolumen zu bekommen.
double min_lot =  mysymbol.LotsMin();
mysymbol.LotsMax() Diese Funktion wird dazu benutzt, das zum Schließen eines Abschlusses für das Symbol erforderliche Maximalvolumen zu bekommen.
double max_lot =  mysymbol.LotsMax();
mysymbol.LotsStep() Diese Funktion wird dazu benutzt, den zum Schließen eines Abschlusses für das Symbol erforderlichen Mindestschritt der Volumenveränderung zu bekommen.
double lot_step = mysymbol.LotsStep();
mysymbol.NormalizePrice(double price) Diese Funktion wird benutzt, um einen auf die korrekten Ziffern des eingerichteten Symbols normalisierten Kurs zu bekommen.
// A normalized current Ask price
double n_price = mysymbol.NormalizePrice(mysymbol.Ask()); 
mysymbol.Select() Diese Funktion wird dazu benutzt, festzustellen, ob ein Symbol im Marktbeobachtungsfenster ausgewählt wurde. Falls ja, liefert es 'true', falls nein liefert es 'false'.
if (mysymbol.Select())
{
  //Symbol successfully selected
}
else
{
  // Symbol could not be selected
}
mysymbol.Select(bool select) Diese Funktion wird zur Auswahl eines Symbols im Marktbeobachtungsfenster oder der Entfernung eines Symbols im Marktbeobachtungsfenster benutzt. Hier sei darauf hingewiesen, dass die Entfernung eines Symbols vom Marktbeoachtungsfenster bei geöffnetem Chart oder bei einer bereits eröffneten Position die Meldung 'false' erzeugt.
if (!mysymbol.Select())
{
   //Symbol not selected, Select the symbol
    mysymbol.Select(true);
}
else
{
 // Symbol already selected, 
 // remove Symbol from market watch window
    mysymbol.Select(false);
}
mysymbol.MarginInitial() Diese Funktion wir dazu verwendet, den zur Eröffnung einer Position mit dem Volumen eines Postens in der Währung der Marge nötigen Betrag zu bekommen.
double init_margin = mysymbol.MarginInitial() ;
mysymbol.TradeMode() Mit dieser Funktion erhält man, die für das Symbol zugelassene Art der Order-Ausführung zu bekommen.
if (mysymbol.TradeMode() == SYMBOL_TRADE_MODE_FULL)
{
 // Full trade allowed for this symbol,
 // no trade restrictions 
}
mysymbol.TradeModeDescription() Mit dieser Funktion erhält man, die Beschreibung der für das Symbol zugelassene Art der Order-Ausführung zu bekommen.
Print("The trade mode for this symbol is",
       mysymbol.TradeModeDescription());

1.3 Die СHistoryOrderInfo Klasse

CHistoryOrderInfo ist eine weitere Klasse mit deren Hilfe man ganz einfach mit den Eigenschaften der Order-History arbeiten kann.

Sobald wir ein Objekt dieser Klasse erzeugt haben, können wir seiner Hilfe dann auf wichtige public Mitgliedsfunktionen zugreifen, die wir zur Lösung eines unmittelbaren Problems brauchen.

Nennen wir das Objekt der Klasse myhistory.

// The CHistoryOrderInfo Class object
CHistoryOrderInfo myhistory;

Sehen wir uns nun einige der Hauptfunktionen dieser Klasse an.

Um mit Hilfe dieser Klasse die Details der Orders in der History zu bekommen, müssen wir zuvor alle Orders in der History kennen und dann das Order-Ticket an unser Klassenobjekt, myhistory, übertragen.

//Select all history orders within a time period
if (HistorySelect(0,TimeCurrent()))  // get all history orders
{
// Get total orders in history
int tot_hist_orders = HistoryOrdersTotal();

Jetzt gehen wir die komplette History vorhandenen Orders durch und erhalten mit Hilfe unseres Klassen-Objekts die Details jeder Order in der History.

ulong h_ticket; // Order ticket

for (int j=0; j<tot_hist_orders; j++)
{
  h_ticket = HistoryOrderGetTicket(j));

  if (h_ticket>0)
  {
    // First thing is to now set the order Ticket to work with by our class object 
Methode Beschreibung Anwendungsbeispiel
myhistory.Ticket(ulong ticket) Mit dieser Funktion wird das Order-Ticket ausgewählt, für das wir die Eigenschaften oder Details bekommen möchten.
myhistory.Ticket(h_ticket);
myhistory.Ticket() Mit dieser Funktion erhält man das Order-Ticket für eine Order.
ulong o_ticket = myhistory.Ticket();
myhistory.TimeSetup() Mit dieser Funktion erhält man die Uhrzeit, wann die Order ausgeführt wurde oder ihre Einrichtung.
datetime os_time = myhistory.TimeSetup();
myhistory.OrderType() Mit dieser Funktion erhält man die Art der Order (ORDER_TYPE_BUY, usw.).
if (myhistory.OrderType() == ORDER_TYPE_BUY)
{
// This is a buy order
}
myhistory.State() Mit dieser Funktion erhält man den aktuellen Status der Order.
Also, ob sie storniert, akzeptiert, abgelehnt oder platziert wurde, usw.
if(myhistory.State() == ORDER_STATE_REJECTED)
{
// order was rejected, not placed.
}
myhistory.TimeDone() Mit dieser Funktion erhält man die Uhrzeit, wann die Order storniert, akzeptiert, abgelehnt oder platziert wurde
datetime ot_done =  myhistory.TimeDone();
myhistory.Magic() Mit dieser Funktion erhält man die Expert Advisor ID, die die Order initiiert hat.
long o_magic = myhistory.Magic();
myhistory.PositionId() Mit dieser Funktion erhält man die ID der Position, in die die Oder bei Platzierung mit eingeschlossen wurde.
long o_posid = myhistory.PositionId();
myhistory.PriceOpen() Mit dieser Funktion erhält man den Eröffnungskurs der Order.
double o_price =  myhistory.PriceOpen();
myhistory.Symbol() Mit dieser Funktion erhält man die Symboleigenschaften der Order (Währungspaar).
string o_symbol =  myhistory.Symbol();

Nicht vergessen: Wir haben diese Funktionen alle innerhalb einer Schleife der gesamten Order in der History verwendet.

1.4 Die СOrderInfo Klasse

COrderInfo ist eine Klasse, mit deren Hilfe man ganz leicht Zugriff auf die Eigenschaften aller pending Orders bekommt. Sobald ein Objekt dieser Klasse erzeugt worden ist, kann es für public Mitgliedsfunktionen dieser Klasse verwendet werden.

Die Arbeit mit dieser Klasse ähnelt der der oben besprochenen CHistoryOrderInfo Klasse ziemlich.

Erzeugen wir also ein Objekt der Klasse und nennen es myorder.

// The OrderInfo Class object
COrderInfo myorder;

Um diese Klasse zur Abfrage der Details einer pending Order verwenden zu können, müssen wir zuvor alle insgesamt vorhandenen Orders kennen und sie dann per Order-Ticket auswählen.

// Select all history orders within a time period
if (HistorySelect(0,TimeCurrent()))   // get all history orders
   {    
     // get total orders
     int o_total = OrdersTotal();

Also gehen wir per Schleife durch alle Orders und erhalten mit Hilfe des gerade erzeugten Objekts all ihre entsprechenden Eigenschaften.

for (int j=0; j<o_total; j++)
{
 // we must confirm if the order is available for us to get its details using the Select function of the COrderInfo Class
Methode Beschreibung Anwendungsbeispiel
myorder.Select(ulong ticket) Mit dieser Funktion wählt man eine Order per Ticket-Nummer aus, sodass diese dann leicht bearbeitet werden kann.
if (myorder.Select(OrderGetTicket(j)) 
   { // order has been selected and can now be manipulated.
   }
myorder.Ticket() Mit dieser Funktion erhält man das Order-Ticket für die ausgewählte Order
ulong o_ticket = myorder.Ticket();
myorder.TimeSetup() Mit dieser Funktion erhält man die Uhrzeit, wann diese Order eingerichtet wurde.
datetime o_setup = myorder.TimeSetup();
myorder.Type() Mit dieser Funktion erhält man die Art der Order wie z.B. ORDER_TYPE_BUY_STOP, usw.
if (myorder.Type() == ORDER_TYPE_BUY_LIMIT)
{
// This is a Buy Limit order, etc
}
myorder.State() Mit dieser Funktion erhält man den Status der Order.
Also, ob sie storniert, akzeptiert, abgelehnt oder platziert wurde, usw.
if (myorder.State() ==ORDER_STATE_STARTED)
{
// order has been checked 
// and may soon be treated by the broker
}
myorder.TimeDone() Mit dieser Funktion erhält man die Uhrzeit, wann die Order platziert, abgelehnt oder storniert wurde.
datetime ot_done = myorder.TimeDone();
myorder.Magic() Mit dieser Funktion erhält man die ID des Expert Advisors, der die Order initiiert hat.
long o_magic =  myorder.Magic();
myorder.PositionId() Mit dieser Funktion erhält man die ID der Position, in die die Order bei Platzierung mit eingeschlossen wurde.
long o_posid = myorder.PositionId();
myorder.PriceOpen() Mit dieser Funktion erhält man den Eröffnungskurs für die Order.
double o_price = myorder.PriceOpen();
myorder.StopLoss() Mit dieser Funktion erhält man den Stop Loss der Order.
double  s_loss = myorder.StopLoss();
myorder.TakeProfit() Mit dieser Funktion erhält man den Take Profit der Order.
double t_profit = myorder.TakeProfit();
myorder.PriceCurrent() Mit dieser Funktion erhält man aktuellen Kurs des Symbols in dem die Order platziert wurde.
double cur_price =  myorder.PriceCurrent();
myorder.Symbol() Mit dieser Funktion erhält man den Namen des Symbols in dem die Order platziert wurde.
string o_symbol = myorder.Symbol();
myorder.StoreState() Mit dieser Funktion kann man aktuelle Details der Order speichern oder ablegen, damit man sie später zu Vergleichszwecken heranziehen kann, ob sich irgendetwas verändert hat.
myorder.StoreState();
myorder.CheckState() Mit dieser Funktion überprüft man, ob die sich Details der gespeicherten oder abgelegten Order verändert haben.
if (myorder.CheckState() == true)
{
// Our order status or details have changed
}

1.5 Die CDealInfo Klasse

Die CDealInfo Klasse erlaubt Zugriff auf die gesamte History an Abschluss-Eigenschaften oder Information. Sobald ein Objekt dieser Klasse erzeugt worden ist, können wir damit jede Information übe Abschlüsse in der Historie bekommen, ähnlich wie bei der CHistoryOrderInfo Klasse.

Erzeugen wir also als erstes ein Objekt der Klasse und nennen es mydeal.

// The DealInfo Class object
CDealInfo myinfo;

Wir beginnen mit dem Abruf der gesamten Abschlüsse in der History

if (HistorySelect(0,TimeCurrent()))
   {    
    // Get total deals in history
    int tot_deals = HistoryDealsTotal();

Jetzt gehen wir die komplette History vorhandenen Orders durch und erhalten mit Hilfe unseres Klassen-Objekts die Details jeder Order in der History.

ulong d_ticket; // deal ticket
for (int j=0; j<tot_deals; j++)
    {
     d_ticket = HistoryDealGetTicket(j);
     if (d_ticket>0)  
     {
      // First thing is to now set the deal Ticket to work with by our class object 
Methode Beschreibung Anwendungsbeispiel
mydeal.Ticket(ulong ticket) Mit dieser Funktion richtet man das Ticket des Abschlusses für eine spätere Verwendung durch das soeben erzeugte Objekt ein
mydeal.Ticket(d_ticket);
mydeal.Ticket() Mit dieser Funktion erhält man das Ticket des Abschlusses
ulong deal_ticket = mydeal.Ticket();
mydeal.Order() Mit dieser Funktion erhält man das Ticket des Abschlusses für die Order, in der der Abschluss ausgeführt wurde
long deal_order_no =  mydeal.Order();
mydeal.Time() Mit dieser Funktion erhält man die Uhrzeit, wann der Abschluss ausgeführt wurde
datetime d_time = mydeal.Time();
mydeal.Type() Mit dieser Funktion erhält man die Art des Abschlusses, also DEAL_TYPE_SELL, usw.
if (mydeal.Type() == DEAL_TYPE_BUY)
{
// This deal was executed as a buy deal type
}
mydeal.Entry() Mit dieser Funktion erhält man die Richtung des Abschlusses, also DEAL_ENTRY_IN oder DEAL_ENTRY_OUT, usw.
if (mydeal.Entry() == DEAL_ENTRY_IN)
{
// This was an IN entry deal
}
mydeal.Magic() Mit dieser Funktion erhält man die ID des Expert Advisors, der den Abschluss ausgeführt hat.
long d_magic = mydeal.Magic();
mydeal.PositionId() Mit dieser Funktion erhält man den einmaligen Position-Identifikator für die Position zu der der Abschluss gehörte.
long d_post_id = mydeal.PositionId();
mydeal.Price() Mit dieser Funktion erhält man den Kurs bei dem der Abschluss ausgeführt wurde.
double d_price = mydeal.Price();
mydeal.Volume() Mit dieser Funktion erhält man die Menge (Posten) des Abschlusses.
double d_vol = mydeal.Volume();
mydeal.Symbol() Mit dieser Funktion erhält man das Symbol (Währungspaar) für das der Abschluss ausgeführt wurde.
string d_symbol = mydeal.Symbol();

1.6 Die CPositionInfo Klasse

Die CPositionInfo Klasse erlaubt leichten Zugriff auf die Eigenschaften der aktuellen Position. Um mit ihrer Hilfe die Position-Eigenschaften erhalten zu können, müssen wir ein Objekt dieser Klasse erzeugen.

Dies tun wir nun und nennen es myposition.

// The object of the CPositionInfo class
CPositionInfo myposition;

Mit seiner Hilfe erhalten wir jetzt die Details einer offene Position. Wir beginnen mit der Abfrage der insgesamt vorhandenen offenen Positions:

int pos_total = PositionsTotal();

Nun müssen wir alle offenen Positions durchgehen, um an ihre Details zu kommen.

for (int j=0; j<pos_total; j++)
    {
Methode Beschreibung Anwendungsbeispiel
myposition.Select(const string symbol) Mit dieser Funktion kann man das Symbol auswählen, das der aktuell offenen Position entspricht, damit sie weiter bearbeitet werden kann.
if (myposition.Select(PositionGetSymbol(j)))
{
 // symbol successfully selected, we can now work 
 // on the current open position for this symbol 
}
OR
// when dealing with the current symbol/chart only
if (myposition.Select(_Symbol)) 
{
 // symbol successfully selected, we can now work 
 // on the current open position for this symbol 
}
myposition.Time() Mit dieser Funktion erhält man die Uhrzeit, wann die Position eröffnet wurde.
datetime pos_time = myposition.Time();
myposition.Type() Mit dieser Funktion erhält man die Art der eröffneten Position.
if (myposition.Type() == POSITION_TYPE_BUY)
{
// This is a buy position
}
myposition.Magic() Mit dieser Funktion erhält man die ID des Expert Advisors, der die Position eröffnet hat.
long pos_magic = myposition.Magic();
myposition.Volume() Mit dieser Funktion erhält man die Menge (Posten) der offenen Position.
double pos_vol = myposition.Volume(); // Lots
myposition.PriceOpen() Mit dieser Funktion erhält man den Kurs zu dem die Position eröffnet wurde – den Position- Eröffnungskurs.
double pos_op_price = myposition.PriceOpen();
myposition.StopLoss() Mit dieser Funktion erhält man den Stop Loss Kurs für die offene Position.
double pos_stoploss = myposition.StopLoss();
myposition.TakeProfit() Mit dieser Funktion erhält man den Take Profit Kurs für die offene Position.
double pos_takeprofit = myposition.TakeProfit();
myposition.StoreState() Mit dieser Funktion kann man den aktuellen Status der Position speichern.
// stores the current state of the position
myposition.StoreState();
myposition.CheckState() Mit dieser Funktion kann man nachprüfen, ob sich der Status der offenen Position verändert hat.
if (!myposition.CheckState())
{
  // position status has not changed yet
}
myposition.Symbol() Mit dieser Funktion erhält man den Namen des Symbols in dem die Position eröffnet wurde.
string pos_symbol = myposition.Symbol();

1.7 Die СTrade Klasse

Die CTrade Klasse bietet leichten Zugriff auf alle Handels-Operationen in MQL5. Um sie nutzen zu können, müssen wir zunähst ein Objekt dieser Klasse erzeugen und mit seiner Hilfe dann alle notwendigen Handels-Operationen ausführen.

Wir erzeugen ein Objekt dieser Klasse und nennen es mytrade:

//An object of the CTrade class
CTrade mytrade;

Als ersten Schritt richten wir die meisten Parameter ein, die das Objekt bei der Durchführung von Handels-Operationen anwenden wird.

Methode Beschreibung Anwendungsbeispiel
mytrade.SetExpertMagicNumber(ulong magic) Mit dieser Funktion richtet man die Expert ID (magische Zahl) der Klasse ein, die sie für Handels-Operationen verwenden wird.
ulong Magic_No=12345;
mytrade.SetExpertMagicNumber(Magic_No);
mytrade.SetDeviationInPoints(ulong deviation) Diese Funktion wird auch zur Einrichtung des Abweichungswerts (in Punkten) benutzt, der bei der Platzierung eines Handels verwendet werden soll.
ulong Deviation=20;
mytrade.SetDeviationInPoints(Deviation); 
mytrade.OrderOpen(conststring symbol,
ENUM_ORDER_TYPE
order_type,double volume,
double
limit_price,double price,doublesl,
double
tp,ENUM_ORDER_TYPE_TIME type_time,
datetime
expiration,const stringcomment="")
Mit dieser Funktion wird eine pending Order platziert. Um sie nutzen zu können, müssen zunächst die Parameter vorbereitet und an diese Funktion übertragen werden.
// define the input parameters
double Lots = 0.1;
double SL = 0;
double TP = 0;
// latest Bid price using CSymbolInfo class object
double Oprice = mysymbol.Bid()-_Point*550;
// place (BuyStop) pending order
mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELLSTOP,Lots,0.0,Oprice,
                  SL,TP,ORDER_TIME_GTC,0);
mytrade.OrderModify(ulong ticket,double price,
double
sl,double tp,ENUM_ORDER_TYPE_TIME type_time,datetime expiration)
Mit dieser Funktion wird eine bestehende pending Order verändert.
// Select total orders in history and get total pending orders 
// (as shown within the COrderInfo class section). 
// Use the CSymbolInfo class object to get the current ASK/BID price
int Stoploss = 400;
int Takeprofit = 550;
for(int j=0; j<OrdersTotal(); j++)
{
  ulong o_ticket = OrderGetTicket(j);
  if(o_ticket != 0)
  {
   // Stoploss must have been defined
   double SL = mysymbol.Bid() + Stoploss*_Point;   
   // Takeprofit must have been defined  
   double TP = mysymbol.Bid() - Takeprofit*_Point; 
   // lastest ask price using CSymbolInfo class object
   double Oprice = mysymbol.Bid();                 
   // modify pending BuyStop order
   mytrade.OrderModify(o_ticket,Oprice,SL,TP,ORDER_TIME_GTC,0);
  }
}
mytrade.OrderDelete(ulong ticket) Mit dieser Funktion wird eine pending Order gelöscht.
// Select total orders in history and get total pending orders
// (as shown within the COrderInfo class section). 

int o_total=OrdersTotal();
for(int j=o_total-1; j>=0; j--)
{
   ulong o_ticket = OrderGetTicket(j);
   if(o_ticket != 0)
   {
    // delete the pending Sell Stop order
    mytrade.OrderDelete(o_ticket);
   }
}
mytrade.PositionOpen(const string symbol,ENUM_ORDER_TYPE order_type,double volume,double price,double sl,double tp,const string comment="") Mit dieser Funktion wird eine BUY oder ein SELL Position eröffnet. Um sie nutzen zu können, müssen zunächst alle erforderlichen Parameter vorbereitet und an diese Funktion übertragen werden.
// define the input parameters and use the CSymbolInfo class
// object to get the current ASK/BID price
double Lots = 0.1;
// Stoploss must have been defined 
double SL = mysymbol.Ask() – Stoploss*_Point;   
//Takeprofit must have been defined 
double TP = mysymbol.Ask() + Takeprofit*_Point; 
// latest ask price using CSymbolInfo class object
double Oprice = mysymbol.Ask();
// open a buy trade
mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lots,
                     Oprice,SL,TP,"Test Buy");
mytrade.PositionModify(const string symbol,
double
sl,double tp)
Mit dieser Funktion wird der StopLoss und/oder TakeProfit für eine bestehende, offenen Position verändert. Um sie nutzen zu können, müssen wir zunächst die zu verändernde Position mit Hilfe des CPositionInfo Klassen-Objekts auswählen und das CSymbolInfo Klassen-Objekt anwenden, um den aktuellen GELD/BRIEF-Kurs zu bekommen.
if (myposition.Select(_Symbol))
{
  int newStoploss = 250;
  int newTakeprofit = 500;
  double SL = mysymbol.Ask() – newStoploss*_Point;    
  double TP = mysymbol.Ask() + newTakeprofit*_Point;  
  //modify the open position for this symbol
 mytrade.PositionModify(_Symbol,SL,TP);
}
mytrade.PositionClose(const string symbol,
ulong
deviation=ULONG_MAX)
Mit dieser Funktion wird eine bestehende offene Position geschlossen.
if (myposition.Select(_Symbol))
{
 //close the open position for this symbol
 mytrade.PositionClose(_Symbol);  
}
mytrade.Buy(double volume,const string symbol=NULL,double price=0.0,double sl=0.0,doubletp=0.0,const string comment="") Mit dieser Funktion wird ein Buy-Handel eröffnet. Hierbei ist es ratsam, die Menge (oder Posten) einzustellen, die mit Hilfe dieser Funktion gehandelt werden soll. Zwar können tp (Take Profit) und sl (Stop Loss) später noch für eine Veränderung der eröffneten Position eingerichtet werden, doch zum Eröffnen des Handels verwendet diese Funktion den aktuellen Briefkurs.
double Lots = 0.1;
// Stoploss must have been defined 
double SL = mysymbol.Ask() – Stoploss*_Point; 
//Takeprofit must have been defined
double TP = mysymbol.Ask() +Takeprofit*_Point;
// latest ask price using CSymbolInfo class object
double Oprice = mysymbol.Ask();
// open a buy trade
mytrade.Buy(Lots,NULL,Oprice,SL,TP,“Buy Trade”);

//OR
mytrade.Buy(Lots,NULL,0.0,0.0,0.0,“Buy Trade”);
// modify position later
mytrade.Sell(double volume,const string symbol=NULL,double price=0.0,double sl=0.0,doubletp=0.0,const string comment="") Mit dieser Funktion wird ein Sell-Handel eröffnet. Hierbei ist es ratsam, die Menge (oder Posten) einzustellen, die mit Hilfe dieser Funktion gehandelt werden soll. Zwar können tp (Take Profit) und sl (Stop Loss) später noch für eine Veränderung der eröffneten Position eingerichtet werden, doch zum Eröffnen des Handels verwendet diese Funktion den aktuellen Geldkurs.
double Lots = 0.1;
// Stoploss must have been defined 
double SL = mysymbol.Bid() + Stoploss*_Point;
//Takeprofit must have been defined
double TP = mysymbol.Bid() - Takeprofit*_Point; 
// latest bid price using CSymbolInfo class object
double Oprice = mysymbol.Bid();
// open a Sell trade
mytrade.Sell(Lots,NULL,Oprice,SL,TP,“Sell Trade”); 

//OR
mytrade.Sell(Lots,NULL,0.0,0.0,0.0,“Sell Trade”); 
//(modify position later)
mytrade.BuyStop(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0,
ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="")
Mit dieser Funktion wird eine BuyStop pending Order platziert. Die Standardart dieser Order ist ORDER_TIME_GTC mit Ablaufdatum 0. Diese zwei Variablen müssen nicht festgelegt werden, wenn Sie genau diese Art Order beabsichtigen.
double Lot = 0.1;
//Buy price = bar 1 High + 2 pip + spread
 int sprd=mysymbol.Spread();
 double bprice =mrate[1].high + 2*_Point + sprd*_Point;
//--- Buy price
 double mprice=NormalizeDouble(bprice,_Digits); 
//--- Stop Loss
 double stloss = NormalizeDouble(bprice - STP*_Point,_Digits);
//--- Take Profit
 double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits);
//--- open BuyStop order
 mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit);
mytrade.SellStop(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="") Mit dieser Funktion wird eine SellStop pending Order mit den eingerichteten Parametern platziert. Die Standardart dieser Order ist ORDER_TIME_GTC mit Ablaufdatum 0. Diese zwei Variablen müssen nicht festgelegt werden, wenn Sie genau diese Art Order beabsichtigen.
double Lot = 0.1;
//--- Sell price = bar 1 Low - 2 pip 
//--- MqlRates mrate already declared
 double sprice=mrate[1].low-2*_Point;
//--- SellStop price
 double slprice=NormalizeDouble(sprice,_Digits);
//--- Stop Loss
 double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);
//--- Take Profit
 double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits);
//--- Open SellStop Order
 mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit);
mytrade.BuyLimit(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="") Mit dieser Funktion wird eine BuyLimit Order mit den eingerichteten Parametern platziert.
Usage:
//--- Buy price = bar 1 Open  - 5 pip + spread
double Lot = 0.1;
int sprd=mysymbol.Spread();
//--- symbol spread
double bprice = mrate[1].open - 5*_Point + sprd*_Point;
//--- MqlRates mrate already declared
double mprice=NormalizeDouble(bprice,_Digits);
//--- BuyLimit price
//--- place buyLimit order, modify stoploss and takeprofit later
mytrade.BuyLimit(Lot,mprice,_Symbol);
mytrade.SellLimit (double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="") Mit dieser Funktion wird eine SellLimit Order mit den eingerichteten Parametern platziert.
//--- Sell Limit price = bar 1 Open  + 5 pip
double Lot = 0.1;
//--- MqlRates mrate already declared
double sprice = mrate[1].open + 5*_Point;
//--- SellLimit
double slprice=NormalizeDouble(sprice,_Digits);
//place SellLimit order, modify stoploss and takeprofit later
mytrade.SellLimit(Lot,slprice,_Symbol);

TRADE RESULT FUNCTIONS

mytrade.ResultRetcode() Mit dieser Funktion erhält man den Ergebnis-Code für eine Handels-Operation.
// a trade operation has just been carried out
int return_code = mytrade.ResultRetcode();
mytrade.ResultRetcodeDescription() Mit dieser Funktion erhält man die komplette Beschreibung oder Interpretation des gelieferten Codes einer Handels-Operation.
string ret_message =  ResultRetcodeDescription();
// display it
Alert("Error code - " , mytrade.ResultRetcode() ,
      "Error message - ", ret_message);
mytrade.ResultDeal() Mit dieser Funktion erhält man das Abschluss-Ticket für die offene Position.
long dl_ticket = mytrade.ResultDeal();
mytrade.ResultOrder() Mit dieser Funktion erhält man das Order-Ticket für die eröffnete Position.
long o_ticket = mytrade.ResultOrder();
mytrade.ResultVolume() Mit dieser Funktion erhält man die Menge (Posten) der Order für die eröffnete Position.
double o_volume = mytrade.ResultVolume();
mytrade.ResultPrice() Mit dieser Funktion erhält man den Abschlusskurs für die eröffnete Position.
double r_price = mytrade.ResultPrice();
mytrade.ResultBid() Mit dieser Funktion erhält man den aktuellen Markt-GELDkurs (Re-Quoten Preis).
double rq_bid = mytrade.ResultBid;
mytrade.ResultAsk() Mit dieser Funktion erhält man den aktuellen Markt-BRIEFkurs (Re-Quoten Preis).
double rq_ask = mytrade.ResultAsk;
mytrade.PrintRequest() / mytrade.PrintResult() Mit diesen beiden Funktionen können die Handels-Anfrageparameter bzw. Ergebnis-Parameter in die "Logbuch"-Registerkarte gedruckt werden.
// after a trade operation
// prints the trade request parameters
mytrade.PrintRequest(); 
//prints the trade results
mytrade.PrintResult();  

HANDELSANFRAGE-FUNKTIONEN

mytrade.RequestAction() Mit dieser Funktion erhält man die Art der Handels-Operation für die jüngste, gerade eben abgeschickte Handelsanfrage.
//determine the Trade operation type for the last Trade request
if (mytrade.RequestAction() == TRADE_ACTION_DEAL)
{
  // this is a market order for an immediate execution
}
else if (mytrade.RequestAction() == TRADE_ACTION_PENDING)
{
  // this is a pending order.
}  
mytrade.RequestMagic() Mit dieser Funktion erhält man die Magische Zahl des Experts, die in dieser letzten Anfrage verwendet wurde.
ulong mag_no = mytrade. RequestMagic();
mytrade.RequestOrder()
Mit dieser Funktion erhält man das Order-Ticket, das in dieser letzten Anfrage verwendet wurde. Dies hat hauptsächlich mit Veränderung von pending Orders zu tun.
ulong po_ticket =  mytrade.RequestOrder();
mytrade.RequestSymbol() Mit dieser Funktion erhält man das Symbol oder das Währungspaar, das in dieser letzten Anfrage verwendet wurde.
string symb = mytrade.RequestSymbol(); 
mytrade.RequestVolume() Mit dieser Funktion erhält man die in dieser letzten Anfrage platzierte Handels-Menge (in Posten).
double Lot = mytrade.RequestVolume();  
mytrade.RequestPrice() Mit dieser Funktion erhält man den in dieser letzten Anfrage verwendeten Order-Preis.
double oprice = mytrade.RequestPrice();   
mytrade.RequestStopLimit() Mit dieser Funktion erhält man den in dieser letzten Anfrage verwendeten Stop Loss Preis.
double limitprice = mytrade.RequestStopLimit(); 
mytrade.RequestSL() Mit dieser Funktion erhält man den in dieser letzten Anfrage verwendeten Stop Loss Preis.
double sloss = mytrade.RequestSL();  
mytrade.RequestTP() Mit dieser Funktion erhält man den in dieser letzten Anfrage verwendeten Take Profit Preis.
double tprofit = mytrade.RequestTP();   
mytrade.RequestDeviation() Mit dieser Funktion erhält man die in dieser letzten Anfrage verwendete Abweichung.
ulong dev = mytrade.RequestDeviation();  
mytrade.RequestType() Mit dieser Funktion erhält man die Art der Order, die in dieser letzten Anfrage platziert wurde.
if (mytrade.RequestType() == ORDER_TYPE_BUY)
 {
  // market order Buy was placed in the last request.
mytrade.RequestTypeDescription() Mit dieser Funktion erhält man die Beschreibung der Art der Order, die in dieser letzten Anfrage platziert wurde.
Print("The type of order placed in the last request is :",
      mytrade.RequestTypeDescription());  
mytrade.RequestActionDescription() Mit dieser Funktion erhält man die Beschreibung der Anfragehandlung, die in dieser letzten Anfrage verwendet wurde.
Print("The request action used in the last request is :", 
      mytrade.RequestTypeDescription());
mytrade.RequestTypeFillingDescription() Mit dieser Funktion erhält man die Art der Order-Bestellrichtlinie, die in dieser letzten Anfrage verwendet wurde.
Print("The type of order filling policy used",
      " in the last request is :",
      RequestTypeFillingDescription()); 

Die Handelsklasse-Anfragefunktionen sind sehr nützlich, wenn man Fehler im Zusammenhang mit der Platzierung von Orders ermitteln will. Es kann immer mal zu Fehlermeldungen bei der Platzierung einer Order kommen, und wenn wir dann nicht sofort herausfinden können, was schief gelaufen ist, wird's schnell ziemlich kompliziert. Mit Hilfe der Handelsklasse-Anfragefunktionen können wir feststellen, was wir falsch gemacht haben, indem wir einige der Anfrageparameter, die an den Handelsserver geschickt wurden, ausdrucken. Ein Beispiel eines derartigen Einsatzes ähnelt dem unten stehenden Code:

//--- open Buy position and check the result
         if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
         //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit)) 
           { //--- Request is completed or order placed           
             Alert("A Buy order at price:", mytrade.ResultPrice() , ", vol:",mytrade.ResultVolume(),
                  " has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
            mytrade.PrintResult();
           }
         else
           {
            Alert("The Buy order request at vol:",mytrade.RequestVolume(), ", sl:", mytrade.RequestSL(),
                 ", tp:",mytrade.RequestTP(), ", price:", mytrade.RequestPrice(),
                 " could not be completed -error:",mytrade.ResultRetcodeDescription());
            mytrade.PrintRequest();
            return;
           }

Im obigen Code haben wir versucht, einige der Parameter, die wir in unserer Anfrage gesendet haben, zu ermitteln, nur für den Fall, dass etwas schief gehen sollte. Beispiel: Falls wir den korrekten Stop Loss Preis nicht festgelegt haben, erhalten wir die Fehlermeldung 'Ungültige Stops'. Wenn wir den Wert des Stop Loss mit Hilfe von mytrade.RequestSL() ausdrucken, können wir schnell feststellen, wo das Problem bei unserem angegebenen Stop Loss Preis liegt.

Da wir uns nun ausführlich die Verwendung jeder Klasse angesehen haben, ist es jetzt Zeit, die oben beschrieben Funktionalitäten in der Praxis anzuwenden.

Bitte beachten Sie, dass alle Funktionalitäten, die wir nun im Expert Advisor anwenden werden, oben bereits beschrieben wurden. Daher ist es bestimmt nicht schlecht, immer mal wieder zu den Beschreibungen zurückzugehen, sobald Sie auf eine der Funktionen in den Codes stoßen, die wir jetzt schreiben werden.


2. Die Funktionalitäten der Handelsklassen verwenden

Um die Verwendung der Funktionalitäten der Handelsklassen zu zeigen, schreiben wir einen Expert Advisor, der die folgenden Aufgaben ausführen wird.

  • Er wird nach einer Bedingung für Buy oder Sell Ausschau halten - und wenn die Bedingung erfüllt ist, wird er eine Buy oder Sell Order platzieren, je nachdem, welche Bedingung erfüllt wurde.
  • Ist eine Position eröffnet worden und der Handel entwickelt sich weiter in unsere Richtung, verändern wir den Take Profit oder Stop Loss der Position. Sollte der Handel jedoch entgegen unserer Richtung verlaufen und unser Gewinnziel nicht erreicht werden, dann schließen wir die Position.
  • Unser EA wird auf dem Tages-Chart mit jeder der folgenden Währungen handeln: GBPUSD, AUDUSD, EURUSD, usw.

2.1 Den Expert Advisor schreiben

Zuallererst müssen Sie ein neues MQL5-Dokument aufrufen, einen Expert Advisor (Template) auswählen und anschließend auf 'Weiter' klicken:

Ein neues MQL5-Dokument aufrufen

Abb. 1 Ein neues MQL5-Dokument aufrufen

Den Namen für den Expert Advisor eingeben und auf 'Fertigstellen' klicken. Die Eingabeparameter legen wir später manuell fest

Geben Sie dem neuen Dokument einen Namen

Abb. 2 Dem Expert Advisor einen Namen geben

Das nun erstellte Dokument sollte ungefähr so aussehen:

Skelett des Expert-Codes

Knapp hinter der #property Versionszeile müssen wir alle Handelsklassen, die wir verwenden wollen, mit einschließen.

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The Trade Class
#include <Trade\Trade.mqh>
//--- The PositionInfo Class
#include <Trade\PositionInfo.mqh>
//--- The AccountInfo Class
#include <Trade\AccountInfo.mqh>
//--- The SymbolInfo Class
#include <Trade\SymbolInfo.mqh>

Anschließend legen wir unsere Eingabeparameter fest:

//+------------------------------------------------------------------+
//|  INPUT PARAMETERS                                              |
//+------------------------------------------------------------------+
input int      StopLoss=100;     // Stop Loss
input int      TakeProfit=240;   // Take Profit
input int      ADX_Period=15;    // ADX Period
input int      MA_Period=15;     // Moving Average Period
input ulong    EA_Magic=99977;   // EA Magic Number
input double   Adx_Min=24.0;     // Minimum ADX Value
input double   Lot=0.1;          // Lots to Trade
input ulong    dev=100;          // Deviation 
input long     Trail_point=32;   // Points to increase TP/SL
input int      Min_Bars = 20;    // Minimum bars required for Expert Advisor to trade
input double   TradePct = 25;    // Percentage of Account Free Margin to trade

Wir legen auch andere Parameter fest, die in diesem Expert Advisor-Code verwendet werden:

//+------------------------------------------------------------------+
//|  OTHER USEFUL PARAMETERS                                         |
//+------------------------------------------------------------------+
int adxHandle;                     // handle for our ADX indicator
int maHandle;                    // handle for our Moving Average indicator
double plsDI[],minDI[],adxVal[]; // Dynamic arrays to hold the values of +DI, -DI and ADX values for each bars
double maVal[];                  // Dynamic array to hold the values of Moving Average for each bars
double p_close;                    // Variable to store the close value of a bar
int STP, TKP;                   // To be used for Stop Loss, Take Profit 
double TPC;                        // To be used for Trade percent

Erzeugen wir jetzt ein Objekt für jede der Klassen, die wir mit eingeschlossen haben :

//+------------------------------------------------------------------+
//|  CREATE CLASS OBJECTS                                            |
//+------------------------------------------------------------------+
//--- The Trade Class Object
CTrade mytrade;
//--- The PositionInfo Class Object
CPositionInfo myposition;
//--- The AccountInfo Class Object
CAccountInfo myaccount;
//--- The SymbolInfo Class Object
CSymbolInfo mysymbol;

Als nächstes müssen wir einige Funktionen festlegen, die wir zur Vereinfachung unserer Arbeit anwenden wollen.

Sind sie einmal festgelegt, werden wir sie innerhalb der notwendigen Bereiche in den OnInit() and OnTick() Funktionen aufrufen.

2.1.1 Die checkTrading Funktion

Mit dieser Funktion werden alle Erstprüfungen durchgeführt, um festzustellen, ob unser Expert Advisor handeln kann oder nicht. Liefert diese Funktion 'true', kann unser EA weitermachen, ansonsten wird er keinerlei Handel ausführen.

//+------------------------------------------------------------------+
//|  Checks if our Expert Advisor can go ahead and perform trading   |
//+------------------------------------------------------------------+
bool checkTrading()
{
  bool can_trade = false;
  // check if terminal is syncronized with server, etc
  if (myaccount.TradeAllowed() && myaccount.TradeExpert() && mysymbol.IsSynchronized())
  {
    // do we have enough bars?
    int mbars = Bars(_Symbol,_Period);
    if(mbars >Min_Bars)
    {
      can_trade = true;
    }
  }
  return(can_trade);
}

Wir haben einen Bool Datentyp namens can_trade deklariert und ihn 'false' gemacht. Wir haben das Objekt der CAccountInfo Klasse zur Prüfung, ob der Handel erlaubt ist, verwendet, und auch, um zu sehen, ob auf diesem Account ein Handel per Expert Advisors überhaupt erlaubt ist. Wir verwenden zudem ein Objekt der CSymbolInfo Klasse zur Prüfung, ob der Terminal mit dem Handelsserver synchronisiert ist.

Sind diese drei Bedingungen erfüllt, prüfen wir dann, ob die Gesamtanzahl der aktuellen Balken größer ist als die für unseren EA erforderliche Mindestanzahl, damit er überhaupt handeln kann. Liefert uns diese Funktion 'true', kann unser EA Handelsaktivitäten ausführen. Ansonsten wird unser EA solange keinerlei derartige Aktivitäten ausführen, bis diese Funktion nicht erfüllt ist.

Wie Sie gesehen haben, haben wir beschlossen, alle notwendigen Prüfaktivitäten für einen Handel in dieser Funktion mit einzuschließen und haben dies mit Hilfe der notwendigen Objekte der Standard Handelsklassen-Libraries getan.

2.1.2 Die ConfirmMargin Funktion

//+------------------------------------------------------------------+
//|  Confirms if margin is enough to open an order
//+------------------------------------------------------------------+
bool ConfirmMargin(ENUM_ORDER_TYPE otype,double price)
  {
   bool confirm = false;
   double lot_price = myaccount.MarginCheck(_Symbol,otype,Lot,price); // Lot price/ Margin    
   double act_f_mag = myaccount.FreeMargin();                        // Account free margin 
   // Check if margin required is okay based on setting
   if(MathFloor(act_f_mag*TPC)>MathFloor(lot_price))
     {
      confirm =true;
     }
    return(confirm);
  }

Mit Hilfe des Objekts der CAccountInfo Klasse bestätigen wir, ob genug Marge zur Platzierung eines Handels basierend auf der Einstellung, dass wir nur einen bestimmten Prozentsatz der freien Marge unseres Accounts zur Platzierung einer Order verwenden wollen, vorhanden ist.

Ist der nötige Prozentsatz der freien Marge des Accounts höher als die für die Order erforderliche Marge, dann liefert uns diese Funktion'true', ansonsten eben 'false'. Wir wollen hier nur dann eine Order platzieren, wenn uns die Funktion'true' liefert. Diese Funktion verwendet die Art der Order als Eingabeparameter.

2.1.3 Die checkBuy Funktion

//+------------------------------------------------------------------+
//|  Checks for a Buy trade Condition                                |
//+------------------------------------------------------------------+
bool checkBuy()
{
  bool dobuy = false;
  if ((maVal[0]>maVal[1]) && (maVal[1]>maVal[2]) &&(p_close > maVal[1]))
  {
    // MA increases upwards and previous price closed above MA
    if ((adxVal[1]>Adx_Min)&& (plsDI[1]>minDI[1]))
    {
      // ADX is greater than minimum and +DI is greater tha -DI for ADX
      dobuy = true;
    }
  }
  return(dobuy);
}

Wir haben beschlossen, die Bedingungen zur Eröffnung eines Buy-Handels in diese Funktion zu packen. Wir haben hier keine der Funktionalitäten der Klassen-Objekte verwendet. Wir suchen nach Bedingungen, in denen die Werte des Indikators 'Gleitender Durchschnitt' nach oben ansteigen und der Abschlusskurs des vorigen Balkens größer als der Wert des Gleitenden Durchschnitts an diesem Punkt ist.

Zudem wollen wir auch ein Szenario, in dem der Wert des ADX-Indikators größer ist als das erforderliche Minimum, das wir in den Eingabeparametern festgelegt haben, sowie dass der Wert des positiven DI des ADX-Indikators größer ist als der negative DI-Wert. Sobald all dies erfüllt ist, soll unser EA eine BUY-Order eröffnen.

2.1.4 Die checkSell Funktion

//+------------------------------------------------------------------+
//|  Checks for a Sell trade Condition                               |
//+------------------------------------------------------------------+
bool checkSell()
{
  bool dosell = false;
  if ((maVal[0]<maVal[1]) && (maVal[1]<maVal[2]) &&(p_close < maVal[1]))
  {
    // MA decreases downwards and previuos price closed below MA
    if ((adxVal[1]>Adx_Min)&& (minDI[1]>plsDI[1]))
    {
      // ADX is greater than minimum and -DI is greater tha +DI for ADX
      dosell = true;
    }
  }
  return(dosell);
}

Diese Funktion überprüft genau das Gegenteil der CheckBuy Funktion. Auch hier haben wir keine Klassen-Objekte in dieser Funktion verwendet. Wir suchen nach Bedingungen, in denen die Werte des Indikators 'Gleitender Durchschnitt' nach unten fallen und der Abschlusskurs des vorigen Balkens kleiner als der Wert des Gleitenden Durchschnitts an diesem Punkt ist.

Zudem wollen wir auch ein Szenario, in dem der Wert des ADX-Indikators größer ist als das erforderliche Minimum, das wir in den Eingabeparametern festgelegt haben, sowie dass der Wert des negativen DI des ADX-Indikators größer ist als der positive DI-Wert. Sobald all dies erfüllt ist, soll unser EA eine SELL-Order eröffnen.

2.1.5 Die DeletePending Funktion
//+------------------------------------------------------------------+
//|  Checks if an Open position can be closed                        |
//+------------------------------------------------------------------+
bool checkClosePos(string ptype, double Closeprice)
{
   bool mark = false;
   if (ptype=="BUY")
   {
      // Can we close this position
     if (Closeprice < maVal[1]) // Previous price close below MA
      {
         mark = true;
      }
   }
   if (ptype=="SELL")
   {
      // Can we close this position
      if (Closeprice > maVal[1]) // Previous price close above MA
      {
         mark = true;
      }
   }
   return(mark);
}

Mit dieser Funktion wird geprüft, ob die aktuell offene Position geschlossen werden kann. Mit ihrer Hilfe wird kontrolliert, ob der Schlusskurs des vorigen Balkens größer oder kleiner als der Wert des Indikators 'Gleitender Durchschnitt' an dieser Stelle ist (je nach Richtung des Handels).

Sobald diese Bedingungen erfüllt sind, liefert uns diese Funktion'true', sodass wir damit rechnen, dass unser EA die Position schließt. Diese Funktion besitzt zwei Eingabeparameters: die Art der Order (diesmal den Namen BUY oder SELL) sowie den Schlusskurs des vorigen Balkens.

2.1.6 Die ClosePosition Funktion

//+------------------------------------------------------------------+
//| Checks and closes an open position                               |
//+------------------------------------------------------------------+
bool ClosePosition(string ptype,double clp)
  {
   bool marker=false;
     
      if(myposition.Select(_Symbol)==true)
        {
         if(myposition.Magic()==EA_Magic && myposition.Symbol()==_Symbol)
           {
            //--- Check if we can close this position
            if(checkClosePos(ptype,clp)==true)
              {
               //--- close this position and check if we close position successfully?
               if(mytrade.PositionClose(_Symbol)) //--- Request successfully completed 
                 {
                  Alert("An opened position has been successfully closed!!");
                  marker=true;
                 }
               else
                 {
                  Alert("The position close request could not be completed - error: ",
                       mytrade.ResultRetcodeDescription());
                 }
              }
           }
        }
      return(marker);
     }

Dies ist die Funktion, die die o.g. Funktion tatsächlich anwendet (checkclosepos). Sie bedient sich der Objekte der CPositionInfo und CTrade Klassen. Diese Funktion verwendet das Objekt der CPositionInfo Klasse zur Prüfung der verfügbaren offenen Positionen für die Position, die unser EA eröffnet hat, sowie für das aktuelle Symbol. Sobald eine Position gefunden wird, prüft die Funktion, ob sie mit Hilfe der checkclosepos Funktion geschlossen werden kann.

Liefert checkclosepos 'true', verwendet diese Funktion das Objekt derCTrade Klasse zum Schließen der Position und zeigt die Ergebnisse für diesen Vorgang an. Wurde die Position erfolgreich abgeschlossen, liefert die Funktion 'true'; ansonsten liefert sie 'false'.

Die Funktion nimmt zwei Eingabeparameter (den position name , BUY oder SELL und denprevious bar close price). Diese Parameter wurden in der Tat an die checkclosepos Funktion übertragen, die sie verwendet.

2.1.7 Die CheckModify Funktion

//+------------------------------------------------------------------+
//|  Checks if we can modify an open position                        |
//+------------------------------------------------------------------+
bool CheckModify(string otype,double cprc)
{
   bool check=false;
   if (otype=="BUY")
   {
      if ((maVal[2]<maVal[1]) && (maVal[1]<maVal[0]) && (cprc>maVal[1]) && (adxVal[1]>Adx_Min))
      {
         check=true;
      }
   }
   else if (otype=="SELL")
   {
      if ((maVal[2]>maVal[1]) && (maVal[1]>maVal[0]) && (cprc<maVal[1]) && (adxVal[1]>Adx_Min))
      {
         check=true;
      }
   }
   return(check);
}

Mit dieser Funktion wird nach einer Bedingung gesucht, die bestätigt, ob eine geöffnete Position verändert werden kann oder nicht. Sie verwendet die Namen des Ordertyps und den Schlusskurs des vorigen Balkens als Eingabeparameter.

Diese Funktion überprüft, ob der Gleitende Durchschnitt weiterhin nach oben ansteigt und der Schlusskurs am vorigen Balken immer noch höher als der Wert des Gleitenden Durchschnitts an diesem Punkt ist. Und ob der ADX-Wert auch größer als das erforderliche Minimum (für eine BUY-Position) ist, und prüft zugleich, ob der Gleitende Mittelwert weiterhin nach unten fällt und der Schlusskurs am vorigen Balken immer noch niedriger als der Wert des Gleitenden Durchschnitts an diesem Punkt ist (für eine SELL-Position). Je nach Art der vorliegenden Position, berücksichtigt der EA, sobald eine der Bedingungen erfüllt ist, eine Veränderung der Position.

Die Funktion nimmt zwei Eingabeparameter (den position name , BUY oder SELL und denprevious bar close price).

2.1.8 Die Modifizierungsfunktion

//+------------------------------------------------------------------+
//| Modifies an open position                                        |
//+------------------------------------------------------------------+
   void Modify(string ptype,double stpl,double tkpf)
     {
       //--- New Stop Loss, new Take profit, Bid price, Ask Price
      double ntp,nsl,pbid,pask;                  
      long tsp=Trail_point;
       //--- adjust for 5 & 3 digit prices
      if(_Digits==5 || _Digits==3) tsp=tsp*10;   
       //--- Stops Level
      long stplevel= mysymbol.StopsLevel();      
       //--- Trail point must not be less than stops level
      if(tsp<stplevel) tsp=stplevel;
      if(ptype=="BUY")
        {
          //--- current bid price
         pbid=mysymbol.Bid();           
         if(tkpf-pbid<=stplevel*_Point)
           {
            //--- distance to takeprofit less or equal to Stops level? increase takeprofit
            ntp = pbid + tsp*_Point;
            nsl = pbid - tsp*_Point;
           }
         else
           {
            //--- distance to takeprofit higher than Stops level? dont touch takeprofit
            ntp = tkpf;
            nsl = pbid - tsp*_Point;
           }
        }
      else //--- this is SELL
        {
          //--- current ask price
         pask=mysymbol.Ask();            
         if(pask-tkpf<=stplevel*_Point)
           {
            ntp = pask - tsp*_Point;
            nsl = pask + tsp*_Point;
           }
         else
           {
            ntp = tkpf;
            nsl = pask + tsp*_Point;
           }
        }
      //--- modify and check result
      if(mytrade.PositionModify(_Symbol,nsl,ntp))  
        {
          //--- Request successfully completed    
         Alert("An opened position has been successfully modified!!");
         return;
        }
      else
        {
         Alert("The position modify request could not be completed - error: ",
               mytrade.ResultRetcodeDescription());
         return;
        }

     }

Diese Funktion bedient sich der o.g. Funktion (checkmodify) , um diese Aufgabe auszuführen. Sie verwendet die Objekte der CSymbolInfo und CTrade Klassen. Zunächst haben wir hier vier doppelte Datentypen deklariert, um den neuen Take Profit, Stop Loss, Geldkurs und Briefkurs aufzunehmen. Dann haben wir einen neuen langen Datentyp tsp deklariert, um den Trail_point Wert aufzunehmen, den wir im Bereich Eingabeparameter deklariert haben.

Der Nachzugspunktwert (tsp) wurde dann für 5 und 3 Zahlenkurse angepasst. dann haben wir das CSymbolInfo Objekt verwendet, um das stops level zu erhalten und sicherzustellen, dass der Nachzugspunkt, den wir hinzufügen wollen, nicht geringer als das erforderliche Stop-Level ist. Sollte er geringer sein, dann verwenden wir stattdessen den Wert der Stops-Level.

Je nach Art der Position, verwenden wir ein CSymbolInfo Klassenobjekt, um den aktuellen GELD- oder ggf. BRIEFkurs zu erhalten. Ist die Differenz zwischen dem aktuellen GELD- oder BRIEFkurs und dem ursprünglichen Take Profit Kurs weniger oder gleich der Stops-Levels, passen wir sowohl den Stop Loss als auch den Take Profit Preis an. Ansonsten passen wir nur den Stop Loss Wert an

Anschließend nehmen wir das CTrade Klassenobjekt zur Veränderung des Stop Loss und Take Profit für diese Position. Basierend auf dem Lieferungscode für das Handelsergebnis wird entweder die Meldung 'Erfolg' oder 'Fehlschlag' angezeigt.

Wir sind jetzt mit der Festlegung einiger benutzerdefinierter Funktionen fertig, die unsere Arbeit wesentlich erleichtern werden. Wenden wir uns nun dem Bereich der EA-Codes zu.

2.1.9 Der OnInit Bereich

//--- set the symbol name for our SymbolInfo Object
   mysymbol.Name(_Symbol);
// Set Expert Advisor Magic No using our Trade Class Object
   mytrade.SetExpertMagicNumber(EA_Magic);
// Set Maximum Deviation using our Trade class object
   mytrade.SetDeviationInPoints(dev);
//--- Get handle for ADX indicator
   adxHandle=iADX(NULL,0,ADX_Period);
//--- Get the handle for Moving Average indicator
   maHandle=iMA(_Symbol,Period(),MA_Period,0,MODE_EMA,PRICE_CLOSE);
//--- What if handle returns Invalid Handle
   if(adxHandle<0 || maHandle<0)
     {
      Alert("Error Creating Handles for MA, ADX indicators - error: ",GetLastError(),"!!");
      return(1);
     }
   STP = StopLoss;
   TKP = TakeProfit;
//--- Let us handle brokers that offers 5 or 3 digit prices instead of 4
   if(_Digits==5 || _Digits==3)
     {
      STP = STP*10;
      TKP = TKP*10;
     }
   
//--- Set trade percent
    TPC = TradePct;
    TPC = TPC/100;
//---

Wir setzen das aktuelle Symbol für das CSymbolInfo Klassenobjekt. Außerdem setzen wir mit Hilfe des CTrade Klassenobjekts auch die magische Zahl des Expert Advisors sowie die Abweichung (in Punkten). Danach holen wir uns die Handles für unsere Indikatoren und lassen eine Fehlermeldung anzeigen, sollte beim Erhalt der Handles etwas schief gelaufen sein.

Anschließend passen wir Stop Loss und Take Profit für 3- und 5-stellige Preise an und wandeln auch den Prozentwert der freien Account-Marge um, die wir für den Handel (in Prozenten) verwenden können.

2.1.10 Der OnDeinit Bereich

//--- Release our indicator handles
   IndicatorRelease(adxHandle);
   IndicatorRelease(maHandle);

Hier werden die Indikator-Handles freigegeben.

2.1.11 Der OnTick Bereich

//--- check if EA can trade
    if (checkTrading() == false) 
   {
      Alert("EA cannot trade because certain trade requirements are not meant");
      return;
   }
//--- Define the MQL5 MqlRates Structure we will use for our trade
   MqlRates mrate[];          // To be used to store the prices, volumes and spread of each bar
/*
     Let's make sure our arrays values for the Rates, ADX Values and MA values 
     is store serially similar to the timeseries array
*/
// the rates arrays
   ArraySetAsSeries(mrate,true);
// the ADX values arrays
   ArraySetAsSeries(adxVal,true);
// the MA values arrays
   ArraySetAsSeries(maVal,true);
// the minDI values array
   ArraySetAsSeries(minDI,true);
// the plsDI values array
   ArraySetAsSeries(plsDI,true);

Als erstes prüfen wir, ob unser EA handeln sollte oder nicht. Liefert uns die checktrade Funktion 'false', warten wir auf den nächsten Tick (Kursschwankung) und prüfen noch einmal.

Danach deklarieren wir die MQL5 MqlRates Struktur, um die Kurse jedes Balkens zu bekommen und verwenden dann die ArraySetAsSeries Funktion, um alle erforderlichen Arrays einzurichten.

//--- Get the last price quote using the SymbolInfo class object function
   if (!mysymbol.RefreshRates())
     {
      Alert("Error getting the latest price quote - error:",GetLastError(),"!!");
      return;
     }

//--- Get the details of the latest 3 bars
   if(CopyRates(_Symbol,_Period,0,3,mrate)<0)
     {
      Alert("Error copying rates/history data - error:",GetLastError(),"!!");
      return;
     }

//--- EA should only check for new trade if we have a new bar
// lets declare a static datetime variable
   static datetime Prev_time;
// lest get the start time for the current bar (Bar 0)
   datetime Bar_time[1];
   //copy the current bar time
   Bar_time[0] = mrate[0].time;
// We don't have a new bar when both times are the same
   if(Prev_time==Bar_time[0])
     {
      return;
     }
//Save time into static varaiable, 
   Prev_time = Bar_time[0];

Mit Hilfe des CSymbolInfo Klassenobjekts bekommen wir die aktuellen Kursquoten und kopieren dann die aktuellen Balkenkurse in das mrates Array. Und gleich danach sehen wir nach, ob ein neuer Balken aufgetaucht ist.

Falls ja, wird unser EA selbst nachsehen, ob eine BUY oder SELL Bedingung vorliegt. Falls nicht, wartet er auf den nächsten Balken.

//--- Copy the new values of our indicators to buffers (arrays) using the handle
   if(CopyBuffer(adxHandle,0,0,3,adxVal)<3 || CopyBuffer(adxHandle,1,0,3,plsDI)<3
      || CopyBuffer(adxHandle,2,0,3,minDI)<3)
     {
      Alert("Error copying ADX indicator Buffers - error:",GetLastError(),"!!");
      return;
     }
   if(CopyBuffer(maHandle,0,0,3,maVal)<3)
     {
      Alert("Error copying Moving Average indicator buffer - error:",GetLastError());
      return;
     }
//--- we have no errors, so continue
// Copy the bar close price for the previous bar prior to the current bar, that is Bar 1

   p_close=mrate[1].close;  // bar 1 close price

Wir haben hier die CopyBuffer Funktionen verwendet , um die Buffer unserer Indikatoren in Arrays zu bringen. Sollten hierbei Fehler auftreten, werden diese angezeigt. Der Schlusskurs des vorigen Balkens wurde kopiert.

//--- Do we have positions opened already?
  bool Buy_opened = false, Sell_opened=false; 
   if (myposition.Select(_Symbol) ==true)  // we have an opened position
    {
      if (myposition.Type()== POSITION_TYPE_BUY)
       {
            Buy_opened = true;  //It is a Buy
          // Get Position StopLoss and Take Profit
           double buysl = myposition.StopLoss();      // Buy position Stop Loss
           double buytp = myposition.TakeProfit();    // Buy position Take Profit
           // Check if we can close/modify position
           if (ClosePosition("BUY",p_close)==true)
             {
                Buy_opened = false;   // position has been closed
                return; // wait for new bar
             }
           else
           {
              if (CheckModify("BUY",p_close)==true) // We can modify position
              {
                  Modify("BUY",buysl,buytp);
                  return; // wait for new bar
              }
           } 
       }
      else if(myposition.Type() == POSITION_TYPE_SELL)
       {
            Sell_opened = true; // It is a Sell
            // Get Position StopLoss and Take Profit
            double sellsl = myposition.StopLoss();    // Sell position Stop Loss
            double selltp = myposition.TakeProfit();  // Sell position Take Profit
             if (ClosePosition("SELL",p_close)==true)
             {
               Sell_opened = false;  // position has been closed
               return;   // wait for new bar
             }
             else
             {
                 if (CheckModify("SELL",p_close)==true) // We can modify position
                 {
                     Modify("SELL",sellsl,selltp);
                     return;  //wait for new bar
                 }
             } 
       }
    }

Mit Hilfe des CPositionInfo Klassenobjekts wählen und prüfen wir nach, ob wir für das aktuelle Symbol eine offenen Position haben. Falls ja, und wenn diese Position ein BUY ist, setzen wir Buy_opened auf 'true' und verwenden dann das CPositionInfo Klassenobjekt, um den Stop Loss und Take Profit der Position zu bekommen. Mit Hilfe einer bereits zuvor festgelegten Funktion, ClosePosition, haben wir geprüft, ob die Position geschlossen werden kann. Liefert uns die Funktion 'true', ist die Position geschlossen worden. Also setzen wir Buy_opened auf 'false', wo die ursprüngliche BUY-Position gerade geschlossen wurde. Der EA wartet nun den nächsten Tick ab.

Sollte die Funktion jedoch 'false' liefern, ist die Position nicht geschlossen worden. Jetzt können wir nachsehen, ob wir die Position verändern können. Dies geht mit Hilfe von CheckModify, was wir oben festgelegt haben. Liefert uns die Funktion 'true', bedeutet das, dass die Position verändert werden kann, also machen wir dies mit Hilfe der Modify Funktion.

Falls jedoch andererseits eine Position existiert und dies ein SELL ist, setzen wir Sell_opened auf 'true' und verwenden dann das CPositionInfo Klassenobjekt, um den Stop Loss und Take Profit der Position zu bekommen. Wir haben die gleichen Schritte wie bei der BUY-Position wiederholt, um so zu sehen, ob die Position geschlossen oder verändert werden kann.

      if(checkBuy()==true)
        {
         //--- any opened Buy position?
         if(Buy_opened)
           {
            Alert("We already have a Buy position!!!");
            return;    //--- Don't open a new Sell Position
           }

         double mprice=NormalizeDouble(mysymbol.Ask(),_Digits);                //--- latest ask price
         double stloss = NormalizeDouble(mysymbol.Ask() - STP*_Point,_Digits); //--- Stop Loss
         double tprofit = NormalizeDouble(mysymbol.Ask()+ TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_BUY,mprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- open Buy position and check the result
         if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
         //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit)) 
           {
               //--- Request is completed or order placed
             Alert("A Buy order has been successfully placed with deal Ticket#:",
                  mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Buy order request at vol:",mytrade.RequestVolume(), 
                  ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
                  ", price:", mytrade.RequestPrice(), 
                     " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }
        }

Wir können aber auch die PositionOpen Funktion verwenden

if(checkBuy()==true)
        {
         //--- any opened Buy position?
         if(Buy_opened)
           {
            Alert("We already have a Buy position!!!");
            return;    //--- Don't open a new Sell Position
           }

         double mprice=NormalizeDouble(mysymbol.Ask(),_Digits);               //--- latest Ask price
         double stloss = NormalizeDouble(mysymbol.Ask() - STP*_Point,_Digits); //--- Stop Loss
         double tprofit = NormalizeDouble(mysymbol.Ask()+ TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_BUY,mprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- open Buy position and check the result
         //if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
         if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit))
           {
              //--- Request is completed or order placed            
              Alert("A Buy order has been successfully placed with deal Ticket#:",
            mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Buy order request at vol:",mytrade.RequestVolume(), 
                    ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                    ", price:", mytrade.RequestPrice(), 
                    " could not be completed -error:",mytrade.ResultRetcodeDescription());

            return;
           }
        }

Hier verwenden wir die Funktion checkbuy zur Prüfung zur Einrichtung eines BUY, und falls wir 'true' bekommen, sind unsere Handelsbedingungen für einen BUY erfüllt worden. Wenn wir bereits eine BUY-Position haben, wollen wir ja keine neue Order platzieren. Danach haben wir das CSymbolInfo Klassenobjekt verwendet, um den aktuellen BRIEFkurs zu bekommen und haben Stop Loss und Take Profit wie erforderlich verändert.

Wir haben auch die ConfirmMargin Funktion verwendet, um nachzusehen, ob der Prozentwert des Accounts, der zur Platzierung einer Order zulässig ist, größer als die zur Platzierung dieser Order erforderliche Marge ist. Liefert uns die Funktion 'true', dann platzieren wir den Handel. Ansonsten tun wird dies nicht.

Mit Hilfe des CTrade Klassenobjekts haben wir unsere Order platziert und das gleiche Aufrufs-Objekts benutzt, um den Lieferungs-Code der Handels-Operation zu bekommen. Auf Grundlage der Ergebnisse des Handels wird uns eine Meldung angezeigt.

if(checkSell()==true)
        {
         //--- any opened Sell position?
         if(Sell_opened)
           {
            Alert("We already have a Sell position!!!");
            return;    //--- Wait for a new bar
           }

         double sprice=NormalizeDouble(mysymbol.Bid(),_Digits);             //--- latest Bid price
         double ssloss=NormalizeDouble(mysymbol.Bid()+STP*_Point,_Digits);   //--- Stop Loss
         double stprofit=NormalizeDouble(mysymbol.Bid()-TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_SELL,sprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- Open Sell position and check the result
         if(mytrade.Sell(Lot,_Symbol,sprice,ssloss,stprofit))
         //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_SELL,Lot,sprice,ssloss,stprofit))
           {
               //---Request is completed or order placed            
               Alert("A Sell order has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Sell order request at Vol:",mytrade.RequestVolume(), 
                    ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                    ", price:", mytrade.RequestPrice(), 
                    " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }

        }

Wir können aber auch die PositionOpen Funktion verwenden:

if(checkSell()==true)
        {
         //--- any opened Sell position?
         if(Sell_opened)
           {
            Alert("We already have a Sell position!!!");
            return;    //--- Wait for a new bar
           }

         double sprice=NormalizeDouble(mysymbol.Bid(),_Digits);             //--- latest Bid price
         double ssloss=NormalizeDouble(mysymbol.Bid()+STP*_Point,_Digits);   //--- Stop Loss
         double stprofit=NormalizeDouble(mysymbol.Bid()-TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_SELL,sprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- Open Sell position and check the result
         //if(mytrade.Sell(Lot,_Symbol,sprice,ssloss,stprofit))
         if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_SELL,Lot,sprice,ssloss,stprofit))
           {
             //---Request is completed or order placed            
             Alert("A Sell order has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Sell order request at Vol:",mytrade.RequestVolume(),
                 ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                 ", price:", mytrade.RequestPrice(), 
                   " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }
        }

Genauso wie wir es gerade bei BUY gemacht haben, suchen wir mit Hilfe der Checksell Funktion nach einer Sell-Einrichtung. Liefert sie uns 'true' und wir haben noch keine Sell-Position offen, dann prüfen wir mit Hilfe der ConfirmMargin Funktion, ob wir genügend Geld zum Eröffnen der Order haben. Liefert uns ConfirmMargin 'true', platzieren wir mit Hilfe des CTrade Klassenobjekts. Auf Grundlage der Antwort vom Handelsserver, wird das Ergebnis des Handels mit Hilfe der CTrade Klassenobjekt-Funktionen angezeigt.

Bis jetzt haben wir uns angesehen, wie wir die Trade class Libraries beim Schreiben eines Expert Advisors nutzen können. Als nächstes müssen wir unseren Expert Advisor mit dem Strategie-Tester testen und seine Leistung begutachten

Den EA-Code erstellen und dann in den Strategie-Tester laden.

Erstellungsbericht für den EA

Abb. 3 Expert Advisor Erstellungsbericht

Unter Verwendung der Standard-Einstellungen: Take Profit - 270, Stop Loss - 100 und Nachzugspunkt (TP/SL) - 32, erhalten wir auf dem GBPUSD Tages-Chart folgende Ergebnisse:

Abb. 4 Expert Advisor Testbericht - GBPUSD Tages-Chart

Abb. 5 Expert Advisor Testgraph - GBPUSD Tages-Chart

Abb. 6 Expert Advisor Testbericht zeigt Veränderungen von offenen Positions - GBPUSD Tages-Chart

Abb. 7 Expert Advisor Test-Chartbericht für GBPUSD Tages-Chart

Sie können den EA gerne auf jeden anderen Symbol-Tages-Chart mit unterschiedlichen Einstellungen von Take Profit, Stop Loss und Nachzugspunkt-Einstellungen testen und schauen was dabei herauskommt.

Sie sollten hierbei allerdings nie vergessen, dass dieser Expert Advisor nur zu Testzwecken geschrieben worden ist.

Schauen wir uns jetzt an, wie wir andere Klassen (COrderInfo, CHistoryOrderInfo, und CDealInfo) verwenden können, um Details zu Orders/Abschlüssen zu bekommen.

2.2 Eine Pending Order eröffnen/löschen

In diesem Beispiel schreiben wir einen einfachen Expert Advisor, der eine pending Order (BuyStop oder SellStop) platziert, wenn Bedingungen für eine Buy bzw. eine Sell-Einrichtung erfüllt sind.

2.2.1 Die erforderlichen Klassen mit einschließen

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The Trade Class
#include <Trade\Trade.mqh>
//--- The PositionInfo Class
#include <Trade\PositionInfo.mqh>
//--- The SymbolInfo Class
#include <Trade\SymbolInfo.mqh>
//--- The OrderInfo Class
#include <Trade\OrderInfo.mqh>

Wir haben die vier Klassen umfasst, die wir in diesem einfachen Expert Advisor verwenden werden, und haben sie in den Beispielen oben erklärt.

Ich beschreibe daher hier nicht jeden Abschnitt des Expert Advisors, da er dem oben ausführlich erklärten sehr ähnlich ist. Ich werde jedoch den wichtigen Teil des Expert Advisors erläutern, der erklärt, was wir in diesem Abschnitt besprechen wollen.

Der einzige Unterschied ist, dass wir beschlossen haben, ein MqlRates mrate[] auf globalem Umfang zu deklarieren.

//--- Define the MQL5 MqlRates Structure we will use for our trade
   MqlRates mrate[];     // To be used to store the prices, volumes and spread of each bar

Haben wir dann die Klassen mit eingeschlossen, dürfen wir nicht vergessen, Objekte jeder Klasse zu erzeugen:

//+------------------------------------------------------------------+
//|  CREATE CLASS OBJECTS                                            |
//+------------------------------------------------------------------+
//--- The CTrade Class Object
CTrade mytrade;
//--- The CPositionInfo Class Object
CPositionInfo myposition;
//--- The CSymbolInfo Class Object
CSymbolInfo mysymbol;
//--- The COrderInfo Class Object
COrderInfo myorder;

Die CheckBuy() und CheckSell() Funktionen sind die gleichen wie im oben erklärten Expert Advisor.

Was wir hier tun wollen, ist eine BUYSTOP Order bei einer Buy-Einrichtung platzieren, und eine SELLSTOP Order bei einer Sell-Einrichtung.

Sehen wir uns einige der Funktionen, die wir zur Erleichterung unserer Arbeit, erzeugt haben, an.

2.2.2 Die CountOrders Funktion

//+------------------------------------------------------------------+
//|  Count Total Orders for this expert/symbol                             |
//+------------------------------------------------------------------+
int CountOrders()
  {
   int mark=0;

   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(myorder.Select(OrderGetTicket(i)))
        {
         if(myorder.Magic()==EA_Magic && myorder.Symbol()==_Symbol) mark++;
        }
     }
   return(mark);
  }

Mit dieser Funktion erhält man die gesamten pending Orders, die zu einem bestimmten Zeitpunkt vorhanden sind.

Mit Hilfe des Objekts unserer Klasse COrderInfo haben wir die Details der Order geprüft, ob sie mittels der myorder.Select() Funktion erfolgreich ausgewählt wurde.

Wenn die durch unser Klassenobjekt gelieferte Magische Zahl und das Symbol das sind, was wir wollen, hat unser Expert Advisor die Order platziert. Also wird sie gezählt und in der Variablen mark abgelegt.

2.2.3 Die DeletePending Funktion

//+------------------------------------------------------------------+
//| Checks and Deletes a pending order                                |
//+------------------------------------------------------------------+
bool DeletePending()
  {
   bool marker=false;
//--- check all pending orders
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(myorder.Select(OrderGetTicket(i)))
        {
         if(myorder.Magic()==EA_Magic && myorder.Symbol()==_Symbol)
           {
            //--- check if order has stayed more than two bars time
            if(myorder.TimeSetup()<mrate[2].time)
              {
               //--- delete this pending order and check if we deleted this order successfully?
                if(mytrade.OrderDelete(myorder.Ticket())) //Request successfully completed 
                  {
                    Alert("A pending order with ticket #", myorder.Ticket(), " has been successfully deleted!!");
                    marker=true;
                  }
                 else
                  {
                    Alert("The pending order # ",myorder.Ticket(),
                             " delete request could not be completed - error: ",mytrade.ResultRetcodeDescription());
                  }

              }
           }
        }
     }
   return(marker);
  }

Genauso wie die countorder Funktion bedient sich diese Funktion auch der COrderInfo Klassenfunktionen, um Eigenschaften von Orders zu bekommen. Die Funktion sucht nach jeder pending Order, die drei Balken zuvor eingerichtet (die Zeit der Einrichtung der pending Order ist weniger als mrate[2].time) und noch nicht ausgelöst wurde.

Fällt irgendeine Order in diese Kategorie, wird diese Order mit Hilfe der CTrade Klassenfunktion OrderDelete gelöscht. Bei Erfolg liefert uns diese Funktion 'true', bei Fehlschlagen 'false'.

Die beiden o.g. Funktionen werden sofort nachdem sich ein neuer Balken gebildet hat, verwendet und noch vor der Prüfung nach der Einrichtung eines neuen Handels. Wir möchten auch sichergehen, dass wir zu einem bestimmten Zeitpunkt nicht mehr als maximal drei pending Orders platziert haben. Dazu verwenden wir folgenden Code:

// do we have more than 3 already placed pending orders
if (CountOrders()>3) 
  {
     DeletePending(); 
     return;  
  }

2.2.4 Platzierung einer Pending Order

if(checkBuy()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Buy position?
      if(Buy_opened)
        {
         Alert("We already have a Buy position!!!");
         return;    //--- Don't open a new Sell Position
        }
      //Buy price = bar 1 High + 2 pip + spread
      int sprd=mysymbol.Spread();
      double bprice =mrate[1].high + 10*_Point + sprd*_Point;
      double mprice=NormalizeDouble(bprice,_Digits);               //--- Buy price
      double stloss = NormalizeDouble(bprice - STP*_Point,_Digits); //--- Stop Loss
      double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits); //--- Take Profit
      //--- open BuyStop order
      if(mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit))
      //if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_BUY_STOP,Lot,0.0,bprice,stloss,tprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A BuyStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The BuyStop order request at vol:",mytrade.RequestVolume(), 
                 ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
               ", price:", mytrade.RequestPrice(), 
                 " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

Wir können aber auch die OrderOpen Funktion zur Platzierung der BUYSTOP Order verwenden

if(checkBuy()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Buy position?
      if(Buy_opened)
        {
         Alert("We already have a Buy position!!!");
         return;    //--- Don't open a new Sell Position
        }
      //Buy price = bar 1 High + 2 pip + spread
      int sprd=mysymbol.Spread();
      double bprice =mrate[1].high + 10*_Point + sprd*_Point;
      double mprice=NormalizeDouble(bprice,_Digits);               //--- Buy price
      double stloss = NormalizeDouble(bprice - STP*_Point,_Digits); //--- Stop Loss
      double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits); //--- Take Profit
      //--- open BuyStop order
      //if(mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit))
      if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_BUY_STOP,Lot,0.0,bprice,stloss,tprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A BuyStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The BuyStop order request at vol:",mytrade.RequestVolume(), 
              ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
              ", price:", mytrade.RequestPrice(), 
                " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

Bei Platzierung einer BUYSTOP Order, ist der Eröffnungskurs der Balken 1 High + 2Pip (Kursänderung) + Spread (Differenz zw. Geld- und Briefkurs).

Denken Sie daran, dass der angezeigte Kurs auf dem Chart der GELDkurs ist und Sie bei der Platzierung von Long/Buy-Orders den BRIEFkurs brauchen. Deshalb haben wir den Spread dem Balken 1 High hinzugefügt, damit wir jetzt den entsprechenden Briefkurs + 2pip haben. Stop Loss und Take Profit wurden bereist in den Eingabeparametern definiert.

Haben wir dann alle notwendigen Parameter vorbereitet, platzieren wir unsere Order mit Hilfe der CTrade Klassenfunktion BuyStop oder OrderOpen. Die Art der Order ist hier ORDER_TYPE_BUY_STOP (Buy Stop Order). Wir verwenden den gleichen Preis für den Limitpreis, doch handelt es sich hier nicht um eine BuyLimit Order. Zudem setzen wir die Gültigkeitszeit der Order auf ORDER_TIME_GTC, d.h. die Order bleibt gültig bis sie storniert wird.

Wenn Sie ORDER_TIME_GTC oder ORDER_TIME_DAY verwenden, müssen Sie keien Ablaufzeit angeben, deshalb haben wir die Ablaufzeit auf 0 gesetzt.

if(checkSell()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Sell position?
      if(Sell_opened)
        {
         Alert("We already have a Sell position!!!");
         return;    //--- Wait for a new bar
        }
      //--- Sell price = bar 1 Low - 2 pip 
      double sprice=mrate[1].low-10*_Point;
      double slprice=NormalizeDouble(sprice,_Digits);            //--- Sell price
      double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);   //--- Stop Loss
      double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits); //--- Take Profit
      //--- Open SellStop Order
      if(mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit))
      //if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELL_STOP,Lot,0.0,slprice,ssloss,stprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A SellStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The SellStop order request at Vol:",mytrade.RequestVolume(), 
              ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                ", price:", mytrade.RequestPrice(), 
                " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

Wir können aber auch die OrderOpen Funktion zur Platzierung der Order verwenden:

if(checkSell()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Sell position?
      if(Sell_opened)
        {
         Alert("We already have a Sell position!!!");
         return;    //--- Wait for a new bar
        }
      //--- Sell price = bar 1 Low - 2 pip 
      double sprice=mrate[1].low-10*_Point;
      double slprice=NormalizeDouble(sprice,_Digits);            //--- Sell price
      double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);   //--- Stop Loss
      double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits); //--- Take Profit
      //--- Open SellStop Order
      //if(mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit))
      if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELL_STOP,Lot,0.0,slprice,ssloss,stprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A SellStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The SellStop order request at Vol:",mytrade.RequestVolume(), 
                ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                ", price:", mytrade.RequestPrice(), 
              " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

Wie bei der Platzierung der BuyStop Order, ist der Eröffnungskurs der Balken 1 low + 2pip. Hier müssen wir keinen Spread hinzufügen, da wir ja den GELDkurs zur Platzierung von Short/Sell Orders brauchen.

Zur Platzierung der SellStop Order verwenden wir auch die gleiche OrderOpen Funktion oder die SellStop Funktion. Die Art der Order ist hier ORDER_TYPE_SELL_STOP (Sell Stop Order).

Unten sehen Sie die Ergebnisse unseres einfachen Expert Advisors.

Abb. 8 Testbericht für den pending Order EA

Abb. 9 Graphbericht für den EA

Abb. 10. Chartbericht für den EA

2.3 Wie man Details zu Orders/Abschlüssen erhält

In diesem Beispiel zeigen wir, wie man die Details einer Order erhält, sobald diese ausgelöst worden ist.

In dieser Phase ist sie keine pending Order mehr, da sie ausgelöst wurde und somit zu einem Abschluss geworden ist

Um diese Verfahren auch wirklich zu verstehen, betrachten wir uns die Logbuch-Details eines unserer Handel:

Bearbeitungsvorgang der Order

Abb. 11 Bearbeitungsvorgang der Order

  • Schritt 1: Eine pending Order wird platziert und wartet darauf, bis die Bedingungen erfüllt sind (pending Order)
  • Schritt 2: Bedingung ist erfüllt, pending Order wird ausgelöst und wird zu einem Abschluss (pending Order ist jetzt in der History)
  • Schritt 3: Abschlus wird ausgeführt und wir haben eine eröffnete Position. (Abschluss ist jetzt in der History)

2.3.1 Wie man Eigenschaften von Orders erhält (History)

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The Trade Class
#include <Trade\HistoryOrderInfo.mqh>
//+------------------------------------------------------------------+
//|  CREATE CLASS OBJECT                                             |
//+------------------------------------------------------------------+
//--- The HistoryOrderInfo Class Object
CHistoryOrderInfo myhistory;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Get all orders in History and get their details
   int buystop=0;
   int sellstop=0;
   int buylimit=0;
   int selllimit=0;
   int buystoplimit=0;
   int sellstoplimit=0;
   int buy=0;
   int sell=0;

   int s_started=0;
   int s_placed=0;
   int s_cancelled=0;
   int s_partial=0;
   int s_filled=0;
   int s_rejected=0;
   int s_expired=0;

   ulong o_ticket;
// Get all history records
   if(HistorySelect(0,TimeCurrent())) // get all history orders
     {
      // Get total orders in history
      for(int j=HistoryOrdersTotal(); j>0; j--)
        {
         // select order by ticket
         o_ticket=HistoryOrderGetTicket(j);
         if(o_ticket>0)
           {
            // Set order Ticket to work with
            myhistory.Ticket(o_ticket);
            Print("Order index ",j," Order Ticket is: ",myhistory.Ticket()," !");
            Print("Order index ",j," Order Setup Time is: ",TimeToString(myhistory.TimeSetup())," !");
            Print("Order index ",j," Order Open Price is: ",myhistory.PriceOpen()," !");
            Print("Order index ",j," Order Symbol is: ",myhistory.Symbol() ," !");
            Print("Order index ",j," Order Type is: ", myhistory.Type() ," !");
            Print("Order index ",j," Order Type Description is: ",myhistory.TypeDescription()," !");
            Print("Order index ",j," Order Magic is: ",myhistory.Magic()," !");
            Print("Order index ",j," Order Time Done is: ",myhistory.TimeDone()," !");
            Print("Order index ",j," Order Initial Volume is: ",myhistory.VolumeInitial()," !");
            //
            //
            if(myhistory.Type() == ORDER_TYPE_BUY_STOP) buystop++;
            if(myhistory.Type() == ORDER_TYPE_SELL_STOP) sellstop++;
            if(myhistory.Type() == ORDER_TYPE_BUY) buy++;
            if(myhistory.Type() == ORDER_TYPE_SELL) sell++;
            if(myhistory.Type() == ORDER_TYPE_BUY_LIMIT) buylimit++;
            if(myhistory.Type() == ORDER_TYPE_SELL_LIMIT) selllimit++;
            if(myhistory.Type() == ORDER_TYPE_BUY_STOP_LIMIT) buystoplimit++;
            if(myhistory.Type() == ORDER_TYPE_SELL_STOP_LIMIT) sellstoplimit++;

            if(myhistory.State() == ORDER_STATE_STARTED) s_started++;
            if(myhistory.State() == ORDER_STATE_PLACED) s_placed++;
            if(myhistory.State() == ORDER_STATE_CANCELED) s_cancelled++;
            if(myhistory.State() == ORDER_STATE_PARTIAL) s_partial++;
            if(myhistory.State() == ORDER_STATE_FILLED) s_filled++;
            if(myhistory.State() == ORDER_STATE_REJECTED) s_rejected++;
            if(myhistory.State() == ORDER_STATE_EXPIRED) s_expired++;
           }
        }
     }
// Print summary
   Print("Buy Stop Pending Orders : ",buystop);
   Print("Sell Stop Pending Orders: ",sellstop);
   Print("Buy Orders : ",buy);
   Print("Sell Orders: ",sell);
   Print("Total Orders in History is :",HistoryOrdersTotal()," !");
   
   Print("Orders type summary");
   Print("Market Buy Orders: ",buy);
   Print("Market Sell Orders: ",sell);
   Print("Pending Buy Stop: ",buystop);
   Print("Pending Sell Stop: ",sellstop);
   Print("Pending Buy Limit: ",buylimit);
   Print("Pending Sell Limit: ",selllimit);
   Print("Pending Buy Stop Limit: ",buystoplimit);
   Print("Pending Sell Stop Limit: ",sellstoplimit);
   Print("Total orders:",HistoryOrdersTotal()," !");

   Print("Orders state summary");
   Print("Checked, but not yet accepted by broker: ",s_started);
   Print("Accepted: ",s_placed);
   Print("Canceled by client: ",s_cancelled);
   Print("Partially executed: ",s_partial);
   Print("Fully executed: ",s_filled);
   Print("Rejected: ",s_rejected);
   Print("Expired: ",s_expired);
  }

Dies ist nur ein einfaches Skript, das zeigt, wie man Details von Orders in unseren History-Einträgen erhält. Wir haben die CHistoryOrderInfo Klasse mit eingeschlossen und ein Objekt der Klasse erzeugt

Und mit Hilfe dieses Objekts holen wir uns nun die Details der Orders.

Ergebnis des History-Order Skripts

Abb. 12 Ergebnis des History-Order Skripts

2.3.2 Wie man Eigenschaften von Abschlüssen erhält (History)

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The CDealInfo Class
#include <Trade\DealInfo.mqh>
//+------------------------------------------------------------------+
//|  Create class object                                             |
//+------------------------------------------------------------------+
//--- The CDealInfo Class Object
CDealInfo mydeal;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Get all deals in History and get their details
    int buy=0;
    int sell=0;
    int deal_in=0;
    int deal_out=0;
    ulong d_ticket;
    // Get all history records
    if (HistorySelect(0,TimeCurrent())) 
    {
      // Get total deals in history
      for (int j=HistoryDealsTotal(); j>0; j--)
      {
         // select deals by ticket
         if (d_ticket = HistoryDealGetTicket(j))
         {
          // Set Deal Ticket to work with
          mydeal.Ticket(d_ticket);
          Print("Deal index ", j ," Deal Ticket is: ", mydeal.Ticket() ," !");
          Print("Deal index ", j ," Deal Execution Time is: ", TimeToString(mydeal.Time()) ," !");
          Print("Deal index ", j ," Deal Price is: ", mydeal.Price() ," !");
          Print("Deal index ", j ," Deal Symbol is: ", mydeal.Symbol() ," !");
          Print("Deal index ", j ," Deal Type Description is: ", mydeal.TypeDescription() ," !");
          Print("Deal index ", j ," Deal Magic is: ", mydeal.Magic() ," !");
          Print("Deal index ", j ," Deal Time is: ", mydeal.Time() ," !");
          Print("Deal index ", j ," Deal Initial Volume is: ", mydeal.Volume() ," !");
          Print("Deal index ", j ," Deal Entry Type Description is: ", mydeal.EntryDescription() ," !");
          Print("Deal index ", j ," Deal Profit is: ", mydeal.Profit() ," !");
          //
          if (mydeal.Entry() == DEAL_ENTRY_IN) deal_in++;
          if (mydeal.Entry() == DEAL_ENTRY_OUT) deal_out++;
          if (mydeal.Type() == DEAL_TYPE_BUY) buy++;
          if (mydeal.Type() == DEAL_TYPE_SELL) sell++;
         }
      }
    }
    // Print Summary
    Print("Total Deals in History is :", HistoryDealsTotal(), " !");
    Print("Total Deal Entry IN is : ", deal_in);
    Print("Total Deal Entry OUT is: ", deal_out);
    Print("Total Buy Deal is : ", buy);
    Print("Total Sell Deal is: ", sell);
  }

Dies ist ebenfalls ein einfaches Skript, das zeigt, wie man Details von Abschluss in unseren History-Einträgen erhält.

Ergebnis des Skripts für Abschluss-Details

Abb. 13 Ergebnis des Abschluss-History Skripts


Fazit

In diesem Beitrag konnten wir uns die wichtigsten Funktionen der Standard Handelsklasse-Libraries ansehen und haben gezeigt, wie einige dieser Funktionalitäten zum Schreiben von Expert Advisors eingesetzt werden können, die Positions-Veränderungen, Platzierung und Löschung von pending Orders sowie die Verifizierung von Margen vor der Platzierung eines Handels implementieren.

Wir haben zudem gezeigt, wie man mit diesen Funktionen Order- und Abschluss-Details erhält. Beim Schreiben unseres Expert Advisor in diesem Beitrag haben wir einige dieser Funktionen nicht benutzt. Doch je nachdem, welche Handelsstrategie Sie einsetzen wollen, können Sie mehr oder weniger der in diesem Beispiel verwendeten Funktionen, benutzen.

Es ist bestimmt keine schlechte Idee, den Abschnitt mit den Beschreibungen der verschiedenen Funktionen nochmals anzusehen und nachzuprüfen, wie Sie die Funktionen für Ihren Expert Advisor möglichst optimal einsetzen können.

Die Standard Klassen-Libraries sind dazu gedacht, das Leben sowohl für Händler als auch Entwickler leichter zu machen - also sollten Sie sie auch reichlich verwenden.

Übersetzt aus dem Englischen von MetaQuotes Software Corp.
Originalartikel: https://www.mql5.com/en/articles/138

Test-Performance der Berechnung von gleitenden Mittelwerten in MQL5 Test-Performance der Berechnung von gleitenden Mittelwerten in MQL5

Seit der Erstellung des ersten Moving-Average-Indikators ist eine Vielzahl von Indikatoren erschienen. Viele von ihnen nutzen ähnliche Glättungsmethoden, doch die Glättung der unterschiedlichen Algorithmen von gleitenden Mittelwerten wurde nie eingehend studiert. In diesem Beitrag betrachten wir Möglichkeiten zur Nutzung der gleitenden Mittelwerte in MQL5 und vergleichen ihre Performance.

Erstellen eines Expert Advisors, der mit verschiedenen Instrumenten handelt Erstellen eines Expert Advisors, der mit verschiedenen Instrumenten handelt

Das Konzept der Diversifizierung von Vermögenswerten auf Finanzmärkten ist ziemlich alt und war für Neueinsteiger im Handel immer interessant. In diesem Beitrag stellt der Verfasser eine äußerst einfache Vorgehensweise für die Erstellung eines Expert Advisors vor, der mit mehreren Währungen handelt, um diese Strömung von Handelsstrategien vorzustellen.

Verwendung der TesterWithdrawal() Funktion zur Nachahmung der Gewinnentnahme Verwendung der TesterWithdrawal() Funktion zur Nachahmung der Gewinnentnahme

Dieser Beitrag beschreibt die Verwendung der TesterWithDrawal() Funktion zur Abschätzung von Risiken in Handelssystemen, die mit der Entnahme eines gewissen Teils des Vermögens während der Operationen zu tun haben. Zusätzlich wird die Auswirkung dieser Funktion auf den Algorithmus zur Berechnung der Inanspruchnahme von Eigenkapital im Strategie-Tester beschrieben. Diese Funktion ist bei der Optimierung von Parametern Ihres Expert Advisors sehr sinnvoll.

Die optimale Berechnungsmethode für das Gesamtvolumen an Positions nach der festgelegten Magischen Zahl Die optimale Berechnungsmethode für das Gesamtvolumen an Positions nach der festgelegten Magischen Zahl

In diesem Beitrag geht es um das Problem der Berechnung des Gesamtvolumen an Positions nach festgelegtem Symbol und magischer Zahl. Die hier vorgestellte Methode verlangt nur den minimal notwendigen Teil der Abschluss-History, ermittelt den nächsten Zeitpunkt, als die Gesamtposition gleich Null war und führt Berechnungen an den jüngsten Abschlüssen aus. Des Weiteren wird hier ebenfalls die Arbeit mit globalen Variablen des Client-Terminals behandelt.