Trailing stop---invalid request - page 2

 
  1. As requested in post #2 by @Carl Schreiber, please have your code output to the log the relevant data of the modification attempt. Print the Bid price, Ask price, position's Open price, previous stops and the new stops, Stops Level, Freeze Level, and show us the log output for when the trailing fails.
  2. In your code you are not checking for the stops not being different. If you try to update stops with the same values, it will also report an error. So please add that condition to your code.
  3. Also, on a different note, prices should be aligned to the tick size, not normalised to the number of digits. In the case of many currency pairs, where tick size and point size are the same, this issue does not appear, but the method is incorrect and you should correct it for the case of other symbols. So please read the following post ... https://www.mql5.com/en/forum/390453#comment_28220035
 
Fernando Carreiro #:
  1. As requested in post #2 by @Carl Schreiber, please have your code output to the log the relevant data of the modification attempt. Print the Bid price, Ask price, position's Open price, previous stops and the new stops, Stops Level, Freeze Level, and show us the log output for when the trailing fails.
  2. In your code you are not checking for the stops are not different. If you try to update stops with the same values, it will also report an error. So please add that condition to your code.
  3. Also, on a different note, prices should be aligned to the tick size, not normalised to the number of digits. In the case of many currency pairs, where tick size and point size are the same, this issue does not appear, but the method is incorrect and you should correct it for the case of other symbols. So please read the following post ... https://www.mql5.com/en/forum/390453#comment_28220035

Ok so this is my code part that involves stop loss and take profit...I've tried to modify it with ticks but it gives me the same error in  the tester....now I'm going to paste that

void CalculateSLTP(double current_price, double &sl, double &tp)
{
    // Ottieni il valore dell'ATR
    int atrHandle = iATR(_Symbol, 0, ATR_Period);
    if (atrHandle == INVALID_HANDLE)
    {
        Print("Errore nell'ottenere l'handle ATR: ", GetLastError());
        return;
    }

    // Copia il buffer dei dati ATR
    double atrBuffer[];
    ArraySetAsSeries(atrBuffer, true);
    int copied = CopyBuffer(atrHandle, 0, 0, 1, atrBuffer);
    if (copied <= 0)
    {
        Print("Errore nel copiare i dati ATR, numero di dati copiati: ", copied);
        Print("Codice errore: ", GetLastError());
        IndicatorRelease(atrHandle);
        return;
    }

    // Verifica il valore dell'ATR
    double atrValue = atrBuffer[0];
    Print("ATR copiato correttamente: ", atrValue);

    // Calcolo della distanza per SL e TP
    double stop_distance = atrValue * ATRMultiplier;
    double target_distance = stop_distance * RiskRewardRatio;

    // Arrotonda le distanze al tick size
    double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
    stop_distance = MathRound(stop_distance / tick_size) * tick_size;
    target_distance = MathRound(target_distance / tick_size) * tick_size;

    Print("Distanza SL (arrotondata al tick): ", stop_distance);
    Print("Distanza TP (arrotondata al tick): ", target_distance);

    // Ottieni il livello minimo di stop dal broker
    double stop_level = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * tick_size;
    Print("Livello minimo di distanza per SL/TP: ", stop_level);

    if (atrValue <= 0 || stop_distance < stop_level)
    {
        Print("ERRORE: ATR troppo basso o distanza SL inferiore al livello minimo.");
        IndicatorRelease(atrHandle);
        return;
    }

    // Calcolo SL e TP in base al tipo di ordine
    if (OrderType == ORDER_TYPE_BUY)
    {
        sl = current_price - stop_distance;
        tp = current_price + target_distance;
    }
    else if (OrderType == ORDER_TYPE_SELL)
    {
        sl = current_price + stop_distance;
        tp = current_price - target_distance;
    }

    // Arrotonda i valori di SL e TP al tick size
    sl = MathRound(sl / tick_size) * tick_size;
    tp = MathRound(tp / tick_size) * tick_size;

    Print("SL calcolato: ", sl, ", TP calcolato: ", tp);

    IndicatorRelease(atrHandle);
}




// Funzione per aprire una posizione
void OpenTrade(int order_type)
{
    Print("Apertura di un nuovo trade...");

    // Variabili per SL e TP
    double sl = 0;
    double tp = 0;

    // Ottieni il prezzo corrente
    double current_price = (order_type == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID);

    // Calcola SL e TP
    CalculateSLTP(current_price, sl, tp);

    // Ottieni la dimensione del tick per il simbolo corrente
    double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE); // Ottieni la dimensione del tick

    // Calcola la distanza minima dal prezzo corrente
    double stop_level = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * tick_size; // Distanza minima richiesta dal broker
    if (stop_level <= 0)
    {
        Print("Errore nel recupero del livello minimo di stop. Stop level impostato a valore predefinito.");
        stop_level = 10 * tick_size; // Valore predefinito
    }

    // Calcola il lotto minimo e massimo
    double min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
    double max_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);

    // Calcola la distanza dello stop loss in tick (non in punti)
    double stop_loss_distance = MathAbs(current_price - sl) / tick_size;  // Ora è diviso per tick_size

    // Calcola la dimensione del lotto
    double lot_size = 0.3;

    // Verifica la distanza minima di SL/TP in base alla dimensione del tick
    if (MathAbs(sl - current_price) < stop_level)  // Distanza minima per SL
    {
        sl = current_price + stop_level;  // Allineato alla dimensione del tick
    }
    if (MathAbs(tp - current_price) < stop_level)  // Distanza minima per TP
    {
        tp = current_price + stop_level;  // Allineato alla dimensione del tick
    }

    // Controlla che SL e TP siano diversi
    if (MathAbs(sl - tp) < 0.0001)  // Ad esempio, se sono troppo vicini
    {
        Print("SL e TP sono troppo vicini, aggiustamento...");
        tp = sl + 0.001;  // Aggiungi una distanza minima
    }

    // Allineamento dei prezzi per il tipo di ordine
    sl = round(sl / tick_size) * tick_size;  // Allinea SL alla dimensione del tick
    tp = round(tp / tick_size) * tick_size;  // Allinea TP alla dimensione del tick

    if (order_type == ORDER_TYPE_BUY)
    {
        Print("Tentativo di apertura ordine BUY...");
        if (trade.Buy(lot_size, _Symbol, current_price, sl, tp))
        {
            Print("Ordine BUY aperto con successo.");
        }
        else
        {
            int error_code = GetLastError();  // Ottieni il codice errore
            Print("Errore nell'aprire ordine BUY. Codice errore: ", error_code);
        }
    }
    else if (order_type == ORDER_TYPE_SELL)
    {
        Print("Tentativo di apertura ordine SELL...");
        if (trade.Sell(lot_size, _Symbol, current_price, sl, tp))
        {
            Print("Ordine SELL aperto con successo.");
        }
        else
        {
            int error_code = GetLastError();  // Ottieni il codice errore
            Print("Errore nell'aprire ordine SELL. Codice errore: ", error_code);
        }
    }
}

// Funzione per calcolare SL e TP in ticks
void CalculateSLTP(int current_price_ticks, int &sl_ticks, int &tp_ticks)
{
    // Logica di calcolo per SL e TP
    // (Aggiungere la logica del calcolo per il trailing stop e gli altri criteri di entrata)
    
    sl_ticks = current_price_ticks - 10;  // esempio di SL a 10 tick sotto il prezzo
    tp_ticks = current_price_ticks + 20;  // esempio di TP a 20 tick sopra il prezzo
}
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   DEBUG: No condition met for opening order.
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   Calculating RSI value...
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   RSI successfully copied: 29.983356134781133
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   Calculating MACD values...
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   MACD values obtained: MACD: -0.0019258271391831006, Signal: -0.0008571263376794908
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   Calculating ADX value...
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   ADX successfully copied: 26.62934860671219
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   Calculating Bollinger Bands...
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   Final SMA value: 1.271688
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   Standard Deviation: 0.003096100127592956
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   Bollinger Bands calculated: Upper: 1.277880200255186, Middle: 1.271688, Lower: 1.265495799744814
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   DEBUG: BUY condition met (RSI < RSI_Oversold: true, MACD Main > MACD Signal: false, ADX > ADX Threshold: true, BID price < Lower Band: 1.2647300000000001, ASK price: 1.2647300000000001)
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   A position is already open for the symbol: GBPUSD
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   Calling ApplyTrailingStop() function
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   DEBUG: BID price: 1.26462, ASK price: 1.2647300000000001
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   DEBUG: Stop level: 0.0, Freeze level: 0.0
CS 2 16:11:13.004   Trades                                          2024.01.02 15:18:12  failed modify #2 buy 0.3 GBPUSD sl: 1.26060, tp: 1.27588 -> sl: 1.26262, tp: 1.27588 [Invalid request]
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   Error updating SL/TP: 4756
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:12   DEBUG: Error updating trailing stop BUY. Error code: 4756
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:13   Calculating RSI value...
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:13   RSI successfully copied: 30.059167403751076
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:13   Calculating MACD values...
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:13   MACD values obtained: MACD: -0.0019242316975878193, Signal: -0.0008569490663911262
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:13   Calculating ADX value...
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:13   ADX successfully copied: 26.62934860671219
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:13   Calculating Bollinger Bands...
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:13   Final SMA value: 1.2716889999999998
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:13   Standard Deviation: 0.003093835645327337
CS 0 16:11:13.004 new trend following 2 (GBPUSD,H1) 2024.01.02 15:18:13   Bollinger Bands calculated: Upper: 1.2778766712906546, Middle: 1.2716889999999998, Lower: 1.265501328709345


And this is the tester

 
  1. If the error is the generalised "Invalid request", then please report to the log the actual trading result error code using the ResultRetcode() method.
  2. On a separate unrelated issue, don't keep instantiating and releasing the Indicator on every call. Instantiate it once on in OnInit() and then reuse the handle when needed.
Documentation on MQL5: Standard Library / Trade Classes / CTrade / ResultRetcode
Documentation on MQL5: Standard Library / Trade Classes / CTrade / ResultRetcode
  • www.mql5.com
Gets the code of request execution result. Return Value The code of request result...
 
Fernando Carreiro #:
  1. If the error is the generalised "Invalid request", then please report to the log the actual trading result error code using the ResultRetcode() method.
  2. On a separate unrelated issue, don't keep instantiating and releasing the Indicator on every call. Instantiate it once on in OnInit() and then reuse the handle when needed.
CS  0   08:39:10.852   new trend following 5 (GBPUSD,H1)   2024.01.02 15:25:45   DEBUG: BUY condition satisfied (RSI < RSI_Oversold: true, MACD Main > MACD Signal: false, ADX > ADX Threshold: true, BID Price < Lower Band: 1.26425, ASK Price: 1.26425)
CS  0   08:39:10.852   new trend following 5 (GBPUSD,H1)   2024.01.02 15:25:45   A position already exists for the symbol: GBPUSD
CS  0   08:39:10.852   new trend following 5 (GBPUSD,H1)   2024.01.02 15:25:45   Calling the ApplyTrailingStop() function
CS  0   08:39:10.852   new trend following 5 (GBPUSD,H1)   2024.01.02 15:25:45   DEBUG: BID Price: 1.2641200000000001, ASK Price: 1.26425
CS  0   08:39:10.852   new trend following 5 (GBPUSD,H1)   2024.01.02 15:25:45   DEBUG: Stop level: 0.0, Freeze level: 0.0
CS  2   08:39:10.852   Trades                                              2024.01.02 15:25:45   failed modify #2 buy 0.3 GBPUSD sl: 1.26060, tp: 1.27588 -> sl: 1.26212, tp: 1.27588 [Invalid request]
CS  0   08:39:10.852   new trend following 5 (GBPUSD,H1)   2024.01.02 15:25:45   Error updating SL/TP. Error code: 10013
CS  0   08:39:10.852   new trend following 5 (GBPUSD,H1)   2024.01.02 15:25:45   Error description: Invalid request
CS  0   08:39:10.852   new trend following 5 (GBPUSD,H1)   2024.01.02 15:25:45   DEBUG: Error updating trailing stop BUY. Error code: 4756

This is the log....the retcode gives me 10013 which is also invalid request.

During the test, even when the price rises significantly on the chart, the log doesn't show any attempt to apply the trailing stop. The log only sporadically shows the trailing stop being attempted, and even then, it happens only immediately after opening an order.

Do you need me to share the part of the code where the trailing stop is implemented in the OnTick function?


 

Pietroalutto1 #:

// Get the current order ticket (for pending orders)
    ulong ticket = PositionGetInteger(POSITION_TICKET);

    // Check if the position is pending using OrderSelect()
    if (OrderSelect(ticket))
    {
        long order_type = OrderGetInteger(ORDER_TYPE);  // Order type

        // If the order is pending (BUY_LIMIT, SELL_LIMIT, BUY_STOP, SELL_STOP)
        if (order_type == ORDER_TYPE_BUY_LIMIT || order_type == ORDER_TYPE_SELL_LIMIT || 
            order_type == ORDER_TYPE_BUY_STOP || order_type == ORDER_TYPE_SELL_STOP)
        {
            Print("DEBUG: The position is a pending order. Trailing stop cannot be applied.");
            return;
        }
    }


You are mixing up the concepts of Positions and Orders. Don't think in the MT4 way. An open position is NEVER a "pending order". It is just an open position currently in the market, irrespective of what order created it.

The part I marked in red is useless. Take it out.

Please read the following article ...

Articles

Orders, Positions and Deals in MetaTrader 5

MetaQuotes, 2011.02.01 16:13

Creating a robust trading robot cannot be done without an understanding of the mechanisms of the MetaTrader 5 trading system. The client terminal receives the information about the positions, orders, and deals from the trading server. To handle this data properly using the MQL5, it's necessary to have a good understanding of the interaction between the MQL5-program and the client terminal.
 
Pietroalutto1 #:
// Function to apply the trailing stop with checks for pending orders and freeze level
void ApplyTrailingStop()
{
    // Check if the position is active (not pending)
    if (!PositionSelect(_Symbol)) 
    {
        Print("DEBUG: No active position for the symbol ", _Symbol);
        return;
    }

    // Get the current order ticket (for pending orders)
    ulong ticket = PositionGetInteger(POSITION_TICKET);

...

    // Trailing stop calculation for BUY

...

            // Modify the trailing stop only if the new distance is valid
            if (trade.PositionModify(_Symbol, trailing_stop_price, PositionGetDouble(POSITION_TP)))
...


The "PositionModify" method call you are using is for "netting" accounts, not "hedging" accounts. Which account type are you using?

For "hedging" accounts you should be using the method with a position ticket ...

Modifies position parameters by the specified ticket.

bool  PositionModify(
   const ulong   ticket,     // position ticket
   double        sl,         // Stop Loss price 
   double        tp          // Take Profit price
   )
Documentation on MQL5: Standard Library / Trade Classes / CTrade / PositionModify
Documentation on MQL5: Standard Library / Trade Classes / CTrade / PositionModify
  • www.mql5.com
Modifies the position parameters by specified symbol. Modifies position parameters by the specified ticket. Parameters symbol [in]  Name of...
 
Fernando Carreiro #:


The "PositionModify" method call you are using is for "netting" accounts, not "hedging" accounts. Which account type are you using?

For "hedging" accounts you should be using the method with a position ticket ...

Modifies position parameters by the specified ticket.

thank you for the answer. I use hedging account

I paste the modified code so you can tell me if there are errors:

void ApplyTrailingStop()
  {
  
// Controlla se esiste una posizione attiva per il simbolo
   if(!PositionSelect(_Symbol))
     {
      Print("DEBUG: Nessuna posizione attiva per il simbolo ", _Symbol);
      return;
     }

// Ottieni il ticket della posizione
   ulong ticket = PositionGetInteger(POSITION_TICKET);
   double stop_loss = PositionGetDouble(POSITION_SL);
   double take_profit = PositionGetDouble(POSITION_TP);
   double entry_price = PositionGetDouble(POSITION_PRICE_OPEN);
   long position_type = PositionGetInteger(POSITION_TYPE);

// Ottieni i prezzi di BID e ASK
   double bid_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double ask_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   double stop_level = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * tick_size;
   double freeze_level = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL) * tick_size;

   Print("DEBUG: Prezzo BID: ", bid_price, ", Prezzo ASK: ", ask_price);
   Print("DEBUG: Livello stop: ", stop_level, ", Livello freeze: ", freeze_level);

   double trailing_stop_price = 0.0;

   if(position_type == POSITION_TYPE_BUY)
     {
      trailing_stop_price = bid_price - TrailingStopDistance * tick_size;
      trailing_stop_price = MathRound(trailing_stop_price / tick_size) * tick_size;

      if(trailing_stop_price > stop_loss + stop_level)
        {
         if(trade.PositionModify(ticket, trailing_stop_price, take_profit))  // Modifica con ticket
              {
               Print("DEBUG: Trailing stop SELL aggiornato a: ", trailing_stop_price);
              }

         else
           {
            int error_code = GetLastError();
            Print("DEBUG: Errore aggiornamento trailing stop BUY. Codice errore: ", error_code);
            Print("DEBUG: Descrizione errore: ", GetRetcodeDescription(error_code));
           }
        }
      else
        {
         Print("DEBUG: Il nuovo trailing stop non soddisfa i requisiti.");
        }
     }
   else
      if(position_type == POSITION_TYPE_SELL)
        {
         trailing_stop_price = ask_price + TrailingStopDistance * tick_size;
         trailing_stop_price = MathRound(trailing_stop_price / tick_size) * tick_size;

         if(trailing_stop_price < stop_loss - stop_level)
           {
            if(trade.PositionModify(ticket, trailing_stop_price, take_profit))  // Modifica con ticket
              {
               Print("DEBUG: Trailing stop SELL aggiornato a: ", trailing_stop_price);
              }
            else
              {
               int error_code = GetLastError();
               Print("DEBUG: Errore aggiornamento trailing stop SELL. Codice errore: ", error_code);
               Print("DEBUG: Descrizione errore: ", GetRetcodeDescription(error_code));
              }
           }
         else
           {
            Print("DEBUG: Il nuovo trailing stop non soddisfa i requisiti.");
           }
        }
  }
 
Pietroalutto1 #:thank you for the answer. I use hedging account

Then your entire "ApplyTrailingStop()" logic should be redesigned. It is assuming "netting" or single position, which on a "hedging" account is not the case.

You need to go through all the currently open positions, filtering by Symbol and Magic Number and then applying the trailing stop to each that fits your conditions.

Your EA's logic needs to be redesigned.

 
Fernando Carreiro #:

Then your entire "ApplyTrailingStop()" logic should be redesigned. It is assuming "netting" or single position, which on a "hedging" account is not the case.

You need to go through all the currently open positions, filtering by Symbol and Magic Number and then applying the trailing stop to each that fits your conditions.

Your EA's logic needs to be redesign

or maybe I can change to a netting account

 
Pietroalutto1 #: or maybe I can change to a netting account

No, don't be lazy! Make your code work properly for both types of accounts.

Study how to properly handle the trade functionality on MT5 ...

Articles

Orders, Positions and Deals in MetaTrader 5

MetaQuotes, 2011.02.01 16:13

Creating a robust trading robot cannot be done without an understanding of the mechanisms of the MetaTrader 5 trading system. The client terminal receives the information about the positions, orders, and deals from the trading server. To handle this data properly using the MQL5, it's necessary to have a good understanding of the interaction between the MQL5-program and the client terminal.