Problem: multiple firing of orders within bars

 
I have used an expert advisor that can place orders at the beginning of a new bar, and that works fine with adding the time and prevtime limitation as described in the manual.

I am now trying to run an expert advisor that is able to send orders within a bar when my conditions are met. However, I have the problem that the system fires mutiple orders each time, often 2-3 but sometimes 5-8 orders within a second or so.

I assumed that MT4 works at the tick level - but my loop does not seem to be able to stop the firing and I am wondering what is going on. I also tried the sleep function after the OrderSend function to slow down my system but it does not seem to help.

Does anybody have an idea what is happening here, or has a programming fix to restrict these multiple orders to just one when working at the tick level within a bar?
 
Try something like this:

static datetime lastordertime= 0;
int sometimelimit= 10 * 60;  // don't re-order within 10 minutes


...


if (CurTime()-lastordertime > sometimelimit) {
   OrderSend(....);
   lastordertime= CurTime();
}
 
Or:

static datetime lastorderbartime= 0;
...


if (Time[0]!=lastorderbartime) {  // don't reorder in the same bar
   OrderSend(....);
   lastordertime= Time[0];
}
 
Try something like this:

static datetime lastordertime= 0;
int sometimelimit= 10 * 60;  // don't re-order within 10 minutes
...

if (CurTime()-lastordertime > sometimelimit) {
   OrderSend(....);
   lastordertime= CurTime();
}



hello shimodax,

thank you for your ideas. i wish to have intra-bar trades, so the second solution would not apply, but i am currently testing your suggestion above.

i have tried the following for intra-bar orders before, to limit to one open long/short trade at a time. for some reason it does not seem to work. can anyone see the flaw in my code or logic for the following approach?

Here is the backbones of the code (... means left out code that is not relevant here)

//BEGIN
extern double Lots = 0.1;
extern double Stop_Loss = 50;
extern double Slippage=5;
extern double Acct_Lowest=500;
extern double Limit_1a=20;
//... plus other external variables


int start()
{
//...plus some other variables defined
static double Already_Buy, Already_Sell;
int cnt, ticket, total;

// ...initial data checks


//Check for open positions of same price
total=OrdersTotal();
for(cnt=0;cnt<total;cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); // check opened BUY positions for same price
if(
OrderType()==OP_BUY &&
OrderSymbol()==Symbol()
)

{
Already_Buy=1; // long position is already opened at same price
break; // no need to check more positons since found one
}
else {Already_Buy=0;}


OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); // check opened SELL positions for same price
if(
OrderType()==OP_SELL &&
OrderSymbol()==Symbol()
)

{
Already_Sell=1; // short position is already opened at same price
break; // no need to check more positons since found one
}
else {Already_Sell=0;}


} // end for loop


//BEGIN ACTIVITY

//LONG TRADES
if
(
// ... my conditions for Long Trade
&& Already_Buy != 1

{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,Ask,Stop_Loss*Point,Ask+Limit_1a*Point,"Sample",123,0,Blue);
Already_Buy=1; // security fix: if delayed confirmation from dealer, this should stop more orders. necessary?
return(0);
}

//SHORT TRADES
if
(
// ... my conditions for Short Trade
&& Already_Sell != 1
)

{

ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,Bid+Stop_Loss*Point,Bid-Limit_1a*Point,"Sample",123,0,Red);
Already_Sell=1; // security fix: if delayed confirmation from dealer, this should stop more orders. necessary?
return(0);
}


return(0);
}
// the end.
 
You're resetting your already_buy/sell values for every order that doesn't match the criteria (eg. an existing open buy order will reset your already sell (in the else clause)).

Try to set them both to zero before looping through the orders and inside the loop just set them to 1 when an matching order is found.


Markus
 

You're resetting your already_buy/sell values for every order that doesn't match the criteria (eg. an existing open buy order will reset your already sell (in the else clause)).

Try to set them both to zero before looping through the orders and inside the loop just set them to 1 when an matching order is found.


Markus



Thank you!! Good idea, and I hear what you are saying. I am in process of testing the program with your fix. This raises 2 questions though:

(1) Shouldn't 'break' jump out of the 'for-loop' and prevent the resetting of the variable as you suggest?

(2) With setting the already_buy/sell variables to zero outside of the 'for-loop', don't I risk multiple firing because when the program executes upon the next tick, the order confirmation from the broker may not have arrived yet and the program will keep ordering at the same price until it shows as an opened order? I tried to prevent that by setting already_buy/sell = 1 after the order is sent, but with setting already_buy/sell before the 'for-loop' as you suggest that effort will not work anymore.

BTW, is the use of 'ticket=OrderSend()' correct? I took that from the dictionary and not sure why that is necessary. Couldn't I use 'SendOrder()' without ticket? Or do I need to loop through ticket? I assume I do not need to initialize any of the system functions that have a () at the end of the variable name, such as SendOrder() or OrderOpenPrice()?

Thanks so much for your help - been very useful already!
 
Hi!

First the easy one. If you're not interested in the return value, you can just use

OrderSend(....);

However, usually it is a good idea to check the return and give an error message if it doesn't fit.


Regarding your orders. The break will exit, but which ever type comes first wil null out the other and will open the door to open the other type again (if you have a sell first and a buy open as second, your test for buy will null the already_buy before the next if checks for sell and breaks the loop).

I'm not sure if your extra security will be necessary. My assumption would be that if OrderOpen comes back with an order ticket number, the order is in the order list and can be checked (but I'm not entirely sure).


Markus
 
Hi!

First the easy one. If you're not interested in the return value, you can just use

OrderSend(....);

However, usually it is a good idea to check the return and give an error message if it doesn't fit.


Regarding your orders. The break will exit, but which ever type comes first wil null out the other and will open the door to open the other type again (if you have a sell first and a buy open as second, your test for buy will null the already_buy before the next if checks for sell and breaks the loop).

I'm not sure if your extra security will be necessary. My assumption would be that if OrderOpen comes back with an order ticket number, the order is in the order list and can be checked (but I'm not entirely sure).


Markus



Thank you, Shimodax - your answers do help me understand more and more.

I tried to incorporate your idea and tested it, to no avail. Not very often, but it still sends multiple orders. Is the below fix what you suggested or do you still see a flaw?

//Check for open positions of same price

Already_Buy=0;
Already_Sell=0;

total=OrdersTotal();
for(cnt=0;cnt<total;cnt++)
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); // check opened BUY positions for same price
if(
OrderType()==OP_BUY &&
OrderSymbol()==Symbol()
)

{
Already_Buy=1; // long position is already opened at same price
break; // no need to check more positons since found one
}


OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); // check opened SELL positions for same price
if(
OrderType()==OP_SELL &&
OrderSymbol()==Symbol()
)

{
Already_Sell=1; // short position is already opened at same price
break; // no need to check more positons since found one
}


} // end for loop
 
In this case now, if you have both orders open (buy and sell) the first one found will leave the loop (through the break) and will let the other Already_xxxx variable zero. So try to remove the breaks and you should be fine.


Markus
 

In this case now, if you have both orders open (buy and sell) the first one found will leave the loop (through the break) and will let the other Already_xxxx variable zero. So try to remove the breaks and you should be fine.


Markus


Thank you - I removed the breaks and also put the loop into two separate for-loops after each other to ensure nothing gets tangled up. Running tests at the moment.
 
you are a genius, Markus! it works like a treat now. thank you so much.

do you know if it is possible to take such a loop that checks for existing open orders through the Strategy Tester by using OrderSelect()? or does it need to be programmed differently?
Reason: