Summary: Free MT4 script that automatically trails stop loss for open positions. Complete MQL4 source code included. Customizable trailing distance, step size, and position selection. Easy to install and modify.




Free MT4 Trailing Stop Script – Full MQL4 Source Code



What This Script Does



Managing trailing stops manually is tedious and error-prone. This MT4 script automatically adjusts your stop loss as price moves in your favor. Once activated on a position, it continuously monitors price and moves the stop loss higher (for long positions) or lower (for short positions) according to your parameters.

This is not an EA but a script – you run it once on a chart, and it works on an open position until you close the position or remove the script.

Key Features



| Feature | Description |
|---------|-------------|
| Automatic trailing | Stop loss follows price automatically without manual adjustment |
| Customizable distance | Set trailing stop in pips (e.g., 30 pips behind current price) |
| Step locking | Set minimum step size to avoid excessive modifications |
| Position selection | Apply to current chart symbol only or all open positions |
| Magic number filter | Only affect positions with specific magic number (EA-friendly) |
| Lightweight | Minimal CPU usage, runs efficiently |

Complete MQL4 Source Code



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

``cpp
//+------------------------------------------------------------------+
//| TrailingStop.mq4 |
//| Autonomous Compilation |
//| |
//+------------------------------------------------------------------+
#property copyright "ForexEA Blog"
#property link ""
#property version "1.00"
#property strict
#property show_inputs

//--- input parameters
input double TrailingStopPips = 30; // Trailing stop distance (pips)
input double TrailingStepPips = 10; // Minimum step to move stop (pips)
input bool ApplyToAllSymbols = false; // Apply to all symbols?
input int MagicFilter = 0; // Magic number filter (0 = all)
input bool CloseOnReverse = false; // Close position if trailing triggers?
input int Slippage = 3; // Slippage for modification

//--- global variables
double pip_size;
string symbol_target;

//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- determine pip size based on symbol
symbol_target = _Symbol;
pip_size = GetPipSize(symbol_target);

if(pip_size == 0)
{
Print("Error: Cannot determine pip size for ", symbol_target);
return;
}

Print("Starting trailing stop script on ", symbol_target);
Print("Trailing distance: ", TrailingStopPips, " pips");
Print("Step size: ", TrailingStepPips, " pips");

//--- main loop
while(!IsStopped())
{
TraverseOpenPositions();
Sleep(500); // check every 500ms
}
}

//+------------------------------------------------------------------+
//| Get pip size for a given symbol |
//+------------------------------------------------------------------+
double GetPipSize(string symbol)
{
double point_value = MarketInfo(symbol, MODE_POINT);
double digits = MarketInfo(symbol, MODE_DIGITS);

//--- standard pip calculation
if(digits == 3 || digits == 5)
return point_value 10;
else
return point_value;
}

//+------------------------------------------------------------------+
//| Traverse all open positions and apply trailing stop |
//+------------------------------------------------------------------+
void TraverseOpenPositions()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
continue;

//--- filter by symbol
if(!ApplyToAllSymbols && OrderSymbol() != symbol_target)
continue;

//--- filter by magic number
if(MagicFilter != 0 && OrderMagicNumber() != MagicFilter)
continue;

//--- process based on order type
if(OrderType() == OP_BUY)
ProcessBuyPosition();
else if(OrderType() == OP_SELL)
ProcessSellPosition();
}
}

//+------------------------------------------------------------------+
//| Process buy position trailing stop |
//+------------------------------------------------------------------+
void ProcessBuyPosition()
{
double current_stop = OrderStopLoss();
double current_price = MarketInfo(OrderSymbol(), MODE_BID);
double new_stop = current_price - TrailingStopPips
pip_size;

//--- round to proper digits
int digits = (int)MarketInfo(OrderSymbol(), MODE_DIGITS);
new_stop = NormalizeDouble(new_stop, digits);

//--- check if trailing should be applied
bool should_update = false;

if(current_stop == 0)
{
//--- no existing stop loss, set initial trailing stop
should_update = true;
}
else
{
//--- only update if the new stop is higher than current stop
if(new_stop > current_stop + TrailingStepPips pip_size)
should_update = true;
}

if(should_update && new_stop < current_price)
{
bool modified = OrderModify(OrderTicket(), OrderOpenPrice(), new_stop, OrderTakeProfit(), 0, clrNONE);
if(modified)
{
Print("Trailing stop updated for buy order #", OrderTicket(),
" - New stop: ", DoubleToString(new_stop, digits));
}
else
{
Print("Failed to modify order #", OrderTicket(), " - Error: ", GetLastError());
}
}
}

//+------------------------------------------------------------------+
//| Process sell position trailing stop |
//+------------------------------------------------------------------+
void ProcessSellPosition()
{
double current_stop = OrderStopLoss();
double current_price = MarketInfo(OrderSymbol(), MODE_ASK);
double new_stop = current_price + TrailingStopPips
pip_size;

//--- round to proper digits
int digits = (int)MarketInfo(OrderSymbol(), MODE_DIGITS);
new_stop = NormalizeDouble(new_stop, digits);

//--- check if trailing should be applied
bool should_update = false;

if(current_stop == 0)
{
should_update = true;
}
else
{
if(new_stop < current_stop - TrailingStepPips * pip_size)
should_update = true;
}

if(should_update && new_stop > current_price)
{
bool modified = OrderModify(OrderTicket(), OrderOpenPrice(), new_stop, OrderTakeProfit(), 0, clrNONE);
if(modified)
{
Print("Trailing stop updated for sell order #", OrderTicket(),
" - New stop: ", DoubleToString(new_stop, digits));
}
else
{
Print("Failed to modify order #", OrderTicket(), " - Error: ", GetLastError());
}
}
}

//+------------------------------------------------------------------+
//| Script deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("Trailing stop script stopped. Reason: ", reason);
}
//+------------------------------------------------------------------+
`

Installation Instructions



Step 1: Copy the complete code above
Step 2: Open MetaTrader 4 → File → Open Data Folder → MQL4 → Scripts
Step 3: Create a new file named
TrailingStop.mq4
Step 4: Paste the code and press Compile (F7)
Step 5: If compilation succeeds, the script appears in Navigator → Scripts
Step 6: Drag the script onto a chart with an open position
Step 7: Set parameters in the popup window and click OK

Parameter Explanation



| Parameter | Default | Description |
|-----------|---------|-------------|
|
TrailingStopPips | 30 | Distance behind current price where stop loss is placed |
|
TrailingStepPips | 10 | Minimum price movement required to move stop loss again |
|
ApplyToAllSymbols | false | If true, affects all symbols; if false, only current chart symbol |
|
MagicFilter | 0 | Only affect orders with this magic number (0 = all orders) |
|
CloseOnReverse | false | Currently reserved for future feature |
|
Slippage | 3 | Allowed slippage in pips when modifying stop loss |

How Trailing Stop Works



Example – Buy Position:
  • Entry price: 1.10000

  • TrailingStopPips: 30 pips

  • Initial stop loss: 1.09700 (30 pips below entry)


  • When price rises:
  • Price at 1.10300 → New stop: 1.10000 (breakeven)

  • Price at 1.10600 → New stop: 1.10300 (30 pips behind)

  • Price at 1.11000 → New stop: 1.10700


  • The stop loss only moves forward, never backward, locking in profits as price moves in your favor.

    Step Parameter Explained:
  • TrailingStepPips = 10 means the script only moves the stop loss when price has moved at least 10 pips beyond the last stop position

  • This prevents excessive order modifications and reduces CPU usage


  • Usage Examples



    Example 1: Protect a Running Gold Long Position


  • Open a buy order on XAUUSD

  • Drag TrailingStop script onto XAUUSD chart

  • Set TrailingStopPips = 50 (gold moves more)

  • Set TrailingStepPips = 15

  • Script will trail 50 pips behind, moving stop every 15 pips


  • Example 2: Apply to EA Orders Only


  • Your EA uses magic number 12345

  • Set MagicFilter = 12345

  • Script only affects positions opened by your EA, ignoring manual trades


  • Example 3: Monitor All Open Positions


  • Set ApplyToAllSymbols = true

  • Script runs on any chart and manages all positions across all symbols


  • Modifying the Code for Custom Behavior



    Change to Close on Trail (instead of moving stop)


    Replace the modification section with:

    `cpp
    if(should_update)
    {
    bool closed = OrderClose(OrderTicket(), OrderLots(),
    MarketInfo(OrderSymbol(), MODE_BID), Slippage, clrNONE);
    if(closed)
    Print("Position closed by trailing stop");
    }
    `

    Add Alert When Stop Loss Moves


    Add this line after successful modification:

    `cpp
    PlaySound("alert.wav");
    Alert("Trailing stop triggered on order #", OrderTicket());
    `

    Troubleshooting



    | Issue | Solution |
    |-------|----------|
    | Script does nothing | Make sure you have an open position on the chart |
    | Stop loss not moving | Check if price has moved enough to exceed TrailingStepPips |
    | Compilation errors | Verify file extension is
    .mq4, not .txt |
    | Script stops after a few seconds | Scripts run once by default. This script has a while loop to keep running – make sure you dragged it as a script, not an EA |

    Important Notes



  • <strong>Script runs continuously</strong> – Unlike EAs, scripts normally execute once and exit. This script contains a while(!IsStopped()) loop to keep running. To stop it, right-click the chart → Expert Advisors → Remove, or click the "Stop" button in the script properties.


  • <strong>Risk Warning</strong> – Trailing stops do not guarantee profits. In fast-moving markets, slippage may cause execution at worse prices than expected.


  • <strong>Broker Limitations</strong> – Some brokers require minimum stop distance. If you set TrailingStopPips` too small, modification may fail (error 130 – Invalid stops).


  • ---

    Want more professional scripts and EAs for gold and forex trading? [Sign up for our newsletter] to receive weekly free tools and discounted access to our premium EA library.

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

  • Own compilation and testing on MT4 Build 1420+