Schleifen und Schließen oder Löschen von Aufträgen - Seite 5

 
Eleni Anna Branou:

Bitte verwenden Sie die Schaltfläche </>, um Ihren Code einzufügen.


Meine Entschuldigung... Hier ist es im richtigen Format...

OrdersTotal() nicht korrekt...

Ich war überrascht, dass eine Schleifencode-Sequenz, die OrdersTotal() verwendet, keine korrekten Ergebnisse liefert (beobachtet bei zwei verschiedenen Brokern).

Ich verwende MT4 Version 1090 auf einem Linux Ubuntu-MATE 16.04 Desktop, auf dem WINE 3.0 läuft.

Hier ist, was ich verwendet habe...

Hier ist es:

for(int cc = 0; cc < OrdersTotal(); cc++)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);

Ich habe bei zwei verschiedenen Brokern festgestellt, dass der Wert von OrdersTotal() nicht immer mit dem übereinstimmt, was auf der Registerkarte 'Trade' des MT4-Brokers angezeigt wird. Zunächst dachte ich, dass es am Broker liegt, dass OrdersTotal() nicht richtig funktioniert. Als ich es beim zweiten Broker bemerkte, begann ich mich zu fragen, ob MT4 ein internes 'Problem' hat, oder ob mein Code falsch ist ODER ob dies ein Problem mit der korrekten Synchronisierung von MT4 mit dem Server.... ist?

Nachdem ich diesen Forumsthread gelesen habe, frage ich mich, ob ich bessere Ergebnisse erzielen würde, wenn ich die for..-Schleife so ändern würde, dass sie lautet:

for(int cc = OrdersTotal() - 1; cc >= 0; cc--)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);
ODER gibt es ein Flag oder eine Codezeile, die sicherstellt, dass OrdersTotal() während eines OnTick()-Ereignisses korrekt synchronisiert wird?

Jede Klärung in Bezug auf diese wäre sehr hilfreich und würde sehr geschätzt werden!

 
Simon Gniadkowski:

Dies ist einer der häufigsten Fehler, die ich sehe, wahrscheinlich zum Teil auf die wie Müll wie Expert Advisor Builder. So dachte ich, es war Zeit für einen Thread zu diesem Thema gewidmet, so dass es für zukünftige Referenz verlinkt werden kann.

Das Problem

Nehmen wir ein einfaches Beispiel; wir wollen eine Funktion, um alle offenen Aufträge für unsere EA zu schließen, gibt es viele Beispiele, aber lassen Sie uns eine von Grund auf neu erstellen.

Wir brauchen eine Schleife, weil wir alle unsere Aufträge für einen bestimmten EA schließen wollen. Innerhalb dieser Schleife haben wir Code, um den Auftrag auszuwählen, Code, um zu prüfen, ob es das richtige Symbol und die richtige magische Zahl ist, und schließlich Code, um den Auftrag zu schließen:

Dieser Code ist schlecht . . . VERWENDEN SIE IHN NICHT. . . Ich werde im nächsten Abschnitt erklären, warum...

Die Erläuterung

Gehen wir den obigen Code durch, Zeile für Zeile, Auftrag für Auftrag...

Nehmen wir an, wir haben die folgenden Aufträge, die wir schließen wollen. Sie haben alle die gleiche magische Zahl und das gleiche Symbol wie unser EA, also soll unser Code sie alle schließen:

Position Ticket-Nummer
0111
1222
2 333
3444
4555

Erster Durchlauf durch die Schleife:

Der Anfangswert von PositionIndex ist 0, so dass der Auftrag an Position 0 ausgewählt wird, Ticketnummer 111, dieser Auftrag wird erfolgreich gelöscht und die verbleibenden Aufträge ändern ihre Position wie folgt:

Position Ticket-Nummer
0222
1 333
2444
3555

Zweiter Durchlauf durch die Schleife:

Der Wert von PositionIndex ist jetzt 1, so dass der Auftrag an Position 1 ausgewählt wird, Ticketnummer 333, dieser Auftrag wird erfolgreich gelöscht und die verbleibenden Aufträge ändern ihre Position wie folgt:

Position Ticket-Nummer
0222
1 444
2555

3. Durchlauf durch die Schleife:

Jetzt istder Wert von PositionIndex 2, so dass der Auftrag an Position 2 ausgewählt wird, Ticketnummer 555, dieser Auftrag wird erfolgreich gelöscht und die verbleibenden Aufträge ändern ihre Position wie folgt:

Position Ticket-Nummer
0222
1 444

4. Durchlauf durch die Schleife:

jetzt ist der Wert von PositionIndex 3 OrderSelect() versucht, die Order an Position 3 auszuwählen und scheitert, der continue nimmt die Ausführung des Codes zum nächsten Wert in der Schleife . .


5. und letzter Durchlauf durch die Schleife:

jetzt ist der Wert von PositionIndex gleich 4 OrderSelect() versucht, die Order an Position 4 auszuwählen und schlägt fehl, der Continue führt den Code zum nächsten Wert in der Schleife aus . . . die Schleife ist beendet.


Wir haben jetzt noch 2 Aufträge, die Tickets 222 und 444, die eigentlich hätten abgeschlossen werden müssen, es aber nicht wurden ... und nun die Frage, wie man dieses Problem lösen kann.

Die Lösung

Der folgende Code ist die korrekte Vorgehensweise, wenn offene Aufträge geschlossen oder schwebende Aufträge gelöscht werden sollen.

Der wesentliche Unterschied besteht darin, dass die Schleife von ( TotalNumberOfOrders - 1 ) auf 0 dekrementiert

Gehen wir noch einmal den obigen Code durch - Zeile für Zeile, Auftrag für Auftrag.

Wir haben die gleichen Aufträge wie zuvor:

Position Ticket-Nummer
0111
1222
2333
3444
4555

1. Durchlauf durch die Schleife:

Der Anfangswert von PositionIndex ist TotalNumberOfOrders - 1, was gleich 5 - 1 = 4 ist, also wird der Auftrag an Position 4 ausgewählt, Ticketnummer 555, dieser Auftrag wird erfolgreich gelöscht und die verbleibenden Aufträge ändern ihre Position wie folgt:

Position Ticket-Nummer
0111
1222
2333
3444

Zweiter Durchlauf durch die Schleife:

Der Wert von PositionIndex ist jetzt 3, also wird die Bestellung an Position 3 ausgewählt, Ticketnummer 444, diese Bestellung wird erfolgreich gelöscht und die verbleibenden Bestellungen ändern ihre Position wie folgt:

Position Ticket-Nummer
0111
1222
2333

3. Durchlauf durch die Schleife:

Der Wert von PositionIndex istjetzt 2, so dass der Auftrag an Position 2 ausgewählt wird, Ticketnummer 333, dieser Auftrag wird erfolgreich gelöscht und die verbleibenden Aufträge ändern ihre Position wie folgt:

Position Ticket-Nummer
0111
1222

4. Durchlauf durch die Schleife:

Der Wert von PositionIndex istjetzt 1 , so dass der Auftrag an Position 1 ausgewählt wird, Ticketnummer 222, dieser Auftrag wird erfolgreich gelöscht und die verbleibenden Aufträge ändern ihre Position wie folgt:

Position Ticket-Nummer
0111

5. und letzter Durchlauf durch die Schleife:

jetzt ist der Wert von PositionIndex 0 also wird der Auftrag an Position 0 ausgewählt, Ticketnummer 111, dieser Auftrag wird erfolgreich gelöscht, Wert 0 ist der letzte gültige Wert für die Schleife ... die Schleife ist beendet.

Wir haben alle übereinstimmenden Aufträge erfolgreich gelöscht...

Link zu diesem Thema: Schleifen und Schließen oder Löschen von Aufträgen

Vielen Dank! Das ist eine sehr klare Erklärung.
 
Hallo Programmierer,
Ich habe mir diesen Thread durchgelesen, in dem es um die Auftragsauswahl geht. Ich habe tatsächlich einen Code, bei dem ich glaube, alles richtig gemacht zu haben, aber die Auswahl funktioniert bei mir nicht, da ich den OpenPrice desausgewählten Auftragsnicht lesen kann. Alles andere funktioniert gut, nur dieser Teil des Codes nicht. Ich bin mir nicht sicher, warum.
Der gesamte Code hat 4 Abschnitte, in denen ich den OrderOpenPrice aufrufen muss, nachdem die Bestellung gesendet wurde... OrderSend funktioniert gut, OrderSelect liefert mir nicht die gewünschten Ergebnisse. Verweisen Sie auf 1 Abschnitt des Codes, wenn Sie helfen können.
Vielen Dank!
 if(Protection_Step_One==1)
        {
        while(Protective_Order<0)
          {
          RefreshRates();
          Protective_Order=OrderSend(Symbol(),OP_SELL,Protective_Lots,NormalizeDouble(MarketInfo(Symbol(),MODE_BID),MarketInfo(Symbol(),MODE_DIGITS)),3,0,0,"Intermediary",MN_Sell_Intermediary_Protection,0,Cyan);
          }
  //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Addition for Clamp       
          for (int i=OrdersTotal()-1; i>=0; i--)
            {if(OrderSelect(i,SELECT_BY_POS, MODE_TRADES)==true)
               {if (OrderMagicNumber()==MN_Sell_Intermediary_Protection)
                  { RefreshRates();
                  Intermediary_OpenPrice_Sell= OrderOpenPrice();
                  }
                }
             }   
               //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>..
        if(Protective_Order!=-1)
          { 
          Protection_Step_One=0;
          RealTime_Drawing=2;
          Protective_Mode_Activated=1;
          Protective_Order=-2;
          Defcon=2;

 

Vielen Dank, lieberSimon Gniadkowski,

Ihr Beitrag hat mir wirklich Zeit erspart.

 
Gelson Kasonia:
void OnStart()
{
     int Protective_Order=OrderSend(_Symbol,ORDER_TYPE_BUY,0.01,Ask,3,0,0,"Intermediary");
     if(Protective_Order<0)
          return;
     if(!OrderSelect(Protective_Order,SELECT_BY_TICKET, MODE_TRADES))
          return;
     Print(Protective_Order, " OrderOpenPrice: ", OrderOpenPrice());
}
 

Dies ist der Code, den ich für das Schließen von Marktaufträgen vorschlage

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersBackward()
  {
   for(int i=OrdersTotal()-1; i>=0 && !IsStopped(); i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(!OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))

            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
        }
     }
  }

Und ich schlage vor, dass dies der korrekte Weg ist, wenn eine Forward-for-Schleife verwendet wird (um den FIFO-Regeln der US-Broker zu entsprechen)

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersForward()
  {
   for(int i=0; i<OrdersTotal() && !IsStopped(); i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))
           {
            i--;
           }
         else
           {
            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
           }
        }
     }
  }

In der Vorwärtsschleife,

  1. Die Funktion OrderTotal() wird innerhalb der for-Schleife verwendet, um die verbleibende Anzahl der offenen Aufträge bei jeder Schleifeniteration zu aktualisieren, um zu vermeiden, dass der Index außerhalb des Arraybereichs liegt.
  2. Der Index i wird bei jedem abgeschlossenen Auftrag dekrementiert, um zu vermeiden, dass einige Aufträge übersprungen werden.
 
amrali: Der Index i wird bei jedem abgeschlossenen Auftrag dekrementiert, um zu vermeiden, dass einige Aufträge übersprungen werden.
Bei mehreren Aufträgen (ein EA, mehrere Charts, mehrere EAs, manueller Handel) können während des Wartens auf den Abschluss des aktuellen Vorgangs (Schließen, Löschen, Ändern) eine beliebige Anzahl anderer Vorgänge an anderen Aufträgen gleichzeitig stattfinden und die Positionsindizierung ändern:
  1. Bei Nicht-FIFO-Brokern (US-Brokern)(oder wenn der EA nur eine Order pro Symbol öffnet) können Sie einfach in einer Positionsschleife rückwärts zählen, und Sie werden keine Order verpassen. Machen Sie es sich zur Gewohnheit, immer rückwärts zu zählen.
    Schleifen und Schließen oder Löschen von Orders - MQL4 Programmierforum
    Für FIFO (US-Broker)und wenn Sie (möglicherweise) mehrere Orders pro Symbol verarbeiten, müssen Sie die früheste Order finden, sie schließen und bei einer erfolgreichen Operation alle verbleibenden Positionen erneut verarbeiten.
    CloseOrders durch FIFO Regeln - Strategy Tester - MQL4 Programmierforum - Seite 2 #16

  2. und überprüfen Sie OrderSelect, falls frühere Positionen gelöscht wurden.
    Was sind die Rückgabewerte der Funktion ? Wie verwende ich sie? - MQL4-Programmierforum
    Häufige Fehler in MQL4-Programmen und wie man sie vermeidet - MQL4 Artikel
  3. und wenn Sie (potenziell) mehrere Aufträge verarbeiten, müssen SieRefreshRates() nach Serveraufrufen aufrufen, wenn Sie beim nächsten Auftrag/Serveraufruf die vordefinierten Variablen(Bid/Ask) oder (richtungsunabhängig) OrderClosePrice() verwenden möchten.
 

Sie werden wissen, wie sehr mir das geholfen hat. Nicht nur mit dem Code, an dem ich gearbeitet habe, sondern mit meinem gesamten Verständnis. Es funktioniert jetzt perfekt und ich habe das Verständnis, um es auf verschiedene Weise zu implementieren.

Ich bin wirklich sehr dankbar für diese Informationen.