I tried a few things for my ChangeTheColor EA but stil kept getting the odd one. George then suggested replacing calls to OrderSend and OrderModify with a customised version that uses a semaphore (Global Variable) that stops EAs sending trades until the semaphore says they can.
Just replace all calls to OrderSend with _OrderSend and OrderModify with _OrderModify and drop the following code into the EA.
Code: Select all
/////////////////////////////////////////////////////////////////////////
//
// Replace internal functions with updated ones to use trade semaphores
//
/////////////////////////////////////////////////////////////////////////
int _OrderSend(string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment="", int magic=0, datetime expiration=0, color arrow_color=CLR_NONE) {
int res = -1;
//try to lock resource
if (LockTradingThread()<0) {
Alert("Unable to place trade, timeout exceeded.");
return(res);
}
RefreshRates();
//place trade
res = OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrow_color);
//unlock resource
UnlockTradingThread();
return(res);
}
bool _OrderModify( int ticket, double price, double stoploss, double takeprofit, datetime expiration, color arrow_color=CLR_NONE) {
bool res = false;
//try to lock resource
if (LockTradingThread()<0) {
Alert("Unable to modify trade, timeout exceeded.");
return(res);
}
RefreshRates();
//modify order
res = OrderModify(ticket, price, stoploss, takeprofit, expiration, arrow_color);
//unlock resource
UnlockTradingThread();
return(res);
}
/////////////////////////////////////////////////////////////////////////////////
// int LockTradingThread( int MaxWaiting_sec = 30 )
//
// The function replaces the LockTradingThread value 0 with 1.
// If LockTradingThread = 1 at the moment of launch, the function waits until LockTradingThread is 0,
// and then replaces.
// If there is no global variable LockTradingThread, the function creates it.
// Return codes:
// 1 - successfully completed. The global variable LockTradingThread was assigned with value 1
// -1 - LockTradingThread = 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 - LockTradingThread = 1 at the moment of launch of the function, the waiting limit was exceeded
// (MaxWaiting_sec)
/////////////////////////////////////////////////////////////////////////////////
int LockTradingThread( int MaxWaiting_sec = 30 )
{
// at testing, there is no resaon to divide the trade context - just terminate
// the function
if(IsTesting()) return(1);
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
// LockTradingThread value
if(GlobalVariableCheck( "LockTradingThread" ))
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("LockTradingThread()-GlobalVariableCheck(\"LockTradingThread\")-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( "LockTradingThread", 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("LockTradingThread()-GlobalVariableSet(\"LockTradingThread\",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 LockTradingThread becomes = 0 and change the value of LockTradingThread 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 LockTradingThread from 0 to 1
// if succeed, leave the function returning 1 ("successfully completed")
if(GlobalVariableSetOnCondition( "LockTradingThread", 1.0, 0.0 ))
return(1);
else
// if not, 2 reasons for it are possible: LockTradingThread = 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("LockTradingThread()-GlobalVariableSetOnCondition(\"LockTradingThread\",1.0,0.0 )-Error #",
_GetLastError );
continue;
}
}
//if there is no error, it means that LockTradingThread = 1 (another expert is trading), then display
// information and wait...
Print("Wait until another expert finishes trading...");
Sleep(1000);
}
}
/////////////////////////////////////////////////////////////////////////////////
// void UnlockTradingThread()
//
// The function sets the value of the global variable LockTradingThread = 0.
// If the LockTradingThread does not exist, the function creates it.
/////////////////////////////////////////////////////////////////////////////////
void UnlockTradingThread()
{
int _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( "LockTradingThread", 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("UnlockTradingThread()-GlobalVariableSet(\"LockTradingThread\",0.0)-Error #",
_GetLastError );
}
Sleep(100);
}
}