Besoin d'aide avec l'erreur #130 "invalid stoploss". - page 4

 
Merci de l'avoir remarqué Raptor.
J'ai appelé ma fonction DoubleRound avec MODE_TICKVALUE (qui est 12,50) au lieu de MODE_TICKSIZE (0,25).

Je l'ai corrigé, mais cela n'a pas fait disparaître le #130

.
   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);

Voici un journal de l'erreur avec la ligne DoubleRound mise à jour :

#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

pour comparaison, voici un log où cela a fonctionné :

#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

en tout cas, cela semble fonctionner plus souvent maintenant, nous nous rapprochons définitivement :)
 
shinobi:

En tout cas, cela semble fonctionner plus souvent maintenant, nous nous rapprochons définitivement :)

Je ne vois pas pourquoi la modification a échoué... Avez-vous obtenu un nouvel ordre d'achat ou de vente entre l'ordre d'envoi et l'ordre de modification ?

Tout ce que je peux suggérer maintenant, c'est que lorsque vous obtenez une erreur 130... imprimez tout à nouveau, l'offre, la demande (en utilisant MarketInfo), l'OOP, le niveau d'arrêt, le SL que vous essayez de définir, etc, etc...

 
shinobi:
J'ai appelé ma fonction DoubleRound avec MODE_TICKVALUE (qui est 12,50) au lieu de MODE_TICKSIZE (0,25).
La valeur du tic-tac est définitivement fausse. Essayez plutôt ceci avec ticksize :
double DoubleRound(double number, double step){
   return( MathRound(number/step)*step );
}
 
Chers Raptor, WHRoeder et SDC,

L'erreur stoploss #130 n'apparaît plus. Les dernières étapes semblent avoir permis de cerner le problème.
Je vais poster un autre message après celui-ci, résumant toutes les étapes suivies. Ainsi, les autres personnes du forum qui luttent contre l'erreur #130 pourront utiliser ce fil de discussion comme référence.


Merci pour votre aide continue :).

shinobi
 
shinobi:

Merci pour votre aide permanente :).

shinobi
Bravo pour votre persévérance... il y a toujours une explication, c'est juste que parfois il peut être difficile de la trouver.
 
Référence pour les causes possibles de l'erreur #130 : invalid stoploss.
  1. Conseils généraux
  2. Courtier ECN
  3. Courtier à 4/5 chiffres
  4. Changement des taux du marché
  5. Spread
  6. Niveau d'arrêt
  7. Niveau de gel
  8. Ticksize
  9. Exemple complet
  10. Remerciements
  1. Conseils généraux
    La technique la plus importante pour lutter contre les erreurs est la journalisation excessive. Produisez des sorties pour tout ce qui pourrait être lié de près ou de loin à l'erreur. Si vous définissez une fonction de journalisation que vous pouvez activer et désactiver, vous pouvez conserver le code après avoir résolu le problème.
    Lors de l'initialisation de votre conseiller expert, vous devez consigner toutes les informations que MarketInfo peut vous communiquer : https://docs.mql4.com/constants/marketinfo.
    Veillez également à toujours vérifier les valeurs de retour des fonctions, par exemple pour OrderModify :
    if (!OrderSelect(ticket, SELECT_BY_TICKET)) {
          int error_code = GetLastError();
          Print("Error: " + ErrorDescription(error_code));
          return(-1);
    }  


  2. ECN Broker
    Les courtiers ECN exigent que vous passiez des ordres séparés pour l'achat/la vente et le stoploss/le takeprofit. Vous devez donc diviser votre code en deux ordres comme ceci :
    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);
    
    Pour les ordres de vente, vous devez remplacer OP_BUY par OP_SELL. Vous devez également vérifier les valeurs de retour de OrderSelect et OrderModify (voir Conseils généraux ci-dessus).

  3. Courtier à 4/5 chiffres
    Certains courtiers exigent que le stoploss, le takeprofit et le slippage soient ajustés à 4/5 chiffres. Vous pouvez faire cela en mettant le code suivant dans votre fonction init() (merci 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; 
    }
    Ensuite vous devez multiplier stoploss, takeprofit et slippage avec pips2db1 avant de les envoyer au Broker.
    OrderModify(ticket, entry_price, stoploss * pips2points, takeprofit * pips2points, 0);

  4. Changement des taux du marché
    Une autre cause possible est que les taux du marché ont changé entre le moment où le tick a activé l'Expert Advisor (EA), et celui où l'EA OrderSend() ou OrderModify() a été exécuté. Pour éviter ce problème, il y a deux solutions possibles :
    La première consiste à utiliser : RefreshRates() avant d'utiliser des variables de marché prédéfinies comme : Ask et Bid. (ces variables obtiennent leurs valeurs lorsque le tick active l'EA).
    La seconde consiste à ne pas utiliser du tout les variables de marché prédéfinies. Au lieu de cela, vous pouvez utiliser les valeurs actuelles du marché avec MarketInfo(). Au lieu de Ask, Bid et Point, utilisez
    MarketInfo(Symbol(), MODE_ASK)
    MarketInfo(Symbol(), MODE_BID)
    MarketInfo(Symbol(), MODE_POINT)
    

  5. Spread
    Si le stoploss ou le takeprofit sont trop proches du prix d'entrée, l'ordre sera rejeté. Afin d'éviter ce problème, vous devez tenir compte de l'écart actuel entre le Ask et le Bid. Là encore, il existe deux solutions :
    La première consiste à calculer le spread et à l'ajouter/soustraire à votre stoploss/takeprofit.
    double spread = MarketInfo(Symbol(), MODE_ASK) - MarketInfo(Symbol(), MODE_BID);
    //buy
    stoploss = stoploss - spread;
    takeprofit = takeprofit + spread;
    //sell
    stoploss = stoploss + spread;
    takeprofit = takeprofit - spread;
    La deuxième solution consiste à prendre implicitement en compte l'écart entre l'offre et la demande, lors du calcul du stoploss ou du takeprofit :
    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. Niveau stop
    Les courtiers ont un certain niveau de stop. Si votre stoploss est inférieur à ce niveau, votre ordre sera rejeté. Vous pouvez vérifier le niveau stop avec MarketInfo(Symbol(), MODE_STOPLEVEL).
    Pour éviter cela, vérifiez votre stoploss par rapport au niveau stop du courtier et ajustez-le si nécessaire :
    double stoplevel = MarketInfo(Symbol(), MODE_STOPLEVEL);
    if(stoploss < stoplevel)
       stoploss = stoplevel + 1;

  7. Freeze Level
    Le Freeze Level est un concept similaire. Votre stoploss doit également être supérieur au niveau de gel du courtier. Vous pouvez vérifier le niveau de gel par MarketInfo(Symbol(), MODE_FREEZELEVEL).
    Pour éviter cela, vérifiez à nouveau votre stoploss par rapport au niveau de gel du courtier :
    double freezelevel = MarketInfo(Symbol(), MODE_FREEZELEVEL);
    if(stoploss < freezelevel)
       stoploss = freezelevel + 1;

  8. Ticksize
    Enfin, votre stoploss ou takeprofit peut être rejeté, car le symbole ne supporte que les stoploss/takeprofit qui correspondent à son ticksize. Le ticksize est la distance minimale sur laquelle le prix du symbole peut monter et descendre. Par exemple, si le prix est de 1000 et le ticksize de 0,25, alors le prix ne peut monter ou descendre que d'un multiple de 0,25 (0,25 * n, où n est un nombre naturel). Le prix peut donc monter de 0,25 pour atteindre 1000,25 ou descendre de 1,75 pour atteindre 998,25.
    Pour tenir compte du ticksize, vous avez besoin d'une fonction pour arrondir les valeurs doubles à une certaine valeur de pas (par exemple, le 0,25 le plus proche). Voici une telle fonction :
    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);
    }
    Par exemple, appeler DoubleRound avec nombre = 1023.81234 et pas = 0.25 renverrait 1023.75. Si vous l'appelez avec 1023.967834, vous obtiendrez 1024.00.
    Maintenant, avant d'envoyer le stoploss ou le takeprofit, arrondissez-le à la taille de tick du symbole avec :
    stoploss = (stoploss, MarketInfo(Symbol(), MODE_TICKSIZE));
    takeprofit = (takeprofit, MarketInfo(Symbol(), MODE_TICKSIZE));

  9. Exemple complet
    Voici un petit exemple complet prenant en compte toutes les contre-mesures ci-dessus :
    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);
    }
    J'espère que cela vous aidera à vous débarrasser du numéro 130. Si la modification de votre code ne fonctionne pas, utilisez d'abord un exemple minimal, comme celui ci-dessus. Et ensuite, lorsque l'erreur disparaît, reprenez la modification dans votre code.

    Bonne chance,
    shinobi

  10. Remerciements
    Mes remerciements à Raptor, WHRoeder, SDC, BigAl, gjol et 35806 pour m'avoir aidé à me débarrasser de l'erreur et à mettre en place cette référence.