Непонятно только почему этот зигзаг в реалтайме ничего не рисует.
Отрисовывает историю при запуске и дальше все стоит. В чем дело ?
Рисуется очередной пик, только когда он достигнут. Пока очередного пика нет, кривая останавливается на предыдущем пике.
Все это я понимаю, но у меня так не работает.
Я запустил его на М1 с параметром 6: историю отрисовывает и дальше стоит.
За это время мой зигзаг (полностью совпадая с твоим на истории) нарисовал
уже 9 секций (т.е. 9 пиков).
По-моему напрягаться чтобы зигзаг ловил все, что только можно, и рисовал
вертикальные секции можно только из чисто академического интереса.
А уж напрягать ради этого разработчиков .... :-(
Гы ... какой вы недальновидный :) Явно тему не прорабатывали.
Begun, я поправил алгоритм, так что теперь этот зигзаг ловит указанные вами и им подобные хвосты.
Оказывается такие ситуации встречаются чаще, чем я думал.
Благодаря изменениям поведение индикатора улучшилось и в некоторых других ситуациях.
Так что спасибо за инициативу.
Begun, я поправил алгоритм, так что теперь этот зигзаг ловит указанные вами и им подобные хвосты.
Оказывается такие ситуации встречаются чаще, чем я думал.
Благодаря изменениям поведение индикатора улучшилось и в некоторых других ситуациях.
Так что спасибо за инициативу.
Рад за вас Yurixx. На самом деле в природе существует однозначный алгоритм рассчета пунктового зигзага на OHLC рядах. Можно сравнить ваш и наш :) fx-system at mail.ru
Осталось только сподвигнуть MT разработчиков на правильный тип линии.
Выловил (с вашей подачи) и устранил проблему. Теперь в очень широкие часы, когда должен быть и макс. и мин., не рисуем ничего, так как внутри бара все равно нельзя ничего сделать. Плюс к этому, выкладываю третий индикатор, который совмещает "точный" и "отстающий" зигзаги (и рисует сигналы по обоим, так что будьте внимательны). Я нашел по крайней мере одну ситуацию, когда это нужно: если требуются "точные" сигналы, то есть, проставленные в тех точках, где есть экстремумы, а не позже, когда мы смогли их рассчитать, но при этом неохота пересчитывать индикаторы вглубь при каждом баре. В этом случае:
Мда... Не ожидал, что функции 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/"
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);
}
//+------------------------------------------------------------------+
Для авторизации и пользования сайтом MQL5.com необходимо разрешить использование файлов Сookie.
Пожалуйста, включите в вашем браузере данную настройку, иначе вы не сможете авторизоваться.
Вы вошли в аккаунт. Двухфакторная аутентификация отключена. Настройте её заново и отсканируйте новый QR-код или продолжите с отключённой двухфакторной аутентификацией.
Отрисовывает историю при запуске и дальше все стоит. В чем дело ?
Рисуется очередной пик, только когда он достигнут. Пока очередного пика нет, кривая останавливается на предыдущем пике.
Все это я понимаю, но у меня так не работает.
Я запустил его на М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); */По-моему напрягаться чтобы зигзаг ловил все, что только можно, и рисовал
вертикальные секции можно только из чисто академического интереса.
А уж напрягать ради этого разработчиков .... :-(
Гы ... какой вы недальновидный :) Явно тему не прорабатывали.
ИМХО
Оказывается такие ситуации встречаются чаще, чем я думал.
Благодаря изменениям поведение индикатора улучшилось и в некоторых других ситуациях.
Так что спасибо за инициативу.
#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); //+------------------------------------------------------------------+.
Оказывается такие ситуации встречаются чаще, чем я думал.
Благодаря изменениям поведение индикатора улучшилось и в некоторых других ситуациях.
Так что спасибо за инициативу.
Рад за вас Yurixx. На самом деле в природе существует однозначный алгоритм рассчета пунктового зигзага на OHLC рядах. Можно сравнить ваш и наш :) fx-system at mail.ru
Осталось только сподвигнуть MT разработчиков на правильный тип линии.
Сравнить можно. Выкладывайте. :-)
А насчет того, что природа занималась однозначным решением этого вопроса - сомневаюсь.
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); */В МТ3, кто не помнит, из этих функций при одинаковых барах всегда возвращался первый (более старый в истории) бар. И это было как то понятно, потому что поиск эктремумов в этих функциях шел от конца к началу. Но ведь в МТ4 все наоборот - поиск идет от начала к концу.
Именно поэтому, в ZigZage МТ3 было лишнее условие, которое из двух баров с одинаковыми High или Low всегда вырезался первый (более старый).
Я эту фишку обнаружил только сегодня, поэтому могут быть грабли с написанием кода, когда уверен, что функция Highest и Lowest возвращают ближайший бар из двух возможных.
Написал скрипт для проверки, который демонстрирует это.
Кто еще не знал об этом?