TrailingByFractals
Download scriptThis 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.
//+------------------------------------------------------------------+
//| 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