Help Me Understand This Impossible Situation

 

Sometime last year, my EA which had been working fine without any issues started placing double orders of the same type.  Contrary to my beliefs, the MQL5 community was sure that my code was executing multiple times, so I placed some checks in my code that would prevent this (A CyclePause (Where AO crosses 0), the clearing of the  TransactImmediately flag that allows the BUY transaction to occur, a check to make sure I don't have any open positions, and a WHILE loop which literally stops the EA in its tracks until it reaches 20000). 

The following is my code for determining when to place a BUY order...Please note the PRINT line so I can see that this piece of logic was executed.

         // Place Buy Order
         if (CyclePause < 1 && DoNotTradeTillAfterTime < time && OpenPositions < 1 
             && myRSIValue < 25 
            && (LastSignal == "" || (LastSignal == "buy" && ((MathAbs(LastBuyAsk - Ask) /_Point) > 225)) || (LastSignal == "sell" && ((MathAbs(LastSellAsk - Ask) /_Point) > 425)) )
            )
            if (TransactImmediately=="buy"||(TransactImmediately=="Buy"))
               {
                  TradeAmt = Amt;
                  plusorminuscount=0;
                  Print("*** - Buy TransactImmediately= ",TransactImmediately,"   RSI=",myRSIValue);
                  TransactImmediately="";
                  Print("Buy...(",Amt,",NULL,",Ask,",",(Ask-500* _Point),",",(Ask+150* _Point),",NULL)");
                  trade.Buy(Amt,NULL,Ask,(Ask-750* _Point),(Ask+250* _Point),NULL);  
                  RSL = (Ask-450* _Point);
                  InitiateRecoveryProtocolAt = (Ask-InitiateRecoveryProtocolAtPoint* _Point);  
                  OrderType = "B"; 
                  OrderPrice=Ask;
                  TakeProfit = NormalizeDouble((Ask+100* _Point),6);
                  ProfitAmt = 35;
                  NewTakeProfit = NormalizeDouble((Ask+85* _Point),6);
                  signal = "buy";
                  prevplusorminuscount=prevplusorminuscount*-1;
                  CyclePause = 1;
                  PrepareTransImmed = "";
                  DoNotTradeTillAfterTime = time + 60;
                  
                  int i=0;
                  do
                  {
                     i++; // without this operator an infinite loop will appear!
                     Comment("i = ",i,"   ",time, "   ", DoNotTradeTillAfterTime);
                     if (i>20000)DoNotTradeTillAfterTime = time;
                  }
                  while(DoNotTradeTillAfterTime > time); 
               }
        
      }  

So how is the following double BUY execution possible then?

2021.03.10 01:10:00.789 Test3a (EURUSD,M1)      477.TransactImmediately: Buy   RSI: 17.42
2021.03.10 01:10:00.789 Test3a (EURUSD,M1)      *** - Buy TransactImmediately= Buy   RSI=17.42
2021.03.10 01:10:00.789 Test3a (EURUSD,M1)      Buy...(0.2,NULL,1.18919,1.18419,1.19069,NULL)
2021.03.10 01:10:00.789 Test3a (EURUSD,M1)      477.TransactImmediately: Buy   RSI: 17.42
2021.03.10 01:10:00.789 Test3a (EURUSD,M1)      *** - Buy TransactImmediately= Buy   RSI=17.42
2021.03.10 01:10:00.789 Test3a (EURUSD,M1)      Buy...(0.2,NULL,1.18919,1.18419,1.19069,NULL)

This does not happen while testing...Only when ran on my LIVE account.


Thanks in Advance,

Mike

 
                  int i=0;
                  do
                  {
                     i++; // without this operator an infinite loop will appear!
                     Comment("i = ",i,"   ",time, "   ", DoNotTradeTillAfterTime);
                     if (i>20000)DoNotTradeTillAfterTime = time;
                  }
                  while(DoNotTradeTillAfterTime > time); 

What kind of timing is this loop supposed to do? There's only 20000 calls to Comment() without any read-outs of the system clock.

Why don't you just remember the TimeCurrent() value and return control to the GUI like any other EA coder does?

 

Why would I want a read out of the system clock when I'm only using time as an exit control to the While loop?  Using an integer value instead of a time value is useful when displaying the Comments in the "Testing" of the EA, since when you run the EA using TEST/Historical data, a minute expires in a less than a blink of an eye unless you manually slow down the processing speed.  Using the While loop until the counter reaches 20000 (which only takes about 10 seconds to go through its full iteration) gives me more flexibility, as I can keep the processing speed at full throttle, see the Comments counting up to 20000, and then when it reaches 20000, my code continues at full throttle without me having readjust the processing speed. 

Perhaps other EA coders like to throttle down the speed of their testing, but I don't.

 
MikeKratz:

Why would I want a read out of the system clock when I'm only using time as an exit control to the While loop?  Using an integer value instead of a time value is useful when displaying the Comments in the "Testing" of the EA, since when you run the EA using TEST/Historical data, a minute expires in a less than a blink of an eye unless you manually slow down the processing speed.  Using the While loop until the counter reaches 20000 (which only takes about 10 seconds to go through its full iteration) gives me more flexibility, as I can keep the processing speed at full throttle, see the Comments counting up to 20000, and then when it reaches 20000, my code continues at full throttle without me having readjust the processing speed. 

Perhaps other EA coders like to throttle down the speed of their testing, but I don't.

you are missing the point....  your loop means you are doing nothing for 10 seconds other than using up resources for no purpose.

checking a timeout is more efficient and allows other things to be done with the resources in those ten seconds. running code at full throttle as you call it, for ten seconds to acheive nothing in that time is pointless.

with regards to your original question, put a break point in at the IF and check the values of the varibles in the debugger on each call, we can't see the rest of your code so we can't say how many times it is being called.. or how you are setting things like OpenPositions

 

Read https://www.mql5.com/ru/forum/170952/page70#comment_6585014 and the next post. Most likely you have similar logic which can allow for multiple positions to be opened.

You want to return from Ontick as fast as possible. Using sleep or long loops is not good practice as you will miss ticks. Fix the entry logic.

 
Paul Anscombe:

you are missing the point....  your loop means you are doing nothing for 10 seconds other than using up resources for no purpose.

checking a timeout is more effiecient and allows other things to be done with the resources in those ten seconds. running code at full throttle as you call it, for ten seconds to acheive nothing in that time is pointless.

No...It seems everyone else is missing the entire point of this question/post and focusing entirely on 'why' I wrote the code the way I did.

I know the While loop ties up resources...That's why I used it.  The While loop makes sure that absolutely nothing else can be done for 10 seconds, because I was told before that the EA was cycling through a second time and placing a second (not duplicate) transaction and I knew it wasn't.

So, back to the issue at hand...How can a duplicate/identicalorder be posted when it's impossible for the EA to get back to the trade.Buy command the same millisecond


That is what I am missing.

 
Enrique Dangeroux:

Read https://www.mql5.com/ru/forum/170952/page70#comment_6585014 and the next post. Most likely you have similar logic which can allow for multiple positions to be opened.

You want to return from Ontick as fast as possible. Using sleep or long loops is not good practice as you will miss ticks. Fix the entry logic.

Thanks for your reply...No...The OpenPositions variable must be < 1, or No Open Orders, in order for a Buy trade to be made. 

//---------------------------------------------------------------------                    
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
void OnTick()
  {
  
  int OpenPositions = PositionsTotal();
  
  

The question at hand is how can a duplicate order (the same millisecond) be done with a While loop that ties up system resources for 10 seconds?  I wish I did not have to use it, but this is the second time this Duplicity problem has struck me.

No, I do not want to return Ontick as fast as possible.  I only allow 1 trade to be open at a time as I really don't use TP and can only track 1 order at a time as I readjust the SL (both coming and going) using sliding code I wrote, and there are alot of variables to contend with.  It ensures that I make at least ~100 pips profit, but will continue to slide/increase increase so long as the ASK does not fall back below that last SL update.  Like I said...I wish I did not have to tie up the system for 10 seconds, but all other efforts to thwart this duplicity problem (previously) was only solved with the While loop tieing up resources.

 
MikeKratz:

No...It seems everyone else is missing the entire point of this question/post and focusing entirely on 'why' I wrote the code the way I did.

I know the While loop ties up resources...That's why I used it.  The While loop makes sure that absolutely nothing else can be done for 10 seconds, because I was told before that the EA was cycling through a second time and placing a second (not duplicate) transaction and I knew it wasn't.

So, back to the issue at hand...How can a duplicate/identicalorder be posted when it's impossible for the EA to get back to the trade.Buy command the same millisecond


That is what I am missing.

without the rest of the code it is guessing games, have you checked the actual terminal journal for that period what does it show? 

 
No matter what you state, given the info you provide, the code is executed twice.

The print statement seems proof of this thesis.

Btw, it could be the new compiler version simply optimizes your "sleep"-Loop and therefore it is useless.

I would suggest to rethink the process of how to "make the EA wait".

A time check function would be useful. You could try GetMicroseconds(). And wait for a suitable time.

Further conclusions do not seem possible, given the provided info.
Reason: