Zum Inhalt springen
View in the app

A better way to browse. Learn more.

#T/N/X/T

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Anzahl offener Trades begrenzen - Hilfe benötigt!

Geschrieben

Moin Leute,

 

ich verzeifel so langsam. Es ist also folgende Situation: ich möchte zu Handelsbeginn einen Trade eröffnen. Je nach Situation ist dass dann long oder short. Danach soll überprüft werden, ob die Anzahl der maximalen Trades überschritten ist. Wenn ja, soll der älteste gelöscht werden. Im Backtest funktioniert das einwandfrei. In der Praxis schafft er es jedoch nicht, den Trade zu schließen. Dabei dachte ich, ich hätte schon genug Schleifen eingebaut. Eventuell kann ja jemand helfen. Danke vorab :correct:.

 

Hier der verkürzte Code (nur die short Seite):

 

datetime today,prevday;
today = iTime(NULL,PERIOD_D1,0);
int MaxShortOrders = 3;

if (today>prevday) OpenTrade(Symbol(), OP_SELL, Lots, Ask, Slippage, 0, 0, "Sell(#" + MagicNumber + ")", MagicNumber, 0, CLR_NONE);

        for (k = Total; k >= 0; k--) {
           OrderSelect(k, SELECT_BY_POS, MODE_TRADES);
           if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) {
                 if (OrderType()==OP_SELL) OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()+StopLoss, OrderOpenPrice()-TPs, 0, CLR_NONE);          
                 Sleep(2000);
                 OldOrderClose (MagicNumber, MaxLongOrders, MaxShortOrders);                
           }
        } 

[...]

//Close oldest Order
int OldOrderClose (int MagicNumber, int MaxLongOrders, int MaxShortOrders) {
  int i, j, OldestOrder=2147483646, ShortTradesThisEA = 0, loopcount=0;
  datetime OldestOpenTime=2147483646;
  
  // Orders zählen
  for (i=OrdersTotal(); i>=0; i--) {
     if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
        if (OrderMagicNumber() == MagicNumber && OrderType()==OP_SELL) ShortTradesThisEA++;
     }
  }

  if ((ShortTradesThisEA <= MaxShortOrders)) prevday = today;
  
  if (ShortTradesThisEA > MaxShortOrders) {
     for (j=OrdersTotal(); j>=0; j--)
     {
     if (OrderSelect(j, SELECT_BY_POS, MODE_TRADES)) {
        if (OrderMagicNumber() == MagicNumber && OrderType()==OP_SELL) {
              if (OrderOpenTime() < OldestOpenTime) {
                 OldestOrder = OrderTicket();
                 OldestOpenTime = OrderOpenTime();
              }
        }
     }
     }   
     if (OrderSelect(OldestOrder, SELECT_BY_TICKET)) {
        if (OrderType()==OP_SELL){
           int STicket=OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, CLR_NONE);
              while(STicket == -1) {
                 Sleep(1000);
                 loopcount++;
                 if(loopcount > 100) break;
                 STicket=OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, CLR_NONE);
             }          
        prevday = today;
        }     
     }   
  }     
}

Featured Replies

Geschrieben

Hallo,

 

ich vermute, dass es an dem Bid-Kurs liegt, den du beim Close übergibst.

 

Da Sell-Positionen immer zum Ask-Kurs geschlossen werden, müßtest du mal statt Bid Ask im OrderClose verwenden.

 

Ansonsten muss natürlich noch sichergestellt sein, dass alle Positionen die du in dem EA öffnest und verwaltest das gleiche OrderSymbol haben. Wenn nicht, dann dürftest du nicht Bid und Ask verwenden sondern müßtest dir die aktuellen Kurse mit MarketInfo holen.

 

Wenn das alles nicht weiterhilt, solltest du nach jeder Funktion LastError (und ErrorDescription) auswerten, um einen Hinweis auf den Fehler zu bekommen.

 

vg

Geschrieben
  • Autor

ich vermute, dass es an dem Bid-Kurs liegt, den du beim Close übergibst.

Oh, wie peinlich. Gleiches gilt natürlich auch für die Ordereröffnung. Da ist es nur nicht aufgefallen, weil ich mir in einer Schleife nochmal die Kurse hole und es dort richtig zugewiesen ist. Vielen Dank für den Hinweis. Weiß auch nicht, in welchem Rausch ich das falsch eingebaut habe...

Geschrieben

Mahlzeit...

 

nur mal so als Frage von mir:

 

Wir sprechen hier schon von mql4,oder? Denn entweder habe ich den einen oder anderen Rotwein zuviel drin, oder ich kappier das mit den einen oder anderen Variablen nichtmehr... :stars:

 

lg NC

 

Edit: :stars:

Geschrieben
  • Autor

Wir sprechen hier schon von mql4,oder?

Ja, ist MQL für den MT4. Bei Fragen zu den Variablen einfach fragen :wink:.

Geschrieben

Hast du dein Probelm schon gelöst?

 

Einen kleinen Fehler hast du übrigens noch beim Durclaufen aller Orders. Die höchste Ordernummer ist immer "OrdersTotal()-1" weil die Zählung ja bei 0 beginnt. Müßtest du also in den for-Schleifen bei dem Startwert berücksichtigen.

 

Dieser Fehler dürfte zwar nichts mit dem eigentlichen Problem zu tun haben, aber sollte man trotzdem beachten.

Geschrieben
  • Autor

Hast du dein Probelm schon gelöst?

 

Einen kleinen Fehler hast du übrigens noch beim Durclaufen aller Orders. Die höchste Ordernummer ist immer "OrdersTotal()-1" weil die Zählung ja bei 0 beginnt. Müßtest du also in den for-Schleifen bei dem Startwert berücksichtigen.

 

Dieser Fehler dürfte zwar nichts mit dem eigentlichen Problem zu tun haben, aber sollte man trotzdem beachten.

Das zeigt ja erst der Alltag - bin aber optimistisch. Im Backtest funktionierte es ja. Gleiches gilt im übrigen für das OrdersTotal. Meinst Du wirklich, dass es ein "schlimmer" Fehler ist? Ansonsten läuft er ja einfach nur die Schleife 1x mehr durch, oder sehe ich das falsch?

 

Update

Habe das mal mit dem -1 eingebaut. Das scheint dann eher fehlerhaft zu sein. So wie es ist, ist es also anscheinend richtig. Ist ja auch logisch. Wenn nur noch eine Order vorhanden ist, ist OrdersTotal eben 1 und nicht 0. Wenn ich bei also 1-1 machen würde, würde er die Schleife nicht mehr durchlaufen. Die Ordernummer ist irrelevant, nur die Anzahl ist wichtig.

Geschrieben

Meinst Du wirklich, dass es ein "schlimmer" Fehler ist?

 

Nein, hatte ich ja schon geschrieben ist nur ein Schönheitsfehler. Kann aber unter Umständen an anderen Stellen zu Fehlern führen.Deshalb sollte man natürlich möglichst jeden noch so kleinen Fehler vermeiden.

 

Habe das mal mit dem -1 eingebaut. Das scheint dann eher fehlerhaft zu sein.

 

Das kann eigentlich nicht sein, dann hast du vielleicht noch einen anderen Fehler gemacht.

 

Wenn nur noch eine Order vorhanden ist, ist OrdersTotal eben 1 und nicht 0. Wenn ich bei also 1-1 machen würde, würde er die Schleife nicht mehr durchlaufen. Die Ordernummer ist irrelevant, nur die Anzahl ist wichtig.

 

Das stimmt nicht, wenn OrdersToral() == 1 ist, dann wird die Schleife dann trotzdem einmal durchlaufen. Eine korrekte For-Schelife würde so aussehen:

 

for (j=OrdersTotal()-1; j>=0; j--) 
{
...
}

Geschrieben
  • Autor
Wie sehen das die anderen Profis denn hier? Ich weiß zumindest, dass er das bei mir richtig macht, wenn ich aber das mit -1 mache eben nicht.
Geschrieben

Wie sehen das die anderen Profis denn hier? Ich weiß zumindest, dass er das bei mir richtig macht, wenn ich aber das mit -1 mache eben nicht.

nochmal langsam: es soll maximal 3 Orders offen sein, es wird immer wieder eine neue aufgemacht und wenn die 4. aufgemacht wird soll die 1. geschlossen werden (wodurch die 2. zur 1. wird etc) ?

 

Was meinst du mit "er schafft es nicht den Trade zu schliessen?" Im Sinn von er tuts nicht (auch kein Hinweis im Log) oder im Sinn von er versuchts, kriegt aber Errors?

Wenn zweites: welche Errors?

 

noch was: warum checkst du das closeOld in jedem Schleifendurchlauf? Wennst viele Orders offen hast, machst du unmengen sinnlose Berechnungen...

Du koenntest vermutlich alle for schleifen in eine zusammenpacken und ein bissl performance erhoehen, aber bei 3 Orders is es eh nit schlimm und als Informatiker muss man sagen es is eh asymptotisch gleich (solang du das staendige OldClose aus der Schleife rausziehst ;)

 

zum OrdersTotal: da wir bei 0 zu zaehlen beginnen, ist das -1 richtig. Du zaehlst ja auch bis 0 (in deinem Fall von oben runter).

Bsp OrdersTotal() == 1:

deine Schleife startet mit j= 1, dann kommt j= 0 (weil 0 >= 0) und dann is aus. Du schaust dir also 2 Orders an, obwohl es nur eine Order gibt...

 

wenn es X Orders gibt, dann haben sie die Nummern 0,...,(X-1) deswegen bis OrdersTotal() - 1.

 

EDIT: Tests einfach mal: wenn j == OrdersTotal() ist, sollte OrderSelect(j,...) false liefern. In deinem fall ignoriert die Schleife also den falschen Index einfach.

 

EDIT2: nur sicherheitshalber: Das "Total" im Code is im Original schon ein OrdersTotal() oder?

 

HTH

Geschrieben

Das mit dem -1 bei OrdersTotal() ist zwar richtig, stört aber nicht, da du bei der if-Abfrage

if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {

im ersten Durchlauf sowieso ein "false" bekommst und die folgende Anweisung sowieso überspringst.

 

Außer dem schon erwähnten Bid beim Schließen der Short Position seh ich jetzt auf dem ersten Blick auch nichts, warum die älteste Position mit diesem Code nicht geschlossen werden sollte.

Wenn es aber weiterhin nicht funktioniert, dann würd ich mir ein paar Debug-Prints einbauen um die jeweiligen Variablenwerte kontrollieren zu können.

Sonst wird die Suche recht mühsam.

Geschrieben
  • Autor

EDIT2: nur sicherheitshalber: Das "Total" im Code is im Original schon ein OrdersTotal() oder?

Ja, ist nur eine Variable - ich könnte auch OrdersTotal() schreiben.

 

Nun nochmal zu dem -1. Ich verstehe eure Argumentation und sie erschließt sich mir auch. Das einzige, was dagegen spricht sind die Ergebnisse des Backtests. Aber auch das werde ich raus finden :wink:.

 

Habe es mal blöckeweise probiert. Die Verzerrung tritt auf, wenn ich es im folgenden Block ändere. Kann es daran liegen, dass in ihm erneut eine Schleife (durch die Funktion OldOrderClose, siehe Posting #1) aufgerufen wird?

 

        for (k = Total; k >= 0; k--) {
           OrderSelect(k, SELECT_BY_POS, MODE_TRADES);
           if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) {
                 if (OrderType()==OP_SELL) OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()+StopLoss, OrderOpenPrice()-TPs, 0, CLR_NONE);
                 if (OrderType()==OP_BUY) OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()-StopLoss, OrderOpenPrice()+TPl, 0, CLR_NONE);          
                 Sleep(2000);
                 OldOrderClose (MagicNumber, MaxLongOrders, MaxShortOrders);                
           }
        } 

Geschrieben
  • Autor

nochmal langsam: es soll maximal 3 Orders offen sein, es wird immer wieder eine neue aufgemacht und wenn die 4. aufgemacht wird soll die 1. geschlossen werden (wodurch die 2. zur 1. wird etc) ?

 

noch was: warum checkst du das closeOld in jedem Schleifendurchlauf? Wennst viele Orders offen hast, machst du unmengen sinnlose Berechnungen...

Du koenntest vermutlich alle for schleifen in eine zusammenpacken und ein bissl performance erhoehen, aber bei 3 Orders is es eh nit schlimm und als Informatiker muss man sagen es is eh asymptotisch gleich (solang du das staendige OldClose aus der Schleife rausziehst ;)

Ja, und zwar die älteste. Und das klappt ja auch soweit.

Das mit dem mehrfachen Schleifendurchlauf liegt daran, dass ich das System nach Ideen modular erweitert habe. Schön ist das sicherlich noch nicht :wink:.

Geschrieben
  • Autor

Habe es mal blöckeweise probiert. Die Verzerrung tritt auf, wenn ich es im folgenden Block ändere. Kann es daran liegen, dass in ihm erneut eine Schleife (durch die Funktion OldOrderClose, siehe Posting #1) aufgerufen wird?

Muss wohl daran liegen - habe nun die OrderClose-Routine außerhalb der Schleife gelegt. Nun geht es überall mit dem -1. Danke nochmal an alle wachsamen Augen.

Geschrieben

Muss wohl daran liegen

Ich wage eine Begründung, warum das ursprüngliche -1 nicht funktionierte: da du mit OldOrderClose die OrdersTotal ggf. durch ein Close änderst, zählt die Schleife "falsch".

 

Beispiel:

Es sind 4 Trades offen, die Schleife soll also 4 Durchläufe machen, bei Einsatz der -1 rückwärts von 3 bis 0 (= 4mal). Durch das OldOrderClose wird ein Trade geschlossen. Damit ist OrdersTotal "plötzlich" 3, deine Schleife zählt aber dennoch wie ursprünglich initialisiert weiter.

 

Daher war es korrekt von dir, den Aufruf von OldOrderClose außerhalb der Schleife zu platzieren.

Geschrieben
  • Autor

So, weiter gehts im Text. Habe das nun mal auf ein paar MT4 zum testen laufen gelassen. Nun habe ich das Problem, dass er auf ca. der Hälfte tatsächlich die Orders geschlossen hat, auf der anderen Hälfte nicht. Okay, das schiebe ich vielleicht auf "Server überlastet" oder sonst was. Das Problem, dass ich jetzt habe, ist, dass auch nach einem Neustart des MT die Orders nicht geschlossen werden. Richtig zählen tut er jedoch, der "Loopcount exceeded" ist es auch nicht. So langsam bekomme ich noch mehr graue Haare als ohnehin schon...

 

//Close oldest Order
int OldOrderClose (int MagicNumber, int MaxLongOrders, int MaxShortOrders) {
  int i, j, OldestOrder=2147483646, LongTradesThisEA = 0, ShortTradesThisEA = 0, loopcount=0;
  datetime OldestOpenTime=2147483646;
  for (i=OrdersTotal()-1; i>=0; i--) {
     if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
        if (OrderMagicNumber() == MagicNumber && OrderType()==OP_BUY) LongTradesThisEA++;
        if (OrderMagicNumber() == MagicNumber && OrderType()==OP_SELL) ShortTradesThisEA++;
        Print ("Open Longs:" + LongTradesThisEA + " | Open Shorts:" + ShortTradesThisEA);
     }
  }

// Long Seite zur besseren Übersichtlichkeit raus genommen
 
  if (ShortTradesThisEA > MaxShortOrders) {
    Print ("Too much short Trades");      
    for (j=OrdersTotal()-1; j>=0; j--)
     {
     if (OrderSelect(j, SELECT_BY_POS, MODE_TRADES)) {
        if (OrderMagicNumber() == MagicNumber && OrderType()==OP_SELL) {
              if (OrderOpenTime() < OldestOpenTime) {
                 OldestOrder = OrderTicket();
                 OldestOpenTime = OrderOpenTime();
              }
        }
     }
     }   
     if (OrderSelect(OldestOrder, SELECT_BY_TICKET)) {
        if (OrderType()==OP_SELL){
           int STicket=OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, CLR_NONE);
              while(STicket == -1) {
                 Sleep(200);
                 loopcount++;
                 if(loopcount > 1000) {
                  Print ("Loopcount exceeded");
                  break;
                  }
                 RefreshRates();
                 STicket=OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, CLR_NONE);
             }          
        prevday = today;
        }     
     }   
  }
}  

Geschrieben

Gibts irgendwelche Logmeldungen bei den MTs dies nicht schaffen? Fehlermeldungen etc?

 

Weil wenn es bei ein paar einwandfrei geht, bei an paar nicht, is es vermutlich kein offensichtlicher Fehler. Und debuggen ohne Journal und Log anzuschauen ist meist reine Zeitverschwendung.

Geschrieben
  • Autor

Gibts irgendwelche Logmeldungen bei den MTs dies nicht schaffen? Fehlermeldungen etc?

Nein, keine Fehlermeldungen. Der EA soll ja auch noch TP und SL der offenen Orders modifizieren. Das funktioniert auch einwandfrei. Auch die Routine, ob heute schon Orders geöffnet/geschlossen wurden, arbeitet er ohne Probleme ab (dies beides war auf allen Konten der Fall). Er schafft es nur nicht, die zu vielen Orders zu schließen - und selbst das, wo ich es derzeit nur noch mit einem Konto probiere. Er erkennt, dass er zu viele shorts hat ("Too much short Trades" wird auch ausgegeben) nur schließen tut er nix.

 

Update

Habe nun sogar noch eine weitere Testroutine eingebaut - er findet auch korrekterweise die älteste short Order und gibt mir das Ticket aus. Nur schließen will er nicht...

Geschrieben

Der Fehler ist zumindest nicht offensichtlich.

Ich würde definitiv noch ein paar Prints einfügen um

a) OrdersTotal()

b) OldestOrder

c) OldestOpenTime

d) sTicket

auszugeben.

Wenn du dann einen Fall hast, bei dem es wieder nicht funktioniert, dann sollte es anhand dieser Informationen recht einfach sein, die Ursache du ermitteln.

 

Auch Edit:

Was bekommst du denn dann als sTicket zurück?

Geschrieben
  • Autor

Der Fehler ist zumindest nicht offensichtlich.

Ich würde definitiv noch ein paar Prints einfügen um

a) OrdersTotal()

b) OldestOrder

c) OldestOpenTime

d) sTicket

auszugeben.

Wenn du dann einen Fall hast, bei dem es wieder nicht funktioniert, dann sollte es anhand dieser Informationen recht einfach sein, die Ursache du ermitteln.

Genau das habe ich mir auch gedacht - das "Problem" scheint zu sein, dass STicket nach dem ersten Versuch den Wert 0 annimmt. Er kommt also nie in die while-Schleife. Nun frage ich mich, was es bedeutet, wenn ein OrderClose den Wert 0 zurück liefert. Das OrderTicket ist korrekt - er findet also die älteste Order anstandslos und merkt sich auch das richtige Ticket.

Geschrieben

Genau das habe ich mir auch gedacht - das "Problem" scheint zu sein, dass STicket nach dem ersten Versuch den Wert 0 annimmt. Er kommt also nie in die while-Schleife. Nun frage ich mich, was es bedeutet, wenn ein OrderClose den Wert 0 zurück liefert. Das OrderTicket ist korrekt - er findet also die älteste Order anstandslos und merkt sich auch das richtige Ticket.

Du kannstr dann noch das Problem über GetLastError() ausgeben lassen. Dann siehst du warum OrderClose nicht funktioniert hat.

Geschrieben
  • Autor

Ich habs gefunden!!!

Nun wird es ganz tricky. Der Fehler liegt einfach darin, dass OrderClose im Gegensatz zu OrderSend vom Typ BOOL (und nicht INT) ist. Da soll mal einer drauf kommen...

 

Nun klappt es einwandfrei!!! Danke an alle Mitdenkenden. Wieder was gelernt.

 

Korrekt muss es also so aussehen:

  if (ShortTradesThisEA > MaxShortOrders) {
     for (j=OrdersTotal()-1; j>=0; j--)
     {
     if (OrderSelect(j, SELECT_BY_POS, MODE_TRADES)) {
        if (OrderMagicNumber() == MagicNumber && OrderType()==OP_SELL) {
              if (OrderOpenTime() < OldestOpenTime) {
                 OldestOrder = OrderTicket();
                 OldestOpenTime = OrderOpenTime();
              }
        }
     }
     }   
          
     if (OrderSelect(OldestOrder, SELECT_BY_TICKET)) {
        if (OrderType()==OP_SELL){
           bool STicket=OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, CLR_NONE);
              while(STicket == false) {
                 Sleep(200);
                 loopcount++;
                 if(loopcount > 1000) break;
                 RefreshRates();
                 STicket=OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, CLR_NONE);
             }          
        prevday = today;
        }     
     }   
  } 

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

Account

Navigation

Suche

Suche

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.