← BlogRisk Management
Risk Management

EA Position Sizing for a Drawdown Lock

A trailing drawdown lock ratchets up with every new equity high and never gives ground back. Most EAs have no idea it exists.

EA Position Sizing for a Drawdown Lock

The Floor That Follows You Up

Static drawdown is the version most people picture. A hard floor, set on day one from your starting balance. Touch it and the account is done.

A trailing drawdown lock moves. Every time the account prints a new high, the floor steps up behind it. Then it stays there. Lose the next day and it does not step back down with you.

Chart comparing a static drawdown floor as a flat line against an EOD trailing drawdown lock that steps upward with new equity highs
Chart comparing a static drawdown floor as a flat line against an EOD trailing drawdown lock that steps upward with new equity highs

That one difference breaks most EAs.

We keep meeting traders who proved out their risk logic on a static-drawdown demo and assumed it would carry over. It doesn't. Sizing that ignores the ratchet is why accounts get flagged in week two of an evaluation, usually on a day that felt completely ordinary.

Before the math, two details firms do not agree on.

The first is when the floor updates. Earn2Trade's evaluation accounts use an end-of-day drawdown: your minimum balance is recalculated from closed positions after the session ends, then holds for the whole next day. Apex is harsher. Its intraday trailing threshold follows your peak balance in real time, unrealized profit included, so a trade that spikes in your favour and gives it all back still drags the floor up permanently. Same word, "trailing", two very different risk pictures.

The second is units. Both of those are futures firms, so they count contracts, not lots. The logic below transfers. The numbers don't. Your firm's rule sheet gives you the constants; this post gives you the shape of the calculation.

Fixed Lots Assume A Fixed Budget

Fixed lot sizing rests on one assumption: that your risk budget stays the same size. Under a trailing lock it doesn't. It shrinks every time the floor ratchets up behind you.

Equity curve for Account A showing a choppy first week with the EOD trailing lock still sitting near its initial floor
Equity curve for Account A showing a choppy first week with the EOD trailing lock still sitting near its initial floor
Equity curve for Account B showing ten days of new highs with the EOD trailing lock ratcheted up close behind, leaving a thin buffer
Equity curve for Account B showing ten days of new highs with the EOD trailing lock ratcheted up close behind, leaving a thin buffer

The failure looks the same every time we see it. A trader backtests an EA at a flat 0.1 lot on EUR/USD. It behaves on a static-drawdown demo. They deploy it on a funded account with a trailing lock, and the EA carries on risking an identical dollar amount per trade, with no idea where today's equity sits relative to the high-water mark.

Two accounts, same EA, same lot size, opposite outcomes:

  • Account A had a rough first week. Equity never made a new high, so the lock is still parked near the initial floor. Plenty of room.
  • Account B ran hot for ten days. Equity high-watered again and again and the lock followed it up. The gap between current equity and the lock is now a fraction of what it was on day one, even though the balance looks a lot healthier than Account A's.

A fixed lot size treats those two accounts as identical. Account B is one bad session from a breach and its sizing logic never said a word.

Size From The Buffer, Not The Balance

Stop sizing off the starting balance. Size off the live distance between current equity and the current lock level. That distance is the only money you actually have to lose.

Flowchart showing the six-step process from live equity to a normalized lot size under a trailing drawdown lock
Flowchart showing the six-step process from live equity to a normalized lot size under a trailing drawdown lock
buffer = current_equity - drawdown_lock_level
risk_amount = buffer x risk_per_trade_pct
lot_size = risk_amount / (stop_loss_pips x pip_value)

Three details decide whether this works in practice.

The base is buffer, never equity. Equity tells you how much money is in the account. Buffer tells you how much room is left before the firm switches you off, and that is the number a live sizing decision depends on.

risk_per_trade_pct should shrink as the buffer shrinks rather than sit at one figure forever. Percentages are below, but the principle is simple enough: the closer you sit to the lock, the smaller a bite each trade takes out of what remains.

pip_value has to come from the symbol. Gold and EUR/USD do not share a pip value per 0.01 lot, and a 4-digit broker feed does not agree with a 5-digit one. Hardcode a pip value and the formula keeps returning confident, wrong numbers on every symbol but the one you tested.

What Those Percentages Cost

Risk per trade should shrink as the buffer to the lock narrows: roughly 0.75% early in an evaluation, 0.5% mid-evaluation, and 0.25% or flat once the buffer drops under 40%. A static floor never moves, so 1-1.5% stays standard risk there.

Risk per trade by drawdown regime Every percentage below applies to the remaining buffer, never the account balance. The bar shows where that row sits between an empty buffer and a full one.

Drawdown regimeRisk / tradeWhy
Trailing lockEarly evaluation - buffer above 80% of max0.75%Lock hasn't ratcheted much yet - buffer is close to full
Trailing lockMid-evaluation - buffer 40-80%0.5%Lock has moved up; each trade risks a proportionally bigger share of what's left
Trailing lockNear lock - buffer under 40%0.25%or flatPreserve the account; this isn't the trade to press
Static drawdownFunded or live - floor never moves1-1.5%Floor doesn't move - sizing can stay closer to standard risk management

What those percentages cost in lots Same three tiers as above, priced out. EUR/USD, 30-pip stop, $10 per pip per standard lot; lots rounded down to a 0.01 volume step.

Remaining buffer0.75%> 80% left0.5%40-80% left0.25%< 40% left
$600$4.500.01 lots$3.000.01 lots$1.50under 0.01 min
$1,200$9.000.03 lots$6.000.02 lots$3.000.01 lots
$2,500$18.750.06 lots$12.500.04 lots$6.250.02 lots
$5,000$37.500.12 lots$25.000.08 lots$12.500.04 lots

Look at the top-right cell. A $600 buffer at 0.25% funds $1.50 of risk, and the smallest lot your broker will accept costs $3.00 on a 30-pip stop. The honest answer there is no trade at all. Remember that cell, because it is the one most sizing code gets wrong.

These percentages are a starting frame, not constants. Apex and Earn2Trade calculate their floors from different things at different moments, and that changes what a sensible tier looks like on each.

Same EA, Two Regimes

A $50,000 evaluation account. The EA risks 30 pips per trade on EUR/USD.

Under a trailing lock, mid-evaluation, equity is $51,200 and the lock has ratcheted up to $50,600. Buffer: $600. Risking 0.5% of that is $3, which at $10 per pip and a 30-pip stop buys you 0.01 lots. Small. But the gains are already banked, and the job now is not handing them back.

Under static drawdown, same balance, the floor is still fixed at $47,500. Buffer: $3,700. Risking 1.5% is $55.50, which works out to $1.85 per pip, or 0.185 lots. On a 0.01 volume step you round down and trade 0.18.

Same EA, same account size, same day, eighteen times the position size. A flat 0.1-lot EA will never notice either situation.

Computing It In MQL5

Pull live equity, subtract the lock level you're tracking, and normalize the result to the symbol's volume step so the broker doesn't bounce the order.

//--- Inputs: set these from your firm's specific drawdown rule
input double RiskPctBuffer     = 0.5;     // % of buffer risked per trade
input double DrawdownLockLevel = 50600.0; // refreshed from your high-water calc
input int    StopLossPips      = 30;

double CalculateLotSize()
  {
   double equity = AccountInfoDouble(ACCOUNT_EQUITY);
   double buffer = equity - DrawdownLockLevel;

   if(buffer <= 0)
      return 0.0; // no room left - do not open a new position

   double riskAmount = buffer * (RiskPctBuffer / 100.0);

   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double tickSize  = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   if(tickValue <= 0 || tickSize <= 0)
      return 0.0; // symbol data not ready - sizing would be guesswork

   // A pip is 10 points only on 3- and 5-digit quotes.
   double pipSize  = (_Digits == 3 || _Digits == 5) ? _Point * 10 : _Point;
   double pipValue = tickValue * (pipSize / tickSize);

   double rawLot = riskAmount / (StopLossPips * pipValue);

   double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   double minLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);

   double lot = MathFloor(rawLot / lotStep) * lotStep;

   if(lot < minLot)
      return 0.0; // budget can't afford the minimum lot - skip, don't round up

   return MathMin(maxLot, lot);
  }

AccountInfoDouble(ACCOUNT_EQUITY) gives you equity rather than balance, and the difference is floating P/L, which is exactly what an intraday lock reacts to. The AccountInfoDouble reference lists the rest of the account properties. On MT4 the call is AccountEquity() and the arithmetic is unchanged.

The two return 0.0 guards are the whole point of the function. The first stops the EA trading once it is already through the lock. The second is that top-right table cell in code: when the risk budget cannot pay for the broker's minimum lot, the trade does not happen. Clamping up to minLot instead is a tempting one-liner and it quietly does the opposite of what you asked, taking more risk precisely when there is least room for it.

Rounding down to SYMBOL_VOLUME_STEP keeps the order acceptable. Send an unrounded volume and OrderSend fails with 4756, whose result structure carries retcode 10014, invalid volume. The outer code tells you nothing; the retcode is where the reason lives, so log both.

One caveat on pipSize. The 3-and-5-digit test covers forex. Metals, indices and crypto define a pip however the broker feels like it, so check SYMBOL_TRADE_TICK_VALUE against a known lot size on each symbol before you trust the output.

And DrawdownLockLevel is an input for a reason. It needs a routine that recalculates it on your firm's schedule, whether that is a session-close snapshot or a running peak. The sizing function is only ever as good as the lock value you hand it.

The Bug That Breaches Accounts

We have found this one in EAs that were otherwise well built. The lot-sizing function reads AccountBalance() once inside OnInit(), stores it, and never looks again.

On a static-drawdown account that is harmless, because the floor doesn't move either. On a trailing lock it is the entire problem. The EA is sizing every trade against a number that was true on day one and has not been true since.

Read equity fresh on every call, and pair it with a lock value that updates on schedule.

Here is what the difference costs. Both charts below show the same $100,000 account on gold, the same lock trailing 6,000 behind the high-water mark, and the same market: a run to 108,000 that ratchets the lock to 102,000, then two losing days. The only variable is how the EA sizes.

Equity curve sized at a fixed 0.1 lot falling from 108,000 through an EOD trailing lock at 102,000, with the lot panel below showing one flat line
The fixed 0.1 lot risks the same amount on the day the buffer is 6,000 as on the day it's 1,600. The second losing day closes 1,000 below the lock, with the account still 1,000 up on the month.
The same equity path sized from the remaining buffer, stopping above the EOD trailing lock, with the lot panel below stepping down from 0.10 to 0.02 lots
Same market, same losing days. Because the first loss narrowed the buffer to 1,600, the second trade is sized 0.02 instead of 0.10 and costs 520. The account lands 1,080 above the lock and keeps trading.

An account that is up on the month, breached. Not by a bad strategy, by a stale number.

Prove It In Strategy Tester First

None of this should touch a funded account untested. The MetaTrader 5 Strategy Tester lets you step through equity and watch the calculated lot size bar by bar in the Journal tab.

  • Test over a period with a run of consecutive new highs in it, so the lock actually ratchets and you can see the lot size shrink behind it.
  • Check the Journal for a returned lot of 0.0 when the simulated buffer goes negative, and again when it is positive but too thin to fund the minimum lot. Eyeballing the equity curve will not show you either case.
  • If you run a grid or martingale EA, test this against that too. Layered exposure compounds the problem quickly. We wrote separately about controlling drawdown in a grid or martingale EA.

For the general mechanics of how different firms define their locks, PropScorer's explainer is a reasonable place to start. This post is the part that comes after: turning that rule into a lot size.

Size off the live buffer. Recalculate the lock on your firm's schedule. Return zero when there is nothing left to risk.

If tracking a moving lock by hand sounds like a spreadsheet you'll forget to update mid-session, that is the gap our Equity Tracker MT5 fills. It puts your live distance to the lock on the chart, so the number your EA sizes against is the number you are looking at.

Frequently Asked Questions

What is a trailing drawdown lock in a prop firm evaluation?

A trailing drawdown lock is a floor that moves up every time the account posts a new equity high, then holds there. Unlike a static drawdown, it never steps back down, so the account's risk budget shrinks any time equity pulls back from its own high-water mark.

Why does fixed lot sizing fail under a trailing drawdown lock?

Fixed lot sizing assumes a constant risk budget. Under a trailing lock, the real budget is the buffer between equity and the lock, and that buffer shrinks every time the lock ratchets up. An EA that risks the same dollar amount regardless can breach an account that is still profitable overall.

Should EA position sizing be based on account equity or the buffer to the lock?

The buffer, never raw equity. Equity shows how much money is in the account; buffer shows how much room is left before the firm switches trading off, and that is the number a live sizing decision has to depend on.

What happens if a lot-sizing function reads account balance only once in OnInit()?

It sizes every trade against a number that was only ever true on day one. That is harmless on a static-drawdown account, but on a trailing lock it can breach an account that is still up on the month, because the lock has moved and the EA never noticed.

Why should risk per trade shrink as the buffer narrows?

Because the buffer is the entire remaining risk budget, not a fixed pool. Risking a flat percentage of a shrinking buffer takes a proportionally bigger bite out of what's left with every trade near the lock, which is why risk per trade should scale down as the buffer narrows.

Peace of MindTrade with confidence
60-Day RefundOn every paid product
Secure PaymentPayPal · MQL5
Direct support< 2h reply, 6 languages