로그 항목의 의미

 
Expert Advisor가 거래를 성사하려고 할 때 (처음이 아님) 다음과 같은 메시지가 표시됩니다. Ping 실패
그것은 무엇이며 어떻게 처리합니까?
MT가 다시 시작되면(거래 종료 조건이 여전히 유효함) 거래가 성공적으로 종료됩니다.

로그에 오류가 없습니다. 내가 문자 그대로 줄을 통해 넣은 파일의 출력은 OrderSend 가 오류 없이 작동했음을 보여주지만 여기에 문제가 있습니다. a) 주문이 열린 목록에 남아 있고 b) MT가 다시 시작되었습니다. 즉, 목록뿐만 아니라 현실에서도 마찬가지입니다.

Meta가 Alpari, 계정 142605, 티켓 1728130으로 로그를 확인하려는 경우

나는 여전히 답을 얻기를 바랍니다. 이것은 이 오류에 대한 나의 첫 번째 메시지가 아닙니다.
감사합니다,
쿼크
 
감사합니다. 살펴보겠습니다.
요청한 순간부터 ping이 실패하는 순간까지 로그를 보낼 수 있습니까(타임아웃을 확인하는 것이 중요)? 그리고 이것은 실제 또는 데모 계정에 있습니까?
 

감사합니다. 살펴보겠습니다.
요청한 순간부터 ping이 실패하는 순간까지 로그를 보낼 수 있습니까(타임아웃을 확인하는 것이 중요)? 그리고 이것은 실제 또는 데모 계정에 있습니까?


이것은 데모 계정에 있습니다. 로그... MT를 닫고 열었으므로 "로그" 탭의 항목이 업데이트되었습니다. 다음에 복사하고 다시 시작하면 며칠이 걸릴 것 같은 느낌이 듭니다. 문제의 반복을 의미합니다. 나는 Experts\logs 디렉토리의 로그만 제공할 수 있습니다. 그게 당신이 의미하는 무엇입니까?

계정 기록에서 이 거래는 다음 행에 해당합니다(그런데 이 탭에서 버퍼에 행 단위로 복사가 없는 이유는 무엇입니까?).
1728130 2005.08.31 15:00 매수 0.10 유로 1.2223 1.2183 0 2005.08.31 20:07 1.2330 0 107.00 금요일

나는 모스크바에 있으며 거래 시간을 분석할 때 필요할 수 있습니다.

거래는 20.07에 전문가에 의해 마감되었습니다. 실제로 청산 조건은 20.01에 발생했지만 포지션은 청산되지 않았습니다. MT를 청산했다가 20시 7분, 즉 재시동 직후 몇 초 만에 포지션을 청산했습니다.

이제 로그(전체)를 보았지만 147KB가 있습니다. 원하시면 첨부하겠습니다. 하지만 이 거래에 대한 항목은 두 개뿐입니다.

17:00:18 _Friday_Expert EURUSD,H1: 오픈 #1728130 1.2223 sl에서 0.10 EURUSD 매수: 1.2183 ok
...
22:07:24 _Friday_Expert EURUSD,H1: 마감 #1728130 1.2223 sl에서 0.10 EURUSD 매수 sl: 1.2183 가격 1.2330

즉, 20.01 에서 포지션 을 청산하려는 시도가 없었던 것으로 보입니다. "닮음" - a) "로그" 탭에(MT에서 삭제하는 것을 예상하지 못함) ping 시도 및 실패에 대한 설명이 있었고 b) 이것이 이 Expert Advisor의 첫 번째 문제가 아니기 때문에 , 내부에서 어떻게 보이는지 보십시오.

	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는 단순히 파일에 텍스트를 씁니다.
따라서 위치를 닫으려는 시도에 적합한 파일의 모든 항목이 나타났지만 경고가 호출되지 않았습니다. 즉, OrderClose가 성공적인 완료 코드를 반환했습니다.


 
그래서 약속한 대로 오류가 반복될 때까지 기다렸습니다. 이 오류는 이미 하나 이상의 Expert Advisor에서 표시되었으므로 코드에 없을 수도 있습니다(어떤 일이 발생할 수 있음에도 불구하고). 그러나 그 Expert Advisor는 가능한 모든 것을 한 줄로 파일에 출력하는 기능이 없다는 의미에서 "준비되지 않았습니다".

오류 발생: 로그에서 ping이 실패했습니다.

ping 실패가 발생한 후 시스템은 OrderSend 실행을 허용하지 않아야 하며, 이 경우 오류 메시지 가 생성됩니다.

이 경우 오류 메시지는 없고 로그 항목만 있습니다. 프로그램은 거래를 성공적으로 마감한 것처럼 작동하며 거래만 마감되지 않습니다.

따라서 저널(Journal)에서:
2005.09.05 16:01:35 TradeContext: 핑 실패
2005.09.05 16:01:35 TradeContext: 핑 오류
2005.09.05 16:01:14 '142605': 주문 마감 #1775545 1.2535 sl: 0.0000 tp: 0.0000 가격 1.2542에 0.10 EURUSD 매도
2005.09.05 16:01:14 '142605': 로그인(4.00, #27FFBBD7)

그건 그렇고, 나는 왜 sl: 0.0000인지 이해하고 싶습니다. 0을 전달하지 않습니다.

이 경우 시작 기능은 다음과 같습니다.

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는 문자열을 파일로 출력하는 함수입니다.

다음은 시작부터 호출되는 포지션 클로징 함수입니다. 보시다시피 포지션 청산을 5번 시도하고(테스트 목적으로만 수행했습니다) 오류 코드가 반환되지 않으면(즉, MT는 해당 포지션이 청산된 것으로 간주) 아직 열려 있는 주문 중에서 검색합니다. 원하는 티켓을 가지고 있는 사람을 위해.

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



아래 로그는 주문을 마감하려는 5번의 시도가 모두 실패했음을 보여줍니다(티켓이 사라지지 않음). 반면 MT는 포지션이 마감된 것으로 간주합니다.

2005년 5월 9일 14:1:29, 신호: 없음
312758.00000000 - 312754.00000000 >= 4
매도 포지션 청산 시도, 티켓: 1775545
이 티켓이 아직 있는 상태로 주문하세요. 다시 시도하세요.
이 티켓이 아직 있는 상태로 주문하세요. 다시 시도하세요.
이 티켓이 아직 있는 상태로 주문하세요. 다시 시도하세요.
이 티켓이 아직 있는 상태로 주문하세요. 다시 시도하세요.
이 티켓이 아직 있는 상태로 주문, 다시 시도, 판매 종료

참고: "신호: 없음"에 놀라지 마십시오. 그래야 합니다. 이것은 새 포지션을 열라는 신호이고, 닫으라는 신호는 "312758.00000000 - 312754.00000000 >= 4" 부등식의 충족에 의해 생성됩니다.


친애하는 개발자 여러분!
우리가 함께 이 문제를 해결할 수 있기를 진심으로 바랍니다.

쿼크

추신 평소와 같이 MT를 다시 시작한 후 c.l. 없이 전문가가 포지션을 닫았습니다. 문제.

 
아직 개발자의 답변을 기다리고 있습니다.
모든 Expert Advisors에서 거래를 열거나 닫으려고 할 때 파일에 결과를 기록하는 코드를 추가했습니다. 결과는 실망스럽습니다. 거의 격주로 모든 전문가의 경우 주문을 한 번 열고 닫는 것만으로는 충분하지 않습니다. 평균적으로 2개가 필요합니다(위의 코드 참조, 5번의 시도 주기가 있음). 때로는 5개도 충분하지 않습니다. 동시에 MT는 주문이 성공적으로 열렸습니다-닫힌 것처럼 작동하며 오류 메시지를 표시 하지 않습니다.

나는 "오류 번호 6" 스레드에서 제안된 모든 세마포어(그런데 여전히 가끔 발생함)를 사용하고 전문가 타이머는 각 전문가가 자체 10초 안에 시작되도록 합니다. 즉, 전문가 간의 충돌이 발생할 수 있습니다. 해서는 안 된다.

다른 개발자가 실시간 EA에서 아래 코드를 사용하여 모든 주문이 예상대로 작동하는지 확인하는 것이 좋습니다. 거래의 관점에서 이것은 파일 출력 기능으로 둘러싸인 일반 OrderSend입니다.

욕설은 없지만 MT에서는 무역 서버와의 상호 작용을 디버그해야 할 것 같습니다.

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

// ------

 
아마도 귀하의 Expert Advisors는 거래를 너무 자주 열고 닫을 것입니다. 나는 특별히 지금 거래의 이력 (8명의 고문이 매달리고 있음)을 살펴보았고, 1분 내에 하나 이상의 거래가 발생하는 순간은 총합(10개 이하)이 모두 성공적입니다. 사실, 어드바이저는 1H, 4H, D1에 막대를 열어 작업하고 타임아웃은 어디에나 삽입되지만 타임아웃은 한 어드바이저의 트랜잭션 사이에만 발생합니다(사실 저는 필요하지 않았습니다). 어드바이저 사이에는 세마포어가 없습니다.
그런 다음 데모 계정에서 허용 간격의 경계를 찾아야 합니다.
 
또한 현재 8명의 고문이 모두 M5에 매달려 있습니다.
00:00~12:00
거래 - 141
오류 - 3("1" 및 2개의 "6").

Quark, komposterius에 있는 Expert Advisor(M1에 있음)의 최신 버그 버전을 던질 수 있습니까? 8개의 창을 더 걸겠습니다 - 무슨 일이 일어나는지 보세요 ;)
 
얘들 아, 당신은 주요 내용을 이해하지 못했습니다. 나는 분 전문가가 없습니다. 모든 거래는 정시에 이루어집니다. 나는 빈번한 거래를 하지 않으며, 많아야 한 시간에 한 번입니다.

전문가는 대기열(세마포어 사용)을 기다립니다. 또한 예를 들어 10과 같은 마법을 가진 전문가는 막대 시작부터 10 * 10 = 100초 동안 기다린 후 거래합니다. 따라서 마술 11을 가진 전문가와 교차할 확률은 세마포어가 없어도 0에 가깝습니다.

MT가 한 번 실패하면(ping 실패, 오류 6이 나옴 등) 시스템에서 전체적으로 문제가 발생하여 이 Expert Advisor의 후속 거래가 실패하게 됩니다.

로그 예(위 코드):

구매 시도, 시도 0 실패, 오류 6
구매 시도, 시도 1 실패, 오류 129
구매 시도, 시도 2 실패, 오류 129
구매 시도, 3번 시도 실패, 오류 129
구매 시도, 시도 4 실패, 오류 129
지그재그 구매 오류: 4050
2.28000000, 0.02700000, 0.00000000

우리는 여기에 무엇을 가지고 있습니까? 처음에는 오류가 발생했습니다(로그에서 - 서버 연결 오류). 그런 다음 5번의 시도(사이클에 5번 있음)는 잘못된 가격인 129번을 제공합니다. 아래는 가격입니다 - 아주 정상입니다. 이 가격으로 MT를 다시 시작한 후 주문이 성공적으로 열렸습니다. 그런 다음 - 4050, 잘못된 인수 수입니다. 이것은 다른 호출에서 잘 작동하는 함수를 위한 것입니다. 오류 보고 시스템의 명확한 실패.

문제가 자주 발생하려면 전문가가 많이 있어야 한다고 생각하지만 전문가 한 명을 데려왔습니다. 컴포스터, Roche, 개발자들이 코드를 보고 조언을 해주기를 바랍니다. 그래도 여기의 포인트는 MT에 있는 것 같다.

전문가:
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);
}

// ------



지시자:

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



라이브러리 파일은 전문가 디렉토리에 있어야 합니다.

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

// ------

 
글쎄, 당신은 마침내 나를 흥미롭게 만들었습니다, Quark :)
개발자가 해당 주의 공석에 대해 생각할 때입니다. 그러면 개발자를 위한 모든 종류의 더러운 트릭을 찾을 수 있습니다.
아마도 핑 문제일 수도 있고, 주문을 재시도하는 주기가 없습니다. 아마도 여기에서 새로 고침에 전화를 걸어 최신 가격을 입력해야 할 수도 있습니다.
길을 잃었습니다...:)
 
글쎄, 당신은 마침내 나를 흥미롭게 만들었습니다, Quark :)
개발자가 해당 주의 공석에 대해 생각할 때입니다. 그러면 개발자를 위한 모든 종류의 더러운 트릭을 찾을 수 있습니다.
아마도 핑 문제일 수도 있고, 주문을 재시도하는 주기가 없습니다. 아마도 여기에서 새로 고침에 전화를 걸어 최신 가격을 입력해야 할 수도 있습니다.
길을 잃었습니다...:)


좋은 생각이야... 이제 할게...
 
새 판, Rosh 제공:
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();
		}
	}
}

사유: