Ошибка номер 6 - страница 9

 
Слава, я поставил Вашу версию эксперта, на 12 окон (12 валют). Ошибок стало меньше, но они есть. Сори. Я успел получить 138 и 1. Попробуйте сами.

Надеюсь на дальнейшие указания.

Кварк
 
Кстати, код
while(!IsStopped())
{
	if(GlobalVariableGet(strTradeSemaphore) == 0.0)
	{
		GlobalVariableSet(strTradeSemaphore, 1.0);
		bSemaphored = true;
         
		break;
	}
		
	Sleep(1000);
}



допускает, что между if(GlobalVariableGet(strTradeSemaphore) == 0.0) и GlobalVariableSet(strTradeSemaphore, 1.0); вклинится другой эксперт. Нужна функция, которая захватит и запрет поток исполнения (то есть, дождется ресурса), а затем вернет контроль эксперту. Что-то вроде WaitForExclusive()

Хотя, возможно, дело и не в этом. Но ошибки сыплются, увы.

 
Вот так лучше. Но появились ошибки, которых раньше не было, например, ошибка 1.
Надеюсь на помощь.

Кстати, раз уж этот разговор возник, как автоматически определить, сколько знаков оставлять для цены при помощи NormalizeDouble, то есть, 4 для EURUSD, 2 для EURJPY... ?

double dStopLoss;
int nHoursToHold;

datetime timePrev = 0;

int nSlip = 5;

double dLotSize = 0.1;

int nMagic = 0;
int nDigits = 4;

string strTradeSemaphore = "TradeSemaphore";

//////////////////
int init ()
{
	if(!GlobalVariableCheck(strTradeSemaphore)) 
		GlobalVariableSet(strTradeSemaphore, 0.0);
	
	dStopLoss = 110 * Point;
	nHoursToHold = 1;
	
	if(Symbol() == "EURUSD")
		nMagic = 1;
	else if(Symbol() == "EURJPY")
	{
		nMagic = 2;
		nDigits = 2;
	}
	else if(Symbol() == "USDCHF")
		nMagic = 3;
	else if(Symbol() == "GBPUSD")
		nMagic = 4;
	else if(Symbol() == "GBPJPY")
	{
		nMagic = 5;
		nDigits = 2;
	}
	else if(Symbol() == "GBPCHF")
		nMagic = 6;
	else if(Symbol() == "USDJPY")
	{
		nMagic = 7;
		nDigits = 2;
	}
	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);

	// ------
	
	int nSignal = GetSignal();

	while(!IsStopped())
	{
		if(GlobalVariableGet(strTradeSemaphore) == 0.0)
			GlobalVariableSet(strTradeSemaphore, nMagic);

		if(GlobalVariableGet(strTradeSemaphore) == nMagic)
			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);
			}
		}
	}

	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();

	int nResult = OrderSend(Symbol(), OP_SELL, dLotSize, NormalizeDouble(Bid, nDigits), 
		nSlip, NormalizeDouble(Bid + dStopLoss, nDigits), 0, "Friday", nMagic, 0, OrangeRed);

	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(Symbol() + ", sell: " + NormalizeDouble(Bid, nDigits) + ", Stop: " + 
			NormalizeDouble(Bid + dStopLoss, nDigits) + ", error: " + nError);
	}
}

// ------

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

	dLotSize = GetLotSize();

	int nResult = OrderSend(Symbol(), OP_BUY, dLotSize, NormalizeDouble(Ask, nDigits), 
		nSlip, NormalizeDouble(Ask - dStopLoss, nDigits), 0, "Friday", nMagic, 0, Aqua);

	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(Symbol() + ", buy: " + NormalizeDouble(Ask, nDigits) + 
			", Stop: " + NormalizeDouble(Ask - dStopLoss, nDigits) + ", 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);
}

 
Ошибка 138 все-таки иногда появляется (я гоняю 12 пар на минутках, поэтому получение ошибки не заставляет долго ждать), а также ошибка 129 при вполне нормальной цене.
 
Итак. Ошибка 1. В вольном переводе из хелпа "что-то не так". 12 валютных пар на минутках, ошибка примерно раз в 5-10 минут.

Ошибка 138. Несколько раз в минуту (то есть, несколько из 12 экспертов ее порождают).

Ошибка 129. Я уж и цену нормировал, и чего только не делал...
 
стати, раз уж этот разговор возник, как автоматически определить, сколько знаков оставлять для цены при помощи NormalizeDouble, то есть, 4 для EURUSD, 2 для EURJPY... ?
	int _Digits = MarketInfo( Symbol(), MODE_DIGITS );




а один твой эксперт с моими 5-ю выдал за всё это время одну ошибку - 6.
в моей коррекции эксперт не работает - нахомутали в этом билде =)
ах, да... мои 5 тоже не работают =)))) вот, блин...

 
стати, раз уж этот разговор возник, как автоматически определить, сколько знаков оставлять для цены при помощи NormalizeDouble, то есть, 4 для EURUSD, 2 для EURJPY... ?
	int _Digits = MarketInfo( Symbol(), MODE_DIGITS );




а один твой эксперт с моими 5-ю выдал за всё это время одну ошибку - 6.
в моей коррекции эксперт не работает - нахомутали в этом билде =)
ах, да... мои 5 тоже не работают =)))) вот, блин...



Спасибо за код, сам бы долго искал.
Эксперт, предложенный Славой и улучшенный :) мной приводится ниже. Можно запускать его как я - в 12 окнах, с 12 валютами. Работает на любых таймфреймах, но на минутках быстрее :) Ошибки так и сыплются, блин... Понять бы, почему.

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(GlobalVariableGet(strTradeSemaphore) == 0.0)
			GlobalVariableSet(strTradeSemaphore, nMagic);

		if(GlobalVariableGet(strTradeSemaphore) == nMagic)
			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);
			}
		}
	}

	Sleep(500);

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

	Sleep(500);
	
	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);
}


 
Кстати, код [skipped]
допускает, что между if(GlobalVariableGet(strTradeSemaphore) == 0.0) и GlobalVariableSet(strTradeSemaphore, 1.0); вклинится другой эксперт. Нужна функция, которая захватит и запрет поток исполнения (то есть, дождется ресурса), а затем вернет контроль эксперту. Что-то вроде WaitForExclusive()

Хотя, возможно, дело и не в этом. Но ошибки сыплются, увы.

именно так. я поэтому и говорил про гипотетическую функцию GlobalVariableSetOnCondition, которая могла бы устанавливать глобальную переменную первым параметром при условии, что значение её равно значению второго параметра. так как доступ к глобальным переменным блокируется, то это даст "атомарность"

теперь про функцию IsStopped. она проверяет флаг остановки эксперта, для того, чтобы эксперт мог нормально завершиться (у него есть на это 2.5 секунды). рекомендуется использовать эту функцию в качестве одного из условий цикла, особенно бесконечного
 

именно так. я поэтому и говорил про гипотетическую функцию GlobalVariableSetOnCondition, которая могла бы устанавливать глобальную переменную первым параметром при условии, что значение её равно значению второго параметра. так как доступ к глобальным переменным блокируется, то это даст "атомарность"


Слава, хоть убейте, не понимаю я этот текст. Или другими словами как-нибудь объясните, или покажите, что имеете в виду. Если можно.

Кстати, что не так в переделанном мной куске кода? То есть, ясно, что что-то не так, так как не работает, но я не вижу ошибки. По моим прикидкам, это и должно было обеспечить эксклюзивный доступ...

while(!IsStopped())
{
	if(GlobalVariableGet(strTradeSemaphore) == 0.0)
		GlobalVariableSet(strTradeSemaphore, nMagic);

	if(GlobalVariableGet(strTradeSemaphore) == nMagic)
		break;
		
	Sleep(1000);
}
 

именно так. я поэтому и говорил про гипотетическую функцию GlobalVariableSetOnCondition, которая могла бы устанавливать глобальную переменную первым параметром при условии, что значение её равно значению второго параметра. так как доступ к глобальным переменным блокируется, то это даст "атомарность"


Слава, хоть убейте, не понимаю я этот текст. Или другими словами как-нибудь объясните, или покажите, что имеете в виду. Если можно.

речь идёт о предотвращении возможности вклинивания между вызовами функций GlobalVariableGet и GlobalVariableSet. вклинивание другим экспертом реально, так как ошибки всё равно наблюдаются. я потому и говорю про атомарный доступ. мы с Вами говорим о решении одной и той же проблемы только разными словами

Кстати, что не так в переделанном мной куске кода? То есть, ясно, что что-то не так, так как не работает, но я не вижу ошибки. По моим прикидкам, это и должно было обеспечить эксклюзивный доступ...

while(!IsStopped())
{
	if(GlobalVariableGet(strTradeSemaphore) == 0.0)
		GlobalVariableSet(strTradeSemaphore, nMagic);

	if(GlobalVariableGet(strTradeSemaphore) == nMagic)
		break;
		
	Sleep(1000);
}



Ваш пример получше будет
Причина обращения: