Need Help with Error #130 invalid stoploss - page 4

 
Thanks for noticing Raptor.
I called my DoubleRound function with MODE_TICKVALUE (which is 12.50) instead of MODE_TICKSIZE (0.25).

I fixed it, but it didn't make the #130 go away

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

Here's a log of the error with the updated DoubleRound line:

#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

for comparison, here is a log, where it worked:

#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

in any case, it seems to work more often now, we are definitely getting closer. :)
 
shinobi:

in any case, it seems to work more often now, we are definitely getting closer. :)

I can't see why that Modify failed . . . are you getting a fresh Bid/Ask between the OrderSend and OrderModify ?

All I can suggest now is that when you get an error 130 . . . print everything afresh, Bid, Ask (using MarketInfo), OOP, StopLevel, SL you are trying to set, etc, etc.

 
shinobi:
I called my DoubleRound function with MODE_TICKVALUE (which is 12.50) instead of MODE_TICKSIZE (0.25).
Tick value is definitely wrong. Try this instead with ticksize:
double DoubleRound(double number, double step){
   return( MathRound(number/step)*step );
}
 
Dear Raptor, WHRoeder and SDC,

The #130 stoploss error does not appear anymore. The last steps seemed to have finally pinned down the problem.
I will post another post after this, summarizing all steps taken. So others in the forum fighting Error #130 can use this thread as a reference.


Thanks for your ongoing help :).

shinobi
 
shinobi:

Thanks for your ongoing help :).

shinobi
Well done for sticking with it . . there is always an explanation, just that sometimes it can be tricky finding it.
 
Reference for possible causes of Error #130: invalid stoploss.
  1. General Tips
  2. ECN Broker
  3. 4/5-Digit Broker
  4. Changing Market Rates
  5. Spread
  6. Stop Level
  7. Freeze Level
  8. Ticksize
  9. Complete Example
  10. Acknowledgements
  1. General Tips
    The most important technique for fighting errors is excessive logging. Make output for everything that could remotely be connected to the error. If you define a log function which you can switch on and off, you can keep the code after having solved the problem.
    When initializing your expert adviser you should log all information MarketInfo can tell you: https://docs.mql4.com/constants/marketinfo
    Also always be sure to check the return values of functions, e.g. for OrderModify:
    if (!OrderSelect(ticket, SELECT_BY_TICKET)) {
          int error_code = GetLastError();
          Print("Error: " + ErrorDescription(error_code));
          return(-1);
    }  


  2. ECN Broker
    ECN Broker require you to make separate orders for buy/sell and stoploss/takeprofit. So you need to split your code into two orders like this:
    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);
    
    For sell orders you need to replace OP_BUY by OP_SELL. You also should check the return values of OrderSelect and OrderModify (see General Tips above).

  3. 4/5-Digit Broker
    Some Brokers demand stoploss, takeprofit and slippage to be adjusted to 4/5 digits. You can do that with putting the following code into your init() function (thx 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; 
    }
    Then you need to multiply stoploss, takeprofit and slippage with pips2db1 before sending it to the Broker
    OrderModify(ticket, entry_price, stoploss * pips2points, takeprofit * pips2points, 0);

  4. Changing Market Rates
    Another possible cause is that market rates changed between the tick activated the Expert Advisor (EA), and the EA OrderSend() or OrderModify() was executed. To avoid this problem, there are two possible solutions:
    The first one is to use: RefreshRates() before using predefined market variables like: Ask and Bid. (these variables get their values when the tick activates the EA)
    The second one is not to use predefined market variables at all. Instead you can use the current market values with MarketInfo(). Instead of Ask, Bid and Point use
    MarketInfo(Symbol(), MODE_ASK)
    MarketInfo(Symbol(), MODE_BID)
    MarketInfo(Symbol(), MODE_POINT)
    

  5. Spread
    If stoploss or takeprofit are too close to the entry price, the order will be rejected. In order to avoid this problem, you should take into account the current spread between Ask and Bid. Again there are two solutions:
    The first one is to compute the spread and add/subtract it to your 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;
    The second solution to implicitly take the spread into account using Ask and Bid, when computing stoploss or 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. Stop Level
    Brokers have a certain stop level. If your stoploss is below that level, your order will be rejected. You can check the stop level with MarketInfo(Symbol(), MODE_STOPLEVEL).
    To avoid this check your stoploss against the broker's stop level and adjust it if necessary:
    double stoplevel = MarketInfo(Symbol(), MODE_STOPLEVEL);
    if(stoploss < stoplevel)
       stoploss = stoplevel + 1;

  7. Freeze Level
    Freeze Level is a similar concept. Your stoploss also needs to be greater than the broker's freeze level. You can check the freeze level by MarketInfo(Symbol(), MODE_FREEZELEVEL).
    To avoid this, again check your stoploss against the broker's freezelevel:
    double freezelevel = MarketInfo(Symbol(), MODE_FREEZELEVEL);
    if(stoploss < freezelevel)
       stoploss = freezelevel + 1;

  8. Ticksize
    Finally your stoploss or takeprofit might be rejected, because the Symbol only supports stoploss/takeprofit which match it's ticksize. The ticksize is the minimal distance the prize of the symbol can go up and down. E.g. If the price is 1000 and the ticksize 0.25, then the price can only go up or down by a multiple of 0.25 (0.25 * n, where n is a natural number). So the price might go up by 0.25 to 1000.25 or down by 1.75 to 998.25.
    To account for ticksize, you need a function to round double values to a certain step value (e.g. the nearest 0.25). Here is such a function:
    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);
    }
    E.g calling DoubleRound with number = 1023.81234 and step = 0.25 would return 1023.75. Calling it with 1023.967834 would return 1024.00
    Now before sending stoploss or takeprofit, round it to the Symbol's ticksize with:
    stoploss = (stoploss, MarketInfo(Symbol(), MODE_TICKSIZE));
    takeprofit = (takeprofit, MarketInfo(Symbol(), MODE_TICKSIZE));

  9. Complete Example
    Here is a complete small example taking into account all of the above counter measures:
    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);
    }
    I hope that helps getting rid of #130. If modifying your code doesn't work, use a minimal example, like the one above, first. And then, when the error disappears take over the changed into your code.

    Good Luck,
    shinobi

  10. Acknowledgements
    My thanks to Raptor, WHRoeder, SDC, BigAl, gjol and 35806 for helping me get rid of the error and put together this reference.