Lot Size - Error 131 Invalid Trade Volume

 

I am getting an error 131 "Invalid Trade Volume" when I place an order using Lots rounded to two decimal places. However, MarketInfo (Symbol(),MODE_LOTSTEP) returns 0.01 indicating that I should be able to use two decimal places for Lot sizes. The EA works correctly when I use a Lot size rounded to one decimal place. I also have another third party EA which works ok with my broker using Lots rounded to two decimal places. Can anyone explain what is going on here?

 

1) MarketInfo(Symbol(),MODE_MINLOT) is what matters.

2) Make sure there's really no extra digits ex) 0.0100000001

 
MinLot and LotStep is what matters. Rounding to 2 decimal places is wrong except on those brokers that have LotStep exactly 0.01.
double NormalizePrice(double p, string pair=""){
    // https://forum.mql4.com/43064#515262 zzuegg reports for non-currency DE30:
    // MarketInfo(chart.symbol,MODE_TICKSIZE) returns 0.5
    // MarketInfo(chart.symbol,MODE_DIGITS) return 1
    // Point = 0.1
    // Prices to open must be a multiple of ticksize
    if (pair == "") pair = Symbol();
    double ts = MarketInfo(pair, MODE_TICKSIZE)
    return( MathRound(p/ts) * ts );
}
double NormalizeLots(double lots, string pair=""){
    if (pair == "") pair = Symbol();
    double  lotStep     = MarketInfo(pair, MODE_LOTSTEP),
            minLot      = MarketInfo(pair, MODE_MINLOT);
    lots            = MathRound(lots/ls) * ls;
    if (lots < minLot) lots = 0;    // or minLot
    return(lots);
}
 
WHRoeder:
MinLot and LotStep is what matters. Rounding to 2 decimal places is wrong except on those brokers that have LotStep exactly 0.01.

Your routine is still not correct. This line is the problem

lots            = MathRound(lots/ls) * ls

Multiplying a rounded double by a large value makes the result no longer rounded.

I tested it with a little script

#include "debug.mqh"

int deinit(){
   DEBUG("CLOSEDEBUGFILE");
}

int start(){
    
   double ts = MarketInfo(Symbol(),MODE_TICKSIZE);
   for( int n=0; n<5000; n++ ){
      double val = Bid*1.003 + n*Point*1.00000027;
      val = ts * MathRound( val/ts );
      DEBUG("n=" + n + " : " +  DoubleToStrMorePrecision(val,19) );
   }

   return(0);
}

The debug statement is just printing to a file. This works fine with currencies near unit value, but fails with JPY pairs.

2012.05.04 23:59 : n=0 : 80.0799999999999983
2012.05.04 23:59 : n=1 : 80.0810000000000031
2012.05.04 23:59 : n=2 : 80.0820000000000079
2012.05.04 23:59 : n=3 : 80.0829999999999984
2012.05.04 23:59 : n=4 : 80.0840000000000032
2012.05.04 23:59 : n=5 : 80.0850000000000080
2012.05.04 23:59 : n=6 : 80.0859999999999985
2012.05.04 23:59 : n=7 : 80.0870000000000033
2012.05.04 23:59 : n=8 : 80.0880000000000081
2012.05.04 23:59 : n=9 : 80.0889999999999986
2012.05.04 23:59 : n=10 : 80.0900000000000034
2012.05.04 23:59 : n=11 : 80.0910000000000082
2012.05.04 23:59 : n=12 : 80.0919999999999988
2012.05.04 23:59 : n=13 : 80.0930000000000035
2012.05.04 23:59 : n=14 : 80.0940000000000083
2012.05.04 23:59 : n=15 : 80.0949999999999989
2012.05.04 23:59 : n=16 : 80.0960000000000036
2012.05.04 23:59 : n=17 : 80.0970000000000084
2012.05.04 23:59 : n=18 : 80.0979999999999990
2012.05.04 23:59 : n=19 : 80.0990000000000038

2012.05.04 23:59 : n=20 : 80.1000000000000085

----------------------------------------------------------------------------------------------

And XAUUSD is really bad.

2012.05.04 23:59 : n=0 : 1646.0500000000001819
2012.05.04 23:59 : n=1 : 1646.1000000000001364
2012.05.04 23:59 : n=2 : 1646.1000000000001364
2012.05.04 23:59 : n=3 : 1646.1000000000001364
2012.05.04 23:59 : n=4 : 1646.1000000000001364
2012.05.04 23:59 : n=5 : 1646.1000000000001364
2012.05.04 23:59 : n=6 : 1646.1500000000000910
2012.05.04 23:59 : n=7 : 1646.1500000000000910
2012.05.04 23:59 : n=8 : 1646.1500000000000910
2012.05.04 23:59 : n=9 : 1646.1500000000000910
2012.05.04 23:59 : n=10 : 1646.1500000000000910
2012.05.04 23:59 : n=11 : 1646.2000000000000455
2012.05.04 23:59 : n=12 : 1646.2000000000000455
2012.05.04 23:59 : n=13 : 1646.2000000000000455
2012.05.04 23:59 : n=14 : 1646.2000000000000455
2012.05.04 23:59 : n=15 : 1646.2000000000000455
2012.05.04 23:59 : n=16 : 1646.2500000000000000
2012.05.04 23:59 : n=17 : 1646.2500000000000000
2012.05.04 23:59 : n=18 : 1646.2500000000000000
2012.05.04 23:59 : n=19 : 1646.2500000000000000
2012.05.04 23:59 : n=20 : 1646.2500000000000000

2012.05.04 23:59 : n=21 : 1646.3000000000001819

--------------------------------------------------------------------------------------------------------

I use a NormalizeDouble after the

lots            = MathRound(lots/ls) * ls

step to clean it up nicely.

 

And by "clean it up nicely" I mean

int start(){
    
   double ts = MarketInfo(Symbol(),MODE_TICKSIZE);
   for( int n=0; n<100; n++ ){
      double val = Bid*1.003 + n*Point*1.00000027;
      val = ts * MathRound( val/ts );
      val = NormalizeDouble(val,MarketInfo(Symbol(),MODE_DIGITS)); 
      DEBUG("n=" + n + " : " +  DoubleToStrMorePrecision(val,19) );
   }

   return(0);
}

do the best it can do.

2012.05.04 23:59 : n=0 : 1646.0499999999999545
2012.05.04 23:59 : n=1 : 1646.0999999999999091
2012.05.04 23:59 : n=2 : 1646.0999999999999091
2012.05.04 23:59 : n=3 : 1646.0999999999999091
2012.05.04 23:59 : n=4 : 1646.0999999999999091
2012.05.04 23:59 : n=5 : 1646.0999999999999091
2012.05.04 23:59 : n=6 : 1646.1500000000000910
2012.05.04 23:59 : n=7 : 1646.1500000000000910
2012.05.04 23:59 : n=8 : 1646.1500000000000910
2012.05.04 23:59 : n=9 : 1646.1500000000000910
2012.05.04 23:59 : n=10 : 1646.1500000000000910
2012.05.04 23:59 : n=11 : 1646.2000000000000455
2012.05.04 23:59 : n=12 : 1646.2000000000000455
2012.05.04 23:59 : n=13 : 1646.2000000000000455
2012.05.04 23:59 : n=14 : 1646.2000000000000455
2012.05.04 23:59 : n=15 : 1646.2000000000000455
2012.05.04 23:59 : n=16 : 1646.2500000000000000
2012.05.04 23:59 : n=17 : 1646.2500000000000000
2012.05.04 23:59 : n=18 : 1646.2500000000000000
2012.05.04 23:59 : n=19 : 1646.2500000000000000
2012.05.04 23:59 : n=20 : 1646.2500000000000000

2012.05.04 23:59 : n=21 : 1646.2999999999999546

--------------------------------------------------------------------------------------

For some reason it is printing more digits than it Normalizes :-(

But at least only the last three are rubbish on this test whereas before it was the last four digits :-)

Reason: