MQL5 Risk Management: Position Sizing Code Templates & Guide

This page provides production-ready MQL5 code templates for implementing professional risk management in Expert Advisors, covering percentage-based position sizing, dynamic stop-loss placement, and account drawdown controls. Whether you are building your first EA or hardening an existing system, these patterns will help you protect capital while maximizing consistency across multiple currency pairs.

mql5 risk management codemql5 position sizingmql5 lot size calculationmql5 stop loss take profit codemql5 risk percent per trade

Strategy Logic

Entry Conditions

N/A — this is a tutorial/indicator reference page. The example code demonstrates how to calculate a proper lot size before entering any trade, not a specific entry signal. Actual entry signals (moving average crossovers, breakouts, etc.) are kept minimal so the risk logic remains the focus.

Exit Conditions

N/A — this is a tutorial/indicator reference page. The code shows how to attach a correctly sized stop-loss and take-profit to every order so that the risk-to-reward ratio is enforced automatically at the moment of order placement.

MQL5 Expert Advisor Code

//+------------------------------------------------------------------+
//|  RiskManagementEA.mq5                                            |
//|  Tutorial: Professional position sizing and risk controls         |
//|  For educational purposes — test thoroughly before live use       |
//+------------------------------------------------------------------+
#property copyright "Pineify Educational Series"
#property version   "1.00"
#property strict

//--- Input parameters
input double   RiskPercent      = 1.0;    // Risk per trade (% of account balance)
input double   RewardRatio      = 2.0;    // Reward-to-risk ratio (R:R)
input int      StopLossPips     = 30;     // Stop-loss distance in pips
input int      MagicNumber      = 202401; // Unique EA identifier
input int      MaxOpenTrades    = 3;      // Maximum simultaneous positions
input double   MaxDailyLossPct  = 3.0;   // Daily loss circuit-breaker (% of balance)
input int      MA_Period        = 50;     // Moving average period for trend filter
input ENUM_TIMEFRAMES MA_TF     = PERIOD_H1; // MA timeframe

//--- Global variables
int    g_maHandle   = INVALID_HANDLE;
double g_dailyStart = 0.0;
datetime g_lastBarTime = 0;

//+------------------------------------------------------------------+
//| Expert initialisation                                             |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Create MA handle for simple trend filter
   g_maHandle = iMA(_Symbol, MA_TF, MA_Period, 0, MODE_EMA, PRICE_CLOSE);
   if(g_maHandle == INVALID_HANDLE)
     {
      Print("ERROR: Failed to create MA indicator handle");
      return INIT_FAILED;
     }

   // Record starting balance for daily loss tracking
   g_dailyStart = AccountInfoDouble(ACCOUNT_BALANCE);

   Print("RiskManagementEA initialised on ", _Symbol,
         " | Risk: ", RiskPercent, "% | SL: ", StopLossPips, " pips");
   return INIT_SUCCEEDED;
  }

//+------------------------------------------------------------------+
//| Expert deinitialization                                           |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(g_maHandle != INVALID_HANDLE)
      IndicatorRelease(g_maHandle);

   Print("RiskManagementEA removed. Reason code: ", reason);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                              |
//+------------------------------------------------------------------+
void OnTick()
  {
   //--- Only act on new bar to avoid re-entry noise
   datetime currentBar = iTime(_Symbol, PERIOD_CURRENT, 0);
   if(currentBar == g_lastBarTime)
      return;
   g_lastBarTime = currentBar;

   //--- Circuit-breaker: halt trading if daily loss limit exceeded
   if(IsDailyLossBreached())
     {
      Print("Daily loss limit reached. No new trades today.");
      return;
     }

   //--- Respect maximum open-trade cap
   if(CountOpenPositions() >= MaxOpenTrades)
      return;

   //--- Read MA for trend direction
   double maBuffer[];
   ArraySetAsSeries(maBuffer, true);
   if(CopyBuffer(g_maHandle, 0, 0, 3, maBuffer) < 3)
      return;

   double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double maValue = maBuffer[1]; // confirmed previous bar value

   //--- Simple demo entry: long above MA, short below MA
   if(price > maValue && CountOpenPositions() == 0)
      OpenTrade(ORDER_TYPE_BUY);
   else if(price < maValue && CountOpenPositions() == 0)
      OpenTrade(ORDER_TYPE_SELL);
  }

//+------------------------------------------------------------------+
//| Calculate lot size based on account risk percentage              |
//+------------------------------------------------------------------+
double CalculateLotSize(double stopLossPips)
  {
   double balance       = AccountInfoDouble(ACCOUNT_BALANCE);
   double riskAmount    = balance * (RiskPercent / 100.0);

   double tickSize      = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   double tickValue     = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double point         = SymbolInfoDouble(_Symbol, SYMBOL_POINT);

   // Convert pips to points (accounts for 5-digit brokers)
   double pipInPoints   = 10.0 * point;
   double slInPoints    = stopLossPips * pipInPoints;

   if(tickSize == 0 || tickValue == 0 || slInPoints == 0)
      return 0;

   double moneyPerLotPerPip = (pipInPoints / tickSize) * tickValue;
   double rawLots           = riskAmount / (stopLossPips * moneyPerLotPerPip);

   // Normalise to broker lot-step constraints
   double lotStep  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   double minLot   = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot   = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);

   double lots = MathFloor(rawLots / lotStep) * lotStep;
   lots = MathMax(minLot, MathMin(maxLot, lots));

   return NormalizeDouble(lots, 2);
  }

//+------------------------------------------------------------------+
//| Open a trade with risk-managed SL and TP                         |
//+------------------------------------------------------------------+
bool OpenTrade(ENUM_ORDER_TYPE orderType)
  {
   double lots = CalculateLotSize(StopLossPips);
   if(lots <= 0)
     {
      Print("Lot size calculation returned 0 — trade skipped.");
      return false;
     }

   double point       = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   double pipPoints   = 10.0 * point;
   double slDistance  = StopLossPips * pipPoints;
   double tpDistance  = slDistance * RewardRatio;

   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

   double entryPrice, sl, tp;
   if(orderType == ORDER_TYPE_BUY)
     {
      entryPrice = ask;
      sl         = NormalizeDouble(entryPrice - slDistance, _Digits);
      tp         = NormalizeDouble(entryPrice + tpDistance, _Digits);
     }
   else
     {
      entryPrice = bid;
      sl         = NormalizeDouble(entryPrice + slDistance, _Digits);
      tp         = NormalizeDouble(entryPrice - tpDistance, _Digits);
     }

   MqlTradeRequest request = {};
   MqlTradeResult  result  = {};

   request.action    = TRADE_ACTION_DEAL;
   request.symbol    = _Symbol;
   request.volume    = lots;
   request.type      = orderType;
   request.price     = entryPrice;
   request.sl        = sl;
   request.tp        = tp;
   request.deviation = 10;
   request.magic     = MagicNumber;
   request.comment   = StringFormat("Risk %.1f%% SL%dpips", RiskPercent, StopLossPips);
   request.type_filling = ORDER_FILLING_FOK;

   bool sent = OrderSend(request, result);
   if(!sent || result.retcode != TRADE_RETCODE_DONE)
     {
      Print("OrderSend failed. Retcode: ", result.retcode,
            " | Lots: ", lots, " | SL: ", sl, " | TP: ", tp);
      return false;
     }

   Print("Trade opened | ", EnumToString(orderType),
         " | Lots: ", lots,
         " | Entry: ", entryPrice,
         " | SL: ", sl,
         " | TP: ", tp,
         " | Risk$: ", NormalizeDouble(AccountInfoDouble(ACCOUNT_BALANCE) * RiskPercent / 100.0, 2));
   return true;
  }

//+------------------------------------------------------------------+
//| Count open positions for this EA on this symbol                  |
//+------------------------------------------------------------------+
int CountOpenPositions()
  {
   int count = 0;
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0 &&
         PositionGetString(POSITION_SYMBOL) == _Symbol &&
         (int)PositionGetInteger(POSITION_MAGIC) == MagicNumber)
         count++;
     }
   return count;
  }

//+------------------------------------------------------------------+
//| Check if the daily loss circuit-breaker has been triggered       |
//+------------------------------------------------------------------+
bool IsDailyLossBreached()
  {
   double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY);
   double lossPercent   = ((g_dailyStart - currentEquity) / g_dailyStart) * 100.0;
   return lossPercent >= MaxDailyLossPct;
  }
//+------------------------------------------------------------------+

Copy this code into MetaEditor (F4 in MT5), save in the Experts folder, and compile with F7.

Generate a Custom Multi-pair Educational EA →

Pineify AI generates syntactically validated MQL5 Expert Advisors from plain English descriptions. Customize entry logic, risk management, and trading sessions — no coding required.

Pine Script vs MQL5: Same Strategy, Different Platforms

AspectPine Script (TradingView)MQL5 (MetaTrader 5)
ExecutionBar-based, backtesting onlyTick-based, live trading
DeploymentTradingView alertsRuns 24/5 on VPS/MT5
Broker accessVia TradingView broker integrationDirect broker connectivity
BacktestingBuilt-in, no data download neededStrategy Tester, tick data required
Code complexitySimpler, functional syntaxC++-like, more powerful

Pineify supports both platforms. Prototype your strategy visually in TradingView Pine Script, then generate the equivalent MQL5 EA for live MT5 trading.

Frequently Asked Questions

Related MQL5 Expert Advisors