/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Library // ------------------------------------------------- // Name: XCXFIMAEALib ... // Description: XFIMAEA Library ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://saherelm.ir" #property version "1.00" #property description "SaherElm XFIMAEA Library" #property strict // // Imports ... #include "../../Helpers/x-saherelm.xfima.helper.mq5" // // Definitions ... // // Enumerations ... // // ZigZag Point Type ... enum ENUM_X_ZIGZAG_POINT_TYPE { X_ZIGZAG_POINT_TYPE_NONE = 0, // None X_ZIGZAG_POINT_TYPE_PEAK = 1, // PEAK X_ZIGZAG_POINT_TYPE_VALE = 2, // VALE }; /** * Validate ... * * @param value: ENUM_X_ZIGZAG_POINT_TYPE ... * * @return ( bool ) */ bool IsXValid(ENUM_X_ZIGZAG_POINT_TYPE value) { // bool result = false; // result = value != X_ZIGZAG_POINT_TYPE_NONE; // return result; } /** * Represent Specified ZigZag Point Type as String ... * * @param value: ENUM_X_ZIGZAG_POINT_TYPE ... * * @return ( string ) */ string ToXString(ENUM_X_ZIGZAG_POINT_TYPE value) { return EnumToString(value); } // // Structs ... /** * Specified ZigZag Point ... **/ struct XZigZagPoint { // // Props ... double value; // Value datetime time; // Time string symbol; // Symbol ENUM_X_DIRECTION dir; // Direction ENUM_TIMEFRAMES period; // Period ENUM_X_ZIGZAG_POINT_TYPE type; // Type // // Constructor ... XZigZagPoint() { Clean(); } // // Init ... /** * Initialize Structure ... * * @param _value: double, value of point ... * @param _time: datetime, time of point ... * @param _symbol: string, Symbol ... * @param _dir: ENUM_X_DIRECTION, direction of point ... * @param _period: ENUM_TIMEFRAMES, period ... * @param _type: ENUM_X_ZIGZAG_POINT_TYPE, point type ... * * @return ( bool ) */ bool Init( double _value, datetime _time, string _symbol, ENUM_X_DIRECTION _dir, ENUM_TIMEFRAMES _period, ENUM_X_ZIGZAG_POINT_TYPE _type // ) { // bool result = false; // dir = _dir; time = _time; type = _type; value = _value; symbol = _symbol; period = _period; // result = IsValid(); if (!result) { Clean(); } // return result; } // // Tools ... /** * Cleanup Model ... */ void Clean() { // value = 0; time = NULL; symbol = NULL; period = NULL; dir = X_DIRECTION_NONE; type = X_ZIGZAG_POINT_TYPE_NONE; // ZeroMemory(this); } /** * Validate Model ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = value > 0 && IsXValid(type) && HasDirection(dir) && IsSpecifiedValid(time) && IsSpecifiedValid(symbol) && IsSpecifiedValid(period); // return result; } /** * Check Point is Bullish or not ... * * @return ( bool ) */ bool IsBullish() { // bool result = false; // result = IsValid() && IsSpecifiedBullish(dir); // return result; } /** * Check Point is Bearish or not ... * * @return ( bool ) */ bool IsBearish() { // bool result = false; // result = IsValid() && IsSpecifiedBearish(dir); // return result; } /** * Check two Struct are Same or not ... * * @param item: XZigZagPoint ... * * @return ( bool ) */ bool IsSameAs(XZigZagPoint &item) { // bool result = false; // result = IsValid() && item.IsValid() && dir == item.dir && type == item.type && time == item.time && value == item.value && symbol == item.symbol && period == item.period; // return result; } /** * Check Structure Exists in Specified Collection or not ... * * @param items: XZigZagPoint, reference Array ... * @param index: int, reference to Holds Founded Index ... * * @return ( bool ) */ bool IsExists( XZigZagPoint &items[], int &index // ) { // bool result = false; // // Prepare ... index = -1; // // Validate ... result = IsValid() && HasChild(items); if (!result) { return result; } // int count = ArraySize(items); for (int i = 0; i < count; i++) { // result = IsSameAs(items[i]); if (result) { // index = i; // break; } } // result = result && IsValidIndex(index); // return result; } /** * Add Structure to Specified Collection only if not Exists ... * * @param items: XZigZagPoint, reference Array ... */ void AddIfNotExists(XZigZagPoint &items[]) { // // Validate ... if (!IsValid()) { return; } // if (!HasChild(items)) { // AddRef( this, items // ); // return; } // int index = -1; bool isExists = IsExists(items, index); if (!isExists) { // AddRef( this, items // ); } } // // Logging Tools ... /** * Extract Specified Token of Struct ... * * @return ( string ) */ string GetTag() { return GetToken(this); } /** * Represent an String Unique Identifier for Chart Objects ... * * @return ( string ) */ string GetObjectID() { // string result = ""; // if (!IsValid()) { return result; } // result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_" + ToXString(dir) + "_" + ToXString(type) + "_" + ToXString(TimeToSeconds(time)); // return result; } /** * Represent a Point as String ... * * @param spacer: string, How to Represent Spaces ... * * @return ( string ) */ string GetMessage(string spacer = NULL) { // string result = ""; // // Normalize Spacer ... if (!IsSpecifiedValid(spacer)) { spacer = " "; } // // Validate ... if (!IsValid()) { return result; } // result = ToXString(dir) + spacer + GetTag() + ":" + spacer + "Symbol: " + symbol + spacer + "Period: " + ToXString(period) + spacer + "Type: " + ToXString(type) + spacer + "Direction: " + ToXString(dir) + spacer + "Value: " + ToXString(value) + spacer + "Time: " + ToXString(time) + spacer; // return result; } }; /** * Specified ZigZag based Market Analysis ... **/ struct XZigZagAnalysis { // // Props ... string symbol; // Symbol ... datetime time; // Time ... ENUM_TIMEFRAMES period; // Period ... XZigZagPoint pivots[]; // ZigZag Pivots ... // ENUM_X_DIRECTION dir; // Direction ... // // Pivots ... // XZigZagPoint lastPeak; XZigZagPoint recentPeak; // XZigZagPoint lastVale; XZigZagPoint recentVale; // // Constructor ... XZigZagAnalysis() { Clean(); } // // Initialize ... /** * Analyse Market Structure ... * * @param bar: XOHCL, Specified Bar ... * @param points: XZigZagPoint, Specified ZigZag Points Collection ... * * @return ( bool ) */ bool Analyse( XOHCL &bar, XZigZagPoint &points[] // ) { // bool result = false; // // Validate ... result = bar.IsValid() && HasChild(points) && bar.symbol == points[0].symbol; if (!result) { // Clean(); return result; } // // AssignSymbol and Period ... time = bar.time; symbol = bar.symbol; period = bar.period; // // Detect At lease Two PEAK and Two Vale ... XZigZagPoint tmpPoints[]; Copy( points, tmpPoints // ); // // Detect Highs ... // // Highest High ... // XZigZagPoint iZGPeak1; XZigZagPoint iZGPeak2; // // First ... int idx = GetHighest( tmpPoints, X_ZIGZAG_POINT_TYPE_PEAK // ); result = IsValidIndex(idx); if (!result) { // Clean(); iZGPeak1.Clean(); iZGPeak2.Clean(); SpecifiedClean(tmpPoints); // return result; } iZGPeak1 = tmpPoints[idx]; ArrayRemove( tmpPoints, idx, 1 // ); // // Second ... idx = GetHighest( tmpPoints, X_ZIGZAG_POINT_TYPE_PEAK // ); result = IsValidIndex(idx); if (!result) { // Clean(); iZGPeak1.Clean(); iZGPeak2.Clean(); SpecifiedClean(tmpPoints); // return result; } iZGPeak2 = tmpPoints[idx]; ArrayRemove( tmpPoints, idx, 1 // ); // // Detect Lows ... // XZigZagPoint iZGVale1; XZigZagPoint iZGVale2; // // First ... idx = GetLowest( tmpPoints, X_ZIGZAG_POINT_TYPE_VALE // ); result = IsValidIndex(idx); if (!result) { // Clean(); iZGPeak1.Clean(); iZGPeak2.Clean(); iZGVale1.Clean(); iZGVale2.Clean(); SpecifiedClean(tmpPoints); // return result; } iZGVale1 = tmpPoints[idx]; ArrayRemove( tmpPoints, idx, 1 // ); // // Second ... idx = GetLowest( tmpPoints, X_ZIGZAG_POINT_TYPE_VALE // ); result = IsValidIndex(idx); if (!result) { // Clean(); iZGPeak1.Clean(); iZGPeak2.Clean(); iZGVale1.Clean(); iZGVale2.Clean(); SpecifiedClean(tmpPoints); // return result; } iZGVale2 = tmpPoints[idx]; ArrayRemove( tmpPoints, idx, 1 // ); // // Check Directions ... bool isBullish = // (iZGPeak1.time > iZGPeak2.time && iZGVale1.time < iZGVale2.time) // ; bool isBearish = // (iZGPeak1.time < iZGPeak2.time && iZGVale1.time > iZGVale2.time) // ; result = (isBullish && !isBearish) || (isBearish && !isBullish); if (!result) { // Clean(); iZGPeak1.Clean(); iZGPeak2.Clean(); iZGVale1.Clean(); iZGVale2.Clean(); SpecifiedClean(tmpPoints); // return result; } // // Setting Direction ... dir = isBullish ? X_DIRECTION_BULLISH : isBearish ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; // // Setting Points ... Copy( points, pivots // ); // // Assigning Peaks and Vales ... if (result) { // lastPeak = iZGPeak1; lastVale = iZGVale1; recentPeak = iZGPeak2; recentVale = iZGVale2; } // // Calculate Support and Resistance ... // // Validate ... result = IsValid(); if (!result) { Clean(); } // // Cleanup Resources ... iZGPeak1.Clean(); iZGPeak2.Clean(); iZGVale1.Clean(); iZGVale2.Clean(); SpecifiedClean(tmpPoints); // return result; } // // Tools ... /** * Cleanup Model ... */ void Clean() { // time = NULL; symbol = NULL; period = NULL; dir = X_DIRECTION_NONE; SpecifiedClean(pivots); // lastPeak.Clean(); lastVale.Clean(); recentPeak.Clean(); recentVale.Clean(); // ZeroMemory(this); } /** * Validate Model ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = // HasChild(pivots) && HasDirection(dir) && IsSpecifiedValid(time) && IsSpecifiedValid(symbol) && IsSpecifiedValid(period) && // lastPeak.IsValid() && lastVale.IsValid() && recentPeak.IsValid() && recentVale.IsValid() // ; // return result; } /** * Calculate Analysis Age, based on Specified Time Frame ... * * @param forPeriod: ENUM_TIMEFRAMES, Specified Period ... * * @return ( int ) */ int GetAge( ENUM_TIMEFRAMES forPeriod = NULL // ) { // int result = -1; // // Validate ... if (!IsValid()) { return result; } // // Normalize ... if (!IsSpecifiedValid(forPeriod)) { forPeriod = period; } // result = GetBarIndex( symbol, forPeriod, time // ); // return result; } /** * Check two item is Same or not ... * * @param item: XZigZagAnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSameAs(XZigZagAnalysis &item) { // bool result = false; // result = IsValid() && item.IsValid() && time == item.time && IsSameMarketAs(item); // return result; } /** * Check to model Has Same Symbol ... * * @param item: XZigZagAnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSameSymbolAs(XZigZagAnalysis &item) { // bool result = false; // result = IsValid() && item.IsValid() && symbol == item.symbol; // return result; } /** * Check to model Has Same Period ... * * @param item: XZigZagAnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSamePeriodAs(XZigZagAnalysis &item) { // bool result = false; // result = IsValid() && item.IsValid() && period == item.period; // return result; } /** * Check to model Has Same Symbol/Period ... * * @param item: XZigZagAnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSameMarketAs(XZigZagAnalysis &item) { // bool result = false; // result = IsValid() && item.IsValid() && IsSameSymbolAs(item) && IsSamePeriodAs(item); // return result; } /** * Check to model Has Same Direction ... * * @param item: XZigZagAnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSameDirectionAs(XZigZagAnalysis &item) { // bool result = false; // result = IsValid() && item.IsValid() && dir == item.dir; // return result; } /** * Check to model Has Analysis Trend ... * * @param item: XZigZagAnalysis, dest model for Checking ... * * @return ( bool ) */ bool IsSameTrendAs(XZigZagAnalysis &item) { // bool result = false; // result = IsValid() && item.IsValid() && IsSameMarketAs(item) && IsSameDirectionAs(item); // return result; } // // Loggint Tools ... /** * Extract Specified Token of Struct ... * * @return ( string ) */ string GetTag() { return GetToken(this); } /** * Represent an String Unique Identifier for Chart Objects ... * * @return ( string ) */ string GetObjectID() { // string result = ""; // if (!IsValid()) { return result; } // result = GetTag() + "_" + symbol + "_" + ToXString(period) + "_" + ToXString(dir) + "_" + ToXString(TimeToSeconds(time)); // return result; } /** * Represent a Point as String ... * * @param spacer: string, How to Represent Spaces ... * * @return ( string ) */ string GetMessage(string spacer = NULL) { // string result = ""; // // Normalize Spacer ... if (!IsSpecifiedValid(spacer)) { spacer = " "; } // // Validate ... if (!IsValid()) { return result; } // result = ToXString(dir) + spacer + GetTag() + ":" + spacer + "Symbol: " + symbol + spacer + "Period: " + ToXString(period) + spacer + "Direction: " + ToXString(dir) + spacer + "Time: " + ToXString(time) + spacer; // return result; } // }; // // Extensions ... /** * Get Highest ZigZagPoint Index in Specified Collection ... * * @param items: XZigZagPoint, Specified Points Collection to Search ... * @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Points Type ... * * @return ( int ) */ int GetHighest( XZigZagPoint &items[], ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_POINT_TYPE_NONE // ) { // int result = -1; // // Validate ... if (!HasChild(items)) { return result; } // bool has = false; XZigZagPoint iPoint; int count = ArraySize(items); for (int i = 0; i < count; i++) { // // Passed Type ... has = !IsXValid(type) ? true : type == items[i].type; // // Check Can Assign ... has = has && (!iPoint.IsValid() || (iPoint.IsValid() && items[i].value > iPoint.value)); if (has) { // result = i; iPoint = items[i]; } } // // Validate Result ... has = iPoint.IsValid() && IsValidIndex(result); if (!has) { // result = -1; iPoint.Clean(); return result; } // iPoint.Clean(); // return result; } /** * Get Lowest ZigZagPoint Index in Specified Collection ... * * @param items: XZigZagPoint, Specified Points Collection to Search ... * @param type: ENUM_X_ZIGZAG_POINT_TYPE, Specified Points Type ... * * @return ( int ) */ int GetLowest( XZigZagPoint &items[], ENUM_X_ZIGZAG_POINT_TYPE type = X_ZIGZAG_POINT_TYPE_NONE // ) { // int result = -1; // // Validate ... if (!HasChild(items)) { return result; } // bool has = false; XZigZagPoint iPoint; int count = ArraySize(items); for (int i = 0; i < count; i++) { // // Passed Type ... has = !IsXValid(type) ? true : type == items[i].type; // // Check Can Assign ... has = has && (!iPoint.IsValid() || (iPoint.IsValid() && items[i].value < iPoint.value)); if (has) { // result = i; iPoint = items[i]; } } // // Validate Result ... has = iPoint.IsValid() && IsValidIndex(result); if (!has) { // result = -1; iPoint.Clean(); return result; } // iPoint.Clean(); // return result; } //