Methoden zur Fernsteuerung von EAs

Dmitriy Gizlyk | 27 November, 2018

Inhalt

Einführung

Verschiedene automatisierte Systeme für den Handel an den Finanzmärkten sind in unserem digitalen Zeitalter weit verbreitet. Die Hauptvorteile elektronischer Expert Advisors (EAs) können 24 Stunden am Tag einwandfrei die Algorithmen ausführen. Das virtuelle Hosting ermöglicht den autonomen Einsatz von EAs rund um die Uhr.

Leider funktionieren nicht alle EAs in allen Marktsituationen gleichermaßen gut. In diesen Fällen müssen Händler sie oft manuell aktivieren und deaktivieren. Dies ist einfach, wenn ein Nutzer direkten Zugriff auf das Terminal hat. Aber was ist, wenn Sie keinen schnellen Zugriff auf das Terminal mit einem funktionierenden EA haben? In solchen Fällen wäre es gut, den EA-Betrieb fernsteuern zu können. Betrachten wir eine der möglichen Methoden der EA-Fernbedienung im Terminal.

1. Erklärung des Problems

Auf den ersten Blick scheint die Aufgabe klar zu sein: Wir müssen ein Programm erstellen, das nach Erhalt externer Befehle Anweisungen an EAs sendet. Aber nachdem wir das Problem genauer betrachtet haben, können wir sehen, dass MetaTrader 5 keine Möglichkeit bietet, die Arbeit eines Drittanbieters EA direkt mit Hilfe von Programmiermitteln zu beeinflussen. Jeder EA arbeitet in einem separaten Datenstrom, und es ist unmöglich, einen laufenden EA in einem geöffneten Chart zu erkennen. Der Nutzer fxsaber bot eine Lösung in der "Expert - Bibliothek für MetaTrader 5" an.

In diesem Code schlägt der Autor vor, die Möglichkeit zu nutzen, Vorlagen (templates) zu speichern. Auf den ersten Blick hat das Speichern von Vorlagen keinen Einfluss auf den Betrieb von Programmen, die auf einem Diagramm ausgeführt werden. Dies ist wahr, aber beim Speichern der Chartvorlage werden alle auf dem Chart existierenden grafischen Objekte sowie alle gestarteten Anwendungen und deren Parameter in der Datei gespeichert. Die anschließende Anwendung der gespeicherten Vorlage auf das Diagramm stellt alle grafischen Objekte und Programme zusammen mit den gespeicherten Parametern wieder her.

Eine weitere Seite dieser Auswirkung ist, dass alle Objekte und Programme, die vor dem Laden der Vorlage vorhanden waren, aus dem Diagramm entfernt werden. Mit anderen Worten, wenn ein EA auf dem Chart gestartet wird, wird er entfernt, falls die Vorlage den EA nicht enthält, und umgekehrt. Das Laden und Löschen eines EAs vom Chart reduziert sich somit auf die Bearbeitung einer Vorlagendatei.

Natürlich ist es möglich, die notwendigen Vorlagen vorab vorzubereiten und die notwendigen zuladen, ohne sie bearbeiten zu müssen. In diesem Fall wächst die Anzahl der benötigten Vorlagen jedoch doppelt so schnell wie die Anzahl der verwendeten EAs. Außerdem, wenn verschiedene EA-Einstellungen für verschiedene Symbole verwendet werden, erhöht das Hinzufügen jedes Arbeitssymbols die Anzahl der Vorlagen. Das Erstellen von Vorlagen wird zur Routine, aber es ist notwendig, beim Anwenden nichts durcheinander zu bringen.

Die Bearbeitung von Vorlagen hat auch ihre eigenen Besonderheiten. Standardmäßig werden die Vorlagen im Verzeichnis "data_folder\Profiles\Templates\" gespeichert. Aber MQL5 erlaubt es, nur mit Dateien in der "Sandbox" zu arbeiten. fxsaber kam wieder einmal mit einer Lösung heraus: Er schlug vor, den Pfad zur Sandbox hinzuzufügen, wenn man den Namen der Vorlagedatei angibt. Dadurch ist es möglich, auf die Vorlagendatei zuzugreifen, ohne Bibliotheken von Drittanbietern zu verwenden.

Danken wir fxsaber für seinen scharfen Verstand und sein außergewöhnliches Denken.

Nachdem wir EA-Managementmethoden definiert haben, arbeiten wir an einem Kommunikationsmodell zwischen Programm und Nutzer. Die Welt von heute zwingt die Menschen, mobil zu bleiben und ihre Smartphones immer dabei zu haben. Die MetaTrader 5 Plattform bietet Versionen sowohl für iPhone als auch für Android. Nach der Anbindung des Terminals an ihre Konten können die Nutzer die Preisbewegungen auf dem Chart analysieren und manuell handeln. Derzeit erlauben mobile Endgeräte die Verwendung von EAs und Indikatoren von Drittanbietern nicht. Desktop-Terminals und virtuelles Hosting sind die einzigen Optionen, wenn Sie EAs verwenden möchten.

Das mit einem Konto verbundene mobile Endgerät ermöglicht die Anzeige des gesamten Kontos, aber es gibt keine direkten Verbindungskanäle zwischen dem mobilen und dem Desktop-Endgerät. Das Einzige, was wir beeinflussen können, ist das Erteilen und Löschen von Aufträgen. Erteilte Aufträge werden sofort auf dem Konto angezeigt und können von einem EA im Desktop-Terminal verfolgt werden. So können wir zusammen mit der Auftragserteilung Steuerbefehle an unseren Master-EA übertragen. Wir müssen nur die Liste der Befehle und den Code definieren, die übergeben werden soll. In den folgenden Abschnitten werden diese Fragen behandelt.

2. Analysieren der Vorlagedatei

Schauen wir uns zuerst die Struktur der Vorlagedatei (template) an. Das Beispiel unten ist eine Vorlage für den Chart von EURUSD M30 und dem darauf gestarteten EA ExpertMACD mit dem Indikator MACD.

<chart>
id=130874249669663027
symbol=EURUSD
period_type=0
period_size=30
digits=5
.....
.....
windows_total=2

<expert>
name=ExpertMACD
path=Experts\Advisors\ExpertMACD.ex5
expertmode=0
<inputs>
Inp_Expert_Title=ExpertMACD
Inp_Signal_MACD_PeriodFast=12
Inp_Signal_MACD_PeriodSlow=24
Inp_Signal_MACD_PeriodSignal=9
Inp_Signal_MACD_TakeProfit=50
Inp_Signal_MACD_StopLoss=20
</inputs>
</expert>

<window>
height=162.766545
objects=103

<indicator>
name=Main
........
</indicator>
<object>
.......
</object>

<object>
........
</object>
........
........
<object>
........
</object>

</window>

<window>
height=50.000000
objects=0

<indicator>
name=MACD
path=
apply=1
show_data=1
scale_inherit=0
scale_line=0
scale_line_percent=50
scale_line_value=0.000000
scale_fix_min=0
scale_fix_min_val=-0.001895
scale_fix_max=0
scale_fix_max_val=0.001374
expertmode=0
fixed_height=-1

<graph>
name=
draw=2
style=0
width=1
color=12632256
</graph>

<graph>
name=
draw=1
style=2
width=1
color=255
</graph>
fast_ema=12
slow_ema=24
macd_sma=9
</indicator>
</window>
</chart>

Wie aus dem Code ersichtlich, sind die Informationen in der Vorlagendatei strukturiert und durch Tags unterteilt. Die Datei beginnt mit dem Tag <chart>, der die wichtigsten Chartdaten enthält, einschließlich Chart-ID, Symbol und Zeitrahmen. Die Informationen, die uns interessieren, befinden sich zwischen den Tags <expert> und </expert>.

Am Anfang des Blocks befinden sich Daten des EAs: Sein Kurzname wird im Diagramm angezeigt und der Dateipfad. Als Nächstes kommt das Expertenmodus-Flag. Sein Status zeigt an, ob der EA den Handel zulässt. Auf das Flag folgen die EA-Parameter, die durch die Tags <inputs> </inputs> hervorgehoben werden. Dann können wir Daten in den Unterfenstern der Charts finden. Jedes Subfenster wird durch die Tags <window> und </window> hervorgehoben, die Beschreibungen der gestarteten Indikatoren (<indicator> ... </indicator>) und der angewandten grafischen Objekte (<object> ... </object>) enthalten.

Beachten Sie auch, dass es ratsam wäre, diese aus der Vorlage zu entfernen, wenn ein EA und/oder ein Indikator, der auf dem Chart gestartet wurde, grafische Objekte erstellt. Andernfalls werden die Objekte aus der Vorlage auf das Diagramm angewendet und beim Start eines solchen EA und/oder Indikators werden die gleichen Objekte neu erstellt.

Dies kann zu einer unkontrollierten Erzeugung einer großen Anzahl identischer Objekte führen, die das Chart überladen, sowie zu einem übermäßigen Verbrauch von Computerressourcen. Im schlimmsten Fall zeigt das notwendige Programm den Fehler bei der Objekterstellung an und wird vom dem Chart entfernt.

Vom Programm erzeugte Objekte werden in der Regel in der grafischen Objektliste ausgeblendet, wenn ihnen die Eigenschaft "hidden" (ausgeblendet) zugewiesen wurde, um sie vor Nutzermodifikationen zu schützen. Das Flag "hidden" wird bereitgestellt, um diese Eigenschaft in der Vorlage zu setzen. Sie ist gleich 1 für ausgeblendete Objekte.

Um den EA zu aktivieren/deaktivieren, müssen wir lediglich die Vorlagendatei neu schreiben, indem wir den Wert der Expertenmodus-Flagge ändern und dabei versteckte Objekte löschen. Durch das Anwenden der neuen Vorlage wird der EA mit der erforderlichen Eigenschaft neu gestartet.

3. Definieren der Befehle

Nachdem die Hauptprinzipien des zu entwickelnden EA definiert wurden, ist es an der Zeit, das Kommunikationssystem zu erstellen. Früher haben wir uns bereits entschieden, Aufträge für das Senden von Befehlen zu verwenden. Aber wie senden wir Befehle mit Aufträgen, ohne das Finanzergebnis zu beeinträchtigen? Für diese Zwecke verwenden wir Pending-Order, die nach Erhalt des Befehls vom EA gelöscht werden.

Bei der Erteilung eines Pending-Auftrags sollten wir darauf achten, dass dieser nicht innerhalb seines Arbeitszeitintervalls aktiviert wird. Die Lösung liegt hier auf der Hand - wir müssen einen Auftrag in ausreichender Entfernung zum aktuellen Preis aufgeben.

Zu meiner Überraschung fand ich es bei der Arbeit mit einem mobilen Endgerät unmöglich, Kommentare den geöffneten Aufträgen hinzuzufügen. Gleichzeitig können die Nutzer Kommentare zu Aufträgen sehen, die im Desktop-Terminal erstellt wurden. So können wir eine einseitige Kommunikation vom Master-EA zu einem Nutzer herstellen. Nutzer können auf diese Weise jedoch keine Befehle ausgeben.

Trotzdem können wir noch Pending-Orders erteilen, die vom EA gelesen werden sollen, aber nur ohne Kommentare. Dafür aber können wir das Preis- und Auftragssymbol für die Übergabe des Befehls verwenden. Hier könnten wir den Preis für die Kodierung des Befehls definieren. Er sollte einen ausreichenden Abstand zum aktuellen Preis haben, damit der erteilte Auftrag unter keinen Umständen ausgelöst wird.

Ich glaube, das sind die Preise nahe Null. In der Theorie ist die Wahrscheinlichkeit, dass ein Symbol gegen Null geht, vernachlässigbar gering. Wenn wir also den Auftragspreis auf 1-5 Ticks festlegen, wird er höchstwahrscheinlich nie aktiviert. Natürlich sind wir in diesem Fall auf den Sell-Stop-Orders beschränkt, da die Verwendung von Stop-Orders die freie Marge nicht beeinflusst.

Vergessen wir nicht, dass wir Kommentare von Aufträgen in der mobilen Anwendung lesen können, d.h. unser Master-EA ist in der Lage, die Daten auf diese Weise zu übermitteln.

Zusammenfassend werden die folgenden Befehlscodes vorgeschlagen:

# Preis Volumen Befehl
1 1 Tick egal Statusabfrage des EAs'.
Der Master-EA platziert eine Pending-Order mit dem Symbol des EAs. Der Name des EAs und die Handelserlaubnis werden im Kommentar angegeben.
2 2 Ticks egal Stoppt den Handel des EAs.
Ohne Kommentar werden alle EAs gestoppt. Wurde der Befehl aufgrund einer Auftragsänderung nach dem ersten Befehl ausgegeben, wird ein bestimmter EA mit einem bestimmten Symbol gestoppt.
3 3 Ticks egal Handelsstart mit dem EA.
Das Funktionsprinzip ist dasselbe wie bei Befehl 2.
4 4 Ticks 1 min. KAUF-Lot
2 min. VERKAUFS-Lot
3 min. Lot Alle
Entfernen von Pending-Orders.
5 5 Ticks 1 min. KAUF-Lot
2 min. VERKAUFS-Lot
3 min. Lot Alle
Positionen schließen.


4. Erstellen des Master-EAs

Nachdem wir nun die Funktionsweise und die Kommunikationsform vollständig verstanden haben, beginnen wir mit der Entwicklung des EA. Unser EA-Code wird Methoden aus der "Expert - Bibliothek für MetaTrader 5" mit einer kleinen Änderung verwenden - alle Methoden der Bibliothek werden zur besseren Übersichtlichkeit 'public'.

Zuerst weisen wir den angewandten Tags mnemonische Namen zu, um die Handhabung zu erleichtern. Einige von ihnen sind bereits in der verwendeten Bibliothek deklariert.

#define FILENAME (__FILE__ + ".tpl")
#define PATH "\\Files\\"
#define STRING_END "\r\n"
#define EXPERT_BEGIN ("<expert>" + STRING_END)
#define EXPERT_END ("</expert>" + STRING_END)
#define EXPERT_INPUT_BEGIN ("<inputs>" + STRING_END)
#define EXPERT_INPUT_END ("</inputs>" + STRING_END)
#define EXPERT_CHART_BEGIN ("<chart>" + STRING_END)
#define EXPERT_NAME "name="
#define EXPERT_PATH "path="
#define EXPERT_STOPLEVEL "stops_color="

Additional ones are declared in our EA code.

#define OBJECT_BEGIN             ("<object>" + STRING_END)
#define OBJECT_END               ("</object>" + STRING_END)
#define OBJECTS_NUMBER           ("objects=")
#define OBJECT_HIDDEN            ("hidden=1")
#define EXPERT_EXPERTMODE        ("expertmode=")

Es sei auch darauf hingewiesen, dass fxsaber sich um die Kompatibilität seiner Bibliothek mit anderem Code gekümmert und mnemonische Namen am Ende der Bibliothek gelöscht hat. Dieser Ansatz eliminiert Fehler bei der Neuzuweisung des gleichen Namens an ein anderes Makro. Dies erlaubt jedoch nicht die Verwendung solcher Erklärungen außerhalb der Bibliothek. Um ähnliche Deklarationen von Makros im EA-Code nicht zu wiederholen, entfernen Sie die Kommentarzeichen "//" vor der #undef-Direktive im Library-Code.

//#undef EXPERT_STOPLEVEL
//#undef EXPERT_PATH
//#undef EXPERT_NAME
//#undef EXPERT_CHART_BEGIN
//#undef EXPERT_INPUT_END
//#undef EXPERT_INPUT_BEGIN
//#undef EXPERT_END
//#undef EXPERT_BEGIN
//#undef STRING_END
//#undef PATH
//#undef FILENAME

Dann deklarieren wir zwei Variablen für unseren Master-EA: die Verfallszeit des Informationsauftrages und die Magicnummer für die Identifikation.

sinput int      Expirations =  5;
sinput ulong    Magic       =  88888;

Wir binden die oben erwähnte und die Bibliothek mit den Handelsoperationen ein.

#include <fxsaber\Expert.mqh>
#include <Trade\Trade.mqh>

Im Block der globalen Variablen deklarieren wir eine Instanz der Klasse der Handelsoperationen und der Variablen zum Speichern des Arbeitscharts und der Ticketnummer des letzten Auftrags.

CTrade   *Trade;
ulong     chart;
ulong     last_command;

In der Funktion OnInit initialisieren wir die globalen Variablen.

int OnInit()
  {
//---
   Trade =  new CTrade();
   if(CheckPointer(Trade)==POINTER_INVALID)
      return INIT_FAILED;
   Trade.SetDeviationInPoints(0);
   Trade.SetExpertMagicNumber(Magic);
   Trade.SetMarginMode();
   Trade.SetTypeFillingBySymbol(_Symbol);
//---
   chart=ChartID();
   last_command=0;
//---
   return(INIT_SUCCEEDED);
  }

Vergessen wir nicht, die Instanz der Handelsoperationen in der Funktion OnDeinit wieder zu entfernen.

void OnDeinit(const int reason)
  {
//---
   if(CheckPointer(Trade)!=POINTER_INVALID)
      delete Trade;
  }


4.1. Befehlsmanager

Der Start des Master-EAs erfolgt aus der Transaktion OnTradeTransaction. Beachten wir, dass der Aufruf der Funktion für einen Auftrag mehrfach verarbeitet werden kann. Deshalb werden wir vor der Ausführung des Programmcodes eine Reihe von Prüfungen durchführen.

Wir prüfen die Verfügbarkeit der Ticketnummer des Auftrags für das zu bearbeitende Ereignis. Wir werden auch den Auftragsstatus überprüfen, um das Ereignis von gelöschten Aufträgen zu vermeiden. Außerdem sollten wir die Magicnummer des Auftrages überprüfen, um das Bearbeiten von Aufträgen von EAs zu vermeiden, und wir überprüfen die Auftragsart, da unsere Befehle nur bei Sell-Stop-Orders betrifft. Darüber hinaus sollten wir die Art einer Handelsoperation überprüfen, da eine Order hinzugefügt oder geändert werden soll.

Nach erfolgreichem Abschluss aller Prüfungen starten wir den in der Funktion CheckCommand angeordneten Befehlsmanager.

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//---
   if(trans.order>0 && trans.order_state!=ORDER_STATE_REQUEST_CANCEL && request.magic==0 && 
      trans.order_type==ORDER_TYPE_SELL_STOP && 
      (trans.type==TRADE_TRANSACTION_ORDER_ADD || trans.type==TRADE_TRANSACTION_ORDER_UPDATE))
      CheckCommand(trans,request);
  }

Beim Start der Funktion CheckCommand erhält sie über ihre Parameter die Handels- und Anforderungsstrukturen. Zuerst prüfen wir, ob diese Anfrage schon einmal bearbeitet wurde. Wenn der Befehl bereits verarbeitet wurde, verlassen wir die Funktion.

void CheckCommand(const MqlTradeTransaction &trans,
                  const MqlTradeRequest &request)
  {
   if(last_command==trans.order)
      return;

Falls nicht, dekodieren wir den Preis des Auftrags in den Befehl.

   double tick=SymbolInfoDouble(trans.symbol,SYMBOL_TRADE_TICK_SIZE);
   uint command=(uint)NormalizeDouble(trans.price/tick,0);

Dann verwenden wir den Operator switch, um die Funktion aufzurufen, die dem angekommenen Befehl entspricht.

   switch(command)
     {
      case 1:
        if(StringLen(request.comment)>0 || trans.type==TRADE_TRANSACTION_ORDER_UPDATE)
           return;
        if(trans.order<=0 || (OrderSelect(trans.order) && StringLen(OrderGetString(ORDER_COMMENT))>0))
           return;
        GetExpertsInfo();
        break;
      case 2:
        ChangeExpertsMode(trans,request,false);
        break;
      case 3:
        ChangeExpertsMode(trans,request,true);
        break;
      case 4:
        DeleteOrders(trans);
        break;
      case 5:
        ClosePosition(trans);
        break;
      default:
        return;
     }

Abschließend speichern wir die Ticketnummer des letzten Auftrags und löschen den Auftrag aus dem Konto.

   last_command=trans.order;
   Trade.OrderDelete(last_command);
  }

Der vollständige Code aller Funktionen findet sich im Anhang.


4.2. Die Daten der gestarteten EAs

Die Funktion GetExpertsInfo ist für die Beschaffung von Daten über alle im Terminal gestarteten EAs zuständig. Wie bereits entschieden, platziert diese Funktion informative Stop-Orders für das Symbol, das anzeigt, auf welchem Symbol der EA gestartet wird, während der EA-Name und sein Status in den Auftragskommentaren angezeigt werden.

Wir löschen zu Beginn der Funktion zuvor erteilte Aufträge, indem wir die Funktion DeleteOrdersByMagic aufrufen.

void GetExpertsInfo(void)
  {
   DeleteOrdersByMagic(Magic);

Weiters ordnen wir anschließend die Schleife so an, dass sie über alle aktiven Charts im Terminal iteriert. Die Schleife beginnt mit der Überprüfung, ob auf dem analysierten Chart unser Master-EA arbeitet. Wenn ja, wechseln wir zum nächsten Chart.

   long i_chart=ChartFirst();
   while(i_chart>=0 && !IsStopped())
     {
      if(i_chart==0 || i_chart==chart)
        {
         i_chart=ChartNext(i_chart);
         continue;
        }

Als nächstes laden wir die Vorlage für den Chart mit einer Prüfung vorher, ob der EA auf dem Chart arbeitet. Wenn der fehlt oder die Vorlage nicht geladen wurde, wechseln wir zum nächsten Chart.

      string temp=EXPERT::TemplateToString(i_chart,true);
      if(temp==NULL)
        {
         i_chart=ChartNext(i_chart);
         continue;
        }

Danach suchen wir den Block des EAs in der Vorlage. Wurde er nicht gefunden, wechseln wir zum nächsten Chart.

      temp=EXPERT::StringBetween(temp,EXPERT_BEGIN,EXPERT_END);
      if(temp==NULL)
        {
         i_chart=ChartNext(i_chart);
         continue;
        }

Danach rufen wir den Namen des EAs und seinen Status ab. Sie werden verwendet, um den Kommentar des zukünftigen Info-Auftrags zu bilden. Wenn dem EA erlaubt ist zu handeln, wird der Buchstabe "T" vor seinen Namen gestellt, ansonsten wird der Buchstabe "S" verwendet.

      string name =  EXPERT::StringBetween(temp,EXPERT_NAME,STRING_END);
      bool state  =  (bool)StringToInteger(EXPERT::StringBetween(temp,EXPERT_EXPERTMODE,STRING_END));
      string comment =  (state ? "T " : "S ")+name;

Am Ende der Schleife bestimmen wir das Symbol des Charts und die Verfallszeit des Info-Auftrages. Der Auftrag wird gesendet und wir wechseln zum nächsten Chart.

      string symbol=ChartSymbol(i_chart);
      ENUM_ORDER_TYPE_TIME type=ORDER_TIME_GTC;
      datetime expir=0;
      if(Expirations>0)
        {
         expir=TimeCurrent()+Expirations*60;
         type=ORDER_TIME_SPECIFIED;
        }
      Trade.SellStop(SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN),SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE),symbol,0,0,type,expir,comment);
      i_chart=ChartNext(i_chart);
     }
  }

In der genannten Funktion haben wir die Methoden aus der fxsaber's Bibliothek verwendet - die Vorlagedatei des Charts als Zeichenkette und die Teilzeichenkette zwischen den angegebenen Tags.

Wir überprüfen gegebenenfalls, ob der EA im Chart vorhanden ist, um die Vorlage für eine Zeichenkettenvariable für das angegebene Diagramm zu erhalten. Wir speichern dann die Vorlage des angegebenen Diagramms und lesen Sie die erhaltene Vorlage als Binärarray. Wir konvertieren das numerische Array in die Zeichenkette und geben die aufrufenden Funktionen zurück. Wenn in einer Verifizierungsphase Fehler auftreten, gibt die Funktion NULL zurück.

  static string TemplateToString( const long Chart_ID = 0, const bool CheckExpert = false )
  {
    short Data[];
    return(((!CheckExpert || EXPERT::Is(Chart_ID)) && ::ChartSaveTemplate((ulong)Chart_ID, PATH + FILENAME) && (::FileLoad(FILENAME, Data) > 0)) ?
           ::ShortArrayToString(Data) : NULL);
  }

Um die Teilzeichenkette zwischen den Tags zu erhalten, definieren wir zunächst die Anfangs- und End-Position der Zeichenkette.

  static string StringBetween( string &Str, const string StrBegin, const string StrEnd = NULL )
  {
    int PosBegin = ::StringFind(Str, StrBegin);
    PosBegin = (PosBegin >= 0) ? PosBegin + ::StringLen(StrBegin) : 0;

    const int PosEnd = ::StringFind(Str, StrEnd, PosBegin);

Dann reduzieren wir die Teilzeichenkette auf das Original und geben ihn zurück.

    const string Res = ::StringSubstr(Str, PosBegin, (PosEnd >= 0) ? PosEnd - PosBegin : -1);
    Str = (PosEnd >= 0) ? ::StringSubstr(Str, PosEnd + ::StringLen(StrEnd)) : NULL;

    if (Str == "")
      Str = NULL;

    return(Res);
  }

Der gesamte Code aller Klassen und Methoden befindet sich in der Anlage.

4.3. Funktion zur Statusänderung des EAs

Der Status des EAs wird in der Funktion ChangeExpertsMode geändert. Die angegebene Funktion erhält in ihren Parametern die Handelsbetriebs- und Anforderungsstrukturen sowie einen neuen Status für die Installation des EAs.

void ChangeExpertsMode(const MqlTradeTransaction &trans,
                       const MqlTradeRequest &request,
                       bool  ExpertMode)
  {
   string comment=request.comment;
   if(StringLen(comment)<=0 && OrderSelect(trans.order))
      comment=OrderGetString(ORDER_COMMENT);      
   string exp_name=(StringLen(comment)>2 ? StringSubstr(comment,2) : NULL);

Als Nächstes wird eine Schleife so organisiert, dass sie, wie oben beschrieben, alle Charts mit Vorlagen durchläuft.

   long i_chart=ChartFirst();
   while(i_chart>=0 && !IsStopped())
     {
      if(i_chart==0 || i_chart==chart || (StringLen(exp_name)>0 && ChartSymbol()!=trans.symbol))
        {
         i_chart=ChartNext(i_chart);
         continue;
        }
      string temp=EXPERT::TemplateToString(i_chart,true);
      if(temp==NULL)
        {
         i_chart=ChartNext(i_chart);
         continue;
        }

In der nächsten Phase prüfen wir gegebenenfalls die Verfügbarkeit des erforderlichen Experten auf dem Chart. Wenn der im Chart gestartete EA nicht der Anforderung entspricht, fahren wir mit dem nächsten Chart fort. Wir überprüfen auch den aktuellen Status des EAs. Falls er dem für die Installation angegebenen Status entspricht, fahren wir mit dem nächsten Chart fort.

      string NewTemplate   =  NULL;
      if(exp_name!=NULL)
        {
         NewTemplate=EXPERT::StringBetween2(temp,NULL,EXPERT_NAME);
         string name=EXPERT::StringBetween(temp,NULL,STRING_END);
         if(name!=exp_name)
           {
            i_chart=ChartNext(i_chart);
            continue;
           }
         NewTemplate+=name+STRING_END;
        }
//---
      NewTemplate+=EXPERT::StringBetween2(temp,NULL,EXPERT_EXPERTMODE);
      bool state  =  (bool)StringToInteger(EXPERT::StringBetween(temp,NULL,STRING_END));
      if(state==ExpertMode)
        {
         i_chart=ChartNext(i_chart);
         continue;
        }

Nachdem alle erforderlichen Prüfungen bestanden wurden, erstellen wir eine neue Vorlage mit dem angegebenen Expertenstatus. Wir entfernen die ausgeblendeten Objekte aus der Vorlage und wenden die neue Vorlage auf den Chart an. Nachdem alle Vorgänge ausgeführt wurden, fahren wir mit dem nächsten Chart fort.

      NewTemplate+=IntegerToString(ExpertMode)+STRING_END+temp;
      NewTemplate=DeleteHiddenObjects(NewTemplate);
      EXPERT::TemplateApply(i_chart,NewTemplate,true);
//---
      i_chart=ChartNext(i_chart);
     }

Nachdem die Schleife über alle Charts gelaufen ist, beginnen wir mit der Erfassung von Informationen zu den laufenden EAs, um dem Nutzer den neuen Status der EAs anzuzeigen.

   GetExpertsInfo();
  }

Der vollständige Code aller Funktionen findet sich im Anhang.

4.4. Funktionen zum Löschen und Schließen von Positionen

Die Funktionen für das Löschen von Aufträgen und dem Eröffnen von Positionen basieren auf dem gleichen Algorithmus, der sich nur in den Zielobjekten unterscheidet. Deshalb betrachten wir in diesem Artikel nur einen von ihnen. Beim Aufruf der Funktion DeleteOrders wird ihr in den Parametern die Struktur der Handelsoperationen übergeben. Mit dieser Struktur wird das Auftragsvolumen in Richtung geschlossener Aufträge dekodiert (gemäß der Befehlstabelle aus Abschnitt 3).

void DeleteOrders(const MqlTradeTransaction &trans)
  {
   int direct=(int)NormalizeDouble(trans.volume/SymbolInfoDouble(trans.symbol,SYMBOL_VOLUME_MIN),0);

Die Schleife zur Iteration über alle auf dem Konto erteilten Aufträge wird anschließend eingerichtet. In dieser Schleife wird die Auftragsart auf die Einhaltung des eingehenden Befehls überprüft. Wenn eine Übereinstimmung vorliegt, wird eine Aufforderung zur Entfernung des Auftrags gesendet.

   for(int i=total-1;i>=0;i--)
     {
      ulong ticket=OrderGetTicket((uint)i);
      if(ticket<=0)
         continue;
//---
      switch((ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE))
        {
         case ORDER_TYPE_BUY_LIMIT:
         case ORDER_TYPE_BUY_STOP:
         case ORDER_TYPE_BUY_STOP_LIMIT:
           if(direct==2)
              continue;
           Trade.OrderDelete(ticket);
           break;
         case ORDER_TYPE_SELL_LIMIT:
         case ORDER_TYPE_SELL_STOP:
         case ORDER_TYPE_SELL_STOP_LIMIT:
           if(direct==1)
              continue;
           Trade.OrderDelete(ticket);
           break;
        }
     }
  }

Der vollständige Code aller Funktionen findet sich im Anhang.


Schlussfolgerung

Dieser Artikel schlägt die Methode für die EA-Fernbedienung in der MetaTrader 5-Plattform vor. Diese Lösung erhöht die Mobilität von Händlern, die Handelsroboter in ihrer Tätigkeit einsetzen. Der vorgestellte Nicht-Standard-Ansatz mit der Verwendung von Standardfunktionen ermöglicht es, mehrere Probleme ohne die Verwendung verschiedener DLLs zu lösen.

Referenzen

Expert - Bibliothek für MetaTrader 5

Die dieses Artikels

#
Name
Typ
Beschreibung
1 Expert.mqh Klassenbibliothek Expert - Bibliothek für MetaTrader 5
2 Master.mq5 Expert Advisor Master-EA für das Management anderer EAs, zu starten auf dem Terminal
3 Master.mqproj Projektdatei Projekt Master-EA