I have always been able to limit open orders across multiple pairs that all have different "magic numbers" but recently I am having a problem because my EA will open more than the allowed 1 trade if the entry criteria is met at the same time on different pairs. E.g. if the EA opens a trade when price opens above an MA and 2 pairs have this occur at the open of a bar even with the below code both orders can still be sent. Frustrating and wondering if there is any way to solve this?
I have always been able to limit open orders across multiple pairs that all have different "magic numbers" but recently I am having a problem because my EA will open more than the allowed 1 trade if the entry criteria is met at the same time on different pairs. E.g. if the EA opens a trade when price opens above an MA and 2 pairs have this occur at the open of a bar even with the below code both orders can still be sent. Frustrating and wondering if there is any way to solve this?
The code you post doesn't make sense as your count variable will always be equal to OrderTotal() except if there is an error with OrderSelect().
A minor error :
Print("OrderSend() OrderSelect() error - ", ErrorDescription(GetLastError()));
Why do you want to limit the EA when it's on multiple pairs? Different pairs, different signals. Diversify, you want to trade both to lessen risk.
What I do is adjust lotsize appropriately. When a pair is about to open (hasn't reached it's trigger price yet) it creates a Global Variable such as EA_pair_tf. The value is a timeout (like at end of bar.) When the trigger is reached, I lock a mutex, count the number of EAs about to trade (nOpening) and adjust:
- account balance * percentage = Risk = (OrderOpenPrice - OrderStopLoss)*DIR * DeltaPerLot() * Lotsize; therefor:
- Lotsize = (account balance * percentage / (OOP-OSL) / DeltaPerLot. Reduce AB by currently open orders at risk amounts, and by number of EAs about to open:
- Lotsize = ([account balance - balance_chart_atRisk )* percentage / (OOP-OSL) / DeltaPerLot / nOpening.
Thank you all so much. I spent a lot of time reading and coding a "mutex" and came up with the following bits of code that seems to work, however if orders get sent at the exact same time there can still be multiple orders open.
//checks if there is an open order int IfOrderDoesNotExist2() { bool exists = false; for (int i=OrdersTotal()-1; i >= 0; i--) if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { { exists = true; } } else { Print("OrderSelect() error - ", ErrorDescription(GetLastError())); } if (exists == false) { TradeIsNotBusy(); } } //sends buy order if trade is not busy void BuyOrder4() { double SL = Ask - BuyStoploss4*PipValue*Point; if (BuyStoploss4 == 0) SL = 0; double TP = Ask + BuyTakeprofit4*PipValue*Point; if (BuyTakeprofit4 == 0) TP = 0; if(TradeIsBusy() < 0) return(-1); // RefreshRates(); int ticket = -1; if (true) ticket = OrderSend(Symbol(), OP_BUY, BuyLots4, Ask, 4, 0, 0, "My Expert", OrderID, 0, Blue); else ticket = OrderSend(Symbol(), OP_BUY, BuyLots4, Ask, 4, SL, TP, "My Expert", OrderID, 0, Blue); if (ticket > -1) { if (true) { OrderSelect(ticket, SELECT_BY_TICKET); bool ret = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0, Blue); if (ret == false) Print("OrderModify() error - ", ErrorDescription(GetLastError())); } // TradeIsNotBusy(); } else { Print("OrderSend() error - ", ErrorDescription(GetLastError())); } } //functions for trade is busy ///////////////////////////////////////////////////////////////////////////////// // int TradeIsBusy( int MaxWaiting_sec = 30 ) // // The function replaces the TradeIsBusy value 0 with 1. // If TradeIsBusy = 1 at the moment of launch, the function waits until TradeIsBusy is 0, // and then replaces. // If there is no global variable TradeIsBusy, the function creates it. // Return codes: // 1 - successfully completed. The global variable TradeIsBusy was assigned with value 1 // -1 - TradeIsBusy = 1 at the moment of launch of the function, the waiting was interrupted by the user // (the expert was removed from the chart, the terminal was closed, the chart period and/or symbol // was changed, etc.) // -2 - TradeIsBusy = 1 at the moment of launch of the function, the waiting limit was exceeded // (MaxWaiting_sec) ///////////////////////////////////////////////////////////////////////////////// int TradeIsBusy( int MaxWaiting_sec = 30 ) { // at testing, there is no resaon to divide the trade context - just terminate // the function if(IsTesting()){ return(1); } GetLastError(); int _GetLastError = 0, StartWaitingTime = GetTickCount(); //+------------------------------------------------------------------+ //| Check whether a global variable exists and, if not, create it | //+------------------------------------------------------------------+ while(true) { // if the expert was terminated by the user, stop operation if(IsStopped()) { Print("The expert was terminated by the user!"); return(-1); } // if the waiting time exceeds that specified in the variable // MaxWaiting_sec, stop operation, as well if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000) { Print("Waiting time (" + MaxWaiting_sec + " sec) exceeded!"); return(-2); } // check whether the global variable exists // if it does, leave the loop and go to the block of changing // TradeIsBusy value if(GlobalVariableCheck( "TradeIsBusy" )) break; else // if the GlobalVariableCheck returns FALSE, it means that it does not exist or // an error has occurred during checking { _GetLastError = GetLastError(); // if it is still an error, display information, wait for 0.1 second, and // restart checking if(_GetLastError != 0) { Print("TradeIsBusy()-GlobalVariableCheck(\"TradeIsBusy\")-Error #", _GetLastError ); Sleep(100); continue; } } // if there is no error, it means that there is just no global variable, try to create // it // if the GlobalVariableSet > 0, it means that the global variable has been successfully created. // Leave the function if(GlobalVariableSet( "TradeIsBusy", 1.0 ) > 0 ) return(1); else // if the GlobalVariableSet has returned a value <= 0, it means that an error // occurred at creation of the variable { _GetLastError = GetLastError(); // display information, wait for 0.1 second, and try again if(_GetLastError != 0) { Print("TradeIsBusy()-GlobalVariableSet(\"TradeIsBusy\",0.0 )-Error #", _GetLastError ); Sleep(100); continue; } } } //+----------------------------------------------------------------------------------+ //| If the function execution has reached this point, it means that global variable | //| variable exists. | //| Wait until the TradeIsBusy becomes = 0 and change the value of TradeIsBusy for 1 | //+----------------------------------------------------------------------------------+ while(true) { // if the expert was terminated by the user, stop operation if(IsStopped()) { Print("The expert was terminated by the user!"); return(-1); } // if the waiting time exceeds that specified in the variable // MaxWaiting_sec, stop operation, as well if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000) { Print("The waiting time (" + MaxWaiting_sec + " sec) exceeded!"); return(-2); } // try to change the value of the TradeIsBusy from 0 to 1 // if succeed, leave the function returning 1 ("successfully completed") if(GlobalVariableSetOnCondition( "TradeIsBusy", 1.0, 0.0 )) return(1); else // if not, 2 reasons for it are possible: TradeIsBusy = 1 (then one has to wait), or // an error occurred (this is what we will check) { _GetLastError = GetLastError(); // if it is still an error, display information and try again if(_GetLastError != 0) { Print("TradeIsBusy()-GlobalVariableSetOnCondition(\"TradeIsBusy\",1.0,0.0 )-Error #", _GetLastError ); continue; } } //if there is no error, it means that TradeIsBusy = 1 (another expert is trading), then display // information and wait... Comment("Wait until another expert finishes trading..."); Sleep(1000); Comment(""); } } ///////////////////////////////////////////////////////////////////////////////// // void TradeIsNotBusy() // // The function sets the value of the global variable TradeIsBusy = 0. // If the TradeIsBusy does not exist, the function creates it. ///////////////////////////////////////////////////////////////////////////////// void TradeIsNotBusy() { int _GetLastError; GetLastError(); // at testing, there is no sense to divide the trade context - just terminate // the function if(IsTesting()) { return(0); } while(true) { // if the expert was terminated by the user, ïðåêðàùàåì ðàáîòó if(IsStopped()) { Print("The expert was terminated by the user!"); return(-1); } // try to set the global variable value = 0 (or create the global // variable) // if the GlobalVariableSet returns a value > 0, it means that everything // has succeeded. Leave the function if(GlobalVariableSet( "TradeIsBusy", 0.0 ) > 0) return(1); else // if the GlobalVariableSet returns a value <= 0, this means that an error has occurred. // Display information, wait, and try again { _GetLastError = GetLastError(); if(_GetLastError != 0 ) Print("TradeIsNotBusy()-GlobalVariableSet(\"TradeIsBusy\",0.0)-Error #", _GetLastError ); } Sleep(100); } }
Thanks again I have had a good study and tried to implement aspects of your code. I can get the mutex to work the majority of the time but every now and then an additional trade slips through the gap at the exact same time, despite my EA having a limit open order set to 1, a mutex to prevent 2 being send and the same time and the fact that it only trades at the open of a bar! This is my order send code and I have included both functions from the article in global variables/mutex: https://www.mql5.com/en/articles/1412
Perhaps I am missing something like having TradeIsBusy() and TradeIsNotBusy() in the wrong position? Maybe I need to change the waiting time so that the order that got blocked out initially is never actually sent? Maybe it is just possible that both orders will always go through as they are sent at EXACTLY the same time.
void BuyOrder4() { if(TradeIsBusy() < 0) //correct place?? return(-1); //correct place?? double SL = Ask - BuyStoploss4*PipValue*Point; if (BuyStoploss4 == 0) SL = 0; double TP = Ask + BuyTakeprofit4*PipValue*Point; if (BuyTakeprofit4 == 0) TP = 0; int ticket = -1; if (true) ticket = OrderSend(Symbol(), OP_BUY, BuyLots4, Ask, 4, 0, 0, "My Expert", OrderID, 0, Blue); else ticket = OrderSend(Symbol(), OP_BUY, BuyLots4, Ask, 4, SL, TP, "My Expert", OrderID, 0, Blue); if (ticket > -1) { if (true) { OrderSelect(ticket, SELECT_BY_TICKET); bool ret = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0, Blue); if (ret == false) Print("OrderModify() error - ", ErrorDescription(GetLastError())); } } else { Print("OrderSend() error - ", ErrorDescription(GetLastError())); } TradeIsNotBusy(); //correct place?? return(0); //correct place?? }
Thanks again I have had a good study and tried to implement aspects of your code. I can get the mutex to work the majority of the time but every now and then an additional trade slips through the gap at the exact same time, despite my EA having a limit open order set to 1, a mutex to prevent 2 being send and the same time and the fact that it only trades at the open of a bar! This is my order send code and I have included both functions from the article in global variables/mutex: https://www.mql5.com/en/articles/1412
Perhaps I am missing something like having TradeIsBusy() and TradeIsNotBusy() in the wrong position? Maybe I need to change the waiting time so that the order that got blocked out initially is never actually sent? Maybe it is just possible that both orders will always go through as they are sent at EXACTLY the same time.
When is . .
if (true)
. . . ever false ? so why bother with the if and the else ?
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
I have always been able to limit open orders across multiple pairs that all have different "magic numbers" but recently I am having a problem because my EA will open more than the allowed 1 trade if the entry criteria is met at the same time on different pairs. E.g. if the EA opens a trade when price opens above an MA and 2 pairs have this occur at the open of a bar even with the below code both orders can still be sent. Frustrating and wondering if there is any way to solve this?