Invalid Stop

 

Hello

Can you kindly review my code and advise the cause of the invalid stop error. Please see the code below. Thanks

#property copyright "User"
#property link      ""
#property version   "1.00"
// Include necessary libraries for trading operations and indicators
#include <Trade\Trade.mqh>
#include <Indicators\Oscilators.mqh>
//--- input parameters
input int      ATR_Period      = 14;     // ATR period
input double   ATR_Multiplier  = 2.0;    // Multiplier for ATR stop loss
input double   LotSize         = 0.1;    // Trade volume
input int      MagicNumber     = 12345;  // Magic number to identify trades
//--- Global variables
CTrade         m_trade;                  // Trade object
CiATR          m_atr;                    // ATR indicator object
double         m_atr_value;              // Current ATR value
double         m_support_level;          // Current Support level
double         m_resistance_level;       // Current Resistance level
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    // Initialize the Trade object
    m_trade.SetExpertMagicNumber(MagicNumber);
    
    // Initialize the ATR indicator
    if(!m_atr.Create(_Symbol, _Period, ATR_Period))
    {
        Print("Failed to create ATR indicator, error: ", GetLastError());
        return INIT_FAILED;
    }
    
    return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // Clean up indicator if necessary
    //m_atr.Release();
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    if (PositionsTotal() < 1) // Only open a trade if no position is open
    {
        FindSupportResistance();
        CheckAndOpenTrade();
    }
    else // Manage existing position with trailing stop
    {
        ManageTrailingStop();
    }
}
//+------------------------------------------------------------------+
//| Function to find Support and Resistance levels                   |
//+------------------------------------------------------------------+
void FindSupportResistance()
{
    // A simple method: use the last 50 bars' low for support and high for resistance
    int bars_to_check = 50;
    double high_array[], low_array[];
    
    // Copy High and Low prices to arrays
    if(CopyHigh(_Symbol, _Period, 0, bars_to_check, high_array) > 0 && 
       CopyLow(_Symbol, _Period, 0, bars_to_check, low_array) > 0)
    {
        m_resistance_level = high_array[ArrayMaximum(high_array)];
        m_support_level = low_array[ArrayMinimum(low_array)];
    }
}
//+------------------------------------------------------------------+
//| Function to check conditions and open a trade                    |
//+------------------------------------------------------------------+
void CheckAndOpenTrade()
{
    // Refresh prices
    MqlTick last_tick;
    SymbolInfoTick(_Symbol, last_tick);
    double current_price = last_tick.ask; // Use ask for buy, bid for sell
    // A simple entry logic: Buy if price breaks resistance, Sell if price breaks support
    // (This is a basic example; a real strategy needs more conditions)
    if (current_price > m_resistance_level)
    {
        // Calculate initial stop loss using ATR distance below entry
        m_atr_value = m_atr.Main(0); // Get current ATR value
        double stop_loss_price = current_price - m_atr_value * ATR_Multiplier;
        
        // Ensure stop loss respects broker's minimum distance
        double min_sl_distance = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
        if (current_price - stop_loss_price < min_sl_distance)
        {
            stop_loss_price = current_price - min_sl_distance;
        }
        // Send buy order
        m_trade.Buy(LotSize, _Symbol, last_tick.ask, stop_loss_price, 0, "Buy on Resistance Breakout");
    }
    else if (current_price < m_support_level)
    {
        // Calculate initial stop loss using ATR distance above entry
        m_atr_value = m_atr.Main(0); // Get current ATR value
        double stop_loss_price = current_price + m_atr_value * ATR_Multiplier;
        // Ensure stop loss respects broker's minimum distance
        double min_sl_distance = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
        if (stop_loss_price - current_price < min_sl_distance)
        {
            stop_loss_price = current_price + min_sl_distance;
        }
        // Send sell order
        m_trade.Sell(LotSize, _Symbol, last_tick.bid, stop_loss_price, 0, "Sell on Support Breakout");
    }
}
//+------------------------------------------------------------------+
//| Function to manage the ATR trailing stop loss                    |
//+------------------------------------------------------------------+
void ManageTrailingStop()
{
    PositionSelectByTicket(PositionGetTicket(0)); // Select the first (and in this example, only) position
    
    double current_sl = PositionGetDouble(POSITION_SL);
    double current_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); // Use Ask for long, Bid for short
    ENUM_POSITION_TYPE  pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
    m_atr_value = m_atr.Main(0); // Get the current ATR value
    // Calculate new stop loss level
    double new_sl_level;
    if (pos_type == POSITION_TYPE_BUY)
    {
        current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID); // Use Bid for calculation when managing existing buy position
        new_sl_level = current_price - m_atr_value * ATR_Multiplier;
        // Modify SL only if the new SL is higher (locking in profit/reducing loss) and valid
        if (new_sl_level > current_sl && new_sl_level < current_price)
        {
            // Check broker's minimum distance
            double min_sl_distance = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
            if (current_price - new_sl_level >= min_sl_distance)
            {
               m_trade.PositionModify(PositionGetTicket(0), new_sl_level, PositionGetDouble(POSITION_TP));
            }
        }
    }
    else if (pos_type == POSITION_TYPE_SELL)
    {
        current_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); // Use Ask for calculation when managing existing sell position
        new_sl_level = current_price + m_atr_value * ATR_Multiplier;
        // Modify SL only if the new SL is lower (locking in profit/reducing loss) and valid
        if (new_sl_level < current_sl && new_sl_level > current_price)
        {
             // Check broker's minimum distance
            double min_sl_distance = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
            if (new_sl_level - current_price >= min_sl_distance)
            {
               m_trade.PositionModify(PositionGetTicket(0), new_sl_level, PositionGetDouble(POSITION_TP));
            }
        }
    }
}
 
Tshepo Nkosi:

Hello

Can you kindly review my code and advise the cause of the invalid stop error. Please see the code below. Thanks

You should always normalize a price to your given digits specificity before you send it in an order.

Also, some broker-dealers require SL's and TP's to be sent as position modifications--meaning they can't be sent within the entry order. Research your broker-dealer.

Documentation on MQL5: NormalizeDouble / Conversion Functions
Documentation on MQL5: NormalizeDouble / Conversion Functions
  • www.mql5.com
Rounding floating point number to a specified accuracy. Parameters value [in] Value with a floating point. digits [in]  Accuracy format...
[Deleted]  
Tshepo NkosiCan you kindly review my code and advise the cause of the invalid stop error. Please see the code below. Thanks

Please read and apply the following in your EA (even if it is not for a Market product):

Articles

The checks a trading robot must pass before publication in the Market

MetaQuotes, 2016.08.01 09:30

Before any product is published in the Market, it must undergo compulsory preliminary checks in order to ensure a uniform quality standard. This article considers the most frequent errors made by developers in their technical indicators and trading robots. An also shows how to self-test a product before sending it to the Market.