How To Manage 0.5 or 0.05 Price Steps (Tick Value, Tick Size) in order to avoid Error 130

 

Dear All,

My Broker extended the digits from 1 to 2 for DE30. Unfortunately at the second digit only 0 and 5 are allowed.

Valid Prices: 13080.00, 13080.05, 13080.10

Invalid Prices: 13080.01, 13080.02, 13080.03, 13080.04, 13080.06, ...

Until now I used NormalizeDouble(Price, Digits); in oder to get valid prices.

Unfortunately this is no more working. Are there any other methods available to round the price?

BR Sebastian

 
Sebastian Lenk:

Dear All,

My Broker extended the digits from 1 to 2 for DE30. Unfortunately at the second digit only 0 and 5 are allowed.

Valid Prices: 13080.00, 13080.05, 13080.10

Invalid Prices: 13080.01, 13080.02, 13080.03, 13080.04, 13080.06, ...

Until now I used NormalizeDouble(Price, Digits); in oder to get valid prices.

Unfortunately this is no more working. Are there any other methods available to round the price?

BR Sebastian

Solid and elegant way:

double
   dblLotsMinimum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN  ),
   dblLotsMaximum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX  ),
   dblLotsStep    = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP );
// Adjust Volume for allowable conditions double    dblLotsNext = fmin( dblLotsMaximum,                                     // Prevent too greater volume                    fmax( dblLotsMinimum,                                   // Prevent too smaller volume                      round( dblLots ) * dblLotsStep ) );  // Align to Step value

https://www.mql5.com/en/forum/214894#comment_5697033

How to calculate lots using multiplier according to number of opened orders?
How to calculate lots using multiplier according to number of opened orders?
  • 2017.09.01
  • www.mql5.com
Hello guys. I'd like to place every consequitive order using multiplier. Now I've hardcoded my prefered lots using an array. I don't like it...
 

Sebastian Lenk: My Broker extended the digits from 1 to 2 for DE30. Unfortunately at the second digit only 0 and 5 are allowed.

Valid Prices: 13080.00, 13080.05, 13080.10

Invalid Prices: 13080.01, 13080.02, 13080.03, 13080.04, 13080.06, ...

Until now I used NormalizeDouble(Price, Digits); in oder to get valid prices.

Unfortunately this is no more working. Are there any other methods available to round the price?


You must NOT use NormalizeDouble(). You must use the Tick-Size to correctly set the price values. This has been discussed on the forum many times, so do a search but the most common post you will see goes something like this ...

whroeder1:
Do NOT use NormalizeDouble, EVER. For ANY Reason. It's a kludge, don't use it. It's use is always wrong


In essence, make sure that your price quotes, are properly aligned to the Tick size (see following examples).

...
double tickSize = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE );
...
double normalised_price = round( price / tick_size ) * tick_size;
...
// Or use a function
double Round2Ticksize( double price )
{
   double tick_size = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE );
   return( round( price / tick_size ) * tick_size );
}


You may also benefit from reading this: https://www.mql5.com/en/forum/223705#comment_6279080

MathRound fails for one particular number
MathRound fails for one particular number
  • 2017.12.31
  • www.mql5.com
Good evening! I am using to round a couple of doubles to two decimal places. Works, apart from one double: Any ideas...
 
Sebastian Lenk:

Dear All,

My Broker extended the digits from 1 to 2 for DE30. Unfortunately at the second digit only 0 and 5 are allowed.

Valid Prices: 13080.00, 13080.05, 13080.10

Invalid Prices: 13080.01, 13080.02, 13080.03, 13080.04, 13080.06, ...

Until now I used NormalizeDouble(Price, Digits); in oder to get valid prices.

Unfortunately this is no more working. Are there any other methods available to round the price?

BR Sebastian

The somewhat solid, but not elegant way:

MathRound(num * 20.) / 20.;

I'd probably go with @Enrique Dangeroux 's suggestion.

 
Anthony Garot: The somewhat solid, but not elegant way:
MathRound(num * 20.) / 20.;
  1. Don't hard code constants. Replace your 20. with 1/TickSize. Then your result is exactly the same as Fernando Carreiro's post.
  2. Write self-documenting code:
    double round_nearest(double v, double to){ return to * MathRound(v / to); }
    double round_down(   double v, double to){ return to * MathFloor(v / to); }
    double round_up(     double v, double to){ return to * MathCeil( v / to); }
    
    double normalize_price(double p, double d=0.0){
       double tickSize    = MarketInfo(_Symbol, MODE_TICKSIZE);
       if(d > 0)   return round_up(p,      tickSize);
       if(d < 0)   return round_down(p,    tickSize);
                   return round_nearest(p, tickSize);
    }
    double   normalize_lots(double lots){
       double lotStep     = MarketInfo(_Symbol, MODE_LOTSTEP);
       return round_down(lots, lotStep);
       return lots;
    }
    


 

whroeder1:

Then your result is exactly the same as Fernando Carreiro's post.

My apologies to @Fernando Carreiro ! I totally missed the code part of your post. It was early morning, not enough coffee . . . .


 
Anthony Garot: My apologies to @Fernando Carreiro ! I totally missed the code part of your post. It was early morning, not enough coffee . . . .

No worries! No need to apologise!
 

Alternative (easy) option:

You can use the CDouble (wrapper) library for MQL4/5. 

CDouble open_price = 13080.007921837498;

double rounded_to_ticksize = open_price.AsRoundedTick();

...or...

double open_price = CDouble::RoundToTick(13080.007921837498);
 
nicholi shen:

Alternative (easy) option:

You can use the CDouble (wrapper) library for MQL4/5. 

...or...

Wow... That is exactly what everyone here was looking for! thanks so much

Reason: