Hello everyone,
I'm experiencing a critical issue with a custom stepped trailing stop that I've implemented in my MQL5 Expert Advisor (EA).
The trailing stop logic should be as follows:
- Stepped Logic: The trailing stop moves the stop loss in fixed increments of 10 points.
- Favorable Movement Only: The stop loss updates only when the price moves 10 points in favor of the position.
- Restriction: The stop loss can only tighten (move closer to the price), never widen.
- Crossing the Entry Price: The stop loss can cross the entry price to ensure a minimum profit.
- No Reversal: the trailing stop can never go back until the take profit or the stop loss is reached.
- Incremental Update: the stop loss must be updated incrementally, starting from the initial stop loss and moving 10 points at a time.
However, during backtests, I've observed an anomalous and unacceptable behavior:
- The trailing stop activates and moves the stop loss too quickly, even with price movements smaller than the intended 10 points.
- In practice, the stop loss moves below or above the entry price as soon as the price moves slightly in favor of the position, completely ignoring the initial stop loss level and the 10-point threshold.
- This behavior renders the trailing stop unusable, as it exposes capital to excessive and unpredictable risks.
Example:
- I open a BUY position at 1.10000 with an initial stop loss at 1.09900 (100 points away).
- I expect the stop loss to remain at 1.09900 until the price reaches 1.10010.
- Instead, as soon as the price rises to 1.10002 (only 2 points of profit), the stop loss immediately moves to 1.10000 (the entry price), completely ignoring the initial stop loss level and the 10-point threshold.
I've carefully examined the code of the UpdateTrailingStop() function, but I can't pinpoint the cause of the problem. I suspect there's an error in the logic for calculating the new stop loss or in managing the update conditions.
I'm attaching the code of the UpdateTrailingStop() function for your analysis:
Thank you in advance for your help.
The "jump" floor method is really neat but in this case you just need to maintain the original distance of the stop loss at all times , and , make sure any new sl is bigger by trailing step than the previous one.
If i understood correctly that is.
#include <Trade\Trade.mqh> CTrade trade; bool placed=false; double initialStopSize=0.0; double trailingStopLevel=0.0; int OnInit() { placed=false; return(INIT_SUCCEEDED); } void OnTick() { if(!placed){ placed=true; MqlTick T; if(SymbolInfoTick(_Symbol,T)){ trailingStopLevel=10.0*_Point; initialStopSize=100.0*_Point; double SL=NormalizeDouble(T.bid-initialStopSize,_Digits); trade.Buy(0.01,_Symbol,T.ask,SL,0.0); } }else{ MonitorPriceAndStepTrailingStop(); } } // Function for price monitoring and Step Trailing Stop void MonitorPriceAndStepTrailingStop() { //Print("MonitorPriceAndStepTrailingStop called"); // Debug: confirm that the function is called for (int i = PositionsTotal() - 1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if (ticket > 0) { // Verify that the position belongs to the correct symbol if (PositionGetString(POSITION_SYMBOL) == Symbol()) { if (PositionSelectByTicket(ticket)) { double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT); double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); double existingSL = PositionGetDouble(POSITION_SL); //buy if(PositionGetInteger(POSITION_TYPE)==ORDER_TYPE_BUY){ double distance=currentPrice-existingSL; if(distance>=initialStopSize){ //project new stop loss by taking into account the original SL size double new_sl=currentPrice-initialStopSize; //if it is higher than before set it if(new_sl>=existingSL+trailingStopLevel){ trade.PositionModify(ticket, new_sl, PositionGetDouble(POSITION_TP)); } } } //sell else if(PositionGetInteger(POSITION_TYPE)==ORDER_TYPE_SELL){ double distance=existingSL-currentPrice; if(distance>=initialStopSize){ //project new stop loss by taking into account the original SL size double new_sl=currentPrice+initialStopSize; //if it is higher than before set it if(new_sl<=existingSL-trailingStopLevel){ trade.PositionModify(ticket, new_sl, PositionGetDouble(POSITION_TP)); } } } } else { Print("Error: unable to select position with ticket ", ticket); // Debug: error in position selection } } else { Print("Error: position does not belong to the correct symbol"); // Debug: position on a different symbol } } else { Print("Error: invalid ticket for position ", i); // Debug: invalid ticket } } }
Il metodo del floor "jump" è davvero interessante, ma in questo caso devi solo mantenere sempre la distanza originale dello stop loss e assicurarti che ogni nuovo sl sia più grande del precedente per un trailing step.
Se ho capito bene, cioè.
#include <Trade/Trade.mqh> CTrade trade; // Strategy settings double StepTrailingStop = 10; // Step of 10 basis points double PipValue() { return SymbolInfoDouble(_Symbol, SYMBOL_POINT); } void CheckTrailingStop() { if (PositionSelect(_Symbol)) { double price = PositionGetDouble(POSITION_PRICE_OPEN); double sl = PositionGetDouble(POSITION_SL); double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT); int type = PositionGetInteger(POSITION_TYPE); if (type == POSITION_TYPE_BUY) { // Calculate the distance from the opening price double distanceFromOpen = currentPrice - price; // If the price has risen by 10 pips from the opening price if (distanceFromOpen >= StepTrailingStop * PipValue()) { // Calculate the new SL as the previous SL + 10 pips double newSL = sl + StepTrailingStop * PipValue(); // Ensure the new SL is not higher than the current price if (newSL < currentPrice) { if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), newSL, PositionGetDouble(POSITION_TP))) { Print("[ERROR] Trailing Stop update failed (BUY): ", GetLastError()); } else { Print("[INFO] Trailing Stop updated (BUY): New SL=", newSL); } } } } else if (type == POSITION_TYPE_SELL) { // Calculate the distance from the opening price double distanceFromOpen = price - currentPrice; // If the price has fallen by 10 pips from the opening price if (distanceFromOpen >= StepTrailingStop * PipValue()) { // Calculate the new SL as the previous SL - 10 pips double newSL = sl - StepTrailingStop * PipValue(); // Ensure the new SL is not lower than the current price if (newSL > currentPrice) { if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), newSL, PositionGetDouble(POSITION_TP))) { Print("[ERROR] Trailing Stop update failed (SELL): ", GetLastError()); } else { Print("[INFO] Trailing Stop updated (SELL): New SL=", newSL); } } } } } } void OnTick() { // ... (other parts of your OnTick function) ... // Check and update the trailing stop CheckTrailingStop(); }
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hello everyone,
I'm experiencing a critical issue with a custom stepped trailing stop that I've implemented in my MQL5 Expert Advisor (EA).
The trailing stop logic should be as follows:
However, during backtests, I've observed an anomalous and unacceptable behavior:
Example:
I've carefully examined the code of the UpdateTrailingStop() function, but I can't pinpoint the cause of the problem. I suspect there's an error in the logic for calculating the new stop loss or in managing the update conditions.
I'm attaching the code of the UpdateTrailingStop() function for your analysis:
Thank you in advance for your help.