TrailingByATR

Download script
Author: I_D
TrailingByATR

This 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.

Orders Execution
It can change open orders parameters, due to possible stepping strategy
Indicators Used
Indicator of the average true range
12 Views
0 Downloads
0 Favorites
TrailingByATR
//+------------------------------------------------------------------+
//|                                                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