MetaTrader 4. Build 180.

 
From our site you can download new version of MetaTrader 4, build 180.

Whats new:
1. Improved the simultaneously working experts interaction in trade context;
2. In MQL4 added GlobalVariableSetOnCondition() function;
3. In "stderror.mqh" added descriptions of new error types ERR_TRADE_MODIFY_DENIED and ERR_TRADE_CONTEXT_BUSY;
4. Updated Dictionary of MetaEditor IDE.
 
1. Improved the simultaneously working experts interaction in trade context;


Is item 1 going to reduce the amount of "trade context is busy" errors when multiple EA's try to submit orders simultaneously?

What specific changes does the "improved simultaneously working..." make?
 
From our site you can download new version of MetaTrader 4, build 180.

Whats new:
1. Improved the simultaneously working experts interaction in trade context;
2. In MQL4 added GlobalVariableSetOnCondition() function;
3. In "stderror.mqh" added descriptions of new error types ERR_TRADE_MODIFY_DENIED and ERR_TRADE_CONTEXT_BUSY;
4. Updated Dictionary of MetaEditor IDE.

I have downloaded mt4setup.exe and it did installed as Millennium Trader 4 instead of Meta Trader 4.
Is this how it will be from now on?
 
I have downloaded mt4setup.exe and it did installed as Millennium Trader 4 instead of Meta Trader 4.
Is this how it will be from now on?

there is our mistake. setup file will be updated in 2 days time
 
Is item 1 going to reduce the amount of "trade context is busy" errors when multiple EA's try to submit orders simultaneously?

What specific changes does the "improved simultaneously working..." make?

use new function GlobalVariableSetOnCondition to eliminate "trade context is busy" error. see sample from our russian forum. 12 copies of expert advisor work on the 12 1-minute charts and trade every bar beginning
double dStopLoss;
int nHoursToHold;

datetime timePrev = 0;

int nSlip = 50;

double dLotSize = 0.1;

int nMagic = 0;
int nDigits;

string strTradeSemaphore = "TradeSemaphore";

//////////////////
int init ()
{
	if(!GlobalVariableCheck(strTradeSemaphore)) 
		GlobalVariableSet(strTradeSemaphore, 0.0);
	
	dStopLoss = 110 * Point;
	nHoursToHold = 1;

	nDigits = MarketInfo( Symbol(), MODE_DIGITS );
	
	if(Symbol() == "EURUSD")
		nMagic = 1;
	else if(Symbol() == "EURJPY")
		nMagic = 2;
	else if(Symbol() == "USDCHF")
		nMagic = 3;
	else if(Symbol() == "GBPUSD")
		nMagic = 4;
	else if(Symbol() == "GBPJPY")
		nMagic = 5;
	else if(Symbol() == "GBPCHF")
		nMagic = 6;
	else if(Symbol() == "USDJPY")
		nMagic = 7;
	else if(Symbol() == "AUDUSD")
		nMagic = 8;
	else if(Symbol() == "EURGBP")
		nMagic = 9;
	else if(Symbol() == "USDCAD")
		nMagic = 10;
	else if(Symbol() == "EURCHF")
		nMagic = 11;
	else if(Symbol() == "EURAUD")
		nMagic = 12;
		
	return(0);	
}

// ------

int deinit()
{
	return(0);
}

// ------

int start()
{
	if(Bars < 5)
		return(0);
	
	// The previous bar just closed
	bool bIsBarEnd = false;
	if(timePrev != Time[0] + nMagic) 
		bIsBarEnd = true;
	timePrev = Time[0] + nMagic;
	
	if(!bIsBarEnd)
		return(0);

	// ------
	
	while(!IsStopped())
	{
		if(GlobalVariableGetOnCondition(strTradeSemaphore, 1.0, 0.0) == true) break;
		
		Sleep(1000);
	}

	for(int nCnt = OrdersTotal() - 1; nCnt >= 0; nCnt--)
	{
		OrderSelect(nCnt, SELECT_BY_POS, MODE_TRADES);

		if(OrderMagicNumber() == nMagic)
		{
			if(CurTime() - OrderOpenTime() > (nHoursToHold - 1) * 60 * 60)
			{
				if(OrderType() == OP_BUY)
					OrderClose(OrderTicket(), OrderLots(), Bid, nSlip, Aqua);
				else if(OrderType() == OP_SELL)
					OrderClose(OrderTicket(), OrderLots(), Ask, nSlip, OrangeRed);
			}
		}
	}

	int nSignal = GetSignal();
	
	if(nSignal == OP_BUY) 
		Buy();
	else if(nSignal == OP_SELL) 
		Sell();

	GlobalVariableSet(strTradeSemaphore, 0.0);	
	
	return(0);
}
// ------

void Sell()
{
	if(AccountFreeMargin() < 500)
		return;

	dLotSize = GetLotSize();

	double dNormalizer = MathPow(10, nDigits);
	double dBid = MathFloor(Bid * dNormalizer) / dNormalizer; //NormalizeDouble(Bid, nDigits);
	double dStop = MathFloor((Bid + dStopLoss) * dNormalizer) / dNormalizer; //NormalizeDouble(Bid + dStopLoss, nDigits);

	int nResult = OrderSend(Symbol(), OP_SELL, dLotSize, dBid, 
		nSlip, dStop, 0, "Friday", nMagic, 0, OrangeRed);

	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(Symbol() + ", sell: " + dBid + ", Stop: " + dStop + ", error: " + nError);
	}
}

// ------

void Buy()
{
	if(AccountFreeMargin() < 500)
		return;

	dLotSize = GetLotSize();

	double dNormalizer = MathPow(10, nDigits);
	double dAsk = MathFloor(Ask * dNormalizer) / dNormalizer; //NormalizeDouble(Bid, nDigits);
	double dStop = MathFloor((Ask - dStopLoss) * dNormalizer) / dNormalizer; //NormalizeDouble(Bid + dStopLoss, nDigits);

	int nResult = OrderSend(Symbol(), OP_BUY, dLotSize, dAsk, 
		nSlip, dStop, 0, "Friday", nMagic, 0, Aqua);

	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(Symbol() + ", buy: " + dAsk + 
			", Stop: " + dStop + ", error: " + nError);
	}
}
// ------

double GetLotSize()
{
	double dLot = 0.1;
	
	return(dLot);
}

// ------

int GetSignal()
{
	int nSignal;
	if(MathMod(Hour(), 2) == 0)
		nSignal = OP_BUY;
	else
		nSignal = OP_SELL;
		
	return(nSignal);
}
 
The MetaEditor Dictionary also has a good example of how to use GlobalVariableGetOnCondition(). I think it's actually a little easier to understand than the example here.

Regards,
Loren
 
I didn't like this example because sleep(1000) seems like it can still generate a collision. So I wrote a function to generate a random number between two given numbers. See this thread. "Random number generator within range"

Regards,
Loren
Reason: