⚖️ Normalize Volume to Symbol Rules¶
Convenience method: adjusts volume (lot size) to meet symbol's min/max/step requirements. Prevents "invalid volume" errors when placing orders.
API Information:
- Sugar method:
MT5Sugar.normalizeVolume(String symbol, double volume) - Underlying methods:
MT5Account.symbolInfoDouble()withVOLUME_MIN,VOLUME_MAX,VOLUME_STEP- Source: MT5Sugar convenience layer
🔽 Input¶
| Parameter | Type | Required | Description |
|---|---|---|---|
symbol |
String |
✅ | Symbol name (e.g., "EURUSD") |
volume |
double |
✅ | Volume in lots to normalize |
⬆️ Output¶
Returns: double - Normalized volume meeting symbol's constraints
Normalization rules:
1. Clamp to [volumeMin, volumeMax]
2. Round to nearest volumeStep
Examples:
- Input: 0.05, Symbol: EURUSD (min=0.01, step=0.01) → Output: 0.05
- Input: 0.03, Symbol: XAUUSD (min=0.01, step=0.10) → Output: 0.10
- Input: 100.0, Symbol: EURUSD (max=50.0) → Output: 50.0
💬 Just the essentials¶
- What it is. Adjusts lot size to broker's allowed values.
- Why you need it. Broker rejects invalid volume values.
- Auto-used. All trading methods call this internally.
- Prevents errors. "Invalid volume" rejections from wrong step.
🎯 Purpose¶
Use this method when you need to:
- Calculate volume from risk amount or percentage.
- Ensure calculated volume meets broker requirements.
- Prepare volume before manual order placement.
- Round fractional lot sizes to valid increments.
🔗 Usage Examples¶
1) Normalize calculated volume¶
String symbol = "EURUSD";
double calculatedVolume = 0.157; // From risk calculation
double normalized = sugar.normalizeVolume(symbol, calculatedVolume);
System.out.printf("Calculated volume: %.3f%n", calculatedVolume);
System.out.printf("Normalized volume: %.2f%n", normalized);
// Output:
// Calculated volume: 0.157
// Normalized volume: 0.16 (rounded to 0.01 step)
2) Volume from risk percentage¶
String symbol = "EURUSD";
double balance = sugar.getBalance();
double riskPercent = 2.0; // 2% of balance
// Calculate risk amount
double riskAmount = balance * (riskPercent / 100.0);
// Calculate volume for 50 point SL
double rawVolume = sugar.calculateVolume(symbol, 50, riskAmount);
// Normalize to broker's requirements
double volume = sugar.normalizeVolume(symbol, rawVolume);
System.out.printf("Balance: $%.2f%n", balance);
System.out.printf("Risk (%.1f%%): $%.2f%n", riskPercent, riskAmount);
System.out.printf("Raw volume: %.3f%n", rawVolume);
System.out.printf("Normalized: %.2f lots%n", volume);
3) Check volume limits¶
String symbol = "XAUUSD";
double[] limits = sugar.getVolumeLimits(symbol);
double minVol = limits[0];
double maxVol = limits[1];
double stepVol = limits[2];
System.out.printf("%s volume constraints:%n", symbol);
System.out.printf(" Min: %.2f%n", minVol);
System.out.printf(" Max: %.2f%n", maxVol);
System.out.printf(" Step: %.2f%n", stepVol);
// Test normalization
double[] testVolumes = {0.05, 0.03, 0.15, 100.0};
for (double vol : testVolumes) {
double normalized = sugar.normalizeVolume(symbol, vol);
System.out.printf(" %.2f → %.2f%n", vol, normalized);
}
// Output:
// XAUUSD volume constraints:
// Min: 0.01
// Max: 50.00
// Step: 0.01
// 0.05 → 0.05
// 0.03 → 0.03
// 0.15 → 0.15
// 100.00 → 50.00
4) Handle different step sizes¶
String[] symbols = {"EURUSD", "XAUUSD", "BTCUSD"};
double targetVolume = 0.05;
System.out.printf("Normalizing %.2f lots across symbols:%n", targetVolume);
for (String symbol : symbols) {
double[] limits = sugar.getVolumeLimits(symbol);
double normalized = sugar.normalizeVolume(symbol, targetVolume);
System.out.printf(" %s (step: %.2f) → %.2f%n",
symbol, limits[2], normalized);
}
// Output:
// Normalizing 0.05 lots across symbols:
// EURUSD (step: 0.01) → 0.05
// XAUUSD (step: 0.01) → 0.05
// BTCUSD (step: 0.10) → 0.10 (rounded up to step)
5) Safe volume calculation¶
String symbol = "GBPUSD";
// Calculate volume from some algorithm
double algorithmVolume = calculateOptimalVolume(); // Returns 0.237
// ❌ BAD: Use raw volume (may be rejected)
// long ticket = sugar.buyMarket(symbol, algorithmVolume, null, null);
// ✅ GOOD: Normalize first (though buyMarket does this automatically)
double safeVolume = sugar.normalizeVolume(symbol, algorithmVolume);
long ticket = sugar.buyMarket(symbol, safeVolume, null, null);
System.out.printf("Algorithm suggested: %.3f lots%n", algorithmVolume);
System.out.printf("Normalized to: %.2f lots%n", safeVolume);
System.out.printf("Order placed: #%d%n", ticket);
📌 Important Notes¶
- Normalization algorithm:
- Clamp to [min, max]:
volume = Math.max(min, Math.min(max, volume)) -
Round to step:
steps = round(volume / step); return steps * step -
Auto-called: All trading methods (
buyMarket,sellMarket,buyLimit, etc.) call this internally. -
Common volume constraints:
- Standard FX: min=0.01, max=100, step=0.01
- Micro lots: min=0.001, step=0.001
- Gold: min=0.01, max=50, step=0.01
-
Crypto: varies widely by broker
-
Edge cases:
- Volume < min → Returns min volume
- Volume > max → Returns max volume
-
Between steps → Rounds to nearest step
-
When to use manually:
- Risk-based volume calculations
- Position sizing algorithms
- Portfolio rebalancing
- Generally: Let trading methods handle it automatically
Typical volume rules:
See also¶
- Low-level method:
SymbolInfoDouble- gets volume limits - Related:
getVolumeLimits()- get [min, max, step] array - Related:
calculateVolume()- calculate volume from risk - Auto-uses this: All trading methods normalize volume automatically