MetaTrader 5 herunterladen

Der Fehler 146 ("Trade-Context ist besetzt") und was man dagegen tun kann

9 November 2015, 09:01
Andrey Khatimlianskii
0
353

1. Was ist "Trade-Context" im Hinblick auf's Terminal MetaTrader 4

  Auszug aus MetaEditor:

Um Handelsoperationen von Experten und Skripten zu führen, wurde nur ein Trade zur Verfügung gestellt, das im Trade-Kontext-Programm (Kontext des automatisierten Handels von Experten und Skripten) gestartet wird. Der Grund ist, dass, wenn dieser Kontext mit einer Handelsoperation von einem Experten besetzt ist, dann kann ein anderer Experte oder Skript die Handelsfunktionen in diesem Moment nicht aufrufen, wegen des Fehlers 146 (ERR_TRADE_CONTEXT_BUSY).

Besser gesagt, Handelsoperationen können zugleich nur von einem Experten (oder Script) geführt werden. Alle anderen Experten, die auch versuchen zu handeln, werden vom Fehler 146 gestoppt. Dieser Artikel ist der Lösung dieses Problems gewidmet.


2. Funktion IsTradeAllowed()

Die einfachste Art, herauszufinden, ob der "Trade-Context" frei ist, ist es die Verwendung der Funktion IsTradeAllowed().
  Auszug aus MetaEditor:

"bool IsTradeAllowed()

Liefert TRUE, wenn dem Experten handeln zugelassen wird, und das Trade für Handelsoperationen frei ist,sonst wird FALSE zurückgeliefert.

Das heisst, man kann nur in dem Fall handeln, wenn die Funktion IsTradeAllowed() TRUE liefert.
Die Überprüfung muss direkt vor der Handelsoperation durchgefürt werden.

    Ein Beispiel für die falsche Verwendung der Funktion:

int start()
  {
    // Überprüfen, ob der Trade-Context frei ist
    if(!IsTradeAllowed())
      {
        //Wenn die Funktion IsTradeAllowed() FALSE zurückgeliefert hat, dann informieren den Benutzer darüber,//
        Print("Der Trade-Context ist besetzt! Der Experte kann die Position nicht öffnen!")
        // Und Beenden die Arbeit des Experten.  Es wird fortgesetzt,wenn der nächste Tick kommt 
        Tick// 
        return(-1);
      }
    else
      {
        Wenn die Funktion IsTradeAllowed() TRUE zurückgeliefert hat, dann den Benutzer darüber informieren  
        //Und die Arbeit fortsetzen 
        Print("Der Trade-Context ist frei! Die Arbeit fortsetzen... ");
      }
    // Bestimmen, ob ein Markteintritt jetzt erfolgen sollte 
    ...
    // Berechnen die Stop Loss- und Take Profit-Levels und die Lot-Größe 
    ...
    // Öffnen eine Position
    if(OrderSend(...) < 0) 
         Alert (" Fehler beim Öffnen der Position №  ", GetLastError())
    return(0);
  }
    In diesem Beispiel wird die Überprüfung des Trade-Context-Status am Anfang der Funktion start() durchgeführt. Das ist die falsche Entscheidung - während der ausgegebenen Zeit für die Berechnung ( des Eingangs-Bedarfs zum Markt, der Stop-Loss,und Take-Profit-Levels, der Lot-Größe u.s.w), kann der Traid-Context von einem anderen Experten besetzt werden. In dem Fall hat der Versuch, die Position zu öffnen, keinen Erfolg.


    Ein Beispiel für die richtige Verwendung der Funktion:

int start()
  {
    // Bestimmen, ob ein Markteintritt jetzt erfolgen sollte 
    ...
    // Berechnen die Stop Loss- und Take Profit-Levels und die Lot-Größe 
    ...
    // Und erst jetzt überprüfen, ob der Trade-Context frei ist 
    if(!IsTradeAllowed())
      {
        Print("Der Trade-Context ist besetzt! Der Experte kann die Position nicht öffnen!")
        return(-1);
      }
    else
        Print("Der Trade-Context ist frei! Versuchen die Position zu öffnen...");
    // Wenn die Überprüfung erfolgreich gelaufen ist, eine Position Öffnen 
    if(OrderSend(...) < 0) 
        Alert(" Fehler der Position-Öffnung № ", GetLastError()); 
    return(0);
  }

Die Überprüfung wird hier direkt vor der Position-Öffnung durchgeführt, und die Wahrscheinlichkeit, dass sich ein anderer Experte zwischen diesen beiden Aktionen drängt, ist sehr gering (Sie existiert allerdings. Das wird später behandelt).

Diese Methode hat zwei wesentliche Nachteile:

  • Es gibt immer noch eine Wahrscheinlichkeit, dass Experten zugleich die Überprüfung durchführen und, nach einem positiven Ergebnis versuchen ein Trade auszuführen.
  • Wenn die Überprüfung fehlschlägt, wird der Experte gleich beim nächsten Tick versuchen, ein Trade auszuführen. solch eine Verzögerung ist höchst unerwünscht.

Das zweite Problem kann ziemlich einfach gelöst werden: man muss nur warten, bis der Trade-Context frei wird. Dann beginnt der Experte gleich zu handeln, wenn der andere Experte fertig ist.
Das wird ungefähr so aussehen:

int start()
  {
    // Bestimmen, ob ein Markteintritt jetzt erfolgen sollte 
    ...
    // Berechnen die Stop Loss- und Take Profit-Levels und die Lot-Größe 
    ...
    // Überprüfen, ob der Trade-Context frei ist
    if(!IsTradeAllowed())
      {
        Print("Der Trade-Context ist besetzt! Warten, bis er frei wird...");
        // die endlose Loop 
        while(true)
          {
            // Wenn der Experte vom Benutzer gestoppt wurde, dann brechen die Arbeit (Vorgang) ab 
            if(IsStopped()) 
              { 
                Print("Der Experte wurde vom Benutzer gestoppt!"); 
                return(-1); 
              }
            // Wenn der Trade-Context frei geworden ist, die Loop verlassen und starten zu handeln 
            if(IsTradeAllowed())
              {
                Print("Der Trade Context ist frei!");
                break;
              }
            // Wenn die Loop nicht aus anderen Gründen unterbrochen wird, "warten" 0.1 s 
            // Und Starten die Überprüfung neu
            Sleep(100);
          }
      }
    else
        Print("Der Trade-Context ist frei! Versuchen die Position zu öffnen...");
    // Versuchen die Position zu öffnen
    if(OrderSend(...) < 0) 
        Alert(" Fehler der Position-Öffnung № ", GetLastError()); 
    return(0);
  }
     In dieser aktuellen Realisierung haben wir wieder Problempunkte:
  • Erstens, da die Funktion IsTradeAllowed() nicht nur für den Trade-Context-Status verantwortlich ist, sondern auch für die Aktivierung/Deaktivierung des Experten zum Trading, kann dieser in der endlose Loop versinken und er kann erst dann gestoppt werden,wenn er manuell aus dem Chart entfernt wird.
  • Zweitens, wenn der Experte auf die Freigabe des Trade-Contexts wartet, selbst wenn es sich nur um Sekunden handelt, können die Preise sich ändern und dann ist es nicht mehr möglich, mit ihnen zu traden - Die Daten sollten dann noch einmal eingegeben werden und die Take-Profit- und Stop-Loss-Levels für die kommende Position neu berechnet werden.

Der korrigierte Code wird so aussehen:

// Die Zeit (in Sekunden), während der Experte auf die Freigabe des Trade-Contexts wartet  
//(wenn es besetzt ist) 
int MaxWaiting_sec = 30;
int start()
  {
    // Bestimmen, ob ein Markteintritt jetzt erfolgen sollte 
    ...
    // Berechnen die Stop Loss- und Take Profit-Levels und die Lot-Größe 
    ...
    // Überprüfen, ob der Trade-Context frei ist
    if(!IsTradeAllowed())
      {
        int StartWaitingTime = GetTickCount();
        Print("Der Trade-Context ist besetzt! Warten, bis er frei wird...");
        // die endlose Loop 
        while(true)
          {
            // Wenn der Experte vom Benutzer gestoppt wurde, dann brechen die Arbeit (Vorgang) ab 
            if(IsStopped()) 
              { 
                Print (" der Experte wurde vom Benutzer gestoppt! ");  
                return(-1); 
               }
            // Wenn die Wartezeit länger dauert, als es in der Variable steht  
            // MaxWaiting_sec, Brechen die Arbeit ebenfalls ab
            if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000) 
              {
                Print("Die Wartezeit ist überschnitten (" + MaxWaiting_sec + " sec.)!");
                return(-2);
              }
            // Wenn Der Trade Context frei geworden ist, 
            if(IsTradeAllowed())
              {
                Print("Der Trade Context ist frei!");
                // Erneuern die Marktinformation 
                RefreshRates();
                // Berechnen die Stop Loss- und Take Profit-Levels
                ...
                // Verlassen die Loop und beginnen zu handeln (zu traden)                
                break;
              }
            // Wenn die Loop nicht aus anderen Gründen unterbrochen wird, "warten" 0.1 s  
            // Und dann Starten die Überprüfung neu 
            Sleep(100);
          }
      }
    else
        Print("Der Trade-Context ist frei! Versuchen die Position zu öffnen...");

    // Versuchen die Position zu öffnen
    if(OrderSend(...) < 0) 
         Alert (" Fehler beim Öffnen der Position №  ", GetLastError())
 
    return(0);
  }
    Im obigen Beispiel wurde hinzugefügt:
  • die Erneurung der Marktinformation (RefreshRates()) und die daraus folgende Neuberechnung der Stop-Loss- und Take-Profit -Levels
  • Die maximale Wartezeit MaxWaiting_sec, bei deren Überschneiten der Experte die Arbeit abbricht

In dieser Form kann der Code in seinen Experten verwendet werden.

Der letzte Schritt - Nehmen alles in eine einzelne Funktion raus, was die Überprüfung betrifft. Das erleichtet ihre Intergration in Experten und vereinfacht ihre Verwendung.

/////////////////////////////////////////////////////////////////////////////////
// int _IsTradeAllowed( int MaxWaiting_sec = 30 )
//
// Die Funktion bestimmt den Trade-Context-Status.  Die zurückgelieferten Code: 
//  1 -  Der Trade Context ist frei, man kann handeln 
//  0 - Der Trade Context war besetzt, ist aber frei geworden.  Handeln darf man erst  
//      nach der Erneuerung der Marktinformation. 
// -1 - Der Trade Context ist besetzt, die Wartezeit wurde vom Benutzer abgebrochen ( Der Experte wurde von  
//      der Grafik gelöscht, der Terminal ist geschlossen,  die Periode und/oder das Symbol der Grafik haben sich geändert, ... )
// -2 - Der Trade Context ist besetzt, die maximale Wartezeit ist abgelaufen (MaxWaiting_sec).  
//      Möglicherweise ist dem Experte nicht erlaubt,  zu handeln (das Hacken "Live-Trading" 
//      in den Experteneinstellungen).
//
// MaxWaiting_sec - ist die Zeit (in Sekunden), während der die Funktion wartet  
// auf die Freigabe des Trade-Contexts (wenn er   besetzt ist).  Standardmäßig = 30. 
/////////////////////////////////////////////////////////////////////////////////
int _IsTradeAllowed(int MaxWaiting_sec = 30)
  {
    // Überprüfen, ob der Trade-Context frei ist
    if(!IsTradeAllowed())
      {
        int StartWaitingTime = GetTickCount();
        Print("Der Trade-Context ist besetzt! Warten, bis er frei wird...");
        // die endlose Loop 
        while(true)
          {
            // Wenn der Experte vom Benutzer gestoppt wurde, dann brechen die Arbeit (Vorgang) ab 
            if(IsStopped()) 
              { 
                Print("Der Experte wurde vom Benutzer gestoppt!"); 
                return(-1); 
              }
            // Wenn die Wartezeit länger dauert, als es in der Variable steht  
            // MaxWaiting_sec, Brechen die Arbeit ebenfalls ab
            if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
              {
                Print("Die Wartezeit ist überschnitten (" + MaxWaiting_sec + " sec.)!");
                return(-2);
              }
            // Wenn Der Trade Context frei geworden ist, 
            if(IsTradeAllowed())
              {
                Print("Der Trade Context ist frei!");
                return(0);
              }
            // Wenn die Loop nicht aus anderen Gründen unterbrochen wird, "warten" 0.1 s  
            // Und dann Starten die Überprüfung neu 
            Sleep(100);
          }
      }
    else
      {
        Print("Der Trade-Context ist frei!");
        return(1);
      }
  }

Das Muster des Experten, das die Funktion verwendet:

int start()
  {
    // Bestimmen, ob ein Markteintritt jetzt erfolgen sollte 
    ...
    // Berechnen die Stop Loss- und Take Profit-Levels und die Lot-Größe 
    ...
    // Überprüfen, ob der Trade-Context frei ist
    int TradeAllow = _IsTradeAllowed();
    if(TradeAllow < 0) 
      { 
        return(-1); 
      }
    if(TradeAllow == 0)
      {
        RefreshRates();
        // Berechnen die Stop Loss- und Take Profit-Levels
        ...
      }
    // Öffnen eine Position
    if(OrderSend(...) < 0) 
        Alert(" Fehler der Position-Öffnung № ", GetLastError()); 
    return(0);
  }
    Ziehen wir einige Schlüsse daraus:

Die Funktion IsTradeAllowed () ist einfach zu verwenden und passt ideal zur Differenzierung des Zugriffs auf den Trade-Context, während zwei oder drei Experten gleichzeitig arbeiten. Wegen einiger daraus resultierender Nachteile, schützt seine Verwendung nicht vor dem Fehler 146 , wenn viele Experten gleichzeitig arbeiten und es kann zum Absturz des Experten führen,wenn das Hacken "Live Trading zulassen" deaktiviert ist.

Aus diesem Grund betrachten wir eine alternative Lösung für dieses Problem - die Verwendung der globalen Variable als "Semaphor".

 

3. Die Globale Variablen des Client-Terminal

Zuerst die Definition:...

Die globalen Client-Terminal-Variablen sind Variablen, die für alle Experten, Skripts und Indikatoren zugänglich ist. Das bedeutet, eine globale Variable, die von einem Experte erstellt wurde, kann in einem anderen Experte verwendet werden (in unserem Fall, um Zugriffe zu verteilen)

Im MQL 4 stehen mehrere Funktionen zur Verfügung, um mit globalen Variablen zu arbeiten:

  • GlobalVariableCheck() - um zu prüfen, ob eine globale Variable existiert
  • GlobalVariableDel() - um eine globale Variable zu löschen
  • GlobalVariableGet () - um der Wert der globale Variable zu bekommen
  • GlobalVariableSet () - um eine globale Variable zu erstellen oder zu ändern
  • GlobalVariableSetOnCondition () - um der Wert (angegeben von einem Benutzer) einer globalen Variable durch einen anderen Wert zu ersetzen. Das heißt, der Unterschied zum GlobalVariableSet () besteht darin, dass der neue Wert nur unter einem bestimmten vorherigen Wert eingestellt wird. Es ist eben diese Funktion, die eine Schlüsselfunktion für die Erstellung des Semaphors ist.
  • GlobalVariablesDeleteAll() - um alle globale Variablen zu löschen (Ich kann mir nicht vorstellen, wer das gebrauchen kann:)

Warum muss die GlobalVariableSetOnCondition () verwendet werden, und nicht eine Kombination der Funktionen GlobalVariableGet () und GlobalVariableSet ()? Aus den gleichen Gründen: zwischen der Verwendung von 2 Funktionen kann einige Zeit vergehen. Und ein anderer Experte kann dann in den Umschaltungsprozess des Semaphors geraten. Das können wir aber nicht gebrauchen.

 

4. Das Grundkonzept des Semaphors

Der Experte, der handeln will, muss auch den Semaphore-Status überprüfen Wenn der Semaphore "Rotlicht" zeigt (die globale Variable = 1), bedeutet das, dass ein anderer Experte schon handelt, und man muss warten. Wenn es "grünes Licht" zeigt (die globale Variable = 0), kann man direkt handeln (aber nicht vergessen das "Rotlicht" für andere Experten festzulegen).

Also, wir müssen 2 Funktionen erstellen - eine für das "Rotlicht" und die andere für das "grüne Licht". Die Aufgabe ist auf den ersten Blick sehr einfach. Aber lass uns nicht gleich die Ergebnisse feststellen, und lieber versuchen wir den Ablauf von Aktionen für jede Funktion zu formulieren(lassen uns als Namen sie TradeIsBusy () und TradeIsNotBusy()) nennen und schließlich realisieren wir sie.

 

5. Die Funktion TradeIsBusy()

Wie es schon gesagt wurde, wird die Hauptaufgabe der Funktion warten, bis das "grüne Licht" erscheint, und das "Rotlicht" anmachen. Außerdem müssen wir prüfen, ob die globale Variable existiert und erstellen sie, im Falle, wenn Sie es nicht gibt. Diese Überprüfung wäre vernünftiger (und effizienter) durchführen, wenn die aus der Funktion init() des Experten erstellt wird. Aber dann könnte eine Wahrscheinlichkeit existieren, dass der Benutzer es löscht, und niemand von arbeitenden Experten in der Lage wäre, zu handeln. Deshalb werden wir sie im Körper der erstellten Funktion platzieren.

    All diese Aktionen sollen mit Informationsergebnissen und mit der Bearbeitung der Fehler betreut werden, die während der Arbeit mit der globalen Variablen aufgetreten sind. Zudem darf man nicht über "Hängen bleiben" vergessen - die Arbeitszeit der Funktion muss begrenzt sein.

Das ist, was wir eigentlich bekommen müssen:

/////////////////////////////////////////////////////////////////////////////////
// int TradeIsBusy( int MaxWaiting_sec = 30 )
//
// Die Funktion ändert den Wert der globalen TradeIsBusy von 0 um 1. 
// Wenn es beim Start TradeIsBusy = 1 ist, dann wartet die Funktion, bevor TradeIsBusy = 0 wird,  
// Und erst dann ändert es sich. 
// Falls die globale Variable TradeIsBusy nicht gibt, die Funktion erstellt sie.
// Die zurückgelieferte Code: 
//  1 - erfolgreich abgeschlossen. Die globale Variable TradeIsBusy wurde mit dem Wert 1 zugeordnet.
// -1 - Im Moment des Startes der Funktion TradeIsBusy = 1, die Wartezeit wurde vom Benutzer abgebrochen 
//      (Der Experte wurde von der Grafik gelöscht,  der Terminal wurde geschlossen, die Periode und/oder das Symbol der Grafik hat sich geändert     
//       Grafik, ... ) 
// -2 - Im Moment des Startes der Funktion TradeIsBusy = 1, ist die maximale Wartezeit abgelaufen//
//      (MaxWaiting_sec)
/////////////////////////////////////////////////////////////////////////////////
int TradeIsBusy( int MaxWaiting_sec = 30 )
  {
    // wenn während des Testes keinen Sinn gibt, den Traid-Context zu teilen, einfach Beenden  
    // die Arbeit der Funktion 
    if(IsTesting()) 
        return(1);
    int _GetLastError = 0, StartWaitingTime = GetTickCount();
    //+--------------------------------------------------------------------------------------+
    //| Überprüfen, ob die Hauptvariable gibt  und wenn sie es nicht gibt, erstellen wir sie |
    //+--------------------------------------------------------------------------------------+
    while(true)
      {
        // Wenn der Experte vom Benutzer gestoppt wurde, dann brechen die Arbeit (Vorgang) ab 
        if(IsStopped()) 
          { 
            Print("Der Experte wurde vom Benutzer gestoppt!"); 
            return(-1); 
          }
        // Wenn die Wartezeit länger dauert, als es in der Variable steht  
        // MaxWaiting_sec, Brechen die Arbeit ebenfalls ab
        if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
          {
            Print("Die Wartezeit ist überschnitten (" + MaxWaiting_sec + " sec.)!");
            return(-2);
          }
        Überprüfen, ob die Hauptvariable gibt//  
        // Wenn sie es gibt, Verlassen die Loop und gehen zum Block Wechseln  
        // der Wert der globalen TradeIsBusy  
        if(GlobalVariableCheck( "TradeIsBusy" )) 
            break;
        else
        // wenn GlobalVariableCheck FALSE zurückliefert, bedeutet dies, dass es keine Variable gibt, oder  
        // ein Fehler ist während der Überprüfung aufgetreten 
          {
            _GetLastError = GetLastError();
            // Wenn es schließlich ein Fehler ist, Fordern die Information, Warten 0,1 Sekunden und  
            // Starten die Überprüfung neu 
            if(_GetLastError != 0)
             {
              Print("TradeIsBusy()-GlobalVariableCheck(\"TradeIsBusy\")-Error #",
                    _GetLastError );
              Sleep(100);
              continue;
             }
          }
        // Wenn es keinen Fehler gibt, bedeutet dies, dass es keine globale Variable gibt, Versuchen Sie zu erstellen 
        
        // Wenn GlobalVariableSet > 0 ist, bedeutet dies, dass die globale Variable schon erstellt ist.  
        // Verlassen die Funktion 
        if(GlobalVariableSet( "TradeIsBusy", 1.0 ) > 0 ) 
            return(1);
        else
        // Wenn GlobalVariableSet den Wert <= 0 zurückgeliefert hat, bedeutet dies, dass während der Erstellung  
        // der Variable ein Fehler aufgetreten ist 
         {
          _GetLastError = GetLastError();
          // Liefern die Information zurück, Warten 0,1 Sekunden und versuchen es neu. 
          if(_GetLastError != 0)
            {
              Print("TradeIsBusy()-GlobalVariableSet(\"TradeIsBusy\",0.0 )-Error #",
                    _GetLastError );
              Sleep(100);
              continue;
            }
         }
      }
    //+-------------------------------------------------------------------------------------------------+
    //| Wenn die Erstellung der Funktion bisher gekommen ist, dann gibt es schon die globale Variable.  |  
    //| Warten, solange TradeIsBusy = 0 wird und Ändern den Wert der TradeIsBusy von 0 um 1.            | 
    //+-------------------------------------------------------------------------------------------------+
    while(true)
     {
     // Wenn der Experte vom Benutzer gestoppt wurde, dann brechen die Arbeit (Vorgang) ab 
     if(IsStopped()) 
       { 
         Print("Der Experte wurde vom Benutzer gestoppt!"); 
         return(-1); 
       }
     // Wenn die Wartezeit länger dauert, als es in der Variable steht  
     // MaxWaiting_sec, Brechen die Arbeit ebenfalls ab
     if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)
       {
         Print("Die Wartezeit ist überschnitten (" + MaxWaiting_sec + " sec.)!");
         return(-2);
       }
     // Versuchen den Wert der TradeIsBusy von 0 um 1 zu ändern 
     // wenn es nicht klappt, Verlassen die Funktion und Liefern 1 zurück - "Erfolgreiches Ende"  
     if(GlobalVariableSetOnCondition( "TradeIsBusy", 1.0, 0.0 )) 
         return(1);
     else
     // Wenn's nicht, dann können 2 Gründe sein: TradeIsBusy = 1 (dann muss man warten), oder 
     // ein Fehler ist aufgetreten (das überprüfen wir) 
      {
      _GetLastError = GetLastError();
      // Wenn es schließlich ein Fehler ist, Fordern die Information und versuchen es noch mal 
      if(_GetLastError != 0)
      {
   Print("TradeIsBusy()-GlobalVariableSetOnCondition(\"TradeIsBusy\",1.0,0.0 )-Error #",
         _GetLastError );
       continue;
      }
     }
     // Wenn es keinen Fehler gibt, bedeutet dies, dass TradeIsBusy = 1 ist (der andere Experte handelt schon) -  Liefern die Information zurück   
     // und Warten...
     Comment("Warten, solange der andere Experte das Handeln beendet...");
     Sleep(1000);
     Comment("");
    }
  }

Es scheint hier, alles klar zu sein:

  • Überprüfen, ob die globale Variable gibt, und falls nicht, dann Erstellen sie
  • Der Versuch, den Wert der globalen Variablen von 0 um 1 zu ändern. Das funktioniert nur dann, wenn ihr Wert = 0 wird.

Die Funktion kann maximal MaxWaiting_sec Sekunden funktionieren und verhindert nicht die Löschung des Experten von der Grafik.
Die Information über alle aufgetretenen Fehler wird im Verlauf.

 

6 Die Funktion TradeIsNotBusy()

Die Funktion IsTradeIsNotBusy löst die zurückgegebene Aufgabe - und schaltet "grünes Licht" an.

Sie hat keine Zeitgrenzen und kann nicht vom Benutzer gestoppt werden. Die Motivation ist einfach: Wenn das "grünes Licht" ausgeschaltet ist, ist kein Experte in der Lage, zu handeln.

Selbstverständlich hat sie auch keine zurückgelieferten Codes - Das Ergebnis dazu kann nur ein erfolgreicher Abschluss

So sieht sie aus:

/////////////////////////////////////////////////////////////////////////////////
// void TradeIsNotBusy()
//
// Die Funktion erstellt den Wert der globalen Variable TradeIsBusy = 0.
// Falls die globale Variable TradeIsBusy nicht gibt, die Funktion erstellt sie.
/////////////////////////////////////////////////////////////////////////////////
void TradeIsNotBusy()
  {
    int _GetLastError;
    // wenn während des Testes keinen Sinn gibt, den Traid-Context zu teilen, einfach Beenden  
    // die Arbeit der Funktion 
    if(IsTesting()) 
      { 
        return(0); 
      }
    while(true)
      {
        // Wenn der Experte vom Benutzer gestoppt wurde, dann brechen die Arbeit (Vorgang) ab 
        if(IsStopped()) 
          { 
            Print("Der Experte wurde vom Benutzer gestoppt!"); 
            return(-1); 
          }
        // Versuchen den Wert der Hauptvariable um = 0 zu erstellen.  (oder erstellen die Hauptvariable) 
        // wenn GlobalVariableSet den Wert > 0 zurückgeliefert hat, bedeutet dies, dass alles gut beendet wurde.  
        // Verlassen die Funktion 
        if(GlobalVariableSet( "TradeIsBusy", 0.0 ) > 0) 
            return(1);
        else
        // wenn GlobalVariableSet den Wert <= 0 zurückgeliefert hat, bedeutet dies, dass ein Fehler aufgetreten ist.  
        // Liefern die Information zurück, Warten, und vesuchen es noch mal// 
         {
         _GetLastError = GetLastError();
         if(_GetLastError != 0 )
           Print("TradeIsNotBusy()-GlobalVariableSet(\"TradeIsBusy\",0.0)-Error #", 
                 _GetLastError );
         }
        Sleep(100);
      }
  }

7. Die Integration in Experten und in der Verwendung

Nun haben wir 3 Funktionen zur Differenzierung des Zugriffs auf den Trade-Context. Um ihre Integration in den Experten zu vereinfachen, kann man die Datei TradeContext.mq4 erstellen und die mit der # include-Direktive (Im Anhang) aktivieren.

Das Muster des Experten, das die Funktionen TradeIsBusy() und TradeIsNotBusy()verwendet:

#include <TradeContext.mq4>
 
int start()
  {
    // Bestimmen, ob ein Markteintritt jetzt erfolgen sollte 
    ...
    // Berechnen die Stop Loss- und Take Profit-Levels und die Lot-Größe 
    ...
    // Warten auf die Freigabe des Trade-Context und besetzen ihn (wenn ein Fehler aufgetreten ist,  
    // Verlassen) 
    if(TradeIsBusy() < 0) 
        return(-1); 
    // Erneuern die Marktinformation 
    RefreshRates();
    // Berechnen die Stop Loss- und Take Profit-Levels
    ...
    // Öffnen eine Position
    if(OrderSend(...) < 0) 
      { 
        Alert(" Fehler der Position-Öffnung № ", GetLastError());  
      }

    // Entleeren den Trade-Context 
    TradeIsNotBusy();

    return(0);
  }
 

Bei der Verwendung der Funktion TradeIsBusy () und TradeIsNotBusy () kann nur ein Problem auftreten - Wenn es nachdem als der Tade-Context besetzt wird, den Experte von der Grafik löschen, dann wird die Variable TradeIsBusy gleich 1 bleiben. Andere Experte dürfen danach nicht handeln.

Das Problem kann leicht gelöst werden: Der Experte soll nicht von der Grafik gelöscht werden , wenn er noch handelt;)

  Es ist auch die Situation möglich, dass die Variable TradeIsBusy bei einem Notabsturz nicht genullt wird. In diesem Fall hilft die Funktion TradeIsNotBusy () aus der Funktion init() des Experten .

Und natürlich, kann der Wert der Variable jederzeit manuell geändert werden - F3-Taste im Terminal (es ist eine undokumentierte Möglichkeit, allen Experten das Handel zu deaktivieren ;)


komposter (komposterius@mail.ru), 2006.04.11

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

Beigefügte Dateien |
TradeContext.mqh (26.11 KB)
Besonderheiten und Einschränkungen beim Testen von Handelstrategien in MetaTrader 4 Besonderheiten und Einschränkungen beim Testen von Handelstrategien in MetaTrader 4

Dieser Artikel erläutert Besonderheiten und Einschränkungen beim Testen von Handelsstrategien in MetaTrader 4...

Strategy Tester: Modellierungsmodi beim Testen von Handelsstrategien Strategy Tester: Modellierungsmodi beim Testen von Handelsstrategien

Viele Programme der technischen Analyse lassen Handelsstrategien anhand historischer Daten testen.

Das Beispiel einer Experteneinstellung Das Beispiel einer Experteneinstellung

Die Grundlagen der Programmierung der Programmierungssprache-MQL4 werden am Beispiel der Erstellung eines einfachen Experten-Advisor-Systems durch den Standard-Indikator-MACD betrachtet.

Die Einschätzung der Modellierungsqualität von Minutendaten Die Einschätzung der Modellierungsqualität von Minutendaten

Die Formel der Einschätzung und der Berechnung der Modellierungsqualität von Minutendaten.