failed market buy 0.18 BTCUSD sl: 17498.47 tp: 16756.34 [Invalid stops]
But besides the obvious error above, you should also always normalise prices based on tick size. Don't use the "NormalizeDouble". Also verify your Stops Level too.
Forum on trading, automated trading systems and testing trading strategies
Tick size vs Point(), can be a little tricky in Multicurrency EA
Fernando Carreiro, 2022.03.09 12:11
Tick Size and Point Size can be very different especially on stocks and other symbols besides forex.
Always use Tick Size to adjust and align your prices, not the point size. In essence, make sure that your price quotes, are properly aligned to the Tick size (see following examples).
... double tickSize = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE ); ... double normalised_price = round( price / tick_size ) * tick_size; ... // Or use a function double Round2Ticksize( double price ) { double tick_size = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE ); return( round( price / tick_size ) * tick_size ); };
Forum on trading, automated trading systems and testing trading strategies
Lorentzos Roussos, 2023.01.02 18:52
You can see it programmatically (if the broker has set it) with this script
#property strict //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { int sylimit=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL); int milimit=(int)MarketInfo(_Symbol,MODE_STOPLEVEL); int limit=MathMax(sylimit,milimit); Comment("Limit in points "+IntegerToString(limit)); } //+------------------------------------------------------------------+
SYMBOL_TRADE_STOPS_LEVEL
Minimal indention in points from the current close price to place Stop orders
int
StopLevel Minimum Distance Limitation.
A trade operation will not be performed if any of the following conditions is disrupted.
Order Type
Open Price StopLoss (SL) TakeProfit (TP) BuyModification is prohibited Bid-SL ≥ StopLevel TP-Bid ≥ StopLevel SellModification is prohibited SL-Ask ≥ StopLevel Ask-TP ≥ StopLevel BuyLimitAsk-OpenPrice ≥ StopLevel OpenPrice-SL ≥ StopLevel TP-OpenPrice ≥ StopLevel SellLimitOpenPrice-Bid ≥ StopLevel SL-OpenPrice ≥StopLevel OpenPrice-TP ≥ StopLevel BuyStopOpenPrice-Ask ≥ StopLevel OpenPrice-SL ≥ StopLevel TP-OpenPrice ≥ StopLevel SellStopBid-OpenPrice ≥ StopLevel SL-OpenPrice ≥ StopLevel OpenPrice-TP ≥ StopLevel
FreezeLevel Limitation (Freezing Distance).
Market orders can not be closed if the StopLoss and TakeProfit values violate the FreezLevel parameter requirements.
StopLoss or TakeProfit orders can not be modified if StopLoss or TakeProfit values violate the StopLevel parameter requirements.
Pending orders can not be deleted or modified if the declared open price violates the FreezeLevel parameter requirements.
Order Type
Open Price StopLoss (SL) TakeProfit (TP) BuyModification is prohibited Bid-SL > FreezeLevel TP-Bid > FreezeLevel SellModification is prohibited SL-Ask > FreezeLevel Ask-TP > FreezeLevel BuyLimitAsk-OpenPrice > FreezeLevel Regulated by the StopLevel parameter Regulated by the StopLevel parameter SellLimitOpenPrice-Bid > FreezeLevel Regulated by the StopLevel parameter Regulated by the StopLevel parameter BuyStopOpenPrice-Ask > FreezeLevel Regulated by the StopLevel parameter Regulated by the StopLevel parameter SellStopBid-OpenPrice > FreezeLevel Regulated by the StopLevel parameter Regulated by the StopLevel parameter
You T/P is below your S/L. That is incorrect. For a buy, your T/P should be above the open price and your S/L below your open price. Not the other way round.
Indeed, I didn't even notice that, but I don't see how this value can be like that. For this simple EA, I just took the EMA300 for SL and the EMA100 for TP and before that I checked that the EMA100 is indeed greater than the EMA300.
I go through some other error in the rapport, and here is another one :
2023.01.26 18:07:49.394 Core 01 2022.12.05 17:08:40 failed market buy 1.71 BTCUSD sl: 17047.18 tp: 17169.85 [Invalid stops]
2023.01.26 18:07:49.394 Core 01 2022.12.05 17:08:40 CTrade::OrderSend: market buy 1.71 BTCUSD sl: 17047.18 tp: 17169.85 [invalid stops]
2023.01.26 18:07:49.394 Core 01 2022.12.05 17:09:40 failed market buy 1.71 BTCUSD sl: 17039.98 tp: 17162.56 [Invalid stops]
2023.01.26 18:07:49.394 Core 01 2022.12.05 17:09:40 CTrade::OrderSend: market buy 1.71 BTCUSD sl: 17039.98 tp: 17162.56 [invalid stops]
2023.01.26 18:07:49.394 Core 01 2022.12.05 17:10:40 market buy 1.71 BTCUSD sl: 17019.86 tp: 17139.36 (17085.03 / 17094.03 / 17085.03)
2023.01.26 18:07:49.394 Core 01 2022.12.05 17:10:40 deal #10 buy 1.71 BTCUSD at 17094.03 done (based on order #12)
2023.01.26 18:07:49.394 Core 01 2022.12.05 17:10:40 deal performed [#10 buy 1.71 BTCUSD at 17094.03]
2023.01.26 18:07:49.394 Core 01 2022.12.05 17:10:40 order performed buy 1.71 at 17094.03 [#12 buy 1.71 BTCUSD at 17094.03]
2023.01.26 18:07:49.394 Core 01 2022.12.05 17:10:40 CTrade::OrderSend: market buy 1.71 BTCUSD sl: 17019.86 tp: 17139.36 [done at 17094.03]
The EA tried 2 time to pass a trade, it failed because invalid stops, and on the third time the order pass. But all the value are similar between all the three attempt...
But that is not what is happening. You also don't mention checking where the current price is at in relation to the moving averages. So, you will need to fix the logic of your code.
But that is not what is happening. You also don't mention checking where the current price is at in relation to the moving averages. So, you will need to fix the logic of your code.
Here is the code so far :
I check if it's an uptrend or downtrend (from ema100, 200 and 300), then check if theses ema are not too close from each other, then if the price hit the ema200, I enter a trade with the ema300 as SL and the ema100 as TP.
Just want to practice code logic here, but obviously I miss a bunch of things…
I changed the code for open a trade, in order to get the retcode : 10013 is it now.
if(EMA100M5DataTable[0] > EMA200M5DataTable[0] && EMA200M5DataTable[0] > EMA300M5DataTable[0]) // Uptrend { if((EMA100M5DataTable[0]-EMA200M5DataTable[0])/EMA200M5DataTable[0] > 0.0025 && (EMA200M5DataTable[0]-EMA300M5DataTable[0])/EMA200M5DataTable[0] > 0.0025 && (EMA100M5DataTable[0]-EMA200M5DataTable[0])/EMA200M5DataTable[0] > (EMA200M5DataTable[0]-EMA300M5DataTable[0])/EMA200M5DataTable[0]) // No range { if(currentAsk < EMA200M5DataTable[0] && currentAsk > EMA200M5DataTable[0]*0.9995) // Price hit EMA200 in a uptrend { if(PositionSelect(_Symbol) == false) // Don't have an open position { StopLoseUSD = NormalizeDouble(EMA300M5DataTable[0],Digits()); // Stop Lose price StopLosePer = (currentAsk-EMA300M5DataTable[0])/currentAsk; // Stop Lose % TakeProfitUSD = NormalizeDouble(EMA100M5DataTable[0],Digits()); // Take Profit price Size = capital*leviermax/currentAsk; // Size of the position with full leverage SizeMax = (dailylossmax*0.475)/StopLosePer/currentAsk; // Size max of the position (risk management) if(SizeMax <= Size) { SizeReel = NormalizeDouble(SizeMax,Digits()); // Size of the position cut to 2 decimals } else { SizeReel = NormalizeDouble(Size,Digits()); // Size of the position cut to 2 decimals } //myTradingControlPanel.PositionOpen(_Symbol,ORDER_TYPE_BUY,SizeReel,currentAsk,StopLoseUSD,TakeProfitUSD,"Long hit 200EMA"); // Open Position MqlTradeRequest request; request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = SizeReel; request.type = ORDER_TYPE_BUY; request.type_filling = ORDER_FILLING_FOK; request.price = currentAsk; request.sl = StopLoseUSD; request.tp = TakeProfitUSD; MqlTradeResult result; myTradingControlPanel.OrderSend(request,result); Print(result.retcode); } } } } if(EMA100M5DataTable[0] < EMA200M5DataTable[0] && EMA200M5DataTable[0] < EMA300M5DataTable[0]) // Downtrend { if((EMA200M5DataTable[0]-EMA100M5DataTable[0])/EMA200M5DataTable[0] > 0.0025 && (EMA300M5DataTable[0]-EMA200M5DataTable[0])/EMA200M5DataTable[0] > 0.0025 && (EMA200M5DataTable[0]-EMA100M5DataTable[0])/EMA200M5DataTable[0] > (EMA300M5DataTable[0]-EMA200M5DataTable[0])/EMA200M5DataTable[0]) // No range { if(currentBid > EMA200M5DataTable[0] && currentBid < EMA200M5DataTable[0]*1.0005) // Price hit EMA200 in a downtrend { if(PositionSelect(_Symbol) == false) // Don't have an open position { StopLoseUSD = NormalizeDouble(EMA300M5DataTable[0],Digits()); // Stop Lose price StopLosePer = -(currentBid-EMA300M5DataTable[0])/currentBid; // Stop Lose % TakeProfitUSD = NormalizeDouble(EMA100M5DataTable[0],Digits()); // Take Profit price Size = capital*leviermax/currentBid; // Size of the position with full leverage SizeMax = (dailylossmax*0.475)/StopLosePer/currentBid; // Size max of the position (risk management) if(SizeMax <= Size) { SizeReel = NormalizeDouble(SizeMax,Digits()); // Size of the position cut to 2 decimals } else { SizeReel = NormalizeDouble(Size,Digits()); // Size of the position cut to 2 decimals } //myTradingControlPanel.PositionOpen(_Symbol,ORDER_TYPE_BUY,SizeReel,currentBid,StopLoseUSD,TakeProfitUSD,"Short hit 200EMA"); // Open Position MqlTradeRequest request; request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = SizeReel; request.type = ORDER_TYPE_SELL; request.type_filling = ORDER_FILLING_FOK; request.price = currentBid; request.sl = StopLoseUSD; request.tp = TakeProfitUSD; MqlTradeResult result; myTradingControlPanel.OrderSend(request,result); Print(result.retcode); } } } }
StopLosePer = (currentAsk-EMA300M5DataTable[0])/currentAsk; // Stop Lose %
You buy at the Ask and sell at the Bid. Pending Buy Stop orders become market orders when hit by the Ask.
-
Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using Ask±n, makes your SL shorter and your TP longer, by the spread. Don't you want the specified amount used in either direction?
-
Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask / OrderClosePrice reaches it. To trigger close at a specific Bid price, add the average spread.
MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25 -
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.)
Most brokers with variable spreads widen considerably at end of day (5 PM ET) ± 30 minutes.
My GBPJPY shows average spread = 26 points, average maximum spread = 134.
My EURCHF shows average spread = 18 points, average maximum spread = 106.
(your broker will be similar).
Is it reasonable to have such a huge spreads (20 PIP spreads) in EURCHF? - General - MQL5 programming forum (2022)
You buy at the Ask and sell at the Bid. Pending Buy Stop orders become market orders when hit by the Ask.
-
Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using Ask±n, makes your SL shorter and your TP longer, by the spread. Don't you want the specified amount used in either direction?
-
Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask / OrderClosePrice reaches it. To trigger close at a specific Bid price, add the average spread.
MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25 -
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.)
Most brokers with variable spreads widen considerably at end of day (5 PM ET) ± 30 minutes.
My GBPJPY shows average spread = 26 points, average maximum spread = 134.
My EURCHF shows average spread = 18 points, average maximum spread = 106.
(your broker will be similar).
Is it reasonable to have such a huge spreads (20 PIP spreads) in EURCHF? - General - MQL5 programming forum (2022)
My SL/TP price are the EMA300 price and the EMA100 price. I don't use currentAsk to calculate my SL/TP (the code line you took, I use it for determining my SL % and so my possible position size).
The spread on this chart is a constant : 9$.
But besides the obvious error above, you should also always normalise prices based on tick size. Don't use the "NormalizeDouble". Also verify your Stops Level too.
I changed it. I use this function has you linked it in your answer. Still the same problem, tho.
double Round2Ticksize( double price ) { double tick_size = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE ); return( round( price / tick_size ) * tick_size ); };
I up my topic because I'm still completely stuck : I get the error invalid request 10013 all the way. And after hours watching documentation and my code, I can't see why it's not working. Before this EA I did something a bit similar it was working, when I compare the 2, I don't see difference in my way of sending order, so I don't understand why this very simple code doesn't work properly.
I posted the full code a few comments up, please, is there anyone seeing what I'm missing about this ordersend request?

- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hello;
I get almost every time an error "invalid stops" when I test my EA. I think it's weird that it's not happening 100% of the times, sometimes the order go through. So, I try to figure out, what the difference when the order is taken and when he is rejected because my stops.
How can I find where the issue is? What things should I check/add/code to have valid stops?
I checked the actual value of SL/TP, but they show positive value with the correct number of digit every time.
I tried to make them lower/higher to be sure that they are not too close from the entry price, but the result is the same.
The code :
The error :
2023.01.26 18:13:27.434 Core 01 2022.11.12 02:14:40 failed market buy 0.18 BTCUSD sl: 17498.47 tp: 16756.34 [Invalid stops]