/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Indicator // --------------------------------------------- // Name: XZG // Description: Zogzag Implementation ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://saherelm.ir" #property version "1.00" #property description "SaherElm XZG Indicator" #property strict // #define ShortName "XZG" // // DEFINITIONS ... enum ENUM_X_ZG_SEARCH_MODE { X_ZG_SEARCH_EXTREMUM = 0, // searching for the first extremum X_ZG_SEARCH_PEAK = 1, // searching for the next ZigZag peak X_ZG_SEARCH_VALE = -1 // searching for the next ZigZag vale }; // // How to Calculate Up and Down Price ... enum ENUM_X_ZG_PRICE_MODE { // X_ZG_PRICE_HIGH_LOW_MODE = 1, X_ZG_PRICE_OPEN_CLOSE_MODE = 2, }; // // INPUT ... // input group "Market"; input int depth = 12; // Depth input int deviation = 5; // Deviation input int backStep = 3; // Back Step input ENUM_X_ZG_PRICE_MODE mode = X_ZG_PRICE_HIGH_LOW_MODE; // Mode // input group "Presentation"; input bool showZigZag = true; // Show ZigZag input bool showPeaksAndVales = true; // Show Peaks and Vales // // BUFFERS ... // #property indicator_chart_window // #property indicator_buffers 6 #property indicator_plots 4 // // ZigZag ... // #define mainBufferIndex 0 #define mainBufferPlotIndex 0 double mainBuffer[]; #define mainColorBufferIndex 1 double mainColorBuffer[]; // #property indicator_label1 "XZG Main" #property indicator_type1 DRAW_COLOR_SECTION #property indicator_color1 CLR_NONE, clrRoyalBlue, clrSaddleBrown #property indicator_width1 2 // // Highs ... // // ZigZag Pointer or Line Indicator ... #define arrowBufferIndex 2 #define arrowBufferPlotIndex 1 double arrowBuffer[]; // #define arrowColorBufferIndex 3 double arrowColorBuffer[]; // #property indicator_label2 "XZG PV" #property indicator_type2 DRAW_COLOR_ARROW #property indicator_color2 CLR_NONE, clrAqua, clrMagenta #property indicator_width2 1 // #define highsBufferIndex 4 double highsBuffer[]; // // Lows ... // #define lowsBufferIndex 5 double lowsBuffer[]; // // VARIABLES ... // int mRecalc = 3; // Number of last extremes for recalculation // // EVENT Handlers ... // // Initialization ... int OnInit() { // // Validate Inputs ... if (!ValidateInputs()) { return INIT_PARAMETERS_INCORRECT; } // // logTag = ShortName; // // Define Index Buffers ... DefineBuffers(); // // Set Indicator ShortName ... SetIndicatorName(); // // Init Succeed ... return INIT_SUCCEEDED; } // // DeInitialization ... void OnDeinit(const int reason) { // // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function // REASON_REMOVE 1 Program removed from a chart // REASON_RECOMPILE 2 Program recompiled // REASON_CHARTCHANGE 3 A symbol or a chart period is changed // REASON_CHARTCLOSE 4 Chart closed // REASON_PARAMETERS 5 Inputs changed by a user // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings // REASON_TEMPLATE 7 Another chart template applied // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value // REASON_CLOSE 9 Terminal closed } // // Calculating what we want ... int OnCalculate( const int rates_total, // Total Bars on Chart ... const int prev_calculated, // Total Calculated Bars on Charts ... const datetime &time[], // History of Open Time ... const double &open[], // History of Open Price ... const double &high[], // History of High Price ... const double &low[], // History of Low Price ... const double &close[], // History of Close Price ... const long &tick_volume[], // History of Tick Volumes on Bar ... const long &volume[], // History of Trade Volumes ... const int &spread[] // History of Spread Price ... ) { // double mZGHigh[]; double mZGLow[]; if (mode == X_ZG_PRICE_OPEN_CLOSE_MODE) { // ArrayCopy( mZGHigh, open // ); // ArrayCopy( mZGLow, close // ); } else { // ArrayCopy( mZGHigh, high // ); // ArrayCopy( mZGLow, low // ); } // int zigZagResult = CalcukateZigZag( prev_calculated, rates_total, mZGHigh, mZGLow // ); // if (zigZagResult != rates_total) { return zigZagResult; } // return rates_total; } // // CUSTOM Functions ... // // Validate Input Args for Initialization ... bool ValidateInputs() { // bool result = false; // result = // depth > 0 && deviation > 0 && backStep > 0 // ; // return result; } // // Define Indexes and Styles ... void DefineBuffers() { // // Main ... // SetIndexBuffer(mainBufferIndex, mainBuffer, INDICATOR_DATA); SetIndexBuffer(mainColorBufferIndex, mainColorBuffer, INDICATOR_COLOR_INDEX); // PlotIndexSetInteger(mainBufferPlotIndex, PLOT_SHOW_DATA, showZigZag); PlotIndexSetInteger(mainBufferPlotIndex, PLOT_DRAW_BEGIN, 0); PlotIndexSetDouble(mainBufferPlotIndex, PLOT_EMPTY_VALUE, 0); // // Arrow ... // SetIndexBuffer(arrowBufferIndex, arrowBuffer, INDICATOR_DATA); // PlotIndexSetInteger(arrowBufferPlotIndex, PLOT_SHOW_DATA, showPeaksAndVales); PlotIndexSetInteger(arrowBufferPlotIndex, PLOT_DRAW_BEGIN, 0); PlotIndexSetInteger(arrowBufferPlotIndex, PLOT_ARROW, 159); PlotIndexSetInteger(arrowBufferPlotIndex, PLOT_ARROW_SHIFT, 0); PlotIndexSetDouble(arrowBufferPlotIndex, PLOT_EMPTY_VALUE, 0); // // Arrow Color ... SetIndexBuffer(arrowColorBufferIndex, arrowColorBuffer, INDICATOR_COLOR_INDEX); // // Highs ... SetIndexBuffer(highsBufferIndex, highsBuffer, INDICATOR_CALCULATIONS); // // Lows ... SetIndexBuffer(lowsBufferIndex, lowsBuffer, INDICATOR_CALCULATIONS); } // // Set Indicator Short Name and also we can define Buffers Labels ... void SetIndicatorName() { IndicatorSetString(INDICATOR_SHORTNAME, ShortName); } // // Calculating Zig Zag ... int CalcukateZigZag( const int prev_calculated, const int rates_total, double &high[], double &low[] // ) { // if (rates_total < 100) { return 0; } // // Define Variables ... int i = 0; // int start = 0; int extreme_counter = 0; int extreme_search = X_ZG_SEARCH_EXTREMUM; int shift = 0; int back = 0; int last_high_pos = 0; int last_low_pos = 0; // double val = 0; double res = 0; double curlow = 0; double curhigh = 0; double last_high = 0; double last_low = 0; // double colorIDX = 0; double lastZigZagValue = 0; // // Initializing ... if (prev_calculated == 0) { // ArrayInitialize(mainBuffer, 0); ArrayInitialize(highsBuffer, 0); ArrayInitialize(lowsBuffer, 0); // start = depth; } // // Already Calculated Before ... if (prev_calculated > 0) { // i = rates_total - 1; // // Searching for the third X_ZG_SEARCH_EXTREMUM from the last UnComplete Bar ... while (extreme_counter < mRecalc && i > rates_total - 100) { // res = mainBuffer[i]; if (res != 0) { extreme_counter++; } // i--; } // i++; start = i; // // What type of X_ZG_SEARCH_EXTREMUM we Search for ... if (lowsBuffer[i] != 0) { // curlow = lowsBuffer[i]; extreme_search = X_ZG_SEARCH_PEAK; } else { // curhigh = highsBuffer[i]; extreme_search = X_ZG_SEARCH_VALE; } // // Clear Values ... for (i = start + 1; i < rates_total && !IsStopped(); i++) { // mainBuffer[i] = 0; lowsBuffer[i] = 0; highsBuffer[i] = 0; } } // // Search for High and Low Extremes ... for (shift = start; shift < rates_total && !IsStopped(); shift++) { // // Low ... val = low[Lowest(low, depth, shift)]; if (val == last_low) { val = 0; } else { // last_low = val; // if ((low[shift] - val) > deviation * _Point) { val = 0; } else { // for (back = 1; back <= backStep; back++) { // res = lowsBuffer[shift - back]; if ((res != 0) && (res > val)) { lowsBuffer[shift - back] = 0; } } } } // if (low[shift] == val) { lowsBuffer[shift] = val; } else { lowsBuffer[shift] = 0; } // // High ... val = high[Highest(high, depth, shift)]; if (val == last_high) { val = 0; } else { // last_high = val; // if ((val - high[shift]) > deviation * _Point) { val = 0; } else { // for (back = 1; back <= backStep; back++) { // res = highsBuffer[shift - back]; if ((res != 0) && (res < val)) { highsBuffer[shift - back] = 0; } } } } // if (high[shift] == val) { highsBuffer[shift] = val; } else { highsBuffer[shift] = 0; } } // // Set Last Value ... if (extreme_search == 0) // Undefined Values ... { // last_low = 0; last_high = 0; } else { // last_low = curlow; last_high = curhigh; } // // Final Selection of Extreme Points for ZigZag ... for (shift = start; shift < rates_total && !IsStopped(); shift++) { // res = 0; // switch (extreme_search) { // case X_ZG_SEARCH_EXTREMUM: // if (last_low == 0 && last_high == 0) { // if (highsBuffer[shift] != 0) { // last_high_pos = shift; last_high = high[shift]; // extreme_search = X_ZG_SEARCH_VALE; // mainBuffer[shift] = last_high; // res = 1; } // if (lowsBuffer[shift] != 0) { // last_low_pos = shift; last_low = low[shift]; // extreme_search = X_ZG_SEARCH_PEAK; // mainBuffer[shift] = last_low; // res = 1; } } break; // case X_ZG_SEARCH_PEAK: // if (lowsBuffer[shift] != 0 && lowsBuffer[shift] < last_low && highsBuffer[shift] == 0) { // mainBuffer[last_low_pos] = 0; // last_low_pos = shift; last_low = lowsBuffer[shift]; // mainBuffer[shift] = last_low; // res = 1; } // if (highsBuffer[shift] != 0 && lowsBuffer[shift] == 0) { // last_high_pos = shift; last_high = highsBuffer[shift]; // mainBuffer[shift] = last_high; // extreme_search = X_ZG_SEARCH_VALE; // res = 1; } break; // case X_ZG_SEARCH_VALE: // if (highsBuffer[shift] != 0 && highsBuffer[shift] > last_high && lowsBuffer[shift] == 0) { // mainBuffer[last_high_pos] = 0; // last_high_pos = shift; last_high = highsBuffer[shift]; // mainBuffer[shift] = last_high; } // if (lowsBuffer[shift] != 0 && highsBuffer[shift] == 0) { // last_low_pos = shift; last_low = lowsBuffer[shift]; // mainBuffer[shift] = last_low; // extreme_search = X_ZG_SEARCH_PEAK; } break; } // double iZigZagForColor = lastZigZagValue; double iZigZag = mainBuffer[shift]; if (iZigZag == 0 && lastZigZagValue != 0) { arrowBuffer[shift] = lastZigZagValue; } else if (iZigZag != 0) { // lastZigZagValue = iZigZag; arrowBuffer[shift] = lastZigZagValue; } // colorIDX = lastZigZagValue > iZigZagForColor ? 1 : lastZigZagValue < iZigZagForColor ? 2 : colorIDX; // mainColorBuffer[shift] = showZigZag ? colorIDX : 0; arrowColorBuffer[shift] = showPeaksAndVales ? colorIDX : 0; } // return rates_total; } // // TOOLS ... // // Search for the index of the highest bar ... int Highest( const double &mArray[], const int mDepth, const int mStart // ) { // int result = 0; // if (mStart < 0) { return result; } // double max = mArray[mStart]; result = mStart; // // Start searching ... for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) { // if (mArray[i] > max) { // result = i; max = mArray[i]; } } // // Return index of the highest bar return result; } // // Search for the index of the lowest bar ... int Lowest( const double &mArray[], const int mDepth, const int mStart // ) { // int result = 0; // if (mStart < 0) { return result; } // double min = mArray[mStart]; result = mStart; // // Start searching ... for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) { // if (mArray[i] < min) { // result = i; min = mArray[i]; } } // // Return index of the lowest bar return result; }