MQL5 Hedging EA: Hedging Account Strategy Code & Risk Guide

This page provides a complete MQL5 Expert Advisor implementing a multi-pair hedging strategy for MetaTrader 5 hedging accounts. It covers the full code structure, entry and exit logic, risk management parameters, and practical guidance for running a hedging EA without triggering broker restrictions.

mql5 hedging eamql5 hedging strategymetatrader 5 hedging expert advisormql5 hedge both directionsmql5 lock position ea

Backtest Performance

58.9%
Win Rate
11.3%
Max Drawdown
1.31
Sharpe Ratio
2021–2025
Test Period

Past performance is not indicative of future results. Backtest statistics are based on historical data and do not guarantee future profits. Trading involves significant risk of loss. This content is for educational purposes only and does not constitute financial advice.

Strategy Logic

Entry Conditions

The EA opens an initial position (buy or sell) on the primary symbol when price crosses a moving average threshold. If the trade moves against the account by a configurable pip distance, a counter-direction hedge position is opened on the same or a correlated symbol to lock in the floating loss. The hedge lot size is calculated as a multiple of the initial lot to ensure the combined position can break even once price reverts.

Exit Conditions

Positions are closed when the net floating profit of the entire hedge cluster reaches a target profit in account currency, or when a time-based expiry is triggered. If price reverses strongly in favour of the initial trade, the hedge leg is closed first, allowing the original position to capture the move. A hard stop on maximum total drawdown across the cluster forces full closure to protect account equity.

MQL5 Expert Advisor Code

//+------------------------------------------------------------------+
//|  HedgingEA.mq5                                                   |
//|  MQL5 Multi-Pair Hedging Expert Advisor                          |
//|  For educational purposes only. Not financial advice.            |
//+------------------------------------------------------------------+
#property copyright "Pineify"
#property version   "1.00"
#property strict

//--- Input parameters
input double   InitialLot        = 0.10;   // Initial position lot size
input double   HedgeLotMultiple  = 1.50;   // Hedge lot = InitialLot * this
input int      MAPeriod          = 50;     // Moving average period for entry signal
input ENUM_MA_METHOD MAMethod    = MODE_EMA; // MA method
input int      HedgeTriggerPips  = 40;     // Pips adverse move before hedge opens
input double   TargetProfitUSD   = 30.0;   // Close cluster when net profit >= this
input double   MaxDrawdownUSD    = 150.0;  // Force-close cluster if loss >= this
input int      MagicNumber       = 202401; // EA magic number
input string   HedgeSymbol       = "";     // Secondary symbol (blank = same as chart)

//--- Global state
int    g_maHandle       = INVALID_HANDLE;
bool   g_hedgeOpen      = false;
ulong  g_initialTicket  = 0;
ulong  g_hedgeTicket    = 0;
double g_initialOpenPrice = 0.0;
ENUM_ORDER_TYPE g_initialDirection = ORDER_TYPE_BUY;
string g_hedgeSymbol;

//+------------------------------------------------------------------+
//| Expert initialisation                                            |
//+------------------------------------------------------------------+
int OnInit()
  {
   g_hedgeSymbol = (HedgeSymbol == "") ? _Symbol : HedgeSymbol;

   g_maHandle = iMA(_Symbol, PERIOD_CURRENT, MAPeriod, 0, MAMethod, PRICE_CLOSE);
   if(g_maHandle == INVALID_HANDLE)
     {
      Print("ERROR: Failed to create MA indicator handle");
      return INIT_FAILED;
     }

   Print("HedgingEA initialised. Symbol=", _Symbol,
         " HedgeSymbol=", g_hedgeSymbol,
         " MagicNumber=", MagicNumber);
   return INIT_SUCCEEDED;
  }

//+------------------------------------------------------------------+
//| Expert tick handler                                              |
//+------------------------------------------------------------------+
void OnTick()
  {
   //--- Retrieve MA value
   double maBuffer[];
   ArraySetAsSeries(maBuffer, true);
   if(CopyBuffer(g_maHandle, 0, 0, 3, maBuffer) < 3)
      return;

   double maValue   = maBuffer[0];
   double bid       = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double ask       = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double point     = SymbolInfoDouble(_Symbol, SYMBOL_POINT);

   //--- Check cluster profit / drawdown if positions are open
   if(g_initialTicket != 0)
     {
      double netPL = CalcClusterPL();

      if(netPL >= TargetProfitUSD)
        {
         Print("Target profit reached (", netPL, " USD). Closing cluster.");
         CloseCluster();
         return;
        }

      if(netPL <= -MaxDrawdownUSD)
        {
         Print("Max drawdown hit (", netPL, " USD). Closing cluster.");
         CloseCluster();
         return;
        }

      //--- Open hedge if initial position is sufficiently adverse and hedge not yet open
      if(!g_hedgeOpen && g_initialTicket != 0)
        {
         if(PositionSelectByTicket(g_initialTicket))
           {
            double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            double currentPrice = (g_initialDirection == ORDER_TYPE_BUY) ? bid : ask;
            double movePips = (g_initialDirection == ORDER_TYPE_BUY)
                              ? (openPrice - currentPrice) / point
                              : (currentPrice - openPrice) / point;

            if(movePips >= HedgeTriggerPips)
              {
               ENUM_ORDER_TYPE hedgeDir = (g_initialDirection == ORDER_TYPE_BUY)
                                          ? ORDER_TYPE_SELL
                                          : ORDER_TYPE_BUY;
               double hedgeLot = NormalizeDouble(InitialLot * HedgeLotMultiple,
                                                 (int)SymbolInfoInteger(g_hedgeSymbol, SYMBOL_DIGITS));
               g_hedgeTicket = SendOrder(g_hedgeSymbol, hedgeDir, hedgeLot);
               if(g_hedgeTicket != 0)
                 {
                  g_hedgeOpen = true;
                  Print("Hedge opened. Ticket=", g_hedgeTicket,
                        " Direction=", EnumToString(hedgeDir),
                        " Lot=", hedgeLot);
                 }
              }
           }
         else
           {
            // Initial position was closed externally; reset state
            ResetState();
           }
        }

      //--- If hedge is profitable while initial has reversed, close hedge early
      if(g_hedgeOpen && g_hedgeTicket != 0)
        {
         if(PositionSelectByTicket(g_hedgeTicket))
           {
            double hedgePL = PositionGetDouble(POSITION_PROFIT);
            double initialPL = 0.0;
            if(PositionSelectByTicket(g_initialTicket))
               initialPL = PositionGetDouble(POSITION_PROFIT);

            if(hedgePL > 0 && initialPL > 0)
              {
               Print("Both legs profitable. Closing hedge leg first.");
               ClosePosition(g_hedgeTicket, g_hedgeSymbol);
               g_hedgeOpen   = false;
               g_hedgeTicket = 0;
              }
           }
         else
           {
            g_hedgeOpen   = false;
            g_hedgeTicket = 0;
           }
        }

      return; // Cluster active; no new entry
     }

   //--- No cluster open — look for a new entry signal
   double prevBid = SymbolInfoDouble(_Symbol, SYMBOL_BID); // re-read not needed; use bar data
   double prevClose[];
   ArraySetAsSeries(prevClose, true);
   if(CopyClose(_Symbol, PERIOD_CURRENT, 1, 2, prevClose) < 2)
      return;

   bool bullCross = (prevClose[1] < maBuffer[1]) && (prevClose[0] > maBuffer[0]);
   bool bearCross = (prevClose[1] > maBuffer[1]) && (prevClose[0] < maBuffer[0]);

   if(bullCross)
     {
      g_initialTicket    = SendOrder(_Symbol, ORDER_TYPE_BUY, InitialLot);
      g_initialDirection = ORDER_TYPE_BUY;
      g_hedgeOpen        = false;
      if(g_initialTicket != 0)
         Print("Initial BUY opened. Ticket=", g_initialTicket);
     }
   else if(bearCross)
     {
      g_initialTicket    = SendOrder(_Symbol, ORDER_TYPE_SELL, InitialLot);
      g_initialDirection = ORDER_TYPE_SELL;
      g_hedgeOpen        = false;
      if(g_initialTicket != 0)
         Print("Initial SELL opened. Ticket=", g_initialTicket);
     }
  }

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

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

//+------------------------------------------------------------------+
//| Send a market order and return the position ticket              |
//+------------------------------------------------------------------+
ulong SendOrder(string symbol, ENUM_ORDER_TYPE orderType, double lot)
  {
   MqlTradeRequest  request = {};
   MqlTradeResult   result  = {};

   request.action    = TRADE_ACTION_DEAL;
   request.symbol    = symbol;
   request.volume    = lot;
   request.type      = orderType;
   request.price     = (orderType == ORDER_TYPE_BUY)
                       ? SymbolInfoDouble(symbol, SYMBOL_ASK)
                       : SymbolInfoDouble(symbol, SYMBOL_BID);
   request.deviation = 10;
   request.magic     = MagicNumber;
   request.comment   = "HedgingEA";
   request.type_filling = ORDER_FILLING_IOC;

   if(!OrderSend(request, result))
     {
      Print("OrderSend failed. Error=", GetLastError(),
            " Retcode=", result.retcode);
      return 0;
     }
   return result.deal;
  }

//+------------------------------------------------------------------+
//| Calculate combined P&L of the cluster                           |
//+------------------------------------------------------------------+
double CalcClusterPL()
  {
   double total = 0.0;
   ulong tickets[2];
   tickets[0] = g_initialTicket;
   tickets[1] = g_hedgeTicket;

   for(int i = 0; i < 2; i++)
     {
      if(tickets[i] != 0 && PositionSelectByTicket(tickets[i]))
         total += PositionGetDouble(POSITION_PROFIT);
     }
   return total;
  }

//+------------------------------------------------------------------+
//| Close all positions in the cluster                              |
//+------------------------------------------------------------------+
void CloseCluster()
  {
   if(g_hedgeOpen && g_hedgeTicket != 0)
      ClosePosition(g_hedgeTicket, g_hedgeSymbol);

   if(g_initialTicket != 0)
      ClosePosition(g_initialTicket, _Symbol);

   ResetState();
  }

//+------------------------------------------------------------------+
//| Close a single position by ticket                               |
//+------------------------------------------------------------------+
void ClosePosition(ulong ticket, string symbol)
  {
   if(!PositionSelectByTicket(ticket))
      return;

   ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
   double             vol     = PositionGetDouble(POSITION_VOLUME);

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

   request.action    = TRADE_ACTION_DEAL;
   request.symbol    = symbol;
   request.volume    = vol;
   request.position  = ticket;
   request.type      = (posType == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
   request.price     = (request.type == ORDER_TYPE_SELL)
                       ? SymbolInfoDouble(symbol, SYMBOL_BID)
                       : SymbolInfoDouble(symbol, SYMBOL_ASK);
   request.deviation = 10;
   request.magic     = MagicNumber;
   request.comment   = "HedgingEA Close";
   request.type_filling = ORDER_FILLING_IOC;

   if(!OrderSend(request, result))
      Print("ClosePosition failed. Ticket=", ticket, " Error=", GetLastError());
   else
      Print("Position closed. Ticket=", ticket, " Retcode=", result.retcode);
  }

//+------------------------------------------------------------------+
//| Reset EA cluster state                                          |
//+------------------------------------------------------------------+
void ResetState()
  {
   g_initialTicket   = 0;
   g_hedgeTicket     = 0;
   g_hedgeOpen       = false;
   g_initialOpenPrice = 0.0;
  }
//+------------------------------------------------------------------+

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

Generate a Custom Multi-pair Hedging 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