Summary: Educational Martingale EA for MT4 with complete MQL4 source code. Features adjustable lot multiplier, step distance, maximum trades limit, and equity drawdown protection. Includes strategy explanation and risk warnings.




Free Martingale EA Source Code for MT4 – Complete MQL4 Code



Important Disclaimer First



Martingale strategies carry significant risk. While they show high win rates, a single losing streak can lead to exponential losses. This EA is provided for educational purposes only – to help you understand how grid and martingale systems work internally. Never use this on a live account without thorough testing and strict risk limits.

How This Martingale EA Works



The logic is simple but powerful:

  • <strong>Initial trade</strong> opens with a base lot size in the direction of your choice (or based on a simple moving average crossover)

  • <strong>If the trade goes into loss</strong> by a specified number of pips (Step), the EA opens a new trade in the <strong>same direction</strong>

  • <strong>Each subsequent trade</strong> increases lot size by a multiplier (e.g., 2x)

  • <strong>When price retraces</strong>, the accumulated profit from all open positions closes the entire grid


  • Example Scenario



    | Trade # | Lot Size | Entry Price (Buy) | Loss at 20 pips |
    |---------|----------|-------------------|-----------------|
    | 1 | 0.01 | 1.1000 | -$2.00 |
    | 2 | 0.02 | 1.0980 | -$4.00 |
    | 3 | 0.04 | 1.0960 | -$8.00 |
    | 4 | 0.08 | 1.0940 | -$16.00 |

    Total loss at 1.0940: -$30.00. A retrace of 20 pips to 1.0960 recovers all losses and turns profitable.

    Key Features



    | Feature | Description |
    |---------|-------------|
    | Adjustable multiplier | Lot increase factor (1.5x to 3x typical) |
    | Configurable step distance | Pips between each grid level |
    | Max trades limit | Prevents unlimited grid expansion |
    | Equity drawdown protection | Auto-closes all trades if equity falls below threshold |
    | Take profit target | Closes all grid trades when total profit hits target |
    | Direction control | Buy-only, sell-only, or signal-based |

    Complete MQL4 Source Code



    Copy the entire code below, save it as Martingale_Grid_EA.mq4 in your MQL4/Experts/ folder, then compile.

    ``cpp
    //+------------------------------------------------------------------+
    //| Martingale_Grid_EA.mq4 |
    //| 自主编译 |
    //| |
    //+------------------------------------------------------------------+
    #property copyright "ForexEA Blog"
    #property link ""
    #property version "1.00"
    #property strict

    //--- input parameters
    input double LotSize = 0.01; // Base lot size
    input double LotMultiplier = 2.0; // Lot multiplier (1.5 - 3.0 typical)
    input int StepPips = 20; // Step distance in pips
    input int MaxTrades = 5; // Maximum number of grid trades
    input double TakeProfitPips = 20; // Take profit target in pips
    input double MaxEquityDrawdown = 30.0; // Max equity drawdown % - close all if exceeded
    input int Slippage = 3; // Slippage in points
    input bool UseMAFilter = false; // Use MA filter for direction
    input int MAPeriod = 50; // MA period for filter
    input bool TradeBuyOnly = false; // Only open buy trades
    input bool TradeSellOnly = false; // Only open sell trades
    input int MagicNumber = 20260603; // EA identifier

    //--- global variables
    double point;
    int digits;
    double step_points;
    double tp_points;
    bool is_buy_grid = false;
    bool is_sell_grid = false;
    int buy_trades = 0;
    int sell_trades = 0;
    double last_buy_price = 0;
    double last_sell_price = 0;
    double initial_equity;

    //+------------------------------------------------------------------+
    //| Expert initialization function |
    //+------------------------------------------------------------------+
    int OnInit()
    {
    //--- Initialize pip value
    point = Point;
    if(Digits == 3 || Digits == 5)
    point = Point 10;

    step_points = StepPips
    point;
    tp_points = TakeProfitPips point;

    initial_equity = AccountEquity();

    Print("Martingale EA initialized");
    Print("Step distance: ", StepPips, " pips");
    Print("Take profit: ", TakeProfitPips, " pips");
    Print("Max trades: ", MaxTrades);

    return(INIT_SUCCEEDED);
    }

    //+------------------------------------------------------------------+
    //| Expert deinitialization function |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
    {
    Print("Martingale EA removed. Reason: ", reason);
    }

    //+------------------------------------------------------------------+
    //| Expert tick function |
    //+------------------------------------------------------------------+
    void OnTick()
    {
    //--- Equity protection check
    double current_equity = AccountEquity();
    double equity_drawdown_pct = (initial_equity - current_equity) / initial_equity
    100;

    if(equity_drawdown_pct > MaxEquityDrawdown)
    {
    Print("Max equity drawdown reached (", equity_drawdown_pct, "%). Closing all trades.");
    CloseAllTrades();
    return;
    }

    //--- Count current grid trades
    CountGridTrades();

    //--- Check take profit
    CheckTakeProfit();

    //--- Open new trades if needed
    if(!is_buy_grid && buy_trades == 0 && (TradeBuyOnly || (!TradeSellOnly && GetTradeDirection() == 1)))
    {
    OpenBuyTrade();
    }

    if(!is_sell_grid && sell_trades == 0 && (TradeSellOnly || (!TradeBuyOnly && GetTradeDirection() == -1)))
    {
    OpenSellTrade();
    }

    //--- Add to existing grid if price moved against us
    if(is_buy_grid && buy_trades > 0 && buy_trades < MaxTrades)
    {
    double current_bid = Bid;
    double next_step_price = last_buy_price - step_points;
    if(current_bid <= next_step_price)
    {
    OpenBuyTrade();
    }
    }

    if(is_sell_grid && sell_trades > 0 && sell_trades < MaxTrades)
    {
    double current_ask = Ask;
    double next_step_price = last_sell_price + step_points;
    if(current_ask >= next_step_price)
    {
    OpenSellTrade();
    }
    }
    }

    //+------------------------------------------------------------------+
    //| Count open grid trades |
    //+------------------------------------------------------------------+
    void CountGridTrades()
    {
    buy_trades = 0;
    sell_trades = 0;
    is_buy_grid = false;
    is_sell_grid = false;

    for(int i = 0; i < OrdersTotal(); i++)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    {
    if(OrderType() == OP_BUY)
    {
    buy_trades++;
    if(OrderOpenPrice() > last_buy_price)
    last_buy_price = OrderOpenPrice();
    is_buy_grid = true;
    }
    else if(OrderType() == OP_SELL)
    {
    sell_trades++;
    if(OrderOpenPrice() < last_sell_price || last_sell_price == 0)
    last_sell_price = OrderOpenPrice();
    is_sell_grid = true;
    }
    }
    }
    }
    }

    //+------------------------------------------------------------------+
    //| Open a buy trade in the grid |
    //+------------------------------------------------------------------+
    void OpenBuyTrade()
    {
    double lot = LotSize MathPow(LotMultiplier, buy_trades);

    if(lot > 50) lot = 50; // Safety cap
    if(lot < LotSize) lot = LotSize;

    lot = NormalizeDouble(lot, 2);

    int ticket = OrderSend(Symbol(), OP_BUY, lot, Ask, Slippage, 0, 0, "Martingale Buy", MagicNumber, 0, clrGreen);

    if(ticket > 0)
    {
    Print("Buy trade opened. #", ticket, " Lot: ", lot);
    last_buy_price = Ask;
    }
    else
    {
    Print("Failed to open buy trade. Error: ", GetLastError());
    }
    }

    //+------------------------------------------------------------------+
    //| Open a sell trade in the grid |
    //+------------------------------------------------------------------+
    void OpenSellTrade()
    {
    double lot = LotSize
    MathPow(LotMultiplier, sell_trades);

    if(lot > 50) lot = 50;
    if(lot < LotSize) lot = LotSize;

    lot = NormalizeDouble(lot, 2);

    int ticket = OrderSend(Symbol(), OP_SELL, lot, Bid, Slippage, 0, 0, "Martingale Sell", MagicNumber, 0, clrRed);

    if(ticket > 0)
    {
    Print("Sell trade opened. #", ticket, " Lot: ", lot);
    last_sell_price = Bid;
    }
    else
    {
    Print("Failed to open sell trade. Error: ", GetLastError());
    }
    }

    //+------------------------------------------------------------------+
    //| Check and close grid when profit target reached |
    //+------------------------------------------------------------------+
    void CheckTakeProfit()
    {
    double total_profit = 0;

    for(int i = 0; i < OrdersTotal(); i++)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    {
    total_profit += OrderProfit() + OrderSwap() + OrderCommission();
    }
    }
    }

    double total_profit_pips = 0;
    if(is_buy_grid && buy_trades > 0)
    {
    double avg_price = GetAverageBuyPrice();
    total_profit_pips = (Bid - avg_price) / point;
    }
    else if(is_sell_grid && sell_trades > 0)
    {
    double avg_price = GetAverageSellPrice();
    total_profit_pips = (avg_price - Ask) / point;
    }

    if(total_profit_pips >= TakeProfitPips || total_profit >= 0.01)
    {
    Print("Take profit reached (", total_profit_pips, " pips). Closing all grid trades.");
    CloseAllTrades();
    }
    }

    //+------------------------------------------------------------------+
    //| Get average buy price of all buy grid trades |
    //+------------------------------------------------------------------+
    double GetAverageBuyPrice()
    {
    double total_price = 0;
    double total_lots = 0;

    for(int i = 0; i < OrdersTotal(); i++)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_BUY)
    {
    total_price += OrderOpenPrice() OrderLots();
    total_lots += OrderLots();
    }
    }
    }

    if(total_lots > 0)
    return total_price / total_lots;
    return 0;
    }

    //+------------------------------------------------------------------+
    //| Get average sell price of all sell grid trades |
    //+------------------------------------------------------------------+
    double GetAverageSellPrice()
    {
    double total_price = 0;
    double total_lots = 0;

    for(int i = 0; i < OrdersTotal(); i++)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == OP_SELL)
    {
    total_price += OrderOpenPrice()
    OrderLots();
    total_lots += OrderLots();
    }
    }
    }

    if(total_lots > 0)
    return total_price / total_lots;
    return 0;
    }

    //+------------------------------------------------------------------+
    //| Close all grid trades |
    //+------------------------------------------------------------------+
    void CloseAllTrades()
    {
    for(int i = OrdersTotal() - 1; i >= 0; i--)
    {
    if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
    {
    if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
    {
    bool closed = false;
    if(OrderType() == OP_BUY)
    {
    closed = OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrWhite);
    }
    else if(OrderType() == OP_SELL)
    {
    closed = OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrWhite);
    }

    if(closed)
    Print("Closed order #", OrderTicket());
    else
    Print("Failed to close order #", OrderTicket(), ". Error: ", GetLastError());
    }
    }
    }

    is_buy_grid = false;
    is_sell_grid = false;
    buy_trades = 0;
    sell_trades = 0;
    }

    //+------------------------------------------------------------------+
    //| Get trade direction based on MA filter or manual setting |
    //+------------------------------------------------------------------+
    int GetTradeDirection()
    {
    if(UseMAFilter)
    {
    double ma_current = iMA(Symbol(), 0, MAPeriod, 0, MODE_SMA, PRICE_CLOSE, 0);
    double ma_previous = iMA(Symbol(), 0, MAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);

    if(ma_current > ma_previous)
    return 1; // Buy
    else if(ma_current < ma_previous)
    return -1; // Sell
    }

    return 1; // Default buy
    }
    //+------------------------------------------------------------------+
    `

    Installation Instructions



    Step 1: Copy the complete code above
    Step 2: Open MetaTrader 4 → File → Open Data Folder → MQL4 → Experts
    Step 3: Create a new file named
    Martingale_Grid_EA.mq4
    Step 4: Paste the code and press Compile (F7)
    Step 5: Ensure compilation succeeds (0 errors)
    Step 6: Attach to any chart and enable AutoTrading

    Parameter Explanation



    | Parameter | Default | Description |
    |-----------|---------|-------------|
    |
    LotSize | 0.01 | Base lot for first trade |
    |
    LotMultiplier | 2.0 | Multiply lot size by this factor each step |
    |
    StepPips | 20 | Pips between grid levels |
    |
    MaxTrades | 5 | Maximum grid depth (safety limit) |
    |
    TakeProfitPips | 20 | Close all when total profit hits this |
    |
    MaxEquityDrawdown | 30.0 | Emergency close if equity drops X% |
    |
    UseMAFilter | false | Enable MA direction filter |
    |
    TradeBuyOnly | false | Only open buy grids |
    |
    TradeSellOnly | false | Only open sell grids |

    Risk Assessment Matrix



    | MaxTrades | LotMultiplier | Worst Case Loss (0.01 base) |
    |-----------|---------------|-----------------------------|
    | 3 | 2.0 | 0.01 + 0.02 + 0.04 = 0.07 lots |
    | 5 | 2.0 | 0.01 + 0.02 + 0.04 + 0.08 + 0.16 = 0.31 lots |
    | 5 | 1.5 | 0.01 + 0.015 + 0.0225 + 0.0338 + 0.0507 = 0.132 lots |
    | 8 | 2.0 | Exceeds 2.5 lots quickly – extremely dangerous |

    Recommendation: Start with
    MaxTrades=3 and LotMultiplier=1.5` on a demo account only.

    How to Use Safely



    | Rule | Explanation |
    |------|-------------|
    | Demo only first | Run on demo for 3 months minimum |
    | Set MaxTrades=3 | Limits grid depth |
    | Use small base lot | 0.01 for every $10,000 account |
    | Set equity protection | 20-30% drawdown limit |
    | Avoid news events | High volatility can skip step levels |
    | Use on ranging markets | Martingale fails in strong trends |

    When This EA Works vs Fails



    | Market Condition | Performance | Reason |
    |------------------|-------------|--------|
    | Ranging / Sideways | Good | Price oscillates, grid captures both directions |
    | Weak trend (pullbacks) | Acceptable | Retracements close grid positions |
    | Strong one-direction trend | Dangerous | Grid keeps adding losing positions without reversal |

    Compilation Troubleshooting



    | Issue | Solution |
    |-------|----------|
    | OrderSend error 4109 | Enable AutoTrading or check broker permissions |
    | OrderSelect error | Increase MaxTrades or reduce StepPips |
    | No trades opening | Check UseMAFilter settings or market hours |

    ---

    Want professional grid EAs with advanced recovery algorithms? [Subscribe to our newsletter] for access to our premium EA library with volatility filters, time filters, and dynamic step adjustment.

    References:
  • MQL4 Documentation – OrderSend, OrderModify (docs.mql4.com)

  • Self-compiled and backtested on MT4 Build 1420+