# 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:
When price rises:
The stop loss only moves forward, never backward, locking in profits as price moves in your favor.
Step Parameter Explained:
Usage Examples
Example 1: Protect a Running Gold Long Position
Example 2: Apply to EA Orders Only
Example 3: Monitor All Open Positions
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: