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:

1. Initial trade opens with a base lot size in the direction of your choice (or based on a simple moving average crossover)
2. If the trade goes into loss by a specified number of pips (Step), the EA opens a new trade in the same direction
3. Each subsequent trade increases lot size by a multiplier (e.g., 2x)
4. When price retraces, 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+