The client who ran double risk for six weeks
Last year I reviewed a client's XAUUSD Expert Advisor. The risk input read 2% per trade. The actual exposure per position was 4.1%. Every trade for six weeks had been roughly double the intended size. The formula compiled, passed backtest, and ran live without a single error.
This is not unusual. In about 15 out of the last 40 code rescue projects I have worked on, the lot size formula was the primary defect. Three specific errors account for nearly all of them.
Point is not a pip
The most common failure. On a 5-digit EURUSD broker, Point returns 0.00001. A pip is 0.0001. That is a 10x difference. On XAUUSD, depending on how the broker configures the symbol, the error can be 10x or 100x.
The broken version:
The fix: use SYMBOL_TRADE_TICK_SIZE instead of Point . Ticks are unambiguous — they represent the broker's actual minimum price movement.
Manual pip value vs TickValue
MQL provides SYMBOL_TRADE_TICK_VALUE — the monetary value of one tick for 1.0 lot, already converted to account currency and updated every tick. Many EAs ignore it:
This breaks on EUR-denominated accounts, cross pairs like GBPJPY, and any instrument where the contract size differs from the developer's test setup.
One additional trap: TickValue returns 0 when the market is closed or when the broker's conversion feed is unavailable. An EA that reads this value inside OnInit() on a Sunday gets zero, and the lot size formula divides by zero or returns infinity. The function should read TickValue immediately before OrderSend() and treat zero as a hard stop — do not place the trade.
Lot step normalization
Brokers enforce minimum lot, maximum lot, and lot step. If the formula outputs 0.087 and the step is 0.01, the broker rounds — and different brokers round differently.
The EA should handle this before sending the order:
MathFloor always rounds down. The trader may risk slightly less than the target — never more.
Why these bugs persist
Other errors produce feedback. Error 130 for stop level violations. Error 134 for margin. Error 138 for invalid price. Lot size adjustment produces nothing — OrderSend() returns success, the position fills, the ticket is valid. Nothing in standard error handling catches it.
The only way to detect the mismatch: compare the calculated lot with the actual deal volume via HistoryDealGetDouble(dealTicket, DEAL_VOLUME) . Most EAs never make this comparison.
Complete function
Pass slPoints as price distance (e.g., Ask - stopLossPrice ), not pips. Call this immediately before OrderSend() , not at initialization.
Quick diagnostic
Pull up your last five trades. Compare the lot size your EA calculated (or logged) with the lot size in your account history. If they match exactly, your normalization is correct. If they differ — even by 0.01 — one of these three failures is active.


