Trailing stop---invalid request - page 3

 
Fernando Carreiro #:

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 ...

ok thank you so much and you think that I have to redesign only the trailing stop or all the code logic in order to the hedge account?

 
Pietroalutto1 #: ok thank you so much and you think that I have to redesign only the trailing stop or all the code logic in order to the hedge account?

We did not see all your code so I don't know. You will have to study the article suggested and then analyse and debug your own code.

 
Fernando Carreiro #: We did not see all your code so I don't know. You will have to study the article suggested and then analyse and debug your own code.

When you have some time, could you please check if the trailing stop logic in my code is correct? In the strategy tester, I always get the same error, and I’m not sure if I’m missing something. I’ve also added the logic inside the  OnTick  function, so if you have time, I’d really appreciate it if you could have a look at that too.

Thanks a lot!

void ApplyTrailingStop()
{
    double trailingStopDistance = 200;  // Example distance in pips (you can adjust this)
    double stop_level = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
    double freeze_level = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL) * SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
    double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);

    Print("DEBUG: Trailing stop distance (pips): ", trailingStopDistance);
    Print("DEBUG: Stop level: ", stop_level, ", Freeze level: ", freeze_level);
    Print("DEBUG: Tick size: ", tick_size);

    // Loop through all open positions
    int totalPositions = PositionsTotal();
    Print("DEBUG: Number of open positions: ", totalPositions);

    for (int i = totalPositions - 1; i >= 0; i--)
    {
        // Retrieve the symbol of the position
        if (!PositionSelect(_Symbol))  // Select position by symbol
        {
            Print("DEBUG: Error selecting position with symbol: ", _Symbol);
            continue;  // Skip this iteration if no position is selected
        }

        // Retrieve position details
        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);

        double bid_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
        double ask_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

        Print("DEBUG: Position ", i + 1, " selected.");
        Print("DEBUG: Ticket: ", ticket, ", Position type: ", position_type);
        Print("DEBUG: Entry price: ", entry_price, ", Stop loss: ", stop_loss, ", Take profit: ", take_profit);
        Print("DEBUG: BID price: ", bid_price, ", ASK price: ", ask_price);

        double trailing_stop_price = 0.0;

        if (position_type == POSITION_TYPE_BUY)
        {
            // Calculate the trailing stop for BUY position
            Print("DEBUG: Calculating trailing stop for BUY...");
            Print("DEBUG: BID price: ", bid_price, ", Trailing stop distance: ", trailingStopDistance, ", Tick size: ", tick_size);

            trailing_stop_price = bid_price - trailingStopDistance * tick_size;
            Print("DEBUG: Trailing stop before normalization: ", trailing_stop_price);

            // Normalize trailing stop to the nearest tick
            trailing_stop_price = MathRound(trailing_stop_price / tick_size) * tick_size;
            Print("DEBUG: Trailing stop after normalization: ", trailing_stop_price);

            // Ensure the trailing stop is greater than the current stop loss plus the stop level
            if (trailing_stop_price > stop_loss + stop_level)
            {
                Print("DEBUG: Trailing stop BUY is greater than the current stop loss, proceeding with modification.");

                if (trade.PositionModify(ticket, trailing_stop_price, take_profit))  // Modify with ticket
                {
                    Print("DEBUG: Trailing stop BUY updated to: ", trailing_stop_price);
                }
                else
                {
                    int error_code = GetLastError();
                    Print("DEBUG: Error updating trailing stop BUY. Error code: ", error_code);
                    Print("DEBUG: Error description: ", GetRetcodeDescription(error_code));
                }
            }
            else
            {
                Print("DEBUG: The new trailing stop for BUY does not meet the requirements (less than the current stop loss).");
            }
        }
        else if (position_type == POSITION_TYPE_SELL)
        {
            // Calculate the trailing stop for SELL position
            Print("DEBUG: Calculating trailing stop for SELL...");
            Print("DEBUG: ASK price: ", ask_price, ", Trailing stop distance: ", trailingStopDistance, ", Tick size: ", tick_size);

            trailing_stop_price = ask_price + trailingStopDistance * tick_size;
            Print("DEBUG: Trailing stop before normalization: ", trailing_stop_price);

            // Normalize trailing stop to the nearest tick
            trailing_stop_price = MathRound(trailing_stop_price / tick_size) * tick_size;
            Print("DEBUG: Trailing stop after normalization: ", trailing_stop_price);

            // Ensure the trailing stop is less than the current stop loss minus the stop level
            if (trailing_stop_price < stop_loss - stop_level)
            {
                Print("DEBUG: Trailing stop SELL is less than the current stop loss, proceeding with modification.");

                if (trade.PositionModify(ticket, trailing_stop_price, take_profit))  // Modify with ticket
                {
                    Print("DEBUG: Trailing stop SELL updated to: ", trailing_stop_price);
                }
                else
                {
                    int error_code = GetLastError();
                    Print("DEBUG: Error updating trailing stop SELL. Error code: ", error_code);
                    Print("DEBUG: Error description: ", GetRetcodeDescription(error_code));
                }
            }
            else
            {
                Print("DEBUG: The new trailing stop for SELL does not meet the requirements (greater than the current stop loss).");
            }
        }
    }
}

// OnTick function
void OnTick()
{
    // Get indicator values
    double rsi_value = GetRSIValue();
    GetMACDValue();
    GetADXValue();
    GetBollingerBands();

    // Retrieve the current price based on order type
    double current_price = 0;

    // If the order is BUY, use the Ask price, otherwise the Bid price for SELL
    if (rsi_value < RSI_Oversold && adx_value > ADX_Threshold && SymbolInfoDouble(_Symbol, SYMBOL_ASK) < lower_band)
    {
        current_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);  // Ask price for BUY

        Print("DEBUG: BUY condition satisfied (RSI < RSI_Oversold: ", rsi_value < RSI_Oversold,
              ", MACD Main > MACD Signal: ", macd_main > macd_signal,
              ", ADX > ADX Threshold: ", adx_value > ADX_Threshold,
              ", BID price < Lower Band: ", SymbolInfoDouble(_Symbol, SYMBOL_ASK),
              ", ASK price: ", current_price, ")");
    }
    else if (rsi_value > RSI_Overbought && adx_value > ADX_Threshold && SymbolInfoDouble(_Symbol, SYMBOL_BID) > upper_band)
    {
        current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);  // Bid price for SELL

        Print("DEBUG: SELL condition satisfied (RSI > RSI_Overbought: ", rsi_value > RSI_Overbought,
              ", MACD Main < MACD Signal: ", macd_main < macd_signal,
              ", ADX > ADX Threshold: ", adx_value > ADX_Threshold,
              ", BID price > Upper Band: ", SymbolInfoDouble(_Symbol, SYMBOL_BID),
              ", BID price: ", current_price, ")");
    }
    else
    {
        // Add debug for when neither BUY nor SELL conditions are met
        Print("DEBUG: No conditions met for order opening.");
        return;
    }

    // Check if there is already an open position for the same symbol
    if (!PositionSelect(_Symbol))
    {
        // Conditions are met, now open the order
        if (rsi_value < RSI_Oversold && adx_value > ADX_Threshold && SymbolInfoDouble(_Symbol, SYMBOL_ASK) < lower_band)
        {
            Print("Conditions met for BUY. RSI: ", rsi_value, ", MACD: ", macd_main,
                  ", ADX: ", adx_value, ", Price: ", current_price);
            OpenTrade(ORDER_TYPE_BUY);
        }
        else if (rsi_value > RSI_Overbought && adx_value > ADX_Threshold && SymbolInfoDouble(_Symbol, SYMBOL_BID) > upper_band)
        {
            Print("Conditions met for SELL. RSI: ", rsi_value, ", MACD: ", macd_main,
                  ", ADX: ", adx_value, ", Price: ", current_price);
            OpenTrade(ORDER_TYPE_SELL);
        }
    }
    else
    {
        Print("There is already an open position for the symbol: ", _Symbol);
    }

    Print("Calling the ApplyTrailingStop() function");  // Debug before the call
    ApplyTrailingStop();
}
 
Pietroalutto1 #:

When you have some time, could you please check if the trailing stop logic in my code is correct?

SYMBOL_TRADE_STOPS_LEVEL and SYMBOL_TRADE_FREEZE_LEVEL are int's. Defining them as double's without typecasting might be causing issues.

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 #:
SYMBOL_TRADE_STOPS_LEVEL is an int.

So I have to change it?

 
Pietroalutto1 #:

So I have to change it?

I haven't debugged your code but as a matter of good practice, I always typecast when defining a double by an int.

    double stop_level = double(SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));
    double freeze_level = double(SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL) * SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));

EDIT: Fernando did a deep dive into how to process this as an int in another thread:

Tick size vs Point(), can be a little tricky in Multicurrency EA - Currency Pairs - Expert Advisors and Automated Trading - MQL5 programming forum
Tick size vs Point(), can be a little tricky in Multicurrency EA - How to calculate stoplosses and takeprofits when dealing with multiple currencies
Tick size vs Point(), can be a little tricky in Multicurrency EA - How to calculate stoplosses and takeprofits when dealing with multiple currencies
  • 2022.03.09
  • Omega J Msigwa
  • www.mql5.com
Is the same as point()  for a specific symbol,100% though i'm not sure why they are being called and defined as different things on the docs, but the point i'm trying to make is that using point()   to calculate stoplosses and takeprofits could lead to inaccurate results when dealing with multicurrency ea's that work on different symbols and instruments. Forum on trading, automated trading systems and testing trading strategies
 
Pietroalutto1 #:
    for (int i = totalPositions - 1; i >= 0; i--)
    {
        // Retrieve the symbol of the position
        if (!PositionSelect(_Symbol))  // Select position by symbol

What did I state about "netting" and "hedging" accounts?

PositionGetSymbol

Returns the symbol corresponding to the open position

PositionSelect

Chooses an open position for further working with it

What did I recommend (multiple times) you should read and study? ... Orders, Positions and Deals in MetaTrader 5

Why do you refuse to do the necessary research and due diligence?

Orders, Positions and Deals in MetaTrader 5
Orders, Positions and Deals in MetaTrader 5
  • www.mql5.com
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.