//+------------------------------------------------------------------+ //| ZigZag_2_Line.mq5 | //|Added lines - https://www.mql5.com/ru/users/ich_hub 16.05.2017 | //+------------------------------------------------------------------+ //| ZigZag.mq5 | //| Copyright 2009, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "2009, MetaQuotes Software Corp." #property link "http://www.mql5.com" #property version "1.3" #property indicator_chart_window #property indicator_buffers 3 #property indicator_plots 1 //---- plot Zigzag #property indicator_label1 "Zigzag" #property indicator_type1 DRAW_SECTION #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- input parameters input int ExtDepth=12; input int ExtDeviation=5; input int ExtBackstep=3; input bool ObjLineDel=true; //--- indicator buffers double ZigzagBuffer[]; // main buffer double HighMapBuffer[]; // highs double LowMapBuffer[]; // lows int level=3; // recounting depth double deviation; // deviation in points double price_zig[10]; // Last Point Buffer Price datetime time_zig[10]; // Last Point Buffer Time double pr_1=0,pr_2=0; datetime t_1=0,t_2=0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,ZigzagBuffer,INDICATOR_DATA); SetIndexBuffer(1,HighMapBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(2,LowMapBuffer,INDICATOR_CALCULATIONS); //--- set short name and digits PlotIndexSetString(0,PLOT_LABEL,"ZigZag("+(string)ExtDepth+","+(string)ExtDeviation+","+(string)ExtBackstep+")"); IndicatorSetInteger(INDICATOR_DIGITS,_Digits); //--- set empty value PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); //--- to use in cycle deviation=ExtDeviation*_Point; //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(ObjLineDel) { ObjectDelete(0,"ZZCR1"); ObjectDelete(0,"ZZCR2"); } } //+------------------------------------------------------------------+ //| searching index of the highest bar | //+------------------------------------------------------------------+ int iHighest(const double &array[], int depth, int startPos) { int index=startPos; //--- start index validation if(startPos<0) { Print("Invalid parameter in the function iHighest, startPos =",startPos); return 0; } int size=ArraySize(array); //--- depth correction if need if(startPos-depth<0) depth=startPos; double max=array[startPos]; //--- start searching for(int i=startPos;i>startPos-depth;i--) { if(array[i]>max) { index=i; max=array[i]; } } //--- return index of the highest bar return(index); } //+------------------------------------------------------------------+ //| searching index of the lowest bar | //+------------------------------------------------------------------+ int iLowest(const double &array[], int depth, int startPos) { int index=startPos; //--- start index validation if(startPos<0) { Print("Invalid parameter in the function iLowest, startPos =",startPos); return 0; } int size=ArraySize(array); //--- depth correction if need if(startPos-depth<0) depth=startPos; double min=array[startPos]; //--- start searching for(int i=startPos;i>startPos-depth;i--) { if(array[i]0) { i=rates_total-1; //--- searching third extremum from the last uncompleted bar while(counterZrates_total-100) { res=ZigzagBuffer[i]; if(res!=0) counterZ++; i--; } i++; limit=i; //--- what type of exremum we are going to find if(LowMapBuffer[i]!=0) { curlow=LowMapBuffer[i]; whatlookfor=Pike; } else { curhigh=HighMapBuffer[i]; whatlookfor=Sill; } //--- chipping for(i=limit+1;ideviation) 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(high,ExtDepth,shift)]; if(val==lasthigh) val=0.0; else { lasthigh=val; if((val-high[shift])>deviation) val=0.0; else { for(back=1;back<=ExtBackstep;back++) { res=HighMapBuffer[shift-back]; if((res!=0) && (reslasthigh && 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=Pike; } break; default: return(rates_total); } } //Let's find our points bool fl_stop=false; shift=0; int n=0; bool fl_low=false; ArraySetAsSeries(ZigzagBuffer,true); ArraySetAsSeries(time,true); ArraySetAsSeries(low,true); while(!fl_stop && !IsStopped()) { if(ZigzagBuffer[shift]!=0) { if(n>0) { if((ND(ZigzagBuffer[shift])-ND(low[shift])==0.0)) { price_zig[n]=ZigzagBuffer[shift]; if((n-1)==0) fl_low=true; } else { price_zig[n]=ZigzagBuffer[shift]; } time_zig[n]=iTimeMQL4(Symbol(),Period(),shift); } n++; if(n>=6) fl_stop=true; } shift++; } //Draw the lines if(fl_low) { SetLowZZ(price_zig[2],price_zig[4],time_zig[2],time_zig[4]); SetHighZZ(price_zig[1],price_zig[3],time_zig[1],time_zig[3]); } else { SetLowZZ(price_zig[1],price_zig[3],time_zig[1],time_zig[3]); SetHighZZ(price_zig[2],price_zig[4],time_zig[2],time_zig[4]); } //--- return value of prev_calculated for next call return(rates_total); } //+-------------------------------------------------------------------------------------+ //| Converting values to the accuracy of one item | //+-------------------------------------------------------------------------------------+ double ND(double A) { return(NormalizeDouble(A, _Digits)); } //+------------------------------------------------------------------+ //| https://www.mql5.com/ru/articles/81 | //+------------------------------------------------------------------+ datetime iTimeMQL4(string symbol,int tf,int index) { if(index < 0) return(-1); ENUM_TIMEFRAMES timeframe=TFMigrate(tf); datetime Arr[]; if(CopyTime(symbol,timeframe,index,1,Arr)>0) return(Arr[0]); else return(-1); } //+------------------------------------------------------------------+ //================================================================================================= void SetLowZZ(double price_1,double price_2,datetime time_1,datetime time_2) { ObjectDelete(0,"ZZCR1"); ObjectCreate(0,"ZZCR1",OBJ_TREND,0,time_2,price_2,time_1,price_1); ObjectSetInteger(0,"ZZCR1",OBJPROP_COLOR,clrAqua); ObjectSetInteger(0,"ZZCR1",OBJPROP_WIDTH,2); ObjectSetInteger(0,"ZZCR1",OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(0,"ZZCR1",OBJPROP_BACK,false); ObjectSetInteger(0,"ZZCR1",OBJPROP_RAY_RIGHT,true); } //================================================================================================= void SetHighZZ(double price_1,double price_2,datetime time_1,datetime time_2) { ObjectDelete(0,"ZZCR2"); ObjectCreate(0,"ZZCR2",OBJ_TREND,0,time_2,price_2,time_1,price_1); ObjectSetInteger(0,"ZZCR2",OBJPROP_COLOR,clrKhaki); ObjectSetInteger(0,"ZZCR2",OBJPROP_WIDTH,2); ObjectSetInteger(0,"ZZCR2",OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(0,"ZZCR2",OBJPROP_BACK,false); ObjectSetInteger(0,"ZZCR2",OBJPROP_RAY_RIGHT,true); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ ENUM_TIMEFRAMES TFMigrate(int tf) { switch(tf) { case 0: return(PERIOD_CURRENT); case 1: return(PERIOD_M1); case 5: return(PERIOD_M5); case 15: return(PERIOD_M15); case 30: return(PERIOD_M30); case 60: return(PERIOD_H1); case 240: return(PERIOD_H4); case 1440: return(PERIOD_D1); case 10080: return(PERIOD_W1); case 43200: return(PERIOD_MN1); case 2: return(PERIOD_M2); case 3: return(PERIOD_M3); case 4: return(PERIOD_M4); case 6: return(PERIOD_M6); case 10: return(PERIOD_M10); case 12: return(PERIOD_M12); case 16385: return(PERIOD_H1); case 16386: return(PERIOD_H2); case 16387: return(PERIOD_H3); case 16388: return(PERIOD_H4); case 16390: return(PERIOD_H6); case 16392: return(PERIOD_H8); case 16396: return(PERIOD_H12); case 16408: return(PERIOD_D1); case 32769: return(PERIOD_W1); case 49153: return(PERIOD_MN1); default: return(PERIOD_CURRENT); } } //+------------------------------------------------------------------+