TrailingRatchetB
Download scriptThis script is designed to automate the management of a single trading position by dynamically adjusting its Stop Loss (SL) based on price movement. It operates using two primary logic modes: Profit Protection (Trailing) and Intelligent Loss Recovery (Ratchet).
Core Functionality
The script monitors a specific trade (identified by a ticket number) and executes different rules depending on whether the trade is currently in profit or experiencing a loss.
1. Profit Protection Logic (Trailing)
When the market moves in your favor, the script follows a "step-down" approach to lock in gains:
- Initial Break-Even: Once the price reaches the first designated profit level (Level 1), the Stop Loss is moved to just beyond the entry price (Break-even + 1 point).
- Progressive Locking: As the price continues to rise/fall further, reaching Level 2 and then Level 3, the script moves the Stop Loss to more conservative positions relative to your opening price. This ensures that as you make more profit, a larger portion of those gains is secured.
2. Intelligent Loss Recovery (Ratchet Logic)
If the trade goes into a negative position, the script employs a "Ratchet" mechanism (enabled by a specific setting). This logic is designed to prevent the Stop Loss from moving back into a dangerous zone if the price begins to recover:
- Deepening Protection: If the price drops significantly below your entry, the script identifies how deep the loss is.
- The "Ratchet" Effect: If the price starts to turn around and move back toward your entry point, the script will automatically move the Stop Loss to a new, deeper level. It ensures that if you have already experienced a certain amount of "drawdown," the Stop Loss will not be allowed to retreat back into that same loss area.
- Dynamic Adjustment: As the price recovers through different milestones (Levels 1, 2, and 3), the script updates the Stop Loss to the next safest level, effectively "ratcheting" the risk downward as the market fluctuates.
Summary of Behavior
- Single Position Focus: The tool is intended to manage one trade at a time.
- Safety Checks: Before executing any moves, the script validates that the settings provided are mathematically logical (e.g., ensuring profit levels are higher than loss levels and comply with broker limits).
- Dynamic Scaling: Instead of a standard trailing stop that moves every tick, this script moves in specific "milestones," providing a structured way to manage both winning and losing trades automatically.
//+------------------------------------------------------------------+
//| TrailingRatchetB.mq4 |
//| I_D |
//| http://www.mymmk.com/ |
//+------------------------------------------------------------------+
#property copyright "I_D"
#property link "http://www.mymmk.com/ Ñîôò äëÿ óïðàâëåíèÿ êàïèòàëîì"
extern int iTicket; // óíèêàëüíûé íîìåð (òèêåò) îòêðûòîé ïîçèöèè
extern int iPf_level_1 = 10; // óðîâåíü ïðîôèòà (ïóíêòîâ), ïðè êîòîðîì ñòîïëîññ ïåðåíîñèì â áåçóáûòîê + 1 ïóíêò;
extern int iPf_level_2 = 20; // óðîâåíü ïðîôèòà (ïóíêòîâ), ïðè êîòîðîì ñòîïëîññ ïåðåíîñèì ñ +1 íà ðàññòîÿíèå pf_level_1 ïóíêòîâ îò êóðñà îòêðûòèÿ;
extern int iPf_level_3 = 30; // óðîâåíü ïðîôèòà (ïóíêòîâ), ïðè êîòîðîì ñòîïëîññ ïåðåíîñèì ñ pf_level_1 íà pf_level_2 ïóíêòîâ îò êóðñà îòêðûòèÿ (íà ýòîì äåéñòâèÿ ôóíêöèè çàêàí÷èâàþòñÿ);
extern int iLs_level_1 = 15; // ðàññòîÿíèå îò êóðñà îòêðûòèÿ â ñòîðîíó "ëîññà", íà êîòîðîì áóäåò óñòàíîâëåí ñòîïëîññ ïðè äîñòèæåíèè ïðîôèòîì ïîçèöèè +1 (ò.å. ïðè +1 ñòîïëîññ áóäåò ïîäæàò íà ls_level_1);
extern int iLs_level_2 = 25; // ðàññòîÿíèå îò êóðñà îòêðûòèÿ â "ëîññå", íà êîòîðîì áóäåò óñòàíîâëåí ñòîïëîññ ïðè óñëîâèè, ÷òî êóðñ ñíà÷àëà îïóñêàëñÿ íèæå ls_level_1, à ïîòîì ïîäíÿëñÿ âûøå (ò.å. èìåëè ëîññ, íî îí íà÷àë óìåíüøàòüñÿ - íå äîïóñòèì åãî ïîâòîðíîãî óâåëè÷åíèÿ);
extern int iLs_level_3 = 35; // ðàññòîÿíèå îò êóðñà îòêðûòèÿ "ìèíóñå", íà êîòîðîì áóäåò óñòàíîâëåí ñòîïëîññ ïðè óñëîâèè, ÷òî êóðñ ñíèæàëñÿ íèæå ls_level_2, à ïîòîì ïîäíÿëñÿ âûøå;
extern bool bTrlinloss = false; // ñëåäóåò ëè òðàëèòü íà ó÷àñòêå ëîññîâ (ìåæäó êóðñîì ñòîïëîññà è îòêðûòèÿ)
//+------------------------------------------------------------------+
//| ÒÐÅÉËÈÍÃ RATCHET ÁÀÐÈØÏÎËÜÖÀ |
//| Ïðè äîñòèæåíèè ïðîôèòîì óðîâíÿ 1 ñòîïëîññ - â +1, ïðè äîñòèæåíèè |
//| ïðîôèòîì óðîâíÿ 2 ïðîôèòà - ñòîïëîññ - íà óðîâåíü 1, êîãäà |
//| ïðîôèò äîñòèãàåò óðîâíÿ 3 ïðîôèòà, ñòîïëîññ - íà óðîâåíü 2 |
//| (äàëüøå ìîæíî òðåéëèòü äðóãèìè ìåòîäàìè) |
//| ïðè ðàáîòå â ëîññîâîì ó÷àñòêå - òîæå 3 óðîâíÿ, íî ñõåìà ðàáîòû |
//| ñ íèìè íåñêîëüêî èíàÿ, à èìåííî: åñëè ìû îïóñòèëèñü íèæå óðîâíÿ, |
//| à ïîòîì ïîäíÿëèñü âûøå íåãî (ïðèìåð äëÿ ïîêóïêè), òî ñòîïëîññ |
//| ñòàâèì íà ñëåäóþùèé, áîëåå ãëóáîêèé óðîâåíü (íàïðèìåð, óðîâíè |
//| -5, -10 è -25, ñòîïëîññ -40; åñëè îïóñòèëèñü íèæå -10, à ïîòîì |
//| ïîäíÿëèñü âûøå -10, òî ñòîïëîññ - íà -25, åñëè ïîäíèìåìñÿ âûùå |
//| -5, òî ñòîïëîññ ïåðåíåñåì íà -10, ïðè -2 (ñïðýä) ñòîï íà -5 |
//| ðàáîòàåì òîëüêî ñ îäíîé ïîçèöèåé îäíîâðåìåííî. Ïðè çàïóñêå |
//| ýêñïåðòà åìó íåîáõîäèìî óêàçàòü óíèêàëüíûé íîìåð (òèêåò) |
//| îòêðûòîé ïîçèöèè (iTicket) |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
TrailingRatchetB(iTicket,iPf_level_1,iPf_level_2,iPf_level_3,iLs_level_1,iLs_level_2,iLs_level_3,bTrlinloss);
return(0);
}
//+------------------------------------------------------------------+
void TrailingRatchetB(int ticket,int pf_level_1,int pf_level_2,int pf_level_3,int ls_level_1,int ls_level_2,int ls_level_3,bool trlinloss)
{
// ïðîâåðÿåì ïåðåäàííûå çíà÷åíèÿ
if ((ticket==0) || (!OrderSelect(ticket,SELECT_BY_TICKET)) || (pf_level_2<=pf_level_1) || (pf_level_3<=pf_level_2) ||
(pf_level_3<=pf_level_1) || (pf_level_2-pf_level_1<=MarketInfo(Symbol(),MODE_STOPLEVEL)*Point) || (pf_level_3-pf_level_2<=MarketInfo(Symbol(),MODE_STOPLEVEL)*Point) ||
(pf_level_1<=MarketInfo(Symbol(),MODE_STOPLEVEL)))
{
Print("Òðåéëèíã ôóíêöèåé TrailingRatchetB() íåâîçìîæåí èç-çà íåêîððåêòíîñòè çíà÷åíèé ïåðåäàííûõ åé àðãóìåíòîâ.");
return(0);
}
// åñëè äëèííàÿ ïîçèöèÿ (OP_BUY)
if (OrderType()==OP_BUY)
{
double dBid = MarketInfo(Symbol(),MODE_BID);
// Ðàáîòàåì íà ó÷àñòêå ïðîôèòîâ
// åñëè ðàçíèöà "òåêóùèé_êóðñ-êóðñ_îòêðûòèÿ" áîëüøå ÷åì "pf_level_3+ñïðýä", ñòîïëîññ ïåðåíîñèì â "pf_level_2+ñïðýä"
if ((dBid-OrderOpenPrice())>=pf_level_3*Point)
{
if ((OrderStopLoss()==0) || (OrderStopLoss()<OrderOpenPrice() + pf_level_2 *Point))
OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice() + pf_level_2*Point,OrderTakeProfit(),OrderExpiration());
}
else
// åñëè ðàçíèöà "òåêóùèé_êóðñ-êóðñ_îòêðûòèÿ" áîëüøå ÷åì "pf_level_2+ñïðýä", ñòîïëîññ ïåðåíîñèì â "pf_level_1+ñïðýä"
if ((dBid-OrderOpenPrice())>=pf_level_2*Point)
{
if ((OrderStopLoss()==0) || (OrderStopLoss()<OrderOpenPrice() + pf_level_1*Point))
OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice() + pf_level_1*Point,OrderTakeProfit(),OrderExpiration());
}
else
// åñëè ðàçíèöà "òåêóùèé_êóðñ-êóðñ_îòêðûòèÿ" áîëüøå ÷åì "pf_level_1+ñïðýä", ñòîïëîññ ïåðåíîñèì â +1 ("îòêðûòèå + ñïðýä")
if ((dBid-OrderOpenPrice())>=pf_level_1*Point)
// åñëè ñòîïëîññ íå îïðåäåëåí èëè õóæå ÷åì "îòêðûòèå+1"
{
if ((OrderStopLoss()==0) || (OrderStopLoss()<OrderOpenPrice() + 1*Point))
OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice() + 1*Point,OrderTakeProfit(),OrderExpiration());
}
// Ðàáîòàåì íà ó÷àñòêå ëîññîâ
if (trlinloss==true)
{
// Ãëîáàëüíàÿ ïåðåìåííàÿ òåðìèíàëà ñîäåðæèò çíà÷åíèå ñàìîãî óðîâíÿ óáûòêà (ls_level_n), íèæå êîòîðîãî îïóñêàëñÿ êóðñ
// (åñëè îí ïîñëå ýòîãî ïîäíèìàåòñÿ âûøå, óñòàíàâëèâàåì ñòîïëîññ íà áëèæàéøåì áîëåå ãëóáîêîì óðîâíå óáûòêà (åñëè ýòî íå íà÷àëüíûé ñòîïëîññ ïîçèöèè)
// Ñîçäà¸ì ãëîáàëüíóþ ïåðåìåííóþ (îäèí ðàç)
if(!GlobalVariableCheck("zeticket"))
{
GlobalVariableSet("zeticket",ticket);
// ïðè ñîçäàíèè ïðèñâîèì åé "0"
GlobalVariableSet("dpstlslvl",0);
}
// åñëè ðàáîòàåì ñ íîâîé ñäåëêîé (íîâûé òèêåò), çàòèðàåì çíà÷åíèå dpstlslvl
if (GlobalVariableGet("zeticket")!=ticket)
{
GlobalVariableSet("dpstlslvl",0);
GlobalVariableSet("zeticket",ticket);
}
// óáûòî÷íûì ñ÷èòàåì ó÷àñòîê íèæå êóðñà îòêðûòèÿ è äî ïåðâîãî óðîâíÿ ïðîôèòà
if ((dBid-OrderOpenPrice())<pf_level_1*Point)
{
// åñëè (òåêóùèé_êóðñ ëó÷øå/ðàâíî îòêðûòèå) è (dpstlslvl>=ls_level_1), ñòîïëîññ - íà ls_level_1
if (dBid>=OrderOpenPrice())
if ((OrderStopLoss()==0) || (OrderStopLoss()<(OrderOpenPrice()-ls_level_1*Point)))
OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice()-ls_level_1*Point,OrderTakeProfit(),OrderExpiration());
// åñëè (òåêóùèé_êóðñ ëó÷øå óðîâíÿ_óáûòêà_1) è (dpstlslvl>=ls_level_1), ñòîïëîññ - íà ls_level_2
if ((dBid>=OrderOpenPrice()-ls_level_1*Point) && (GlobalVariableGet("dpstlslvl")>=ls_level_1))
if ((OrderStopLoss()==0) || (OrderStopLoss()<(OrderOpenPrice()-ls_level_2*Point)))
OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice()-ls_level_2*Point,OrderTakeProfit(),OrderExpiration());
// åñëè (òåêóùèé_êóðñ ëó÷øå óðîâíÿ_óáûòêà_2) è (dpstlslvl>=ls_level_2), ñòîïëîññ - íà ls_level_3
if ((dBid>=OrderOpenPrice()-ls_level_2*Point) && (GlobalVariableGet("dpstlslvl")>=ls_level_2))
if ((OrderStopLoss()==0) || (OrderStopLoss()<(OrderOpenPrice()-ls_level_3*Point)))
OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice()-ls_level_3*Point,OrderTakeProfit(),OrderExpiration());
// ïðîâåðèì/îáíîâèì çíà÷åíèå íàèáîëåå ãëóáîêîé "âçÿòîé" ëîññîâîé "ñòóïåíüêè"
// åñëè "òåêóùèé_êóðñ-êóðñ îòêðûòèÿ+ñïðýä" ìåíüøå 0,
if ((dBid-OrderOpenPrice()+MarketInfo(Symbol(),MODE_SPREAD)*Point)<0)
// ïðîâåðèì, íå ìåíüøå ëè îí òîãî èëè èíîãî óðîâíÿ óáûòêà
{
if (dBid<=OrderOpenPrice()-ls_level_3*Point)
if (GlobalVariableGet("dpstlslvl")<ls_level_3)
GlobalVariableSet("dpstlslvl",ls_level_3);
else
if (dBid<=OrderOpenPrice()-ls_level_2*Point)
if (GlobalVariableGet("dpstlslvl")<ls_level_2)
GlobalVariableSet("dpstlslvl",ls_level_2);
else
if (dBid<=OrderOpenPrice()-ls_level_1*Point)
if (GlobalVariableGet("dpstlslvl")<ls_level_1)
GlobalVariableSet("dpstlslvl",ls_level_1);
}
} // end of "if ((dBid-OrderOpenPrice())<pf_level_1*Point)"
} // end of "if (trlinloss==true)"
}
// åñëè êîðîòêàÿ ïîçèöèÿ (OP_SELL)
if (OrderType()==OP_SELL)
{
double dAsk = MarketInfo(Symbol(),MODE_ASK);
// Ðàáîòàåì íà ó÷àñòêå ïðîôèòîâ
// åñëè ðàçíèöà "òåêóùèé_êóðñ-êóðñ_îòêðûòèÿ" áîëüøå ÷åì "pf_level_3+ñïðýä", ñòîïëîññ ïåðåíîñèì â "pf_level_2+ñïðýä"
if ((OrderOpenPrice()-dAsk)>=pf_level_3*Point)
{
if ((OrderStopLoss()==0) || (OrderStopLoss()>OrderOpenPrice() - (pf_level_2 + MarketInfo(Symbol(),MODE_SPREAD))*Point))
OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice() - (pf_level_2 + MarketInfo(Symbol(),MODE_SPREAD))*Point,OrderTakeProfit(),OrderExpiration());
}
else
// åñëè ðàçíèöà "òåêóùèé_êóðñ-êóðñ_îòêðûòèÿ" áîëüøå ÷åì "pf_level_2+ñïðýä", ñòîïëîññ ïåðåíîñèì â "pf_level_1+ñïðýä"
if ((OrderOpenPrice()-dAsk)>=pf_level_2*Point)
{
if ((OrderStopLoss()==0) || (OrderStopLoss()>OrderOpenPrice() - (pf_level_1 + MarketInfo(Symbol(),MODE_SPREAD))*Point))
OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice() - (pf_level_1 + MarketInfo(Symbol(),MODE_SPREAD))*Point,OrderTakeProfit(),OrderExpiration());
}
else
// åñëè ðàçíèöà "òåêóùèé_êóðñ-êóðñ_îòêðûòèÿ" áîëüøå ÷åì "pf_level_1+ñïðýä", ñòîïëîññ ïåðåíîñèì â +1 ("îòêðûòèå + ñïðýä")
if ((OrderOpenPrice()-dAsk)>=pf_level_1*Point)
// åñëè ñòîïëîññ íå îïðåäåëåí èëè õóæå ÷åì "îòêðûòèå+1"
{
if ((OrderStopLoss()==0) || (OrderStopLoss()>OrderOpenPrice() - (1 + MarketInfo(Symbol(),MODE_SPREAD))*Point))
OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice() - (1 + MarketInfo(Symbol(),MODE_SPREAD))*Point,OrderTakeProfit(),OrderExpiration());
}
// Ðàáîòàåì íà ó÷àñòêå ëîññîâ
if (trlinloss==true)
{
// Ãëîáàëüíàÿ ïåðåìåííàÿ òåðìèíàëà ñîäåðæèò çíà÷åíèå ñàìîãî óðîâíÿ óáûòêà (ls_level_n), íèæå êîòîðîãî îïóñêàëñÿ êóðñ
// (åñëè îí ïîñëå ýòîãî ïîäíèìàåòñÿ âûøå, óñòàíàâëèâàåì ñòîïëîññ íà áëèæàéøåì áîëåå ãëóáîêîì óðîâíå óáûòêà (åñëè ýòî íå íà÷àëüíûé ñòîïëîññ ïîçèöèè)
// Ñîçäà¸ì ãëîáàëüíóþ ïåðåìåííóþ (îäèí ðàç)
if(!GlobalVariableCheck("zeticket"))
{
GlobalVariableSet("zeticket",ticket);
// ïðè ñîçäàíèè ïðèñâîèì åé "0"
GlobalVariableSet("dpstlslvl",0);
}
// åñëè ðàáîòàåì ñ íîâîé ñäåëêîé (íîâûé òèêåò), çàòèðàåì çíà÷åíèå dpstlslvl
if (GlobalVariableGet("zeticket")!=ticket)
{
GlobalVariableSet("dpstlslvl",0);
GlobalVariableSet("zeticket",ticket);
}
// óáûòî÷íûì ñ÷èòàåì ó÷àñòîê íèæå êóðñà îòêðûòèÿ è äî ïåðâîãî óðîâíÿ ïðîôèòà
if ((OrderOpenPrice()-dAsk)<pf_level_1*Point)
{
// åñëè (òåêóùèé_êóðñ ëó÷øå/ðàâíî îòêðûòèå) è (dpstlslvl>=ls_level_1), ñòîïëîññ - íà ls_level_1
if (dAsk<=OrderOpenPrice())
if ((OrderStopLoss()==0) || (OrderStopLoss()>(OrderOpenPrice() + (ls_level_1 + MarketInfo(Symbol(),MODE_SPREAD))*Point)))
OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice() + (ls_level_1 + MarketInfo(Symbol(),MODE_SPREAD))*Point,OrderTakeProfit(),OrderExpiration());
// åñëè (òåêóùèé_êóðñ ëó÷øå óðîâíÿ_óáûòêà_1) è (dpstlslvl>=ls_level_1), ñòîïëîññ - íà ls_level_2
if ((dAsk<=OrderOpenPrice() + (ls_level_1 + MarketInfo(Symbol(),MODE_SPREAD))*Point) && (GlobalVariableGet("dpstlslvl")>=ls_level_1))
if ((OrderStopLoss()==0) || (OrderStopLoss()>(OrderOpenPrice() + (ls_level_2 + MarketInfo(Symbol(),MODE_SPREAD))*Point)))
OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice() + (ls_level_2 + MarketInfo(Symbol(),MODE_SPREAD))*Point,OrderTakeProfit(),OrderExpiration());
// åñëè (òåêóùèé_êóðñ ëó÷øå óðîâíÿ_óáûòêà_2) è (dpstlslvl>=ls_level_2), ñòîïëîññ - íà ls_level_3
if ((dAsk<=OrderOpenPrice() + (ls_level_2 + MarketInfo(Symbol(),MODE_SPREAD))*Point) && (GlobalVariableGet("dpstlslvl")>=ls_level_2))
if ((OrderStopLoss()==0) || (OrderStopLoss()>(OrderOpenPrice() + (ls_level_3 + MarketInfo(Symbol(),MODE_SPREAD))*Point)))
OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice() + (ls_level_3 + MarketInfo(Symbol(),MODE_SPREAD))*Point,OrderTakeProfit(),OrderExpiration());
// ïðîâåðèì/îáíîâèì çíà÷åíèå íàèáîëåå ãëóáîêîé "âçÿòîé" ëîññîâîé "ñòóïåíüêè"
// åñëè "òåêóùèé_êóðñ-êóðñ îòêðûòèÿ+ñïðýä" ìåíüøå 0,
if ((OrderOpenPrice()-dAsk+MarketInfo(Symbol(),MODE_SPREAD)*Point)<0)
// ïðîâåðèì, íå ìåíüøå ëè îí òîãî èëè èíîãî óðîâíÿ óáûòêà
{
if (dAsk>=OrderOpenPrice()+(ls_level_3+MarketInfo(Symbol(),MODE_SPREAD))*Point)
if (GlobalVariableGet("dpstlslvl")<ls_level_3)
GlobalVariableSet("dpstlslvl",ls_level_3);
else
if (dAsk>=OrderOpenPrice()+(ls_level_2+MarketInfo(Symbol(),MODE_SPREAD))*Point)
if (GlobalVariableGet("dpstlslvl")<ls_level_2)
GlobalVariableSet("dpstlslvl",ls_level_2);
else
if (dAsk>=OrderOpenPrice()+(ls_level_1+MarketInfo(Symbol(),MODE_SPREAD))*Point)
if (GlobalVariableGet("dpstlslvl")<ls_level_1)
GlobalVariableSet("dpstlslvl",ls_level_1);
}
} // end of "if ((dBid-OrderOpenPrice())<pf_level_1*Point)"
} // end of "if (trlinloss==true)"
}
}
//+------------------------------------------------------------------+
Comments