What is risk-based position sizing?

Risk-based position sizing means you choose the lot size so that a trade that hits its stop loss loses a fixed share of your account. You decide the risk first, for example 1% of balance, and the distance to the stop loss decides how many lots you can trade. A wide stop gives a small position, and a tight stop gives a larger one.

Risk-based position sizing keeps every loss roughly the same size in money. Without it, a fixed lot size makes some trades risk far more than others, just because their stops sit further away. In an Expert Advisor (EA), the calculation runs automatically before every order.

What is the formula for lot size?

The lot size formula has two parts. First, turn the risk percent into money. Then divide by how much one lot loses if the stop is hit.

risk money   = balance x risk percent / 100
ticks to SL  = stop distance in price / tick size
loss per lot = ticks to SL x tick value
lots         = risk money / loss per lot

A tick is the smallest price change a symbol can make. Tick size (SYMBOL_TRADE_TICK_SIZE) is that change in price units, and tick value (SYMBOL_TRADE_TICK_VALUE) is what one tick is worth for one lot, in the account currency. Using ticks instead of "pips" avoids the confusion between 4-digit and 5-digit quotes.

Which symbol properties does MQL5 give you?

MQL5 exposes everything the formula needs through AccountInfoDouble() and SymbolInfoDouble(). Reading these values at runtime means the same EA works across brokers without code changes.

Property What it returns Used for
ACCOUNT_BALANCE Account balance in deposit currency Risk money
SYMBOL_TRADE_TICK_SIZE Smallest price change Converting stop distance to ticks
SYMBOL_TRADE_TICK_VALUE Value of one tick for one lot, in deposit currency Loss per lot
SYMBOL_VOLUME_MIN Smallest allowed lot size Skip trades that are too small
SYMBOL_VOLUME_MAX Largest allowed lot size Upper clamp
SYMBOL_VOLUME_STEP Lot size increment Rounding down
SYMBOL_TRADE_CONTRACT_SIZE Units per lot (for example ounces of gold) Sanity checks only

How do you calculate lot size in MQL5?

The function below takes the risk percent and the stop distance in price units (for example entry - stopLoss for a buy). It returns a valid lot size, or 0.0 when the trade should be skipped.

// Returns lots so that a stop-loss hit loses riskPercent of balance.
// stopDistance is in price units, e.g. MathAbs(entry - stopLoss).
double LotsForRisk(const double riskPercent, const double stopDistance)
{
   double balance   = AccountInfoDouble(ACCOUNT_BALANCE);
   double tickSize  = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double minLot    = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot    = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double lotStep   = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

   if(stopDistance <= 0.0 || tickSize <= 0.0 || tickValue <= 0.0 || lotStep <= 0.0)
      return(0.0);

   double riskMoney  = balance * riskPercent / 100.0;
   double lossPerLot = (stopDistance / tickSize) * tickValue;
   double lots       = riskMoney / lossPerLot;

   // Round DOWN to the volume step. The tiny epsilon stops 0.3/0.1 = 2.9999 from losing a step.
   lots = MathFloor(lots / lotStep + 1e-9) * lotStep;

   if(lots < minLot)
      return(0.0);                       // too small: skip the trade, do not round up
   lots = MathMin(lots, maxLot);

   int volumeDigits = (int)MathMax(0.0, MathCeil(-MathLog10(lotStep)));
   return(NormalizeDouble(lots, volumeDigits));
}

Why round down and not to the nearest step?

Rounding to the nearest step can round up, and rounding up means the loss at the stop is bigger than the risk you chose. Rounding down always keeps the real risk at or below the target. The same logic explains returning 0.0 below the minimum volume: trading the minimum lot anyway would quietly break the risk rule.

Checking margin before you send the order

A correct lot size can still be too large for the free margin, especially with high leverage limits or several open positions. OrderCalcMargin() returns the margin an order would need, so the EA can compare it with free margin first.

double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double margin;
if(!OrderCalcMargin(ORDER_TYPE_BUY, _Symbol, lots, ask, margin))
   Print("OrderCalcMargin failed, error ", GetLastError());
else if(margin > AccountInfoDouble(ACCOUNT_MARGIN_FREE))
   Print("Not enough free margin for ", lots, " lots");

Worked example (hypothetical numbers)

The numbers below are an example only. Real tick values and contract sizes depend on your broker.

Example: an account has a balance of 10,000 USD and risks 1% per trade, so the risk money is 100 USD. The symbol is XAUUSD with a tick size of 0.01 and a tick value of 1.00 USD per lot (a 100-ounce contract). The EA plans a buy with the stop loss 5.00 below the entry.

  • Ticks to stop loss: 5.00 / 0.01 = 500 ticks
  • Loss per lot: 500 x 1.00 = 500 USD
  • Lots: 100 / 500 = 0.20 lots

Example with rounding: the same account uses a stop 7.30 below entry. That is 730 ticks, or 730 USD per lot. The raw size is 100 / 730 = 0.1369 lots, which rounds down to 0.13 lots with a 0.01 step. The real risk becomes 0.13 x 730 = 94.90 USD, slightly under the 100 USD target.

What are the common position sizing mistakes?

Most position sizing bugs come from assuming symbol properties instead of reading them. These are the ones to watch.

  • Tick value is in the account currency. On a USD account trading EURJPY, the tick value changes as USDJPY moves. Read it right before each order, not once in OnInit(). MQL5 also offers SYMBOL_TRADE_TICK_VALUE_LOSS if you want the value used for losing positions specifically.
  • Gold and indices have different contract sizes. One lot of XAUUSD is often 100 ounces, but some brokers use other sizes, and index CFDs vary widely. Tick value already includes the contract size, so trust it over hard-coded numbers.
  • Digits differ by broker. Gold can be quoted with 2 or 3 decimals, and forex with 4 or 5 decimals (or 2 and 3 for JPY pairs). Working in price distance and ticks avoids pip math that breaks between brokers.
  • Spread and slippage add to the loss. A stop loss can fill worse than its price in fast markets. Size from a realistic stop distance, not an optimistic one.
  • The stop must be legal. A stop closer than SYMBOL_TRADE_STOPS_LEVEL points is rejected by the server, no matter how small the lot size is.

Where does position sizing fit in an EA?

Position sizing belongs right after the EA decides where the stop loss goes and right before it sends the order. The entry and stop come from the strategy, and the lot size comes from the risk rule. Keeping these steps separate makes each one easy to test on its own.

Sigma7 Gold Swing, an MT5 EA for gold, has position sizing built in and sets a hard stop loss on every trade, which is what makes risk-based sizing possible in the first place. If you are new to how EAs are structured, start with what an Expert Advisor is.

Summary

Risk-based position sizing sets the lot size from a fixed percent of balance and the distance to the stop loss: lots = risk money / (ticks to stop x tick value). In MQL5, read tick size, tick value and volume limits from SymbolInfoDouble(), round down to the volume step, skip trades below the minimum, and check margin with OrderCalcMargin(). For help building or reviewing an EA's risk logic, see MT4/MT5 Expert Advisor development.

Need this built? See MT4 / MT5 Expert Advisors or get in touch.

FAQ

Questions about this topic

What percent of my account should I risk per trade?

Many traders use a small fixed percent, often somewhere between 0.5% and 2% of balance. The right number depends on your strategy's losing streaks and your own drawdown limit, so test it in the Strategy Tester before choosing.

Should I size positions from balance or equity?

Balance is simpler and stays stable while trades are open. Equity includes open profit and loss, so it shrinks risk during drawdowns but can change between two trades placed seconds apart. Pick one and use it consistently.

Why does my EA open 0.01 lots when the math says 0.013?

The broker only accepts volumes in steps of SYMBOL_VOLUME_STEP, often 0.01. The function rounds down to the nearest valid step, so 0.013 becomes 0.01 and the real risk is a little lower than planned.

Does this work for gold and indices, not just forex?

Yes, as long as you use tick size and tick value from the symbol properties. Those values already include the broker's contract size, so the same formula works for XAUUSD, indices and currency pairs.

Keep reading

More on MT4 / MT5 Expert Advisors

Have a bot, a backend or a strategy in mind?

Tell me what you want to build and where you are with it. Send a few lines about the project and I’ll reply with questions and next steps.

Rajshahi, Bangladesh