Three clients brought me the same EA rescue brief this year: a multi-position strategy with excellent single-trade backtest results and inconsistent live performance whenever the market moved against two or more open positions at once. All three EAs had the same root cause — a single function call on a single line of code. `AccountBalance()` does not know your open trades exist.
The Invisible Exposure Problem
`AccountBalance()` returns your account balance: the sum of all closed trade results. It does not include the profit or loss of any currently open positions. When you have no open trades, balance and equity are identical. When you have open losing positions, they diverge — equity falls, balance stays flat.

Most EA lot-size formulas look like this:
double lots = (AccountBalance() * riskPercent) / (stopLossPoints * tickValue);For a single-position system, this is correct. The account has no open trades, balance equals equity, the calculation reflects reality.
For a multi-position system, the formula breaks down the moment the first position moves into a loss.
Here is what that looks like in practice. Account: $10,000. Risk per trade: 1%. Stop loss: $400 per position. The first position opens at 0.25 lots — correct. That position moves $300 into loss. `AccountBalance()` still returns $10,000. The second position opens at 0.25 lots — but the trader’s real equity is $9,700. The second position is sized 3% too large, which is small enough to miss on a single trade.
Then the third position opens with $600 of unrealized loss across the two open trades. Still sized from $10,000. By this point, the account is carrying three positions each calculated as if none of the others exist. The cumulative exposure is not 3% — it is 3% calculated on a number that does not reflect what the account is actually worth right now.
The failure is invisible in backtesting because Strategy Tester calculates metrics on closed trades. The open-trade distortion only surfaces in live accounts where multiple positions run simultaneously for hours or days.
Why This Pattern Is Everywhere
`AccountBalance()` appears in every MQL tutorial I have reviewed, every AI-generated code snippet, and every template EA that served as the starting point for a rescue project in 2025. It produces the right answer for single-position systems, which is what most tutorials demonstrate and what most backtests simulate. Nobody catches the problem during development because the problem does not exist in single-position mode.
In optimization and rescue work at barmenteros FX, the pattern is almost always the same: an EA originally built and tested with one position at a time, then deployed to a scaling-in or multi-symbol strategy without revisiting the lot-size function. The function looks correct. It compiles. It passes a basic single-position backtest. The problem only reveals itself when two or three positions run simultaneously against a trending move.
The specific code I encounter is almost always the same: a well-structured `CalculateLotSize()` function with proper argument validation, correct tick value handling, and accurate lot normalization — except for one line where `AccountBalance()` should be `AccountEquity()`. The rest of the function is fine. That one substitution is the entire fix.
Three Correct Approaches (and When to Use Each)
There is no single correct replacement for `AccountBalance()` in every multi-position EA. The right choice depends on what type of position accumulation the EA is designed for.
`AccountEquity()`— correct for most multi-position EAs
`AccountEquity()` returns balance plus all open trade floating P&L. When open positions are losing, equity is lower than balance. A lot-size formula based on equity automatically sizes each new position from the account’s current real value, not a stale balance number.
For scaling-in strategies, this is the right default. As the market moves against you and equity drops, each subsequent position opens smaller. The formula functions as a natural drawdown brake — it does not prevent losses, but it prevents the sizing from amplifying them.
Replace `AccountBalance()` with `AccountEquity()` and you are correct for the majority of multi-position use cases.
`AccountFreeMargin()`— for margin-constrained dense grids
`AccountFreeMargin()` returns the available margin not yet committed to open positions. This is the appropriate constraint when your primary concern is not blowing the broker’s margin requirement — rather than controlling percentage risk.
A lot-size formula based on free margin ensures you cannot open a position that exceeds your available margin, but it does not cap your total risk exposure directly. Use it as a secondary check or a binding constraint on top of an equity-based formula, not as a standalone replacement.
Pre-allocated exposure budget — for fixed-grid EAs
If your EA opens a known maximum number of positions — a 5-level grid, an 8-slot recovery pattern — the cleanest approach is to allocate the total risk budget at session open and divide it across the maximum slot count.
For example: 3% total equity budget across a maximum of 3 positions means 1% per slot. The lot size for each slot is calculated once at session start and does not recalculate dynamically as equity moves. This eliminates compound accumulation entirely, because the total budget is fixed before the first position opens.
The trade-off: if equity drops significantly mid-session, the pre-allocated lot sizes are proportionally larger than the original target. For most grid EAs operating within a single trading session, this is an acceptable trade-off against the more serious problem of unbounded accumulation.
The Grid EA Edge Case
`AccountEquity()`-based sizing handles scaling-in strategies well, but grid EAs present a specific failure mode that equity-based sizing does not solve on its own.
A grid adds positions as price moves against you — which means equity is falling at exactly the moment new positions are opening. With `AccountEquity()`, each new level opens smaller than the previous one, which is the correct directional behaviour. The problem is that “smaller at each step” does not prevent the aggregate from becoming unworkable.
I worked with a client whose grid EA on XAUUSD used `AccountEquity()`-based sizing at 1% risk per position. During a 600-pip directional move, the grid accumulated 9 simultaneous positions. Each individual level was correctly sized smaller than the previous one as equity declined. At grid level 9, the sum of all open positions represented 8% of the starting account — even though no single position had been sized above 1% of its respective equity reference at the time it opened.
The trader believed the equity-based approach was conservative because the lot sizes were decreasing at each level. They were right about the individual positions. They had not modelled the aggregate.

For grid EAs, use pre-allocated exposure budgeting with an explicit maximum level cap. Decide upfront: this grid will open at most N levels, and the total risk budget for the full pattern is X%. Each level gets X%/N. Then enforce that level cap in code as a hard stop — not as a preference.
How to Diagnose Your EA Right Now
This is a code review step, not a backtest. Three checks, five minutes.
1. Find your lot-size calculation. It is usually in a function named `CalculateLotSize()`, `GetLotSize()`, or similar — or inline in the order-open logic. In MT4, look for the call before `OrderSend()`. In MT5, before `trade.Buy()` or `trade.Sell()`.
2. Search for `AccountBalance()`. If your EA can open more than one position simultaneously and this function is in the lot-size calculation, the calculation is wrong. There are no exceptions.
3. Apply the default fix. Replace `AccountBalance()` with `AccountEquity()`. If your EA is a fixed grid with a known maximum level count, use pre-allocated budgeting instead — calculate the per-slot lot size once and hold it constant for the session.
To verify the fix: run the EA in Strategy Tester with a configuration that produces multiple simultaneous positions. During a drawdown phase where multiple positions are open and losing, lot sizes for new positions should be visibly smaller than the initial lot size. If they are not decreasing, an `AccountBalance()` reference is still active somewhere — check for secondary lot-size calculations, copy-pasted logic in separate order types, or hedge position handling.
This pattern — undersized individual risk that accumulates into outsized aggregate exposure — is one of several lot-size failure modes that only surface once an EA moves beyond single-position testing.
If you want an independent review of your EA’s lot-size logic before going live, the EA Debugging & Code Review service at barmenteros FX covers position sizing, order management, and risk calculation — delivered as a structured report with the exact lines that need changing.
Most lot-size formulas are correct for position one and wrong for every position after that. The fix is a single function name.


Leave a Reply