How do you solve the problem of invalid volume?

612

Hi, everyone,

But there is an "invalid volume" problem in my coding.

Below is the method I learn and think at mql5 articles.

```//+------------------------------------------------------------------+
//| Check the correctness of the order volume                        |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume,string &description)
{
//--- minimal allowed volume for trade operations
double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
if(volume<min_volume)
{
description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
return(false);
}

//--- maximal allowed volume of trade operations
double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
if(volume>max_volume)
{
description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);
return(false);
}

//--- get minimal step of volume changing
double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);

int ratio=(int)MathRound(volume/volume_step);
if(MathAbs(ratio*volume_step-volume)>0.0000001)
{
description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
volume_step,ratio*volume_step);
return(false);
}
description="Correct volume value";
return(true);
}```

I am going to put above code into "on Init" function of my expert advisor.

Lot size of order at my expert advisor is 0.1 and volume is 0.01.

Is it right?

Thanks to everyone.

37727

Chang Suk Chung:

Hi, everyone,

But there is an "invalid volume" problem in my coding.

Below is the method I learn and think at mql5 articles.

I am going to put above code into "on Init" function of my expert advisor.

Lot size of order at my expert advisor is 0.1 and volume is 0.01.

Is it right?

Thanks to everyone.

This function should be called just before sending an order. And you have to use it properly (checking returned value, if false volume is not good).
612

Alain Verleyen:
This function should be called just before sending an order. And you have to use it properly (checking returned value, if false volume is not good).

Thanks very much.
1548

Always normalize the lot size to double with the same broker lot format.

Never go lower than minimum, or over maximum allowed lot size.

I always use such code ...

```int init(){

MinLot = MarketInfo(Symbol(),MODE_MINLOT);
MaxLot = MarketInfo(Symbol(),MODE_MAXLOT);
if(MinLot == 0.001) LotDigits = 3;
if(MinLot == 0.01)  LotDigits = 2;
if(MinLot == 0.1)   LotDigits = 1;

return(0);
}

...
...
...

double GetLotSize(){
double Lot;
Lot = (AccountBalance()*Risk*0.01)/1000;
if (Lot>=MaxLot) Lot = MaxLot;
if (Lot<MinLot) Lot = MinLot;
Lot = NormalizeDouble(Lot,LotDigits);

if(!UseMM) Lot = Lots;
return(Lot);
}
```
...
18342

 Osama Shaban: Always normalize the lot size to double with the same broker lot format.```   Lot = NormalizeDouble(Lot,LotDigits); ``` Do NOT use NormalizeDouble, EVER. For ANY Reason. It's a kludge, don't use it. It's use is always wrong SL/TP (stops) need to be normalized to tick size (not Point.) (On 5Digit Broker Stops are only allowed to be placed on full pip values. How to find out in mql? - MQL4 forum) and abide by the limits Requirements and Limitations in Making Trades - Appendixes - MQL4 Tutorial and that requires understanding floating point equality Can price != price ? - MQL4 forum Open price for pending orders need to be adjusted. On Currencies, Point == TickSize, so you will get the same answer, but it won't work on Metals. So do it right: Trailing Bar Entry EA - MQL4 forum or Bid/Ask: (No Need) to use NormalizeDouble in OrderSend - MQL4 forum Lot size must also be adjusted to a multiple of LotStep and check against min and max. If that is not a power of 1/10 then NormalizeDouble is wrong. Do it right.
1548

whroeder1:
 Do NOT use NormalizeDouble, EVER. For ANY Reason. It's a kludge, don't use it. It's use is always wrong SL/TP (stops) need to be normalized to tick size (not Point.) (On 5Digit Broker Stops are only allowed to be placed on full pip values. How to find out in mql? - MQL4 forum) and abide by the limits Requirements and Limitations in Making Trades - Appendixes - MQL4 Tutorial and that requires understanding floating point equality Can price != price ? - MQL4 forum Open price for pending orders need to be adjusted. On Currencies, Point == TickSize, so you will get the same answer, but it won't work on Metals. So do it right: Trailing Bar Entry EA - MQL4 forum or Bid/Ask: (No Need) to use NormalizeDouble in OrderSend - MQL4 forum Lot size must also be adjusted to a multiple of LotStep and check against min and max. If that is not a power of 1/10 then NormalizeDouble is wrong. Do it right.

I'm sorry, Not convinced as I'm using it for ages in forex (currencies) with no problems at all.

I'm talking here about the lot size normalization.

For price formulas, I use DIGITS instead.

My question, As you said, "It's always wrong" ... Then, why when I use

"#property strict" in my code, I got no errors or warnings and my code works smooth.

Can you give an example to make things more clear please?

37727

Osama Shaban:

I'm sorry, Not convinced as I'm using it for ages in forex (currencies) with no problems at all.

I'm talking here about the lot size normalization.

For price formulas, I use DIGITS instead.

My question, As you said, "It's always wrong" ... Then, why when I use

"#property strict" in my code, I got no errors or warnings and my code works smooth.

Can you give an example to make things more clear please?

Your way to normalize volume is incorrect, even if it runs most of the time for you. The problem is not using NormalizeDouble() which is just a rounding function. The problem is you need to have a multiple of lot step  (or volume step).

The code provided by the OP is correct, he was just knowing how to us it. (This code comes from a Metaquotes article).

Only and simple correct way to normalize volume is :

```         double lotStep=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
volume=MathFloor(volume/lotStep)*lotStep;
```
MathFloor() could be replaced by MathRound() or MathCeil(), or even NormalizeDouble() . The principle is the same.
2696

Please confirm the full use of the code for both MT5 and MT4

Thanks

2696

Osama Shaban:

Always normalize the lot size to double with the same broker lot format.

Never go lower than minimum, or over maximum allowed lot size.

I always use such code ...

...
```int init(){

MinLot = MarketInfo(Symbol(),MODE_MINLOT);
MaxLot = MarketInfo(Symbol(),MODE_MAXLOT);
if(MinLot == 0.001) LotDigits = 3;
if(MinLot == 0.01)  LotDigits = 2;
if(MinLot == 0.1)   LotDigits = 1;

return(0);
}

...
...
...

double GetLotSize(){
double Lot;
Lot = (AccountBalance()*Risk*0.01)/1000;
if (Lot>=MaxLot) Lot = MaxLot;
if (Lot<MinLot) Lot = MinLot;
Lot = NormalizeDouble(Lot,LotDigits);

if(!UseMM) Lot = Lots;
return(Lot);
}

Is this code for MT4 or MT5```
18342

Chang Suk Chung: I am going to put above code into "on Init" function of my expert advisor.

Uriel Melliphant:
```int init(){

MinLot = MarketInfo(Symbol(),MODE_MINLOT);
MaxLot = MarketInfo(Symbol(),MODE_MAXLOT);```
Don't try to use any price or server related functions in OnInit (or on load,) as there may be no connection/chart yet:
1. Terminal starts.
2. Indicators/EAs are loaded. Static and globally declared variables are initialized. (Do not depend on a specific order.)
3. OnInit is called.
4. For indicators OnCalculate is called with any existing history.
5. Human may have to enter password, connection to server begins.
6. New history is received, OnCalculate called again.
7. New tick is received, OnCalculate/OnTick is called. Now TickValue, TimeCurrent, account information and prices are valid.
2696

whroeder1:
Don't try to use any price or server related functions in OnInit (or on load,) as there may be no connection/chart yet:
1. Terminal starts.
2. Indicators/EAs are loaded. Static and globally declared variables are initialized. (Do not depend on a specific order.)
3. OnInit is called.
4. For indicators OnCalculate is called with any existing history.
5. Human may have to enter password, connection to server begins.
6. New history is received, OnCalculate called again.
7. New tick is received, OnCalculate/OnTick is called. Now TickValue, TimeCurrent, account information and prices are valid.

whroeder1