//+------------------------------------------------------------------+ //| Zigzag_R_.mq4 | //| Copyright © 2005-2007, MetaQuotes Software Corp. | //| http://www.metaquotes.net/ | //+------------------------------------------------------------------+ /* Этот вариант Zigzag'а является простой оптимизацией старого | варианта, к которому привыкли сотни тысяч пользователей Metatrader | еще с версии МТ3 (язык MQL2). | Использование индикатора без оптимизации делало сложным и долгим | тестирование советников, использующих значения пользовательского | индикатора Zigzag. Оптимизированный вариант решает данную проблему. | В первый раз, при первом запуске индикатор просчитывает всю историю. | При последующих вызовах при приходе новых тиков в реальном времени | или при использовании в тестере находится третий экстремум от | текущего времени вглубь истории и пересчет начинается с него. Если | Вы хотите начинать пересчет со второго экстремума, поменяйте | значение переменной level, которая определяет глубину пересчета: | int level = 3; // recounting's depth | Все названия внешних переменных сохранены из соображений | преемственности. Кроме того, убраны экстремумы, висящие в воздухе, | которые образовывались на минутных тайм-фреймах. | //+------------------------------------------------------------------+ */ #property copyright "Copyright © 2007, MetaQuotes Software Corp." #property link "http://www.metaquotes.net/" //---- #property indicator_chart_window #property indicator_buffers 1 #property indicator_color1 Red //---- indicator parameters extern int ExtDepth = 12; extern int ExtDeviation = 5; extern int ExtBackstep =3; //---- indicator buffers double ZigzagBuffer[]; double HighMapBuffer[]; double LowMapBuffer[]; // recounting's depth int level = 3; bool downloadhistory = false; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { IndicatorBuffers(3); //---- drawing settings SetIndexStyle(0, DRAW_SECTION); //---- indicator buffers mapping SetIndexBuffer(0, ZigzagBuffer); SetIndexBuffer(1, HighMapBuffer); SetIndexBuffer(2, LowMapBuffer); SetIndexEmptyValue(0, 0.0); //---- indicator short name IndicatorShortName("ZigZag(" + ExtDepth + "," + ExtDeviation + "," + ExtBackstep + ")"); //---- initialization done return(0); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int start() { int i, counted_bars = IndicatorCounted(); int limit, counterZ, whatlookfor; int shift, back, lasthighpos, lastlowpos; double val, res; double curlow, curhigh, lasthigh, lastlow; // history was downloaded if(counted_bars == 0 && downloadhistory) { ArrayInitialize(ZigzagBuffer, 0.0); ArrayInitialize(HighMapBuffer, 0.0); ArrayInitialize(LowMapBuffer, 0.0); } //---- if(counted_bars == 0) { limit = Bars - ExtDepth; downloadhistory = true; } //---- if(counted_bars > 0) { //---- while(counterZ < level && i < 100) { res = ZigzagBuffer[i]; if(res != 0) counterZ++; i++; } i--; limit=i; //---- if(LowMapBuffer[i] != 0) { curlow = LowMapBuffer[i]; whatlookfor = 1; } else { curhigh = HighMapBuffer[i]; whatlookfor = -1; } //---- for(i = limit - 1; i >= 0; i--) { ZigzagBuffer[i] = 0.0; LowMapBuffer[i] = 0.0; HighMapBuffer[i] = 0.0; } } //---- for(shift = limit; shift >= 0; shift--) { val = Low[iLowest(NULL, 0, MODE_LOW, ExtDepth, shift)]; //---- if(val == lastlow) val = 0.0; else { lastlow = val; //---- if((Low[shift]-val) > (ExtDeviation*Point)) val = 0.0; else { //---- for(back = 1; back <= ExtBackstep; back++) { res = LowMapBuffer[shift+back]; //---- if((res != 0) && (res > val)) LowMapBuffer[shift+back] = 0.0; } } } //---- if(Low[shift] == val) LowMapBuffer[shift] = val; else LowMapBuffer[shift] = 0.0; //--- high val = High[iHighest(NULL,0,MODE_HIGH,ExtDepth,shift)]; //---- if(val == lasthigh) val = 0.0; else { lasthigh = val; //---- if((val - High[shift]) > (ExtDeviation*Point)) val = 0.0; else { //---- for(back = 1; back <= ExtBackstep; back++) { res = HighMapBuffer[shift+back]; //---- if((res != 0) && (res < val)) HighMapBuffer[shift+back] = 0.0; } } } //---- if(High[shift] == val) HighMapBuffer[shift] = val; else HighMapBuffer[shift] = 0.0; } // final cutting if(whatlookfor == 0) { lastlow = 0; lasthigh = 0; } else { lastlow = curlow; lasthigh = curhigh; } //---- for(shift = limit; shift >= 0; shift--) { res = 0.0; //---- switch(whatlookfor) { // look for peak or lawn case 0: if(lastlow == 0 && lasthigh == 0) { if(HighMapBuffer[shift] != 0) { lasthigh = High[shift]; lasthighpos = shift; whatlookfor = -1; ZigzagBuffer[shift] = lasthigh; res = 1; } if(LowMapBuffer[shift] != 0) { lastlow = Low[shift]; lastlowpos = shift; whatlookfor = 1; ZigzagBuffer[shift] = lastlow; res = 1; } } break; // look for peak case 1: if(LowMapBuffer[shift] != 0.0 && LowMapBuffer[shift] < lastlow && HighMapBuffer[shift] == 0.0) { ZigzagBuffer[lastlowpos]=0.0; lastlowpos=shift; lastlow=LowMapBuffer[shift]; ZigzagBuffer[shift]=lastlow; res=1; } if(HighMapBuffer[shift] != 0.0 && LowMapBuffer[shift] == 0.0) { lasthigh = HighMapBuffer[shift]; lasthighpos = shift; ZigzagBuffer[shift] = lasthigh; whatlookfor = -1; res = 1; } break; // look for lawn case -1: if(HighMapBuffer[shift] != 0.0 && HighMapBuffer[shift] > lasthigh && LowMapBuffer[shift] == 0.0) { ZigzagBuffer[lasthighpos] = 0.0; lasthighpos = shift; lasthigh = HighMapBuffer[shift]; ZigzagBuffer[shift] = lasthigh; } if(LowMapBuffer[shift] != 0.0 && HighMapBuffer[shift] == 0.0) { lastlow = LowMapBuffer[shift]; lastlowpos = shift; ZigzagBuffer[shift] = lastlow; whatlookfor = 1; } break; default: return; } } //---- return(0); } //+------------------------------------------------------------------+