Lot Size - Error 131 Invalid Trade Volume

To add comments, please log in or register
petermitchell
127
petermitchell  

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?

Ubzen
5299
Ubzen  

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

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

William Roeder
22457
William Roeder  
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);
}
dabbler
1091
dabbler  
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.

dabbler
1091
dabbler  

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

To add comments, please log in or register