Ce que signifie l'entrée dans le journal de bord

 
Lorsque j'essaie de conclure une transaction avec un conseiller expert, j'obtiens (ce n'est pas la première fois) : Ping failed
Qu'est-ce que c'est et comment y remédier ?
Lorsque vous redémarrez MT (la condition de clôture est toujours valable), l'opération se termine avec succès.

Il n'y a pas d'erreurs dans le journal, la sortie dans le fichier, que j'ai mis littéralement en travers d'une ligne, montre que OrderSend a fonctionné, sans erreur, mais voici le problème : a) l'ordre dans la liste des ouverts est resté et b) il s'est fermé au redémarrage de MT, donc il n'était pas seulement dans la liste, mais aussi dans la réalité.

Au cas où Meta voudrait réconcilier les logs avec Alpari, compte 142605, ticket 1728130

J'espère obtenir encore une réponse, ce n'est pas mon premier post sur cette erreur.
Salutations,
Quark
 
Merci, nous allons nous pencher sur la question.
Pouvez-vous m'envoyer un morceau de journal à partir du moment de la demande jusqu'au moment où le ping échoué est reçu (il est important de vérifier les délais d'attente) ? Et c'est sur un compte réel ou de démonstration ?
 
<br/ translate="no">Merci, nous allons y réfléchir.
Pouvez-vous envoyer un morceau du journal à partir du moment où la demande est faite jusqu'à la réception de l'échec du ping (il est important de vérifier les délais d'attente) ? Et est-ce sur un compte réel ou de démonstration ?


Ceci est sur un compte de démonstration. Log... J'ai fermé et ouvert MT, donc l'entrée de l'onglet "log" a été mise à jour. Je vais le copier la prochaine fois, puis le redémarrer, j'ai l'impression que cela va prendre quelques jours, je veux dire une récurrence du problème. Je ne peux que suggérer un journal du répertoire experts\logs. C'est ce que vous aviez à l'esprit ?

Dans l'historique du compte, cette transaction correspond à la ligne suivante (au fait, pourquoi n'y a-t-il pas de copie ligne par ligne vers le tampon dans cet onglet ?)
1728130 2005.08.31 15:00 acheter 0.10 eurusd 1.2223 1.2183 0 2005.08.31 20:07 1.2330 0 107.00 Vendredi

Je suis à Moscou, cela peut être nécessaire dans l'analyse des temps de transaction.

Notez que le conseiller expert a fermé la transaction à 20 h 07. En fait, la condition de clôture était à 20 h 01, mais la position n'a pas été fermée. J'ai fermé et ouvert MT, et à 20.07, c'est-à-dire immédiatement, dans les secondes qui suivent le redémarrage de la position fermée.

J'ai maintenant regardé le journal (tout le journal), mais il fait 147Kb. Je vous le joins si vous voulez, mais croyez-moi, il n'y a que deux entrées pour cette transaction :

17:00:18 _Friday_Expert EURUSD,H1 : open #1728130 buy 0.10 EURUSD at 1.2223 sl : 1.2183 ok
...
22:07:24 _Friday_Expert EURUSD,H1 : close #1728130 buy 0.10 EURUSD at 1.2223 sl : 1.2183 at price 1.2330

Il semble donc qu'il n'y ait pas de tentative de fermeture de la position à 20.01. "En quelque sorte" parce que a) l'onglet "log" (je ne m'attendais pas à ce que MT le réinitialise) montrait une note sur la tentative et l'échec du ping et b) comme ce n'est pas le premier problème avec cette EA, voyez à quoi elle ressemble de l'intérieur :

.
	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 écrit simplement du texte dans un fichier.
Ainsi, toutes les entrées du fichier qui étaient appropriées pour la tentative de fermeture de la position sont apparues, mais l'alerte n'a pas été appelée, c'est-à-dire que OrderClose a renvoyé le code de réussite.


 
Donc, comme je l'ai promis, j'ai attendu les répétitions d'erreurs. Notez tout de suite que cette erreur était déjà apparue sur un autre EA, donc ce n'est probablement pas la faute du code (bien que tout puisse l'être). Mais cet Expert Advisor était "non préparé", dans le sens où il n'avait pas de fonctions pour sortir tout ce que je pouvais dans le fichier.

Il y a une erreur : ping failed dans le journal.

Peut-être qu'après l'échec d'un ping, votre système ne devrait pas permettre l'exécution de OrderSend, un message d'erreur serait alors généré.

Dans ce cas, il n'y a pas de message d'erreur, seulement une entrée dans le journal. Le programme se comporte comme s'il avait réussi à clôturer la transaction, mais celle-ci n'est pas clôturée.

Donc, dans le journal :
2005.09.05 16:01:35 TradeContext : ping failed
2005.09.05 16:01:35 TradeContext : ping error
2005.09.05 16:01:14 '142605' : ordre de clôture #1775545 sell 0.10 EURUSD at 1.2535 sl : 0.0000 tp : 0.0000 au prix de 1.2542
2005.09.05 16:01:14 '142605' : login (4.00, #27FFBBD7)

Au fait, je me demande vraiment pourquoi sl : 0.0000, je n'envoie pas de zéro.

Dans le même temps, la fonction de démarrage ressemble à ceci :

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 est une fonction qui permet de sortir la chaîne de caractères dans un fichier.

Voici la fonction de position fermée appelée depuis le début. Comme vous pouvez le voir, il essaie de fermer la position 5 fois (je l'ai fait uniquement à des fins de test), et si aucun code d'erreur n'est renvoyé (c'est-à-dire que MT pense que la position est fermée), il recherche parmi les ordres encore ouverts celui qui a le ticket requis.

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");
	}
}



Le journal ci-dessous montre que les 5 tentatives de fermeture d'un ordre ont échoué (le ticket n'a pas disparu), MT croyant que la position est fermée.


5.9.2005 14:1:29, Signal : none
312758.00000000 - 312754.00000000 >= 4
Tentative de clôture d'une position courte, ticket : 1775545
Ordre avec ce ticket toujours présent, réessayer
Ordre avec ce ticket toujours présent, réessayer
Ordre avec ce ticket toujours présent, réessayer
Ordre avec ce ticket toujours présent, réessayer, vente fermée

Note : n'ayez pas peur du "Signal : none" - il devrait être comme ceci. Il s'agit d'un signal pour ouvrir une nouvelle position. Le signal pour fermer une position est généré si l'inégalité "312758.00000000 - 312754.00000000 >= 4" est respectée,


Chers développeurs !
J'espère vraiment que nous parviendrons à résoudre ce problème ensemble.

Quark

P.S. Comme d'habitude, après avoir redémarré MT, j'obtiens la fermeture de la position par expert, sans problème de k.l..

 
Nous attendons toujours la réponse des développeurs.
Ajout d'un code écrivant les résultats dans un fichier lorsque j'essaie d'ouvrir - fermer une transaction dans tous mes EAs. Le résultat est décevant. A peu près à chaque fois, pour tous les EAs, une seule tentative d'ouverture - fermeture d'un ordre n'est pas suffisante. En moyenne, il en faut deux (voir le code ci-dessus, il y a un cycle de cinq tentatives). Parfois, cinq tentatives ne suffisent pas. En même temps, MT fonctionne comme si l'ordre était ouvert - fermé avec succès, aucun message d'erreur n'est donné.

Tous les sémaphores suggérés dans la branche "Erreur numéro 6" (qui, soit dit en passant, se produit encore parfois), je les utilise, plus le timer des Expert Advisors qui garantit que chaque EA démarre dans les 10 secondes qui lui sont dédiées, c'est-à-dire qu'il ne devrait pas y avoir de conflits entre les EAs.

Je suggère aux autres développeurs d'utiliser le code ci-dessous dans des EAs en direct pour vérifier si tous vos ordres fonctionnent comme vous le souhaitez. D'un point de vue commercial, il s'agit simplement d'un OrderSend normal, entouré de fonctions de sortie vers un fichier.

Sans vouloir vous offenser, il semble que MT doive affiner l'interaction avec le serveur de commerce.

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

// ------



 
Peut-être que vos EAs ouvrent/ferment des trades trop souvent. J'ai passé en revue l'historique des transactions (j'ai 8 EA suspendues) et j'ai compté le nombre de fois où il y a plus d'une transaction en une minute (pas plus de 10), toutes sont réussies. C'est vrai, les EAs travaillent sur les ouvertures de barres sur 1H, 4H, D1 et les timeouts sont insérés partout, mais les timeouts seulement entre les transactions d'un EA (en fait je n'en ai pas besoin), pas de sémaphores entre les EAs.
Je dois ensuite trouver la limite de l'intervalle autorisé sur le compte de démonstration.
 
J'ai également 8 EAs en suspens en ce moment, tous sur M5.
De 00:00 à 12:00
métiers - 141
3 erreurs ("1" et deux "6").

Quark, pouvez-vous me jeter dans l'email komposterius ru la dernière version glitchy de votre EA (qui est sur M1) ? Je vais accrocher 8 fenêtres de plus - voir ce qui se passe ;)
 
Vous manquez le point principal. Je n'ai AUCUN expert de la minute. Tous les échanges se font en temps réel. Je n'ai PAS de transactions fréquentes, une par heure tout au plus.

Les experts attendent (à l'aide de sémaphores) pour une file d'attente, de plus, l'EA dont le nombre magique est égal à, par exemple, 10, attend 10 * 10 = 100 secondes à partir du début d'une barre, et ce n'est qu'ensuite qu'il effectue des transactions. Par conséquent, les chances de rencontrer un EA avec magic 11 sont proches de 0, même sans sémaphores.

L'impression est que si MT échoue une fois (ping failed, error 6, etc.), quelque chose ne va pas dans son système et les transactions suivantes de cet EA échouent.

Exemple de journal (code affiché ci-dessus) :

Essayer d'acheter, la tentative 0 a échoué, erreur 6
Essayer d'acheter, tentative 1 a échoué, erreur 129
Essayer d'acheter, tentative 2 a échoué, erreur 129
Essayer d'acheter, tentative 3 a échoué, erreur 129
Essayer d'acheter, tentative 4 a échoué, erreur 129
Erreur d'achat en zigzag : 4050
2.28000000, 0.02700000, 0.00000000

Qu'avons-nous là ? Il y a d'abord eu un échec (dans le journal - erreur de connexion avec le serveur). Ensuite, 5 tentatives (j'en ai 5 dans ma boucle) donnent 129 - mauvais prix. Le prix est en dessous - tout à fait normal. Après avoir redémarré MT à ce prix, l'ordre a été ouvert avec succès. Ensuite, nous obtenons 4050, le mauvais nombre d'arguments. Il s'agit d'une fonction qui fonctionne bien dans d'autres appels. Il y a une défaillance manifeste du système de signalement des erreurs.

Je cite un expert, mais je pense qu'il faut en avoir beaucoup pour que le problème soit fréquent. Espérons que le compositeur, Roche et les développeurs examineront le code et donneront leur avis. Quand même, je pense que c'est une question de MT ici.

Expert :
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);
}

// ------



Indicateur :

#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);
*/



Le fichier de la bibliothèque, doit se trouver dans le répertoire 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);
	}
}

// ------

 
Vous m'avez vraiment intrigué, Quark :)
Il est temps pour les développeurs de réfléchir à un travail pour vous au sein du personnel pour leur trouver toutes sortes de méchancetés.
Peut-être que c'est le ping, je n'ai pas de cycles pour réessayer de passer des commandes, peut-être que je devrais appeler Refresh à ce stade et profiter de prix plus frais.
Je me perds... :)
 
Eh bien, vous avez fini par intriguer, Quark :)<br / translate="no">Il est temps pour les développeurs de penser à un poste vacant pour vous au sein du personnel pour leur trouver toutes sortes de méchancetés.
Peut-être que c'est le ping, je n'ai pas de cycles pour réessayer de passer des commandes, peut-être que je dois appeler Refresh à ce stade et mettre en place des prix plus frais.
Je suis en train de me perdre... :)


Bonne idée... Je vais le faire maintenant...
 
Une nouvelle édition, avec une présentation de 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();
		}
	}
}