//+------------------------------------------------------------------+ //| ZigZag on Parabolic | //| Copyright © 2009, EarnForex | //| http://www.earnforex.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright © 2009, EarnForex" #property link "http://www.earnforex.com" #property version "1.01" #property description "ZigZag on Parabolic - an improved version of the standard MT4 indicator." #property indicator_chart_window #property indicator_buffers 3 #property indicator_plots 2 #property indicator_color1 Aqua #property indicator_color2 Blue #property indicator_type1 DRAW_ZIGZAG #property indicator_style1 STYLE_SOLID #property indicator_width1 1 #property indicator_type2 DRAW_ARROW #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--input variables input double Step = 0.02; // Beginning/Step input double Maximum = 0.2; // End value input bool ExtremumsShift = true; //false - position of detection in time; true - actual position input int History = 0; //Amount of bars to use; 0 - all int EShift; //-- double ZigUp[], ZigDn[], SAR[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void OnInit() { IndicatorSetString(INDICATOR_SHORTNAME, "ZigZagOnParabolic(" + Step + "," + Maximum + ")"); //---- indicator buffers mapping SetIndexBuffer(0, ZigUp, INDICATOR_DATA); SetIndexBuffer(1, ZigDn, INDICATOR_DATA); SetIndexBuffer(2, SAR, INDICATOR_DATA); ArraySetAsSeries(ZigUp, true); ArraySetAsSeries(ZigDn, true); ArraySetAsSeries(SAR, true); ArrayInitialize(ZigUp, 0.0); ArrayInitialize(ZigDn, 0.0); ArrayInitialize(SAR, 0.0); PlotIndexSetInteger(1, PLOT_ARROW, 159); PlotIndexSetString(0, PLOT_LABEL, "ZigZag"); PlotIndexSetString(1, PLOT_LABEL, "SAR"); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0); if (ExtremumsShift) EShift = 1; else EShift = 0; } //+------------------------------------------------------------------+ //| Custom BB_MACD | //+------------------------------------------------------------------+ 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[]) { ArraySetAsSeries(High, true); ArraySetAsSeries(Low, true); static int BarsPrev; //Previous rates_total bool MissBars = ((rates_total - BarsPrev) > 1); //Need to count on some bars int NewBar = 0; if ((rates_total - BarsPrev) == 1) NewBar = 1; //First tick of the latest bar if (MissBars && (BarsPrev != 0)) BarsPrev = reinit(); //Recount bars int limit = rates_total - BarsPrev; //Amount of bars to recalculate if (BarsPrev == 0) limit -= 2; BarsPrev = rates_total; if ((History != 0) && (limit > History)) limit = History - 2; //Normalizing with the History input parameter int mySAR = iSAR(NULL, 0, Step, Maximum); CopyBuffer(mySAR, 0, 0, limit, SAR); for (int i = limit; i >= 0; i--) { double mid[2]; //Average price mid[0] = (High[i] + Low[i]) / 2; //Current bar mid[1] = (High[i + 1] + Low[i + 1]) / 2; //Previous bar static int j; //Counter for the shift between the extremum detection and it's position static bool dir; //Direction: false - down, true - up static double h, l; //Current extremums int shift; //Shift between extremum detections and it's position if (i > 0) j++; //If bar is over than increment the counter of shift if (dir) //Up { if (h < High[i]) { h = High[i]; //New peak j = NewBar; //Reset counter } if ((SAR[i + 1] <= mid[1]) && (SAR[i] > mid[0])) //Reverse of Parabolic SAR { shift = i + EShift * (j + NewBar); if (shift > (rates_total - 1)) shift = rates_total - 1; ZigUp[shift] = h; //Peak dir = false; //Down l = Low[i]; //New current low j = 0; //Reset counter } } else //Down { if (l > Low[i]) { l = Low[i]; //New low j = NewBar; //Reset counter } if ((SAR[i + 1] >= mid[1]) && (SAR[i] < mid[0])) //Reverse of Parabolic SAR { shift = i + EShift * (j + NewBar); if (shift > (rates_total - 1)) shift = rates_total - 1; ZigDn[shift] = l; //Low dir = true; //Up h = High[i]; //New current peak j = 0; //Reset counter } } } return(rates_total); } //============================================================= //Additional reinitilization function int reinit() { ArrayInitialize(ZigUp, 0.0); ArrayInitialize(ZigDn, 0.0); ArrayInitialize(SAR, 0.0); return(0); }