Free MT4 Trailing Stop EA (Pips, Breakeven, Source Code)
Be4 Trailing Stop is a free MetaTrader 4 Expert Advisor that trails your stop loss in pips, starts only after a profit threshold, can move the stop to breakeven first, and trails every open trade. When it runs on a desktop terminal or a VPS, it also manages trades you open from the MT4 mobile app.
MT5 version: the same logic for MetaTrader 5 is available as the free MT5 trailing stop EA, compiled and with source code.
MT4’s built-in trailing stop is useful, but it has three limits that frustrate traders: it is set in points rather than pips, it has no start threshold or breakeven step, and, according to the MetaTrader 4 help, when several trades with a trailing stop are open on the same symbol only the latest one is processed. This small EA fixes all three. The full source code is below, so you can read exactly what it does before you run it.
Download Be4 Trailing Stop (MT4, free .zip)
Version 1.00 · source file Be4-Trailing-Stop.mq4 · no email required
What the EA Does
- Trails in pips, not points. It detects 3- and 5-digit quotes, so “15” means 15 pips on every pair.
- Starts after a minimum profit. The stop does not move until the trade is, for example, 20 pips in profit.
- Optional breakeven step. At a profit you choose, the stop jumps to the entry price plus a few pips.
- Trails every trade. Each open BUY and SELL is managed separately, including several trades on the same pair.
- Works with mobile trades. Trades opened on the iPhone or Android app are trailed as long as the EA runs on a connected desktop terminal or VPS.
- Only tightens stops. It never opens or closes trades, never widens a stop and leaves take-profit levels unchanged.
Inputs and Recommended Settings
| Input | Default | What it does |
|---|---|---|
| TrailStartPips | 20 | Profit in pips before trailing starts |
| TrailDistancePips | 15 | Distance kept between price and the stop |
| TrailStepPips | 1 | Minimum move before the stop is modified again (reduces server requests) |
| BreakevenAtPips | 0 (off) | Profit at which the stop jumps to breakeven |
| BreakevenLockPips | 1 | Pips locked in by the breakeven step (covers the spread) |
| AllSymbols | false | false = only the chart’s pair; true = every pair in the account |
| MagicFilter | -1 | -1 = all trades; 0 = manual and mobile trades only; any other number = trades of one EA |
A good starting point is a trailing distance of about 1 to 1.5 times the pair’s Average True Range on your trading timeframe. Tighter distances get stopped out by normal noise; see how to set a trailing stop in MT4 for four ways to choose the distance.
How to Install the EA in MT4
- Download the .zip above and extract
Be4-Trailing-Stop.mq4. - In MT4, click File → Open Data Folder, then open MQL4 → Experts and copy the file there.
- Back in MT4, right-click Expert Advisors in the Navigator and choose Refresh (or restart MT4). MT4 compiles the .mq4 file automatically. If it does not appear, open it in MetaEditor (F4) and press Compile.
- Drag Be4-Trailing-Stop onto any chart. In the window that opens, tick Allow live trading and set your inputs.
- Make sure the AutoTrading button on the toolbar is green. A status line appears in the chart’s top-left corner.
Run it on one chart only when AllSymbols is true, otherwise two copies will manage the same trades. If MT4 cannot find the indicator or EA after copying, our MT4 indicator not showing fixes apply to Expert Advisors too.
How It Works
On every tick, and once per second for other pairs, the EA loops through open trades. For a BUY it measures profit as (Bid − open price) in pips. If the breakeven step is on and reached, the candidate stop is the entry plus the lock pips. Once profit reaches the start level, the candidate becomes Bid − trailing distance, as long as that is at least one step above the current stop. The stop is only modified if the new level is higher than the old one and respects the broker’s minimum stop distance. SELL trades use the Ask price and the mirror logic. Every change, and every error returned by the broker, is written to the Experts journal.
Important Limits
- MT4 must stay running. Like the built-in trailing stop, an EA runs inside your terminal. If the computer sleeps or MT4 closes, the last stop level stays on the server but stops moving. A VPS solves this.
- Broker rules still apply. Stop levels inside the broker’s minimum distance or freeze level are rejected; the EA skips them and tries again on the next tick.
- Gold and indices. On 2-digit symbols one “pip” equals one point (0.01). Check the result on a demo before using it on metals or CFDs.
- Test on demo first. Run the EA on a demo account with small trades and watch the journal before using it with real money.
Full Source Code
The code is short and commented. You are free to use and modify it for your own trading.
//+------------------------------------------------------------------+
//| Be4-Trailing-Stop.mq4 |
//| Free trailing stop manager for MetaTrader 4 (Be4 v1.00) |
//| https://www.be4tradingforex.com/free-mt4-trailing-stop-ea/ |
//+------------------------------------------------------------------+
//| What it does |
//| - trails the stop loss of open BUY/SELL trades in PIPS |
//| - starts trailing only after a minimum profit |
//| - optional move to breakeven (+ a few pips) first |
//| - trails EVERY trade (MT4's built-in trailing stop only |
//| processes the latest trade per symbol) |
//| - manages trades opened from the MT4 mobile app, as long as |
//| this EA runs on a desktop terminal or VPS |
//| It never opens or closes trades and never widens a stop. |
//| Test on a demo account first. Trading involves risk. |
//+------------------------------------------------------------------+
#property copyright "Be4TradingForex"
#property link "https://www.be4tradingforex.com/free-mt4-trailing-stop-ea/"
#property version "1.00"
#property strict
input double TrailStartPips = 20.0; // Start trailing after this profit (pips)
input double TrailDistancePips = 15.0; // Distance between price and stop (pips)
input double TrailStepPips = 1.0; // Move the stop in steps of at least (pips)
input double BreakevenAtPips = 0.0; // Move stop to breakeven at this profit (0 = off)
input double BreakevenLockPips = 1.0; // Pips locked in when moving to breakeven
input bool AllSymbols = false; // true = manage all symbols, false = this chart only
input int MagicFilter = -1; // -1 = all trades, 0 = manual trades only, N = magic N
//+------------------------------------------------------------------+
//| One pip in price units: 10 points on 3/5-digit quotes |
//+------------------------------------------------------------------+
double PipSize(string sym)
{
int digits = (int)MarketInfo(sym, MODE_DIGITS);
double point = MarketInfo(sym, MODE_POINT);
if(digits == 3 || digits == 5)
return(point * 10.0);
return(point);
}
//+------------------------------------------------------------------+
int OnInit()
{
if(TrailDistancePips <= 0.0 || TrailStartPips < 0.0 || TrailStepPips < 0.0)
{
Print("Be4 Trailing Stop: check the inputs (distance must be above 0).");
return(INIT_PARAMETERS_INCORRECT);
}
EventSetTimer(1); // also manage other symbols between this chart's ticks
ShowStatus();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
EventKillTimer();
Comment("");
}
//+------------------------------------------------------------------+
void OnTick() { ManageTrades(); }
void OnTimer() { ManageTrades(); }
//+------------------------------------------------------------------+
void ShowStatus()
{
Comment("Be4 Trailing Stop v1.00\n",
"Start: ", DoubleToString(TrailStartPips, 1), " pips Distance: ", DoubleToString(TrailDistancePips, 1),
" pips Step: ", DoubleToString(TrailStepPips, 1), " pips\n",
"Breakeven: ", (BreakevenAtPips > 0.0 ? DoubleToString(BreakevenAtPips, 1) + " pips (+" + DoubleToString(BreakevenLockPips, 1) + ")" : "off"),
" Symbols: ", (AllSymbols ? "all" : Symbol()),
" Magic: ", (MagicFilter < 0 ? "all" : IntegerToString(MagicFilter)));
}
//+------------------------------------------------------------------+
void ManageTrades()
{
RefreshRates();
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
continue;
if(OrderType() != OP_BUY && OrderType() != OP_SELL)
continue; // pending orders are left alone
if(!AllSymbols && OrderSymbol() != Symbol())
continue;
if(MagicFilter >= 0 && OrderMagicNumber() != MagicFilter)
continue;
string sym = OrderSymbol();
int digits = (int)MarketInfo(sym, MODE_DIGITS);
double point = MarketInfo(sym, MODE_POINT);
double pip = PipSize(sym);
double minDist = MarketInfo(sym, MODE_STOPLEVEL) * point;
double open = OrderOpenPrice();
double sl = OrderStopLoss();
double cand = 0.0;
if(OrderType() == OP_BUY)
{
double bid = MarketInfo(sym, MODE_BID);
double profit = (bid - open) / pip;
if(BreakevenAtPips > 0.0 && profit >= BreakevenAtPips)
{
double be = NormalizeDouble(open + BreakevenLockPips * pip, digits);
if(sl == 0.0 || be > sl)
cand = be;
}
if(profit >= TrailStartPips)
{
double t = NormalizeDouble(bid - TrailDistancePips * pip, digits);
if((sl == 0.0 || t >= sl + TrailStepPips * pip) && t > cand)
cand = t;
}
// only ever tighten, and respect the broker's minimum stop distance
if(cand > 0.0 && (sl == 0.0 || cand > sl + point / 2.0) && bid - cand >= minDist)
ModifyStop(cand, digits);
}
else // OP_SELL
{
double ask = MarketInfo(sym, MODE_ASK);
double profit = (open - ask) / pip;
if(BreakevenAtPips > 0.0 && profit >= BreakevenAtPips)
{
double be = NormalizeDouble(open - BreakevenLockPips * pip, digits);
if(sl == 0.0 || be < sl)
cand = be;
}
if(profit >= TrailStartPips)
{
double t = NormalizeDouble(ask + TrailDistancePips * pip, digits);
if((sl == 0.0 || t <= sl - TrailStepPips * pip) && (cand == 0.0 || t < cand))
cand = t;
}
if(cand > 0.0 && (sl == 0.0 || cand < sl - point / 2.0) && cand - ask >= minDist)
ModifyStop(cand, digits);
}
}
}
//+------------------------------------------------------------------+
//| Modify the selected order's stop loss, keep everything else |
//+------------------------------------------------------------------+
void ModifyStop(double newSL, int digits)
{
bool ok = OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(newSL, digits),
OrderTakeProfit(), 0, clrNONE);
if(!ok)
Print("Be4 Trailing Stop: could not move the stop of #", OrderTicket(), " (", OrderSymbol(),
") to ", DoubleToString(newSL, digits), ", error ", GetLastError());
else
Print("Be4 Trailing Stop: #", OrderTicket(), " stop moved to ", DoubleToString(newSL, digits));
}
//+------------------------------------------------------------------+
Frequently Asked Questions
Is this trailing stop EA free?
Yes. It is free to download, use and modify, with no email or registration required.
Does it work on the MT4 mobile app?
Expert Advisors cannot run on the mobile app, but trades you open on your phone are managed if the EA runs on a desktop MT4 or a VPS logged in to the same account.
Will the EA open or close trades?
No. It only moves the stop loss of trades that are already open, and only in the direction that locks in more profit.
Does it work with MT5?
No. This version is written in MQL4 for MetaTrader 4. MT5 uses a different language and position model.
Sources
- MetaQuotes, MetaTrader 4 Help: Trailing Stop.
Keep learning