RE Slawa - ответ на зигзаг :) - страница 3

 
Непонятно только почему этот зигзаг в реалтайме ничего не рисует.
Отрисовывает историю при запуске и дальше все стоит. В чем дело ?


Рисуется очередной пик, только когда он достигнут. Пока очередного пика нет, кривая останавливается на предыдущем пике.


Все это я понимаю, но у меня так не работает.
Я запустил его на М1 с параметром 6: историю отрисовывает и дальше стоит.
За это время мой зигзаг (полностью совпадая с твоим на истории) нарисовал
уже 9 секций (т.е. 9 пиков).


Проверю, спасибо.
 
... полная версия...

#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 = 75;

// 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;
		
		if(nLastMinMaxType != 1)	// Expecting maximum
		{
			if(dLastMax <= High[nPos])
			{
				dLastMax = High[nPos];
				nLastMinMaxBar = nPos;
			}
			
			if(Low[nPos] < dLastMax - nMinMaxPoints * Point)	// Maximum found
			{
				arrExtMapBuffer[nPos] = 1;//High[nLastMinMaxBar];
				nLastMinMaxType = 1;
				dLastMin = Low[nPos];
				dLastMax = High[nPos];
				nLastMinMaxBar = nPos;
			}
		}
		else if(nLastMinMaxType != -1)	// Expecting minimum
		{
			if(dLastMin >= Low[nPos])
			{
				dLastMin = Low[nPos];
				nLastMinMaxBar = nPos;
			}
			
			if(High[nPos] > dLastMin + nMinMaxPoints * Point)	// Maximum found
			{
				arrExtMapBuffer[nPos] = -1;//Low[nLastMinMaxBar];
				nLastMinMaxType = -1;
				dLastMax = High[nPos];
				dLastMin = Low[nPos];
				nLastMinMaxBar = nPos;
			}
		}

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

По-моему напрягаться чтобы зигзаг ловил все, что только можно, и рисовал
вертикальные секции можно только из чисто академического интереса.
А уж напрягать ради этого разработчиков .... :-(


Гы ... какой вы недальновидный :) Явно тему не прорабатывали.


ИМХО
 
Begun, я поправил алгоритм, так что теперь этот зигзаг ловит указанные вами и им подобные хвосты.
Оказывается такие ситуации встречаются чаще, чем я думал.
Благодаря изменениям поведение индикатора улучшилось и в некоторых других ситуациях.
Так что спасибо за инициативу.
 
Спасибо, Quark, перенес на график, красиво получилось.
#property indicator_chart_window
//#property indicator_separate_window
#property indicator_buffers 3
//#property indicator_color1 Red
#property indicator_color2 Tomato
#property indicator_color3 Aqua
//#property indicator_minimum -1
//#property indicator_maximum 1

// indicator parameters
extern int nMinMaxPoints = 75;

// indicator buffers
double arrExtMapBuffer[];
double Buyb[];		// Buy indicator line
double Sellb[];		// Sell indicator line		

int nExtCountedBars = 0;

int nLastMinMaxBar;
int nLastMinMaxType;

double dLastMin, dLastMax;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
	string strIndicatorShortName;

	// drawing settings
//	SetIndexStyle(0, DRAW_HISTOGRAM);
//	SetIndexShift(0, 0);
//	SetIndexEmptyValue(0,0.0);
	SetIndexStyle(1,DRAW_ARROW);
   SetIndexArrow(1,233);
   SetIndexStyle(2,DRAW_ARROW);
   SetIndexArrow(2,234);
	
		
	IndicatorDigits(4);
		
	strIndicatorShortName = "Zigzag(" + nMinMaxPoints + ")";  
	IndicatorShortName(strIndicatorShortName);

	// indicator buffers mapping
//	SetIndexBuffer(0, arrExtMapBuffer);
	SetIndexBuffer(1, Buyb);
	SetIndexBuffer(2, Sellb);

	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);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//---- 
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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;
		
		if(nLastMinMaxType != 1)	// Expecting maximum
		{
			if(dLastMax <= High[nPos])
			{
				dLastMax = High[nPos];
				nLastMinMaxBar = nPos;
			}
			
			if(Low[nPos] < dLastMax - nMinMaxPoints * Point)	// Maximum found
			{
				arrExtMapBuffer[nPos] = 1;//High[nLastMinMaxBar];
				nLastMinMaxType = 1;
				dLastMin = Low[nPos];
				dLastMax = High[nPos];
				nLastMinMaxBar = nPos;
				Buyb[nPos] = Low[nPos]-10*Point;
			}
		}
		else if(nLastMinMaxType != -1)	// Expecting minimum
		{
			if(dLastMin >= Low[nPos])
			{
				dLastMin = Low[nPos];
				nLastMinMaxBar = nPos;
			}
			
			if(High[nPos] > dLastMin + nMinMaxPoints * Point)	// Maximum found
			{
				arrExtMapBuffer[nPos] = -1;//Low[nLastMinMaxBar];
				nLastMinMaxType = -1;
				dLastMax = High[nPos];
				dLastMin = Low[nPos];
				nLastMinMaxBar = nPos;
				Sellb[nPos] = High[nPos]+10*Point;
			}
		}

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


//----
   return(0);
  
//+------------------------------------------------------------------+

.

 
Begun, я поправил алгоритм, так что теперь этот зигзаг ловит указанные вами и им подобные хвосты.
Оказывается такие ситуации встречаются чаще, чем я думал.
Благодаря изменениям поведение индикатора улучшилось и в некоторых других ситуациях.
Так что спасибо за инициативу.

Рад за вас Yurixx. На самом деле в природе существует однозначный алгоритм рассчета пунктового зигзага на OHLC рядах. Можно сравнить ваш и наш :) fx-system at mail.ru
Осталось только сподвигнуть MT разработчиков на правильный тип линии.
 
На самом деле в природе существует однозначный алгоритм рассчета пунктового зигзага на OHLC рядах. Можно сравнить ваш и наш :) fx-system at mail.ru


Сравнить можно. Выкладывайте. :-)
А насчет того, что природа занималась однозначным решением этого вопроса - сомневаюсь.
 
Я вас понял :) Ok. Удачи на виражах.
 
Выловил (с вашей подачи) и устранил проблему. Теперь в очень широкие часы, когда должен быть и макс. и мин., не рисуем ничего, так как внутри бара все равно нельзя ничего сделать. Плюс к этому, выкладываю третий индикатор, который совмещает "точный" и "отстающий" зигзаги (и рисует сигналы по обоим, так что будьте внимательны). Я нашел по крайней мере одну ситуацию, когда это нужно: если требуются "точные" сигналы, то есть, проставленные в тех точках, где есть экстремумы, а не позже, когда мы смогли их рассчитать, но при этом неохота пересчитывать индикаторы вглубь при каждом баре. В этом случае:

int nSignal = iCustom(NULL, 0, "_Zigzag_2_Ind", dZigzagSize, 0, 1);
	
if(nSignal != 0)
{
	for(int nCnt = 1; nCnt < Bars; nCnt++)
	{
		nSignal = iCustom(NULL, 0, "_Zigzag_2_Ind", dZigzagSize, 1, nCnt);
		
		if(nSignal != 0)
		{
			if(nD == 0)
				nD = nCnt;
			else if(nC == 0)
				nC = nCnt;
			else if(nB == 0)
				nB = nCnt;
			else if(nA == 0)
			{
				nA = nCnt;
				break;
			}			
		}
	}
...



Итак, код:

#property indicator_chart_window
//#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red

// indicator parameters
extern int nMinMaxPoints = 50;

// indicator buffers
double arrExtMapBuffer[];

int nExtCountedBars = 0;

int nLastMinMaxBar;
int nLastMinMaxType;

double dLastMin, dLastMax;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
	string strIndicatorShortName;

	// drawing settings
	SetIndexStyle(0, DRAW_SECTION);
	SetIndexShift(0, 0);
	SetIndexEmptyValue(0,0.0);
		
	IndicatorDigits(4);
		
	strIndicatorShortName = "Zigzag_1(" + 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);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//---- 
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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)//nLastMinMaxBar != nPos)
				{				
					arrExtMapBuffer[nLastMinMaxBar] = High[nLastMinMaxBar];
					nLastMinMaxType = 1;
					dLastMin = Low[nPos];
					dLastMax = High[nPos];
					nLastMinMaxBar = nPos;
				}
				else
				{
					arrExtMapBuffer[nLastMinMaxBar] = 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)//nLastMinMaxBar != nPos)
				{
					arrExtMapBuffer[nLastMinMaxBar] = Low[nLastMinMaxBar];
					nLastMinMaxType = -1;
					dLastMax = High[nPos];
					dLastMin = Low[nPos];
					nLastMinMaxBar = nPos;
				}
				else
				{
					arrExtMapBuffer[nLastMinMaxBar] = 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);
*/


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



#property copyright "Quark"
#property link      ""

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Yellow
#property indicator_minimum -1
#property indicator_maximum 1

// indicator parameters
extern int nMinMaxPoints = 50;

// indicator buffers
double arrExtMapBuffer[];
double arrExtMapBuffer_1[];

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);
		
	SetIndexStyle(1, DRAW_HISTOGRAM);
	SetIndexShift(1, 0);
	SetIndexEmptyValue(1,0.0);

	IndicatorDigits(4);
		
	strIndicatorShortName = "Zigzag_2(" + nMinMaxPoints + ")";  
	IndicatorShortName(strIndicatorShortName);

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

	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;
		arrExtMapBuffer_1[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.0;//High[nLastMinMaxBar];
					arrExtMapBuffer_1[nLastMinMaxBar] = 1.0;
					nLastMinMaxType = 1;
					dLastMin = Low[nPos];
					dLastMax = High[nPos];
					nLastMinMaxBar = nPos;
				}
				else
				{
					arrExtMapBuffer[nPos] = 0.0;
					arrExtMapBuffer[nPos + 1] = 0.0;
					arrExtMapBuffer_1[nLastMinMaxBar] = 0.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.0;//Low[nLastMinMaxBar];
					arrExtMapBuffer_1[nLastMinMaxBar] = -1.0;
					nLastMinMaxType = -1;
					dLastMax = High[nPos];
					dLastMin = Low[nPos];
					nLastMinMaxBar = nPos;
				}
				else
				{
					arrExtMapBuffer[nPos] = 0;
					arrExtMapBuffer[nPos + 1] = 0;
					arrExtMapBuffer_1[nLastMinMaxBar] = 0.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);
*/
 
Мда... Не ожидал, что функции Highest и Lowest будут в МТ4 заточены конкретно под Zigzag, сделанный еще в МТ3.
В МТ3, кто не помнит, из этих функций при одинаковых барах всегда возвращался первый (более старый в истории) бар. И это было как то понятно, потому что поиск эктремумов в этих функциях шел от конца к началу. Но ведь в МТ4 все наоборот - поиск идет от начала к концу.
Именно поэтому, в ZigZage МТ3 было лишнее условие, которое из двух баров с одинаковыми High или Low всегда вырезался первый (более старый).

Я эту фишку обнаружил только сегодня, поэтому могут быть грабли с написанием кода, когда уверен, что функция Highest и Lowest возвращают ближайший бар из двух возможных.
Написал скрипт для проверки, который демонстрирует это.
//+------------------------------------------------------------------+
//|                                                  TestHighest.mq4 |
//|                                                             Rosh |
//|                                    http://forexsystems.ru/phpBB/ |
//+------------------------------------------------------------------+
#property copyright "Rosh"
#property link      "http://forexsystems.ru/phpBB/&quot;
extern int firstParameter=10;
//+------------------------------------------------------------------+
//| Моя функция Highest                                              |
//+------------------------------------------------------------------+
int MyHighest(int _shift)
  {
  int result=_shift;
  double MaxHigh=High[_shift];
  if (_shift==0) Print("High[0]=",MaxHigh);
//---- 
   
   for (int i=_shift+1;i<_shift+firstParameter;i++)
      {
      if (_shift==0) Print("High[",i,"]=",High[i]);
      //if (High[i]>MaxHigh)  я ожидал так
      if (High[i]>=MaxHigh) // а оказалось вот так
         {
         MaxHigh=High[i];
         result=i;
         }
      }
//----
   return(result);
  }
//+------------------------------------------------------------------+
//| Вывод High баров                                                 |
//+------------------------------------------------------------------+
void PrintHighes(int _shift)
   {
   Print("Трассировка для бара ",_shift);
   for (int i=_shift;i<_shift+firstParameter;i++)
      {
      Print("High[",i,"]=",High[i]);
      }
   return;
   }
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//---- 
   for (int cnt=Bars-firstParameter-1;cnt>=0;cnt--)
      {
      if (MyHighest(cnt)!=Highest(NULL,0,MODE_HIGH,firstParameter,cnt)) {Print("Функции не сходятся на баре ",cnt);PrintHighes(cnt);}
      Print("На баре ",cnt," Функция MyHighest=",MyHighest(cnt),"  Функция Highest=",Highest(NULL,0,MODE_HIGH,firstParameter,cnt));
      }   
//----
   return(0);
  }
//+------------------------------------------------------------------+




Кто еще не знал об этом?

Причина обращения: