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



    1. Script runs continuously – 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.

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

    3. Broker Limitations – 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+