English Русский 中文 Español 日本語 Português
Womit soll man bei der Erstellung eines Handelsroboters für die Moskauer Börse MOEX anfangen

Womit soll man bei der Erstellung eines Handelsroboters für die Moskauer Börse MOEX anfangen

MetaTrader 5Beispiele | 1 August 2016, 10:38
857 0
MetaQuotes
MetaQuotes

Viele Trader auf der Moskauer Börse möchten ihre Handelsalgorithmen automatisieren, aber wissen nicht, womit anfangen. Die Sprache MQL5 bietet nicht nur den riesigen Satz der Handelsfunktionen an, sondern auch die einsatzbereiten Klassen, die die ersten Schritte in Algotrading maximal erleichtern. In diesem Artikel werden wir vorführen, welche fertigen Instrumenten für Algotrader auf der Moskauer Börse die Sprache der Handelsstrategien MQL5 anbietet.

Zwei Arten der Handelsanforderungen auf der Moskauer Börse MOEX

  Die Moskauer Börse MOEX unterstützt zwei Arten der Handelsanforderungen — markt- und limitierte Anforderungen.
  • Die Marktanfragen kommen in der Börse sofort an und werden zum Preise vom besten Angebot erfüllt. Für die Sendung dieser Anforderungen in MQL5 werden die Marktorder des Typs ORDER_TYPE_BUY und ORDER_TYPE_SELL verwendet.
  • Die limitierten Anfragen werden auf dem Server der Börse gespeichert und werden sofort erfüllt, wenn die passende entgegenkommende Anforderung erscheint. In der Sprache MQL5 entsprechen diesen Anfragen die Order des Typs ORDER_TYPE_BUY_LIMIT und ORDER_TYPE_SELL_LIMIT.

Die Marktanfragen gewährleistet die Vollziehung einer Transaktion (aber nicht immer), jedoch gewährleistet es nicht den Preis dabei. Es bedeutet, dass infolge der Handelsoperationen können Sie eine Transaktion zum Preise schließen, der wesentlich sich vom aktuellen Angebot unterscheidet. Zu gleicher Zeit gewährleistet die limitierten Anfragen den Preis, aber nicht das, dass eine Transaktion zu diesem Preise überhaupt abgeschlossen wird. Im Endeffekt können Sie außer dem Markt bleiben, bevor die Erfüllung der Anfrage überhaupt wird.

Alle übrigen Arten der Anforderungen, die den Tradern auf der Moskauer Börse angeboten werden, sind ein Teil jenes Programmkomplexes, durch den die Trader bis zur Börse zusammenwirken. Mit anderen Worten, sind die übrigen Anfragen algorithmische. Sie werden gespeichert und werden außer der Moskauer Börse bearbeitet, und werden dahin in Form von der Markt- oder limitierten Anfragen infolge der inneren Bearbeitung gesendet.

Der Plattform MetaTrader 5 bietet den Tradern die folgenden Arten der Handelsbefehle an, die man für den Handel auf der Moskauer Börse verwenden kann:

Identifikator Beschreibung Die Speicherung und Ausführung

ORDER_TYPE_BUY

Die Marktorder auf den Kauf

Es wird in die Börse in Form von der Marktanfragen auf den Kauf zu dem besten aktuellen Preis des Verkaufes gesendet

ORDER_TYPE_SELL

Die Marktorder auf den Verkauf

Es wird in die Börse in Form von der Marktanfrage auf den Verkauf zu dem besten aktuellen Preis des Kaufes gesendet

ORDER_TYPE_BUY_LIMIT

Die Pendig-Order Buy Limit

Es wird in die Börse in Form von der limitierenden Anfragen auf den Kauf gesendet und wird bei der Erscheinung des besten Angebots des Verkaufes zum gegebenen oder besseren Preis ausgeführt

ORDER_TYPE_SELL_LIMIT

Die Pendig-Order Sell Limit

Es wird in die Börse in Form von der limitierenden Anfragen auf den Kauf gesendet und wird bei der Erscheinung des besten Angebots des Verkaufes zum gegebenen oder besseren Preis ausgeführt

ORDER_TYPE_BUY_STOP

Die Pendig-Order Buy Stop

Die wird auf dem Server MetaTrader 5 gespeichert, und wird bei der Aktivierung in die Börse gesendet:
  • Für die Devisen- und Fondssektion — in Form von der Marktanfragen auf den Kauf
  • Für FORTS — in Form von der limitierenden Anfragen auf den Kauf zum schlechten Preis der Limits

ORDER_TYPE_SELL_STOP

Die Pendig-Order Sell Stop

Die wird auf dem Server MetaTrader 5 gespeichert, und wird bei der Aktivierung in die Börse gesendet:
  • Für die Devisen- und Fondssektion — in Form von der Marktanfrage auf den Verkauf
  • Für FORTS — in Form von der limitierenden Anfrage auf den Verkauf zum schlechten Preis der Limits

ORDER_TYPE_BUY_STOP_LIMIT

Die Pendig-Order BUY STOP LIMIT

Die wird auf dem Server MetaTrader 5 gespeichert, und wird bei der Aktivierung in die Börse in Form von der limitierten Anfrage auf einen Verkauf gesendet

ORDER_TYPE_SELL_STOP_LIMIT

Die Pendig-Order SELL STOP LIMIT

Die wird auf dem Server MetaTrader 5 gespeichert, und wird bei der Aktivierung in die Börse in Form von der limitierten Anfrage auf einen Verkauf gesendet

Für offene Positionen ermöglicht MetaTrader 5 Plattform, die Ebenen der Takeprofit und Stoploss anzugeben, die auf dem Handel-Server MetaTrader 5 gespeichert werden und werden automatisch ausgelöst, auch wenn sie mit dem Trading-Konto nicht verbunden sind:

  • Die Ebene TakeProfit gibt den Preis für die Schließung einer Position in einer günstigen Richtung an, und bei der Aktivierung wird die Limit-Anfrage zum Preis TakeProfit; an die Börse gesendet
  • Die Ebene StopLoss wird verwendet, um den Schutzstop in einer falschen Richtung zu realisieren, und bei der Aktivierung wird die Markt-Anfrage zum Preis StopLoss für die Aktien- und Währungs Sektionen an die Börse gesendet, für FORTS wird die Limit-Anfrage nach dem schlimmsten Preis der Korridor-Grenze gesendet.

Außerdem, der Plattform MetaTrader 5 ermöglicht die Ebene StopLoss/TakeProfit für Pending-Orders einzustellen und zu modifizieren, auch ermöglicht er die Ebene der Aktivierung aller Pending-Orders zu modifizieren.


Handelsoperationen in MetaTrader 5

MetaTrader 5 bietet einige Hauptarten der Handelsoperationen an, die Sie im Handels-Roboter benötigen können:

  1. Kauf/Verkauf zum aktuellen Preis;
  2. Das Setzen der Pending Orders in einem bestimmten Zustand zu kaufen/verkaufen;
  3. Modifizierung / Löschung eines Pending Orders;
  4. Schließung/Erweiterungen/Reduzierungen/Umdrehung der Position.

Alle Handelsoperationen in MQL5 werden mit der Funktion OrderSend() realisiert, die die Steuerung dem Programm in dem Moment zurückgibt, wenn die Handelsorder erfolgreich in die Moskauer Börse gesendet wurde. Der Status der Order in diesem Moment nimmt den Wert ORDER_STATE_PLACED an, und das bedeutet, dass Ihre Order erfolgreich ausgeführt wird (Der Status der Order ORDER_STATE_FILLED oder ORDER_STATE_PARTIAL). Das Endergebnis Ihres Handelsbefehls ist von der aktuellen Marktsituation abhängig, und die Order kann von der Börse aus verschiedenen Gründen abgelehnt werden(der Status ORDER_STATE_REJECTED).

Es gibt auch eine asynchrone Version dieser Funktion — OrderSendAsync(), die viel schneller als OrderSend() funktioniert, denn sie wartet nicht auf die Sendung des Befehls ins Handelssystem der Börse. Die Antwort auf diese Funktion wird sofort gesendet, sobald die Anfrage durch das Terminal MetaTrader 5 gesendet wird. Dies bedeutet, dass Ihre Handels Anfrage der Grundprüfung im Terminal bestanden hat, und wird nun zur Verarbeitung an den Handelsserver MetaTrader 5 gesendet. Wie lange die Bestellung Ihres Befehls in der Warteschlange der Börse dauern wird und wann er ausgeführt oder abgelehnt wird - ist das alles von der Belastung der Börse und der Geschwindigkeit Ihrer Internetverbindung abhängig.

Die ganze Vielfalt der Handelsoperationen beschreibt die Struktur von MqlTradeRequest, der die Beschreibung der Handels-Anfrage enthält. Von daher können die einzelnen Schwierigkeiten mit Handelsoperationen an der richtigen Ausfüllung der Struktur MqlTradeRequest und Verarbeitung der Ausführungsergebnisse der Anfrage liegen.

In Übereinstimmung mit den Regeln Ihres Handelssystems können Sie einen Kauf oder einen Verkauf zum Marktpreis (BUY oder SELL) zu machen, oder einen Pendig Order auf kaufen / verkaufen in einem Abstand vom aktuellen Marktpreis auszuführen:

  • BUY STOP, SELL STOP — Kauf oder Verkauf bei einem Eindringen dieser Ebene (schlechter als der aktuelle Preis). Die Order dieser Art werden auf dem Handel-Server MetaTrader 5 gespeichert und werden an die Moskauer Börse zum Punkt der Betriebsbedingungen-Aktivierung in Form eines Markt- (Aktien- und Währungs Abschnitt) oder eines Limit- (FORTS) Anfrage gesendet.
  • BUY LIMIT, SELL LIMIT — Kauf oder Verkauf bei einer Erreichung dieser Ebene (besser als der aktuelle Preis). Die Order dieser Art werden sofort an die Moskauer Börse in Form eines Limit Anfrage gesendet. Es sollte bemerkt werden, dass Sie auf der Moskauer Börse in einer Limit-Anfrage die Ebene innerhalb der Sprade, oder sogar von der anderen Seite der Sprade angeben können. So begrenzen wir den Schlupf bei einer Transaktion.
  • BUY STOP LIMIT, SELL STOP LIMIT — die Setzung der Order BUY LIMIT oder SELL LIMIT bei der Erreichung dieses Preises. Die Order dieser Art werden auf dem Handel-Server MetaTrader 5 gespeichert und werden an die Moskauer Börse zum Punkt der Betriebsbedingungen-Aktivierung in Form einer Limit-Anfrage gesendet. Die Ebene der Eröffnung einer solchen Limit-Anfrage.

Das Verwendungsprinzip der Orders KBUY STOP, SELL STOP и BUY LIMIT, SELL LIMIT, sowie Möglichkeiten, sie direkt aus dem Preis-Glas zu setzen, sind im Bild unten dargestellt.


Darüber hinaus müssen Sie möglicherweise Pendig Orders modifizieren oder löschen. Dies wird mit Hilfe von der Funktion OrderSend()/OrderSendAsync()gemacht. Die Arbeit mit einer offenen Position ist auch nicht schwierig, denn es wird in der Folge der Ausführung dieser Handelsoperationen stattfinden.

In diesem Artikel zeigen wir Ihnen, wie einfach und leicht Kauf und Verkauf in MQL5 programmiert werden können, wir zeigen auch, wie man mit einem Trading-Konto und Zeicheneigenschaften arbeiten soll. Dabei wird uns Handelsklassen der Standardbibliothek helfen.

Der Handel an der Börse mit Hilfe von Robotern - ist einfach

Die MQL5 Sprache unterstützt alle Handelsmöglichkeiten des MetaTrader 5-Plattforms: Es gibt viele Handelsfunktionen für die Arbeit mit Orders, mit Positionen und Handels Anfragen. Es spielt keine Rolle, in welchem Markt Sie handeln - Futures, Aktien, Optionen usw.

Durch MQL5 Mittel können Sie eine Handel-Anfrage erstellen und sie an den Server über der Funktion OrderSend() oder OrderSendAsync() senden, das Ergebnis ihrer Ausführung erhalten, Handelshistorie schauen, die Auftragsspezifikation für das Werkzeug lernen, das Handels-Ereignis verarbeiten und viele andere notwendige Informationen erhalten.

Für Entwickler der Trading-Roboter ist es wichtig, eine wichtige Tatsache zu verstehen: jede Handelsoperation, egal ob es eine Erröfnung einer Position ist, Stoploss oder Takeprofit setzen, oder Schließung einer Position ist - besteht immer aus einer Reihe von Transaktionen, die auf dem Server MetaTrader 5 und auf der Moskauer Börse durchgeführt werden. Um dies zu sehen, wie dies geschieht, können Sie auf Ihrem Konto den Berater TradeTransactionListener.mql5 anmachen, der einfach das Ereignis TradeTransaction hört und zeigt eine kurze Zusammenfassung von ihnen:

//+------------------------------------------------------------------+
//|                                     TradeTransactionListener.mq5 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   PrintFormat("LAST PING=%.f ms",
               TerminalInfoInteger(TERMINAL_PING_LAST)/1000.);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//---
   static int counter=0;   // счетчик вызовов OnTradeTransaction()
   static uint lasttime=0; // время последнего вызова OnTradeTransaction()
//---
   uint time=GetTickCount();
//--- Wenn die letzte Transaktion länger als 1 Sekunde war
   if(time-lasttime>1000)
     {
      counter=0; // Bedeutet es, dass es eine neue Handels-Operation ist und Sie können den Zähler zurücksetzen
      if(IS_DEBUG_MODE)
         Print(" Eine neue Handelsoperation");
     }
   lasttime=time;
   counter++;
   Print(counter,". ",__FUNCTION__);
//--- Das Ergebnis der Handels-Anfrage
   ulong            lastOrderID   =trans.order;
   ENUM_ORDER_TYPE  lastOrderType =trans.order_type;
   ENUM_ORDER_STATE lastOrderState=trans.order_state;
//--- имя символа, по которому произошла транзакция
   string trans_symbol=trans.symbol;
//--- тип транзакции
   ENUM_TRADE_TRANSACTION_TYPE  trans_type=trans.type;
   switch(trans.type)
     {
      case  TRADE_TRANSACTION_POSITION:   // Änderung der Position
        {
         ulong pos_ID=trans.position;
         PrintFormat("MqlTradeTransaction: Position #%I64u %s modified: SL=%.5f TP=%.5f",
                     pos_ID,trans_symbol,trans.price_sl,trans.price_tp);
        }
      break;
      case TRADE_TRANSACTION_REQUEST:     //Die Sendung einer Handelsanfrage
         PrintFormat("MqlTradeTransaction: TRADE_TRANSACTION_REQUEST");
         break;
      case TRADE_TRANSACTION_DEAL_ADD:    // Das Hinzufügen der Transaktion
        {
         ulong          lastDealID   =trans.deal;
         ENUM_DEAL_TYPE lastDealType =trans.deal_type;
         double        lastDealVolume=trans.volume;
         //--- Der Identifikator der Transaktion im externen System - ist das Ticket, das der Moskauer Börse zugewiesen wird
         string Exchange_ticket="";
         if(HistoryDealSelect(lastDealID))
            Exchange_ticket=HistoryDealGetString(lastDealID,DEAL_EXTERNAL_ID);
         if(Exchange_ticket!="")
            Exchange_ticket=StringFormat("(MOEX deal=%s)",Exchange_ticket);

         PrintFormat("MqlTradeTransaction: %s deal #%I64u %s %s %.2f lot   %s",EnumToString(trans_type),
                     lastDealID,EnumToString(lastDealType),trans_symbol,lastDealVolume,Exchange_ticket);
        }
      break;
      case TRADE_TRANSACTION_HISTORY_ADD: // Das Hinzufügen des Orders zur History
        {
         //--- Der Identifikator des Orders im externen System - ist das Ticket, das der Moskauer Börse zugewiesen wird
         string Exchange_ticket="";
         if(lastOrderState==ORDER_STATE_FILLED)
           {
            if(HistoryOrderSelect(lastOrderID))
               Exchange_ticket=HistoryOrderGetString(lastOrderID,ORDER_EXTERNAL_ID);
            if(Exchange_ticket!="")
               Exchange_ticket=StringFormat("(MOEX ticket=%s)",Exchange_ticket);
           }
         PrintFormat("MqlTradeTransaction: %s order #%I64u %s %s %s   %s",EnumToString(trans_type),
                     lastOrderID,EnumToString(lastOrderType),trans_symbol,EnumToString(lastOrderState),Exchange_ticket);
        }
      break;
      default: // andere Transaktionen  
        {
         //--- Der Identifikator des Orders im externen System - ist das Ticket, das der Moskauer Börse zugewiesen wird
         string Exchange_ticket="";
         if(lastOrderState==ORDER_STATE_PLACED)
           {
            if(OrderSelect(lastOrderID))
               Exchange_ticket=OrderGetString(ORDER_EXTERNAL_ID);
            if(Exchange_ticket!="")
               Exchange_ticket=StringFormat("MOEX ticket=%s",Exchange_ticket);
           }
         PrintFormat("MqlTradeTransaction: %s order #%I64u %s %s   %s",EnumToString(trans_type),
                     lastOrderID,EnumToString(lastOrderType),EnumToString(lastOrderState),Exchange_ticket);
        }
      break;
     }
//--- Das Ticket der Order    
   ulong orderID_result=result.order;
   string retcode_result=GetRetcodeID(result.retcode);
   if(orderID_result!=0)
      PrintFormat("MqlTradeResult: order #%d retcode=%s ",orderID_result,retcode_result);
//---   
  }
//+------------------------------------------------------------------+
//| übersetzt die Zahl-Code der Antwortungen in Zeile-Mnemocode             |
//+------------------------------------------------------------------+
string GetRetcodeID(int retcode)
  {
   switch(retcode)
     {
      case 10004: return("TRADE_RETCODE_REQUOTE");             break;
      case 10006: return("TRADE_RETCODE_REJECT");              break;
      case 10007: return("TRADE_RETCODE_CANCEL");              break;
      case 10008: return("TRADE_RETCODE_PLACED");              break;
      case 10009: return("TRADE_RETCODE_DONE");                break;
      case 10010: return("TRADE_RETCODE_DONE_PARTIAL");        break;
      case 10011: return("TRADE_RETCODE_ERROR");               break;
      case 10012: return("TRADE_RETCODE_TIMEOUT");             break;
      case 10013: return("TRADE_RETCODE_INVALID");             break;
      case 10014: return("TRADE_RETCODE_INVALID_VOLUME");      break;
      case 10015: return("TRADE_RETCODE_INVALID_PRICE");       break;
      case 10016: return("TRADE_RETCODE_INVALID_STOPS");       break;
      case 10017: return("TRADE_RETCODE_TRADE_DISABLED");      break;
      case 10018: return("TRADE_RETCODE_MARKET_CLOSED");       break;
      case 10019: return("TRADE_RETCODE_NO_MONEY");            break;
      case 10020: return("TRADE_RETCODE_PRICE_CHANGED");       break;
      case 10021: return("TRADE_RETCODE_PRICE_OFF");           break;
      case 10022: return("TRADE_RETCODE_INVALID_EXPIRATION");  break;
      case 10023: return("TRADE_RETCODE_ORDER_CHANGED");       break;
      case 10024: return("TRADE_RETCODE_TOO_MANY_REQUESTS");   break;
      case 10025: return("TRADE_RETCODE_NO_CHANGES");          break;
      case 10026: return("TRADE_RETCODE_SERVER_DISABLES_AT");  break;
      case 10027: return("TRADE_RETCODE_CLIENT_DISABLES_AT");  break;
      case 10028: return("TRADE_RETCODE_LOCKED");              break;
      case 10029: return("TRADE_RETCODE_FROZEN");              break;
      case 10030: return("TRADE_RETCODE_INVALID_FILL");        break;
      case 10031: return("TRADE_RETCODE_CONNECTION");          break;
      case 10032: return("TRADE_RETCODE_ONLY_REAL");           break;
      case 10033: return("TRADE_RETCODE_LIMIT_ORDERS");        break;
      case 10034: return("TRADE_RETCODE_LIMIT_VOLUME");        break;
      case 10035: return("TRADE_RETCODE_INVALID_ORDER");       break;
      case 10036: return("TRADE_RETCODE_POSITION_CLOSED");     break;
      default:
         return("TRADE_RETCODE_UNKNOWN="+IntegerToString(retcode));
         break;
     }
//---
  }
//+------------------------------------------------------------------+


Das Beispiel der Arbeit dieses "Zuhörers":

2016.06.09 14:51:19.763 TradeTransactionListener (Si-6.16,M15)  LAST PING=14 ms
Покупка
2016.06.09 14:51:24.856 TradeTransactionListener (Si-6.16,M15)  1. OnTradeTransaction
2016.06.09 14:51:24.856 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_ADD order #49118594 ORDER_TYPE_BUY ORDER_STATE_STARTED   
2016.06.09 14:51:24.859 TradeTransactionListener (Si-6.16,M15)  2. OnTradeTransaction
2016.06.09 14:51:24.859 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_REQUEST
2016.06.09 14:51:24.859 TradeTransactionListener (Si-6.16,M15)  MqlTradeResult: order #49118594 retcode=TRADE_RETCODE_PLACED 
2016.06.09 14:51:24.859 TradeTransactionListener (Si-6.16,M15)  3. OnTradeTransaction
2016.06.09 14:51:24.859 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_UPDATE order #49118594 ORDER_TYPE_BUY ORDER_STATE_REQUEST_ADD   
2016.06.09 14:51:24.881 TradeTransactionListener (Si-6.16,M15)  4. OnTradeTransaction
2016.06.09 14:51:24.881 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_UPDATE order #49118594 ORDER_TYPE_BUY ORDER_STATE_PLACED   
2016.06.09 14:51:24.881 TradeTransactionListener (Si-6.16,M15)  5. OnTradeTransaction
2016.06.09 14:51:24.881 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_DELETE order #49118594 ORDER_TYPE_BUY ORDER_STATE_PLACED   
2016.06.09 14:51:24.884 TradeTransactionListener (Si-6.16,M15)  6. OnTradeTransaction
2016.06.09 14:51:24.884 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_HISTORY_ADD order #49118594 ORDER_TYPE_BUY Si-6.16 ORDER_STATE_FILLED   (MOEX ticket=3377179723)
2016.06.09 14:51:24.884 TradeTransactionListener (Si-6.16,M15)  7. OnTradeTransaction
2016.06.09 14:51:24.885 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_DEAL_ADD deal #6945344 DEAL_TYPE_BUY Si-6.16 1.00 lot   (MOEX deal=185290434)
Установка SL/TP
2016.06.09 14:51:50.872 TradeTransactionListener (Si-6.16,M15)  1. OnTradeTransaction
2016.06.09 14:51:50.872 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_REQUEST
2016.06.09 14:51:50.872 TradeTransactionListener (Si-6.16,M15)  2. OnTradeTransaction
2016.06.09 14:51:50.872 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: Position  #0 Si-6.16 modified: SL=62000.00000 TP=67000.00000
Закрытие позиции (продажа)
2016.06.09 14:52:24.063 TradeTransactionListener (Si-6.16,M15)  1. OnTradeTransaction
2016.06.09 14:52:24.063 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_ADD order #49118750 ORDER_TYPE_SELL ORDER_STATE_STARTED   
2016.06.09 14:52:24.067 TradeTransactionListener (Si-6.16,M15)  2. OnTradeTransaction
2016.06.09 14:52:24.067 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_REQUEST
2016.06.09 14:52:24.067 TradeTransactionListener (Si-6.16,M15)  MqlTradeResult: order #49118750 retcode=TRADE_RETCODE_PLACED 
2016.06.09 14:52:24.067 TradeTransactionListener (Si-6.16,M15)  3. OnTradeTransaction
2016.06.09 14:52:24.067 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_UPDATE order #49118750 ORDER_TYPE_SELL ORDER_STATE_REQUEST_ADD   
2016.06.09 14:52:24.071 TradeTransactionListener (Si-6.16,M15)  4. OnTradeTransaction
2016.06.09 14:52:24.071 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_UPDATE order #49118750 ORDER_TYPE_SELL ORDER_STATE_PLACED   
2016.06.09 14:52:24.073 TradeTransactionListener (Si-6.16,M15)  5. OnTradeTransaction
2016.06.09 14:52:24.073 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_DEAL_ADD deal #6945378 DEAL_TYPE_SELL Si-6.16 1.00 lot   (MOEX deal=185290646)
2016.06.09 14:52:24.075 TradeTransactionListener (Si-6.16,M15)  6. OnTradeTransaction
2016.06.09 14:52:24.075 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_ORDER_DELETE order #49118750 ORDER_TYPE_SELL ORDER_STATE_PLACED   
2016.06.09 14:52:24.077 TradeTransactionListener (Si-6.16,M15)  7. OnTradeTransaction
2016.06.09 14:52:24.077 TradeTransactionListener (Si-6.16,M15)  MqlTradeTransaction: TRADE_TRANSACTION_HISTORY_ADD order #49118750 ORDER_TYPE_SELL Si-6.16 ORDER_STATE_FILLED   (MOEX ticket=3377182821)

Jetzt ist es die Zeit, die Beispiele mit Quellcoden zu betrachten.


Die Arbeit mit dem Handelskonto

Zunächst bei dem Start des Trading Roboters ist es notwendig, Informationen über das Trading-Konto zu erhalten, auf dem sie handeln werden.

Für die Arbeit mit dem Konto gibt es die Klasse CAccountInfo, die speziell für diese Zwecke entwickelt wurde. Wir fügen zu unserem Verbindungscode die Datei AccountInfo.mqh hinzu und deklarieren eine Variable der Klasse account:

#include <Trade\AccountInfo.mqh>
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Objekt für die Arbeit mit einem Konto
CAccountInfo account;
//--- erhalten wir die Nummer des Kontos, auf dem der Berater läuft
   long login=account.Login();
   Print("Login=",login);
//--- Zeigen wir die Währung des Kontos    
   Print("die Währung des Kontos: ",account.Currency());   
//--- Zeigen wir die Balance und den aktuellen Gewinn am Konto
   Print("Balance=",account.Balance(),"  Profit=",account.Profit(),"   Equity=",account.Equity());
//--- Zeigen wir den Typ des Kontos    
   Print("der Typ des Kontos: ",account.TradeModeDescription());
//--- Finden wir heraus, ob es möglich ist, auf diesem Konto überhaupt zu handeln 
   if(account.TradeAllowed())
      Print("Das Handeln auf dem Konto ist erlaubt");
   else
      Print("Der Handel ist auf dem Konto gesperrt: vielleicht wurde der Eingang nach dem Invest-Kennwort durchgeführt ");
//--- Der Berechnungsmodus der Marge
   Print("Der Berechnungsmodus der Marge: ",account.MarginModeDescription());
//--- Finden wir heraus, ob es möglich ist, auf diesem Konto mit einem Experten zu handeln
   if(account.TradeExpert())
      Print("Das automatisierte Handeln auf dem Konto ist erlaubt");
   else
      Print("Das automatisierte Handeln mit Experten und Skripts");
//--- Die maximale Anzahl der Orders ist angegeben oder nicht 
   int orders_limit=account.LimitOrders();
   if(orders_limit!=0)Print("Die maximale Anzahl der aktiven Pending Orders ",orders_limit);
//--- Zeigen wir den Company-Namen und Server-Namen
   Print(account.Company(),": server ",account.Server());
   Print(__FUNCTION__,"  completed"); //---   
  }

Wie es aus dem aufgeführten Kode sichtbar ist, mit Hilfe der Variable account in der Funktion OnInit() kann man viele nützliche Information bekommen. Sie können diesen Code zu Ihrem Experten hinzufügen, und es wird Ihnen viel einfacher, die Logs bei der Analyse seiner Arbeit zu ordnen.

Das Ergebnis des Skripts-Starts ist auf dem Bild vorgeführt.



Das Erhalten der Eigenschaften des Finanzinstruments

Wir haben die Information über die Rechnung bekommen, aber für die Vollziehung der Handelsoperationen muss man die Eigenschaften des Aktiven wissen, nach dem wir handeln wollen. Dafür ist es noch eine bequeme Klasse CSymbolInfo mit der großen Menge der Methoden vorgesehen. Wir werden in dem Beispiel nur einen kleinen Teil von ihnen aufführen.

#include<Trade\SymbolInfo.mqh>
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Objekt für das Erhalten der Eigenschaften des Symbols
CSymbolInfo symbol_info;
//--- geben wir den Namen des Symbols ein, für den wir die Informationen bekommen werden
   symbol_info.Name(_Symbol);
//--- - bekommen wir die vorübergehenden Notierungen und zeigen wir sie
   symbol_info.RefreshRates();
   Print(symbol_info.Name()," (",symbol_info.Description(),")",
         "  Bid=",symbol_info.Bid(),"   Ask=",symbol_info.Ask());
//--- bekommen wir die Anzahl der Zeichen nach dem Komma und die Größe des Punktes 
   Print("Digits=",symbol_info.Digits(),
         ", Point=",DoubleToString(symbol_info.Point(),symbol_info.Digits()));
//--- Fragen wir die Art der Erfüllung der Orders an, ob es keine Beschränkungen gibt
   Print("Beschränkungen für die Handelsoperationen: ",EnumToString(symbol_info.TradeMode()),
         " (",symbol_info.TradeModeDescription(),")");
//--- wir werden den Modus des Abschlusses der Transaktionen aufklären
   Print("Der Ausführungsmodus der Transaktionen: ",EnumToString(symbol_info.TradeExecution()),
         " (",symbol_info.TradeExecutionDescription(),")");
//--- wir werden die Berechnungsart des Wertes der Aufträge aufklären
   Print("Die Berechnung des Wertes des Auftrags: ",EnumToString(symbol_info.TradeCalcMode()),
         " (",symbol_info.TradeCalcModeDescription(),")");
//--- Die Kontraktgröße
   Print("Die Standardkontraktgröße: ",symbol_info.ContractSize());
//--- Die Größe der anfangs Marge für einen Kontrakt
   Print("Die anfangs Marge für einen Standardkontrakt: ",symbol_info.MarginInitial()," ",symbol_info.CurrencyBase());
//--- die minimale, maximale Große des Volumens in den Handelsoperationen
   Print("Volume info: LotsMin=",symbol_info.LotsMin(),"  LotsMax=",symbol_info.LotsMax(),
         "  LotsStep=",symbol_info.LotsStep());
//--- 
   Print(__FUNCTION__,"  completed");   
  }

Und am Bild sind die Eigenschaften des Symbols Si-6.16 aus der Sektion des eiligen Marktes der Moskauer Börse (FORTS) gezeigt. Jetzt sind Sie fertig, unmittelbar zum Handel zugehen.



Die Programmierung der Handelsoperationen

Für die Sendung der Handelsbefehle in der Sprache MQL5 existiert zwei Funktionen — OrderSend() und OrderSendAsync(). In Wirklichkeit sind es zwei Realisationen einer Funktion. Wenn OrderSend() die Handelsanfrage sendet und wartet auf das Ergebnis seiner Ausführung, so schießt einfach die asynchrone OrderSendAsync() eine Anfrage und erlaubt dem Programm weiter funktionieren, ohne Erhaltung der Antwort. So wird es echt einfach in MQL5 handeln, es reicht nur, eine Funktion für alle Handelsoperationen zu verwenden

Beide Funktionen erhalten die Struktur MqlTradeRequest als erster Parameter, der über dutzende Felder enthält. Der Inhalt der notwendigen Felder hängt vom Typ der Handelsoperation ab, deshalb braucht man nicht alle Felder auszufüllen. Falls es einen falschen Wert gibt oder die Abwesenheit des notwendigen Feldes, wird die Anfrage die Überprüfung im Terminal nicht bestehen und wird an den Server gesendet. Dabei 5 Felder fordern den korrekten Wert aus vorbestimmten Aufzählungen zu geben.

So eine große Menge der Felder der Handels-Anfrage wurde dadurch verursacht, denn es gibt die Notwendigkeit für die Beschreibung der Eigenschaften des Orders, die sich abhängig von der Ausführungpolitik, Ablaufzeit, und anderen Parametern ändern. Sie brauchen nicht alle diese Kleinigkeiten zu lernen, verwenden Sie einfach die Klasse CTrade. So kann ungefähr die Verwendung dieser Klasse in unserer Handelsrobot aussehen:

#include<Trade\Trade.mqh>
//--- ein Objekt für die Durchführung der Handelsoperationen
CTrade  trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Geben wir MagicNumber ein, um die eigene Orders zu identifizieren 
   int MagicNumber=123456;
   trade.SetExpertMagicNumber(MagicNumber);
//--- Setzen wir die mögliche Schlupf in Punkten beim Kauf/Verkauf ein 
   int deviation=10;
   trade.SetDeviationInPoints(deviation);
//--- Der Erfüllungsmodus des Orders, man muss den Modus verwenden, der vom Server
   trade.SetTypeFilling(ORDER_FILLING_RETURN);
//--- den Log-Modus erlaubt: besser soll diese Methode überhaupt nicht verursacht werden, die Klasse setzt selber den optimalen Modus
   trade.LogLevel(1); 
//--- welche Funktion für den Handel verwendet werden soll: true - OrderSendAsync(), false - OrderSend()
   trade.SetAsyncMode(true);
//---
   return(0);
  }

Für den Handel auf der Börse, wird es in der Regel der Ausführungsmodus ORDER_FILLING_RETURN verwendet. Der Auszug:

Dieser Modus wird nur in Modus "Ausführung nach dem Markt" und "Börse Ausführung": für den Markt (ORDER_TYPE_BUY und ORDER_TYPE_SELL), Limit und Stop-Limit (ORDER_TYPE_BUY_LIMIT, ORDER_TYPE_SELL_LIMIT, ORDER_TYPE_BUY_STOP_LIMIT und ORDER_TYPE_SELL_STOP_LIMIT). Falls es teilweise ausgeführt wird, wird der Markt- oder Limit-Order mit den restlichen Volumen nicht ausgesetzt, sondern bleibt weiter gültig.

Für Order ORDER_TYPE_BUY_STOP_LIMIT und ORDER_TYPE_SELL_STOP_LIMIT bei der Aktivierung wird der entsprechende Limit-Order ORDER_TYPE_BUY_LIMIT/ORDER_TYPE_SELL_LIMIT mit dem Ausführungstyp ORDER_FILLING_RETURN erstellt.

Schauen wir mal, wie CTrade bei Handelsoperationen hilft.

Kauf/Verkauf zum aktuellen Preis

Oft muss man in Handelsstrategien Kauf/Verkauf zum aktuellen Preis gerade jetzt durchführen. CTrade kennt die Situation und fragt nur den notwendigen Volumen der Handelsoperation nach. Die restlichen Parameter - der Erröffnugspreis und Symbol-Name, Stoploss und Takeprofit-Ebene, Kommentaren zum Ordner — kann man nicht angeben.

//--- 1. Das Beispiel des Kaufes nach dem aktuellen Symbol
   if(!trade.Buy(1))
     {
      //--- berichten wir über den Pech
      Print("Die Methode Buy() hat Pech. Der zurückgelieferte Code=",trade.ResultRetcode(),
            ". Die Beschreibung des Codes: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Die Methode Buy() wurde erfolgreich ausgeführt. Der zurückgelieferte Code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Standartmäßig, wenn der Werkzeug-Name nicht angegeben ist, CTrade verwendet den Symbol-Namen, auf dessen Chart er gestartet ist. Das ist sehr bequem für einfache Strategien. Für den Roboter, der direkt auf eigenen Werkzeugen handelt,  müssen Sie jedes Mal das Symbol klar angeben, nach dem die Handelsoperation durchgeführt wird.

//--- 2. Das Beispiel des Kaufes nach dem gegebenen Symbol
   if(!trade.Buy(1,"Si-6.16"))
     {
      //--- berichten wir über den Pech
      Print("Die Methode Buy() hat Pech. Der zurückgelieferte Code=",trade.ResultRetcode(),
            ". Die Beschreibung des Codes: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Die Methode Buy() wurde erfolgreich ausgeführt. Der zurückgelieferte Code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Man kann alle Parameter des Orders angeben: die Ebene Stop Loss/Take Profit, Kommentaren und der Erröffnugspreis.

//--- 3. Das Beispiel des Kaufes nach dem gegebenen Symbol mit gegebenen SL und TP
   double volume=1;           // Geben wir den Volumen der Handelsoperation
   string symbol="Si-6.16";   // Geben wir das Symbol, auf dem die Operation durchgeführt wird
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // Die Anzahl der Zeichen nach dem Komma
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // Punkt
   double bid=SymbolInfoDouble(symbol,SYMBOL_BID);             // Der aktuelle Preis für die Schließung LONG
   double SL=bid-100*point;                                    // unnormalisierter Wert SL
   SL=NormalizeDouble(SL,digits);                              // normalisieren Stop Loss
   double TP=bid+100*point;                                    // unnormalisierter Wert TP
   TP=NormalizeDouble(TP,digits);                              // normalisieren Take Profit
//--- bekommen wir den Eröffnungspreis für Long-Positionen
   double open_price=SymbolInfoDouble(symbol,SYMBOL_ASK);
   string comment=StringFormat("Buy %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(open_price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
   if(!trade.Buy(volume,symbol,open_price,SL,TP,comment))
     {
      //--- berichten wir über den Pech
      Print("Die Methode Buy() hat Pech. Der zurückgelieferte Code=",trade.ResultRetcode(),
            ". Die Beschreibung des Codes: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Die Methode Buy() wurde erfolgreich ausgeführt. Der zurückgelieferte Code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Erinnern Sie sich, MagicNumber und die mögliche Schlupf haben wir bei der Initialisierung des CTrade gegeben, deshalb werden sie nicht erforderlich. Zwar können sie auch direkt vor jeder Handelsoperation gegeben werden, wenn es erforderlich ist.

Die Setzung des Limit-Orders

Für die Sendung des Limit-Orders wird die entsprechende Methode der Klasse BuyLimit() oder SellLimit() verwendet. Für die Mehrheit der Fälle kann eine kleinere Variante passen, wenn nur der Erröffnungspreis und der Volumen gegeben werden. Der Erröffnungspreis für BuyLimit muss weniger sein, als aktueller Preis, und für SellLimit höher. Das heißt, diese Order wird für den Eingang in den Markt über einen besseren Preis verwendet, in Strategien mit der Rücksicht auf einen Sprung von Unterstützungslevel. Dabei wird das Symbol verwendet, auf dem der Experte gestartet ist:

//--- 1. Das Beispiel der Setzung des Pending-Orders BuyLimit
   string symbol="Si-6.16";                                    // Geben wir das Symbol, auf dem die Order gesetzt wird
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // Die Anzahl der Zeichen nach dem Komma
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // Punkt
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // Der aktuelle Preis für den Kauf
   double price=ask-100*point;                                 // unnormalisierter Eröffnungspreis
   price=NormalizeDouble(price,digits);                        // normalisieren den Eröffnungspreis
//--- alles fertig, senden wir zum Server die Pendig-Order Buy Limit
   if(!trade.BuyLimit(1,price))
     {
      //--- berichten wir über den Pech
      Print("Die Methode BuyLimit()  hat Pech. Der zurückgelieferte Code=",trade.ResultRetcode(),
            ". Die Beschreibung des Codes: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Die Methode BuyLimit() wurde erfolgreich ausgeführt. Der zurückgelieferte Code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Man kann die gründliche Variante mit der Gabe aller Parameter verwenden: die Ebene SL/TP, die Ablaufzeit, den Werkzeug-Name, und Kommentaren zur Order.

//--- 2. Das Beispiel der Setzung des Pending-Orders BuyLimit mit allen Parametern
   double volume=1;
   string symbol="Si-6.16";                                    // Geben wir das Symbol, auf dem die Order gesetzt wird
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // Die Anzahl der Zeichen nach dem Komma
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // Punkt
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // Der aktuelle Preis für den Kauf
   double price=ask-100*point;                                 // unnormalisierter Eröffnungspreis
   price=NormalizeDouble(price,digits);                        // normalisieren den Eröffnungspreis
   int SL_pips=100;                                            // Stop Loss in Punkten
   int TP_pips=100;                                            // Take Profit in Punkten
   double SL=price-SL_pips*point;                              // unnormalisierter Wert SL
   SL=NormalizeDouble(SL,digits);                              // normalisieren Stop Loss
   double TP=price+TP_pips*point;                              // unnormalisierter Wert TP
   TP=NormalizeDouble(TP,digits);                              // normalisieren Take Profit
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);
   string comment=StringFormat("Buy Limit %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
//--- alles fertig, senden wir zum Server die Pendig-Order Buy Limit
   if(!trade.BuyLimit(volume,price,symbol,SL,TP,ORDER_TIME_DAY,expiration,comment))
     {
      //--- berichten wir über den Pech
      Print("Die Methode BuyLimit()  hat Pech. Der zurückgelieferte Code=",trade.ResultRetcode(),
            ". Die Beschreibung des Codes: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Die Methode BuyLimit() wurde erfolgreich ausgeführt. Der zurückgelieferte Code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

In der zweiten Variante muss man richtig die Ebene SL und TP geben. Vergessen Sie nicht, dass die Ebene Take Profit für den Kauf höher als der Eröffnungspreis sein muss, und die Ebene Stop Loss — weniger als der Eröffnungspreis. Für Orders SellLimit ist es umgedreht. Sie können leicht über Ihren Fehler beim Test des Experten auf historische Daten erfahren, die Klasse CTrade zeigt in solchen Fällen automatisch die Meldung (wenn Sie selber die Funktion LogLevel nicht aufgerufen haben).

Die Setzung des Stop-Orders

Für die Sendung des Stop-Orders werden die ähnlichen Methode BuyStop() und SellStop() verwendet. Der Erröffnungspreis für Buy Stop muss weniger sein, als aktueller Preis, und für SellStop höher. Die Stop-Orders werden in Strategien verwendet, die beim Bruch einer Widerstandslinie eingehen, auch für die Beschränkung des Verlustes. einfache Variante:

//--- 1. Das Beispiel der Setzung des Pending-Orders Buy Stop
   string symbol="RTS-6.16";    // Geben wir das Symbol, auf dem die Order gesetzt wird
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // Die Anzahl der Zeichen nach dem Komma
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // Punkt
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // Der aktuelle Preis für den Kauf
   double price=ask+100*point;                                 // unnormalisierter Eröffnungspreis
   price=NormalizeDouble(price,digits);                        // normalisieren den Eröffnungspreis
//--- alles fertig, senden wir zum Server die Pendig-Order Buy Stop 
   if(!trade.BuyStop(1,price))
     {
      //--- berichten wir über den Pech
      Print("Die Methode BuyStop() hat Pech. Der zurückgelieferte Code=",trade.ResultRetcode(),
            ". Die Beschreibung des Codes: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Die Methode BuyStop() wurde erfolgreich ausgeführt. Der zurückgelieferte Code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Und gründlicher, wenn möglichst viel Parameter für die Pending-Order BuyStop gegeben werden muss:

//--- 2. Das Beispiel der Setzung der Pending-Order Buy Stop mit allen Parametern
   double volume=1;
   string symbol="RTS-6.16";    // Geben wir das Symbol, auf dem die Order gesetzt wird
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // Die Anzahl der Zeichen nach dem Komma
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // Punkt
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // Der aktuelle Preis für den Kauf
   double price=ask+100*point;                                 // unnormalisierter Eröffnungspreis
   price=NormalizeDouble(price,digits);                        // normalisieren den Eröffnungspreis
   int SL_pips=100;                                            // Stop Loss in Punkten
   int TP_pips=100;                                            // Take Profit in Punkten
   double SL=price-SL_pips*point;                              // unnormalisierter Wert SL
   SL=NormalizeDouble(SL,digits);                              // normalisieren Stop Loss
   double TP=price+TP_pips*point;                              // unnormalisierter Wert TP
   TP=NormalizeDouble(TP,digits);                              // normalisieren Take Profit
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);
   string comment=StringFormat("Buy Stop %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
//--- alles fertig, senden wir zum Server die Pendig-Order Buy Stop 
   if(!trade.BuyStop(volume,price,symbol,SL,TP,ORDER_TIME_DAY,expiration,comment))
     {
      //--- berichten wir über den Pech
      Print("Die Methode BuyStop() hat Pech. Der zurückgelieferte Code=",trade.ResultRetcode(),
            ". Die Beschreibung des Codes: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Die Methode BuyStop() wurde erfolgreich ausgeführt. Der zurückgelieferte Code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Für die Sendung der SellStop wird die entsprechende Methode der Klasse CTrade verwendet, wichtig ist — richtig den Preis zu geben.

Arbeit mit der Position

Sie können statt der Verwendung der Methoden Buy() und Sell() die Methoden für die Eröffnung de Position verwenden. Allerdings in diesem Fall muss man mehr Details geben:

//--- die Anzahl der Zeichen nach dem Komma
   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
//--- Der Wert des Punktes
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
//--- Erhalten wir den Kauf-Preis
   double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
//--- Berechnen wir und normalisiern die Ebene SL und TP
   double SL=NormalizeDouble(price-100*point,digits);
   double TP=NormalizeDouble(price+100*point,digits);
//--- Füllen wir Kommentaren
   string comment="Buy "+_Symbol+" 1 at "+DoubleToString(price,digits);
//--- alles fertig, versuchen wir, die Position auf den Kauf zu öffnen
   if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,1,price,SL,TP,comment))
     {
      //--- berichten wir über den Pech
      Print("Метод PositionOpen() потерпел неудачу. Der zurückgelieferte Code=",trade.ResultRetcode(),
            ". Die Beschreibung des Codes: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Die Methode PositionOpen() wurde erfolgreich ausgeführt. Der zurückgelieferte Code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Für die Schließung der Position ist es genug, den Namen des Werkzeugs zu geben, den Rest macht die Klasse CTrade selber.

//--- Schließen wir die Position nach dem aktuellen Symbol
   if(!trade.PositionClose(_Symbol))
     {
      //--- berichten wir über den Pech
      Print("Die Methode PositionClose() hat Pech. Der zurückgelieferte Code=",trade.ResultRetcode(),
            ". Die Beschreibung des Codes: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Die Methode PositionClose() wurde erfolgreich ausgeführt. Der zurückgelieferte Code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Bei der geöffneten Position kann man die Ebene StopLoss und TakeProfit ändern. Dies wird mit Hilfe von der Methode ModifyPosition() gemacht.

//--- die Anzahl der Zeichen nach dem Komma
   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
//--- Der Wert des Punktes
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
//--- Erhalten wir den vorübergehenden Preis Bid
   double price=SymbolInfoDouble(_Symbol,SYMBOL_BID);
//--- Berechnen wir und normalisiern die Ebene SL und TP
   double SL=NormalizeDouble(price-100*point,digits);
   double TP=NormalizeDouble(price+100*point,digits);
//--- alles fertig, versuchen wir, die Position auf den Kauf zu modifizieren
   if(!trade.PositionModify(_Symbol,SL,TP))
     {
      //--- berichten wir über den Pech
      Print("Die Methode PositionModify() hat Pech. Der zurückgelieferte Code=",trade.ResultRetcode(),
            ". Die Beschreibung des Codes: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Die Methode PositionModify() wurde erfolgreich ausgeführt. Der zurückgelieferte Code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Die Modifizierung unddie Löschung der Order

Für die Parameter-Änderungen der Pending-Order in der Klasse CTrade ist die Methode OrderModify() vorgesehen, der alle notwendigen Parameter gegeben werden müssen.

//--- Überprüfen wir, ob eine Order platziert wurde  
   if(!OrderSelect(ticket))
     {
      Print("Die Order #",ticket," ist nicht gefunden");
      return;

     }
//--- Symbol 
   string symbol=OrderGetString(ORDER_SYMBOL);
//--- die Anzahl der Zeichen nach dem Komma
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
//--- Der Wert des Punktes
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
//--- Erhalten wir den Eröffnungspreis
   double price=OrderGetDouble(ORDER_PRICE_OPEN);
//--- Berechnen wir und normalisiern die Ebene SL und TP
   double SL=NormalizeDouble(price-200*point,digits);
   double TP=NormalizeDouble(price+200*point,digits);
//--- alles fertig, versuchen wir, die Order zu modifizieren 
   if(!trade.OrderModify(ticket,price,SL,TP,ORDER_TIME_DAY,0))
     {
      //--- berichten wir über den Pech
      Print("Die Methode OrderModify() hat Pech. Der zurückgelieferte Code=",trade.ResultRetcode(),
            ". Die Beschreibung des Codes: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Die Methode OrderModify() wurde erfolgreich ausgeführt. Der zurückgelieferte Code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Sie müssen das Ticket der Order erhalten, das geändert werden muss, und je nach seinem Typ. muss man die richtigen Ebene StopLoss und TakeProfit geben. Außerdem, der neue Erröfnungspreis muss auch korrekt bezüglich des aktuellen Preises sein.

Für die Löschung der Pending Orders braucht man nur ihr Ticket zu kennen:

//--- Überprüfen wir, ob eine Order platziert wurde  
   if(!OrderSelect(ticket))
     {
      Print("Die Order #",ticket," ist nicht gefunden");
      return;
     }
//--- alles fertig, versuchen wir, die Order zu löschen
   if(!trade.OrderDelete(ticket))
     {
      //--- berichten wir über den Pech
      Print("Die Methode OrderDelete() hat Pech. Der zurückgelieferte Code=",trade.ResultRetcode(),
            ". Die Beschreibung des Codes: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Die Methode OrderDelete() wurde erfolgreich ausgeführt. Der zurückgelieferte Code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

In der Klasse gibt es auch eine universelle Methode OrderOpen(), die Pending-Orders von jeder Art setzen kann. Im Unterschied von speziellen Methoden BuyLimit, BuyStop, SellLimit und SellStop, fordert er mehr notwendigen Parameter zu geben. Vielleicht findet ihn jemand bequemer.


Was kann man noch in Handelsklassen finden

In diesem Artikel zeigten wir Ihnen die Tricks mit Programmierung der Handelsoperationen des Kaufs und Verkaufs, auch die Arbeit mit Pendig-Orders. Aber im Abschnitt Handelsklassen gibt es noch einige bequeme Berater für die Roboter-Entwickler in MQL5:

  • COrderInfo — für die Arbeit mit Orders;
  • CHistoryOrderInfo — ür die Arbeit mit beendeten Orders, die in der History geraten sind;
  • CPositionInfo — für die Arbeit mit den Positionen;
  • CDealInfo — für die Arbeit mit Transaktionen;
  • CTerminalInfo — für die Erhaltung der Informationen über den Terminal.

Mit Hilfe dieser Klassen können Sie sich nur auf den Handeln Ihrer Strategie konzentrieren, und alle technischen Fragen werden minimal stören. Außerdem kann man die Klasse CTrade für das Lernen der Handels-Anfragen verwenden, zum Beispiel, für Debugging. Und mit der Zeit können Sie auf seine Basis eigene Klassen erstellen, in den Sie die nötige Logik für die Verarbeitung der Ausführungsergebnisse der Handels-Anfragen realisieren werden.

Fangen Sie an, mit einfachen Skripten in Algotrading

Die im Artikel vorgeschlagenen Arten für die Entwicklung der Handels-Roboter in MQL5 sind vor allem für die Neulinge vorgesehen, aber viele erfahrene Entwickler können da vieles Nützliches finden. Fangen Sie an, mit einfachen Skripten aus diesem Artikel, und Sie verstehen, dass einen Roboter zu erstellen ist viel einfacher, als Sie denken.

Für diejenigen, die sich weiter in diese Richtung entwickeln wollen, bieten wir noch 2 Artikel an:

  1. Grundlagen der Börsenkursbildung am Beispiel des Terminhandelsbereichs der Moskauer Börse
  2. Sichern Ihres EA beim Handel auf der Moskauer Börse

Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/2513

Beigefügte Dateien |
accountinfo.mq5 (4.6 KB)
symbolinfo.mq5 (4.91 KB)
expert_sample.mq5 (37.09 KB)
limit_sample.mq5 (12.86 KB)
Universal Expert Advisor: Einbindung der Standard MetaTrader Module für Signale (Teil 7) Universal Expert Advisor: Einbindung der Standard MetaTrader Module für Signale (Teil 7)
Dieser Teil des Artikels beschreibt die Möglichkeiten der Einbindung der Signal-Module, Teil der Standard-Bibliothek des MetaTraders, durch CStrategy. Der Artikel beschreibt, wie man mit Signalen arbeitet und wie man eigene Strategien auf ihrer Basis erstellt.
Wie man die Signale mit Hilfe vom Berater nach seinen Regeln kopieren soll? Wie man die Signale mit Hilfe vom Berater nach seinen Regeln kopieren soll?
Beim Abonnieren zu Signalen kann eine solche Situation auftreten: Ihre Hebelwirkung im Trading-Konto ist 1:100, der Anbieter hat einen Hebel von 1: 500 und handelt mit einem minimalen Lot, und Ihre Handelsbilanzen handeln nahezu gleich - mit dem Abbildungsverhältnis zwischen 10% und 15%. In diesem Artikel erfahren Sie, wie in diesem Fall das Abbildungsverhältnis erhöhen kann.
Testen von Strategien mit echten Ticks Testen von Strategien mit echten Ticks
Der Artikel enthält die Ergebnisse der Prüfung einer einfachen Trading-Strategie in drei Modi: "1 Minute OHLC", "Jeder Tick" und "Jeder Tick basierend auf echten Ticks" mit tatsächlichen historischen Daten.
Selbstoptimierung der Experten: evolutionäre und genetische Algorithmen Selbstoptimierung der Experten: evolutionäre und genetische Algorithmen
Im Artikel werden die Hauptprinzipien betrachtet, die in den Evolutionsalgorithmen versetzt sind, auch ihre Arten und die Besonderheiten. Auf dem Beispiel des einfachen Experten mit Hilfe der Experimente wird es vorgeführt, was unserem Handelnsystem die Anwendung der Optimierung geben kann. Wir betrachten die Programm-Pakete, die genetische, evolutionäre und andere Arten der Optimierung realisieren und führen die Anwendungsbeispiele bei einer Optimierung eines Prädiktor-Satzes und bei einer Optimierung des Handelnsystems hin.