Unable to modify the SL

 

Hi, having some trouble here, not sure if anyone will be able to assist me?

Price level was 154.023, 10.8 pips from the attempted SL so not sure why there would be

2024.12.17 23:13:36.741 2024.12.16 16:00:00   failed modify #325 sell 0.2 USDJPY sl: 154.131, tp: 0.000 -> sl: 154.131, tp: 0.000 [Invalid stops]

2024.12.17 23:13:36.741 2024.12.16 16:00:00   ERROR: Failed to modify SL | Ticket: 325 | Error: 4756 


ChatGBT told me this about error code but i wanted see if there is a workaround?:

The "Invalid stops" error typically occurs because the stop loss (SL) value you are trying to set does not meet the broker's requirements. This can be due to:

SL too close to the current price – it violates the SYMBOL_TRADE_STOPS_LEVEL.

SL does not align with the symbol's tick size.

Incorrect price normalization.


//+----------------------------------------------------------------------------------------------------------------------------------+
//|  MODIFICATION                                                                                                                                       |
//+----------------------------------------------------------------------------------------------------------------------------------+
// Function to get the precision (digits) for the symbol
int GetDigitsForSymbol(string symbol) {
    return (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
}

// Modify Stop Loss function
void ModifySL(ulong ticket, double entryPrice, double originalSL, 
              double psimpleBuyingTPResult1, double psimpleBuyingTPResult2, double psimpleBuyingTPResult3, 
              double psimpleSellingTPResult1, double psimpleSellingTPResult2, double psimpleSellingTPResult3, 
              double pCloseLongIndicatorBasedTPLevel1, double pCloseLongIndicatorBasedTPLevel2, double pCloseLongIndicatorBasedTPLevel3, 
              double pCloseShortIndicatorBasedTPLevel1, double pCloseShortIndicatorBasedTPLevel2, double pCloseShortIndicatorBasedTPLevel3, 
              double ppipvalue) {

    MqlTradeRequest request;
    MqlTradeResult result;
    ZeroMemory(request);

    if (PositionSelectByTicket(ticket)) {
        string symbol = PositionGetString(POSITION_SYMBOL);
        ENUM_POSITION_TYPE positionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
        double currentPrice = (positionType == POSITION_TYPE_BUY) ? SymbolInfoDouble(symbol, SYMBOL_BID) : SymbolInfoDouble(symbol, SYMBOL_ASK);
        double minSLDistance = SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;

        // Get the symbol's precision
        int digits = GetDigitsForSymbol(symbol);

        PrintFormat("DEBUG: Ticket: %I64u | Symbol: %s | Current Price: %.5f | Entry: %.5f | Original SL: %.5f", 
                    ticket, symbol, currentPrice, entryPrice, originalSL);

        if (originalSL == 0) {
            PrintFormat("ERROR: No original SL set for Ticket: %I64u", ticket);
            return;
        }

        // Separate SL values for BUY and SELL positions
        double halfwaySL_BUY  = NormalizeDouble(entryPrice - (entryPrice - originalSL) / 2.0, digits); // Midway SL for BUY
        double halfwaySL_SELL = NormalizeDouble(entryPrice + (originalSL - entryPrice) / 2.0, digits); // Midway SL for SELL

        double greenSL_BUY  = NormalizeDouble(entryPrice + (entryPrice - originalSL) / 2.0, digits); // 5 pips in green for BUY
        double greenSL_SELL = NormalizeDouble(entryPrice - (originalSL - entryPrice) / 2.0, digits); // 5 pips in green for SELL

        double updatedSL = originalSL;

        // Update SL for BUY positions
        if (positionType == POSITION_TYPE_BUY) {
            if (currentPrice >= psimpleBuyingTPResult1) {
                updatedSL = halfwaySL_BUY; // Move SL midway
                PrintFormat("First TP hit for BUY | Ticket: %I64u | New SL: %.5f", ticket, updatedSL);
            }
            if (currentPrice >= psimpleBuyingTPResult2) {
                updatedSL = greenSL_BUY; // Move SL 5 pips in the green
                PrintFormat("Second TP hit for BUY | Ticket: %I64u | New SL: %.5f", ticket, updatedSL);
            }
        }

        // Update SL for SELL positions
        if (positionType == POSITION_TYPE_SELL) {
            if (currentPrice <= psimpleSellingTPResult1) {
                updatedSL = halfwaySL_SELL; // Move SL midway
                PrintFormat("First TP hit for SELL | Ticket: %I64u | New SL: %.5f", ticket, updatedSL);
            }
            if (currentPrice <= psimpleSellingTPResult2) {
                updatedSL = greenSL_SELL; // Move SL 5 pips in the green
                PrintFormat("Second TP hit for SELL | Ticket: %I64u | New SL: %.5f", ticket, updatedSL);
            }
        }

        // Validate SL respects broker rules
        if ((positionType == POSITION_TYPE_BUY && (updatedSL >= currentPrice || currentPrice - updatedSL < minSLDistance)) ||
            (positionType == POSITION_TYPE_SELL && (updatedSL <= currentPrice || updatedSL - currentPrice < minSLDistance))) {
            PrintFormat("ERROR: Invalid SL adjustment | Ticket: %I64u | SL: %.5f | Current Price: %.5f | Min Distance: %.5f", 
                        ticket, updatedSL, currentPrice, minSLDistance);
            return;
        }

        // Prepare and send the SL modification request
        request.action   = TRADE_ACTION_SLTP;
        request.position = ticket;
        request.symbol   = symbol;
        request.sl       = updatedSL;
        request.tp       = PositionGetDouble(POSITION_TP);
        request.deviation = 10;

        if (OrderSend(request, result)) {
            PrintFormat("SUCCESS: Modified SL | Ticket: %I64u | New SL: %.5f", ticket, updatedSL);
        } else {
            PrintFormat("ERROR: Failed to modify SL | Ticket: %I64u | Error: %d", ticket, GetLastError());
        }
    } else {
        PrintFormat("ERROR: Failed to select position for Ticket: %I64u", ticket);
    }
}

// Helper Function to Adjust SL for All Positions
void AdjustSLForAllPositions(double psimpleBuyingTPResult1, double psimpleBuyingTPResult2, double psimpleBuyingTPResult3, double psimpleSellingTPResult1, double psimpleSellingTPResult2,      
                             double psimpleSellingTPResult3, double pCloseLongIndicatorBasedTPLevel1, double pCloseLongIndicatorBasedTPLevel2, double pCloseLongIndicatorBasedTPLevel3, 
                             double pCloseShortIndicatorBasedTPLevel1, double pCloseShortIndicatorBasedTPLevel2, double pCloseShortIndicatorBasedTPLevel3, double ppipvalue) {
   
    int totalPositions = PositionsTotal();
    for (int i = totalPositions - 1; i >= 0; i--) {
        ulong ticket = PositionGetTicket(i);
        if (ticket > 0 && PositionSelectByTicket(ticket)) {
            double entryPrice = PositionGetDouble(POSITION_PRICE_OPEN);
            double originalSL = PositionGetDouble(POSITION_SL);
            ModifySL(ticket, entryPrice, originalSL, psimpleBuyingTPResult1, psimpleBuyingTPResult2, psimpleBuyingTPResult3, 
                     psimpleSellingTPResult1, psimpleSellingTPResult2, psimpleSellingTPResult3, pCloseLongIndicatorBasedTPLevel1, pCloseLongIndicatorBasedTPLevel2, pCloseLongIndicatorBasedTPLevel3, 
                     pCloseShortIndicatorBasedTPLevel1, pCloseShortIndicatorBasedTPLevel2, pCloseShortIndicatorBasedTPLevel3, ppipvalue);
        }
    }
}

void ClosePositionByTicket(ulong ticket) {
    MqlTradeRequest request;   // Trade request structure
    MqlTradeResult result;     // Trade result structure
    ZeroMemory(request);       // Clear the trade request structure

    // Confirm position validity by ticket
    if (PositionSelectByTicket(ticket)) {
        string symbol = PositionGetString(POSITION_SYMBOL);
        ENUM_POSITION_TYPE positionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
        double volume = PositionGetDouble(POSITION_VOLUME);

        // Set up the request to close the position
        request.action   = TRADE_ACTION_DEAL;           // Close the position
        request.position = ticket;                     // Ticket of the position
        request.symbol   = symbol;                     // Symbol of the position
        request.volume   = volume;                     // Volume of the position
        request.type     = (positionType == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY; // Opposite trade type
        request.price    = (request.type == ORDER_TYPE_SELL) 
                            ? SymbolInfoDouble(symbol, SYMBOL_BID) 
                            : SymbolInfoDouble(symbol, SYMBOL_ASK); // Market price
        request.deviation = 10;                        // Allowable slippage in points

        // Send the request to close the position
        if (OrderSend(request, result)) {
            PrintFormat("Closed Position | Ticket: %I64u | Symbol: %s | Volume: %.2f", 
                       ticket, symbol, volume);
        } else {
            PrintFormat("Failed to Close Position | Ticket: %I64u | Error: %d", 
                       ticket, GetLastError());
        }
    } else {
        PrintFormat("Failed to select position for Ticket: %I64u", ticket);
    }
} 
 
luccc:

Hi, having some trouble here, not sure if anyone will be able to assist me?

Price level was 154.023, 10.8 pips from the attempted SL so not sure why there would be

2024.12.17 23:13:36.741 2024.12.16 16:00:00   failed modify #325 sell 0.2 USDJPY sl: 154.131, tp: 0.000 -> sl: 154.131, tp: 0.000 [Invalid stops]

2024.12.17 23:13:36.741 2024.12.16 16:00:00   ERROR: Failed to modify SL | Ticket: 325 | Error: 4756 


ChatGBT told me this about error code but i wanted see if there is a workaround?:

The "Invalid stops" error typically occurs because the stop loss (SL) value you are trying to set does not meet the broker's requirements. This can be due to:

SL too close to the current price – it violates the SYMBOL_TRADE_STOPS_LEVEL.

SL does not align with the symbol's tick size.

Incorrect price normalization.


Best practice is to auto-check SYMBOL_TRADE_STOPS_LEVEL before sending a SL order (or a TP order).

Symbol Properties - Environment State - Constants, Enumerations and Structures - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Symbol Properties
Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Symbol Properties
  • www.mql5.com
To obtain the current market information there are several functions: SymbolInfoInteger() , SymbolInfoDouble() and SymbolInfoString() . The first...
 
Ryan L Johnson #:

Best practice is to auto-check SYMBOL_TRADE_STOPS_LEVEL before sending a SL order (or a TP order).

Symbol Properties - Environment State - Constants, Enumerations and Structures - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5

I've tested the SYMBOL_TRADE_STOPS_LEVEL in the ontick and returned 31 points. In the example I showed you, the distance was 10.8, so I'm still not sure why i can't modify the position.

 
luccc #:

I've tested the SYMBOL_TRADE_STOPS_LEVEL in the ontick and returned 31 points. In the example I showed you, the distance was 10.8, so I'm still not sure why i can't modify the position.

SYMBOL_TRADE_STOPS_LEVEL is an int. It appears that you've used it to define a double without typecasting:

double minSLDistance = SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;

Symbol Properties - Environment State - Constants, Enumerations and Structures - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5

Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Symbol Properties
Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Symbol Properties
  • www.mql5.com
To obtain the current market information there are several functions: SymbolInfoInteger() , SymbolInfoDouble() and SymbolInfoString() . The first...