Complete .mq5 source code

Gold Grid EA MT5: MQL5 Mechanics and Exposure Limits

Inspect a buy-only grid EA example with point-based spacing, increasing lots and basket-profit closure. It requires a hedging account and has no stop-loss or equity-loss cap. The source explains the mechanics; no verified gold backtest or safe account size is established here.

Strategy logic

Entry conditions

For the chart symbol, request an initial buy when no matching symbol-and-magic positions exist. Add a buy when the current ask is at least GridStep points below the lowest matching entry, up to MaxOrders separate positions. Requested lots follow InitialLots times LotMultiplier raised to the current position count, rounded down to the broker volume step. The example rejects netting accounts because position count would not count grid entries correctly. Use one instance per symbol and magic number.

Exit conditions

When matching floating position profit plus swap reaches ProfitTarget in account currency, latch basket closure and retry remaining positions on subsequent ticks. This is a requested threshold, not guaranteed realized net profit: commissions, price movement and partial/rejected fills matter. A new grid starts after the basket is empty. There is no stop-loss, equity stop or maximum loss; a position cap only limits additions. Closure state is not persisted across a restart.

MQL5 Expert Advisor Code

//+------------------------------------------------------------------+
//| Gold Grid EA - XAUUSD                                           |
//| Pineify.app — WARNING: Grid EAs carry significant risk          |
//+------------------------------------------------------------------+
#property copyright "Pineify.app"
#property version   "1.00"

input int    MagicNumber  = 345678;
input double InitialLots  = 0.01;
input double LotMultiplier= 1.5;
input int    GridStep     = 150;   // Grid spacing in points
input int    MaxOrders    = 8;
input double ProfitTarget = 50.0;  // Account-currency floating profit + swap threshold

bool closingBasket=false;
int OnInit() {
   if(MagicNumber<0 || InitialLots<=0 || LotMultiplier<1 || GridStep<=0 || MaxOrders<1 || ProfitTarget<=0)
      return INIT_PARAMETERS_INCORRECT;
   if(AccountInfoInteger(ACCOUNT_MARGIN_MODE)!=ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) {
      Print("This position-count grid requires a hedging account.");
      return INIT_FAILED;
   }
   return INIT_SUCCEEDED;
}
void OnDeinit(const int reason) {}

void OnTick() {
   int openOrders = CountPositions(MagicNumber);
   double floatingProfit = GetFloatingProfit(MagicNumber);

   if(openOrders==0) closingBasket=false;
   if(openOrders>0 && floatingProfit>=ProfitTarget) closingBasket=true;
   // Continue closing after partial/rejected requests even if profit changes.
   if (closingBasket) {
      CloseAllPositions(MagicNumber);
      return;
   }

   // Open initial order
   if (openOrders == 0) {
      OpenTrade(ORDER_TYPE_BUY, InitialLots, MagicNumber);
      return;
   }

   // Add grid orders if price drops GridStep from lowest order
   if (openOrders < MaxOrders) {
      double lowestPrice = GetLowestOrderPrice(MagicNumber);
      double currentAsk  = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      if (currentAsk>0 && lowestPrice!=DBL_MAX && lowestPrice - currentAsk >= GridStep * _Point) {
         double nextLots = InitialLots * MathPow(LotMultiplier, openOrders);
         OpenTrade(ORDER_TYPE_BUY, nextLots, MagicNumber);
      }
   }
}

double GetLowestOrderPrice(int magic) {
   double lowest = DBL_MAX;
   for (int i = PositionsTotal() - 1; i >= 0; i--) {
      ulong ticket = PositionGetTicket(i);
      if (PositionSelectByTicket(ticket) &&
          (int)PositionGetInteger(POSITION_MAGIC) == magic &&
          PositionGetString(POSITION_SYMBOL)==_Symbol) {
         double price = PositionGetDouble(POSITION_PRICE_OPEN);
         if (price < lowest) lowest = price;
      }
   }
   return lowest;
}

double GetFloatingProfit(int magic) {
   double total = 0;
   for (int i = PositionsTotal() - 1; i >= 0; i--) {
      ulong ticket = PositionGetTicket(i);
      if (PositionSelectByTicket(ticket) &&
          (int)PositionGetInteger(POSITION_MAGIC) == magic &&
          PositionGetString(POSITION_SYMBOL)==_Symbol)
         total += PositionGetDouble(POSITION_PROFIT) + PositionGetDouble(POSITION_SWAP);
   }
   return total;
}

void CloseAllPositions(int magic) {
   for (int i = PositionsTotal() - 1; i >= 0; i--) {
      ulong ticket = PositionGetTicket(i);
      if (!PositionSelectByTicket(ticket)) continue;
      if ((int)PositionGetInteger(POSITION_MAGIC) != magic ||
          PositionGetString(POSITION_SYMBOL)!=_Symbol) continue;
      MqlTradeRequest req = {}; MqlTradeResult res = {};
      req.action   = TRADE_ACTION_DEAL;
      req.position = ticket;
      req.symbol   = _Symbol;
      req.volume   = PositionGetDouble(POSITION_VOLUME);
      req.type     = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
                     ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
      req.price    = (req.type == ORDER_TYPE_SELL)
                     ? SymbolInfoDouble(_Symbol, SYMBOL_BID)
                     : SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      req.type_filling = ORDER_FILLING_IOC;
      if(!OrderSend(req,res) || (res.retcode!=TRADE_RETCODE_DONE && res.retcode!=TRADE_RETCODE_DONE_PARTIAL))
         PrintFormat("Grid close failed: %u %s",res.retcode,res.comment);
   }
}

int CountPositions(int magic) {
   int count = 0;
   for (int i = PositionsTotal() - 1; i >= 0; i--) {
      ulong ticket = PositionGetTicket(i);
      if (PositionSelectByTicket(ticket) &&
          (int)PositionGetInteger(POSITION_MAGIC) == magic &&
          PositionGetString(POSITION_SYMBOL)==_Symbol) count++;
   }
   return count;
}

void OpenTrade(ENUM_ORDER_TYPE type, double lots, int magic) {
   double step=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   double minLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   double maxLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX);
   if(step<=0 || minLot<=0 || maxLot<minLot || !MathIsValidNumber(lots)) {
      Print("Invalid symbol volume properties or requested lots"); return;
   }
   lots=NormalizeDouble(MathFloor((lots+1e-10)/step)*step,8);
   if(lots<minLot || lots>maxLot) {
      Print("Grid order rejected by example volume limits: ",lots); return;
   }
   MqlTradeRequest req = {}; MqlTradeResult res = {};
   req.action = TRADE_ACTION_DEAL; req.symbol = _Symbol; req.volume = lots;
   req.type   = type;
   req.price  = (type == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
                                         : SymbolInfoDouble(_Symbol, SYMBOL_BID);
   req.magic  = magic; req.comment = "Pineify Grid";
   req.type_filling = ORDER_FILLING_IOC;
   if(!OrderSend(req,res) || (res.retcode!=TRADE_RETCODE_DONE && res.retcode!=TRADE_RETCODE_DONE_PARTIAL))
      PrintFormat("Grid entry failed: %u %s",res.retcode,res.comment);
}

Copy this code into MetaEditor, save it in the MQL5/Experts folder, and compile with F7.

Generate a custom XAUUSD grid EA

Describe the entry, exit, position, order, and risk rules you want. Pineify generates editable MQL5 source code that you can inspect and compile in MetaEditor.

Pine Script vs MQL5: Same Strategy, Different Platforms

AspectPine Script (TradingView)MQL5 (MetaTrader 5)
ExecutionSeries evaluated on chart updatesEvent handlers with explicit buffers
DeploymentRuns in TradingView with alertsRuns in the MT5 terminal or on a VPS
Broker accessStrategy orders are simulated; live automation needs a separate integrationDirect broker connectivity
BacktestingStrategy Tester for strategy scriptsStrategy Tester for Expert Advisors
Code complexitySimpler, functional syntaxC++-like, more powerful

The calculation can be implemented on either platform, but the runtime model and buffer APIs differ.

Frequently Asked Questions

Related MQL5 pages

Technical references

Risk and testing note

These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.