/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Seriallize Library // --------------------------------------- // Name: XPOILib // Description: All models related to POIs ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright `023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Imports ... #include "../Libraries/x-saherelm.x-ohcl.lib.mq5" #include "../Libraries/x-saherelm.x-poi.lib.mq5" // // Extensions ... //+------------------------------------------------------------------+ //| Oldest Detection | //+------------------------------------------------------------------+ /** * Get Oldest Index of Specified Collection ... * * @param source: Specified Collection ... * * @return ( int ) */ int GetOldest( XBoxZone &source[] // ) { // int result = -1; // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XBoxZone selected; for (int i = 0; i < count; i++) { // bool canSet = !selected.IsValid() ? true : selected.from > source[i].from; if (canSet) { // result = i; selected = source[i]; } } // selected.Clean(); // return result; } /** * Get Oldest Index of Specified Collection ... * * @param bar: XOHCL, Specified Bar ... * @param source: Specified Collection ... * * @return ( int ) */ int GetOldestByBar( XOHCL &bar, XBoxZone &source[] // ) { // int result = -1; // if (!bar.IsValid()) { return result; } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XBoxZone selected; for (int i = 0; i < count; i++) { // bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, source[i]); if (!isBoxValidForBar) { continue; } // bool canSet = !selected.IsValid() ? true : selected.from > source[i].from; if (canSet) { // result = i; selected = source[i]; } } // selected.Clean(); // return result; } /** * Get Oldest Index of Specified Collection ... * * @param source: Specified Collection ... * @param type: ENUM_X_PIVOT_TYPE, Specified Points Type ... * * @return ( int ) */ int GetOldest( XPivot &source[], ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE // ) { // int result = -1; // // Validate ... if (!HasChild(source)) { return result; } // bool has = false; XPivot iPoint; int count = ArraySize(source); for (int i = 0; i < count; i++) { // // Passed Type ... has = !IsXValid(type) ? true : type == source[i].type; // // Check Can Assign ... has = has && (!iPoint.IsValid() || (iPoint.IsValid() && source[i].GetAge() > iPoint.GetAge())); if (has) { // result = i; iPoint = source[i]; } } // // Validate Result ... has = iPoint.IsValid() && IsValidIndex(result); if (!has) { // result = -1; iPoint.Clean(); return result; } // iPoint.Clean(); // return result; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Youngest Detection | //+------------------------------------------------------------------+ /** * Get Youngest Index of Specified Collection ... * * @param source: Specified Collection ... * * @return ( int ) */ int GetYoungest( XBoxZone &source[] // ) { // int result = -1; // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XBoxZone selected; for (int i = 0; i < count; i++) { // bool canSet = !selected.IsValid() ? true : selected.from < source[i].from; if (canSet) { // result = i; selected = source[i]; } } // selected.Clean(); // return result; } /** * Get Youngest Index of Specified Collection ... * * @param bar: XOHCL, Specified Bar ... * @param source: Specified Collection ... * * @return ( int ) */ int GetYoungestByBar( XOHCL &bar, XBoxZone &source[] // ) { // int result = -1; // if (!bar.IsValid()) { return result; } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XBoxZone selected; for (int i = 0; i < count; i++) { // bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, source[i]); if (!isBoxValidForBar) { continue; } // bool canSet = !selected.IsValid() ? true : selected.from < source[i].from; if (canSet) { // result = i; selected = source[i]; } } // selected.Clean(); // return result; } /** * Get Youngest Index of Specified Collection ... * * @param source: Specified Collection ... * @param type: ENUM_X_PIVOT_TYPE, Specified Points Type ... * * @return ( int ) */ int GetYoungest( XPivot &source[], ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE // ) { // int result = -1; // // Validate ... if (!HasChild(source)) { return result; } // bool has = false; XPivot iPoint; int count = ArraySize(source); for (int i = 0; i < count; i++) { // // Passed Type ... has = !IsXValid(type) ? true : type == source[i].type; // // Check Can Assign ... has = has && (!iPoint.IsValid() || (iPoint.IsValid() && source[i].GetAge() < iPoint.GetAge())); if (has) { // result = i; iPoint = source[i]; } } // // Validate Result ... has = iPoint.IsValid() && IsValidIndex(result); if (!has) { // result = -1; iPoint.Clean(); return result; } // iPoint.Clean(); // return result; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Highest Detection | //+------------------------------------------------------------------+ /** * Get Highest Index of Specified Collection ... * * @param source: Specified Collection ... * * @return ( int ) */ int GetHighest( XBoxZone &source[] // ) { // int result = -1; // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XBoxZone selected; for (int i = 0; i < count; i++) { // bool canSet = !selected.IsValid() ? true : selected.upper < source[i].upper; if (canSet) { // result = i; selected = source[i]; } } // selected.Clean(); // return result; } /** * Get Highest Index of Specified Collection ... * * @param bar: XOHCL, Specified Bar ... * @param source: Specified Collection ... * * @return ( int ) */ int GetHighestByBar( XOHCL &bar, XBoxZone &source[] // ) { // int result = -1; // if (!bar.IsValid()) { return result; } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XBoxZone selected; for (int i = 0; i < count; i++) { // XBoxZone iBox = source[i]; // bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); if (!isBoxValidForBar) { // iBox.Clean(); // continue; } // bool canSet = !selected.IsValid() ? true : selected.upper < iBox.upper; if (canSet) { // result = i; selected = iBox; } // iBox.Clean(); } // selected.Clean(); // return result; } /** * Get Highest Index of Specified Collection ... * * @param source: Specified Collection ... * @param type: ENUM_X_PIVOT_TYPE, Specified Points Type ... * * @return ( int ) */ int GetHighest( XPivot &source[], ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE // ) { // int result = -1; // // Validate ... if (!HasChild(source)) { return result; } // bool has = false; XPivot iPoint; int count = ArraySize(source); for (int i = 0; i < count; i++) { // // Passed Type ... has = !IsXValid(type) ? true : type == source[i].type; // // Check Can Assign ... has = has && (!iPoint.IsValid() || (iPoint.IsValid() && source[i].value > iPoint.value)); if (has) { // result = i; iPoint = source[i]; } } // // Validate Result ... has = iPoint.IsValid() && IsValidIndex(result); if (!has) { // result = -1; iPoint.Clean(); return result; } // iPoint.Clean(); // return result; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Loest Detection | //+------------------------------------------------------------------+ /** * Get Lowest Index of Specified Collection ... * * @param source: Specified Collection ... * * @return ( int ) */ int GetLowest( XBoxZone &source[] // ) { // int result = -1; // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XBoxZone selected; for (int i = 0; i < count; i++) { // XBoxZone iBox = source[i]; // bool canSet = !selected.IsValid() ? true : selected.lower > iBox.lower; if (canSet) { // result = i; selected = iBox; } // iBox.Clean(); } // selected.Clean(); // return result; } /** * Get Lowest Index of Specified Collection ... * * @param bar: XOHCL, Specified Bar ... * @param source: Specified Collection ... * * @return ( int ) */ int GetLowestByBar( XOHCL &bar, XBoxZone &source[] // ) { // int result = -1; // if (!bar.IsValid()) { return result; } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XBoxZone selected; for (int i = 0; i < count; i++) { // XBoxZone iBox = source[i]; // bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); if (!isBoxValidForBar) { // iBox.Clean(); // continue; } // bool canSet = !selected.IsValid() ? true : selected.lower > iBox.lower; if (canSet) { // result = i; selected = iBox; } // iBox.Clean(); } // selected.Clean(); // return result; } /** * Get Lowest Index of Specified Collection ... * * @param source: Specified Collection ... * @param type: ENUM_X_PIVOT_TYPE, Specified Points Type ... * * @return ( int ) */ int GetLowest( XPivot &items[], ENUM_X_PIVOT_TYPE type = X_PIVOT_TYPE_NONE // ) { // int result = -1; // // Validate ... if (!HasChild(items)) { return result; } // bool has = false; XPivot 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; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Box | //+------------------------------------------------------------------+ /** * Extract all items which appears Before Specified Time ... * * @param _time: Specified Time ... * @param dest: refrence collection to hold result ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetBeforeItems( datetime _time, XBoxZone &dest[], XBoxZone &source[] // ) { // int result = 0; // // Prepare ... SpecifiedClean(dest); // // Validate ... int count = ArraySize(source); bool has = HasChild(source) && IsSpecifiedValid(_time); if (!has) { return result; } // // Loop through Items ... for (int i = 0; i < count; i++) { // has = source[i].from < _time; if (has) { // AddIfNotExists( source[i], dest // ); } } // result = ArraySize(dest); // return result; } /** * Extract all items which appears After Specified Time ... * * @param _time: Specified Time ... * @param dest: refrence collection to hold result ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetAfterItems( datetime _time, XBoxZone &dest[], XBoxZone &source[] // ) { // int result = 0; // // Prepare ... SpecifiedClean(dest); // // Validate ... int count = ArraySize(source); bool has = HasChild(source) && IsSpecifiedValid(_time); if (!has) { return result; } // // Loop through Items ... for (int i = 0; i < count; i++) { // has = source[i].from > _time; if (has) { // AddIfNotExists( source[i], dest // ); } } // result = ArraySize(dest); // return result; } /** * Extract all items which appears Above Specified Value ... * * @param _value: Specified Value ... * @param dest: refrence collection to hold result ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetAboveItems( double _value, XBoxZone &dest[], XBoxZone &source[] // ) { // int result = 0; // // Prepare ... SpecifiedClean(dest); // // Validate ... int count = ArraySize(source); bool has = HasChild(source) && NotEmptyZero(_value); if (!has) { return result; } // // Loop through Items ... for (int i = 0; i < count; i++) { // has = source[i].lower > _value; if (has) { // AddIfNotExists( source[i], dest // ); } } // result = ArraySize(dest); // return result; } /** * Extract all items which appears Below Specified Value ... * * @param _value: Specified Value ... * @param dest: refrence collection to hold result ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetBelowItems( double _value, XBoxZone &dest[], XBoxZone &source[] // ) { // int result = 0; // // Prepare ... SpecifiedClean(dest); // // Validate ... int count = ArraySize(source); bool has = HasChild(source) && NotEmptyZero(_value); if (!has) { return result; } // // Loop through Items ... for (int i = 0; i < count; i++) { // has = source[i].upper < _value; if (has) { // AddIfNotExists( source[i], dest // ); } } // result = ArraySize(dest); // return result; } /** * Get Oldest Item Index of all items which appears Before Specified Value ... * * @param _time: Specified Time ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetOldestBefore( datetime _time, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetBeforeItems( _time, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetOldest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Oldest Item Index of all items which appears After Specified Value ... * * @param _time: Specified Time ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetOldestAfter( datetime _time, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetAfterItems( _time, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetOldest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Oldest Item Index of all items which appears Above Specified Value ... * * @param _value: Specified Value ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetOldestAbove( double _value, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetAboveItems( _value, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetOldest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Oldest Item Index of all items which appears Below Specified Value ... * * @param _value: Specified Value ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetOldestBelow( double _value, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetBelowItems( _value, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetOldest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Youngest Item Index of all items which appears Before Specified Value ... * * @param _time: Specified Time ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetYoungestBefore( datetime _time, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetBeforeItems( _time, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetYoungest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Youngest Item Index of all items which appears After Specified Value ... * * @param _time: Specified Time ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetYoungestAfter( datetime _time, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetAfterItems( _time, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetYoungest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Youngest Item Index of all items which appears Above Specified Value ... * * @param _value: Specified Value ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetYoungestAbove( double _value, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetAboveItems( _value, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetYoungest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Youngest Item Index of all items which appears Below Specified Value ... * * @param _value: Specified Value ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetYoungestBelow( double _value, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetBelowItems( _value, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetYoungest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Highest Item Index of all items which appears Before Specified Value ... * * @param _time: Specified Time ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetHighestBefore( datetime _time, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetBeforeItems( _time, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetHighest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Highest Item Index of all items which appears After Specified Value ... * * @param _time: Specified Time ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetHighestAfter( datetime _time, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetAfterItems( _time, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetHighest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Highest Item Index of all items which appears Above Specified Value ... * * @param _value: Specified Value ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetHighestAbove( double _value, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetAboveItems( _value, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetHighest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Highest Item Index of all items which appears Below Specified Value ... * * @param _value: Specified Value ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetHighestBelow( double _value, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetBelowItems( _value, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetHighest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Lowest Item Index of all items which appears Before Specified Value ... * * @param _time: Specified Time ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetLowestBefore( datetime _time, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetBeforeItems( _time, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetLowest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Lowest Item Index of all items which appears After Specified Value ... * * @param _time: Specified Time ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetLowestAfter( datetime _time, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetAfterItems( _time, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetLowest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Lowest Item Index of all items which appears Above Specified Value ... * * @param _value: Specified Value ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetLowestAbove( double _value, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetAboveItems( _value, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetLowest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Get Lowest Item Index of all items which appears Below Specified Value ... * * @param _value: Specified Value ... * @param source: refrence collection to provides data source ... * * @return ( int ) */ int GetLowestBelow( double _value, XBoxZone &source[] // ) { // int result = -1; // XBoxZone tmps[]; int tmpsCount = GetBelowItems( _value, tmps, // Dest ... source // Source ... ); bool has = IsValidSize(tmpsCount); int idx = GetLowest(tmps); has = has && IsValidIndex(idx) && FindIndex( result, tmps[idx], source // ); SpecifiedClean(tmps); // return result; } /** * Validate an Item Strength ... * * @param item: Specified Item for Validating ... * @param minAllowedStrength: int, Minimum required Strength in Point ... * * @return ( bool ) */ bool ValidateStrength( XBoxZone &item, int minAllowedStrength = 0 // ) { // bool result = false; // // Normalize ... minAllowedStrength = NormalizeInt(minAllowedStrength, 0); // // Validate ... result = item.IsValid(); if (!result) { return result; } // // If doent provide Specified Strength Validate Zone ... result = minAllowedStrength <= 0; if (result) { return result; } // double points = GetPoints(item.symbol); double requiredStrength = minAllowedStrength * points; double itemStrength = item.upper - item.lower; // result = itemStrength > 0 && requiredStrength > 0 && itemStrength > requiredStrength; // return result; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Sort | //+------------------------------------------------------------------+ /** * Allowed Sort Param ... **/ enum ENUM_X_SORT_BY { X_SORT_BY_NONE = 0, // None X_SORT_BY_DATE = 1, // by Date X_SORT_BY_VALUE = 2, // by Date }; /** * Check Specified Sort By Validation ... * * @param value: ENUM_X_SORT_BY, value to Validate ... * * @return ( bool ) */ bool IsXValid(ENUM_X_SORT_BY value) { return value != X_SORT_BY_NONE; } /** * Select Specified Index of a Collection by Sort Params ... * * @param source: Collection for Search ... * @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ... * @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ... * * @return ( int ) */ template int SelectItemForSorting( T &source[], ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, ENUM_X_DIRECTION sortDir = X_DIRECTION_BULLISH // ) { // int result = -1; // // Validate ... if (!HasChild(source) || !IsXValid(sortBy) || !HasDirection(sortDir)) { return result; } // // Sort By Date ... if (sortBy == X_SORT_BY_DATE) { // // Select Based on Sorting Direction ... // // form Oldest to Youngest ... if (sortDir == X_DIRECTION_BULLISH) { result = GetOldest(source); } // // form Youngest to Oldest ... else if (sortDir == X_DIRECTION_BEARISH) { result = GetYoungest(source); } // // Not Valid ... else { result = -1; } } // // Sort By Value ... else if (sortBy == X_SORT_BY_VALUE) { // // form Lowst to Highest ... if (sortDir == X_DIRECTION_BULLISH) { result = GetLowest(source); } // // form Highest to Lowest ... else if (sortDir == X_DIRECTION_BEARISH) { result = GetHighest(source); } // // Not Valid ... else { result = -1; } } // // Not Valid ... else { result = -1; } // return result; } /** * Select Specified Index of a Collection by Sort Params ... * * @param source: Collection for Search ... * @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ... * @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ... * * @return ( int ) */ int SelectBarForSorting( XOHCL &source[], ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, ENUM_X_DIRECTION sortDir = X_DIRECTION_BULLISH, ENUM_X_PRICE priceType = X_PRICE_NONE // ) { // int result = -1; // // Validate ... if (!HasChild(source) || !IsXValid(sortBy) || !HasDirection(sortDir)) { return result; } // // Sort By Date ... if (sortBy == X_SORT_BY_DATE) { // // Select Based on Sorting Direction ... // // form Oldest to Youngest ... if (sortDir == X_DIRECTION_BULLISH) { result = GetOldest(source); } // // form Youngest to Oldest ... else if (sortDir == X_DIRECTION_BEARISH) { result = GetYoungest(source); } // // Not Valid ... else { result = -1; } } // // Sort By Value ... else if (sortBy == X_SORT_BY_VALUE) { // // form Lowst to Highest ... if (sortDir == X_DIRECTION_BULLISH) { result = GetLowest(source, priceType); } // // form Highest to Lowest ... else if (sortDir == X_DIRECTION_BEARISH) { result = GetHighest(source, priceType); } // // Not Valid ... else { result = -1; } } // // Not Valid ... else { result = -1; } // return result; } /** * Apply Sort on Specified Collection ... * * @param source: Collection Reference to Sort ... * @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ... * @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ... * @param maxAllowed: int, Max Allowed Collection Size ... */ template void Sort( T &source[], ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, ENUM_X_DIRECTION sortDir = X_DIRECTION_BULLISH, int maxAllowed = 0 // ) { // int idx = -1; bool has = false; // // Validate ... has = IsXValid(sortBy) && HasChild(source) && HasDirection(sortDir); if (!has) { return; } // // Copy source for Manipulating ... T tmps[]; Copy( source, tmps // ); // // Clean Source Collection for Adding Sorted Items ... Clean(source); // // Loop Through Temp Collection Has Child ... while (HasChild(tmps)) { // // Select Based on Sorting Parameter ... idx = SelectItemForSorting( tmps, sortBy, sortDir // ); // // Validate Detected Index ... has = IsValidIndex(idx); if (!has) { break; } // // Add Detected Indexed Item to Source ... AddRef( tmps[idx], source // ); // // Remove Item From Temp Collection ... ArrayRemove( tmps, idx, 1 // ); } // // Cleanup Collection if Max Items Reached ... if (maxAllowed > 0) { // CleanupArray( source, maxAllowed // ); } // // Cleanup Resources ... SpecifiedClean(tmps); } /** * Apply Sort on Specified Collection ... * * @param source: Collection Reference to Sort ... * @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ... * @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ... * @param priceType: ENUM_X_PRICE, Price Selecting Method ... * @param maxAllowed: int, Max Allowed Collection Size ... */ void SortBar( XOHCL &source[], ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, ENUM_X_DIRECTION sortDir = X_DIRECTION_BULLISH, ENUM_X_PRICE priceType = X_PRICE_NONE, int maxAllowed = 0 // ) { // int idx = -1; bool has = false; // // Validate ... has = IsXValid(sortBy) && HasChild(source) && HasDirection(sortDir); if (!has) { return; } // // Copy source for Manipulating ... XOHCL tmps[]; Copy( source, tmps // ); // // Clean Source Collection for Adding Sorted Items ... Clean(source); // // Loop Through Temp Collection Has Child ... while (HasChild(tmps)) { // // Select Based on Sorting Parameter ... idx = SelectBarForSorting( tmps, sortBy, sortDir, priceType // ); // // Validate Detected Index ... has = IsValidIndex(idx); if (!has) { break; } // // Add Detected Indexed Item to Source ... AddRef( tmps[idx], source // ); // // Remove Item From Temp Collection ... ArrayRemove( tmps, idx, 1 // ); } // // Cleanup Collection if Max Items Reached ... if (maxAllowed > 0) { // CleanupArray( source, maxAllowed // ); } // // Cleanup Resources ... SpecifiedClean(tmps); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Extraction | //+------------------------------------------------------------------+ /** * Extract Specific Types of Pivots From a Collection ... * * @param dest: reference Collection to Hold result ... * @param source: Collection to Find Type Specific items ... * @param _type: Specified item Type ... * * @return ( int ) */ int ExtractPivots( XPivot &dest[], XPivot &source[], ENUM_X_PIVOT_TYPE _type // ) { // int result = 0; // // Prepare ... SpecifiedClean(dest); // // Validate ... int count = ArraySize(source); bool has = IsXValid(_type) && IsValidSize(count); if (!has) { return result; } // for (int i = 0; i < count; i++) { // // Check Type Passing ... has = _type == source[i].type; if (!has) { continue; } // AddIfNotExists( source[i], dest // ); } // result = ArraySize(dest); // return result; } /** * Extract Pivots Data for Linear Regression Calculations ... * * @param xData: refrence Collection to Holds X-Axis Data ... * @param yData: refrence Collection to Holds Y-Axis Data ... * @param source: pivots Collection for Extraction ... * * @return ( int ) */ int ExtractPivotsData( double &xData[], double &yData[], XPivot &source[] // ) { // int result = 0; // // Prepare ... SpecifiedClean(xData); SpecifiedClean(yData); // // Validate ... int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XOHCL iBar; bool has = false; double iX = EMPTY_VALUE; double iY = EMPTY_VALUE; for (int i = 0; i < count; i++) { // // Get Pivot Bar ... has = source[i].GetBar(iBar); if (!has) { continue; } // iX = iBar.Index(); iY = source[i].value; // Add( iX, xData // ); // Add( iY, yData // ); // iBar.Clean(); } // iBar.Clean(); // result = MathMin(ArraySize(xData), ArraySize(yData)); // return result; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Support and Resistance | //+------------------------------------------------------------------+ /** * Extract Support Levels of Pivots Collection ... * * @param _minor: refrence to Holds Minor Level ... * @param _major: refrence to Holds Major Level ... * @param source: Collection of Pivots ... * * @return ( bool ) */ bool ExtractSupport( double &_minor, double &_major, XPivot &source[] // ) { // bool result = false; // // Prepare ... _minor = EMPTY_VALUE; _major = EMPTY_VALUE; // // Validate ... int count = ArraySize(source); result = IsValidSize(count); if (!result) { return result; } // bool has = false; double tmp = EMPTY_VALUE; double iValue = EMPTY_VALUE; for (int i = 0; i < count; i++) { // // Check Type ... has = source[i].IsVale(); if (!has) { continue; } // // Reading Value ... iValue = source[i].value; // // Check Can Change Major ... has = !NotEmpty(_major) || _major > iValue; if (has) { // tmp = _major; _major = iValue; } // // Check Can Change Minor ... else { // // Change Minor ... has = !NotEmpty(tmp) || tmp > iValue; if (has) { tmp = iValue; } } } // // Last Update of Minore Minor ... has = NotEmpty(tmp); if (has) { _minor = tmp; } // result = NotEmpty(_major) || NotEmpty(_minor); // return result; } /** * Extract Resistance Levels of Pivots Collection ... * * @param _minor: refrence to Holds Minor Level ... * @param _major: refrence to Holds Major Level ... * @param source: Collection of Pivots ... * * @return ( bool ) */ bool ExtractResistances( double &_minor, double &_major, XPivot &source[] // ) { // bool result = false; // // Prepare ... _minor = EMPTY_VALUE; _major = EMPTY_VALUE; // // Validate ... int count = ArraySize(source); result = IsValidSize(count); if (!result) { return result; } // bool has = false; double tmp = EMPTY_VALUE; double iValue = EMPTY_VALUE; for (int i = 0; i < count; i++) { // // Check Type ... has = source[i].IsPeak(); if (!has) { continue; } // // Reading Value ... iValue = source[i].value; // // Check Can Change Major ... has = !NotEmpty(_major) || _major < iValue; if (has) { // tmp = _major; _major = iValue; } // // Check Can Change Minor ... else { // // Change Minor ... has = !NotEmpty(tmp) || tmp < iValue; if (has) { tmp = iValue; } } } // // Last Update of Minore Minor ... has = NotEmpty(tmp); if (has) { _minor = tmp; } // result = NotEmpty(_major) || NotEmpty(_minor); // return result; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Find Index | //+------------------------------------------------------------------+ /** * Find Specified Item index in a Collection ... * * @param index: int, reference to Hold Index if Exists ... * @param item: Specified item to Detect ... * @param source: Collection to Search for item ... * * @return ( bool ) */ bool FindIndex( int &index, XBoxZone &item, XBoxZone &source[] // ) { // bool result = false; // index = -1; // int count = ArraySize(source); result = item.IsValid() && IsValidSize(count); if (!result) { return result; } // for (int i = 0; i < count; i++) { // bool isSame = item.IsSameAs(source[i]); if (isSame) { // index = i; break; } } // result = IsValidIndex(index); // return result; } /** * Find Specified Item index in a Collection ... * * @param index: int, reference to Hold Index if Exists ... * @param item: Specified item to Detect ... * @param source: Collection to Search for item ... * * @return ( bool ) */ bool FindIndex( int &index, XPivot &item, XPivot &source[] // ) { // bool result = false; // index = -1; // int count = ArraySize(source); result = item.IsValid() && IsValidSize(count); if (!result) { return result; } // for (int i = 0; i < count; i++) { // bool isSame = item.IsSameAs(source[i]); if (isSame) { // index = i; break; } } // result = IsValidIndex(index); // return result; } /** * Find Specified Item index in a Collection ... * * @param index: int, reference to Hold Index if Exists ... * @param item: Specified item to Detect ... * @param source: Collection to Search for item ... * * @return ( bool ) */ bool FindIndex( int &index, XDirectionShift &item, XDirectionShift &source[] // ) { // bool result = false; // index = -1; // int count = ArraySize(source); result = item.IsValid() && IsValidSize(count); if (!result) { return result; } // for (int i = 0; i < count; i++) { // bool isSame = item.IsSameAs(source[i]); if (isSame) { // index = i; break; } } // result = IsValidIndex(index); // return result; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Remove | //+------------------------------------------------------------------+ /** * Remove Specified Item from a Collection ... * * @param item: Specified Item ... * @param source: Specified Collection for Remove item from it ... * * @return ( bool ) */ bool Remove( XPivot &item, XPivot &source[] // ) { // bool result = false; // result = item.IsValid() && HasChild(source); if (!result) { return result; } // int idx = -1; result = FindIndex( idx, item, source // ); if (!result) { return result; } // result = ArrayRemove( source, idx, 1 // ); // return result; } /** * Remove Specified Item from a Collection ... * * @param item: Specified Item ... * @param source: Specified Collection for Remove item from it ... * * @return ( bool ) */ bool Remove( XBoxZone &item, XBoxZone &source[] // ) { // bool result = false; // result = item.IsValid() && HasChild(source); if (!result) { return result; } // int idx = -1; result = FindIndex( idx, item, source // ); if (!result) { return result; } // result = ArrayRemove( source, idx, 1 // ); // return result; } /** * Remove Specified Item from a Collection ... * * @param item: Specified Item ... * @param source: Specified Collection for Remove item from it ... * * @return ( bool ) */ bool Remove( XDirectionShift &item, XDirectionShift &source[] // ) { // bool result = false; // result = item.IsValid() && HasChild(source); if (!result) { return result; } // int idx = -1; result = FindIndex( idx, item, source // ); if (!result) { return result; } // result = ArrayRemove( source, idx, 1 // ); // return result; } /** * Remove Specified items from a Collection ... * * @param items: Specified Items to Remove ... * @param sources: Sepcified Collection for Removing items from it ... * * @return ( int ) */ int Removes( XBoxZone &items[], XBoxZone &sources[] // ) { // int result = 0; // bool has = HasChild(items) && HasChild(sources); if (!has) { return result; } // int idx = -1; has = false; int count = ArraySize(items); for (int i = 0; i < count; i++) { // // Detect Item Index in Collection ... has = FindIndex( idx, items[i], sources // ); if (has) { // // Remove Detected Index from Collection ... has = ArrayRemove( sources, idx, 1 // ); // if (has) { // // Count Removed Items ... result++; } } } // return result; } /** * Remove Specified items from a Collection ... * * @param items: Specified Items to Remove ... * @param sources: Sepcified Collection for Removing items from it ... * * @return ( int ) */ int Removes( XPivot &items[], XPivot &sources[] // ) { // int result = 0; // bool has = HasChild(items) && HasChild(sources); if (!has) { return result; } // int idx = -1; has = false; int count = ArraySize(items); for (int i = 0; i < count; i++) { // // Detect Item Index in Collection ... has = FindIndex( idx, items[i], sources // ); if (has) { // // Remove Detected Index from Collection ... has = ArrayRemove( sources, idx, 1 // ); // if (has) { // // Count Removed Items ... result++; } } } // return result; } /** * Remove Specified items from a Collection ... * * @param items: Specified Items to Remove ... * @param sources: Sepcified Collection for Removing items from it ... * * @return ( int ) */ int Removes( XDirectionShift &items[], XDirectionShift &sources[] // ) { // int result = 0; // bool has = HasChild(items) && HasChild(sources); if (!has) { return result; } // int idx = -1; has = false; int count = ArraySize(items); for (int i = 0; i < count; i++) { // // Detect Item Index in Collection ... has = FindIndex( idx, items[i], sources // ); if (has) { // // Remove Detected Index from Collection ... has = ArrayRemove( sources, idx, 1 // ); // if (has) { // // Count Removed Items ... result++; } } } // return result; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Add If Not Exists | //+------------------------------------------------------------------+ /** * Add Specified Item to Specified Collection, if not Exists ... * * @param item: Item to Add ... * @param sources: Collection to Add item ... * @param maxAllowed: int, Max Allowed Collection Size ... * * @return ( bool ) */ bool AddIfNotExists( XBoxZone &item, XBoxZone &sources[], int maxAllowed = 0 // ) { // bool result = false; // // Validate Args ... result = item.IsValid(); if (!result) { return result; } // // Check Item Exists or not ... int idx = -1; bool isExists = FindIndex( idx, item, sources // ); result = !isExists; if (!result) { return result; } // AddRef( item, sources // ); // // Handle Cleanup Collection // if Max Reached ... if (result && maxAllowed > 0) { // CleanupArray( sources, maxAllowed // ); } // return result; } /** * Add Specified Item to Specified Collection, if not Exists ... * * @param item: Item to Add ... * @param sources: Collection to Add item ... * @param maxAllowed: int, Max Allowed Collection Size ... * * @return ( bool ) */ bool AddIfNotExists( XPivot &item, XPivot &sources[], int maxAllowed = 0 // ) { // bool result = false; // // Validate Args ... result = item.IsValid(); if (!result) { return result; } // // Check Item Exists or not ... int idx = -1; bool isExists = FindIndex( idx, item, sources // ); result = !isExists; if (!result) { return result; } // AddRef( item, sources // ); // // Handle Cleanup Collection // if Max Reached ... if (result && maxAllowed > 0) { // CleanupArray( sources, maxAllowed // ); } // return result; } /** * Add Specified Item to Specified Collection, if not Exists ... * * @param item: Item to Add ... * @param sources: Collection to Add item ... * @param maxAllowed: int, Max Allowed Collection Size ... * * @return ( bool ) */ bool AddIfNotExists( XDirectionShift &item, XDirectionShift &sources[], int maxAllowed = 0 // ) { // bool result = false; // // Validate Args ... result = item.IsValid(); if (!result) { return result; } // // Check Item Exists or not ... int idx = -1; bool isExists = FindIndex( idx, item, sources // ); result = !isExists; if (!result) { return result; } // AddRef( item, sources // ); // // Handle Cleanup Collection // if Max Reached ... if (result && maxAllowed > 0) { // CleanupArray( sources, maxAllowed // ); } // return result; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Extract | //+------------------------------------------------------------------+ /** * Extract Specified Directional Items ... * * @param dest: reference collection to holds extracted items ... * @param source: reference collection to provides data source ... * @param forDir: Specified which direction to Extract items ... * * @return ( int ) */ template int ExtractByDirection( T &dest[], T &source[], ENUM_X_DIRECTION forDir // ) { // int result = 0; // // Prepare ... XClean(dest); // // Validate ... bool has = HasChild(source) && HasDirection(forDir); if (!has) { return result; } // int count = ArraySize(source); for (int i = 0; i < count; i++) { // has = source[i].dir == forDir; if (has) { // AddIfNotExists( source[i], dest // ); } } // result = ArraySize(dest); // return result; } //+------------------------------------------------------------------+ // // // //+------------------------------------------------------------------+ //| Other Extensions | //+------------------------------------------------------------------+ /** * Validate Boxes ... * @param box: XBoxZone instance reference for Validate ... * @param barIndex: int, Bar Index ... * @param barsLength: int, Bars Length for Validation ... * * @return ( bool ) */ bool IsBoxValid( XBoxZone &box, int barIndex = 0, int barsLength = 3 // ) { // bool result = false; // // Normalize Bar Index ... barIndex = NormalizeInt(barIndex, 0); barsLength = NormalizeInt(barsLength, 1); // // Ceck Input Box is Valid ... result = box.IsValid(); if (!result) { return result; } // // Check Input Box is Breaked or not ... // Breaktion Found using Counting Over/Under Close Bars ... bool isBullish = box.IsBullish(); double appliedPrice = box.GetInDirectionalPrice(); result = NotEmptyZero(appliedPrice); if (!result) { return result; } // int toIDX = box.ToIndex(); // XOHCL iBar; int edgeBreakes = 0; for (int i = barIndex; i <= toIDX; i++) { // // Initialize Indexed Bar ... result = iBar.Init( box.symbol, box.period, i // ); // // Checking Price ... result = // // Checking Bar Validation ... result && // // Checking Price Breaked or not ... (isBullish ? iBar.close < box.lower : iBar.close > box.upper); if (result) { edgeBreakes++; } else { edgeBreakes = 0; } // result = edgeBreakes >= barsLength; if (result) { break; } // iBar.Clean(); } // iBar.Clean(); // // return true; // result = edgeBreakes < barsLength; // return result; } // void SortBoxes( XBoxZone &items[], int maxAllowed = 0 // ) { // int idx = -1; bool has = false; // has = HasChild(items); if (!has) { return; } // XBoxZone tmp[]; Copy( items, tmp // ); Clean(items); // while (HasChild(tmp)) { // idx = GetOldest(tmp); has = IsValidIndex(idx); if (!has) { break; } // XBoxZone iBox = tmp[idx]; ArrayRemove( tmp, idx, 1 // ); // AddRef( iBox, items // ); } // if (maxAllowed > 0) { // CleanupArray( items, maxAllowed // ); } // Clean(tmp); } /** * Check a BaxHas Valid Place for Specified Bar ... * * @param bar: XOHCL instance reference, Specified Bar ... * #param box: XBoxZone instance reference, Specified Box ... * * @return ( bool ) */ bool IsBoxPlaceValidForBar( XOHCL &bar, XBoxZone &box // ) { // bool result = false; // result = bar.IsValid() && box.IsValid(); if (!result) { return result; } // result = box.IsBullish() ? bar.low > box.upper : bar.high < box.upper; // return result; } // void ValidateBoxes( XBoxZone &boxes[], int barIndex = 0, int barsLength = 3, bool forceSorting = false, int maxAllowed = 0 // ) { // bool has = false; // // Normalize Args ... barIndex = NormalizeInt(barIndex, 0); barsLength = NormalizeInt(barsLength, 3); // // Validate Args ... has = HasChild(boxes); if (!has) { return; } // // Copy Boxes to tmp ... XBoxZone tmp[]; Copy( boxes, tmp // ); Clean(boxes); // // Looping Through Exists Boxes ... while (HasChild(tmp)) { // // Select Indexed Box ... XBoxZone iBox = tmp[0]; // // Remove Indexed Box ... ArrayRemove( tmp, 0, 1 // ); // // Check Box Validating ... has = IsBoxValid( iBox, barIndex, barsLength // ); if (has) { // AddRef( iBox, boxes // ); } } // // Sorting ... if (forceSorting) { // // Check Has Result or not ... has = HasChild(boxes); if (has) { // // Sorting ... SortBoxes( boxes, maxAllowed // ); } } // } void UpdateToTime( XBoxZone &zones[], datetime toTime = NULL // ) { // // Normalize ... toTime = NormalizeTime(toTime); // // Validate ... bool has = HasChild(zones); if (!has) { return; } // int count = ArraySize(zones); for (int i = 0; i < count; i++) { zones[i].to = toTime; } } /** * Converts a Bar to Pivot ... * * @param bar: XOHCL, reference to Specified Bar ... * @param pivot: XPivot, reference to holds result ... * @param forDir: ENUM_X_DIRECTION, specified Pivot Direction ... * @param prefix: string, Specified Pivot Prefix (used for Object Type) ... * @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ... * @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ... * * @return ( bool ) */ bool ToPivot( XOHCL &bar, XPivot &pivot, ENUM_X_DIRECTION forDir, string prefix = NULL, ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, ENUM_X_PRICE valePriceType = X_PRICE_LOW // ) { // bool result = false; // // Prepare ... pivot.Clean(); // // Normalize ... if (!IsXValid(peakPriceType)) { peakPriceType = X_PRICE_HIGH; } if (!IsXValid(valePriceType)) { valePriceType = X_PRICE_LOW; } // // Validate ... result = bar.IsValid() && HasDirection(forDir) && IsXValid(peakPriceType) && IsXValid(valePriceType); if (!result) { return result; } // // Check Direction ... bool isBullish = IsSpecifiedBullish(forDir); // // Prepare Value of Pivot ... double iValue = isBullish ? bar.GetPrice(valePriceType) : bar.GetPrice(peakPriceType); // // Prepare Pivot Type ... ENUM_X_PIVOT_TYPE iType = isBullish ? X_PIVOT_TYPE_VALE : X_PIVOT_TYPE_PEAK; // // Initialize Pivot ... result = pivot.Init( iValue, bar.time, bar.symbol, forDir, bar.period, iType // ); if (result) { // // Set Prefix if Pivot initialized successfully ... pivot.prefix = prefix; } // // Validate ... result = pivot.IsValid(); if (!result) { pivot.Clean(); } // return result; } /** * Converts a Bar to Pattern Pivot ... * * @param bar: XOHCL, reference to Specified Bar ... * @param pivot: XPivot, reference to holds result ... * @param patternDir: ENUM_X_DIRECTION, specified Pivot Direction ... * @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern Type ... * @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ... * @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ... * * @return ( bool ) */ bool ToPivot( XOHCL &bar, XPivot &pivot, ENUM_X_DIRECTION patternDir, ENUM_X_BAR_PATTERN pattern, ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, ENUM_X_PRICE valePriceType = X_PRICE_LOW // ) { // bool result = false; // // Prepare ... pivot.Clean(); // // Normalize ... if (!IsXValid(peakPriceType)) { peakPriceType = X_PRICE_HIGH; } if (!IsXValid(valePriceType)) { valePriceType = X_PRICE_LOW; } // // Validate ... result = bar.IsValid() && IsXValid(pattern) && IsXValid(peakPriceType) && IsXValid(valePriceType) && HasDirection(patternDir); if (!result) { return result; } // datetime iTime = bar.time; string iSymbol = bar.symbol; string iPrefix = ToXString(pattern); ENUM_TIMEFRAMES iPeriod = bar.period; double iValue = IsXBullish(patternDir) ? bar.GetPrice(X_PRICE_LOW) : IsXBearish(patternDir) ? bar.GetPrice(X_PRICE_HIGH) : EMPTY_VALUE; ENUM_X_PIVOT_TYPE iType = IsXBullish(patternDir) ? X_PIVOT_TYPE_VALE : IsXBearish(patternDir) ? X_PIVOT_TYPE_PEAK : X_PIVOT_TYPE_NONE; // result = pivot.Init( iValue, iTime, iSymbol, patternDir, iPeriod, iType // ); if (result) { pivot.prefix = iPrefix; } // // Cleanup Resources ... if (!result) { pivot.Clean(); } // return result; } /** * Converts POI Bar to Box ... * * @param bar: XOHCL, reference to Specified Pattern ... * @param box: XBoxZone, reference to holds result ... * @param forDir: ENUM_X_DIRECTION, Specified Pattern Direction ... * @param prefix: string, Specified Pattern Type ... * @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ... * @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ... * * @return ( bool ) */ bool ToBox( XOHCL &bar, XBoxZone &box, ENUM_X_DIRECTION forDir, string prefix = NULL, ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, ENUM_X_PRICE valePriceType = X_PRICE_LOW // ) { // bool result = false; // // Prepare ... box.Clean(); // // Normalize ... if (!IsXValid(peakPriceType)) { peakPriceType = X_PRICE_HIGH; } if (!IsXValid(valePriceType)) { valePriceType = X_PRICE_LOW; } // // Validate ... result = bar.IsValid() && HasDirection(forDir) && IsXValid(peakPriceType) && IsXValid(valePriceType); if (!result) { return result; } // // Check if is Valid Pattern ... ENUM_X_BAR_PATTERN iPattern = ToBarPattern(prefix); result = IsXValid(iPattern); if (result) { // // Conver to Box as Pattern ... result = ToBox( bar, box, forDir, iPattern, peakPriceType, valePriceType // ); } // // There is not any Valid Pattern Provided ... else { // bool isBullish = IsXBullish(forDir); double peakPrice = bar.GetPrice(peakPriceType); double valePrice = bar.GetPrice(valePriceType); // string iType = prefix; datetime iAt = bar.time; datetime iTo = bar.time; double iUpper = peakPrice; double iLower = valePrice; string iSymbol = bar.symbol; datetime iFrom = bar.BeforeOn(); ENUM_TIMEFRAMES iPeriod = bar.period; // // Assign Values to Box ... box.at = iAt; box.to = iTo; box.from = iFrom; box.type = iType; box.dir = forDir; box.upper = iUpper; box.lower = iLower; box.symbol = iSymbol; box.period = iPeriod; } // // Validate result ... result = box.IsValid(); if (!result) { // box.Clean(); return result; } // return result; } /** * Converts Pattern Bar to Box ... * * @param bar: XOHCL, reference to Specified Pattern ... * @param box: XBoxZone, reference to holds result ... * @param forDir: ENUM_X_DIRECTION, Specified Pattern Direction ... * @param prefix: string, Specified Pattern Type ... * @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ... * @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ... * * @return ( bool ) */ bool ToBox( XOHCL &bar, XBoxZone &box, ENUM_X_DIRECTION patternDir, ENUM_X_BAR_PATTERN pattern, ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, ENUM_X_PRICE valePriceType = X_PRICE_LOW // ) { // bool result = false; // // Prepare ... box.Clean(); // // Normalize ... if (!IsXValid(peakPriceType)) { peakPriceType = X_PRICE_HIGH; } if (!IsXValid(valePriceType)) { valePriceType = X_PRICE_LOW; } // // Validate ... result = bar.IsValid() && IsXValid(pattern) && IsXValid(peakPriceType) && IsXValid(valePriceType) && HasDirection(patternDir); if (!result) { return result; } // // Define Requirements ... XOHCL tmpBar; XBoxZone tmpBox; bool has = false; datetime iAt = bar.time; datetime iTo = bar.time; double iUpper = EMPTY_VALUE; double iLower = EMPTY_VALUE; string iSymbol = bar.symbol; datetime iFrom = bar.BeforeOn(); string iType = ToXString(pattern); ENUM_TIMEFRAMES iPeriod = bar.period; // bool isBullish = IsXBullish(patternDir); double peakPrice = bar.GetPrice(peakPriceType); double valePrice = bar.GetPrice(valePriceType); // // Calculate Requirements Based on Pattern Type and Direction ... switch (pattern) { // case X_BAR_PATTERN_HIGH: { // tmpBar.Clean(); has = GetBreakerBar( bar, tmpBar, peakPriceType, peakPriceType, X_DIRECTION_BULLISH // ); if (has) { iFrom = tmpBar.time; } // iUpper = peakPrice; iLower = bar.GetUp(); } break; // case X_BAR_PATTERN_LOW: { // tmpBar.Clean(); has = GetBreakerBar( bar, tmpBar, valePriceType, valePriceType, X_DIRECTION_BEARISH // ); if (has) { iFrom = tmpBar.time; } // iUpper = bar.GetDown(); iLower = valePrice; } break; // case X_BAR_PATTERN_MOMENTUM: { // tmpBar.Clean(); ENUM_X_PRICE iPType = isBullish ? valePriceType : peakPriceType; has = GetBreakerBar( bar, tmpBar, iPType, iPType, patternDir // ); if (has) { iFrom = tmpBar.time; } // iUpper = peakPrice; iLower = valePrice; } break; // case X_BAR_PATTERN_ENGULFED: { // tmpBar.Clean(); ENUM_X_PRICE iPType = isBullish ? valePriceType : peakPriceType; has = GetBreakerBar( bar, tmpBar, iPType, iPType, patternDir // ); if (has) { iFrom = tmpBar.time; } // iUpper = peakPrice; iLower = valePrice; } break; // case X_BAR_PATTERN_TRUE_GAPED: { // tmpBar.Clean(); has = bar.GetPreviousBar(tmpBar); if (has) { // iFrom = tmpBar.time; // iUpper = isBullish ? valePrice : tmpBar.GetPrice(valePriceType); iLower = isBullish ? tmpBar.GetPrice(peakPriceType) : peakPrice; } } break; // case X_BAR_PATTERN_PINNED: { // tmpBar.Clean(); ENUM_X_PRICE iPType = isBullish ? valePriceType : peakPriceType; has = GetBreakerBar( bar, tmpBar, iPType, iPType, patternDir // ); if (has) { iFrom = tmpBar.time; } // iUpper = isBullish ? bar.GetDown() : peakPrice; iLower = isBullish ? valePrice : bar.GetUp(); } break; // case X_BAR_PATTERN_STAR: { // tmpBar.Clean(); ENUM_X_PRICE iPType = isBullish ? valePriceType : peakPriceType; has = GetBreakerBar( bar, tmpBar, iPType, iPType, patternDir // ); if (has) { // iFrom = tmpBar.time; // int idx = -1; int mLength = tmpBar.Index() - bar.Index(); iLower = bar.FindLowest(idx, mLength, valePriceType); iUpper = bar.FindHighest(idx, mLength, peakPriceType); } } break; // case X_BAR_PATTERN_PIERCING: { // tmpBar.Clean(); ENUM_X_PRICE iPType = isBullish ? valePriceType : peakPriceType; has = GetBreakerBar( bar, tmpBar, iPType, iPType, patternDir // ); if (has) { iFrom = tmpBar.time; } // iUpper = peakPrice; iLower = valePrice; } break; // case X_BAR_PATTERN_RISING: { // tmpBar.Clean(); ENUM_X_PRICE iPType = isBullish ? valePriceType : peakPriceType; has = GetBreakerBar( bar, tmpBar, iPType, iPType, patternDir // ); if (has) { iFrom = tmpBar.time; } // iUpper = peakPrice; iLower = valePrice; } break; // case X_BAR_PATTERN_FLAG: { // tmpBar.Clean(); ENUM_X_PRICE iPType = isBullish ? valePriceType : peakPriceType; has = GetBreakerBar( bar, tmpBar, iPType, iPType, patternDir // ); if (has) { iFrom = tmpBar.time; } // int idx = -1; int mLength = 3; iUpper = bar.FindHighest(idx, mLength, peakPriceType); iLower = bar.FindLowest(idx, mLength, valePriceType); } break; // case X_BAR_PATTERN_SIGNALKEY: { // tmpBar.Clean(); ENUM_X_PRICE iPType = isBullish ? valePriceType : peakPriceType; has = GetBreakerBar( bar, tmpBar, iPType, iPType, patternDir // ); if (has) { iFrom = tmpBar.time; } // has = bar.GetPreviousBar(tmpBar); if (has) { // iUpper = MathMax(peakPrice, tmpBar.GetPrice(peakPriceType)); iLower = MathMin(valePrice, tmpBar.GetPrice(valePriceType)); } } break; // case X_BAR_PATTERN_OB: { // tmpBox.Clean(); has = ToOBBox( bar, tmpBox, patternDir // ); if (has) { // iFrom = tmpBox.from; iUpper = tmpBox.upper; iLower = tmpBox.lower; } } break; // case X_BAR_PATTERN_FVG: { // tmpBox.Clean(); has = ToFVGBox( bar, tmpBox, patternDir // ); if (has) { // iFrom = tmpBox.from; iUpper = tmpBox.upper; iLower = tmpBox.lower; } } break; // case X_BAR_PATTERN_SUPPORT: { // tmpBar.Clean(); ENUM_X_PRICE iPType = isBullish ? valePriceType : peakPriceType; has = GetBreakerBar( bar, tmpBar, iPType, iPType, patternDir // ); if (has) { iFrom = tmpBar.time; } // iUpper = isBullish ? peakPrice : valePrice; iLower = isBullish ? peakPrice : valePrice; } break; // case X_BAR_PATTERN_RESISTANCE: { // tmpBar.Clean(); ENUM_X_PRICE iPType = isBullish ? valePriceType : peakPriceType; has = GetBreakerBar( bar, tmpBar, iPType, iPType, patternDir // ); if (has) { iFrom = tmpBar.time; } // iUpper = isBullish ? peakPrice : valePrice; iLower = isBullish ? peakPrice : valePrice; } break; } // // Assign Values to Box ... box.at = iAt; box.to = iTo; box.from = iFrom; box.type = iType; box.upper = iUpper; box.lower = iLower; box.symbol = iSymbol; box.period = iPeriod; box.dir = patternDir; // result = box.IsValid(); // // Cleanup Resources ... if (!result) { box.Clean(); } tmpBar.Clean(); tmpBox.Clean(); // return result; } /** * Converts a Bar to OB Box ... * * @param bar: XOHCL, Specified Bar ... * @param box: XBoxZone, destination Box ... * @param forDir: ENUM_X_DIRECTION, Specified Direction ... * * @return ( bool ) */ bool ToOBBox( XOHCL &bar, XBoxZone &box, ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // ) { // bool result = false; // // Prepare ... box.Clean(); // // Normalize ... if (!HasDirection(forDir)) { forDir = bar.GetDirection(); } // // Validate ... result = bar.IsValid() && HasDirection(forDir) && bar.GetDirection() == forDir; if (!result) { return result; } // // Detect OB Start Bar ... XOHCL obStartBar; result = GetDirectionalBar( bar, obStartBar, Opposit(forDir) // ); if (!result) { // obStartBar.Clean(); return result; } // box.dir = forDir; box.to = bar.time; box.at = bar.time; box.symbol = bar.symbol; box.period = bar.period; box.from = obStartBar.time; box.type = ToXString(X_BAR_PATTERN_OB); box.lower = MathMin(obStartBar.low, bar.low); box.upper = MathMax(obStartBar.high, bar.high); // result = box.IsValid(); // // Cleanup Resources ... if (!result) { box.Clean(); } obStartBar.Clean(); // return result; } /** * Converts a Bar to FVG Box ... * * @param bar: XOHCL, Specified Bar ... * @param box: XBoxZone, destination Box ... * @param forDir: ENUM_X_DIRECTION, Specified Direction ... * * @return ( bool ) */ bool ToFVGBox( XOHCL &bar, XBoxZone &box, ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // ) { // bool result = false; // // Prepare ... box.Clean(); // // Normalize ... if (!HasDirection(forDir)) { forDir = bar.GetDirection(); } // // Validate ... result = bar.IsValid() && HasDirection(forDir) && bar.GetDirection() == forDir; if (!result) { return result; } // // Detect FVG Start Bar ... XOHCL fvgStartBar; result = bar.BarAt( bar.Index() + 2, fvgStartBar); if (!result) { // fvgStartBar.Clean(); return result; } // bool isBullish = IsXBullish(forDir); // box.dir = forDir; box.to = bar.time; box.at = bar.time; box.upper = isBullish ? bar.low : bar.high; box.symbol = bar.symbol; box.period = bar.period; box.lower = isBullish ? fvgStartBar.high : fvgStartBar.low; box.from = fvgStartBar.time; box.type = ToXString(X_BAR_PATTERN_FVG); // result = box.IsValid(); // // Cleanup Resources ... if (!result) { box.Clean(); } fvgStartBar.Clean(); // return result; } /** * Converts a Bar to Support Box ... * * @param bar: XOHCL, Specified Bar ... * @param box: XBoxZone, destination Box ... * @param toTime: datetime, Specified Box to Time ... * * @return ( bool ) */ bool ToSupportBox( XOHCL &bar, XBoxZone &box, datetime toTime = NULL, int validationLength = 0 // ) { // bool result = false; // // Prepare ... box.Clean(); // // Normalize ... toTime = NormalizeTime(toTime); validationLength = NormalizeInt(validationLength, 0); // // Validate ... result = bar.IsValid(); if (!result) { return result; } // XOHCL breaker; result = GetBreakerBar( bar, breaker, X_PRICE_LOW, X_PRICE_DOWN, X_DIRECTION_BEARISH, 500 // ); if (!result) { breaker.Clean(); } // box.to = toTime; box.at = bar.time; box.from = breaker.IsValid() ? breaker.time : validationLength <= 0 ? bar.time : GetBarTime( bar.symbol, bar.period, bar.Index() + validationLength // ); box.lower = bar.low; box.symbol = bar.symbol; box.period = bar.period; box.upper = bar.GetDown(); box.dir = X_DIRECTION_BULLISH; box.type = ToXString(X_BAR_PATTERN_SUPPORT); // result = box.IsValid(); if (!result) { box.Clean(); } // return result; } /** * Converts a Bar to Resistance Box ... * * @param bar: XOHCL, Specified Bar ... * @param box: XBoxZone, destination Box ... * @param toTime: datetime, Specified Box to Time ... * * @return ( bool ) */ bool ToResistanceBox( XOHCL &bar, XBoxZone &box, datetime toTime = NULL, int validationLength = 0 // ) { // bool result = false; // // Prepare ... box.Clean(); // // Normalize ... toTime = NormalizeTime(toTime); validationLength = NormalizeInt(validationLength, 0); // // Validate ... result = bar.IsValid(); if (!result) { return result; } // XOHCL breaker; result = GetBreakerBar( bar, breaker, X_PRICE_HIGH, X_PRICE_UP, X_DIRECTION_BULLISH, 500 // ); if (!result) { breaker.Clean(); } // box.to = toTime; box.at = bar.time; box.from = breaker.IsValid() ? breaker.time : validationLength <= 0 ? bar.time : GetBarTime( bar.symbol, bar.period, bar.Index() + validationLength // ); box.upper = bar.high; box.symbol = bar.symbol; box.period = bar.period; box.lower = bar.GetUp(); box.dir = X_DIRECTION_BEARISH; box.type = ToXString(X_BAR_PATTERN_RESISTANCE); ; // result = box.IsValid(); if (!result) { box.Clean(); } // return result; } /** * Check Specified Zone is Breaked by Specified Bar or not ... * * @param bar: Specified Bar ... * @param zone: Specified Zone ... * @param forceBarEdge: bool, flag to Check Breaktion by high ot low ... * * @return ( bool ) */ bool IsBreaked( XOHCL &bar, XBoxZone &zone, bool forceBarEdge = false // ) { // bool result = false; // // Validate ... result = bar.IsValid() && zone.IsValid(); if (!result) { return result; } // // Check Break ... result = zone.IsBullish() ? bar.close < zone.lower : bar.close > zone.upper; // // Apply Force Bar Edge ... if (forceBarEdge) { // result = result && zone.IsBullish() ? bar.low > zone.upper : bar.high < zone.lower; } // return result; } /** * Check Specified Zone is Tested by Specified Bar or not ... * * @param bar: Specified Bar ... * @param zone: Specified Zone ... * * @return ( bool ) */ bool IsTested( XOHCL &bar, XBoxZone &zone // ) { // bool result = false; // // Validate ... result = bar.IsValid() && zone.IsValid(); if (!result) { return result; } // // Check Test ... result = zone.IsBullish() ? bar.low < zone.upper : bar.high > zone.lower; // return result; } /** * Check Specified Bar is Inside Specified Zone or not ... * * @param bar: Specified Bar ... * @param zone: Specified Zone ... * * @return ( bool ) */ bool IsInside( XOHCL &bar, XBoxZone &zone // ) { // bool result = false; // // Validate ... result = bar.IsValid() && zone.IsValid(); if (!result) { return result; } // // Check Inside ... result = zone.IsBullish() ? bar.low < zone.upper && bar.low > zone.lower : bar.high > zone.lower && bar.high < zone.upper; // return result; } /** * Check Specified Bar is Acted On Specified Zone or not ... * * @param bar: Specified Bar ... * @param zone: Specified Zone ... * * @return ( bool ) */ bool IsActed( XOHCL &bar, XBoxZone &zone // ) { // bool result = false; // // Validate ... result = bar.IsValid() && zone.IsValid(); if (!result) { return result; } // // Get Previous Bar ... XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // // Previous Bar must one of Following States: // - Tested; // - Inside; // - Breaked; bool isTested = IsTested(pBar, zone); bool isInside = IsInside(pBar, zone); bool isBreaked = IsBreaked(pBar, zone); result = isTested || isInside || isBreaked; if (!result) { return result; } // // Current Bar Must Close Over / Under Zone ... result = zone.IsBullish() ? bar.close > zone.upper : zone.IsBearish() ? bar.close < zone.lower : false; // // Cleanup Resources ... pBar.Clean(); // return result; } /** * Check Specified Bar is Acted On Specified Zone or not ... * * @param bar: Specified Bar ... * @param zone: Specified Zone ... * @param validationLength: Specified Length for Breaks ... * * @return ( bool ) */ bool IsValidBreaked( XOHCL &bar, XBoxZone &zone, int validationLength = 3 // ) { // bool result = false; // // Normalize ... validationLength = NormalizeInt(validationLength, 1); // // Validate ... result = bar.IsValid() && zone.IsValid(); if (!result) { return result; } // XOHCL iBar; int count = 0; int start = bar.Index(); int end = start + validationLength; for (int i = start; i < end; i++) { // // Initialize Indexed Bar ... result = bar.BarAt(i, iBar); if (!result) { break; } // result = IsBreaked(iBar, zone); if (result) { count++; } } // result = IsValidSize(count) && count >= validationLength; // // Cleanup Resources ... iBar.Clean(); // return result; } /** * Check Specified Bar is Fake Breaked Specified Zone or not ... * * @param bar: Specified Bar ... * @param zone: Specified Zone ... * @param validationLength: Specified Length for Breaks ... * * @return ( bool ) */ bool IsFakeBreaked( XOHCL &bar, XBoxZone &zone, int validationLength = 3 // ) { // bool result = false; // // Normalize ... validationLength = NormalizeInt(validationLength, 1); // // Validate ... result = bar.IsValid() && zone.IsValid(); if (!result) { return result; } // // Check Bar Must Acting Zone ... result = zone.IsBullish() ? bar.close > zone.upper : zone.IsBearish() ? bar.close < zone.lower : false; if (!result) { return result; } // // Detect Breaker Bars ... XOHCL breakerBars[]; int breakerBarsCount = GetBreakerBars( zone, breakerBars // ); result = IsValidSize(breakerBarsCount); if (!result) { // XClean(breakerBars); return result; } // // Get Youngest Breaker Bars ... int idx = GetYoungest(breakerBars); result = IsValidIndex(idx); if (!result) { // XClean(breakerBars); return result; } // result = breakerBars[idx].Index() - bar.Index() <= validationLength; // // Cleanup Resources ... XClean(breakerBars); // return result; } /** * Check a Bar is Inside a Zone or not ... * * @param index: int, reference to holds detected index ... * @param bar: reference to Specified Bar ... * @param source: reference collection to provide source ... * * @return ( bool ) */ bool HasInside( int &index, XOHCL &bar, XBoxZone &source[] // ) { // bool result = false; // // Prepare ... index = -1; // // Validate ... result = bar.IsValid() && HasChild(source); if (!result) { return result; } // int count = ArraySize(source); for (int i = 0; i < count; i++) { // result = IsInside( bar, source[i] // ); if (result) { // index = i; break; } } // return result; } /** * Extract all Items which Specified Bar is inside them ... * * @param bar: reference to Specified Bar ... * @param dest: reference to result ... * @param source: reference collection to provide source ... * * @return ( int ) */ int ExtractInsides( XOHCL &bar, XBoxZone &dest[], XBoxZone &source[] // ) { // int result = 0; // // Prepare ... SpecifiedClean(dest); // // Validate ... bool has = bar.IsValid() && HasChild(source); if (!result) { return result; } // int count = ArraySize(source); for (int i = 0; i < count; i++) { // has = IsInside( bar, source[i] // ); if (has) { // AddIfNotExists( source[i], dest // ); } } // result = ArraySize(dest); // return result; } /** * Collect all Bars which Breakes Specified Zone ... * * @param zone: reference to Specified Zone ... * @param dest: reference Collection to hold result ... * * @return ( int ) */ int GetBreakerBars( XBoxZone &zone, XOHCL &dest[] // ) { // int result = 0; // // Validate ... bool has = zone.IsValid(); if (!has) { return result; } // // Prepare ... SpecifiedClean(dest); // // Do Action ... XOHCL iBar; int start = zone.ToIndex(); int end = zone.FromIndex(); for (int i = start; i < end; i++) { // // Initialize indexed Bar ... has = iBar.Init( zone.symbol, zone.period, i // ); if (!has) { continue; } // has = IsBreaked( iBar, zone, false // Breakes by Close ... ); if (has) { // AddIfNotExists( iBar, dest // ); } // iBar.Clean(); } // result = ArraySize(dest); // iBar.Clean(); // return result; } /** * Collect all Bars which Inside Specified Zone ... * * @param zone: reference to Specified Zone ... * @param dest: reference Collection to hold result ... * * @return ( int ) */ int GetInsideBars( XBoxZone &zone, XOHCL &dest[] // ) { // int result = 0; // // Validate ... bool has = zone.IsValid(); if (!has) { return result; } // // Prepare ... SpecifiedClean(dest); // // Do Action ... XOHCL iBar; int start = zone.ToIndex(); int end = zone.FromIndex(); for (int i = start; i < end; i++) { // // Initialize indexed Bar ... has = iBar.Init( zone.symbol, zone.period, i // ); if (!has) { continue; } // has = IsInside( iBar, zone // ); if (has) { // AddIfNotExists( iBar, dest // ); } // iBar.Clean(); } // result = ArraySize(dest); // iBar.Clean(); // return result; } /** * Collect all Bars which Tested Specified Zone ... * * @param zone: reference to Specified Zone ... * @param dest: reference Collection to hold result ... * * @return ( int ) */ int GetTesterBars( XBoxZone &zone, XOHCL &dest[] // ) { // int result = 0; // // Validate ... bool has = zone.IsValid(); if (!has) { return result; } // // Prepare ... SpecifiedClean(dest); // // Do Action ... XOHCL iBar; int start = zone.ToIndex(); int end = zone.FromIndex(); for (int i = start; i < end; i++) { // // Initialize indexed Bar ... has = iBar.Init( zone.symbol, zone.period, i // ); if (!has) { continue; } // has = IsTested( iBar, zone // ); if (has) { // AddIfNotExists( iBar, dest // ); } // iBar.Clean(); } // result = ArraySize(dest); // iBar.Clean(); // return result; } //+------------------------------------------------------------------+ //