TrailingByATR
Download scriptThis script is designed for the MetaTrader 4 platform to automate the management of an open trade's "Stop Loss" level. It specifically uses a dynamic calculation method based on market volatility rather than fixed price points.
Core Concept: ATR-Based Trailing
The logic relies on a technical indicator called ATR (Average True Range). The ATR measures how much an asset's price typically moves over a specific period. Instead of moving your Stop Loss by a set number of pips, this script calculates the "distance" based on current market volatility. If the market becomes more volatile, the distance adjusts; if it calms down, the distance narrows accordingly.
How the Logic Works
1. Dual Volatility Monitoring The script monitors two different ATR settings simultaneously (defined by different periods). It compares both and selects the larger value as its baseline. This ensures that the trailing mechanism remains conservative and reacts to the most significant volatility detected between the two timeframes.
2. Custom Sensitivity Users can apply a multiplier (coefficient) to this volatility distance. For example, if you want your Stop Loss to stay further away from the current price than the standard volatility suggests, you can increase this coefficient.
3. Smart Movement Rules The script behaves differently depending on whether you are in a "Buy" or "Sell" position:
- For Buy Positions: It attempts to move the Stop Loss upward (closer to the current price as it rises).
- For Sell Positions: It attempts to move the Stop Loss downward (closer to the current price as it falls).
4. Trailing Modes The logic includes a specific toggle to determine when the "trailing" should start:
- Standard Mode: The script generally ensures the new Stop Loss is better than the previous one and respects your entry price.
- Loss Zone Mode: If enabled, the script is more aggressive and can adjust the Stop Loss even if the trade is currently in a loss position (moving it closer to the current price regardless of whether the initial entry price has been surpassed).
5. Safety Checks Before making any changes, the script performs several automated checks:
- It verifies that the specific trade ticket provided is valid and currently open.
- It ensures the timeframe selected is supported.
- It checks against "Stop Levels"—the minimum distance required by the broker—to ensure the trade isn't modified into an invalid state, which would cause an error.
Summary for the User
Essentially, this tool automates the "defense" of your trade. It watches how much the market is "breathing" (volatility) and keeps your Stop Loss at a calculated distance from the live price. It ensures that as a trade moves in your favor, your protection moves with it, while providing options to control how strictly that protection follows the price during winners versus losers.
//+------------------------------------------------------------------+
//| TrailingByATR.mq4 |
//| I_D |
//| http://www.mymmk.com/ |
//+------------------------------------------------------------------+
#property copyright "I_D"
#property link "http://www.mymmk.com/"
extern int iTicket; // óíèêàëüíûé íîìåð (òèêåò) îòêðûòîé ïîçèöèè
extern int iAtr_timeframe; // ïåðèîä ãðàôèêà, íà êîòîðîì ñ÷èòàåòñÿ ATR (1, 5, 15, 30, 60, 240, 1440, 10080, 43200)
extern int iAtr1_period = 5; // ïåðèîä ïåðâîãî ATR
extern int iAtr1_shift = 1; // ñäâèã ïåðâîãî ATR
extern int iAtr2_period = 36; // ïåðèîä âòîðîãî ATR
extern int iAtr2_shift = 1; // ñäâèã âòîðîãî ATR
extern double dCoeff = 1; // êîýôôèöèåíò, íà êîòîðûé ìíîæèì ATR, ÷òîáû ïîëó÷èòü ñòîïëîññ (ïðè coeff=1 ñòîï áóäåð ðàçìåùåí íà ðàññòîÿíèè â 1 ATR, ïðè coeff=1.5 - íà ðàññòîÿíèè â ïîëòîðà ATR è ò.ä.)
extern bool bTrlinloss = false; // ñëåäóåò ëè òðàëèòü íà ó÷àñòêå ëîññîâ (ìåæäó êóðñîì ñòîïëîññà è îòêðûòèÿ)
//+------------------------------------------------------------------+
//| ÒÐÅÉËÈÍÃ ÏÎ ATR (Average True Range, Ñðåäíèé èñòèííûé äèàïàçîí) |
//| Ïðè çàïóñêå ýêñïåðòà åìó íåîáõîäèìî óêàçàòü óíèêàëüíûé íîìåð |
//| (òèêåò) îòêðûòîé ïîçèöèè, à òàêæå îïðåäåëèòü ïàðàìåòðû òðåéëèíãà:|
//| ïåðèîä ÀÒR è êîýôôèöèåíò, íà êîòîðûé óìíîæàåòñÿ ATR. Ò.î. |
//| ñòîïëîññ "òÿíåòñÿ" íà ðàññòîÿíèè ATR õ N îò òåêóùåãî êóðñà; |
//| ïåðåíîñ - íà íîâîì áàðå (ò.å. îò öåíû îòêðûòèÿ î÷åðåäíîãî áàðà) |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
TrailingByATR(iTicket,iAtr_timeframe,iAtr1_period,iAtr1_shift,iAtr2_period,iAtr2_shift,dCoeff,bTrlinloss);
return(0);
}
//+------------------------------------------------------------------+
void TrailingByATR(int ticket,int atr_timeframe,int atr1_period,int atr1_shift,int atr2_period,int atr2_shift,double coeff,bool trlinloss)
{
// ïðîâåðÿåì ïåðåäàííûå çíà÷åíèÿ
if ((ticket==0) || (atr1_period<1) || (atr2_period<1) || (coeff<=0) || (!OrderSelect(ticket,SELECT_BY_TICKET)) ||
((atr_timeframe!=1) && (atr_timeframe!=5) && (atr_timeframe!=15) && (atr_timeframe!=30) && (atr_timeframe!=60) &&
(atr_timeframe!=240) && (atr_timeframe!=1440) && (atr_timeframe!=10080) && (atr_timeframe!=43200)) || (atr1_shift<0) || (atr2_shift<0))
{
Print("Òðåéëèíã ôóíêöèåé TrailingByATR() íåâîçìîæåí èç-çà íåêîððåêòíîñòè çíà÷åíèé ïåðåäàííûõ åé àðãóìåíòîâ.");
return(0);
}
double curr_atr1; // òåêóùåå çíà÷åíèå ATR - 1
double curr_atr2; // òåêóùåå çíà÷åíèå ATR - 2
double best_atr; // áîëüøåå èç çíà÷åíèé ATR
double atrXcoeff; // ðåçóëüòàò óìíîæåíèÿ áîëüøåãî èç ATR íà êîýôôèöèåíò
double newstop; // íîâûé ñòîïëîññ
// òåêóùåå çíà÷åíèå ATR-1, ATR-2
curr_atr1 = iATR(Symbol(),atr_timeframe,atr1_period,atr1_shift);
curr_atr2 = iATR(Symbol(),atr_timeframe,atr2_period,atr2_shift);
// áîëüøåå èç çíà÷åíèé
best_atr = MathMax(curr_atr1,curr_atr2);
// ïîñëå óìíîæåíèÿ íà êîýôôèöèåíò
atrXcoeff = best_atr * coeff;
// åñëè äëèííàÿ ïîçèöèÿ (OP_BUY)
if (OrderType()==OP_BUY)
{
// îòêëàäûâàåì îò òåêóùåãî êóðñà (íîâûé ñòîïëîññ)
newstop = Bid - atrXcoeff;
// åñëè trlinloss==true (ò.å. ñëåäóåò òðàëèòü â çîíå ëîññîâ), òî
if (trlinloss==true)
{
// åñëè ñòîïëîññ íåîïðåäåëåí, òî òðàëèì â ëþáîì ñëó÷àå
if ((OrderStopLoss()==0) && (newstop<Bid-MarketInfo(Symbol(),MODE_STOPLEVEL)*Point))
{
if (!OrderModify(ticket,OrderOpenPrice(),newstop,OrderTakeProfit(),OrderExpiration()))
Print("Íå óäàëîñü ìîäèôèöèðîâàòü îðäåð ¹",OrderTicket(),". Îøèáêà: ",GetLastError());
}
// èíà÷å òðàëèì òîëüêî åñëè íîâûé ñòîï ëó÷øå ñòàðîãî
else
{
if ((newstop>OrderStopLoss()) && (newstop<Bid-MarketInfo(Symbol(),MODE_STOPLEVEL)*Point))
if (!OrderModify(ticket,OrderOpenPrice(),newstop,OrderTakeProfit(),OrderExpiration()))
Print("Íå óäàëîñü ìîäèôèöèðîâàòü îðäåð ¹",OrderTicket(),". Îøèáêà: ",GetLastError());
}
}
else
{
// åñëè ñòîïëîññ íåîïðåäåëåí, òî òðàëèì, åñëè ñòîï ëó÷øå îòêðûòèÿ
if ((OrderStopLoss()==0) && (newstop>OrderOpenPrice()) && (newstop<Bid-MarketInfo(Symbol(),MODE_STOPLEVEL)*Point))
{
if (!OrderModify(ticket,OrderOpenPrice(),newstop,OrderTakeProfit(),OrderExpiration()))
Print("Íå óäàëîñü ìîäèôèöèðîâàòü îðäåð ¹",OrderTicket(),". Îøèáêà: ",GetLastError());
}
// åñëè ñòîï íå ðàâåí 0, òî ìåíÿåì åãî, åñëè îí ëó÷øå ïðåäûäóùåãî è êóðñà îòêðûòèÿ
else
{
if ((newstop>OrderStopLoss()) && (newstop>OrderOpenPrice()) && (newstop<Bid-MarketInfo(Symbol(),MODE_STOPLEVEL)*Point))
if (!OrderModify(ticket,OrderOpenPrice(),newstop,OrderTakeProfit(),OrderExpiration()))
Print("Íå óäàëîñü ìîäèôèöèðîâàòü îðäåð ¹",OrderTicket(),". Îøèáêà: ",GetLastError());
}
}
}
// åñëè êîðîòêàÿ ïîçèöèÿ (OP_SELL)
if (OrderType()==OP_SELL)
{
// îòêëàäûâàåì îò òåêóùåãî êóðñà (íîâûé ñòîïëîññ)
newstop = Ask + atrXcoeff;
// åñëè trlinloss==true (ò.å. ñëåäóåò òðàëèòü â çîíå ëîññîâ), òî
if (trlinloss==true)
{
// åñëè ñòîïëîññ íåîïðåäåëåí, òî òðàëèì â ëþáîì ñëó÷àå
if ((OrderStopLoss()==0) && (newstop>Ask+MarketInfo(Symbol(),MODE_STOPLEVEL)*Point))
{
if (!OrderModify(ticket,OrderOpenPrice(),newstop,OrderTakeProfit(),OrderExpiration()))
Print("Íå óäàëîñü ìîäèôèöèðîâàòü îðäåð ¹",OrderTicket(),". Îøèáêà: ",GetLastError());
}
// èíà÷å òðàëèì òîëüêî åñëè íîâûé ñòîï ëó÷øå ñòàðîãî
else
{
if ((newstop<OrderStopLoss()) && (newstop>Ask+MarketInfo(Symbol(),MODE_STOPLEVEL)*Point))
if (!OrderModify(ticket,OrderOpenPrice(),newstop,OrderTakeProfit(),OrderExpiration()))
Print("Íå óäàëîñü ìîäèôèöèðîâàòü îðäåð ¹",OrderTicket(),". Îøèáêà: ",GetLastError());
}
}
else
{
// åñëè ñòîïëîññ íåîïðåäåëåí, òî òðàëèì, åñëè ñòîï ëó÷øå îòêðûòèÿ
if ((OrderStopLoss()==0) && (newstop<OrderOpenPrice()) && (newstop>Ask+MarketInfo(Symbol(),MODE_STOPLEVEL)*Point))
{
if (!OrderModify(ticket,OrderOpenPrice(),newstop,OrderTakeProfit(),OrderExpiration()))
Print("Íå óäàëîñü ìîäèôèöèðîâàòü îðäåð ¹",OrderTicket(),". Îøèáêà: ",GetLastError());
}
// åñëè ñòîï íå ðàâåí 0, òî ìåíÿåì åãî, åñëè îí ëó÷øå ïðåäûäóùåãî è êóðñà îòêðûòèÿ
else
{
if ((newstop<OrderStopLoss()) && (newstop<OrderOpenPrice()) && (newstop>Ask+MarketInfo(Symbol(),MODE_STOPLEVEL)*Point))
if (!OrderModify(ticket,OrderOpenPrice(),newstop,OrderTakeProfit(),OrderExpiration()))
Print("Íå óäàëîñü ìîäèôèöèðîâàòü îðäåð ¹",OrderTicket(),". Îøèáêà: ",GetLastError());
}
}
}
}
//+------------------------------------------------------------------+
Comments