Brauche Hilfe bei Fehler #130 ungültiger Stoploss - Seite 4

 
Danke für den Hinweis, Raptor.
Ich habe meine DoubleRound-Funktion mit MODE_TICKVALUE (12,50) statt MODE_TICKSIZE (0,25) aufgerufen.

Ich habe das behoben, aber das hat die #130 nicht verschwinden lassen

   if(long)
      SL = MarketInfo(Symbol(), MODE_BID) - (stoploss * MarketInfo(Symbol(), MODE_POINT));
   else
      SL = MarketInfo(Symbol(), MODE_ASK) + (stoploss * MarketInfo(Symbol(), MODE_POINT));
   Log("SL: " + SL);   
   //round to nearest Tickvalue   
   SL = DoubleRound(SL, MarketInfo(Symbol(), MODE_TICKSIZE));
   Log("SL rounded: " + SL);

Hier ist ein Protokoll des Fehlers mit der aktualisierten DoubleRound-Zeile:

#ESZ1,M5: loaded successfully 
#ESZ1,M5: Date: 2011/11/16 21:54
#ESZ1,M5: Symbol: #ESZ1
#ESZ1,M5: Depot: 56127.45000000
#ESZ1,M5: Stop Level [Points]: 75.00000000
#ESZ1,M5: Freeze Level [Points]: 0.00000000
#ESZ1,M5: Spread [Points]: 25.00000000
#ESZ1,M5: Min/Max Lot: 0.01000000/1000.00000000
#ESZ1,M5: Point: 0.01000000
#ESZ1,M5: Tick Size: 0.25000000
#ESZ1,M5: Tick Value: 12.50000000
#ESZ1,M5: Digits: 2.00000000
#ESZ1,M5: Contract: 2011.09.14 00:00-2011.12.16 23:59
#ESZ1,M5: Expert ID: 35698390 
#ESZ1,M5: Init successfully completed.
#ESZ1,M5: initialized

#ESZ1,M5: Opening Position: Short
#ESZ1,M5: pos size: 1.00000000
#ESZ1,M5: Ask/Bid 1251.00000000/1250.75000000
#ESZ1,M5: Spread 0.25000000
#ESZ1,M5: open #13719226 sell 1.00 #ESZ1 at 1250.75 ok
#ESZ1,M5: Order 13719226 Successfully Opened
#ESZ1,M5: Stoplevel: 75.00000000
#ESZ1,M5: Freezelevel: 0.00000000
#ESZ1,M5: stoploss: 100.00000000
#ESZ1,M5: SL: 1252.00000000
#ESZ1,M5: SL rounded: 1252.00000000
#ESZ1,M5: error=130

zum Vergleich hier ein Protokoll, bei dem es funktioniert hat:

#ESZ1,M5: Opening Position: Long
#ESZ1,M5: pos size: 1.00000000
#ESZ1,M5: Ask/Bid 1249.25000000/1249.00000000
#ESZ1,M5: Spread 0.25000000
#ESZ1,M5: open #13719321 buy 1.00 #ESZ1 at 1249.25 ok 
#ESZ1,M5: Order 13719321 Successfully Opened 
#ESZ1,M5: Stoplevel: 75.00000000
#ESZ1,M5: Freezelevel: 0.00000000
#ESZ1,M5: stoploss: 100.00000000
#ESZ1,M5: SL: 1248.00000000
#ESZ1,M5: SL rounded: 1248.00000000
#ESZ1,M5: modify #13719321 buy 1.00 #ESZ1 at 1249.25 sl: 1248.00 tp: 0.00 ok 
#ESZ1,M5: Stoploss successfully set

Auf jeden Fall scheint es jetzt öfter zu funktionieren, wir sind definitiv näher dran :)
 
shinobi:

Auf jeden Fall scheint es jetzt öfter zu funktionieren, wir sind definitiv näher dran :)

Ich kann nicht erkennen, warum die Änderung fehlgeschlagen ist... erhalten Sie ein neues Bid/Ask zwischen OrderSend und OrderModify?

Ich kann nur vorschlagen, dass Sie, wenn Sie einen Fehler 130 erhalten, alles neu ausdrucken, Bid, Ask (mit MarketInfo), OOP, StopLevel, SL, den Sie setzen wollen, etc. etc.

 
shinobi:
Ich habe meine Funktion DoubleRound mit MODE_TICKVALUE (12,50) anstelle von MODE_TICKSIZE (0,25) aufgerufen.
Der Tickwert ist definitiv falsch. Versuchen Sie dies stattdessen mit ticksize:
double DoubleRound(double number, double step){
   return( MathRound(number/step)*step );
}
 
Lieber Raptor, WHRoeder und SDC,

Der Stoploss-Fehler #130 tritt nicht mehr auf. Die letzten Schritte schienen das Problem endlich auf den Punkt gebracht zu haben.
Ich werde nachher noch einen weiteren Beitrag verfassen, in dem ich alle unternommenen Schritte zusammenfasse. So können andere im Forum, die mit dem Fehler #130 kämpfen, diesen Thread als Referenz verwenden.


Vielen Dank für eure laufende Hilfe :).

Shinobi
 
shinobi:

Vielen Dank für Ihre laufende Hilfe :).

Shinobi
Gut gemacht, dass du drangeblieben bist ... es gibt immer eine Erklärung, nur manchmal ist es schwierig, sie zu finden.
 
Referenz für mögliche Ursachen des Fehlers #130: Ungültiger Stoploss.
  1. Allgemeine Tipps
  2. ECN-Broker
  3. 4/5-stelliger Broker
  4. Ändern von Marktkursen
  5. Spread
  6. Stopp-Level
  7. Freeze Level
  8. Tick-Größe
  9. Vollständiges Beispiel
  10. Danksagungen
  1. Allgemeine Tipps
    Die wichtigste Technik zur Fehlerbekämpfung ist die exzessive Protokollierung. Geben Sie alles aus, was im Entferntesten mit dem Fehler in Verbindung stehen könnte. Wenn Sie eine Protokollierungsfunktion definieren, die Sie ein- und ausschalten können, können Sie den Code nach Behebung des Problems behalten.
    Bei der Initialisierung Ihres Expertenberaters sollten Sie alle Informationen protokollieren, die MarketInfo Ihnen mitteilen kann: https://docs.mql4.com/constants/marketinfo
    Überprüfen Sie auch immer die Rückgabewerte von Funktionen, z.B. bei OrderModify:
    if (!OrderSelect(ticket, SELECT_BY_TICKET)) {
          int error_code = GetLastError();
          Print("Error: " + ErrorDescription(error_code));
          return(-1);
    }  


  2. ECN Broker
    Bei ECN-Brokern müssen Sie separate Aufträge für Kauf/Verkauf und Stoploss/Takeprofit erteilen. Sie müssen also Ihren Code in zwei Aufträge aufteilen, etwa so:
    int ticket = OrderSend(Symbol(), OP_BUY, 1, MarketInfo(Symbol(), MODE_ASK), 2, 0, 0, "", 12345);
    OrderSelect(ticket, SELECT_BY_TICKET);
    entry_price = OrderOpenPrice();
    OrderModify(ticket, entry_price, stoploss, takeprofit, 0);
    
    Für Verkaufsaufträge müssen Sie OP_BUY durch OP_SELL ersetzen. Sie sollten auch die Rückgabewerte von OrderSelect und OrderModify überprüfen (siehe Allgemeine Tipps oben).

  3. 4/5-stelliger Broker
    Einige Broker verlangen, dass Stoploss, Takeprofit und Slippage auf 4/5 Ziffern eingestellt werden. Sie können dies erreichen, indem Sie den folgenden Code in Ihre init()-Funktion einfügen (danke WHRoeder):
    int     pips2points;    // slippage  3 pips    3=points    30=points
    double  pips2dbl;       // Stoploss 15 pips    0.0015      0.00150
    int     Digits.pips;    // DoubleToStr(dbl/pips2dbl, Digits.pips)
    
    //init digit adjustment
    if (Digits % 2 == 1) {      // DE30=1/JPY=3/EURUSD=5 forum.mql4.com/43064#515262
        pips2dbl    = Point*10; pips2points = 10;   Digits.pips = 1;
    } else {
        pips2dbl    = Point;    pips2points =  1;   Digits.pips = 0; 
    }
    Dann müssen Sie stoploss, takeprofit und slippage mit pips2db1 multiplizieren, bevor Sie sie an den Broker senden
    OrderModify(ticket, entry_price, stoploss * pips2points, takeprofit * pips2points, 0);

  4. Sich ändernde Marktkurse
    Eine weitere mögliche Ursache ist, dass sich die Marktkurse zwischen der Aktivierung des Expert Advisor (EA) und der Ausführung der EA OrderSend() oder OrderModify() geändert haben. Um dieses Problem zu vermeiden, gibt es zwei mögliche Lösungen:
    Die erste ist die Verwendung von: RefreshRates() vor der Verwendung von vordefinierten Marktvariablen wie: Ask und Bid. (diese Variablen erhalten ihre Werte, wenn der Tick den EA aktiviert)
    Die zweite Möglichkeit ist, vordefinierte Marktvariablen überhaupt nicht zu verwenden. Stattdessen können Sie die aktuellen Marktwerte mit MarketInfo() verwenden. Anstelle von Ask, Bid und Point verwenden Sie
    MarketInfo(Symbol(), MODE_ASK)
    MarketInfo(Symbol(), MODE_BID)
    MarketInfo(Symbol(), MODE_POINT)
    

  5. Spread
    Wenn Stoploss oder Takeprofit zu nahe am Einstiegskurs liegen, wird die Order abgelehnt. Um dieses Problem zu vermeiden, sollten Sie den aktuellen Spread zwischen Ask und Bid berücksichtigen. Auch hier gibt es zwei Lösungen:
    Die erste besteht darin, den Spread zu berechnen und ihn zu Ihrem Stoploss/Takeprofit zu addieren/subtrahieren.
    double spread = MarketInfo(Symbol(), MODE_ASK) - MarketInfo(Symbol(), MODE_BID);
    //buy
    stoploss = stoploss - spread;
    takeprofit = takeprofit + spread;
    //sell
    stoploss = stoploss + spread;
    takeprofit = takeprofit - spread;
    Die zweite Lösung besteht darin, den Spread implizit zu berücksichtigen, indem man Ask und Bid bei der Berechnung von Stoploss oder Takeprofit verwendet:
    stoploss = 50
    takeprofit = 50
    //buy
    SL = MarketInfo(Symbol(), MODE_BID) - (stoploss * MarketInfo(Symbol(), MODE_POINT))
    TP = MarketInfo(Symbol(), MODE_ASK) + (takeprofit * MarketInfo(Symbol(), MODE_POINT))
    //sell
    SL = MarketInfo(Symbol(), MODE_ASK) + (stoploss * MarketInfo(Symbol(), MODE_POINT))
    TP = MarketInfo(Symbol(), MODE_BID) -  (takeprofit * MarketInfo(Symbol(), MODE_POINT))

  6. Stop-Level
    Makler haben ein bestimmtes Stop-Level. Wenn Ihr Stoploss unter diesem Niveau liegt, wird Ihr Auftrag abgelehnt. Sie können das Stop-Level mit MarketInfo(Symbol(), MODE_STOPLEVEL) überprüfen.
    Um dies zu vermeiden, sollten Sie Ihren Stop Loss mit dem Stop Level des Brokers vergleichen und ihn gegebenenfalls anpassen:
    double stoplevel = MarketInfo(Symbol(), MODE_STOPLEVEL);
    if(stoploss < stoplevel)
       stoploss = stoplevel + 1;

  7. Freeze Level
    Freeze Level ist ein ähnliches Konzept. Ihr Stoploss muss ebenfalls größer sein als das Freeze Level des Brokers. Sie können das Freeze Level mit MarketInfo(Symbol(), MODE_FREEZELEVEL) überprüfen.
    Um dies zu vermeiden, sollten Sie Ihren Stoploss ebenfalls mit dem Freeze-Level des Brokers vergleichen:
    double freezelevel = MarketInfo(Symbol(), MODE_FREEZELEVEL);
    if(stoploss < freezelevel)
       stoploss = freezelevel + 1;

  8. Ticksize
    Schließlich kann es sein, dass Ihr Stoploss oder Takeprofit abgelehnt wird, weil das Symbol nur Stoploss/Takeprofit unterstützt, die seiner Ticksize entsprechen. Die Ticksize ist der minimale Abstand, den der Preis des Symbols nach oben und unten gehen kann. Wenn z.B. der Preis 1000 beträgt und die Ticksize 0,25, dann kann der Preis nur um ein Vielfaches von 0,25 (0,25 * n, wobei n eine natürliche Zahl ist) steigen oder fallen. Der Kurs kann also um 0,25 auf 1000,25 steigen oder um 1,75 auf 998,25 sinken.
    Um die Tick Size zu berücksichtigen, brauchen Sie eine Funktion, die Double-Werte auf einen bestimmten Schrittwert rundet (z. B. die nächsten 0,25). Hier ist eine solche Funktion:
    double DoubleRound(double number, double step)
    {
        double mod = MathMod(number, step);
        if(mod < step/2.0)
          step = 0;
        double rounded = number - mod + step;
        return (rounded);
    }
    Ein Aufruf von DoubleRound mit number = 1023.81234 und step = 0.25 würde z.B. 1023.75 zurückgeben. Ein Aufruf mit 1023,967834 würde 1024,00 zurückgeben.
    Bevor Sie nun Stoploss oder Takeprofit senden, runden Sie es auf die Tickgröße des Symbols mit:
    stoploss = (stoploss, MarketInfo(Symbol(), MODE_TICKSIZE));
    takeprofit = (takeprofit, MarketInfo(Symbol(), MODE_TICKSIZE));

  9. Vollständiges Beispiel
    Hier ist ein vollständiges kleines Beispiel, das alle oben genannten Gegenmaßnahmen berücksichtigt:
    int init()
    {
        //for 4/5 Digits-Broker adjustment
        int     pips2points;    // slippage  3 pips    3=points    30=points
        double  pips2dbl;       // Stoploss 15 pips    0.0015      0.00150
        int     Digits.pips;    // DoubleToStr(dbl/pips2dbl, Digits.pips)
    
       //init digit adjustment
       if (Digits % 2 == 1) {      // DE30=1/JPY=3/EURUSD=5 forum.mql4.com/43064#515262
                   pips2dbl    = Point*10; pips2points = 10;   Digits.pips = 1;
       } else {
                   pips2dbl    = Point;    pips2points =  1;   Digits.pips = 0; 
       }
    
       Print("Date: " + Year() + "/" + Month() + "/" + Day() + " " + Hour() + ":" + Minute());
       Print("Symbol: " + Symbol());
       Print("Depot: " + AccountBalance());
       Print("Stop Level [Points]: " + MarketInfo(Symbol(), MODE_STOPLEVEL));
       Print("Freeze Level [Points]: " + MarketInfo(Symbol(), MODE_FREEZELEVEL));
       Print("Spread [Points]: " + MarketInfo(Symbol(), MODE_SPREAD));
       Print("Min/Max Lot: " + MarketInfo(Symbol(), MODE_MINLOT) + "/" + MarketInfo(Symbol(), MODE_MAXLOT));
       Print("Point: " + MarketInfo(Symbol(), MODE_POINT));
       Print("Tick Size: " + MarketInfo(Symbol(), MODE_TICKSIZE));
       Print("Tick Value: " + MarketInfo(Symbol(), MODE_TICKVALUE));
       Print("Digits: " + MarketInfo(Symbol(), MODE_DIGITS));
       Print("Contract: " + TimeToStr(MarketInfo(Symbol(), MODE_STARTING)) + "-" + TimeToStr(MarketInfo(Symbol(), MODE_EXPIRATION)));
    }
    
    //long = true: buy; long = false: sell
    int take_position(bool long)
    {
       int stoploss = 50;
       double SL = 0.0;
       int ticket = -1;
       
       //send order
       if(long)  //buy
          ticket = OrderSend(Symbol(), OP_BUY, 1, MarketInfo(Symbol(), MODE_ASK), 2, 0, 0, "", 1234);  
       else      //sell
          ticket = OrderSend(Symbol(), OP_SELL, 1, MarketInfo(Symbol(), MODE_BID), 2, 0, 0, "", 1234); 
    
       //check for errors
       if(result_ticket == -1) {
          int error_code = GetLastError();
          Print("Error: " + ErrorDescription(error_code));
          return(-1);
       }
       Print("order "+ticket+" successfully opened");
    
       //select order
       if (!OrderSelect(result_ticket, SELECT_BY_TICKET)) {
          int error_code = GetLastError();
          Print("Error: " + ErrorDescription(error_code));
          return(-1);
       }    
       double entry_price = OrderOpenPrice();
       
       //check stoplevel
       double stoplevel = MarketInfo(Symbol(), MODE_STOPLEVEL);
       Print("Stoplevel: " + stoplevel);
       if(stoploss < stoplevel)
          stoploss = stoplevel + 1;
    
       //check freezelevel
       double freezelevel = MarketInfo(Symbol(), MODE_FREEZELEVEL);
       Print("Freezelevel: " + freezelevel);
       if(stoploss < freezelevel)
          stoploss = freezelevel + 1;
    
       Print("adjusted stoploss: " + stoploss);
       
       //account for spread AND account for 4/5-Digit Brokers
       if(long)
          SL = MarketInfo(Symbol(), MODE_BID) - (stoploss * pips2dbl);
       else
          SL = MarketInfo(Symbol(), MODE_ASK) + (stoploss * pips2dbl);
       Print("SL: " + SL);
       
       //round to nearest Tickvalue   
       SL = DoubleRound(SL, MarketInfo(Symbol(), MODE_TICKSIZE));
       Print("SL rounded: " + SL);
       
       //set stoploss
       if(!OrderModify(result_ticket, entry_price, SL, 0, Red)) {
          int error_code = GetLastError();
          Print("Error: " + ErrorDescription(error_code));
          return(-1);
       }
    
       Print("Stoploss successfully set");
       return(0);
    }
    Ich hoffe, das hilft, #130 loszuwerden. Wenn die Änderung Ihres Codes nicht funktioniert, verwenden Sie zunächst ein Minimalbeispiel, wie das obige. Und dann, wenn der Fehler verschwindet, übernehmen Sie das Geänderte in Ihren Code.

    Viel Glück!
    Shinobi

  10. Danksagung
    Mein Dank geht an Raptor, WHRoeder, SDC, BigAl, gjol und 35806, die mir geholfen haben, den Fehler zu beheben und diese Referenz zusammenzustellen.