sl script works buys, not sells.

 

gidday. i want my script to work on forex pairs, all trades, from all forec symbols. My script below is working on both usd and aud deposit accounts, but only on BUY TRADES. help!

I want all my trades have an sl that is equivalent of $350. 

//+------------------------------------------------------------------+
//|                                               SCR5.rRemoveSL.mq5 |
//|                                  Copyright 2026, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
#include <Trade/Trade.mqh>
//bool finished;
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnStart()
  {
   CTrade trade;
   CPositionInfo position;
   trade.SetAsyncMode(true);
   string sym;
   static int start = PositionsTotal(), pos=0, dig;
   static double ts, tv, step, ltv;//, poi; //pft, ltv, cursl, maxsl;
//---
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      if(position.SelectByIndex(i))
        {
         sym=position.Symbol();
         ts=SymbolInfoDouble(sym,SYMBOL_TRADE_TICK_SIZE);
         ltv=PositionGetDouble(POSITION_VOLUME);
         dig=(int)SymbolInfoInteger(sym,SYMBOL_DIGITS);
         step=position.PriceOpen();
         if(position.Type()==POSITION_TYPE_BUY)
           {
            tv=SymbolInfoDouble(sym,SYMBOL_TRADE_TICK_VALUE_LOSS);
            step-=NormalizeDouble(.35 * 1000 / ts * tv / ltv / pow(10,dig*2),dig);
            if(PositionGetDouble(POSITION_SL)!=step)
               if(trade.PositionModify(position.Ticket(),step,NULL))
                  pos-=1;
           }
         else
            if(position.Type()==POSITION_TYPE_SELL)
              {
               tv=SymbolInfoDouble(sym,SYMBOL_TRADE_TICK_VALUE_PROFIT);
               step+=NormalizeDouble(.35 * 1000 / ts * tv / ltv / pow(10,dig*2),dig);
               if(PositionGetDouble(POSITION_SL)!=step)
                  if(trade.PositionModify(position.Ticket(),step,NULL))
                     pos-=1;
              }
        }
     }
  }
//+------------------------------------------------------------------+
 

i wrote a different script that prints out much of the data for usdjpy on my aud account.

The 0.35 in the code is my common tradesize, albeit i want other trades with different sizes -- to have sl that is equivalent of $350 ie if my trade is 0.14, then my sl target will be roughly 2.5X the distance from open price as on the larger 0.35 trade.

Here is the output of that script. supporting my calc result is 875 points for the 0.35 trade. i have also supported this by using myfxbook calculator and got same result of 87.5 pips.


NOTE by "Not working" i mean i get Invalid stops errors. These sell trades do not have a sl on them.
 
Why not ask AI tools? For experienced developers, AI can be helpful. I sometimes put my hand written code into AI and get it to do a code review for me.
 
Conor Mcnamara #:
Why not ask AI tools? For experienced developers, AI can be helpful. I sometimes put my hand written code into AI and get it to do a code review for me.
i just havent made the time to explore that much. and like they say bout "old dogs" and "new tricks".
 
Michael Charles Schefe #NOTE by "Not working" i mean i get Invalid stops errors. These sell trades do not have a sl on them.

Always, before sending an order to modify a position, you need to check the stop levels. Here's an example:

//+--------------------------------------------------------------------------------------------------------------------+
//| Check stop levels
//+--------------------------------------------------------------------------------------------------------------------+
bool CheckStopsLevel(string symbol, ENUM_ORDER_TYPE type, double sl, double tp)
  {
   if(g_cache.stopsLevel == 0)
      return true;

   double price = (type == ORDER_TYPE_BUY) ? g_cache.bid : g_cache.ask;
   double minDistance = g_cache.stopsLevel * g_cache.point;

   if(type == ORDER_TYPE_BUY)
     {
      if(price - sl <= minDistance)
         return false;
      if(tp - price <= minDistance)
         return false;
     }
   else
     {
      if(sl - price <= minDistance)
         return false;
      if(price - tp <= minDistance)
         return false;
     }

   return true;
  }
 
Michael Charles Schefe #:

Antes de realizar a verificação sugerida acima, você pode usar a seguinte função para calcular seu "passo" (deve funcionar para qualquer símbolo e moeda de depósito):

//+--------------------------------------------------------------------------------------------------------------------+
//| Calculates SL price based on a desired risk amount
//| Returns: true if calculated successfully, false otherwise
//+--------------------------------------------------------------------------------------------------------------------+
bool CalculateSLByAmount(string symbol, ENUM_POSITION_TYPE posType, double openPrice,
                         double volume, double riskAmount, double &slPrice)
  {
   slPrice = 0.0;

   if(volume <= 0.0 || riskAmount <= 0.0 || openPrice <= 0.0)
     {
      Print("<", __FUNCTION__, "> ERROR: Invalid parameters - ", symbol);
      return false;
     }

   double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
   if(point <= 0.0)
     {
      Print("<", __FUNCTION__, "> ERROR: Could not get SYMBOL_POINT - ", symbol);
      return false;
     }

// Defines the order type
   ENUM_ORDER_TYPE orderType = (posType == POSITION_TYPE_BUY) ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;

// Calculate the hypothetical loss with SL = openPrice ± 1 point
   double slTest;
   if(posType == POSITION_TYPE_BUY)
      slTest = openPrice - point;
   else
      slTest = openPrice + point;

   double profitPerPoint;
   if(!OrderCalcProfit(orderType, symbol, volume, openPrice, slTest, profitPerPoint))
     {
      Print("<", __FUNCTION__, "> ERROR: OrderCalcProfit failed - ", symbol);
      return false;
     }

// profitPerPoint should be negative (loss). We take the absolute value
   double lossPerPoint = MathAbs(profitPerPoint);

   if(lossPerPoint <= 0.0)
     {
      Print("<", __FUNCTION__, "> ERROR: Invalid loss per point - ", symbol);
      return false;
     }

// Calculate how many points correspond to the desired risk
   double pointsForRisk = riskAmount / lossPerPoint;

// Calculate the final SL price
   if(posType == POSITION_TYPE_BUY)
      slPrice = openPrice - (pointsForRisk * point);
   else
      slPrice = openPrice + (pointsForRisk * point);

// Normalizes the price for the symbol
   NormalizePrice(symbol, slPrice);

   return true;
  }

//+--------------------------------------------------------------------------------------------------------------------+
//| Normalize the price (example)
//+--------------------------------------------------------------------------------------------------------------------+
void NormalizePrice(string symbol, double &price)
  {
   if(g_cache.tickSize == 0.0)
      price = NormalizeDouble(price, (int)g_cache.digits);
   else
      price = NormalizeDouble(MathRound(price / g_cache.tickSize) * g_cache.tickSize, (int)g_cache.digits);
  }
 
Vinicius Pereira De Oliveira #:

Always, before sending an order to modify a position, you need to check the stop levels. Here's an example:

considering the distance of the sl is 875 points, i highly doubt that any stop level is that much. but i will add similar code for event when the sl is close to current price. thanks.

Vinicius Pereira De Oliveira #:

Before performing the verification suggested above, you can use the following function to calculate your "step" (should work for any symbol and deposit currency):

will check it out. thanks.

 
Michael Charles Schefe #considering the distance of the sl is 875 points, i highly doubt that any stop level is that much. but i will add similar code for event when the sl is close to current price. thanks.
So consider using something similar to the NormalizePrice() example above; that might be the problem. 👍
 
Vinicius Pereira De Oliveira #:
So consider using something similar to the NormalizePrice() example above; that might be the problem. 👍
            step-=NormalizeDouble(((double)MathFloor((.35 * 1000 / ts * tv / ltv / (double)pow(10,dig*2)) / ts) - 1) * ts, dig);

tried this. and same thing, same error.

but in coming weekend i will create a new script using much of the code that you posted above to see if i can use it -- assuming that i can follow the math!

 
Michael Charles Schefe:

gidday. i want my script to work on forex pairs, all trades, from all forec symbols. My script below is working on both usd and aud deposit accounts, but only on BUY TRADES. help!

I want all my trades have an sl that is equivalent of $350. 

Try this code, hope it works.

#include <Trade\Trade.mqh>

void OnStart()

  {

   CTrade trade;

   CPositionInfo position;

   trade.SetAsyncMode(false); 

   string sym;

   double ts, tv, step, ltv, current_sl, current_tp;

   int dig;


   for(int i = PositionsTotal() - 1; i >= 0; i--)

     {

      if(position.SelectByIndex(i))

        {

         sym = position.Symbol();

         ts  = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE);

         ltv = PositionGetDouble(POSITION_VOLUME);

         dig = (int)SymbolInfoInteger(sym, SYMBOL_DIGITS);

         step = position.PriceOpen();

         

         current_sl = PositionGetDouble(POSITION_SL);

         current_tp = PositionGetDouble(POSITION_TP);
         

         if(position.Type() == POSITION_TYPE_BUY)

           {

            tv = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE_LOSS);

            step -= NormalizeDouble(.35 * 1000 / ts * tv / ltv / pow(10, dig*2), dig);
            

            if(MathAbs(current_sl - step) > SymbolInfoDouble(sym, SYMBOL_POINT))

              {

               trade.PositionModify(position.Ticket(), step, current_tp); 

              }

           }

         else if(position.Type() == POSITION_TYPE_SELL)

           {

            tv = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE_LOSS);

            

            step += NormalizeDouble(.35 * 1000 / ts * tv / ltv / pow(10, dig*2), dig);

            

            if(MathAbs(current_sl - step) > SymbolInfoDouble(sym, SYMBOL_POINT))

              {

               trade.PositionModify(position.Ticket(), step, current_tp); 

              }

           }

        }

     }

  }

//+------------------------------------------------------------------+
 

i changed the step so that it was simple 2000 points and then 800 points. ALL WITH SAME RESULTS. sell trades are not being modified. mayve it IS NOT my math formulae that was the problem! Can someone test the code on their own demo account please.

//+------------------------------------------------------------------+
//|                                               SCR5.rRemoveSL.mq5 |
//|                                  Copyright 2026, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
#include <Trade/Trade.mqh>
//bool finished;
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnStart()
  {
   CTrade trade;
   CPositionInfo position;
   trade.SetAsyncMode(true);
   string sym;
   static int start = PositionsTotal(), pos=0; //, dig;
//   static double step;
//---
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      if(position.SelectByIndex(i))
        {
         sym=position.Symbol();
         double point = SymbolInfoDouble(sym,SYMBOL_POINT);
         int dig = (int)SymbolInfoInteger(sym,SYMBOL_DIGITS);
         double step=(double)position.PriceOpen();
         if(position.Type()==POSITION_TYPE_BUY)
           {
            step-=point*800;
            if(trade.PositionModify(position.Ticket(),NormalizeDouble(step,dig),NULL))
               pos-=1;
           }
         else
            if(position.Type()==POSITION_TYPE_SELL)
              {
               step+=point*800;
               if(trade.PositionModify(position.Ticket(),NormalizeDouble(step,dig),NULL))
                  pos-=1;
              }
        }
     }
  }
//+------------------------------------------------------------------+