Using trade.BuyStop and unexpected Invalid Price errors inconsistently - page 2

 
Fernando Carreiro #:

If you are getting, zero for "SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL)", then there is no "Stops Level" in play.

In the code above, you don't seem to be checking if the Stop Orders are actually away from current prices or not. Don't assume they are. Check, that the stop order is above current Ask price for buys, and below current Bid for sell orders.

Show as actual log entries for the errors, where all the data is properly reported.

Add "debugging" to your code. Print out details to the log, such as current bid & ask, entry, stop-loss and take profit for the order, the trade result error code, etc.

Not quite 100%, but you are getting a much better understanding of enumerations. Suffice to say that you should always use the enumerations for the "indexing" and not their value. Don't ever hard-code the "indexing" values (i.e.use "SYMBOL_TRADE_STOPS_LEVEL" and not "31").

EDIT: Please show your updated code with all the updates you have made in accordance with the requirements outlined in the article.

Hi again Fernando,

Below you will find the updated code as well as an attached log file. I have tried to take in all that you have said. Please let me know if I have still made some errors. I no longer get invalid price in the logs.

I am confused why print seems to display the data just fine but doing printformat just shows zeros for everything. 


Edit: I apologize that the print statements are becoming a bit unkempt. Will address this in further updates going forward and once I figure out why Print works but not PrintFormat.

//+------------------------------------------------------------------+
//|                            EA_Shark_BuyStopLimit_3BarFractal.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+

#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Trade\Trade.mqh>
CTrade trade; 

//--- Global Service Variables 
MqlRates PriceDataTable[]; // Array to get price data to be used with fractals. Includes Volume.
int numberOfPriceDataPoints; // The amount of bars to use with CopyBuffer/CopyRates to populate new data from handles to arrays. 

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
//---
   ArraySetAsSeries(PriceDataTable,true); // Setting up table/array for time series data
   
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
   
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
//---
   //double stops_level = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL);
   //Print(SYMBOL_TRADE_STOPS_LEVEL);
   //PrintFormat("The SYMBOL_TRADE_STOPS_LEVEL for ES is %d points", (stops_level / Point()));
   //Print("*** " + SYMBOL_TRADE_STOPS_LEVEL);
   numberOfPriceDataPoints = CopyRates(_Symbol,0,0,10,PriceDataTable); // Collects data from shift 0 to shift 9 
   
   int symbolStopsLevel = (int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
   
   double currentBid, currentAsk, tickSize, confirmationLevel, entryLevel, stopLossLevel, takeProfitLevel, riskWindow, normalizedEntryLevel, normalizedStopLossLevel, normalizedTakeProfitLevel;
  
   currentBid = SymbolInfoDouble(_Symbol,SYMBOL_BID); // Get latest Bid Price
   currentAsk = SymbolInfoDouble(_Symbol,SYMBOL_ASK); // Get latest Ask Price
   tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   
   bool priceFractalBull3Bar = (PriceDataTable[2].low < PriceDataTable[3].low && PriceDataTable[2].low <= PriceDataTable[1].low); // 3 Bar  
   
   if(PositionSelect(_Symbol) == false && PositionsTotal() < 1 && OrdersTotal() < 1) // We have no open position
   {
      if(priceFractalBull3Bar)
      {
         // Set Levels and Distances for 2:1RR
         entryLevel = PriceDataTable[1].high + tickSize;
         stopLossLevel = PriceDataTable[2].low - tickSize;
         riskWindow = (entryLevel-stopLossLevel) * 2;
         takeProfitLevel = riskWindow + entryLevel;
         
         // Align price levels to tick size
         normalizedEntryLevel = round(entryLevel / tickSize) * tickSize;
         normalizedStopLossLevel = round(stopLossLevel / tickSize) * tickSize;
         normalizedTakeProfitLevel = round(takeProfitLevel / tickSize) * tickSize;
         
         // Print Levels for review
         Print("Price Bull Fractal - 3 Bar: ");      
         Print("currentAsk: " + currentAsk); // adding these since forum posts previously mentioned this as the "explanation"
         Print("currentBid: " + currentBid);
         Print("Entry Level: " + entryLevel);
         Print("Stop Loss Level: " + stopLossLevel);
         Print("Take Profit Level: " + takeProfitLevel);
         Print("Normalized EntryLevel: " + normalizedEntryLevel);
         Print("Normalized Stop Loss Level: " + normalizedStopLossLevel);
         Print("Normalized Take Profit Level: " + normalizedTakeProfitLevel);
         
         PrintFormat("Current Bid: %d. Current Ask: %d. Entry Level: %d. Stop Loss Level: %d, Take Profit Level: %d, Symbol Stops Level: %d.",
                           currentBid, currentAsk, normalizedEntryLevel, normalizedStopLossLevel, normalizedTakeProfitLevel, symbolStopsLevel);
         PrintFormat("Broker Stops Level: %d. Stops Level Raw: %d.", symbolStopsLevel, SYMBOL_TRADE_STOPS_LEVEL);
         if(symbolStopsLevel!=0)
         {
            PrintFormat("SYMBOL_TRADE_STOPS_LEVEL=%d: StopLoss and TakeProfit must"+
                           " not be nearer than %d points from the closing price",symbolStopsLevel,symbolStopsLevel);
         }
         
         if(normalizedEntryLevel > currentAsk)
         {  
            // Fire Trade
            trade.BuyStop(1, normalizedEntryLevel, _Symbol, normalizedStopLossLevel, normalizedTakeProfitLevel, ORDER_TIME_GTC, ORDER_TYPE_BUY_STOP_LIMIT);
         }
         else
         {
            Print("Bullish Entry Level has exceeded the currentAsk");
            Print("Current Ask: " + currentAsk + " Entry Level: " + normalizedEntryLevel);
         }
       }      
   }  
}

// END //
Files:
20230415.log  835 kb
 
cgleckman #: Hi again Fernando, Below you will find the updated code as well as an attached log file. I have tried to take in all that you have said. Please let me know if I have still made some errors. I no longer get invalid price in the logs. I am confused why print seems to display the data just fine but doing printformat just shows zeros for everything. Edit: I apologize that the print statements are becoming a bit unkempt. Will address this in further updates going forward and once I figure out why Print works but not PrintFormat.
  1. When you use the CopyRates function, you don’t check the results and any errors. You just assume that it returns the data without question.

  2. You are not using a “magic number”, so your EA will not play “nicely” with other EAs or even itself on other timeframes. You are just assuming that your EA is the only one working on the current symbol.

  3. You are not checking whether the entry price is valid for the pending order. I even posted an image showing the conditions required for the entry price. For a buy stop order, the entry must be above the Ask + Stops-Level, and for a sell stop order, it must be below the Bid - Stops-Level. You have not implemented it.

  4. Remember that buy orders open at Ask and close at Bid, and sell orders open at Bid and close at Ask. Look at the image posted.

  5. Considering the points above, you are also not checking the Stop-Loss and Take-Profit according to those rules. If the distance between the Entry and Stop-Loss (or Take-Profit) is smaller than the spread at the time it is triggered, it might be immediately closed when it is triggered.

  6. We have not touched yet on position sizing (volume) and risk calculation, but I will assume you will address all that in the future.

  7. There are also several other points that you have not addressed, such as filling mode, maximum deviation (slippage), etc. but I will leave that for you to research on your own.

  8. As for PrintFormat, please read the documentation, as %d is for integer values, not floating-point values.

 
Fernando Carreiro #:
  1. When you use the CopyRates function, you don’t check the results and any errors. You just assume that it returns the data without question.

  2. You are not using a “magic number”, so your EA will not play “nicely” with other EAs or even itself on other timeframes. You are just assuming that your EA is the only one working on the current symbol.

  3. You are not checking whether the entry price is valid for the pending order. I even posted an image showing the conditions required for the entry price. For a buy stop order, the entry must be above the Ask + Stops-Level, and for a sell stop order, it must be below the Bid - Stops-Level. You have not implemented it.

  4. Remember that buy orders open at Ask and close at Bid, and sell orders open at Bid and close at Ask. Look at the image posted.

  5. Considering the points above, you are also not checking the Stop-Loss and Take-Profit according to those rules. If the distance between the Entry and Stop-Loss (or Take-Profit) is smaller than the spread at the time it is triggered, it might be immediately closed when it is triggered.

  6. We have not touched yet on position sizing (volume) and risk calculation, but I will assume you will address all that in the future.

  7. There are also several other points that you have not addressed, such as filling mode, maximum deviation (slippage), etc. but I will leave that for you to research on your own.

  8. As for PrintFormat, please read the documentation, as %d is for integer values, not floating-point values.

Just catching up and wanted to say thank you for all you do for the community and elevating others. Its very much appreciated. 

 
Fernando Carreiro #:
  1. When you use the CopyRates function, you don’t check the results and any errors. You just assume that it returns the data without question.

  2. You are not using a “magic number”, so your EA will not play “nicely” with other EAs or even itself on other timeframes. You are just assuming that your EA is the only one working on the current symbol.

  3. You are not checking whether the entry price is valid for the pending order. I even posted an image showing the conditions required for the entry price. For a buy stop order, the entry must be above the Ask + Stops-Level, and for a sell stop order, it must be below the Bid - Stops-Level. You have not implemented it.

  4. Remember that buy orders open at Ask and close at Bid, and sell orders open at Bid and close at Ask. Look at the image posted.

  5. Considering the points above, you are also not checking the Stop-Loss and Take-Profit according to those rules. If the distance between the Entry and Stop-Loss (or Take-Profit) is smaller than the spread at the time it is triggered, it might be immediately closed when it is triggered.

  6. We have not touched yet on position sizing (volume) and risk calculation, but I will assume you will address all that in the future.

  7. There are also several other points that you have not addressed, such as filling mode, maximum deviation (slippage), etc. but I will leave that for you to research on your own.

  8. As for PrintFormat, please read the documentation, as %d is for integer values, not floating-point values.

Hi Fernando,

I appreciate these 8 points that you have sent me. As I mentioned this is a barebones EA to show the issue we were having without tons of clutter and hundreds of lines of code. As for #3, #5, #7, #8 I will work to address these and see where I end up. Thank you very much for your help. I do apologize for any confusion that may of occurred with some of your listed points above.

Thank you again!

Reason: