11#property  link           " https://www.earnforex.com/metatrader-expert-advisors/Trailing-Stop-on-Profit/" 
2- #property  version        " 1.01 " 
2+ #property  version        " 1.02 " 
33#property  strict 
4- #property  copyright      " EarnForex.com - 2022 " 
4+ #property  copyright      " EarnForex.com - 2023 " 
55#property  description    " This Expert Advisor will start trailing the stop-loss after a given profit is reached." 
66#property  description    "  " 
77#property  description    " WARNING: No warranty. This EA is offered \" as is\" . Use at your own risk.\r\n " 
@@ -22,6 +22,7 @@ input group "Expert advisor settings"
2222input  int  TrailingStop  = 50 ;                       // Trailing Stop, points 
2323input  int  Profit  = 100 ;                            // Profit in points when TS should kick in. 
2424input  group  " Orders filtering options" 
25+ input  bool  OnlyCurrentSymbol  = true ;               // Apply to current symbol only 
2526input  ENUM_CONSIDER  OnlyType  = All ;                // Apply to 
2627input  bool  UseMagic  = false ;                       // Filter by magic number 
2728input  int  MagicNumber  = 0 ;                         // Magic number (if above is true) 
@@ -35,7 +36,7 @@ input bool SendApp = true;                         // Send notification to mobil
3536input  bool  SendEmail  = true ;                       // Send notification via email 
3637input  group  " Graphical window" 
3738input  bool  ShowPanel  = true ;                       // Show graphical panel 
38- input  string  IndicatorName  = " TSOP"  ;               // Indicator  name (to name the objects) 
39+ input  string  ExpertName  = " TSOP"  ;                   // Expert  name (to name the objects) 
3940input  int  Xoff  = 20 ;                               // Horizontal spacing for the control panel 
4041input  int  Yoff  = 20 ;                               // Vertical spacing for the control panel 
4142
@@ -106,53 +107,67 @@ void TrailingStop()
106107        if  (SymbolInfoInteger (PositionGetString (POSITION_SYMBOL ), SYMBOL_TRADE_MODE ) == SYMBOL_TRADE_MODE_DISABLED ) continue ;
107108
108109        // Filters. 
109-         if  (PositionGetString (POSITION_SYMBOL ) != Symbol ()) continue ;
110+         if  (( OnlyCurrentSymbol ) && ( PositionGetString (POSITION_SYMBOL ) != Symbol () )) continue ;
110111        if  ((UseMagic ) && (PositionGetInteger (POSITION_MAGIC ) != MagicNumber )) continue ;
111112        if  ((UseComment ) && (StringFind (PositionGetString (POSITION_COMMENT ), CommentFilter ) < 0 )) continue ;
112113        if  ((OnlyType  != All ) && (PositionGetInteger (POSITION_TYPE ) != OnlyType )) continue ;
113114
115+         double  point  = SymbolInfoDouble (PositionGetString (POSITION_SYMBOL ), SYMBOL_POINT );
116+         
114117        // Normalize trailing stop value to the point value. 
115-         double  TSTP  = TrailingStop  * _Point ;
116-         double  P  = Profit  * _Point ;
118+         double  TSTP  = TrailingStop  * point ;
119+         double  P  = Profit  * point ;
117120
118-         double  Bid  = SymbolInfoDouble (Symbol ( ), SYMBOL_BID );
119-         double  Ask  = SymbolInfoDouble (Symbol ( ), SYMBOL_ASK );
121+         double  Bid  = SymbolInfoDouble (PositionGetString ( POSITION_SYMBOL ), SYMBOL_BID );
122+         double  Ask  = SymbolInfoDouble (PositionGetString ( POSITION_SYMBOL ), SYMBOL_ASK );
120123        double  OpenPrice  = PositionGetDouble (POSITION_PRICE_OPEN );
121124        double  StopLoss  = PositionGetDouble (POSITION_SL );
122125        double  TakeProfit  = PositionGetDouble (POSITION_TP );
126+         int  eDigits  = (int )SymbolInfoInteger (PositionGetString (POSITION_SYMBOL ), SYMBOL_DIGITS );
127+         double  TickSize  = SymbolInfoDouble (OrderSymbol (), SYMBOL_TRADE_TICK_SIZE );
123128
124129        if  (PositionGetInteger (POSITION_TYPE ) == POSITION_TYPE_BUY )
125130        {
126-             if  (NormalizeDouble (Bid  - OpenPrice , _Digits ) >= NormalizeDouble (P , _Digits ))
131+             if  (NormalizeDouble (Bid  - OpenPrice , eDigits ) >= NormalizeDouble (P , eDigits ))
127132            {
128-                 if  ((TSTP  != 0 ) && (StopLoss  < NormalizeDouble (Bid  - TSTP , _Digits )))
133+                 double  new_sl  = NormalizeDouble (Bid  - TSTP , eDigits );
134+                 if  (TickSize  > 0 ) // Adjust for tick size granularity. 
135+                 {
136+                     new_sl  = NormalizeDouble (MathRound (new_sl  / TickSize ) * TickSize , eDigits );
137+                 }
138+                 if  ((TSTP  != 0 ) && (StopLoss  < new_sl ))
129139                {
130-                     ModifyPosition (ticket , OpenPrice , NormalizeDouble ( Bid  -  TSTP ,  _Digits ),  TakeProfit );
140+                     ModifyPosition (ticket , OpenPrice , new_sl ,  TakeProfit ,  PositionGetString ( POSITION_SYMBOL ) );
131141                }
132142            }
133143        }
134144        else  if  (PositionGetInteger (POSITION_TYPE ) == POSITION_TYPE_SELL )
135145        {
136-             if  (NormalizeDouble (OpenPrice  - Ask , _Digits ) >= NormalizeDouble (P , _Digits ))
146+             if  (NormalizeDouble (OpenPrice  - Ask , eDigits ) >= NormalizeDouble (P , eDigits ))
137147            {
138-                 if  ((TSTP  != 0 ) && ((StopLoss  > NormalizeDouble (Ask  + TSTP , _Digits )) || (StopLoss  == 0 )))
148+                 double  new_sl  = NormalizeDouble (Ask  + TSTP , eDigits );
149+                 if  (TickSize  > 0 ) // Adjust for tick size granularity. 
150+                 {
151+                     new_sl  = NormalizeDouble (MathRound (new_sl  / TickSize ) * TickSize , eDigits );
152+                 }
153+                 if  ((TSTP  != 0 ) && ((StopLoss  > new_sl ) || (StopLoss  == 0 )))
139154                {
140-                     ModifyPosition (ticket , OpenPrice , NormalizeDouble ( Ask  +  TSTP ,  _Digits ),  TakeProfit );
155+                     ModifyPosition (ticket , OpenPrice , new_sl ,  TakeProfit ,  PositionGetString ( POSITION_SYMBOL ) );
141156                }
142157            }
143158        }
144159    }
145160}
146161
147- void  ModifyPosition (ulong  Ticket , double  OpenPrice , double  SLPrice , double  TPPrice )
162+ void  ModifyPosition (ulong  Ticket , double  OpenPrice , double  SLPrice , double  TPPrice ,  string   symbol )
148163{
149164    for  (int  i  = 1 ; i  <= OrderOpRetry ; i ++) // Several attempts to modify the position. 
150165    {
151166        bool  result  = Trade .PositionModify (Ticket , SLPrice , TPPrice );
152167        if  (result )
153168        {
154169            Print (" TRADE - UPDATE SUCCESS - Order "  , Ticket , "  new stop-loss "  , SLPrice );
155-             NotifyStopLossUpdate (Ticket , SLPrice );
170+             NotifyStopLossUpdate (Ticket , SLPrice ,  symbol );
156171            break ;
157172        }
158173        else 
@@ -161,22 +176,21 @@ void ModifyPosition(ulong Ticket, double OpenPrice, double SLPrice, double TPPri
161176            string  ErrorText  = ErrorDescription (Error );
162177            Print (" ERROR - UPDATE FAILED - error modifying order "  , Ticket , "  return error: "  , Error , "  Open="  , OpenPrice ,
163178                  "  Old SL="  , PositionGetDouble (POSITION_SL ),
164-                   "  New SL="  , SLPrice , "  Bid="  , SymbolInfoDouble (Symbol () , SYMBOL_BID ), "  Ask="  , SymbolInfoDouble (Symbol () , SYMBOL_ASK ));
179+                   "  New SL="  , SLPrice , "  Bid="  , SymbolInfoDouble (symbol , SYMBOL_BID ), "  Ask="  , SymbolInfoDouble (symbol , SYMBOL_ASK ));
165180            Print (" ERROR - "  , ErrorText );
166181        }
167182    }
168183}
169184
170- void  NotifyStopLossUpdate (ulong  Ticket , double  SLPrice )
185+ void  NotifyStopLossUpdate (ulong  Ticket , double  SLPrice ,  string   symbol )
171186{
172187    if  (!EnableNotify ) return ;
173188    if  ((!SendAlert ) && (!SendApp ) && (!SendEmail )) return ;
174-     string  EmailSubject  = IndicatorName  + "  "   + Symbol () + "  Notification"  ;
175-     string  EmailBody  = AccountInfoString (ACCOUNT_COMPANY ) + "  - "   + AccountInfoString (ACCOUNT_NAME ) + "  - "   + IntegerToString (AccountInfoInteger (ACCOUNT_LOGIN )) + " \r\n\r\n "   + IndicatorName  + "  Notification for "   + Symbol ()  + " \r\n\r\n "  ;
189+     string  EmailSubject  = ExpertName  + "  "   + Symbol () + "  Notification"  ;
190+     string  EmailBody  = AccountInfoString (ACCOUNT_COMPANY ) + "  - "   + AccountInfoString (ACCOUNT_NAME ) + "  - "   + IntegerToString (AccountInfoInteger (ACCOUNT_LOGIN )) + " \r\n\r\n "   + ExpertName  + "  Notification for "   + symbol  + " \r\n\r\n "  ;
176191    EmailBody  += " Stop-loss for order "   + IntegerToString (Ticket ) + "  moved to "   + DoubleToString (SLPrice , _Digits );
177-     string  AlertText  = IndicatorName  + "  - Notification: "  ;
178-     AlertText  += " Stop-loss for order "   + IntegerToString (Ticket ) + "  moved to "   + DoubleToString (SLPrice , _Digits );
179-     string  AppText  = AccountInfoString (ACCOUNT_COMPANY ) + "  - "   + AccountInfoString (ACCOUNT_NAME ) + "  - "   + IntegerToString (AccountInfoInteger (ACCOUNT_LOGIN )) + "  - "   + IndicatorName  + "  - "   + Symbol () + "  - "  ;
192+     string  AlertText  = symbol  + "  - Stop-loss for order "   + IntegerToString (Ticket ) + "  moved to "   + DoubleToString (SLPrice , _Digits );
193+     string  AppText  = AccountInfoString (ACCOUNT_COMPANY ) + "  - "   + AccountInfoString (ACCOUNT_NAME ) + "  - "   + IntegerToString (AccountInfoInteger (ACCOUNT_LOGIN )) + "  - "   + ExpertName  + "  - "   + symbol  + "  - "  ;
180194    AppText  += " Stop-loss for order "   + IntegerToString (Ticket ) + "  moved to "   + DoubleToString (SLPrice , _Digits );
181195    if  (SendAlert ) Alert (AlertText );
182196    if  (SendEmail )
@@ -187,12 +201,12 @@ void NotifyStopLossUpdate(ulong Ticket, double SLPrice)
187201    {
188202        if  (!SendNotification (AppText )) Print (" Error sending notification "   + IntegerToString (GetLastError ()));
189203    }
190-     Print (IndicatorName  + "  - last notification sent on "   + TimeToString (TimeCurrent ()));
204+     Print (ExpertName  + "  - last notification sent on "   + TimeToString (TimeCurrent ()));
191205}
192206
193- string  PanelBase  = IndicatorName  + " -P-BAS"  ;
194- string  PanelLabel  = IndicatorName  + " -P-LAB"  ;
195- string  PanelEnableDisable  = IndicatorName  + " -P-ENADIS"  ;
207+ string  PanelBase  = ExpertName  + " -P-BAS"  ;
208+ string  PanelLabel  = ExpertName  + " -P-LAB"  ;
209+ string  PanelEnableDisable  = ExpertName  + " -P-ENADIS"  ;
196210
197211int  PanelMovX  = 50 ;
198212int  PanelMovY  = 20 ;
@@ -275,7 +289,7 @@ void DrawPanel()
275289
276290void  CleanPanel ()
277291{
278-     ObjectsDeleteAll (ChartID (), IndicatorName );
292+     ObjectsDeleteAll (ChartID (), ExpertName );
279293}
280294
281295void  ChangeTrailingEnabled ()
0 commit comments