Invalid Stops

To add comments, please log in or register
Sicco
47
Sicco  

Hello, I'm trying to figure out what the cause of the error "Invalid Stops" is inside my EA.

I have been reading this forum and googling around for days but have not found the solution yet, hence I'm creating a topic here.


So, In my EA I'm getting this error when opening an order and modifying an order, probably only once per 50 times.

I will show you the code and the printed results from the code:

input int TakeProfit                    = 50;
input int StopLoss                      = 5;
input int DealDistance                  = 5;
input int Maximum_Slippage              = 1;
input int MagicNumber                   = 1;

//****************************************************************************//
void Blabla()
{
        RefreshRates();
        double Sell_OpenPrice   = Bid - (DealDistance * Point);
        double Sell_TakeProfit  = NULL;
        double Sell_StopLoss    = NULL;

        double Lotsize                  = CalculateLotSize();

        if(TakeProfit > 0)
                Sell_TakeProfit = Sell_OpenPrice - (TakeProfit * Point);
        if(StopLoss > 0)
                Sell_StopLoss   = Sell_OpenPrice + (StopLoss * Point);

        if(OrderSend(Symbol(), OP_SELLSTOP,     Lotsize, Sell_OpenPrice,        Maximum_Slippage, Sell_StopLoss,        Sell_TakeProfit,        NULL, MagicNumber, 0) == -1)
        {
                Print("XXXXXXXXXX Error: ", ErrorDescription(GetLastError()));
                Print("XXXXXXXXXX: Tried to open a SellStop Order, values:.....");
                Print("XXXXXXXXXX: Lotsize: " + Lotsize);
                Print("XXXXXXXXXX: Sell_OpenPrice: " + Sell_OpenPrice);
                Print("XXXXXXXXXX: Sell_StopLoss: " + Sell_StopLoss);
                Print("XXXXXXXXXX: Sell_TakeProfit: " + Sell_TakeProfit);
                Print("XXXXXXXXXX: Ask: " + Ask);
                Print("XXXXXXXXXX: Bid: " + Bid);
                Print("XXXXXXXXXX: StopLevel: " + MarketInfo(Symbol(), MODE_STOPLEVEL));
                Print("XXXXXXXXXX: FreezeLevel: " + MarketInfo(Symbol(), MODE_FREEZELEVEL));
        }
}

InvalidStops Print


As you can see, all the printed values seem fine, so.... I'm clueless.

Keith Watford
Moderator
20380
Keith Watford  
Sicco:

As you can see, all the printed values seem fine, so.... I'm clueless.

They are not fine.

Apart from placing trades with ridiculously small stops......

Entry price is 1.28641

SL is 1.28646

Ask is 1.28647

So Ask is already above your SL level.

Sicco
47
Sicco  
Keith Watford:

They are not fine.

Apart from placing trades with ridiculously small stops......

Entry price is 1.28641

SL is 1.28646

Ask is 1.28647

So Ask is already above your SL level.

It's a SellStop order, so it does not matter if the current Ask price is above SL.

Fabio Cavalloni
3778
Fabio Cavalloni  

You need to always normalize values before use them in OrderSend or OrderModify functions.

And you need to be always sure that stops are valid for order type that you are sending.

Buy orders: SL always below order price and TP always above order price

Sell orders: SL always above order price and TP always below order price.


You need also to check STOP_LEVELS of your broker and be sure that any order you sent meet these requirements.

Keith Watford
Moderator
20380
Keith Watford  
Sicco:

It's a SellStop order, so it does not matter if the current Ask price is above SL.

OK, you got me there. I wasn't thinking.

It is probably what Fabio says.

Sicco
47
Sicco  

Guys, I appreciate the fact that you are trying to help, but didn't you see the printed values?

Invalid Stops

STOP_LEVELS = 0,

SL is above open price, TP is below open price.

Normalize values? Look at all the values, they all have the correct amount of digits.

Fabio Cavalloni
3778
Fabio Cavalloni  

I can't see any NormalizeDouble command in your code.

You are assuming that values are normalized because when you print them you see them normalized, but it's not true.

Use NormalizeDouble function.


if(TakeProfit > 0)
                Sell_TakeProfit = Sell_OpenPrice - (TakeProfit * Point);
        if(StopLoss > 0)
                Sell_StopLoss   = Sell_OpenPrice + (StopLoss * Point);

        if(OrderSend(Symbol(), OP_SELLSTOP,     Lotsize, NormalizeDouble(Sell_OpenPrice,Digits),Maximum_Slippage, NormalizeDouble(Sell_StopLoss,Digits),NormalizeDouble(Sell_TakeProfit,Digits),NULL, MagicNumber, 0) == -1)
Sicco
47
Sicco  
Fabio Cavalloni:

I can't see any NormalizeDouble command in your code.

You are assuming that values are normalized because when you print them you see them normalized, but it's not true.

Use NormalizeDouble function.


Aha... so the printed values aren't representing the real value....


Alright, I shall run the EA again with NormalizeDouble at each OpenPrice, StopLoss and TakeProfit and see if the error still occurs.


One thing I noticed when browsing through this forum is that the function NormalizeDouble is said to be a bad function and should not be used.

I'm not sure what to believe in this, I shall run my test now anyways and see if it makes a difference.

William Roeder
20208
William Roeder  
  1. You buy at the Ask and sell at the Bid. So for buy orders you pay the spread on open. For sell orders you pay the spread on close.
    1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid reaches it. Not the Ask. Your SL is shorter by the spread and your TP is longer. Don't you want the same/specified amount for either direction?
    2. Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask reaches it. To trigger at a specific Bid price, add the average spread.
                MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25
    3. The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools → Options (Control-O) → charts → Show ask line.)

  2. Your 5 point stop loss is smaller than the spread + the minimum. You can't move stops (or pending prices) closer to the market than the minimum: MODE_STOPLEVEL * _Point or SymbolInfoInteger(SYMBOL_TRADE_STOPS_LEVEL).
              Requirements and Limitations in Making Trades - Appendixes - MQL4 Tutorial

Sicco
47
Sicco  
Fabio Cavalloni:

I can't see any NormalizeDouble command in your code.

You are assuming that values are normalized because when you print them you see them normalized, but it's not true.

Use NormalizeDouble function.


After testing I can conclude that NormalizeDouble did not fix the issue.

The only change I noticed was that it would display a value like 1.11000 as 1.11.

William Roeder:
  1. You buy at the Ask and sell at the Bid. So for buy orders you pay the spread on open. For sell orders you pay the spread on close.
    1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid reaches it. Not the Ask. Your SL is shorter by the spread and your TP is longer. Don't you want the same/specified amount for either direction?
    2. Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask reaches it. To trigger at a specific Bid price, add the average spread.
                MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25
    3. The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools → Options (Control-O) → charts → Show ask line.)

  2. Your 5 point stop loss is smaller than the spread + the minimum. You can't move stops (or pending prices) closer to the market than the minimum: MODE_STOPLEVEL * _Point or SymbolInfoInteger(SYMBOL_TRADE_STOPS_LEVEL).
              Requirements and Limitations in Making Trades - Appendixes - MQL4 Tutorial

I understand everything that you say here.

Although the error should be related to something else, because if you look at the printed values...

MODE_STOPLEVEL = 0

Spread = 1


So how would a SellStop with a 5 point StopLoss not be possible?

Keith Watford
Moderator
20380
Keith Watford  

From the documentation....

A zero value of MODE_STOPLEVEL means either absence of any restrictions on the minimal distance for Stop Loss/Take Profit or the fact that a trade server utilizes some external mechanisms for dynamic level control, which cannot be translated in the client terminal. In the second case, GetLastError() can return error 130, because MODE_STOPLEVEL is actually "floating" here.

12
To add comments, please log in or register