TrailingByFractals

Download script
Author: I_D
TrailingByFractals

This script is designed to automate the management of an open trading position by dynamically adjusting the "Stop Loss" level based on technical price patterns known as fractals. Rather than moving a stop loss at fixed intervals (like every 10 pips), this tool looks for natural structural turning points in the market to determine where it is safest to place your protection.

Core Functionality

The script monitors a specific trade (identified by a unique ticket number) and performs the following logic:

1. Identification of Market Structure (Fractals) The tool scans the price history on a user-defined timeframe to find "fractals." A fractal is essentially a peak or a valley where the price reaches a high or low point relative to the bars immediately surrounding it. The user can define how many bars are required to confirm these peaks and valleys.

2. Context-Aware Trailing The script behaves differently depending on whether you are in a "Buy" (long) or "Sell" (short) position:

  • For Buy Positions: It searches for the most recent "valley" (low point). It aims to place your stop loss just below this low point.
  • For Sell Positions: It searches for the most recent "peak" (high point). It aims to place your stop loss just above this high point.

3. Safety Buffers and Offsets To prevent the stop loss from being placed exactly on the price tip—which could lead to premature exits due to minor market noise—the script includes an "indent" or offset. This ensures there is a small cushion of breathing room between the actual fractal peak/valley and your new stop loss level.

Operational Modes

The logic allows for two distinct ways to manage the trade:

  • Profit-Only Trailing (Default): The script will only move the stop loss if it improves your position into a profit zone. It ensures that the new stop loss is placed at a better price than your original entry point, effectively "locking in" gains as the market moves in your favor.
  • Loss Recovery Trailing: If enabled, the script will move the stop loss even if the trade is currently in a losing position. This is useful for protecting against a total account wipe-out by moving the stop to the nearest structural floor/ceiling, regardless of whether you are currently "up" or "down."

Safeguards and Validations

Before making any changes, the script performs several automated checks:

  • Validation: It ensures the inputs provided (timeframes, bar counts, etc.) are valid before attempting to run.
  • Price Proximity: It checks with the broker's rules (Stop Levels) to ensure that a requested move isn't too close to the current market price, which would otherwise cause the order to be rejected.
  • Comparison Logic: The script only updates your stop loss if the new calculated level is actually better (closer to the price in the direction of profit) than the existing one. It will not "move backward" and increase your risk.
Price Data Components
Series array that contains the lowest prices of each barSeries array that contains the highest prices of each bar
Orders Execution
It can change open orders parameters, due to possible stepping strategy
16 Views
0 Downloads
0 Favorites
TrailingByFractals
//+------------------------------------------------------------------+
//|                                           TrailingByFractals.mq4 |
//|                                                              I_D |
//|                                            http://www.mymmk.com/ |
//+------------------------------------------------------------------+
#property copyright "I_D"
#property link      "http://www.mymmk.com/ Ñîôò äëÿ óïðàâëåíèÿ êàïèòàëîì"

extern   int      iTicket;             // óíèêàëüíûé íîìåð (òèêåò) îòêðûòîé ïîçèöèè
extern   int      iTmfrm;              // ïåðèîä ãðàôèêà, íà êîòîðîì îïðåäåëÿþòñÿ ôðàêòàëû (1, 5, 15, 30, 60, 240, 1440, 10080, 43200)
extern   int      iFrktl_bars = 5;     // êîë-âî áàðîâ âî ôðàêòàëå
extern   int      iIndent = 3;         // îòñòóï îò òåíè áàðà, íà êîòîðîì ðàçìåùàåòñÿ ñòîïëîññ
extern   bool     bTrlinloss = false;  // ñëåäóåò ëè òðàëèòü íà ó÷àñòêå ëîññîâ (ìåæäó êóðñîì ñòîïëîññà è îòêðûòèÿ)

//+------------------------------------------------------------------+
//| ÒÐÅÉËÈÍÃ ÏÎ ÔÐÀÊÒÀËÀÌ                                            |
//| Ïðè çàïóñêå ýêñïåðòà åìó íåîáõîäèìî óêàçàòü óíèêàëüíûé íîìåð     |
//| (òèêåò) îòêðûòîé ïîçèöèè, à òàêæå îïðåäåëèòü ïàðàìåòðû òðåéëèíãà:|
//| òàéìôðåéì, ïî ôðàêòàëàì êîòîðîãî ïðîèçâîäèòñÿ òðåéëèíã, êîë-âî   |
//| áàðîâ â ôðàêòàëå, îòñòóï îò ýêñòðåìóìà (ïóíêòîâ) ïðè ðàçìåùåíèè  |
//| ñòîïëîññà, à òàêæå ñëåäóåò ëè òðàëèòü â çîíå óáûòêîâ (bTrlinloss)|
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {    
   return(0);
  }
  
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
   return(0);
  }
  
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  { 
   TrailingByFractals(iTicket,iTmfrm,iFrktl_bars,iIndent,bTrlinloss);
   return(0);
  }
//+------------------------------------------------------------------+

void TrailingByFractals(int ticket,int tmfrm,int frktl_bars,int indent,bool trlinloss)
   {
   int i, z; // counters
   int extr_n; // íîìåð áëèæàéøåãî ýêñòðåìóìà frktl_bars-áàðíîãî ôðàêòàëà 
   double temp; // ñëóæåáíàÿ ïåðåìåííàÿ
   int after_x, be4_x; // ñâå÷åé ïîñëå è äî ïèêà ñîîòâåòñòâåííî
   int ok_be4, ok_after; // ôëàãè ñîîòâåòñòâèÿ óñëîâèþ (1 - íåïðàâèëüíî, 0 - ïðàâèëüíî)
   int sell_peak_n, buy_peak_n; // íîìåðà ýêñòðåìóìîâ áëèæàéøèõ ôðàêòàëîâ íà ïðîäàæó (äëÿ ïîäæàòèÿ äë.ïîç.) è ïîêóïêó ñîîòâåòñâåííî   
   
   // ïðîâåðÿåì ïåðåäàííûå çíà÷åíèÿ
   if ((frktl_bars<=3) || (indent<0) || (ticket==0) || ((tmfrm!=1) && (tmfrm!=5) && (tmfrm!=15) && (tmfrm!=30) && (tmfrm!=60) && (tmfrm!=240) && (tmfrm!=1440) && (tmfrm!=10080) && (tmfrm!=43200)) || (!OrderSelect(ticket,SELECT_BY_TICKET)))
      {
      Print("Òðåéëèíã ôóíêöèåé TrailingByFractals() íåâîçìîæåí èç-çà íåêîððåêòíîñòè çíà÷åíèé ïåðåäàííûõ åé àðãóìåíòîâ.");
      return(0);
      } 
   
   temp = frktl_bars;
      
   if (MathMod(frktl_bars,2)==0)
   extr_n = temp/2;
   else                
   extr_n = MathRound(temp/2);
      
   // áàðîâ äî è ïîñëå ýêñòðåìóìà ôðàêòàëà
   after_x = frktl_bars - extr_n;
   if (MathMod(frktl_bars,2)!=0)
   be4_x = frktl_bars - extr_n;
   else
   be4_x = frktl_bars - extr_n - 1;    
   
   // åñëè äëèííàÿ ïîçèöèÿ (OP_BUY), íàõîäèì áëèæàéøèé ôðàêòàë íà ïðîäàæó (ò.å. ýêñòðåìóì "âíèç")
   if (OrderType()==OP_BUY)
      {
      // íàõîäèì ïîñëåäíèé ôðàêòàë íà ïðîäàæó
      for (i=extr_n;i<iBars(Symbol(),tmfrm);i++)
         {
         ok_be4 = 0; ok_after = 0;
         
         for (z=1;z<=be4_x;z++)
            {
            if (iLow(Symbol(),tmfrm,i)>=iLow(Symbol(),tmfrm,i-z)) 
               {
               ok_be4 = 1;
               break;
               }
            }
            
         for (z=1;z<=after_x;z++)
            {
            if (iLow(Symbol(),tmfrm,i)>iLow(Symbol(),tmfrm,i+z)) 
               {
               ok_after = 1;
               break;
               }
            }            
         
         if ((ok_be4==0) && (ok_after==0))                
            {
            sell_peak_n = i; 
            break;
            }
         }
     
      // åñëè òðàëèòü â óáûòêå
      if (trlinloss==true)
         {
         // åñëè íîâûé ñòîïëîññ ëó÷øå èìåþùåãîñÿ (â ò.÷. åñëè ñòîïëîññ == 0, íå âûñòàâëåí)
         // à òàêæå åñëè êóðñ íå ñëèøêîì áëèçêî, íó è åñëè ñòîïëîññ óæå íå áûë ïåðåìåùåí íà ðàññìàòðèâàåìûé óðîâåíü         
         if ((iLow(Symbol(),tmfrm,sell_peak_n)-indent*Point>OrderStopLoss()) && (iLow(Symbol(),tmfrm,sell_peak_n)-indent*Point<Bid-MarketInfo(Symbol(),MODE_STOPLEVEL)*Point))
            {
            if (!OrderModify(ticket,OrderOpenPrice(),iLow(Symbol(),tmfrm,sell_peak_n)-indent*Point,OrderTakeProfit(),OrderExpiration()))
            Print("Íå óäàëîñü ìîäèôèöèðîâàòü ñòîïëîññ îðäåðà ¹",OrderTicket(),". Îøèáêà: ",GetLastError());
            }
         }
      // åñëè òðàëèòü òîëüêî â ïðîôèòå, òî
      else
         {
         // åñëè íîâûé ñòîïëîññ ëó÷øå èìåþùåãîñÿ È êóðñà îòêðûòèÿ, à òàêæå íå ñëèøêîì áëèçêî ê òåêóùåìó êóðñó
         if ((iLow(Symbol(),tmfrm,sell_peak_n)-indent*Point>OrderStopLoss()) && (iLow(Symbol(),tmfrm,sell_peak_n)-indent*Point>OrderOpenPrice()) && (iLow(Symbol(),tmfrm,sell_peak_n)-indent*Point<Bid-MarketInfo(Symbol(),MODE_STOPLEVEL)*Point))
            {
            if (!OrderModify(ticket,OrderOpenPrice(),iLow(Symbol(),tmfrm,sell_peak_n)-indent*Point,OrderTakeProfit(),OrderExpiration()))
            Print("Íå óäàëîñü ìîäèôèöèðîâàòü ñòîïëîññ îðäåðà ¹",OrderTicket(),". Îøèáêà: ",GetLastError());
            }
         }
      }
      
   // åñëè êîðîòêàÿ ïîçèöèÿ (OP_SELL), íàõîäèì áëèæàéøèé ôðàêòàë íà ïîêóïêó (ò.å. ýêñòðåìóì "ââåðõ")
   if (OrderType()==OP_SELL)
      {
      // íàõîäèì ïîñëåäíèé ôðàêòàë íà ïðîäàæó
      for (i=extr_n;i<iBars(Symbol(),tmfrm);i++)
         {
         ok_be4 = 0; ok_after = 0;
         
         for (z=1;z<=be4_x;z++)
            {
            if (iHigh(Symbol(),tmfrm,i)<=iHigh(Symbol(),tmfrm,i-z)) 
               {
               ok_be4 = 1;
               break;
               }
            }
            
         for (z=1;z<=after_x;z++)
            {
            if (iHigh(Symbol(),tmfrm,i)<iHigh(Symbol(),tmfrm,i+z)) 
               {
               ok_after = 1;
               break;
               }
            }            
         
         if ((ok_be4==0) && (ok_after==0))                
            {
            buy_peak_n = i;
            break;
            }
         }        
      
      // åñëè òðàëèòü â óáûòêå
      if (trlinloss==true)
         {
         if (((iHigh(Symbol(),tmfrm,buy_peak_n)+(indent+MarketInfo(Symbol(),MODE_SPREAD))*Point<OrderStopLoss()) || (OrderStopLoss()==0)) && (iHigh(Symbol(),tmfrm,buy_peak_n)+(indent+MarketInfo(Symbol(),MODE_SPREAD))*Point>Ask+MarketInfo(Symbol(),MODE_STOPLEVEL)*Point))
            {
            if (!OrderModify(ticket,OrderOpenPrice(),iHigh(Symbol(),tmfrm,buy_peak_n)+(indent+MarketInfo(Symbol(),MODE_SPREAD))*Point,OrderTakeProfit(),OrderExpiration()))
            Print("Íå óäàëîñü ìîäèôèöèðîâàòü ñòîïëîññ îðäåðà ¹",OrderTicket(),". Îøèáêà: ",GetLastError());
            }
         }      
      // åñëè òðàëèòü òîëüêî â ïðîôèòå, òî
      else
         {
         // åñëè íîâûé ñòîïëîññ ëó÷øå èìåþùåãîñÿ È êóðñà îòêðûòèÿ
         if ((((iHigh(Symbol(),tmfrm,buy_peak_n)+(indent+MarketInfo(Symbol(),MODE_SPREAD))*Point<OrderStopLoss()) || (OrderStopLoss()==0))) && (iHigh(Symbol(),tmfrm,buy_peak_n)+(indent+MarketInfo(Symbol(),MODE_SPREAD))*Point<OrderOpenPrice()) && (iHigh(Symbol(),tmfrm,buy_peak_n)+(indent+MarketInfo(Symbol(),MODE_SPREAD))*Point>Ask+MarketInfo(Symbol(),MODE_STOPLEVEL)*Point))
            {
            if (!OrderModify(ticket,OrderOpenPrice(),iHigh(Symbol(),tmfrm,buy_peak_n)+(indent+MarketInfo(Symbol(),MODE_SPREAD))*Point,OrderTakeProfit(),OrderExpiration()))
            Print("Íå óäàëîñü ìîäèôèöèðîâàòü ñòîïëîññ îðäåðà ¹",OrderTicket(),". Îøèáêà: ",GetLastError());
            }
         }
      }      
   }
//+------------------------------------------------------------------+

Comments