This is a mystery to me!

 

I have written a small EA and when testing I get the infamous ordersend error 130: invalid stops message. 

3 14:49:36.262 2018.12.19 09:29:25  SpikeScalper GBPUSD,M1: OrderSend error 130

0 14:49:36.262 2018.12.19 09:29:25  SpikeScalper GBPUSD,M1: Alert: Open Sell Order - Error 130: invalid stops

0 14:49:36.262 2018.12.19 09:29:25  SpikeScalper GBPUSD,M1:  Lots: 0 Price: 1.26576 Stop: 30 Profit: 90

3 14:49:36.262 2018.12.19 09:29:26  SpikeScalper GBPUSD,M1: OrderSend error 130

0 14:49:36.262 2018.12.19 09:29:26  SpikeScalper GBPUSD,M1: Alert: Open Buy Order - Error 130: invalid stops

0 14:49:36.262 2018.12.19 09:29:26  SpikeScalper GBPUSD,M1:  Lots: 0 Price: 1.26587 Stop: 30 Profit: 90

As you can see the error message reports the SL and TP as points and not prices. 

But that cannot be since i convert the SL and TP to price levels as you can see in the attached code.

The other thing that is strange the print message for the SL and TP is not reported in the journal (as can be seen above in the extract from the journal).

Can anybody tell me why this is happening?

   RefreshRates();
   
       BuyStopLoss = Ask - (StopLoss * UsePoint);
       BuyTakeProfit = Ask + (TakeProfit * UsePoint);

       SellStopLoss = Bid + (StopLoss * UsePoint);
       SellTakeProfit = Bid - (TakeProfit * UsePoint);  
       
        
      Print("BuyStopLoss is ", BuyStopLoss, " SellStopLoss is ", SellStopLoss);

 
 
Ernest Klokow:


RefreshRates();
   
       BuyStopLoss =NormalizeDouble((Ask - StopLoss * UsePoint),Digits);
       BuyTakeProfit = NormalizeDouble((Ask + TakeProfit * UsePoint),Digits);

       SellStopLoss = NormalizeDouble((Bid + StopLoss * UsePoint),Digits);
       SellTakeProfit = NormalizeDouble((Bid - TakeProfit * UsePoint),Digits);
       
        
      Print("BuyStopLoss is ", BuyStopLoss, " SellStopLoss is ", SellStopLoss);


 

Thank you so much everybody for your help and advice.

It is greatly appreciated!

 
Ernest Klokow:

I have written a small EA and when testing I get the infamous ordersend error 130: invalid stops message. 

3 14:49:36.262 2018.12.19 09:29:25  SpikeScalper GBPUSD,M1: OrderSend error 130

0 14:49:36.262 2018.12.19 09:29:25  SpikeScalper GBPUSD,M1: Alert: Open Sell Order - Error 130: invalid stops

0 14:49:36.262 2018.12.19 09:29:25  SpikeScalper GBPUSD,M1:  Lots: 0 Price: 1.26576 Stop: 30 Profit: 90

3 14:49:36.262 2018.12.19 09:29:26  SpikeScalper GBPUSD,M1: OrderSend error 130

0 14:49:36.262 2018.12.19 09:29:26  SpikeScalper GBPUSD,M1: Alert: Open Buy Order - Error 130: invalid stops

0 14:49:36.262 2018.12.19 09:29:26  SpikeScalper GBPUSD,M1:  Lots: 0 Price: 1.26587 Stop: 30 Profit: 90

As you can see the error message reports the SL and TP as points and not prices. 

But that cannot be since i convert the SL and TP to price levels as you can see in the attached code.

The other thing that is strange the print message for the SL and TP is not reported in the journal (as can be seen above in the extract from the journal).

Can anybody tell me why this is happening?


Try this code.... And check your broker's stop level. Need stop loss and take profit are equal or higher from stop level!!!

Always uses Ask+... and Bid-... not Ask-... or Bid+.... to set levels. Because Ask is higher from Bid price on all pairs.

       if(StopLoss < MarketInfo(Symbol(),MODE_STOPLEVEL)) StopLoss = MarketInfo(Symbol(),MODE_STOPLEVEL);
       if(TakeProfit < MarketInfo(Symbol(),MODE_STOPLEVEL)) TakeProfit = MarketInfo(Symbol(),MODE_STOPLEVEL);
        

       BuyStopLoss = Bid - (StopLoss * Point);
       BuyTakeProfit = Ask + (TakeProfit * Point);

       SellStopLoss = Ask + (StopLoss * Point);
       SellTakeProfit = Bid - (TakeProfit * Point);  
 
Nikolaos Pantzos:

Try this code.... And check your broker's stop level. Need stop loss and take profit are equal or higher from stop level!!!

Always uses Ask+... and Bid-... not Ask-... or Bid+.... to set levels. Because Ask is higher from Bid price on all pairs.

You're mostly right and also whorder's mostly right... Combine the advice and you have a full working solution. 

#define roundIt(NUMBER ,STEP, FUNC) (FUNC((NUMBER) / (STEP)) * (STEP))

bool getValidStoploss(double &result, const int order_type, int sl_points, double entry_price=WRONG_VALUE)
{
   int min_points = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
   sl_points = sl_points < min_points ? min_points : sl_points;
   double tick_step = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   switch (order_type) {
      case OP_BUY:
         if (entry_price == WRONG_VALUE)
            entry_price = Ask;
      case OP_BUYLIMIT:
      case OP_BUYSTOP:
         if (entry_price == WRONG_VALUE)
            return false;
         double new_sl = roundIt(entry_price - sl_points * _Point, tick_step, round);
         if (entry_price - new_sl < min_points * _Point)
            result = roundIt(entry_price - sl_points * _Point, tick_step, floor);
         else
            result = new_sl;
         return true;
      case OP_SELL:
         if (entry_price == WRONG_VALUE)
            entry_price = Bid;
      case OP_SELLLIMIT:
      case OP_SELLSTOP:
         if (entry_price == WRONG_VALUE) 
            return false;
         new_sl = roundIt(entry_price + sl_points * _Point, tick_step, round);
         if (new_sl - entry_price < min_points * _Point) 
            result = roundIt(entry_price + sl_points * _Point, tick_step, ceil);
         else
            result = new_sl;
         return true;    
   }
   return false;
}

void OnStart()
{
   int stoploss_points = 1;
   double sl_result;
   if (getValidStoploss(sl_result, OP_SELL, stoploss_points))
      Print(Bid, "->", sl_result);
}
 
nicholi shen:

You're mostly right and also whorder's mostly right... Combine the advice and you have a full working solution. 

Hey Nicholi,

Could you kindly explain this syntax? :-

#define roundIt(NUMBER ,STEP, FUNC) (FUNC((NUMBER) / (STEP)) * (STEP))

It looks like you have defined some kind of funky anonymous function! :)


Cheers and thanks.

 
Geester:

Hey Nicholi,

Could you kindly explain this syntax? :-

It looks like you have defined some kind of funky anonymous function! :)


Cheers and thanks.

Defining the MACRO this way allows for dependency injection. In other words, it allows you to pass a function as an argument. In this example, the FUNC arg takes any function with one parameter (can have more than one as long as default args are defined for the remaining) and returns a number. You can see more examples in the CAppDialog class. 

This of course is not really a function so when you see

double x = roundIt(entry_price + sl_points * _Point, tick_step, ceil);

it's really being replaced by the compiler as

double x = (ceil((entry_price + sl_points * _Point) / tick_step) * tick_step);
 
nicholi shen:

Defining the MACRO this way allows for dependency injection. In other words, it allows you to pass a function as an argument. In this example, the FUNC arg takes any function with one parameter (can have more than one as long as default args are defined for the remaining) and returns a number. You can see more examples in the CAppDialog class. 

This of course is not really a function so when you see

it's really being replaced by the compiler as

Thanks, Nicholi, that's awesome!  - I had no idea you could do this sort of thing in MQL :)

 
nicholi shen:

Defining the MACRO this way allows for dependency injection. In other words, it allows you to pass a function as an argument. In this example, the FUNC arg takes any function with one parameter (can have more than one as long as default args are defined for the remaining) and returns a number. You can see more examples in the CAppDialog class. 

This of course is not really a function so when you see

it's really being replaced by the compiler as

Just one last question, what is a "tick_step"? I see this in your CDouble class and don't really understand the concept of the "step" aspect? 

Cheers and thanks! :)

Reason: