Viewing the resource: Crafting a Dynamic Grid Trader Cosmic Expedition with MQL5 🚀

Crafting a Dynamic Grid Trader Cosmic Expedition with MQL5 🚀

Allan Munene Mutiiria 2025-06-21 18:41:26 104 Views
Hey there, forex adventurer! We’re about to embark on a fun, detailed journey through the MQL5 cod...

Introduction

Imagine you’re the captain of a starship, cruising through the forex galaxy, dropping trading probes at key spots to catch price swings. That’s what the Grid EA with Dynamic Lot Sizing does—it’s like your ship’s computer, automating a trading strategy that places trades at regular intervals (like a grid) and adjusts their size to maximize profits. This EA uses a 21-period Simple Moving Average (SMA) to decide when to start trading, then builds a grid of buy or sell trades every 500 pips, doubling the lot size each time (starting at 0.01 lots). It has two ways to close trades: either when all trades together hit a $100 profit, or when the price reaches the average entry price plus or minus 50 pips. Each trade aims for a 200-pip profit, like setting a destination for your probes. My goal here is to walk you through this code as if we’re chatting over coffee, making every part crystal clear for beginners. I’ll use examples, keep it engaging, and explain why each piece matters, like showing you how to steer your starship. Let’s chart this cosmic course together!

Strategy Blueprint

Before we dig into the code, let’s map out what this EA does, like sketching a star chart for your trading expedition:

  • Starting the Journey: The EA watches the 21-period SMA. When the price low crosses above the SMA, it opens a buy trade; when the high crosses below, it opens a sell. This first trade uses a small lot size (0.01) and sets a 200-pip take profit.

  • Building the Grid: If the price moves 500 pips against the trade (e.g., down for buys), the EA adds another trade with double the lot size (0.02, then 0.04, etc.), each with its own 200-pip take profit. It’s like sending out more probes to cover a wider area.

  • Closing the Expedition: You can choose one of two closure modes:

    • Profit Target: Close all trades when their combined profit hits $100, like collecting all your probes’ treasures.

    • Breakeven Points: Close all trades when the price hits the average entry price (weighted by lot sizes) plus or minus 50 pips, like safely returning to base.

  • Safety Features: Trades only start on new bars to avoid spamming, and the EA checks the SMA to align with trends, like ensuring your ship’s on the right course. This strategy is like a cosmic expedition, spreading trades to catch market swings while aiming to close them profitably, perfect for traders who want automation with smart risk control.

Code Implementation

Alright, let’s get into the code! Think of this as exploring your starship’s control panels, where each button and screen does something specific. I’ll break it down into steps, explain each part like I’m showing a newbie how it works, and use examples to make it real. We’ll go from setting up the ship to launching trades, managing the grid, and docking safely, with smooth transitions to keep it fun and clear.

Step 1: Setting Up Your Starship—Getting the EA Ready

First, we need to power up our starship by setting up the EA’s core systems, like turning on the engines and navigation tools.

//+------------------------------------------------------------------+
//|                              GRID EA WITH DYNAMIC LOT SIZING.mq5 |
//|      Copyright 2024, ALLAN MUNENE MUTIIRIA. #@Forex Algo-Trader. |
//|                           https://youtube.com/@ForexAlgo-Trader? |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, ALLAN MUNENE MUTIIRIA. #@Forex Algo-Trader"
#property link      "https://youtube.com/@ForexAlgo-Trader?"
#property description "======= IMPORTANT =======\n"
#property description "1. This is a FREE EA."
#property description "2. To get the source code of the EA, follow the Copyright link."
#property description "3. Incase of anything, contact developer via the link provided."
#property description "Hope you will enjoy the EA Logic.\n"
#property description "*** HAPPY TRADING! ***"
#property version   "1.00"

#include <Trade/Trade.mqh>
CTrade obj_Trade;

enum ClosureMode{
   CLOSE_BY_PROFIT,CLOSE_BY_POINTS
};

input ClosureMode closureMode = CLOSE_BY_POINTS;

double breakevenPoints = 50*_Point;
double TakeProfit;
double initialLotsize = 0.1;
double takeProfitPoints = 200 *_Point;
double profitTotal_inCurrency = 100;

double gridSize;
double gridSize_spacing = 500*_Point;
double Lotsize;

bool isTradeAllowed = true;
int totalBars = 0;
int handle = INVALID_HANDLE;
double maData[];

int OnInit(){
   handle = iMA(_Symbol,_Period,21,0,MODE_SMA,PRICE_CLOSE);
   if (handle == INVALID_HANDLE){
      Print("ERROR: FAILED TO INITIALIZE THE MA. REVERTING NOW");
      return (INIT_FAILED);
   }
   Print("Handle ID = ",handle);
   ArraySetAsSeries(maData,true);
   return(INIT_SUCCEEDED);
}

What’s Happening Here?Imagine you’re in the starship’s cockpit, flipping switches to get ready. The #property section is like your ship’s ID, showing it’s a free EA by Allan in 2024 with a YouTube link for support. We include "Trade/Trade.mqh" to let "obj_Trade" handle trading, like installing a trading autopilot. The enum ClosureMode lets you choose how to close trades ("CLOSE_BY_PROFIT" for $100 or "CLOSE_BY_POINTS" for breakeven), set as an input so you can tweak it later.

We define variables like "breakevenPoints" (50 pips, scaled by "_Point"), "initialLotsize" (0.1 lots), "takeProfitPoints" (200 pips), "profitTotal_inCurrency" ($100), and "gridSize_spacing" (500 pips), like setting your ship’s default coordinates. "isTradeAllowed" (true) controls new trades, "totalBars" tracks bars, "handle" and "maData[]" manage the 21-period SMA.

In "OnInit()", we set up the SMA with "iMA()", checking it works (if "handle == INVALID_HANDLE", we stop with "INIT_FAILED"). We log the handle ID with "Print()", set "maData" as a time series with "ArraySetAsSeries()", and return INIT_SUCCEEDED, like saying, “Ship’s ready, captain!” This gets our radar ready to spot trade signals, like powering up your navigation screen.

Step 2: Launching the First Probe—Starting the Grid

Now, let’s launch our first trade when the price crosses the SMA, like sending out your initial probe to explore the market.

bool IsNewBar(){
   int bars = iBars(_Symbol,_Period);
   if (bars > totalBars){
      totalBars = bars;
      return true;
   }
   return false;
}

void UpdateMovingAverage(){
   if (CopyBuffer(handle,0,1,3,maData) < 3)
      Print("ERROR: UNABLE TO UPDATE MOVING AVERAGE DATA");
}

void ExecuteInitialTrade(double ask, double bid){
   if (iLow(_Symbol,_Period,1) > maData[1] && iLow(_Symbol,_Period,2) < maData[1]){
      Print("BUY SIGNAL");
      gridSize = ask - gridSize_spacing;
      TakeProfit = ask + takeProfitPoints;
      if (obj_Trade.Buy(Lotsize,_Symbol,ask,0,TakeProfit,"Initial Buy"))
         Print("Initial Buy order executed at ",ask," with lot ",Lotsize);
      else
         Print("Initial Buy failed at ",ask);
      isTradeAllowed = false;   
   }
   else if (iHigh(_Symbol,_Period,1) < maData[1] && iHigh(_Symbol,_Period,2) > maData[1]){
      Print("SELL SIGNAL");
      gridSize = bid + gridSize_spacing;
      TakeProfit = bid - takeProfitPoints;
      if (obj_Trade.Sell(Lotsize,_Symbol,bid,0,TakeProfit,"Initial Sell"))
         Print("Initial Sell order executed at ",bid," with lot ",Lotsize);
      else
         Print("Initial Sell failed at ",bid);
      isTradeAllowed = false;   
   }
}

void OnTick(){
   if (closureMode == CLOSE_BY_PROFIT)
      CheckAndCloseProfitTargets();
   
   if (IsNewBar())
      isTradeAllowed = true;
   
   UpdateMovingAverage();
   
   if (PositionsTotal() == 0){
      Lotsize = initialLotsize;
   }
   
   double low1 = iLow(_Symbol,_Period,1);
   double high1 = iHigh(_Symbol,_Period,1);
   double ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   
   if (PositionsTotal() == 0 && isTradeAllowed){
      ExecuteInitialTrade(ask,bid);
   }
}

What’s Happening Here?Okay, let’s pretend we’re in the control room, watching the market on a big screen. The "OnTick()" function runs every price tick, like your ship’s sensors constantly checking the market. It first checks if we’re using "CLOSE_BY_PROFIT" mode with "CheckAndCloseProfitTargets()", which we’ll cover later. It calls "IsNewBar()" to see if a new candle has formed using "iBars()", updating "totalBars" and setting "isTradeAllowed" to true, like giving your ship a green light to launch probes on new data.

"UpdateMovingAverage()" grabs the latest SMA data with "CopyBuffer()", pulling 3 bars into "maData", logging errors if it fails, like ensuring your navigation screen is up to date. If no trades are open ("PositionsTotal() == 0"), we reset "Lotsize" to "initialLotsize" (0.1), like prepping your first probe.

In "ExecuteInitialTrade()", we check for a signal by comparing the low and high of the last two bars ("iLow()", "iHigh()") against the SMA ("maData[1]"). For a buy, the low of bar 1 must be above the SMA, and bar 2’s low below it ("iLow(_Symbol,_Period,1) > maData[1] && iLow(_Symbol,_Period,2) < maData[1]"), like the price crossing upward. We set "gridSize" 500 pips below the ask ("ask - gridSize_spacing") for the next trade, set "TakeProfit" 200 pips above ("ask + takeProfitPoints"), and open a buy with "obj_Trade.Buy()", logging success or failure with "Print()". Sells work the opposite way, checking highs crossing below the SMA. Setting "isTradeAllowed = false" prevents multiple initial trades, like ensuring only one probe launches at a time. For example, if EURUSD’s low crosses above the SMA at 1.2000, the EA buys 0.1 lots with a take profit at 1.2200, logging “BUY SIGNAL”.

Step 3: Expanding the Grid—Adding More Probes

If the market moves against us, we add more trades to the grid, like sending out additional probes to cover more ground.

void ManageGridPositions(double ask, double bid){
   for (int i=PositionsTotal()-1; i>=0; i--){
      ulong ticket = PositionGetTicket(i);
      if (PositionSelectByTicket(ticket)){
         int positionType = (int)PositionGetInteger(POSITION_TYPE);
         if (positionType == POSITION_TYPE_BUY){
            if (ask <= gridSize){
               Lotsize *= 2;
               if (obj_Trade.Buy(Lotsize,_Symbol,ask,0,TakeProfit,"Grid Position BUY"))
                  Print("Grid BUY order executed at ",ask," with lots: ",Lotsize);
               else
                  Print("Grid BUY failed at ",ask);
               gridSize = ask - gridSize_spacing;   
            }
         }
         else if (positionType == POSITION_TYPE_SELL){
            if (bid >= gridSize){
               Lotsize *= 2;
               if (obj_Trade.Sell(Lotsize,_Symbol,bid,0,TakeProfit,"Grid Position SELL"))
                  Print("Grid SELL order executed at ",bid," with lots: ",Lotsize);
               else
                  Print("Grid SELL failed at ",bid);
               gridSize = bid + gridSize_spacing;   
            }
         }
      }
   }
}

void OnTick(){
   // ... (initial trade logic)
   if (PositionsTotal() > 0){
      ManageGridPositions(ask, bid);
   }
}

What’s Happening Here?Now, imagine your first probe is out, but the market’s moving against you—like EURUSD dropping to 1.1950 after your buy at 1.2000. The "ManageGridPositions()" function, called in "OnTick()" when trades are open ("PositionsTotal() > 0"), checks if it’s time to add more probes.

We loop through open positions with "PositionsTotal()", grabbing each trade’s ticket using "PositionGetTicket()", "PositionSelectByTicket()". We check the trade type with "PositionGetInteger(POSITION_TYPE)". For buys ("POSITION_TYPE_BUY"), if the ask price hits or falls below "gridSize" ("ask <= gridSize", e.g., 1.1950, 500 pips below 1.2000), we double "Lotsize" (0.1 to 0.2), open a new buy with "obj_Trade.Buy()", and update "gridSize" 500 pips lower ("ask - gridSize_spacing"). Sells work similarly, adding trades when the bid rises 500 pips above "gridSize". Each new trade uses the same "TakeProfit" (e.g., 1.2200 for buys), like aligning all probes to the same destination. The EA logs each trade with "Print()", like “Grid BUY order executed at 1.1950 with lots: 0.2”. This builds a grid, like spreading probes to catch a price bounce back.

Step 4: Collecting the Payload—Closing Trades Smartly

Finally, we close trades when we hit our profit or breakeven targets, like gathering your probes’ treasures or returning to base.

void CheckAndCloseProfitTargets(){
   if (PositionsTotal() > 1){
      double totalProfit = 0;
      for (int i=PositionsTotal()-1; i>=0; i--){
         ulong ticket = PositionGetTicket(i);
         if (PositionSelectByTicket(ticket)){
            totalProfit += PositionGetDouble(POSITION_PROFIT);
         }
      }
      if (totalProfit >= profitTotal_inCurrency){
         Print("PROFIT TARGET REACHED (",totalProfit,"). CLOSING ALL POSITIONS NOW.");
         CloseAllPositions();
      }
   }
}

void CheckBreakevenClose(double ask, double bid){
   if (PositionsTotal() <= 1)
      return;
   double weightedBrekeven = CalculateTheWeightedBreakEvenPrice();
   int posType = -1;
   
   for (int i=0; i<PositionsTotal(); i++){
      ulong ticket = PositionGetTicket(i);
      if (PositionSelectByTicket(ticket)){
         posType = (int)PositionGetInteger(POSITION_TYPE);
         break;
      }
   }
   
   if (posType == -1)
      return;
   
   if (posType == POSITION_TYPE_BUY){
      if (bid >= weightedBrekeven + breakevenPoints){
         Print("CLOSING BUY POSITIONS: BID (",bid,") >= BREAKEVEN (",weightedBrekeven,") + ",breakevenPoints);
         CloseAllPositions();
      }
   }
   else if (posType == POSITION_TYPE_SELL){
      if (ask <= weightedBrekeven - breakevenPoints){
         Print("CLOSING SELL POSITIONS: ASK (",ask,") <= BREAKEVEN (",weightedBrekeven,") + ",breakevenPoints);
         CloseAllPositions();
      }
   }
}

double CalculateTheWeightedBreakEvenPrice(){
   double totalCost = 0;
   double totalVolume = 0;
   int posType = -1;
   
   for (int i=0; i<PositionsTotal(); i++){
      ulong ticket = PositionGetTicket(i);
      if (PositionSelectByTicket(ticket)){
         posType = (int)PositionGetInteger(POSITION_TYPE);
         break;
      }
   }
   for (int i=0; i<PositionsTotal(); i++){
      ulong ticket = PositionGetTicket(i);
      if (PositionSelectByTicket(ticket)){
         if (PositionGetInteger(POSITION_TYPE) == posType){
            double price = PositionGetDouble(POSITION_PRICE_OPEN);
            double volume = PositionGetDouble(POSITION_VOLUME);
            totalCost += price * volume;
            totalVolume += volume;
         }
      }
   }
   if (totalVolume > 0){
      return(totalCost/totalVolume);
   }
   else 
      return (0);
}

void CloseAllPositions(){
   for (int i=PositionsTotal()-1; i>=0; i--){
      ulong ticket = PositionGetTicket(i);
      if (PositionSelectByTicket(ticket)){
         if (obj_Trade.PositionClose(ticket))
            Print("Closed position with ticket: ",ticket);
         else
            Print("Failed to close position with ticket: ",ticket);
      }
   }
}

void OnTick(){
   // ... (grid management)
   if (closureMode == CLOSE_BY_POINTS && PositionsTotal() > 1){
      CheckBreakevenClose(ask, bid);
   }
}

What’s Happening Here?Let’s say your grid has grown—maybe you have buys at 1.2000 (0.1 lots), 1.1950 (0.2 lots), and 1.1900 (0.4 lots) on EURUSD. Now, it’s time to bring those probes home! The EA has two ways to do this, depending on "closureMode".

In "CheckAndCloseProfitTargets()", used when "closureMode == CLOSE_BY_PROFIT", we loop through trades with "PositionsTotal()", summing profits with "PositionGetDouble(POSITION_PROFIT)". If "totalProfit >= profitTotal_inCurrency" ($100), we call "CloseAllPositions()", which closes each trade with "obj_Trade.PositionClose()", logging results with "Print()", like “PROFIT TARGET REACHED (105.23). CLOSING ALL POSITIONS NOW.” This is like collecting $100 worth of treasure from your probes.

For "CLOSE_BY_POINTS", "CheckBreakevenClose()" kicks in when there’s more than one trade ("PositionsTotal() > 1"). It uses "CalculateTheWeightedBreakEvenPrice()", which loops through trades to sum the cost (price times volume) and volume ("PositionGetDouble(POSITION_PRICE_OPEN)", "POSITION_VOLUME"), calculating the average entry price ("totalCost/totalVolume"). For buys, if the bid price exceeds this breakeven plus 50 pips ("bid >= weightedBrekeven + breakevenPoints"), we close all trades. For sells, it’s when the ask falls below breakeven minus 50 pips. For example, if your buys have a weighted breakeven of 1.1930, and the bid hits 1.1980, the EA logs “CLOSING BUY POSITIONS: BID (1.1980) >= BREAKEVEN (1.1930) + 0.0050” and closes everything, like safely docking your ship.

Step 5: Docking the Starship—Cleaning Up

When the expedition’s over, we tidy up to leave the chart clean.

void OnDeinit(const int reason){
}

What’s Happening Here?In "OnDeinit()", the code is empty, like leaving your starship’s screens on. We could add "IndicatorRelease(handle)" to free the SMA and "ArrayFree(maData)" to clear the buffer, like shutting down your navigation system, but for now, it’s a light cleanup. This means the EA doesn’t leave junk behind, but it could be cleaner with those additions.

Why This EA’s a Cosmic Legend (and Keeps You Engaged!)

This EA is a grid-trading legend, spreading trades like probes across the forex galaxy to catch price swings. Its dynamic lot sizing and dual closure modes make it versatile, though doubling lots needs careful risk management (see notes). Example? Start a buy grid on EURUSD at 1.2000, add trades at 1.1950 and 1.1900, and close at a $100 profit or breakeven at 1.1930 + 50 pips—pure cosmic treasure! Beginners will love the clear setup, and pros can tweak it, making it a must-have for grid traders.

Putting It All Together

To launch this EA:

  1. Open MetaEditor in MetaTrader 5, like stepping into your starship’s cockpit.

  2. Copy the code, hit F5 to compile, and fix any typos—no captain wants a glitchy ship!

  3. Drop the EA on your chart, enable AutoTrading, and watch it build a grid of trades based on SMA signals.

  4. Check logs for signals (e.g., “BUY SIGNAL”, “CLOSING BUY POSITIONS”) to track your expedition, like reading mission reports.

  5. Test on a demo account first—real pips deserve a practice run!

Conclusion

We’ve built a Dynamic Grid Trader that’s like a starship navigating the forex galaxy, launching trades at set intervals, doubling lots, and closing them with profit or breakeven targets. This MQL5 code is your navigation computer, explained in a way that feels like a friendly chat, packed with examples to make it real, and designed to spark your trading curiosity. Ready to explore? Check our video guide on the website for a front-row seat to this cosmic expedition. Now go conquer those market stars! 🌌

Disclaimer: Trading’s like a space expedition—exciting but risky. Losses can exceed deposits. Test on a demo account before going live.

Disclaimer: The ideas and strategies presented in this resource are solely those of the author and are intended for informational and educational purposes only. They do not constitute financial advice, and past performance is not indicative of future results. All materials, including but not limited to text, images, files, and any downloadable content, are protected by copyright and intellectual property laws and are the exclusive property of Forex Algo-Trader or its licensors. Reproduction, distribution, modification, or commercial use of these materials without prior written consent from Forex Algo-Trader is strictly prohibited and may result in legal action. Users are advised to exercise extreme caution, perform thorough independent research, and consult with qualified financial professionals before implementing any trading strategies or decisions based on this resource, as trading in financial markets involves significant risk of loss.

Recent Comments

Go to discussion to Comment or View other Comments

No comments yet. Be the first to comment!