//+------------------------------------------------------------------+ //| ZigZag.mq5 | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2000-2025, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #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 InpDepth =12; // Depth input int InpDeviation=5; // Deviation input int InpBackstep =3; // Back Step //--- indicator buffers double ZigZagBuffer[]; // main buffer double HighMapBuffer[]; // ZigZag high extremes (peaks) double LowMapBuffer[]; // ZigZag low extremes (bottoms) int ExtRecalc=3; // number of last extremes for recalculation enum EnSearchMode { Extremum=0, // searching for the first extremum Peak=1, // searching for the next ZigZag peak Bottom=-1 // searching for the next ZigZag bottom }; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,ZigZagBuffer,INDICATOR_DATA); SetIndexBuffer(1,HighMapBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(2,LowMapBuffer,INDICATOR_CALCULATIONS); //--- set short name and digits string short_name=StringFormat("ZigZag(%d,%d,%d)",InpDepth,InpDeviation,InpBackstep); IndicatorSetString(INDICATOR_SHORTNAME,short_name); PlotIndexSetString(0,PLOT_LABEL,short_name); IndicatorSetInteger(INDICATOR_DIGITS,_Digits); //--- set an empty value PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); } //+------------------------------------------------------------------+ //| ZigZag calculation | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { if(rates_total<100) return(0); //--- int i=0; int start=0,extreme_counter=0,extreme_search=Extremum; int shift=0,back=0,last_high_pos=0,last_low_pos=0; double val=0,res=0; double curlow=0,curhigh=0,last_high=0,last_low=0; //--- initializing if(prev_calculated==0) { ArrayInitialize(ZigZagBuffer,0.0); ArrayInitialize(HighMapBuffer,0.0); ArrayInitialize(LowMapBuffer,0.0); start=InpDepth; } //--- ZigZag was already calculated before if(prev_calculated>0) { i=rates_total-1; //--- searching for the third extremum from the last uncompleted bar while(extreme_counterrates_total-100) { res=ZigZagBuffer[i]; if(res!=0.0) extreme_counter++; i--; } i++; start=i; //--- what type of exremum we search for if(LowMapBuffer[i]!=0.0) { curlow=LowMapBuffer[i]; extreme_search=Peak; } else { curhigh=HighMapBuffer[i]; extreme_search=Bottom; } //--- clear indicator values for(i=start+1; iInpDeviation*_Point) val=0.0; else { for(back=1; back<=InpBackstep; 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[Highest(high,InpDepth,shift)]; if(val==last_high) val=0.0; else { last_high=val; if((val-high[shift])>InpDeviation*_Point) val=0.0; else { for(back=1; back<=InpBackstep; back++) { res=HighMapBuffer[shift-back]; if((res!=0) && (reslast_high && LowMapBuffer[shift]==0.0) { ZigZagBuffer[last_high_pos]=0.0; last_high_pos=shift; last_high=HighMapBuffer[shift]; ZigZagBuffer[shift]=last_high; } if(LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]==0.0) { last_low=LowMapBuffer[shift]; last_low_pos=shift; ZigZagBuffer[shift]=last_low; extreme_search=Peak; } break; default: return(rates_total); } } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| Search for the index of the highest bar | //+------------------------------------------------------------------+ int Highest(const double &array[],const int depth,const int start) { if(start<0) return(0); double max=array[start]; int index=start; //--- start searching for(int i=start-1; i>start-depth && i>=0; i--) { if(array[i]>max) { index=i; max=array[i]; } } //--- return index of the highest bar return(index); } //+------------------------------------------------------------------+ //| Search for the index of the lowest bar | //+------------------------------------------------------------------+ int Lowest(const double &array[],const int depth,const int start) { if(start<0) return(0); double min=array[start]; int index=start; //--- start searching for(int i=start-1; i>start-depth && i>=0; i--) { if(array[i]