O que significa a entrada do diário de bordo

 
Quando tento fechar um negócio com um Expert Advisor, recebo (não é a primeira vez): Ping falhou
O que é isso e como lidar com isso?
Ao reiniciar a MT (condição de fechamento ainda é válida), o negócio é fechado com sucesso.

Não há erros no registro, a saída no arquivo, que coloquei literalmente através de uma linha, mostra que a ordem de envio funcionou, nenhum erro, mas aqui está o problema: a) a ordem na lista de aberta permaneceu e b) fechou no reinício da MT, portanto não só estava na lista, mas também na realidade.

Caso Meta queira reconciliar os logs com Alpari, conta 142605, bilhete 1728130

espero ainda obter uma resposta, este não é o meu primeiro post sobre este erro.
Cumprimentos,
Quark
 
Obrigado, vamos analisar o assunto.
Você pode me enviar um pedaço de log desde o momento do pedido até o momento em que o ping falhou (é importante verificar os horários de saída)? E isso está em conta real ou demo?
 
<br/ translate="no"> Obrigado, vamos analisar isso.
Você pode enviar um pedaço do registro desde o momento em que o pedido é feito até o recebimento do ping falhar (é importante verificar os horários de saída)? E isso está em uma conta real ou de demonstração?


Isto está em uma conta de demonstração. Log... Eu fechei e abri o MT, então a entrada da guia "log" foi atualizada. Vou copiá-lo da próxima vez, depois recomeçar, parece que vai demorar alguns dias, quero dizer, uma recorrência do problema. Só posso sugerir um registro do diretório de especialistas\logs. É isso que você tinha em mente?

No histórico da conta, esta transação corresponde à seguinte linha (a propósito, por que não há cópia linha por linha para fazer buffer nesta guia?)
1728130 2005.08.31 15:00 comprar 0.10 eurusd 1.2223 1.2183 0 2005.08.31 20:07 1.2330 0 107.00 Sexta-feira

Estou em Moscou, pode ser necessário na análise dos tempos de comércio.

Observe que o consultor especializado fechou o comércio às 20h07. Na verdade, a condição de fechamento foi às 20h01, mas a posição não foi fechada. Eu fechei e abri a MT, e às 20.07, ou seja, imediatamente, dentro de segundos após reiniciar a posição fechada.

Agora olhamos o tronco (o tronco inteiro), mas é de 147Kb. Eu o anexarei se você quiser, mas acredite, há apenas duas entradas para este negócio:

17:00:18 _Sexta-feira_Expert EURUSD,H1: abrir #1728130 comprar 0,10 EURUSD a 1,2223 sl: 1,2183 ok
...
22:07:24 _Sexta-feira_Expert EURUSD,H1: fechar #1728130 comprar 0,10 EURUSD a 1,2223 sl: 1,2183 ao preço 1,2330

Portanto, parece não haver nenhuma tentativa de fechar a posição a 20,01. "Mais ou menos" porque a) a aba "log" (eu não esperava que a MT a redefinisse) mostrou uma nota sobre a tentativa de ping e o fracasso e b) como este não é o primeiro problema com esta EA, veja como ela se parece por dentro:

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

		if(OrderMagicNumber() == nMagic)
		{
SaveComment("\r\n\t" + MathFloor(CurTime() / 3600) + " - " +
	MathFloor(OrderOpenTime() / 3600) + " >= " + nHoursToHold);

			int nCurHour = TimeHour(CurTime());
			int nOrderOpenHour = TimeHour(OrderOpenTime());
			if(nOrderOpenHour > nCurHour)
				nCurHour += 24;
			
			// if(MathFloor(CurTime() / 3600) - MathFloor(OrderOpenTime() / 3600) >= nHoursToHold)
			if(nCurHour - nOrderOpenHour >= nHoursToHold) 
			{
				if(OrderType() == OP_BUY)
				{
					CloseBuy("Friday");
SaveComment(", nbuy closed"); 
				}
				else if(OrderType() == OP_SELL)
				{
					CloseSell("Friday");
SaveComment(", sell closed");
				}
			}
		}
	}

...


void CloseBuy(string strExpertName)
{
	int nTicket = OrderTicket();
	SaveComment("\r\n\tAttempting to close long position, ticket: " + nTicket);
	
	int nResult = OrderClose(OrderTicket(), OrderLots(), Bid, nSlip, Aqua);
		
	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(strExpertName + ", error: " + nError);
	}
		
}

// ------

void CloseSell(string strExpertName)
{
	int nTicket = OrderTicket();
	SaveComment("\r\n\tAttempting to close short position, ticket: " + nTicket);
	
	int nResult = OrderClose(OrderTicket(), OrderLots(), Ask, nSlip, OrangeRed);
	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(strExpertName + ", error: " + nError);
	}

}
// ------



SaveComment apenas escreve texto em um arquivo.
Assim, todas as entradas no arquivo que eram apropriadas para tentativa de fechamento de posição apareceram, mas o alerta não foi chamado, ou seja, OrderClose devolveu o código de conclusão bem sucedida.


 
Portanto, como prometi, esperei por repetições de erros. Observe imediatamente que este erro já havia aparecido em outra EA, portanto provavelmente não é culpa do código (embora tudo possa ser). Mas aquele Expert Advisor não estava "pronto", no sentido de que não estava preenchido com todas as funções possíveis para sair para o arquivo.

Há um erro: o ping falhou no registro.

Talvez depois de um ping falhar, seu sistema não deva permitir que OrderSend seja executado, então uma mensagem de erro seria gerada.

Neste caso, não há mensagem de erro, apenas uma entrada de registro. O programa se comporta como se tivesse conseguido fechar o comércio, só que o comércio não está fechado.

Portanto, no log:
2005.09.05 16:01:35 TradeContext: ping falhou
2005.09.05 16:01:35 TradeContext: ping error
2005.09.05 16:01:14 '142605': fechar pedido #1775545 vender 0,10 EURUSD a 1,2535 sl: 0.0000 tp: 0.0000 ao preço 1.2542
2005.09.05 16:01:14 '142605': login (4.00, #27FFBBBD7)

A propósito, estou realmente me perguntando porque sl: 0.0000, eu não envio zero.

Ao mesmo tempo, a função de início é semelhante a esta:

int start()
{
	if(Bars < 5)
		return(0);
	
	Report("Friday", nMagic, bReportDone);

	// ------
	
	if(!IsBarEnd())
		return(0);
		
	CheckTradeSemaphore();
	
	// ------
	
	if(bUseMm == true)
	{
		dProfit = 0;
		
		for(int nCnt = 0; nCnt < HistoryTotal(); nCnt++)
		{
			OrderSelect(nCnt, SELECT_BY_POS, MODE_HISTORY);
			if(OrderMagicNumber() == nMagic && OrderType() <= OP_SELL)
			{
				dProfit += OrderProfit();
			}
		}
	}

	int nSignal = GetSignal();

SaveComment(Day() + "." + Month() + "." + Year() + " " + Hour() + ":" + Minute() + ":" + Seconds());
switch(nSignal)
{
	case -1: SaveComment(", Signal: none"); break;
	case OP_BUY: SaveComment(", Signal: buy"); break;
	case OP_SELL: SaveComment(", Signal: sell"); break;
	default: SaveComment(", Signal: ????"); break;
}

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

		if(OrderMagicNumber() == nMagic)
		{
SaveComment("\r\n\t" + MathFloor(CurTime() / 3600) + " - " +
	MathFloor(OrderOpenTime() / 3600) + " >= " + nHoursToHold);

			int nCurHour = TimeHour(CurTime());
			int nOrderOpenHour = TimeHour(OrderOpenTime());
			if(nOrderOpenHour > nCurHour)
				nCurHour += 24;
			
			// if(MathFloor(CurTime() / 3600) - MathFloor(OrderOpenTime() / 3600) >= nHoursToHold)
			if(nCurHour - nOrderOpenHour >= nHoursToHold) 
			{
				if(OrderType() == OP_BUY)
				{
					CloseBuy("Friday");
SaveComment(", buy closed"); 
				}
				else if(OrderType() == OP_SELL)
				{
					CloseSell("Friday");
SaveComment(", sell closed");
				}
			}
		}
	}

 	int nNumOfOpenedOrders = 0;
	for(nCnt = OrdersTotal() - 1; nCnt >= 0; nCnt--)
	{
		OrderSelect(nCnt, SELECT_BY_POS, MODE_TRADES);
		if(OrderMagicNumber() == nMagic)
			nNumOfOpenedOrders++;
	}

	if(nNumOfOpenedOrders == 0)
	{
		if(nSignal == OP_BUY) 
		{
SaveComment("\r\n\tAsk: " + Ask + ", StopLoss: " + dStopLoss + ", TakeProfit: " + dTakeProfit);
			Buy("Friday");
SaveComment("\r\n\tbuy opened");
		}
		else if(nSignal == OP_SELL) 
		{
SaveComment("\r\n\tBid: " + Bid + ", StopLoss: " + dStopLoss + ", TakeProfit: " + dTakeProfit);
			Sell("Friday");
SaveComment("\r\n\tsell opened");
		}
	}
SaveComment("\r\n");

	// ------
	
//	ModifyOrders();
	
	// ------
	
	if(!IsTesting())
		GlobalVariableSet(strTradeSemaphore, 0.0);	

	// ------
		
	return(0);
}



SaveComment é uma função que permite a saída da cadeia de caracteres para um arquivo.

Aqui está a função de posição próxima chamada desde o início. Como você pode ver, ele tenta fechar a posição 5 vezes (eu fiz isso apenas para fins de teste), e se nenhum código de erro for devolvido (ou seja, MT acha que a posição está fechada), ele procura entre as ordens ainda em aberto por aquela que tem o bilhete necessário.

void CloseSell(string strExpertName)
{
	int nTicket = OrderTicket();
	SaveComment("\r\n\tAttempting to close short position, ticket: " + nTicket);
	
	for(int nTry = 0; nTry < 5; nTry++)
	{
		int nResult = OrderClose(OrderTicket(), OrderLots(), Ask, nSlip, OrangeRed);
		if(nResult == -1)
		{
			int nError = GetLastError();
			Alert(strExpertName + ", error: " + nError);
		}
		
		bool bClosed = true;
		for(int nOrderNo = OrdersTotal() - 1; nOrderNo >= 0; nOrderNo--)
		{
			OrderSelect(nOrderNo, SELECT_BY_POS, MODE_TRADES);
			if(OrderTicket() == nTicket)
			{
				bClosed = false;
				break;
			}
		}
		
		if(bClosed == true)
		{
			SaveComment("\r\n\tNo more orders with this ticket No");
			break;
		}
		else
			SaveComment("\r\n\tOrder with this ticket still present, trying again");
	}
}



O registro abaixo mostra que todas as 5 tentativas de fechar uma ordem falharam (o bilhete não desapareceu), com a MT acreditando que a posição está fechada.


5.9.2005 14:1:29, Sinal: nenhum
312758.00000000 - 312754.00000000 >= 4
Tentando fechar posição curta, bilhete: 1775545
Encomendar com este bilhete ainda presente, tentando novamente
Encomendar com este bilhete ainda presente, tentando novamente
Encomendar com este bilhete ainda presente, tentando novamente
Encomendar com este bilhete ainda presente, tentando novamente, vendendo fechado

Nota: não tenha medo do "Sinal: nenhum" - deve ser assim. Este é um sinal para abrir uma nova posição. O sinal para fechar uma posição é gerado se a desigualdade "312758.00000000 - 312754.00000000 >= 4" for atendida


Prezados desenvolvedores!
Espero muito sinceramente que possamos curar este problema juntos.

Quark

P.S. Como sempre, reiniciando o MT, recebo o fechamento da posição pela EA, sem problemas de k.l.

 
Ainda aguardando a resposta dos desenvolvedores.
Acrescentei resultados de escrita de código a um arquivo ao tentar abrir - fechar um negócio em todos os meus EAs. O resultado é decepcionante. Aproximadamente cada vez, para todos os EAs, uma tentativa de abrir - fechar um pedido não é suficiente. Em média, são necessárias duas (ver código acima, há um ciclo de cinco tentativas). Às vezes, cinco tentativas não são suficientes. Ao mesmo tempo, a MT funciona como se o pedido fosse aberto com sucesso - fechado, nenhuma mensagem de erro é dada.

Todos os semáforos sugeridos no ramo "Erro número 6" (que, a propósito, ainda acontece às vezes), eu uso, mais o temporizador dos Expert Advisors garante que cada EA começa em seus 10 segundos dedicados, ou seja, não deve haver conflitos entre as EA.

Sugiro que outros desenvolvedores usem o código abaixo em EAs ao vivo para verificar se todos os seus pedidos funcionam da maneira que você espera. De um ponto de vista comercial, é apenas um OrderSend normal, cercado de funções para produzir para um arquivo.

Sem ofensa, mas parece que a MT precisa afinar a interação com o servidor comercial.

double GetLotSize(double dInitFraction = 0.1, double dProfitFraction = 0.1)
{
	double dLot = 0.1;
	
	if(bUseMm)
	{
		dLot  = (dInitFraction * dInitAmount + dProfitFraction * dProfit) / 1000;

		dLot = MathFloor(dLot * 10) / 10;
	
		if(dLot < 0.1)
			dLot = 0.1;
	}
	
	return(dLot);
}

// ------

void Sell(string strExpertName)
{
	dLotSize = GetLotSize();
	
	if(AccountFreeMargin() < dLotSize * dInitAmount || AccountFreeMargin() < 500)
		return;

	double dTp;
	if(dTakeProfit == 0)
		dTp = 0;
	else
		dTp = Bid - dTakeProfit;

	int nResult;
	for(int nTry = 0; nTry < 5; nTry++)
	{
		SaveComment("Trying to sell, attempt " + nTry + "\r\n");
		
		nResult = OrderSend(Symbol(), OP_SELL, dLotSize, Bid, nSlip, Bid + dStopLoss, 
			dTp, strExpertName, nMagic, 0, OrangeRed);
		
		if(nResult != -1)
		{
			SaveComment(" successfull\r\n");
			break;
		}
		else
			SaveComment(" failed, error " + GetLastError() + "\r\n");
	}	
	
	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(strExpertName + " sell error: " + nError + "\r\n" +
			Bid + ", " + dStopLoss + ", " + dTp);
		SaveComment(strExpertName + " sell error: " + nError + "\r\n" +
			Bid + ", " + dStopLoss + ", " + dTp);
	}
}

// ------

void Buy(string strExpertName)
{
	dLotSize = GetLotSize();
	
	if(AccountFreeMargin() < dLotSize * dInitAmount || AccountFreeMargin() < 500)
		return;

	double dTp;
	if(dTakeProfit == 0)
		dTp = 0;
	else
		dTp = Ask + dTakeProfit;

	int nResult;
	for(int nTry = 0; nTry < 5; nTry++)
	{
		SaveComment("Trying to buy, attempt " + nTry);
		
		nResult = OrderSend(Symbol(), OP_BUY, dLotSize, Ask, nSlip, Ask - dStopLoss, 
			dTp, strExpertName, nMagic, 0, Aqua);

		if(nResult != -1)
		{
			SaveComment(" successfull\r\n");
			break;
		}
		else
			SaveComment(" failed, error " + GetLastError() + "\r\n");
	}	

	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(strExpertName + " buy error: " + nError + "\r\n" +
			Ask + ", " + dStopLoss + ", " + dTp);

		SaveComment(strExpertName + " buy error: " + nError + "\r\n" +
			Ask + ", " + dStopLoss + ", " + dTp);
	}
}

// ------

void CloseBuy(string strExpertName)
{
	int nTicket = OrderTicket();
	SaveComment("\r\n\tAttempting to close long position, ticket: " + nTicket);
	
	for(int nTry = 0; nTry < 5; nTry++)
	{
		int nResult = OrderClose(OrderTicket(), OrderLots(), Bid, nSlip, Aqua);
		
		if(nResult == -1)
		{
			int nError = GetLastError();
			Alert(strExpertName + ", error: " + nError);
		}
		
		bool bClosed = true;
		for(int nOrderNo = OrdersTotal() - 1; nOrderNo >= 0; nOrderNo--)
		{
			OrderSelect(nOrderNo, SELECT_BY_POS, MODE_TRADES);
			if(OrderTicket() == nTicket)
			{
				bClosed = false;
				break;
			}
		}
		
		if(bClosed == true)
		{
			SaveComment("\r\n\tNo more orders with this ticket No");
			break;
		}
		else
			SaveComment("\r\n\tOrder with this ticket still present, trying again");
	}
}

// ------

void CloseSell(string strExpertName)
{
	int nTicket = OrderTicket();
	SaveComment("\r\n\tAttempting to close short position, ticket: " + nTicket);
	
	for(int nTry = 0; nTry < 5; nTry++)
	{
		int nResult = OrderClose(OrderTicket(), OrderLots(), Ask, nSlip, OrangeRed);
		if(nResult == -1)
		{
			int nError = GetLastError();
			Alert(strExpertName + ", error: " + nError);
		}
		
		bool bClosed = true;
		for(int nOrderNo = OrdersTotal() - 1; nOrderNo >= 0; nOrderNo--)
		{
			OrderSelect(nOrderNo, SELECT_BY_POS, MODE_TRADES);
			if(OrderTicket() == nTicket)
			{
				bClosed = false;
				break;
			}
		}
		
		if(bClosed == true)
		{
			SaveComment("\r\n\tNo more orders with this ticket No");
			break;
		}
		else
			SaveComment("\r\n\tOrder with this ticket still present, trying again");
	}
}

// ------

void SaveComment(string strComment)
{
	if(!IsTesting())
	{
		int hFile = FileOpen("__test_" + strExpert + "_" + Symbol() + ".txt", 
			FILE_BIN | FILE_READ | FILE_WRITE, '\t');	
	
		FileSeek(hFile, 0, SEEK_END);
		FileWriteString(hFile, strComment, StringLen(strComment));
		// FileFlush(hFile);
	
		FileClose(hFile);
	}
}

// ------



 
Talvez seus EAs abram/fechem negócios com demasiada freqüência. Eu passei especificamente pela história das transações (tenho 8 EAs pendurados) e tenho uma contagem de vezes quando há mais de uma transação em um minuto (não mais de 10), todas elas são bem sucedidas. É verdade, os EAs trabalham em aberturas de bares em 1H, 4H, D1 e timeouts são inseridos em todos os lugares, mas timeouts são inseridos apenas entre negócios de um EA (na verdade eu não preciso deles), nenhum semáforo entre EAs.
Então preciso encontrar o limite do intervalo permissível na conta demo.
 
Também tenho 8 EAs pendurados neste momento, todos na M5.
De 00:00 às 12:00
comércios - 141
3 erros ("1" e dois "6").

Quark, você pode me enviar um e-mail com komposterius arruinar a última versão do seu EA (que está no M1)? Vou pendurar mais 8 janelas - veja o que acontece ;)
 
Vocês não estão percebendo o ponto principal. NÃO tenho especialistas de minuto. Todas as negociações estão em dia. Eu NÃO tenho negócios freqüentes, um por hora, no máximo.

Especialistas esperam (usando semáforos) por uma fila, além disso, o EA com número mágico igual a, por exemplo, 10, espera 10 * 10 = 100 segundos do início de um bar, e só então ele negocia. Portanto, as chances de encontrar um EA com o mágico 11 estão próximas de 0, mesmo sem sem semáforos.

A impressão é que se a MT falhar uma vez (ping falhou, erro 6, etc.) algo dá errado em seu sistema e as negociações subseqüentes deste EA falham.

Exemplo de um registro (código mostrado acima):

Tentando comprar, tentativa 0 falhou, erro 6
Tentando comprar, tentativa 1 falhou, erro 129
Tentando comprar, tentativa 2 falhou, erro 129
Tentando comprar, tentativa 3 falhou, erro 129
Tentando comprar, tentativa 4 falhou, erro 129
Erro de compra em ziguezague: 4050
2.28000000, 0.02700000, 0.00000000

O que temos aqui? Primeiro houve uma falha (no log - erro de conexão com o servidor). Depois 5 tentativas (tenho 5 em meu laço) dão 129 - preço errado. Abaixo está o preço - bastante normal. Após reiniciar a MT a este preço, o pedido foi aberto com sucesso. Então recebemos 4050, número errado de argumentos. Isto é de uma função que funciona bem em outras chamadas. Há uma clara falha no sistema de comunicação de erros.

Citando um especialista, embora eu suspeite que você tenha que ter muitos deles para que o problema ocorra com freqüência. Esperamos que o compositor, Roche e os desenvolvedores analisem o código e aconselhem algo. Ainda assim, acho que é uma questão de MT aqui.

Especialista:
extern double dZigzagSize;
extern int nMa1;
extern int nMa2;
extern int nBuySell;

// ------

double dTrailingStop;
double dStopLoss;
double dTakeProfit;

bool bUseMm = false;

string strExpert = "Zigzag";

// ------

#include "mylib.mq4"

// ------

int init ()
{
	nBars = 0;//Bars;
	if(!IsTesting() && !GlobalVariableCheck(strTradeSemaphore))
		GlobalVariableSet(strTradeSemaphore, 0.0);

	// ------

	if(IsTesting() && nMa1 >= nMa2)
		return(-1);

	if(Symbol() == "EURUSD" && Period() == 60)
	{
		if(!IsTesting())
		{
			dZigzagSize = 210; 					// 210,60,108,3: 2397, 614
			nMa1 = 48;							// 210,48,120,1: 2016, 332
			nMa2 = 120;

			nBuySell = 1;
		}

		nMagic = 23;
	}
	else if(Symbol() == "EURJPY" && Period() == 60)
	{
		if(!IsTesting())
		{										// 240,24,132,1: 1987, 387
			dZigzagSize = 240; 					
			nMa1 = 24;							
			nMa2 = 132;

			nBuySell = 3;
		}										
												
		nMagic = 2;
	}
	else if(Symbol() == "USDCHF" && Period() == 60)
	{
		if(!IsTesting())
		{										// 260,36,204,2: 2219, 262
			dZigzagSize = 260; 					
			nMa1 = 36;							 
			nMa2 = 204;
			
			nBuySell = 2;
		}										
												

		nMagic = 3;
	}
	else if(Symbol() == "GBPUSD" && Period() == 60)
	{
		if(!IsTesting())
		{										// 270,48,84,3: 5515, 679
			dZigzagSize = 270; 					
			nMa1 = 48;							
			nMa2 = 84;							
			
			nBuySell = 3;
		}										

		nMagic = 4;
	}
	else if(Symbol() == "GBPCHF" && Period() == 60)
	{
		if(!IsTesting())
		{										// 270,96,108,1: 2854,292
			dZigzagSize = 270; 					
			nMa1 = 96;							
			nMa2 = 108;

			nBuySell = 1;
		}				
						
		nMagic = 5;
	}
	else if(Symbol() == "USDCAD" && Period() == 60)
	{
		if(!IsTesting())
		{										// 220,60,300: 1906, 213
			dZigzagSize = 220; 					
			nMa1 = 60;							  
			nMa2 = 300;

			nBuySell = 2;
		}				
						
		nMagic = 7;
	}
	else if(Symbol() == "EURAUD" && Period() == 60)
	{
		if(!IsTesting())
		{										// 210,24,36,3: 3921, 545
			dZigzagSize = 230; 					// 230,24,60,3: 3397, 453
			nMa1 = 24;							// 230,24,132,3: 2819, 292 
			nMa2 = 60;
			
			nBuySell = 3;
		}			

		nMagic = 9;
	}
	
	dStopLoss = dZigzagSize * Point;
	dTrailingStop = dZigzagSize * Point;
	
	dTakeProfit = 0;
	
	return(0);
}
//////////////////
int deinit()
{
	if(!IsTesting())
		GlobalVariableSetOnCondition(strTradeSemaphore, 0.0, nMagic);
	return(0);
}
////////////////////
int start()
{
	if(Bars < MathMax(nMa1, nMa2))
		return(0);

	if(IsTesting() && nMa1 >= nMa2)
		return(0);

	Report("Zigzag", nMagic, bReportDone);

	// ------

	if(!IsBarEnd())
		return(0);

	CheckTradeSemaphore();

	// ------

	int nSignal = 0;
	double dMa1;
	double dMa2;
	
	nSignal = iCustom(NULL, 0, "_Zigzag_Ind", dZigzagSize, 0, 1);
		
	dMa1 = iMA(NULL, 0, nMa1, 0, MODE_EMA, PRICE_CLOSE, 1);
	dMa2 = iMA(NULL, 0, nMa2, 0, MODE_EMA, PRICE_CLOSE, 1);

	if(bUseMm == true)
	{
		dProfit = 0;
		
		for(int nCnt = 0; nCnt < HistoryTotal(); nCnt++)
		{
			OrderSelect(nCnt, SELECT_BY_POS, MODE_HISTORY);
			if(OrderMagicNumber() == nMagic && OrderType() <= OP_SELL)
			{
				dProfit += OrderProfit();
			}
		}   
 	}

	for(nCnt = OrdersTotal() - 1; nCnt >= 0; nCnt--)
	{
		OrderSelect(nCnt, SELECT_BY_POS, MODE_TRADES);
		if(OrderMagicNumber() == nMagic)
		{
			int nMode = OrderType(); 
	
			if(nMode == OP_BUY && nSignal == 1)
			{
				CloseBuy("Zigzag");
				break;
			}
			else if(nMode == OP_SELL && nSignal == -1)
			{		
				CloseSell("Zigzag");
				break;					
	    	}
		}
	}

 	int nNumOfOpenedOrders = 0;
	for(nCnt = OrdersTotal() - 1; nCnt >= 0; nCnt--)
	{
		OrderSelect(nCnt, SELECT_BY_POS, MODE_TRADES);
		if(OrderMagicNumber() == nMagic)
			nNumOfOpenedOrders++;
	}

	if(!nNumOfOpenedOrders)
	{
		if(nSignal == -1 && dMa1 >= dMa2)
		{
			if(nBuySell == 1 || nBuySell == 3)
				Buy("Zigzag");
		}
		else if((nSignal == 1 && dMa1 <= dMa2))
		{
			if(nBuySell == 2 || nBuySell == 3)
				Sell("Zigzag");
		}
	}

	// ------
	
	ModifyOrders();	
	
	// ------
	
	if(!IsTesting())
		GlobalVariableSet(strTradeSemaphore, 0.0);	

	// ------

	return(0);
}

// ------



Indicador:

#property copyright "Quark"
#property link      ""

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
#property indicator_minimum -1
#property indicator_maximum 1

// indicator parameters
extern int nMinMaxPoints = 50;

// indicator buffers
double arrExtMapBuffer[];

int nExtCountedBars = 0;

int nLastMinMaxBar;
int nLastMinMaxType;

double dLastMin, dLastMax;

////////////////////////
int init()
{
	string strIndicatorShortName;

	// drawing settings
	SetIndexStyle(0, DRAW_HISTOGRAM);
	SetIndexShift(0, 0);
	SetIndexEmptyValue(0,0.0);
		
	IndicatorDigits(4);
		
	strIndicatorShortName = "Zigzag(" + nMinMaxPoints + ")";  
	IndicatorShortName(strIndicatorShortName);

	// indicator buffers mapping
	SetIndexBuffer(0, arrExtMapBuffer);

	dLastMin = Low[Bars - 1];
	dLastMax = High[Bars - 1];

	nLastMinMaxBar = Bars - 1;
	nLastMinMaxType = 0;

	int nPos = Bars - 1;
	int nLastPos = nPos;

	while(nPos >= 0)	// Looking for a first min or max
	{
		if(dLastMax <= High[nPos])
		{
			dLastMax = High[nPos];
			nLastMinMaxBar = nPos;
		}

		if(dLastMin >= Low[nPos])
		{
			dLastMin = Low[nPos];
			nLastMinMaxBar = nPos;
		}

		if(Low[nPos] < dLastMax - nMinMaxPoints * Point)	// Maximum found
		{
			nLastMinMaxType = 1;
			dLastMin = Low[nPos];
			dLastMax = High[nPos];
			nLastMinMaxBar = nPos;
		
			break;
		}
		else if(High[nPos] > dLastMin + nMinMaxPoints * Point)	// Minimum found
		{
			nLastMinMaxType = -1;
			dLastMax = High[nPos];
			dLastMin = Low[nPos];
			nLastMinMaxBar = nPos;
			
			break;			
		}

		nPos--;
	}

	return(0);
}
////////////////////
int start()
{
	nExtCountedBars = IndicatorCounted();
	if(nExtCountedBars < 0) 
		return(-1);

	// last counted bar will be recounted
	if(nExtCountedBars > 0) 
		nExtCountedBars--;

	Zigzag();  

	return(0);
}
///////////////////
void Zigzag()
{
	int nPos = Bars - nExtCountedBars - 2;

	while(nPos > 0)
	{
		arrExtMapBuffer[nPos] = 0.0;
		
		double dLastMaxTmp = dLastMax;
		double dLastMinTmp = dLastMin;
		
		if(nLastMinMaxType != 1)	// Expecting maximum
		{
			if(dLastMax <= High[nPos])
			{
				dLastMax = High[nPos];
				nLastMinMaxBar = nPos;
			}
			
			if(Low[nPos] < dLastMax - nMinMaxPoints * Point)	// Maximum found
			{
				if(High[nPos] - Low[nPos] <= nMinMaxPoints * Point)
				{
					arrExtMapBuffer[nPos] = 1;//High[nLastMinMaxBar];
					nLastMinMaxType = 1;
					dLastMin = Low[nPos];
					dLastMax = High[nPos];
					nLastMinMaxBar = nPos;
				}
				else
				{
					arrExtMapBuffer[nPos] = 0;
					arrExtMapBuffer[nPos + 1] = 0;
					dLastMax = dLastMaxTmp;
					dLastMin = dLastMinTmp;
				}
			}
		}
		
		if(nLastMinMaxType != -1)	// Expecting minimum
		{
			if(dLastMin >= Low[nPos])
			{
				dLastMin = Low[nPos];
				nLastMinMaxBar = nPos;
			}
			
			if(High[nPos] > dLastMin + nMinMaxPoints * Point)	// Maximum found
			{
				if(High[nPos] - Low[nPos] <= nMinMaxPoints * Point)
				{
					arrExtMapBuffer[nPos] = -1;//Low[nLastMinMaxBar];
					nLastMinMaxType = -1;
					dLastMax = High[nPos];
					dLastMin = Low[nPos];
					nLastMinMaxBar = nPos;
				}
				else
				{
					arrExtMapBuffer[nPos] = 0;
					arrExtMapBuffer[nPos + 1] = 0;
					dLastMax = dLastMaxTmp;
					dLastMin = dLastMinTmp;
				}
			}
		}

		nPos--;
	}
}
///////////////////
/*

if(IsTesting())
{
	FileDelete("__zigzag_test.txt"); 
	hFile = FileOpen("__zigzag_test.txt", FILE_BIN | FILE_WRITE, '\t');	
}

void SaveComment(string strComment)
{
	if(IsTesting())
	{
		FileWriteString(hFile, strComment, StringLen(strComment));
	}
}

if(IsTesting())
	FileClose(hFile);
*/



O arquivo da biblioteca, deve estar no diretório Expert:

double dTp = 0;

//double dStop;

datetime timePrev = 0;
int nBars;
int nDelaySeconds = 10;

int nSlip = 5;

double dProfit = 0;
double dInitAmount = 1000;
double dLotSize = 0.1;

int nMagic = 0;
bool bReportDone = false;

string strTradeSemaphore = "TradeSemaphore";

// ------

void Report(string strFileName, int nMagic, bool& bReportDone)
{
	if(IsTesting())
		return;
	if(Hour() == 0 && Minute() >= nMagic / 2 && IsTesting() == false)
	{
		if(bReportDone == false)
		{
			int hFile = FileOpen(strFileName + "_" + Symbol() + "_" + Period() + ".rpt", 
				FILE_BIN | FILE_WRITE, ',');
			
			string str = "CloseDateTime,Buy,Sell\r\n";
			FileWriteString(hFile, str, StringLen(str)); 

			for(int nCnt = 0; nCnt < HistoryTotal(); nCnt++)
			{
				OrderSelect(nCnt, SELECT_BY_POS, MODE_HISTORY);	
				if(OrderMagicNumber() == nMagic && OrderType() <= OP_SELL && OrderSymbol() == Symbol())
				{
					str = TimeToStr(OrderCloseTime(), TIME_DATE|TIME_MINUTES);
					
					if(OrderType() == OP_BUY)
						str = str + "," + OrderProfit() + ",0";
					else
						str = str + ",0," + OrderProfit();
					
					str = str + "\r\n";
					
					FileWriteString(hFile, str, StringLen(str));
				}
			}			

			FileFlush(hFile); 
			FileClose(hFile); 
			
			bReportDone = true;
		}
	}
	else if(Hour() != 0)
		bReportDone = false;
}

// ------

double GetLotSize(double dInitFraction = 0.1, double dProfitFraction = 0.1)
{
	double dLot = 0.1;
	
	if(bUseMm)
	{
		dLot  = (dInitFraction * dInitAmount + dProfitFraction * dProfit) / 1000;

		dLot = MathFloor(dLot * 10) / 10;
	
		if(dLot < 0.1)
			dLot = 0.1;
	}
	
	return(dLot);
}

// ------

void Sell(string strExpertName)
{
	dLotSize = GetLotSize();
	
	if(AccountFreeMargin() < dLotSize * dInitAmount || AccountFreeMargin() < 500)
		return;

	double dTp;
	if(dTakeProfit == 0)
		dTp = 0;
	else
		dTp = Bid - dTakeProfit;

	int nResult;
	for(int nTry = 0; nTry < 5; nTry++)
	{
		SaveComment(Day() + "." + Month() + "." + Year() + " " + Hour() + ":" + Minute() + ":" + Seconds());
		SaveComment(" Trying to sell, attempt " + nTry + "\r\n");
		SaveComment("Ask: " + Ask + ", StopLoss: " + dStopLoss + ", TakeProfit: " + dTakeProfit + "\r\n");
		
		nResult = OrderSend(Symbol(), OP_SELL, dLotSize, Bid, nSlip, Bid + dStopLoss, 
			dTp, strExpertName, nMagic, 0, OrangeRed);
		
		if(nResult != -1)
		{
			SaveComment(" successfull\r\n");
			break;
		}
		else
			SaveComment(" failed, error " + GetLastError() + "\r\n");
	}	
	
	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(strExpertName + " sell error: " + nError + "\r\n" +
			Bid + ", " + dStopLoss + ", " + dTp);
		SaveComment(strExpertName + " sell error: " + nError + "\r\n" +
			Bid + ", " + dStopLoss + ", " + dTp);
	}
}

// ------

void Buy(string strExpertName)
{
	dLotSize = GetLotSize();
	
	if(AccountFreeMargin() < dLotSize * dInitAmount || AccountFreeMargin() < 500)
		return;

	double dTp;
	if(dTakeProfit == 0)
		dTp = 0;
	else
		dTp = Ask + dTakeProfit;

	int nResult;
	for(int nTry = 0; nTry < 5; nTry++)
	{
		SaveComment(Day() + "." + Month() + "." + Year() + " " + Hour() + ":" + Minute() + ":" + Seconds());
		SaveComment(" Trying to buy, attempt " + nTry + "\r\n");
		SaveComment("Bid: " + Bid + ", StopLoss: " + dStopLoss + ", TakeProfit: " + dTakeProfit);
		
		nResult = OrderSend(Symbol(), OP_BUY, dLotSize, Ask, nSlip, Ask - dStopLoss, 
			dTp, strExpertName, nMagic, 0, Aqua);

		if(nResult != -1)
		{
			SaveComment(" successfull\r\n");
			break;
		}
		else
			SaveComment(" failed, error " + GetLastError() + "\r\n");
	}	

	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(strExpertName + " buy error: " + nError + "\r\n" +
			Ask + ", " + dStopLoss + ", " + dTp);

		SaveComment(strExpertName + " buy error: " + nError + "\r\n" +
			Ask + ", " + dStopLoss + ", " + dTp);
	}
}

// ------

void ModifyOrders()
{
	for(int nCnt = 0; nCnt < OrdersTotal(); nCnt++)
	{
		OrderSelect(nCnt, SELECT_BY_POS, MODE_TRADES);
		if(OrderMagicNumber() == nMagic)
		{
			if(OrderType() == OP_BUY)
			{
				if(OrderStopLoss() < Bid - dTrailingStop - 5 * Point)
				{
					OrderModify(OrderTicket(), OrderOpenPrice(), 
						Bid - dTrailingStop, OrderTakeProfit(), 0, Aqua);

					break;
				}
			}
			
			if(OrderType() == OP_SELL)
			{
				if(OrderStopLoss() > Ask + dTrailingStop + 5 * Point)
				{
					OrderModify(OrderTicket(), OrderOpenPrice(), 
						Ask + dTrailingStop, OrderTakeProfit(), 0, OrangeRed);

					break;
				}
			}
		}
	}
}

// ------
/*
void ModifyOrders(double dTrailingConvergence = 1)
{
	for(int nCnt = 0; nCnt < OrdersTotal(); nCnt++)
	{
		OrderSelect(nCnt, SELECT_BY_POS, MODE_TRADES);
		if(OrderMagicNumber() == nMagic)
		{
			if(dTrailingConvergence != 1)
			{
				dStop *= dTrailingConvergence;
				dStop = NormalizeDouble(dStop, MarketInfo(Symbol(), MODE_DIGITS));
				if(dStop < 10 * Point)
					dStop = 10 * Point;			
			}

			if(OrderType() == OP_BUY)
			{
				if(OrderStopLoss() < Bid - dStop - 5 * Point)
				{
					OrderModify(OrderTicket(), OrderOpenPrice(), 
						Bid - dStop, OrderTakeProfit(), 0, Aqua);

					break;
				}
			}
			
			if(OrderType() == OP_SELL)
			{
				if(OrderStopLoss() > Ask + dStop + 5 * Point)
				{
					OrderModify(OrderTicket(), OrderOpenPrice(), 
						Ask + dStop, OrderTakeProfit(), 0, OrangeRed);

					break;
				}
			}
		}
	}
}
*/
// ------

bool IsBarEnd()
{
	bool bIsBarEnd = false;
	if(nBars != Bars)
	{
		if(IsTesting() || (!IsTesting() && CurTime() > Time[0] + nMagic * nDelaySeconds))
		{
			bIsBarEnd = true;
			nBars = Bars;
		}
	}
	
	return(bIsBarEnd);
}

// ------

void CheckTradeSemaphore()
{
	if(!IsTesting())
	{
//		int n = 1;
		while(!IsStopped())
		{
			GlobalVariableSetOnCondition(strTradeSemaphore, nMagic, 0.0);
//			if(GlobalVariableGet(strTradeSemaphore) == 0.0)
//				GlobalVariableSet(strTradeSemaphore, nMagic);

			if(GlobalVariableGet(strTradeSemaphore) == nMagic)
				break;

//			Comment(GlobalVariableGet(strTradeSemaphore) + ": " + n);
//			n++;
		
			Sleep(1000);
		}
	
		RefreshRates();
	}
}

// ------
/*
void CloseBuy(string strExpertName)
{
	int nResult = OrderClose(OrderTicket(), OrderLots(), Bid, nSlip, Aqua);
	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(strExpertName + nError);
	}
}

// ------

void CloseSell(string strExpertName)
{
	int nResult = OrderClose(OrderTicket(), OrderLots(), Ask, nSlip, OrangeRed);
	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert("Noc_1 close: " + nError);
	}
}
*/
// ------

void CloseBuy(string strExpertName)
{
	int nTicket = OrderTicket();
	SaveComment("\r\n\tAttempting to close long position, ticket: " + nTicket + "\r\n");
	
	for(int nTry = 0; nTry < 5; nTry++)
	{
		SaveComment(Day() + "." + Month() + "." + Year() + " " + Hour() + ":" + Minute() + ":" + Seconds());
		int nResult = OrderClose(OrderTicket(), OrderLots(), Bid, nSlip, Aqua);
		
		if(nResult == -1)
		{
			int nError = GetLastError();
			Alert(strExpertName + ", error: " + nError);
		}
		
		bool bClosed = true;
		for(int nOrderNo = OrdersTotal() - 1; nOrderNo >= 0; nOrderNo--)
		{
			OrderSelect(nOrderNo, SELECT_BY_POS, MODE_TRADES);
			if(OrderTicket() == nTicket)
			{
				bClosed = false;
				break;
			}
		}
		
		if(bClosed == true)
		{
			SaveComment("\r\n\tNo more orders with this ticket No");
			break;
		}
		else
			SaveComment("\r\n\tOrder with this ticket still present, trying again");
	}
}

// ------

void CloseSell(string strExpertName)
{
	int nTicket = OrderTicket();
	SaveComment("\r\n\tAttempting to close short position, ticket: " + nTicket + "\r\n");
	
	for(int nTry = 0; nTry < 5; nTry++)
	{
		SaveComment(Day() + "." + Month() + "." + Year() + " " + Hour() + ":" + Minute() + ":" + Seconds());
		int nResult = OrderClose(OrderTicket(), OrderLots(), Ask, nSlip, OrangeRed);
		if(nResult == -1)
		{
			int nError = GetLastError();
			Alert(strExpertName + ", error: " + nError);
		}
		
		bool bClosed = true;
		for(int nOrderNo = OrdersTotal() - 1; nOrderNo >= 0; nOrderNo--)
		{
			OrderSelect(nOrderNo, SELECT_BY_POS, MODE_TRADES);
			if(OrderTicket() == nTicket)
			{
				bClosed = false;
				break;
			}
		}
		
		if(bClosed == true)
		{
			SaveComment("\r\n\tNo more orders with this ticket No");
			break;
		}
		else
			SaveComment("\r\n\tOrder with this ticket still present, trying again");
	}
}

// ------

void SaveComment(string strComment)
{
	if(!IsTesting())
	{
		int hFile = FileOpen("__test_" + strExpert + "_" + Symbol() + ".txt", 
			FILE_BIN | FILE_READ | FILE_WRITE, '\t');	
	
		FileSeek(hFile, 0, SEEK_END);
		FileWriteString(hFile, strComment, StringLen(strComment));
		// FileFlush(hFile);
	
		FileClose(hFile);
	}
}

// ------

 
Você realmente me intrigou, Quark :)
É hora de os desenvolvedores pensarem em um trabalho para você na equipe para encontrá-los com todo tipo de maldade.
Talvez seja o ping, eu não tenho ciclos para tentar novamente fazer pedidos, talvez eu devesse chamar o Refresh neste ponto e colocar preços mais frescos.
Eu me perco ...:)
 
Bem, você finalmente ficou intrigado, Quark :)<br / translate="no"> É hora de os desenvolvedores pensarem em uma vaga para você no pessoal para encontrá-los de todos os tipos de malandragem.
Talvez seja o ping, eu não tenho ciclos para tentar novamente fazer pedidos, talvez eu precise chamar o Refresh neste ponto e colocar preços mais frescos.
Eu estou me perdendo ...:)


Boa idéia... Faremos agora...
 
Uma nova edição, com um lançamento da Roche:
void Sell(string strExpertName)
{
	dLotSize = GetLotSize();
	
	if(AccountFreeMargin() < dLotSize * dInitAmount || AccountFreeMargin() < 500)
		return;

	double dTp;
	if(dTakeProfit == 0)
		dTp = 0;
	else
		dTp = Bid - dTakeProfit;

	int nResult;
	for(int nTry = 0; nTry < 5; nTry++)
	{
		SaveComment(Day() + "." + Month() + "." + Year() + " " + Hour() + ":" + Minute() + ":" + Seconds());
		SaveComment(" Trying to sell, attempt " + nTry + "\r\n");
		SaveComment("Ask: " + Ask + ", StopLoss: " + dStopLoss + ", TakeProfit: " + dTakeProfit + "\r\n");
		
		nResult = OrderSend(Symbol(), OP_SELL, dLotSize, Bid, nSlip, Bid + dStopLoss, 
			dTp, strExpertName, nMagic, 0, OrangeRed);
		
		if(nResult != -1)
		{
			SaveComment(" successfull\r\n");
			break;
		}
		else
		{
			SaveComment(" failed, error " + GetLastError() + "\r\n");
			RefreshRates();
		}
	}	
	
	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(strExpertName + " sell error: " + nError + "\r\n" +
			Bid + ", " + dStopLoss + ", " + dTp);
		SaveComment(strExpertName + " sell error: " + nError + "\r\n" +
			Bid + ", " + dStopLoss + ", " + dTp);
	}
}

// ------

void Buy(string strExpertName)
{
	dLotSize = GetLotSize();
	
	if(AccountFreeMargin() < dLotSize * dInitAmount || AccountFreeMargin() < 500)
		return;

	double dTp;
	if(dTakeProfit == 0)
		dTp = 0;
	else
		dTp = Ask + dTakeProfit;

	int nResult;
	for(int nTry = 0; nTry < 5; nTry++)
	{
		SaveComment(Day() + "." + Month() + "." + Year() + " " + Hour() + ":" + Minute() + ":" + Seconds());
		SaveComment(" Trying to buy, attempt " + nTry + "\r\n");
		SaveComment("Bid: " + Bid + ", StopLoss: " + dStopLoss + ", TakeProfit: " + dTakeProfit);
		
		nResult = OrderSend(Symbol(), OP_BUY, dLotSize, Ask, nSlip, Ask - dStopLoss, 
			dTp, strExpertName, nMagic, 0, Aqua);

		if(nResult != -1)
		{
			SaveComment(" successfull\r\n");
			break;
		}
		else
		{
			SaveComment(" failed, error " + GetLastError() + "\r\n");
			RefreshRates();
		}
	}	

	if(nResult == -1)
	{
		int nError = GetLastError();
		Alert(strExpertName + " buy error: " + nError + "\r\n" +
			Ask + ", " + dStopLoss + ", " + dTp);

		SaveComment(strExpertName + " buy error: " + nError + "\r\n" +
			Ask + ", " + dStopLoss + ", " + dTp);
	}
}


void CloseBuy(string strExpertName)
{
	int nTicket = OrderTicket();
	SaveComment("\r\n\tAttempting to close long position, ticket: " + nTicket + "\r\n");
	
	for(int nTry = 0; nTry < 5; nTry++)
	{
		SaveComment(Day() + "." + Month() + "." + Year() + " " + Hour() + ":" + Minute() + ":" + Seconds());
		int nResult = OrderClose(OrderTicket(), OrderLots(), Bid, nSlip, Aqua);
		
		if(nResult == -1)
		{
			int nError = GetLastError();
			Alert(strExpertName + ", error: " + nError);
			SaveComment(strExpertName + ", error: " + nError);
		}
		
		bool bClosed = true;
		for(int nOrderNo = OrdersTotal() - 1; nOrderNo >= 0; nOrderNo--)
		{
			OrderSelect(nOrderNo, SELECT_BY_POS, MODE_TRADES);
			if(OrderTicket() == nTicket)
			{
				bClosed = false;
				break;
			}
		}
		
		if(bClosed == true)
		{
			SaveComment("\r\n\tNo more orders with this ticket No");
			break;
		}
		else
		{
			SaveComment("\r\n\tOrder with this ticket still present, trying again");
			RefreshRates();
		}
	}
}

// ------

void CloseSell(string strExpertName)
{
	int nTicket = OrderTicket();
	SaveComment("\r\n\tAttempting to close short position, ticket: " + nTicket + "\r\n");
	
	for(int nTry = 0; nTry < 5; nTry++)
	{
		SaveComment(Day() + "." + Month() + "." + Year() + " " + Hour() + ":" + Minute() + ":" + Seconds());
		int nResult = OrderClose(OrderTicket(), OrderLots(), Ask, nSlip, OrangeRed);
		if(nResult == -1)
		{
			int nError = GetLastError();
			Alert(strExpertName + ", error: " + nError);
			SaveComment(strExpertName + ", error: " + nError);
		}
		
		bool bClosed = true;
		for(int nOrderNo = OrdersTotal() - 1; nOrderNo >= 0; nOrderNo--)
		{
			OrderSelect(nOrderNo, SELECT_BY_POS, MODE_TRADES);
			if(OrderTicket() == nTicket)
			{
				bClosed = false;
				break;
			}
		}
		
		if(bClosed == true)
		{
			SaveComment("\r\n\tNo more orders with this ticket No");
			break;
		}
		else
		{
			SaveComment("\r\n\tOrder with this ticket still present, trying again");
			RefreshRates();
		}
	}
}