diff --git a/Classes/x-saherelm.x-helper.class.mq5 b/Classes/x-saherelm.x-helper.class.mq5 index 021966ae..ef721663 100644 --- a/Classes/x-saherelm.x-helper.class.mq5 +++ b/Classes/x-saherelm.x-helper.class.mq5 @@ -513,6 +513,32 @@ class XCBaseHelper : public XCBase return result; } + /** + * Normalizing Bar Index ... + * + * @param barIndex: int, Provided Bar Index ... + * + * @return ( int ) + */ + int NormalizeBarIndex(int barIndex) + { + // + int result = barIndex; + + // + if (!IsValid()) + { + return result; + } + + // + int count = CountBars() - 1; + result = NormalizeInt(result, 0, count - 1); + + // + return result; + } + // // Protected ... protected: @@ -635,32 +661,6 @@ class XCBaseHelper : public XCBase return result; } - /** - * Normalizing Bar Index ... - * - * @param barIndex: int, Provided Bar Index ... - * - * @return ( int ) - */ - int NormalizeBarIndex(int barIndex) - { - // - int result = barIndex; - - // - if (!IsValid()) - { - return result; - } - - // - int count = CountBars() - 1; - result = NormalizeInt(result, 0, count - 1); - - // - return result; - } - // // Private ... private: diff --git a/Classes/x-saherelm.x-market.pattern.class.mq5 b/Classes/x-saherelm.x-market.pattern.class.mq5 index b4fd8185..13dbed0f 100644 --- a/Classes/x-saherelm.x-market.pattern.class.mq5 +++ b/Classes/x-saherelm.x-market.pattern.class.mq5 @@ -40,13 +40,6 @@ class XCMarketPatternDetector : public XCBase // // Props ... - // - XBoxZone zones[]; - XBoxZone majorSupport; - XBoxZone minorSupport; - XBoxZone majorResistance; - XBoxZone minorResistance; - // // Constructor ... XCMarketPatternDetector() @@ -63,31 +56,6 @@ class XCMarketPatternDetector : public XCBase ZeroMemory(barAnalyser); } - // - // Actions / Helpers ... - - // - double CalculateQuarter() - { - // - double result = -1; - - // - // Validate ... - bool has = majorSupport.IsValid() && - majorResistance.IsValid(); - if (!has) - { - return result; - } - - // - result = majorSupport.upper + ((majorResistance.lower - majorSupport.upper) / 2); - - // - return result; - } - // // Analysers ... @@ -1304,7 +1272,7 @@ class XCMarketPatternDetector : public XCBase * Check Specified Bar has Pullback Bar Pattern or not ... * * @param bar: XOHCL, Specified Bar ... - * @param zone: XBoxZone, refrence to hold pullback zone ... + * @param zone: XBoxZone, refrence to hold detected zone ... * @param dir: ENUM_X_DIRECTION a reference for Direction ... * @param pullbackLength: int, min required indirectional bars to confirm pullback ... * @param forceBreak: bool, force pullback bar breaks peak or vale of Zone ... @@ -1431,225 +1399,19 @@ class XCMarketPatternDetector : public XCBase return result; } - bool IsContinuationPullbackPattern( - XOHCL &bar, - XBoxZone &zone, - XBoxZone &continuationalZones[], - ENUM_X_DIRECTION &dir, - XOHCL &continuationalBar, - int continuationLength = 3, - bool forceContinuationHasZone = true, - bool forceContinuationHasPattern = true, - int pullbackLength = 2, - bool forcePullbackBreak = false, - int zonesLoopback = 5, - int zonesValidationLength = 5 // - ) - { - // - bool result = false; - - // - // Prepare ... - zone.Clean(); - CleanDirection(dir); - continuationalBar.Clean(); - XClean(continuationalZones); - - // - // Normalize ... - zonesLoopback = NormalizeInt(zonesLoopback, 3); - pullbackLength = NormalizeInt(pullbackLength, 2); - continuationLength = NormalizeInt(continuationLength, 2); - zonesValidationLength = NormalizeInt(zonesValidationLength, 3); - - // - // Validate ... - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - // First we Have to Detect a Pullback ... - result = IsPullbackPattern(bar, zone, dir, pullbackLength, forcePullbackBreak); - - // - // Select PullBack Start Bar ... - XOHCL startBar; - result = result && - zone.FromBar(startBar); - - // - // Check Continuation Direction ... - XOHCL iBar; - int start = startBar.Index() + 1; - int end = start + continuationLength; - for (int i = start; i < end && result; i++) - { - // - // Initialize Indexed Bar ... - iBar.Clean(); - result = - result && - bar.BarAt(i, iBar); - - // - // Check Direction Same ... - result = - result && - dir == iBar.GetDirection(); - - // - if (!result) - { - break; - } - } - - // - // Setting Continuational Bar ... - if (result) - { - continuationalBar = iBar; - } - - // - // Apply Zone Force ... - if (result && forceContinuationHasZone) - { - // - XBoxZone tmps[]; - - // - // Collectiong Support and Resistances ... - CollectZones(startBar, tmps, zonesLoopback, zonesValidationLength, 0, zonesLoopback * 2); - Copy(tmps, continuationalZones, false); - - // - // Collecting Order Blocks ... - // CollectOBs(startBar, tmps, zonesLoopback, 0, zonesLoopback * 2); - // Copy(tmps, continuationalZones, false); - - // - // Collectiong Fair Value Gaps ... - CollectFVGs(startBar, tmps, zonesLoopback, 0, zonesLoopback * 2); - Copy(tmps, continuationalZones, false); - - // - // Extract Directional Zones ... - XClean(tmps); - ExtractByDirection(tmps, continuationalZones, zone.dir); - Copy(tmps, continuationalZones); - - // - // Validate Result ... - result = result && - HasChild(continuationalZones); - - // - XClean(tmps); - } - - // - // Apply Pattern Force ... - if (result && forceContinuationHasPattern) - { - // - bool has = false; - int pattersCount = 0; - ENUM_X_DIRECTION iPatternDir; - for (int i = start; i < end; i++) - { - // - iBar.Clean(); - CleanDirection(iPatternDir); - - // - has = bar.BarAt(i, iBar); - if (!has) - { - break; - } - - // - // Checking Required Patterns ... - - // - // Pin Bar ... - has = IsPinnedBar(iBar, iPatternDir); - has = has && - iPatternDir == zone.dir; - if (has) - { - pattersCount++; - } - - // - // Engulfed Bar ... - has = IsEngulfedBar(iBar, iPatternDir); - has = has && - iPatternDir == zone.dir; - if (has) - { - pattersCount++; - } - - // - // Momentum Bar ... - has = IsMomentumBar(iBar, iPatternDir); - has = has && - iPatternDir == zone.dir; - if (has) - { - pattersCount++; - } - - // - // Piercing ... - has = IsPiercingPattern(iBar, iPatternDir); - has = has && - iPatternDir == zone.dir; - if (has) - { - pattersCount++; - } - - // - // SignalKey ... - has = IsSignalKeyBarPattern(iBar, iPatternDir); - has = has && - iPatternDir == zone.dir; - if (has) - { - pattersCount++; - } - } - - // - result = - result && - IsValidSize(pattersCount); - } - - // - // Cleanup ... - if (!result) - { - // - zone.Clean(); - CleanDirection(dir); - continuationalBar.Clean(); - XClean(continuationalZones); - } - iBar.Clean(); - startBar.Clean(); - - // - return result; - } - + /** + * Check Market Has Consolidation Pattern or not ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param zone: XBoxZone, refrence to hold detected zone ... + * @param dir: ENUM_X_DIRECTION, reference to holds Detected Order Flow Direction ... + * @param validationLength: int, Validation Length ... + * @param breakPriceType: ENUM_X_PRICE, Specified Price Type to Breake Consolidation ... + * @param upperPriceType: ENUM_X_PRICE, Specified Price Type to Detected Upper of Consolidation ... + * @param lowerPriceType: ENUM_X_PRICE, Specified Price Type to Detected Lower of Consolidation ... + * + * @return ( bool ) + */ bool IsConsolidationPattern( XOHCL &bar, XBoxZone &zone, @@ -1898,6 +1660,22 @@ class XCMarketPatternDetector : public XCBase return result; } + /** + * Detect Order Flow ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param dir: ENUM_X_DIRECTION, reference to holds Detected Order Flow Direction ... + * @param orderFlow: XBoxZone, collection reference to holds Detected Order Flow ... + * @param orderFlowValidation: int, number of sequential Zones for Validate Order Flow ... + * @param containsOBs: bool, Specified to Use Order Blocks in Order Flow Detection ... + * @param containsFVGs: bool, Specified to Use Fair Value Gaps in Order Flow Detection ... + * @param containsSupportResistances: bool, Specified to Use Support and Resistances in Order Flow Detection ... + * @param zonesLoopback: int, Zone Detection Loopback ... + * @param zonesValidationLength: int, Zone Validation Length ... + * @param loopback: int, Max Allowed Loopback Bars for Collecting ... + * + * @return ( bool ) + */ bool HasOrderFlow( XOHCL &bar, ENUM_X_DIRECTION &dir, @@ -1908,7 +1686,6 @@ class XCMarketPatternDetector : public XCBase bool containsSupportResistances = false, int zonesLoopback = 5, int zonesValidationLength = 21, - int maxRequiredZone = 0, int loopback = 100 // ) { @@ -1919,6 +1696,7 @@ class XCMarketPatternDetector : public XCBase // Prepare ... XClean(orderFlow); CleanDirection(dir); + int maxRequiredZone = 0; // // Normalize ... @@ -3606,55 +3384,6 @@ class XCMarketPatternDetector : public XCBase // Validate Analysis ... result = analysis.IsValid(); - // - // Update Quarter ... - if (result) - { - // - // Retrieve Previous Bar ... - XOHCL pBar; - has = bar.GetPreviousBar(pBar); - if (has) - { - // - // Update Quarter ... - UpdateZones( - bar, - analysis.quarterActions, - config.quarterZonesValidationLength, // Zones Validation Length ... - config.quarterZonesRequiredToStart, // Zones Count to Start Processing ... - config.quarterZoneDetectionLoopback // Zones Detection Loopback ... - ); - - // - // Fill Quarter Props ... - analysis.majorSupport = majorSupport; - analysis.minorSupport = minorSupport; - analysis.quarter = CalculateQuarter(); - analysis.majorResistance = majorResistance; - analysis.minorResistance = minorResistance; - - // - // Update To Times ... - if (analysis.majorSupport.IsValid()) - { - analysis.majorSupport.to = bar.time; - } - if (analysis.minorSupport.IsValid()) - { - analysis.minorSupport.to = bar.time; - } - if (analysis.majorResistance.IsValid()) - { - analysis.majorResistance.to = bar.time; - } - if (analysis.minorResistance.IsValid()) - { - analysis.minorResistance.to = bar.time; - } - } - } - // // Cleanup Resources ... iZone.Clean(); @@ -3665,786 +3394,6 @@ class XCMarketPatternDetector : public XCBase return result; } - /** - * Update and Manage Support and Resistance Zones ... - * - * @param bar: XOHCL, reference to Specified Bar ... - * @param actions: ENUM_X_DETECTOR_ZONE_ACTION, refernce collection to Notify happens actions ... - * @param validationLength: int, Validation Length for Zones ... - * @param requiredZones: int, Number of required Zones to collecting ... - * @param loopback: int, Max Allowed Loopback Bars for Collecting ... - * - * @return ( int ) - */ - int UpdateZones( - XOHCL &bar, - ENUM_X_DETECTOR_ZONE_ACTION &actions[], - int validationLength = 3, - int requiredZones = 10, - int loopback = 1500 // - ) - { - // - int result = 0; - - // - // Prepare ... - XClean(actions); - - // - // Normalize ... - loopback = NormalizeInt(loopback, 100); - requiredZones = NormalizeInt(requiredZones, 5); - validationLength = NormalizeInt(validationLength, 2); - - // - // Validate ... - bool has = bar.IsValid(); - if (!has) - { - return result; - } - - // - int barIndex = bar.Index(); - - // - // Collect or Manage Zones ... - XOHCL zoneBar; - XBoxZone iZone; - bool hasZone = HasChild(zones); - int zonesCount = ArraySize(zones); - int zoneDetectionLoopback = (validationLength * 2); - if (!hasZone) - { - // - XOHCL iBar; - int start = barIndex; - int end = barIndex + loopback; - for (int i = start; i < end; i++) - { - // - // Extract Detected Zones ... - iBar.Clean(); - has = bar.BarAt(i, iBar); - if (!has) - { - continue; - } - - // - // Check Support ... - iZone.Clean(); - zoneBar.Clean(); - has = HasSupport( - iBar, - zoneBar, - validationLength, // Zone Validation Length ... - zoneDetectionLoopback // Zone Detection Loopback ... - ); - has = has && - ToSupportBox(zoneBar, iZone, bar.time); - if (has) - { - // - AddIfNotExists( - iZone, - zones // - ); - } - - // - // Check Resistance ... - iZone.Clean(); - zoneBar.Clean(); - has = HasResistance( - iBar, - zoneBar, - validationLength, // Zone Validation Length ... - zoneDetectionLoopback // Zone Detection Loopback ... - ); - has = has && - ToResistanceBox(zoneBar, iZone, bar.time); - if (has) - { - // - AddIfNotExists( - iZone, - zones // - ); - } - - // - // Validate Number of Zones ... - zonesCount = ArraySize(zones); - if (zonesCount >= requiredZones) - { - break; - } - } - - // - iBar.Clean(); - iZone.Clean(); - zoneBar.Clean(); - - // - // Update Has Zones ... - hasZone = HasChild(zones); - zonesCount = ArraySize(zones); - } - - // - // Manage Exists Zones ... - if (hasZone) - { - // - // Update Zones To Time ... - UpdateToTime(zones, bar.time); - - // - // Validate Zones ... - CheckZones(bar, zones); - - // - // Remove Breaked Zones ... - RemoveBreakedZones(zones); - - // - hasZone = HasChild(zones); - zonesCount = ArraySize(zones); - } - - // - // Minimum Exists Zones for Detecting majors ... - int minNumberOfZonesForMajors = 5; - bool canLookupMajor = hasZone && - zonesCount >= minNumberOfZonesForMajors; - - // - // Supports ... - - // - // Check Zones Existances ... - bool hasMajorSupport = majorSupport.IsValid(); - bool hasMinorSupport = minorSupport.IsValid(); - - // - // Check Major Support State ... - if (hasMajorSupport) - { - // - XOHCL pBar; - has = bar.GetPreviousBar(pBar); - if (has) - { - // - bool isBreaked = pBar.close < majorSupport.lower; - if (isBreaked) - { - // - int idx = -1; - has = FindIndex(idx, majorSupport, zones); - if (has) - { - zones[idx].breakAt = pBar.time; - } - majorSupport.Clean(); - minorSupport.Clean(); - hasMajorSupport = false; - hasMinorSupport = false; - Add( - X_DETECTOR_ZONE_ACTION_MAJOR_SUPPORT_BREAKED, - actions // - ); - } - } - - // - pBar.Clean(); - } - - // - // Look For Major Support ... - if (!hasMajorSupport) - { - // - minorSupport.Clean(); - hasMinorSupport = false; - - // - // Lookup Major ... - if (canLookupMajor) - { - // - int idx = GetLowestByDir(zones, X_DIRECTION_BULLISH); - hasMajorSupport = IsValidIndex(idx) && !IsXValid(zones[idx].breakAt); - if (hasMajorSupport) - { - // - majorSupport = zones[idx]; - Add( - X_DETECTOR_ZONE_ACTION_MAJOR_SUPPORT_DETECTED, - actions // - ); - } - } - } - - // - // Resistances ... - - // - // Check Zones Existances ... - bool hasMajorResistance = majorResistance.IsValid(); - bool hasMinorResistance = minorResistance.IsValid(); - - // - // Check Major Resistance State ... - if (hasMajorResistance) - { - // - XOHCL pBar; - has = bar.GetPreviousBar(pBar); - if (has) - { - // - bool isBreaked = pBar.close > majorResistance.upper; - if (isBreaked) - { - // - int idx = -1; - has = FindIndex(idx, majorResistance, zones); - if (has) - { - zones[idx].breakAt = pBar.time; - } - majorResistance.Clean(); - minorResistance.Clean(); - hasMajorResistance = false; - hasMinorResistance = false; - Add( - X_DETECTOR_ZONE_ACTION_MAJOR_RESISTANCE_BREAKED, - actions // - ); - } - } - - // - pBar.Clean(); - } - - // - // Look For Major Resistance ... - if (!hasMajorResistance) - { - // - minorResistance.Clean(); - hasMinorResistance = false; - - // - // Lookup Major ... - if (canLookupMajor) - { - // - int idx = GetHighestByDir(zones, X_DIRECTION_BEARISH); - hasMajorResistance = IsValidIndex(idx); - if (hasMajorResistance) - { - // - majorResistance = zones[idx]; - Add( - X_DETECTOR_ZONE_ACTION_MAJOR_RESISTANCE_DETECTED, - actions // - ); - } - } - } - - // - // Check Majors Exixsts ... - has = hasMajorSupport && - hasMajorResistance; - if (has) - { - // - double quarter = CalculateQuarter(); - - // - // For Looking up Minor Support, we - // have to Ensure Major Support Exists ... - if (hasMajorSupport) - { - // - majorSupport.to = bar.time; - - // - // Look for Minor Support ... - if (!hasMinorSupport) - { - // - XBoxZone _supports[]; - int _supportsCount = ExtractByDirection( - _supports, - zones, - X_DIRECTION_BULLISH // - ); - _supportsCount = RemoveBreakedZones(_supports); - has = IsValidSize(_supportsCount); - if (has) - { - // - // Remove Major ... - Remove( - majorSupport, - _supports // - ); - - // - // Count Remain Zones ... - _supportsCount = ArraySize(_supports); - has = IsValidSize(_supportsCount); - if (has) - { - // - // Minors Selected by Youngest ... - int idx = quarter > 0 - ? GetYoungestBelow(quarter, _supports) - : GetYoungest(_supports); - hasMinorSupport = IsValidIndex(idx) && !IsXValid(_supports[idx].breakAt); - if (hasMinorSupport) - { - // - minorSupport = _supports[idx]; - minorSupport.to = bar.time; - minorSupport.from = minorSupport.at; - Add( - X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_DETECTED, - actions // - ); - } - } - } - - // - XClean(_supports); - } - - // - // Validate Minor Support Place ... - if (quarter > 0 && - hasMinorSupport) - { - // - hasMinorSupport = minorSupport.upper < quarter; - if (!hasMinorSupport) - { - // - int idx = -1; - has = FindIndex( - idx, - minorSupport, - zones // - ); - if (has) - { - zones[idx].breakAt = bar.time; - } - minorSupport.Clean(); - } - } - - // - // Refine exists Minor Support ... - if (hasMinorSupport) - { - // - minorSupport.to = bar.time; - - // - XOHCL pBar; - has = bar.GetPreviousBar(pBar); - if (has) - { - // - // Check Break ... - bool isBreaked = pBar.close < minorSupport.lower; - if (isBreaked) - { - // - minorSupport.Clean(); - Add( - X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_BREAKED, - actions // - ); - } - - // - // Check Test ... - bool isTested = !isBreaked && - pBar.low < minorSupport.upper && - pBar.low > minorSupport.lower && - bar.close > minorSupport.lower && - bar.open > minorSupport.lower; - if (isTested) - { - // - Add( - X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_RETESTED, - actions // - ); - } - - // - // Check Refine ... - bool canRefine = !isBreaked && - pBar.low < minorSupport.lower && - pBar.close > minorSupport.lower; - if (canRefine) - { - // - minorSupport.upper = minorSupport.lower; - minorSupport.lower = pBar.low; - Add( - pBar.time, - minorSupport.refines // - ); - Add( - X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_REFINED, - actions // - ); - } - - // - // Check New Minor Support ... - has = !isTested && - !canRefine; - if (has) - { - // - // Check Above Minor Support has Support ... - XBoxZone _supports[]; - int _supportsCount = ExtractByDirection( - _supports, - zones, - X_DIRECTION_BULLISH // - ); - Remove(majorSupport, _supports); - Remove(minorSupport, _supports); - RemoveBreakedZones(_supports); - _supportsCount = ArraySize(_supports); - has = IsValidSize(_supportsCount); - if (has) - { - // - int idx = GetLowestAfter(minorSupport.from, _supports); - hasMinorSupport = IsValidIndex(idx) && - (quarter <= 0 - ? true - : _supports[idx].upper < quarter); - if (hasMinorSupport) - { - // - minorSupport = _supports[idx]; - minorSupport.to = bar.time; - minorSupport.from = minorSupport.at; - Add( - X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_DETECTED, - actions // - ); - } - } - } - } - - // - pBar.Clean(); - } - } - - // - // For Looking up Minor Resistance, we - // have to Ensure Major Resistance Exists ... - if (hasMajorResistance) - { - // - majorResistance.to = bar.time; - - // - // Look for Minor Resistance ... - if (!hasMinorResistance) - { - // - XBoxZone _resistances[]; - int _resistancesCount = ExtractByDirection( - _resistances, - zones, - X_DIRECTION_BEARISH // - ); - _resistancesCount = RemoveBreakedZones(_resistances); - has = IsValidSize(_resistancesCount); - if (has) - { - // - // Remove Major ... - Remove( - majorResistance, - _resistances // - ); - - // - // Count Remain Zones ... - _resistancesCount = ArraySize(_resistances); - has = IsValidSize(_resistancesCount); - if (has) - { - // - // Minors Selected Youngest ... - int idx = GetYoungestAbove(quarter, _resistances); - hasMinorResistance = IsValidIndex(idx); - if (hasMinorResistance) - { - // - minorResistance = _resistances[idx]; - minorResistance.to = bar.time; - minorResistance.from = minorResistance.at; - Add( - X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_DETECTED, - actions // - ); - } - } - } - - // - XClean(_resistances); - } - - // - // Validate Minor Support Place ... - if (quarter > 0 && - hasMinorResistance) - { - // - hasMinorResistance = minorResistance.lower > quarter; - if (!hasMinorResistance) - { - // - int idx = -1; - has = FindIndex( - idx, - minorResistance, - zones // - ); - if (has) - { - zones[idx].breakAt = bar.time; - } - minorResistance.Clean(); - } - } - - // - // Refine exists Minor Resistance ... - if (hasMinorResistance) - { - // - minorResistance.to = bar.time; - - // - // Check Retesting ... - XOHCL pBar; - has = bar.GetPreviousBar(pBar); - if (has) - { - // - // Check Break ... - bool isBreaked = pBar.close > minorResistance.upper; - if (isBreaked) - { - // - minorResistance.Clean(); - Add( - X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_BREAKED, - actions // - ); - } - - // - // Check Test ... - bool isTested = !isBreaked && - pBar.high > minorResistance.lower && - pBar.high < minorResistance.upper && - bar.close < minorResistance.upper && - bar.open < minorResistance.upper; - if (isTested) - { - // - Add( - X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_RETESTED, - actions // - ); - } - - // - // Check Refine ... - bool canRefine = !isBreaked && - pBar.high > minorResistance.upper && - pBar.close < minorResistance.upper; - if (canRefine) - { - // - minorResistance.lower = minorResistance.upper; - minorResistance.upper = pBar.high; - Add( - pBar.time, - minorResistance.refines // - ); - Add( - X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_REFINED, - actions // - ); - } - - // - // Check New Minor Resistace ... - has = !isTested && - !canRefine; - if (has) - { - // - // Check Above Minor Resistance has Resistance ... - XBoxZone _resistances[]; - int _resistancesCount = ExtractByDirection( - _resistances, - zones, - X_DIRECTION_BEARISH // - ); - Remove(majorResistance, _resistances); - Remove(minorResistance, _resistances); - RemoveBreakedZones(_resistances); - _resistancesCount = ArraySize(_resistances); - has = IsValidSize(_resistancesCount); - if (has) - { - // - int idx = GetHighestAfter(minorResistance.from, _resistances); - hasMinorResistance = IsValidIndex(idx) && - (quarter <= 0 - ? true - : _resistances[idx].lower > quarter); - if (hasMinorResistance) - { - // - minorResistance = _resistances[idx]; - minorResistance.to = bar.time; - minorResistance.from = minorResistance.at; - Add( - X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_DETECTED, - actions // - ); - } - } - } - } - - // - pBar.Clean(); - } - } - } - else - { - // - int idx = -1; - - // - has = minorSupport.IsValid() && - FindIndex( - idx, - minorSupport, - zones // - ); - if (has) - { - zones[idx].breakAt = bar.time; - } - minorSupport.Clean(); - hasMinorSupport = false; - - // - has = minorResistance.IsValid() && - FindIndex( - idx, - minorResistance, - zones // - ); - if (has) - { - zones[idx].breakAt = bar.time; - } - minorResistance.Clean(); - hasMinorResistance = false; - } - - // - // Check Bar Zones to Update Zones ... - - // - // Check Support ... - iZone.Clean(); - zoneBar.Clean(); - has = HasSupport( - bar, - zoneBar, - validationLength, // Zone Validation Length ... - zoneDetectionLoopback // Zone Detection Loopback ... - ); - has = has && - ToSupportBox(zoneBar, iZone, bar.time); - if (has) - { - // - AddIfNotExists( - iZone, - zones // - ); - } - - // - // Check Resistance ... - iZone.Clean(); - zoneBar.Clean(); - has = HasResistance( - bar, - zoneBar, - validationLength, // Zone Validation Length ... - zoneDetectionLoopback // Zone Detection Loopback ... - ); - has = has && - ToResistanceBox(zoneBar, iZone, bar.time); - if (has) - { - // - AddIfNotExists( - iZone, - zones // - ); - } - - // - // Actions Counting ... - result = ArraySize(actions); - - // - // Cleanup ... - iZone.Clean(); - zoneBar.Clean(); - - // - return result; - } - int CollectOBs( XOHCL &bar, XBoxZone &dest[], diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index 5b255076..f622ae20 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -1460,6 +1460,49 @@ class XCPOIDrawer : public XCBase } } + /** + * Draw Pivots ... + * + * @param pivots: XPivot, collection reference to Draw ... + * @param config: XPOIDrawConfig, reference to Specified Draw Style ... + */ + void DrawPivots( + XPivot &pivots[], + XPOIDrawConfig &config // + ) + { + // + // Validate ... + bool has = HasChild(pivots); + if (!has) + { + return; + } + + // + XPivot tmps[]; + int count = ArraySize(pivots); + for (int i = 0; i < count; i++) + { + // + XClean(tmps); + int sameCounts = ExtractSameTimePivots(pivots[i], tmps, pivots); + has = IsValidSize(sameCounts); + if (has) + { + // + for (int j = 0; j < sameCounts; j++) + { + DrawPivot(tmps[j], config, j + 1); + } + } + } + + // + // Cleanup ... + XClean(tmps); + } + /** * Draw Specified Pattern info ... * diff --git a/Documents/BKP/tmp.codes.mq5 b/Documents/BKP/tmp.codes.mq5 index 003f38b7..21a5c942 100644 --- a/Documents/BKP/tmp.codes.mq5 +++ b/Documents/BKP/tmp.codes.mq5 @@ -1,564 +1,563 @@ - // - int minRequiredRange = 20; - if (barIndex > maxBarIndex - minRequiredRange - 4) - { - return; - } +// +int minRequiredRange = 20; +if (barIndex > maxBarIndex - minRequiredRange - 4) +{ + return; +} - // - double iP2SCLL = sLLBuffer[barIndex + 2]; - double iP2SCHH = sHHBuffer[barIndex + 2]; +// +double iP2SCLL = sLLBuffer[barIndex + 2]; +double iP2SCHH = sHHBuffer[barIndex + 2]; - // - double iP3SCLL = sLLBuffer[barIndex + 3]; - double iP3SCHH = sHHBuffer[barIndex + 3]; +// +double iP3SCLL = sLLBuffer[barIndex + 3]; +double iP3SCHH = sHHBuffer[barIndex + 3]; - // - double iP4SCLL = sLLBuffer[barIndex + 4]; - double iP4SCHH = sHHBuffer[barIndex + 4]; +// +double iP4SCLL = sLLBuffer[barIndex + 4]; +double iP4SCHH = sHHBuffer[barIndex + 4]; - // - double iP2MCLL = mLLBuffer[barIndex + 2]; - double iP2MCHH = mHHBuffer[barIndex + 2]; +// +double iP2MCLL = mLLBuffer[barIndex + 2]; +double iP2MCHH = mHHBuffer[barIndex + 2]; - // - double iP3MCLL = mLLBuffer[barIndex + 3]; - double iP3MCHH = mHHBuffer[barIndex + 3]; +// +double iP3MCLL = mLLBuffer[barIndex + 3]; +double iP3MCHH = mHHBuffer[barIndex + 3]; - // - double iP4MCLL = mLLBuffer[barIndex + 4]; - double iP4MCHH = mHHBuffer[barIndex + 4]; +// +double iP4MCLL = mLLBuffer[barIndex + 4]; +double iP4MCHH = mHHBuffer[barIndex + 4]; - // - double iP2LCLL = lLLBuffer[barIndex + 2]; - double iP2LCHH = lHHBuffer[barIndex + 2]; +// +double iP2LCLL = lLLBuffer[barIndex + 2]; +double iP2LCHH = lHHBuffer[barIndex + 2]; - // - double iP3LCLL = lLLBuffer[barIndex + 3]; - double iP3LCHH = lHHBuffer[barIndex + 3]; +// +double iP3LCLL = lLLBuffer[barIndex + 3]; +double iP3LCHH = lHHBuffer[barIndex + 3]; - // - double iP4LCLL = lLLBuffer[barIndex + 4]; - double iP4LCHH = lHHBuffer[barIndex + 4]; +// +double iP4LCLL = lLLBuffer[barIndex + 4]; +double iP4LCHH = lHHBuffer[barIndex + 4]; - // - double iP2HCLL = hLLBuffer[barIndex + 2]; - double iP2HCHH = hHHBuffer[barIndex + 2]; +// +double iP2HCLL = hLLBuffer[barIndex + 2]; +double iP2HCHH = hHHBuffer[barIndex + 2]; - // - double iP3HCLL = hLLBuffer[barIndex + 3]; - double iP3HCHH = hHHBuffer[barIndex + 3]; +// +double iP3HCLL = hLLBuffer[barIndex + 3]; +double iP3HCHH = hHHBuffer[barIndex + 3]; - // - double iP4HCLL = hLLBuffer[barIndex + 4]; - double iP4HCHH = hHHBuffer[barIndex + 4]; - - // - // Cycle States ... +// +double iP4HCLL = hLLBuffer[barIndex + 4]; +double iP4HCHH = hHHBuffer[barIndex + 4]; - // - // Create Conditions ... +// +// Cycle States ... - // - bool isSCMaOverMCMa = iSCMa > iMCMa; - bool isPSCMaOverMCMa = iPSCMa > iPMCMa; +// +// Create Conditions ... - // - bool isSCMaUnderMCMa = iSCMa < iMCMa; - bool isPSCMaUnderMCMa = iPSCMa < iPMCMa; +// +bool isSCMaOverMCMa = iSCMa > iMCMa; +bool isPSCMaOverMCMa = iPSCMa > iPMCMa; - // - bool isSCMaCrossedOverMCMa = - isSCMaOverMCMa && - !isPSCMaOverMCMa; +// +bool isSCMaUnderMCMa = iSCMa < iMCMa; +bool isPSCMaUnderMCMa = iPSCMa < iPMCMa; - // - bool isSCMaCrossedUnderMCMa = - isSCMaUnderMCMa && - !isPSCMaUnderMCMa; +// +bool isSCMaCrossedOverMCMa = + isSCMaOverMCMa && + !isPSCMaOverMCMa; - // - bool isLCMaOverHCMa = iLCMa > iHCMa; - bool isPLCMaOverHCMa = iPLCMa > iPHCMa; +// +bool isSCMaCrossedUnderMCMa = + isSCMaUnderMCMa && + !isPSCMaUnderMCMa; - // - bool isLCMaUnderHCMa = iLCMa < iHCMa; - bool isPLCMaUnderHCMa = iPLCMa < iPHCMa; +// +bool isLCMaOverHCMa = iLCMa > iHCMa; +bool isPLCMaOverHCMa = iPLCMa > iPHCMa; - // - bool isLCMaCrossedOverHCMa = - isLCMaOverHCMa && - !isPLCMaOverHCMa; +// +bool isLCMaUnderHCMa = iLCMa < iHCMa; +bool isPLCMaUnderHCMa = iPLCMa < iPHCMa; - // - bool isLCMaCrossedUnderHCMa = - isLCMaUnderHCMa && - !isPLCMaUnderHCMa; +// +bool isLCMaCrossedOverHCMa = + isLCMaOverHCMa && + !isPLCMaOverHCMa; - // - // SC State ... +// +bool isLCMaCrossedUnderHCMa = + isLCMaUnderHCMa && + !isPLCMaUnderHCMa; - // - bool isSCMaBullish = - iSCMaState == bullishState; - bool isPSCMaBullish = - iPSCMaState == bullishState; +// +// SC State ... - // - bool isSCMaBearish = - iSCMaState == bearishState; - bool isPSCMaBearish = - iPSCMaState == bearishState; +// +bool isSCMaBullish = + iSCMaState == bullishState; +bool isPSCMaBullish = + iPSCMaState == bullishState; - // - bool isSCMaSwitchedToBullish = - isSCMaBullish && - !isPSCMaBullish; +// +bool isSCMaBearish = + iSCMaState == bearishState; +bool isPSCMaBearish = + iPSCMaState == bearishState; - // - bool isSCMaSwitchedToBearish = - isSCMaBearish && - !isPSCMaBearish; +// +bool isSCMaSwitchedToBullish = + isSCMaBullish && + !isPSCMaBullish; - // - bool isSCLLOverMCLL = - iSCLL > iMCLL; - bool isPSCLLOverMCLL = - iPSCLL > iPMCLL; - bool isP2SCLLOverMCLL = - iP2SCLL > iP2MCLL; - bool isP3SCLLOverMCLL = - iP3SCLL > iP3MCLL; - bool isP4SCLLOverMCLL = - iP4SCLL > iP4MCLL; +// +bool isSCMaSwitchedToBearish = + isSCMaBearish && + !isPSCMaBearish; - // - bool isSCHHUnderMCHH = - iSCHH < iMCHH; - bool isPSCHHUnderMCHH = - iPSCHH < iPMCHH; - bool isP2SCHHUnderMCHH = - iP2SCHH < iP2MCHH; - bool isP3SCHHUnderMCHH = - iP3SCHH < iP3MCHH; - bool isP4SCHHUnderMCHH = - iP4SCHH < iP4MCHH; +// +bool isSCLLOverMCLL = + iSCLL > iMCLL; +bool isPSCLLOverMCLL = + iPSCLL > iPMCLL; +bool isP2SCLLOverMCLL = + iP2SCLL > iP2MCLL; +bool isP3SCLLOverMCLL = + iP3SCLL > iP3MCLL; +bool isP4SCLLOverMCLL = + iP4SCLL > iP4MCLL; - // - bool isSCLLCrossedOverMCLL = - isSCLLOverMCLL && - !isPSCLLOverMCLL; - bool isPSCLLCrossedOverMCLL = - isPSCLLOverMCLL && - !isP2SCLLOverMCLL; - bool isP2SCLLCrossedOverMCLL = - isP2SCLLOverMCLL && - !isP3SCLLOverMCLL; - bool isP3SCLLCrossedOverMCLL = - isP3SCLLOverMCLL && - !isP4SCLLOverMCLL; +// +bool isSCHHUnderMCHH = + iSCHH < iMCHH; +bool isPSCHHUnderMCHH = + iPSCHH < iPMCHH; +bool isP2SCHHUnderMCHH = + iP2SCHH < iP2MCHH; +bool isP3SCHHUnderMCHH = + iP3SCHH < iP3MCHH; +bool isP4SCHHUnderMCHH = + iP4SCHH < iP4MCHH; - // - bool isSCHHCrossedUnderMCHH = - isSCHHUnderMCHH && - !isPSCHHUnderMCHH; - bool isPSCHHCrossedUnderMCHH = - isPSCHHUnderMCHH && - !isP2SCHHUnderMCHH; - bool isP2SCHHCrossedUnderMCHH = - isP2SCHHUnderMCHH && - !isP3SCHHUnderMCHH; - bool isP3SCHHCrossedUnderMCHH = - isP3SCHHUnderMCHH && - !isP4SCHHUnderMCHH; +// +bool isSCLLCrossedOverMCLL = + isSCLLOverMCLL && + !isPSCLLOverMCLL; +bool isPSCLLCrossedOverMCLL = + isPSCLLOverMCLL && + !isP2SCLLOverMCLL; +bool isP2SCLLCrossedOverMCLL = + isP2SCLLOverMCLL && + !isP3SCLLOverMCLL; +bool isP3SCLLCrossedOverMCLL = + isP3SCLLOverMCLL && + !isP4SCLLOverMCLL; - // - // MC State ... +// +bool isSCHHCrossedUnderMCHH = + isSCHHUnderMCHH && + !isPSCHHUnderMCHH; +bool isPSCHHCrossedUnderMCHH = + isPSCHHUnderMCHH && + !isP2SCHHUnderMCHH; +bool isP2SCHHCrossedUnderMCHH = + isP2SCHHUnderMCHH && + !isP3SCHHUnderMCHH; +bool isP3SCHHCrossedUnderMCHH = + isP3SCHHUnderMCHH && + !isP4SCHHUnderMCHH; - // - bool isMCMaBullish = - iMCMaState == bullishState; - bool isPMCMaBullish = - iPMCMaState == bullishState; +// +// MC State ... - // - bool isMCMaBearish = - iMCMaState == bearishState; - bool isPMCMaBearish = - iPMCMaState == bearishState; +// +bool isMCMaBullish = + iMCMaState == bullishState; +bool isPMCMaBullish = + iPMCMaState == bullishState; - // - bool isMCMaSwitchedToBullish = - isMCMaBullish && - !isPMCMaBullish; +// +bool isMCMaBearish = + iMCMaState == bearishState; +bool isPMCMaBearish = + iPMCMaState == bearishState; - // - bool isMCMaSwitchedToBearish = - isMCMaBearish && - !isPMCMaBearish; +// +bool isMCMaSwitchedToBullish = + isMCMaBullish && + !isPMCMaBullish; - // - bool isMCLLOverLCLL = - iMCLL > iLCLL; - bool isPMCLLOverLCLL = - iPMCLL > iPLCLL; - bool isP2MCLLOverLCLL = - iP2MCLL > iP2LCLL; - bool isP3MCLLOverLCLL = - iP3MCLL > iP3LCLL; - bool isP4MCLLOverLCLL = - iP4MCLL > iP4LCLL; +// +bool isMCMaSwitchedToBearish = + isMCMaBearish && + !isPMCMaBearish; - // - bool isMCHHUnderLCHH = - iMCHH < iLCHH; - bool isPMCHHUnderLCHH = - iPMCHH < iPLCHH; - bool isP2MCHHUnderLCHH = - iP2MCHH < iP2LCHH; - bool isP3MCHHUnderLCHH = - iP3MCHH < iP3LCHH; - bool isP4MCHHUnderLCHH = - iP4MCHH < iP4LCHH; +// +bool isMCLLOverLCLL = + iMCLL > iLCLL; +bool isPMCLLOverLCLL = + iPMCLL > iPLCLL; +bool isP2MCLLOverLCLL = + iP2MCLL > iP2LCLL; +bool isP3MCLLOverLCLL = + iP3MCLL > iP3LCLL; +bool isP4MCLLOverLCLL = + iP4MCLL > iP4LCLL; - // - bool isMCLLCrossedOverLCLL = - isMCLLOverLCLL && - !isPMCLLOverLCLL; - bool isPMCLLCrossedOverLCLL = - isPMCLLOverLCLL && - !isP2MCLLOverLCLL; - bool isP2MCLLCrossedOverLCLL = - isP2MCLLOverLCLL && - !isP3MCLLOverLCLL; - bool isP3MCLLCrossedOverLCLL = - isP3MCLLOverLCLL && - !isP4MCLLOverLCLL; +// +bool isMCHHUnderLCHH = + iMCHH < iLCHH; +bool isPMCHHUnderLCHH = + iPMCHH < iPLCHH; +bool isP2MCHHUnderLCHH = + iP2MCHH < iP2LCHH; +bool isP3MCHHUnderLCHH = + iP3MCHH < iP3LCHH; +bool isP4MCHHUnderLCHH = + iP4MCHH < iP4LCHH; - // - bool isMCHHCrossedUnderLCHH = - isMCHHUnderLCHH && - !isPMCHHUnderLCHH; - bool isPMCHHCrossedUnderLCHH = - isPMCHHUnderLCHH && - !isP2MCHHUnderLCHH; - bool isP2MCHHCrossedUnderLCHH = - isP2MCHHUnderLCHH && - !isP3MCHHUnderLCHH; - bool isP3MCHHCrossedUnderLCHH = - isP3MCHHUnderLCHH && - !isP4MCHHUnderLCHH; +// +bool isMCLLCrossedOverLCLL = + isMCLLOverLCLL && + !isPMCLLOverLCLL; +bool isPMCLLCrossedOverLCLL = + isPMCLLOverLCLL && + !isP2MCLLOverLCLL; +bool isP2MCLLCrossedOverLCLL = + isP2MCLLOverLCLL && + !isP3MCLLOverLCLL; +bool isP3MCLLCrossedOverLCLL = + isP3MCLLOverLCLL && + !isP4MCLLOverLCLL; - // - // LC State ... +// +bool isMCHHCrossedUnderLCHH = + isMCHHUnderLCHH && + !isPMCHHUnderLCHH; +bool isPMCHHCrossedUnderLCHH = + isPMCHHUnderLCHH && + !isP2MCHHUnderLCHH; +bool isP2MCHHCrossedUnderLCHH = + isP2MCHHUnderLCHH && + !isP3MCHHUnderLCHH; +bool isP3MCHHCrossedUnderLCHH = + isP3MCHHUnderLCHH && + !isP4MCHHUnderLCHH; - // - bool isLCMaBullish = - iLCMaState == bullishState; - bool isPLCMaBullish = - iPLCMaState == bullishState; +// +// LC State ... - // - bool isLCMaBearish = - iLCMaState == bearishState; - bool isPLCMaBearish = - iPLCMaState == bearishState; +// +bool isLCMaBullish = + iLCMaState == bullishState; +bool isPLCMaBullish = + iPLCMaState == bullishState; - // - bool isLCMaSwitchedToBullish = - isLCMaBullish && - !isPLCMaBullish; +// +bool isLCMaBearish = + iLCMaState == bearishState; +bool isPLCMaBearish = + iPLCMaState == bearishState; - // - bool isLCMaSwitchedToBearish = - isLCMaBearish && - !isPLCMaBearish; +// +bool isLCMaSwitchedToBullish = + isLCMaBullish && + !isPLCMaBullish; - // - bool isLCLLOverHCLL = - iLCLL > iHCLL; - bool isPLCLLOverHCLL = - iPLCLL > iPHCLL; - bool isP2LCLLOverHCLL = - iP2LCLL > iP2HCLL; - bool isP3LCLLOverHCLL = - iP3LCLL > iP3HCLL; - bool isP4LCLLOverHCLL = - iP4LCLL > iP4HCLL; +// +bool isLCMaSwitchedToBearish = + isLCMaBearish && + !isPLCMaBearish; - // - bool isLCHHUnderHCHH = - iLCHH < iHCHH; - bool isPLCHHUnderHCHH = - iPLCHH < iPHCHH; - bool isP2LCHHUnderHCHH = - iP2LCHH < iP2HCHH; - bool isP3LCHHUnderHCHH = - iP3LCHH < iP3HCHH; - bool isP4LCHHUnderHCHH = - iP4LCHH < iP4HCHH; +// +bool isLCLLOverHCLL = + iLCLL > iHCLL; +bool isPLCLLOverHCLL = + iPLCLL > iPHCLL; +bool isP2LCLLOverHCLL = + iP2LCLL > iP2HCLL; +bool isP3LCLLOverHCLL = + iP3LCLL > iP3HCLL; +bool isP4LCLLOverHCLL = + iP4LCLL > iP4HCLL; - // - bool isLCLLCrossedOverHCLL = - isLCLLOverHCLL && - !isPLCLLOverHCLL; - bool isPLCLLCrossedOverHCLL = - isPLCLLOverHCLL && - !isP2LCLLOverHCLL; - bool isP2LCLLCrossedOverHCLL = - isP2LCLLOverHCLL && - !isP3LCLLOverHCLL; - bool isP3LCLLCrossedOverHCLL = - isP3LCLLOverHCLL && - !isP4LCLLOverHCLL; +// +bool isLCHHUnderHCHH = + iLCHH < iHCHH; +bool isPLCHHUnderHCHH = + iPLCHH < iPHCHH; +bool isP2LCHHUnderHCHH = + iP2LCHH < iP2HCHH; +bool isP3LCHHUnderHCHH = + iP3LCHH < iP3HCHH; +bool isP4LCHHUnderHCHH = + iP4LCHH < iP4HCHH; - // - bool isLCHHCrossedUnderHCHH = - isLCHHUnderHCHH && - !isPLCHHUnderHCHH; - bool isPLCHHCrossedUnderHCHH = - isPLCHHUnderHCHH && - !isP2LCHHUnderHCHH; - bool isP2LCHHCrossedUnderHCHH = - isP2LCHHUnderHCHH && - !isP3LCHHUnderHCHH; - bool isP3LCHHCrossedUnderHCHH = - isP3LCHHUnderHCHH && - !isP4LCHHUnderHCHH; +// +bool isLCLLCrossedOverHCLL = + isLCLLOverHCLL && + !isPLCLLOverHCLL; +bool isPLCLLCrossedOverHCLL = + isPLCLLOverHCLL && + !isP2LCLLOverHCLL; +bool isP2LCLLCrossedOverHCLL = + isP2LCLLOverHCLL && + !isP3LCLLOverHCLL; +bool isP3LCLLCrossedOverHCLL = + isP3LCLLOverHCLL && + !isP4LCLLOverHCLL; - // - // HC State ... +// +bool isLCHHCrossedUnderHCHH = + isLCHHUnderHCHH && + !isPLCHHUnderHCHH; +bool isPLCHHCrossedUnderHCHH = + isPLCHHUnderHCHH && + !isP2LCHHUnderHCHH; +bool isP2LCHHCrossedUnderHCHH = + isP2LCHHUnderHCHH && + !isP3LCHHUnderHCHH; +bool isP3LCHHCrossedUnderHCHH = + isP3LCHHUnderHCHH && + !isP4LCHHUnderHCHH; - // - bool isHCMaBullish = - iHCMaState == bullishState; - bool isPHCMaBullish = - iPHCMaState == bullishState; +// +// HC State ... - // - bool isHCMaBearish = - iHCMaState == bearishState; - bool isPHCMaBearish = - iPHCMaState == bearishState; +// +bool isHCMaBullish = + iHCMaState == bullishState; +bool isPHCMaBullish = + iPHCMaState == bullishState; - // - bool isHCMaSwitchedToBullish = - isHCMaBullish && - !isPHCMaBullish; +// +bool isHCMaBearish = + iHCMaState == bearishState; +bool isPHCMaBearish = + iPHCMaState == bearishState; - // - bool isHCMaSwitchedToBearish = - isHCMaBearish && - !isPHCMaBearish; +// +bool isHCMaSwitchedToBullish = + isHCMaBullish && + !isPHCMaBullish; + +// +bool isHCMaSwitchedToBearish = + isHCMaBearish && + !isPHCMaBearish; /////////////////////////////////////////////////////////////////////////////// - // - // HK Signal Bar ... +// +// HK Signal Bar ... - // - double iHKSOpen = hkSBarOpenBuffer[barIndex]; - double iHKSClose = hkSBarCloseBuffer[barIndex]; +// +double iHKSOpen = hkSBarOpenBuffer[barIndex]; +double iHKSClose = hkSBarCloseBuffer[barIndex]; - // - double iHKSMax = MathMax(iHKSOpen, iHKSClose); - double iHKSMin = MathMin(iHKSOpen, iHKSClose); +// +double iHKSMax = MathMax(iHKSOpen, iHKSClose); +double iHKSMin = MathMin(iHKSOpen, iHKSClose); - // - bool isHKSBullish = hkSBarOpenBuffer[barIndex] < hkSBarCloseBuffer[barIndex]; - bool isPHKSBullish = hkSBarOpenBuffer[barIndex + 1] < hkSBarCloseBuffer[barIndex + 1]; +// +bool isHKSBullish = hkSBarOpenBuffer[barIndex] < hkSBarCloseBuffer[barIndex]; +bool isPHKSBullish = hkSBarOpenBuffer[barIndex + 1] < hkSBarCloseBuffer[barIndex + 1]; - // - bool isHKSBearish = hkSBarOpenBuffer[barIndex] > hkSBarCloseBuffer[barIndex]; - bool isPHKSBearish = hkSBarOpenBuffer[barIndex + 1] > hkSBarCloseBuffer[barIndex + 1]; +// +bool isHKSBearish = hkSBarOpenBuffer[barIndex] > hkSBarCloseBuffer[barIndex]; +bool isPHKSBearish = hkSBarOpenBuffer[barIndex + 1] > hkSBarCloseBuffer[barIndex + 1]; - // - bool isHKSSwitchedToBullish = - isHKSBullish && - !isPHKSBullish; +// +bool isHKSSwitchedToBullish = + isHKSBullish && + !isPHKSBullish; - // - bool isHKSSwitchedToBearish = - isHKSBearish && - !isPHKSBearish; +// +bool isHKSSwitchedToBearish = + isHKSBearish && + !isPHKSBearish; - // - // TREND ... +// +// TREND ... - // - double iTrend = trendBuffer[barIndex]; - bool isTrendBullish = trendStateBuffer[barIndex] > 0; - bool isTrendBearish = trendStateBuffer[barIndex] < 0; - bool isTrendSwitchedToBullish = - trendStateBuffer[barIndex] > 0 && - trendStateBuffer[barIndex + 1] <= 0; - bool isTrendSwitchedToBearish = - trendStateBuffer[barIndex] < 0 && - trendStateBuffer[barIndex + 1] >= 0; +// +double iTrend = trendBuffer[barIndex]; +bool isTrendBullish = trendStateBuffer[barIndex] > 0; +bool isTrendBearish = trendStateBuffer[barIndex] < 0; +bool isTrendSwitchedToBullish = + trendStateBuffer[barIndex] > 0 && + trendStateBuffer[barIndex + 1] <= 0; +bool isTrendSwitchedToBearish = + trendStateBuffer[barIndex] < 0 && + trendStateBuffer[barIndex + 1] >= 0; - // - // RSI ... +// +// RSI ... - // - bool isRSIOverOB = rsiBuffer[barIndex] > rsiOBLevel; - bool isPRSIOverOB = rsiBuffer[barIndex + 1] > rsiOBLevel; +// +bool isRSIOverOB = rsiBuffer[barIndex] > rsiOBLevel; +bool isPRSIOverOB = rsiBuffer[barIndex + 1] > rsiOBLevel; - // - bool isRSIUnderOB = rsiBuffer[barIndex] < rsiOBLevel; - bool isPRSIUnderOB = rsiBuffer[barIndex + 1] < rsiOBLevel; +// +bool isRSIUnderOB = rsiBuffer[barIndex] < rsiOBLevel; +bool isPRSIUnderOB = rsiBuffer[barIndex + 1] < rsiOBLevel; - // - bool isRSICrossedOverOB = - isRSIOverOB && - !isPRSIOverOB; +// +bool isRSICrossedOverOB = + isRSIOverOB && + !isPRSIOverOB; - // - bool isRSICrossedUnderOB = - isRSIUnderOB && - !isPRSIUnderOB; +// +bool isRSICrossedUnderOB = + isRSIUnderOB && + !isPRSIUnderOB; - // - bool isRSIOverOS = rsiBuffer[barIndex] > rsiOSLevel; - bool isPRSIOverOS = rsiBuffer[barIndex + 1] > rsiOSLevel; +// +bool isRSIOverOS = rsiBuffer[barIndex] > rsiOSLevel; +bool isPRSIOverOS = rsiBuffer[barIndex + 1] > rsiOSLevel; - // - bool isRSIUnderOS = rsiBuffer[barIndex] < rsiOSLevel; - bool isPRSIUnderOS = rsiBuffer[barIndex + 1] < rsiOSLevel; +// +bool isRSIUnderOS = rsiBuffer[barIndex] < rsiOSLevel; +bool isPRSIUnderOS = rsiBuffer[barIndex + 1] < rsiOSLevel; - // - bool isRSICrossedOverOS = - isRSIOverOS && - !isPRSIOverOS; +// +bool isRSICrossedOverOS = + isRSIOverOS && + !isPRSIOverOS; - // - bool isRSICrossedUnderOS = - isRSIUnderOS && - !isPRSIUnderOS; +// +bool isRSICrossedUnderOS = + isRSIUnderOS && + !isPRSIUnderOS; - // - // ADX ... +// +// ADX ... - // - bool isADXOverThreshold = adxBuffer[barIndex] > adxThreshold; - bool isPADXOverThreshold = adxBuffer[barIndex + 1] > adxThreshold; +// +bool isADXOverThreshold = adxBuffer[barIndex] > adxThreshold; +bool isPADXOverThreshold = adxBuffer[barIndex + 1] > adxThreshold; - // - bool isADXUnderThreshold = adxBuffer[barIndex] < adxThreshold; - bool isPADXUnderThreshold = adxBuffer[barIndex + 1] < adxThreshold; +// +bool isADXUnderThreshold = adxBuffer[barIndex] < adxThreshold; +bool isPADXUnderThreshold = adxBuffer[barIndex + 1] < adxThreshold; - // - bool isADXCrossedOverThreshold = - isADXOverThreshold && - !isPADXOverThreshold; +// +bool isADXCrossedOverThreshold = + isADXOverThreshold && + !isPADXOverThreshold; - // - bool isADXCrossedUnderThreshold = - isADXUnderThreshold && - !isPADXUnderThreshold; +// +bool isADXCrossedUnderThreshold = + isADXUnderThreshold && + !isPADXUnderThreshold; - // - bool isADXBullish = adxpBuffer[barIndex] > adxnBuffer[barIndex]; - bool isPADXBullish = adxpBuffer[barIndex + 1] > adxnBuffer[barIndex + 1]; +// +bool isADXBullish = adxpBuffer[barIndex] > adxnBuffer[barIndex]; +bool isPADXBullish = adxpBuffer[barIndex + 1] > adxnBuffer[barIndex + 1]; - // - bool isADXBearish = adxpBuffer[barIndex] < adxnBuffer[barIndex]; - bool isPADXBearish = adxpBuffer[barIndex + 1] < adxnBuffer[barIndex + 1]; +// +bool isADXBearish = adxpBuffer[barIndex] < adxnBuffer[barIndex]; +bool isPADXBearish = adxpBuffer[barIndex + 1] < adxnBuffer[barIndex + 1]; - // - bool isADXSwitchedToBullish = - isADXBullish && - !isPADXBullish; +// +bool isADXSwitchedToBullish = + isADXBullish && + !isPADXBullish; - // - bool isADXSwitchedToBearish = - isADXBearish && - !isPADXBearish; +// +bool isADXSwitchedToBearish = + isADXBearish && + !isPADXBearish; - // - bool isADXFullySwitchedToBullish = - isADXSwitchedToBullish && - isADXCrossedOverThreshold; +// +bool isADXFullySwitchedToBullish = + isADXSwitchedToBullish && + isADXCrossedOverThreshold; - // - bool isADXFullySwitchedToBearish = - isADXSwitchedToBearish && - isADXCrossedUnderThreshold; +// +bool isADXFullySwitchedToBearish = + isADXSwitchedToBearish && + isADXCrossedUnderThreshold; - // - bool isTriggerBarOverHKS = - iBar.low > iHKSMax; - bool isTriggerBarUnderHKS = - iBar.high < iHKSMin; +// +bool isTriggerBarOverHKS = + iBar.low > iHKSMax; +bool isTriggerBarUnderHKS = + iBar.high < iHKSMin; - // - // KI ... +// +// KI ... - // - bool isKIBullish = kiStateBuffer[barIndex] > 0; - bool isPKIBullish = kiStateBuffer[barIndex + 1] > 0; +// +bool isKIBullish = kiStateBuffer[barIndex] > 0; +bool isPKIBullish = kiStateBuffer[barIndex + 1] > 0; - // - bool isKIBearish = kiStateBuffer[barIndex] < 0; - bool isPKIBearish = kiStateBuffer[barIndex = 1] < 0; +// +bool isKIBearish = kiStateBuffer[barIndex] < 0; +bool isPKIBearish = kiStateBuffer[barIndex = 1] < 0; - // // - // bool isKIOverHKS = - // kiBuffer[barIndex] > iHKSMax; +// // +// bool isKIOverHKS = +// kiBuffer[barIndex] > iHKSMax; - // // - // bool isKIUnderHKS = - // kiBuffer[barIndex] < iHKSMin; - - // - bool isKISwitchedToBullish = - isKIBullish && - !isPKIBullish; +// // +// bool isKIUnderHKS = +// kiBuffer[barIndex] < iHKSMin; - // - bool isKISwitchedToBearish = - isKIBearish && - !isPKIBearish; +// +bool isKISwitchedToBullish = + isKIBullish && + !isPKIBullish; - // - // Detecting Signal ... +// +bool isKISwitchedToBearish = + isKIBearish && + !isPKIBearish; - // - // Bullish ... - isBullish = - // - false - // Conditions Validation ... - // isKIOverHKS && - // isHKSBullish && - // isKISwitchedToBullish - // && - // - // Bar Validation ... - // iBar.IsBullish() && - // iBar.close > kiBuffer[barIndex] - // - ; +// +// Detecting Signal ... +// +// Bullish ... +isBullish = // - // Bearish ... - isBearish = - // - false - // Conditions Validation ... - // isKIUnderHKS && - // isHKSBearish && - // isKISwitchedToBearish - // && - // - // Bar Validation ... - // iBar.IsBearish() && - // iBar.close < kiBuffer[barIndex] - // - ; + false + // Conditions Validation ... + // isKIOverHKS && + // isHKSBullish && + // isKISwitchedToBullish + // && + // + // Bar Validation ... + // iBar.IsBullish() && + // iBar.close > kiBuffer[barIndex] + // + ; + +// +// Bearish ... +isBearish = + // + false + // Conditions Validation ... + // isKIUnderHKS && + // isHKSBearish && + // isKISwitchedToBearish + // && + // + // Bar Validation ... + // iBar.IsBearish() && + // iBar.close < kiBuffer[barIndex] + // + ; //////////////////////////////////////////////////////////////////// - // int mSameKICount = 0; int mSameKIBullishCount = 0; @@ -2046,3 +2045,5123 @@ void DoProcess( //////////////////////////////////////////////////////////////////// +/** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( bool ) + */ +bool AnalysePVPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractPVPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength, // Max Allowed Loopback ... + validationLength // Validation Length ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XPV", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; +} + +/** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( bool ) + */ +bool AnalyseMAPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractMAPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength, // Max Allowed Loopback ... + validationLength // Validation Length ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XMA", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; +} + +/** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( bool ) + */ +bool AnalyseSARPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractSARPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength // Max Allowed Loopback ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XSAR", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; +} + +/** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( bool ) + */ +bool AnalyseZigZagPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractZigZagPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength // Max Allowed Loopback ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XZG", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; +} + +/** + * Analyse Market based on Specified Bar ... + * + * @param structure: XFIMAMarketStructure, reference to holds result ... + * @param config: XFIMAMarketStructureConfig, reference to Configure Detector ... + * @param barIndex: int, Bar Index ... + */ +void AnalyseMarket( + XFIMAMarketStructure &structure, + XFIMAMarketStructureConfig &config, + int barIndex = 0 // +) +{ + // + // Prepare ... + structure.Clean(); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + bool has = false; + + // + has = structure.bar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + structure.Clean(); + return; + } + + // + // Reading Bar Patterns ... + XOHCL iBar; + XPatternAnalysis iPatternAnalysis; + for (int i = barIndex; i < barIndex + config.loopback; i++) + { + // + // Cleanup ... + iBar.Clean(); + iPatternAnalysis.Clean(); + + // + // Initialize Indexed Bar ... + // + has = structure.bar.BarAt(i, iBar); + if (!has) + { + break; + } + + // + // Analyse Indexed Bar ... + has = AnalyseBarPatterns(iBar, iPatternAnalysis, config.barsAnalysisConfig); + if (has) + { + // + AddRef( + iPatternAnalysis, + structure.barsAnalysis // + ); + + // + if (i == barIndex) + { + structure.barAnalysis = iPatternAnalysis; + } + } + + // + // Check Satisfied ... + has = ArraySize(structure.barsAnalysis) >= config.requiredPivots; + if (has) + { + break; + } + } + + // + // Handle Pivot Analysis ... + + // + // XPV ... + if (config.analysePVPivots) + { + // + // Reading Pivots ... + has = AnalysePVPivots( + structure.pvAnalysis, + barIndex, + config.requiredPivots, + config.loopback, + config.pvPivotsValidationLength // + ); + if (!has) + { + structure.pvAnalysis.Clean(); + } + } + + // + // XZG ... + if (config.analyseZGPivots) + { + // + // Reading Pivots ... + has = AnalyseZigZagPivots( + structure.zgAnalysis, + barIndex, + config.requiredPivots, + config.loopback // + ); + if (!has) + { + structure.zgAnalysis.Clean(); + } + } + + // + // Cleanup ... + iBar.Clean(); + iPatternAnalysis.Clean(); +} + +//////////////////////////////////////////////////////////////////// + +/** + * Check Specified Bar has MA Cross or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... + * + * @return ( bool ) + */ +bool HasMACross( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + double validCrossDiffMultiplier = 1 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double fast[]; + int fastCount = CopyMAFast(barIndex, 2, fast); + + // + double slow[]; + int slowCount = CopyMASlow(barIndex, 2, slow); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + int count = MathMin(fastCount, slowCount); + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + bool notEmpty = + NotEmptyZero(fast[0]) && + NotEmptyZero(fast[1]) && + NotEmptyZero(slow[0]) && + NotEmptyZero(slow[1]); + + // + isBullish = + notEmpty && + fast[0] > slow[0] && + fast[1] < slow[1]; + + // + isBearish = + notEmpty && + fast[0] < slow[0] && + fast[1] > slow[1]; + + // + result = + isBullish || + isBearish; + + // + // Validate Direction Change ... + if (result && + validCrossDiffMultiplier > 0) + { + // + double _points = GetPoints(GetSymbol()); + double diff = MathAbs(fast[0] - slow[0]); + + // + result = diff >= (validCrossDiffMultiplier * _points); + } + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + + // + return result; +} + +/** + * Check Specified Bar Price is In Boundary or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool IsInBoundary( + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Bar ... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + double value = bar.GetPrice(priceType); + + // + // Read Boundary Values ... + double min; + double max; + result = GetBoundaryValues(min, max, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + result = value < max && + value > min; + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar Price is Over Boundary Min ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool IsOverBoundaryMin( + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Boundary ... + double min; + double max; + result = GetBoundaryValues(min, max, barIndex); + if (!result) + { + return result; + } + + // + // Retrieve Bar .... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + double value = bar.GetPrice(priceType); + + // + result = value > min; + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar Price is Under Boundary Max ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool IsUnderBoundaryMax( + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Boundary ... + double min; + double max; + result = GetBoundaryValues(min, max, barIndex); + if (!result) + { + return result; + } + + // + // Retrieve Bar .... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + double value = bar.GetPrice(priceType); + + // + result = value < max; + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check Boundary Fake Breaked or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param overMaxPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * @param underMinPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * + * @return ( bool ) + */ +bool IsBoundaryFakeBreaked( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + ENUM_X_PRICE overMaxPriceType = X_PRICE_NONE, + ENUM_X_PRICE underMinPriceType = X_PRICE_NONE // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(overMaxPriceType)) + { + overMaxPriceType = X_PRICE_CLOSE; + } + if (!IsXValid(underMinPriceType)) + { + underMinPriceType = X_PRICE_CLOSE; + } + + // + // Initial Bars ... + XOHCL bar; + XOHCL pBar; + double min; + double max; + double pMin; + double pMax; + double boundaryValues[]; + result = + bar.Init( + mSymbol, + mPeriod, + barIndex // + ) && + bar.GetPreviousBar(pBar) && + GetBoundaryValues(min, max, barIndex) && + GetBoundaryValues(pMin, pMax, barIndex + 1) && + FillBoundaryValues(boundaryValues, barIndex) > 0; + + // + bool isBullish = + result && + pBar.IsBearish() && + bar.IsBullish() && + pBar.GetPrice(underMinPriceType) < pMin && + bar.GetPrice(underMinPriceType) > min && + (bar.GetPrice(underMinPriceType) > FindLesserThan(max, boundaryValues) || + bar.GetPrice(underMinPriceType) > FindBiggerThan(min + ((max - min) / 2), boundaryValues)); + + // + bool isBearish = + result && + pBar.IsBullish() && + bar.IsBearish() && + pBar.GetPrice(overMaxPriceType) > pMax && + bar.GetPrice(overMaxPriceType) < max && + (bar.GetPrice(overMaxPriceType) < FindBiggerThan(min, boundaryValues) || + bar.GetPrice(overMaxPriceType) < FindLesserThan(min + ((max - min) / 2), boundaryValues)); + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Cleanup ... + bar.Clean(); + pBar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar's Price in Hot Place or Not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param overMaxPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * @param underMinPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * + * @return ( bool ) + */ +bool IsInHotPlace( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + ENUM_X_PRICE overMaxPriceType = X_PRICE_NONE, + ENUM_X_PRICE underMinPriceType = X_PRICE_NONE // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(overMaxPriceType)) + { + overMaxPriceType = X_PRICE_LOW; + } + if (!IsXValid(underMinPriceType)) + { + underMinPriceType = X_PRICE_HIGH; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Initialize Bar ... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double overMaxPrice = bar.GetPrice(overMaxPriceType); + double underMinPrice = bar.GetPrice(underMinPriceType); + + // + // Reading Boundary Value ... + double min; + double max; + result = GetBoundaryValues( + min, + max, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + bool isBullish = underMinPrice < min; + bool isBearish = overMaxPrice > max; + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar price Crossed in Boundary or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to hold Crossed in Dir ... + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool IsCrossedInBoundary( + ENUM_X_DIRECTION &dir, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + int pBarIndex = barIndex + 1; + + // + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Check PrevBar Is in Hot Place ... + result = IsInHotPlace( + dir, + pBarIndex, + X_PRICE_LOW, + X_PRICE_HIGH // + ); + if (!result) + { + // + dir = X_DIRECTION_NONE; + + // + return result; + } + + // + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + // Current Bar must Into Boundary ... + result = IsInBoundary(priceType, barIndex); + if (!result) + { + dir = X_DIRECTION_NONE; + } + + // + result = HasDirection(dir); + + // + return result; +} + +/** + * Check Specified Bar price Crossed out Boundary or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to hold Crossed in Dir ... + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool IsCrossedOutBoundary( + ENUM_X_DIRECTION &dir, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + int pBarIndex = barIndex + 1; + + // + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Prev Bar Must in Boundary ... + bool isBullish = IsInBoundary(X_PRICE_LOW, pBarIndex); + bool isBearish = IsInBoundary(X_PRICE_HIGH, pBarIndex); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Current Bar must Out of Boundary ... + + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + + // + isBullish = + result && + isBullish && + bar.IsBullish() && + !IsInBoundary(priceType, barIndex); + + // + isBearish = + result && + isBearish && + bar.IsBearish() && + !IsInBoundary(priceType, barIndex); + + // + result = isBullish || + isBearish; + if (!result) + { + // + bar.Clean(); + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar has Boundary Trend or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool HasBoundaryTrend( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double fast = GetMAFast(barIndex); + double slow = GetMASlow(barIndex); + + // + double maBandUpper = GetMABandUpper(barIndex); + double maBandLower = GetMABandLower(barIndex); + + // + double pbBandUpper = GetPBBandUpper(barIndex); + double pbBandLower = GetPBBandLower(barIndex); + + // + double hkBandUpper = GetHKBandUpper(barIndex); + double hkBandLower = GetHKBandLower(barIndex); + + // + result = + NotEmptyZero(fast) && + NotEmptyZero(slow) && + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower); + if (!result) + { + return result; + } + + // + bool isBullish = + fast > hkBandLower && + slow > hkBandLower && + maBandUpper > hkBandLower && + maBandLower > hkBandLower && + pbBandUpper > hkBandLower && + pbBandLower > hkBandLower; + bool isBearish = + fast < hkBandUpper && + slow < hkBandUpper && + maBandUpper < hkBandUpper && + maBandLower < hkBandUpper && + pbBandUpper < hkBandUpper && + pbBandLower < hkBandUpper; + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; +} + +/** + * Check Specified Bar has Boundary Trend Switched or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool HasBoundarySwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = HasBoundaryTrend( + dir, + barIndex // + ); + if (!result) + { + return result; + } + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + result = HasBoundaryTrend( + dir, + barIndex + 1 // + ); + if (!result) + { + return result; + } + bool isPBullish = IsXBullish(dir); + bool isPBearish = IsXBearish(dir); + + // + bool isSwitchedToBullish = + isBullish && !isPBullish; + bool isSwitchedToBearish = + isBearish && !isPBearish; + result = isSwitchedToBullish || + isSwitchedToBearish; + if (result) + { + // + dir = isSwitchedToBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; +} + +/** + * Check Fibo Section is Changed or not ... + * + * @param dir: reference to hold section change direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool IsFiboSectionChanged( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + // Reading Values ... + + // + double iFiboUpper = GetFiboUpper(barIndex); + double pFiboUpper = GetFiboUpper(barIndex + 1); + + // + double iFiboMiddle = GetFiboMiddle(barIndex); + double pFiboMiddle = GetFiboMiddle(barIndex + 1); + + // + double iFiboLower = GetFiboLower(barIndex); + double pFiboLower = GetFiboLower(barIndex + 1); + + // + isBullish = iFiboLower >= pFiboMiddle && + iFiboMiddle >= pFiboUpper; + isBearish = iFiboUpper <= pFiboMiddle && + iFiboMiddle <= pFiboLower; + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (!result) + { + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; +} + +/** + * Check for Fibo Push Exists or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to hold result ... + * @param barIndex: int, Specified Bar Index ... + * @param validationLength: int, Validation Length ... + * + * @return ( bool ) + */ +bool HasFiboPush( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + int validationLength = 5 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 3); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL iBar; + bool isBullish = false; + bool isBearish = false; + + // + double iFiboUpper = EMPTY_VALUE; + double pFiboUpper = EMPTY_VALUE; + + // + double iFiboMiddle = EMPTY_VALUE; + double pFiboMiddle = EMPTY_VALUE; + + // + double iFiboLower = EMPTY_VALUE; + double pFiboLower = EMPTY_VALUE; + + // + // Check Zone Validation ... + int start = barIndex; + int end = start + validationLength; + for (int i = start; i < end; i++) + { + // + // Reading Values ... + + // + iFiboUpper = GetFiboUpper(i); + pFiboUpper = GetFiboUpper(i + 1); + + // + iFiboMiddle = GetFiboMiddle(i); + pFiboMiddle = GetFiboMiddle(i + 1); + + // + iFiboLower = GetFiboLower(i); + pFiboLower = GetFiboLower(i + 1); + + // + result = iFiboUpper == pFiboUpper; + if (!result) + { + break; + } + } + + // + if (result) + { + // + result = iBar.Init( + mSymbol, + mPeriod, + barIndex // + ); + + // + if (result) + { + // + iFiboUpper = GetFiboUpper(barIndex); + iFiboMiddle = GetFiboMiddle(barIndex); + iFiboLower = GetFiboLower(barIndex); + + // + isBullish = iBar.IsBullish() && + iBar.close > iFiboLower && + iBar.low < iFiboLower; + isBearish = iBar.IsBearish() && + iBar.close < iFiboUpper && + iBar.high > iFiboUpper; + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; +} + +/** + * Check Has Higher Low Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ +bool HasZigZagHigherLow( + int barIndex = 0, + bool forceBarValidation = false // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsVale(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot vales[]; + count = ExtractPivots( + vales, + pivots, + X_PIVOT_TYPE_VALE // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + vales[0].value > vales[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open > vales[0].value && + bar.close > vales[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; +} + +/** + * Check Has Lower Low Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ +bool HasZigZagLowerLow( + int barIndex = 0, + bool forceBarValidation = false // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsVale(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot vales[]; + count = ExtractPivots( + vales, + pivots, + X_PIVOT_TYPE_VALE // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + vales[0].value < vales[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open < vales[0].value && + bar.close < vales[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; +} + +/** + * Check Has Higher High Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ +bool HasZigZagHigherHigh( + int barIndex = 0, + bool forceBarValidation = false // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsPeak(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot peaks[]; + count = ExtractPivots( + peaks, + pivots, + X_PIVOT_TYPE_PEAK // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + peaks[0].value > peaks[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open > peaks[0].value && + bar.close > peaks[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; +} + +/** + * Check Has Lower High Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ +bool HasZigZagLowerHigh( + int barIndex = 0, + bool forceBarValidation = false // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsPeak(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot peaks[]; + count = ExtractPivots( + peaks, + pivots, + X_PIVOT_TYPE_PEAK // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + peaks[0].value < peaks[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open < peaks[0].value && + bar.close < peaks[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; +} + +// +// SAR ... + +/** + * Check Specified Bar has SAR Switch or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool HasSARSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double sars[]; + int count = CopySarState(barIndex, 2, sars); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + isBullish = + sars[0] >= 1 && + sars[1] <= -1; + + // + isBearish = + sars[0] <= -1 && + sars[1] >= 1; + + // + result = + isBullish || + isBearish; + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(sars); + + // + return result; +} + +// +// PV ... + +// +// HK ... + +/** + * Check Specified Bar has HK Switch or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool HasHKSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + double open[]; + int openCount = CopyHKOpen(barIndex, 2, open); + + // + double close[]; + int closeCount = CopyHKClose(barIndex, 2, close); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + int count = MathMin(openCount, closeCount); + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + bool notEmpty = + NotEmptyZero(open[0]) && + NotEmptyZero(open[1]) && + NotEmptyZero(close[0]) && + NotEmptyZero(close[1]); + + // + isBullish = + notEmpty && + open[0] < close[0] && + open[1] > close[1]; + + // + isBearish = + notEmpty && + open[0] > close[0] && + open[1] < close[1]; + + // + result = + isBullish || + isBearish; + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(open); + XClean(close); + + // + return result; +} + +/** + * Check Specified Bar has HK Band Based Trend or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to holds trend direction, if exists ... + * @param barIndex: int, Specified Bar Index ... + * @param validationLength: int, validation of trend ... + * + * @return ( bool ) + */ +bool HasHKBasedTrend( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + int validationLength = 5 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 1); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Define Requirements ... + XOHCL iBar; + double hkUpper; + double hkLower; + bool has = false; + int bullishCount = 0; + int bearishCount = 0; + bool isBullish = false; + bool isBearish = false; + + // + // Count Bullish/Bearish Directions ... + int start = barIndex + 1; + int end = start + validationLength; + for (int i = start; i < end; i++) + { + // + // Reading Requirements ... + + // + // Read Indexed Bar ... + iBar.Clean(); + result = iBar.Init( + mSymbol, + mPeriod, + i // + ); + if (!result) + { + break; + } + + // + // Reading Values ... + hkUpper = GetHKBandUpper(i); + hkLower = GetHKBandLower(i); + result = NotEmptyZero(hkUpper) && + NotEmptyZero(hkLower); + if (!result) + { + return result; + } + + // + // Check Trend ... + + // + // Bullish ... + isBullish = iBar.low > hkLower; + if (isBullish) + { + bullishCount++; + } + + // + // Bearish ... + isBearish = iBar.high < hkUpper; + if (isBearish) + { + bearishCount++; + } + + // + iBar.Clean(); + + // + } + + // + // Validate Results ... + isBullish = + bullishCount >= validationLength; + isBearish = + bearishCount >= validationLength; + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + + // + // Setting Direction if Has Trend ... + if (result) + { + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; +} + +/** + * Check Specified Bar has HK Band Based Trend Switch or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to holds trend direction, if exists ... + * @param barIndex: int, Specified Bar Index ... + * @param validationLength: int, validation of trend ... + * + * @return ( bool ) + */ +bool IsHKBasedTrendSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + int validationLength = 5 // +) +{ + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 1); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + bool hasTrend = HasHKBasedTrend( + dir, + barIndex, + validationLength // + ); + bool isBullish = hasTrend && + IsXBullish(dir); + bool isBearish = hasTrend && + IsXBearish(dir); + + // + bool hasPTrend = HasHKBasedTrend( + dir, + barIndex + 1, + validationLength // + ); + bool isPBullish = hasPTrend && + IsXBullish(dir); + bool isPBearish = hasPTrend && + IsXBearish(dir); + + // + dir = X_DIRECTION_NONE; + + // + // Checking Result ... + isBullish = isBullish && !isPBullish; + isBearish = isBearish && !isPBearish; + + // + result = + (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup ... + + // + return result; +} + +/** + * Check if Price Over HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsOverHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandUpper(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check if Price Over HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsOverHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandLower(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check if Price Under HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsUnderHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandUpper(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check if Price Under HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsUnderHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandLower(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; +} + +/** + * Check Price Switched Over HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsSwitchedOverHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsOverHKBandUpper(priceType, barIndex); + bool isPBarPassed = !IsOverHKBandUpper(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; +} + +/** + * Check Price Switched Under HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsSwitchedUnderHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsUnderHKBandUpper(priceType, barIndex); + bool isPBarPassed = !IsUnderHKBandUpper(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; +} + +/** + * Check Price Switched Over HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsSwitchedOverHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsOverHKBandLower(priceType, barIndex); + bool isPBarPassed = !IsOverHKBandLower(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; +} + +/** + * Check Price Switched Under HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ +bool IsSwitchedUnderHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsUnderHKBandLower(priceType, barIndex); + bool isPBarPassed = !IsUnderHKBandLower(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastOverHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsOverHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastUnderHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsUnderHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastOverHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsOverHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastUnderHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsUnderHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastSwitchedOverHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedOverHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastSwitchedUnderHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedUnderHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastSwitchedOverHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedOverHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +/** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ +bool FindLastSwitchedUnderHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedUnderHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; +} + +// +// ZigZag Pivots With Liquidity ... + +/** + * Check ZigZag has Lower Low by Liquidity or Not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ +bool HasZigZagLowerLowByLiquidity( + int barIndex = 0, + bool forceBarValidation = false // +) +{ + // + bool result = false; + + // + // Normalize ... + XOHCL bar; + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsVale(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot selected[]; + count = ExtractPivots( + selected, + pivots, + X_PIVOT_TYPE_VALE // + ); + result = IsValidSize(count) && + count >= 3; + if (!result) + { + // + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; + } + + // + // Do Calculations ... + result = + // + // Check Pivot ... + selected[0].value < selected[1].value && + // + // Check Liquidity ... + selected[1].value > selected[2].value && + // + // Check Bar Place ... + (!forceBarValidation + ? true + : bar.open > selected[0].value && + bar.close > selected[0].value); + + // + // Cleanup ... + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; +} + +/** + * Check ZigZag has Higher High by Liquidity or Not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ +bool HasZigZagHigherHighByLiquidity( + int barIndex = 0, + bool forceBarValidation = false // +) +{ + // + bool result = false; + + // + // Normalize ... + XOHCL bar; + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsPeak(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot selected[]; + count = ExtractPivots( + selected, + pivots, + X_PIVOT_TYPE_PEAK // + ); + result = IsValidSize(count) && + count >= 3; + if (!result) + { + // + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; + } + + // + // Do Calculations ... + result = + // + // Check Pivot ... + selected[0].value > selected[1].value && + // + // Check Liquidity ... + selected[1].value < selected[2].value && + // + // Check Bar Place ... + (!forceBarValidation + ? true + : bar.open < selected[0].value && + bar.close < selected[0].value); + + // + // Cleanup ... + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; +} + +// +// Extractions ... + +/** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( int ) + */ +int ExtractPVPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + bool lookupPeaks = true; + bool lookupVales = true; + + // + XOHCL iBar; + XPivot iPivot; + bool has = false; + int idx = barIndex - 1; + int samePeaksCount = 0; + int sameValesCount = 0; + double tmpPeaksBuffer[]; + double tmpValesBuffer[]; + string symbol = GetSymbol(); + double iPValue = EMPTY_VALUE; + double iVValue = EMPTY_VALUE; + double pPValue = EMPTY_VALUE; + double pVValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + if (!has) + { + continue; + } + + // + // Detecting ... + + // + // Peak ... + if (lookupPeaks) + { + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_PEAK_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpPeaksBuffer // Buffer ... + ); + ArraySetAsSeries(tmpPeaksBuffer, true); + + // + // Reading Values ... + iPValue = tmpPeaksBuffer[0]; + pPValue = tmpPeaksBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iPValue)) + { + // + // Check New Peak ... + has = + !NotEmptyZero(pPValue) + ? true + : iPValue != pPValue; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + iPValue == iBar.high + ? X_PIVOT_TYPE_PEAK + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // Check Validation Length ... + has = + has && + (validationLength <= 0 + ? true + : samePeaksCount >= validationLength); + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iPValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_PV); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + samePeaksCount = 0; + } + else if (iPValue == pPValue) + { + samePeaksCount++; + } + } + } + + // + // Vale ... + if (lookupVales) + { + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_VALE_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpValesBuffer // Buffer ... + ); + ArraySetAsSeries(tmpValesBuffer, true); + + // + // Reading Values ... + iVValue = tmpValesBuffer[0]; + pVValue = tmpValesBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iVValue)) + { + // + // Check New Vale ... + has = + !NotEmptyZero(pVValue) + ? true + : iVValue != pVValue; + if (has) + { + // + // Calculate and Validate Type ... + // Vales Only Valid when Confirmed by Bar Low ... + iType = + iVValue == iBar.low + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // Check Validation Length ... + has = + has && + (validationLength <= 0 + ? true + : sameValesCount >= validationLength); + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iVValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_PV); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + sameValesCount = 0; + } + else if (iVValue == pVValue) + { + sameValesCount++; + } + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + return result; +} + +/** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ +int ExtractMAPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + double validCrossDiffMultiplier = 1, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + double fast[]; + double slow[]; + XPivot iPivot; + int count = 0; + bool has = false; + int idx = barIndex - 1; + datetime iPivotTime = NULL; + string symbol = GetSymbol(); + double iFValue = EMPTY_VALUE; + double pFValue = EMPTY_VALUE; + double iSValue = EMPTY_VALUE; + double pSValue = EMPTY_VALUE; + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + double iSelectedValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + XClean(fast); + XClean(slow); + iPivot.Clean(); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Reading Buffer ... + int fastCount = CopyMAFast(idx, 2, fast); + int slowCount = CopyMASlow(idx, 2, slow); + count = MathMin(fastCount, slowCount); + has = IsValidSize(count); + + // + // Reading Values ... + + // + iFValue = fast[0]; + pFValue = fast[1]; + + // + iSValue = slow[0]; + pSValue = slow[1]; + + // + // Validate Value ... + has = + HasMACross( + iDir, + idx, + validCrossDiffMultiplier // + ) && + NotEmptyZero(iFValue) && + NotEmptyZero(iSValue) && + NotEmptyZero(pFValue) && + NotEmptyZero(pSValue); + if (has) + { + // + // Check Direction Changed ... + isSwitchedToBullish = IsXBullish(iDir); + isSwitchedToBearish = IsXBearish(iDir); + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + iPivotTime = GetBarTime( + symbol, + period, + idx // + ); + + // + // Select Value based on Pivot Type ... + iSelectedValue = IsXPeak(iType) + ? MathMax(iFValue, iSValue) + : MathMin(iFValue, iSValue); + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iSelectedValue, + iPivotTime, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_MA_CROSS); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + iPivot.Clean(); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + iPivot.Clean(); + + // + return result; +} + +/** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ +int ExtractHKPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + double open[]; + XPivot iPivot; + int count = 0; + double close[]; + bool has = false; + int idx = barIndex - 1; + datetime iPivotTime = NULL; + string symbol = GetSymbol(); + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + double iSelectedValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + XClean(open); + XClean(close); + iPivot.Clean(); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Reading Buffer ... + int openCount = CopyHKOpen(idx, 2, open); + int closeCount = CopyHKClose(idx, 2, close); + count = MathMin(openCount, closeCount); + has = IsValidSize(count); + + // + // Validate Value ... + has = + HasHKSwitch( + iDir, + idx // + ) && + NotEmptyZero(open[0]) && + NotEmptyZero(open[1]) && + NotEmptyZero(close[0]) && + NotEmptyZero(close[1]); + if (has) + { + // + // Check Direction Changed ... + isSwitchedToBullish = IsXBullish(iDir); + isSwitchedToBearish = IsXBearish(iDir); + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_HK); + + // + iPivotTime = GetBarTime( + symbol, + period, + idx // + ); + + // + // Select Value based on Pivot Type ... + iSelectedValue = IsXPeak(iType) + ? MathMax(open[0], close[0]) + : MathMin(open[0], close[0]); + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iSelectedValue, + iPivotTime, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + XClean(open); + XClean(close); + iPivot.Clean(); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + XClean(open); + XClean(close); + iPivot.Clean(); + + // + return result; +} + +/** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ +int ExtractSARPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + XOHCL iBar; + XOHCL pBar; + XPivot iPivot; + bool has = false; + double tmpSarBuffer[]; + int idx = barIndex - 1; + string symbol = GetSymbol(); + double iValue = EMPTY_VALUE; + double pValue = EMPTY_VALUE; + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + has = + has && + iBar.GetPreviousBar(pBar); + if (!has) + { + continue; + } + + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_SAR_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpSarBuffer // Buffer ... + ); + ArraySetAsSeries(tmpSarBuffer, true); + + // + // Reading Values ... + iValue = tmpSarBuffer[0]; + pValue = tmpSarBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iValue)) + { + // + // Check Sar Direction Changed ... + isSwitchedToBullish = iValue < iBar.low && + pValue > pBar.high; + isSwitchedToBearish = iValue > iBar.high && + pValue < pBar.low; + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_SAR_SWITCH); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + return result; +} + +/** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ +int ExtractZigZagPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + XOHCL iBar; + XPivot iPivot; + bool has = false; + int idx = barIndex - 1; + double tmpZigZagBuffer[]; + double iValue = EMPTY_VALUE; + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + if (!has) + { + continue; + } + + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_ZIGZAG_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 1, // Number of Requirements ... + tmpZigZagBuffer // Buffer ... + ); + ArraySetAsSeries(tmpZigZagBuffer, true); + + // + // Read and Validate Value ... + iValue = tmpZigZagBuffer[0]; + has = NotEmptyZero(iValue); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Calculate and Validate Type ... + iType = + iValue == iBar.high + ? X_PIVOT_TYPE_PEAK + : iValue == iBar.low + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Calculate and Validate Dir ... + iDir = + IsXVale(iType) + ? X_DIRECTION_BULLISH + : IsXPeak(iType) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(iDir); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_ZIGZAG); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + return result; +} + +/** + * Extract Validated Zones ... + * + * @param zones: XBoxZone, collection reference to holds results ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFZones: int, required Number of Zones ... + * @param breakValidLength: int, Breake Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * @param shadowMultiplier: double a Shadow Multiplier for Validation ... + * @param validationStrength: double, Minimum Strngth Multiplier in Point to Validate ... + * @param validationLength: int, Validation Length of Zones ... + * @param maxAllowedLoopbackLength: int, max Allowed Loopback Length ... + * + * @return ( int ) + */ +int ExtractHKZones( + XBoxZone &zones[], + int barIndex = 0, + int requiredNumberOFZones = 50, + int breakValidLength = 3, + bool validateFakeBreakes = true, + double shadowMultiplier = 3, + double validationStrength = 1, + int validationLength = 21, + int maxAllowedLoopbackLength = 1500 // +) +{ + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(zones); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 7); + shadowMultiplier = NormalizeDouble(shadowMultiplier, 1); + validationStrength = NormalizeDouble(validationStrength, 1); + requiredNumberOFZones = NormalizeInt(requiredNumberOFZones, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 100); + + // + // Reading Values ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + double minAllowedStrength = (validationStrength * GetPoints(symbol)); + + // + int count = 0; + XBoxZone zone; + bool has = false; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + double up = EMPTY_VALUE; + double low = EMPTY_VALUE; + double open = EMPTY_VALUE; + double high = EMPTY_VALUE; + double down = EMPTY_VALUE; + double body = EMPTY_VALUE; + double close = EMPTY_VALUE; + double range = EMPTY_VALUE; + bool lowShadowPassed = false; + bool highShadowPassed = false; + double lowShadow = EMPTY_VALUE; + double highShadow = EMPTY_VALUE; + double startHKLow = EMPTY_VALUE; + double startHKOpen = EMPTY_VALUE; + double startHKHigh = EMPTY_VALUE; + double startHKClose = EMPTY_VALUE; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + int end = start + maxAllowedLoopbackLength; + for (int i = start; i < end; i++) + { + // + // Cleanup ... + zone.Clean(); + dir = X_DIRECTION_NONE; + + // + // Reading HK Buffesr ... + low = GetHKLow(i); + open = GetHKOpen(i); + high = GetHKHigh(i); + close = GetHKClose(i); + + // + // Initialized Start Bar ... + if (i == start) + { + // + startHKLow = low; + startHKOpen = open; + startHKHigh = high; + startHKClose = close; + } + + // + // Check Direction ... + isBullish = open < close; + isBearish = open > close; + dir = + (isBullish && !isBearish) + ? X_DIRECTION_BULLISH + : (isBearish && !isBullish) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(dir); + if (!has) + { + continue; + } + + // + // Calculate Requirements for Processing ... + up = isBullish + ? close + : open; + down = isBullish + ? open + : close; + body = MathAbs(up - down); + range = high - low; + highShadow = high - up; + lowShadow = down - low; + + // + // Detecting Shadows ... + + // + // Low Shadow ... + lowShadowPassed = lowShadow >= (shadowMultiplier * highShadow); + + // + // High Shadow ... + highShadowPassed = highShadow >= (shadowMultiplier * lowShadow); + + // + has = (lowShadowPassed && !highShadowPassed) || + (highShadowPassed && !lowShadowPassed); + if (!has) + { + continue; + } + + // + // Filling Zone ... + + // + zone.symbol = symbol; + zone.period = period; + zone.from = GetBarTime( + zone.symbol, + zone.period, + i // + ); + zone.dir = lowShadowPassed + ? X_DIRECTION_BULLISH + : highShadowPassed + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + zone.upper = + IsXBullish(zone.dir) + ? down + : IsXBearish(zone.dir) + ? high + : EMPTY_VALUE; + + // + zone.lower = + IsXBullish(zone.dir) + ? low + : IsXBearish(zone.dir) + ? up + : EMPTY_VALUE; + + // + zone.to = TimeCurrent(); + zone.type = ToXString(XFIMA_PIVOT_HK) + "_" + (IsXBullish(zone.dir) ? "Support" : IsXBearish(zone.dir) ? "Resistance" + : ""); + + // + // Validate ... + has = + zone.IsValid() && + HasDirection(zone.dir) && + NotEmptyZero(zone.upper) && + NotEmptyZero(zone.lower) && + (zone.IsBullish() + ? startHKLow > zone.upper + : startHKHigh < zone.lower) && + (zone.upper - zone.lower) >= minAllowedStrength && + ValidateHKZone(zone, validationLength, breakValidLength, validateFakeBreakes); + if (has) + { + // + AddIfNotExists( + zone, + zones // + ); + } + + // + // Cleanup Resources ... + zone.Clean(); + + // + // Validating ... + result = ArraySize(zones); + has = IsValidSize(result) && + result >= requiredNumberOFZones; + if (has) + { + break; + } + } + + // + // Cleanup Resources ... + zone.Clean(); + + // + return result; +} + +// +// Values Retrievers ... + +/** + * Filling Specified Bar index Boundary Values ... + * + * @param dest: double, reference collection to hold boundary Values ... + * @param barIndex: int, Specified Bar's Index ... + * @param containsFastSlow: bool, Contains XMA Fast / Slow ... + * @param containsMABand: bool, Contains XMA Boundary Upper / Lower ... + * @param containsHKBound: bool, Contains XHK Boundary Upper / Lower ... + * @param containsPBBand: bool, Contains XPB Boundary Upper / Lower ... + * @param containsFiboLevels: nool, Contains XFIBO Levels ... + * + * @return ( int ) + */ +int FillBoundaryValues( + double &dest[], + int barIndex = 0, + bool containsFastSlow = true, + bool containsMABand = true, + bool containsHKBound = true, + bool containsPBBand = true, + bool containsFiboLevels = false // +) +{ + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // Read and Validate Values ... + + // + double fast = GetMAFast(barIndex); + double slow = GetMASlow(barIndex); + + // + double maBandUpper = GetMABandUpper(barIndex); + double maBandLower = GetMABandLower(barIndex); + + // + double pbBandUpper = GetPBBandUpper(barIndex); + double pbBandLower = GetPBBandLower(barIndex); + + // + double hkBandUpper = GetHKBandUpper(barIndex); + double hkBandLower = GetHKBandLower(barIndex); + + // + double fiboUpper = GetFiboUpper(barIndex); + double fiboLower = GetFiboLower(barIndex); + double fiboMiddle = GetFiboMiddle(barIndex); + + // + has = + NotEmptyZero(fast) && + NotEmptyZero(slow) && + NotEmptyZero(fiboLower) && + NotEmptyZero(fiboUpper) && + NotEmptyZero(fiboMiddle) && + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower); + if (!has) + { + return result; + } + + // + // Fill Dest ... + + // + // XMA Fast / Slow ... + if (containsFastSlow) + { + // + Add(fast, dest); + Add(slow, dest); + } + + // + // XMA Bound ... + if (containsMABand) + { + // + Add(maBandUpper, dest); + Add(maBandLower, dest); + } + + // + // XHK Band ... + if (containsHKBound) + { + // + Add(hkBandUpper, dest); + Add(hkBandLower, dest); + } + + // + // XPB Band ... + if (containsPBBand) + { + // + Add(pbBandUpper, dest); + Add(pbBandLower, dest); + } + + // + // XFIBO Zones ... + if (containsFiboLevels) + { + // + Add(fiboLower, dest); + Add(fiboUpper, dest); + Add(fiboMiddle, dest); + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Retrieve Fast, Slow, MA Band Upper/Lower, HK Band Upper/Lower and PB Band Upper/Lower Min/Max ... + * + * @param min: double, minimum value ... + * @param max: double, maximum value ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ +bool GetBoundaryValues( + double &min, + double &max, + int barIndex = 0, + bool containsFastSlow = true, + bool containsMABand = true, + bool containsHKBound = true, + bool containsPBBand = true, + bool containsFiboLevels = false // +) +{ + // + bool result = false; + + // + // Prepare ... + min = EMPTY_VALUE; + max = EMPTY_VALUE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double fast = GetMAFast(barIndex); + double slow = GetMASlow(barIndex); + + // + double maBandUpper = GetMABandUpper(barIndex); + double maBandLower = GetMABandLower(barIndex); + + // + double pbBandUpper = GetPBBandUpper(barIndex); + double pbBandLower = GetPBBandLower(barIndex); + + // + double hkBandUpper = GetHKBandUpper(barIndex); + double hkBandLower = GetHKBandLower(barIndex); + + // + double fiboUpper = GetFiboUpper(barIndex); + double fiboLower = GetFiboLower(barIndex); + double fiboMiddle = GetFiboMiddle(barIndex); + + // + result = + NotEmptyZero(fast) && + NotEmptyZero(slow) && + NotEmptyZero(fiboLower) && + NotEmptyZero(fiboUpper) && + NotEmptyZero(fiboMiddle) && + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower); + if (!result) + { + return result; + } + + // + double values[]; + + // + if (containsFastSlow) + { + // + Add(fast, values); + Add(slow, values); + } + + // + if (containsMABand) + { + // + Add(maBandUpper, values); + Add(maBandLower, values); + } + + // + if (containsHKBound) + { + // + Add(hkBandUpper, values); + Add(hkBandLower, values); + } + + // + if (containsPBBand) + { + // + Add(pbBandUpper, values); + Add(pbBandLower, values); + } + + // + if (containsFiboLevels) + { + // + Add(fiboLower, values); + Add(fiboUpper, values); + Add(fiboMiddle, values); + } + + // + result = HasChild(values); + if (!result) + { + return result; + } + + // + min = GetMin(values); + max = GetMax(values); + + // + result = + NotEmptyZero(min) && + NotEmptyZero(max) && + min < max; + + // + return result; +} diff --git a/Documents/BKP/tmp.poi.drawer.codes.mq5 b/Documents/BKP/tmp.poi.drawer.codes.mq5 index b6be4fe6..520477d6 100644 --- a/Documents/BKP/tmp.poi.drawer.codes.mq5 +++ b/Documents/BKP/tmp.poi.drawer.codes.mq5 @@ -334,3 +334,46 @@ // return result; } + + // + // Testing Draws ... + + // + XFIMAMarketStructure pivots[]; + + // + XPivot pvPivots[]; + XPivot hkPivots[]; + XPivot maPivots[]; + XPivot zgPivots[]; + XPivot sarPivots[]; + + // + poiDetector.CollectZGPivots(zgPivots); + poiDetector.CollectMAPivots(maPivots); + poiDetector.CollectHKPivots(hkPivots); + poiDetector.CollectPVPivots(pvPivots); + poiDetector.CollectSARPivots(sarPivots); + + // + // Merging All Pivots ... + Copy(pvPivots, pivots, false); + Copy(zgPivots, pivots, false); + Copy(maPivots, pivots, false); + Copy(hkPivots, pivots, false); + Copy(sarPivots, pivots, false); + + // + if (HasChild(pivots)) + { + poiDrawer.DrawPivots(pivots, iDrawConfig); + } + + // + // Cleanup ... + XClean(pivots); + XClean(pvPivots); + XClean(hkPivots); + XClean(maPivots); + XClean(zgPivots); + XClean(sarPivots); diff --git a/Documents/BKP/tmp.poi.mq5 b/Documents/BKP/tmp.poi.mq5 index db780f87..303dab0c 100644 --- a/Documents/BKP/tmp.poi.mq5 +++ b/Documents/BKP/tmp.poi.mq5 @@ -5384,11 +5384,8 @@ class XCSession : public XCFromToZone // }; - // - - template bool ToBox( T *&source[], @@ -6307,7 +6304,6 @@ void SpecifiedUpdateTo( } } - /** * Check a Box is Used or not ... * @@ -6682,7 +6678,6 @@ bool IsBoxPlaceValidForBar( return result; } - /** * Check Source Box is Below Dest ... * @@ -7056,3 +7051,132 @@ bool HasInsideBox( // return result; } + +///////////////////////////////////////////// + +// +// Analyse Bar Patterns ... +if (result && config.analyseBarPatterns) +{ + // + // Try to Detect Bars Analysis ... + int fromIndex = -1; + if (!IsXValid(fromTime)) + { + fromIndex = barIndex + config.loopback; + } + else + { + fromIndex = GetBarIndex( + symbol, + period, + fromTime // + ); + } + result = IsValidIndex(fromIndex); + if (result) + { + // + fromIndex = MathMin(fromIndex, barIndex + config.requiredPivots); + + // + for (int i = barIndex; i < fromIndex; i++) + { + // + tmpBar.Clean(); + tmpBarAnalysis.Clean(); + result = structure.bar.BarAt(i, tmpBar); + result = result && + AnalyseBarPatterns( + tmpBar, + tmpBarAnalysis, + config.barsAnalysisConfig // + ); + if (!result) + { + break; + } + + // + AddRef( + tmpBarAnalysis, + structure.barsAnalysis // + ); + } + } +} + +//////////////////////////////////////////////// + +/** + * Draw Specified Market Structure Based on Given Configs ... + * + * @param structure: XFIMAMarketStructure, reference to Provide Specifid Market Structure ... + * @param config: XFIMAMarketStructureDrawerConfig, reference to Provide Drawing Configurations ... + */ +void DrawMarketStructure( + XFIMAMarketStructure &structure, + XFIMAMarketStructureDrawerConfig &config // +) +{ + // + // Validate ... + bool has = structure.IsValid(); + if (!has) + { + return; + } + + // + // PV Analysis ... + if (config.drawPVAnalysis) + { + // + has = structure.pvAnalysis.IsValid(); + if (has) + { + // + DrawPivotAnalysis( + structure.pvAnalysis, + config.pivotAnalysisDrawConfig // + ); + } + } + + // + // ZG Analysis ... + if (config.drawZGAnalysis) + { + // + has = structure.zgAnalysis.IsValid(); + if (has) + { + // + DrawPivotAnalysis( + structure.zgAnalysis, + config.pivotAnalysisDrawConfig // + ); + } + } + + // + // Bars Analysis ... + if (config.drawBarsAnalysis) + { + // + int count = ArraySize(structure.barsAnalysis); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + DrawPatternAnalysis( + structure.barsAnalysis[i], + config.barAnalysisDrawConfig // + ); + } + } + } +} diff --git a/Documents/BKP/x-saherelm.x-market.pattern.class.mq5 b/Documents/BKP/x-saherelm.x-market.pattern.class.mq5 new file mode 100644 index 00000000..560cb436 --- /dev/null +++ b/Documents/BKP/x-saherelm.x-market.pattern.class.mq5 @@ -0,0 +1,4780 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XCMarketPatternDetector +// Description: provides all Alerts requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Libraries/x-saherelm.x-pivot.analysis.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCMarketPatternDetector : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + XBoxZone zones[]; + XBoxZone majorSupport; + XBoxZone minorSupport; + XBoxZone majorResistance; + XBoxZone minorResistance; + + // + // Constructor ... + XCMarketPatternDetector() + { + barAnalyser = new XCBarAnalyser(); + } + + // + // Deconstructor ... + ~XCMarketPatternDetector() + { + // + delete barAnalyser; + ZeroMemory(barAnalyser); + } + + // + // Actions / Helpers ... + + // + double CalculateQuarter() + { + // + double result = -1; + + // + // Validate ... + bool has = majorSupport.IsValid() && + majorResistance.IsValid(); + if (!has) + { + return result; + } + + // + result = majorSupport.upper + ((majorResistance.lower - majorSupport.upper) / 2); + + // + return result; + } + + // + // Analysers ... + + /** + * Check for Price Touch Support Level ... + * + * @param bar: XOHCL, Specified Bar ... + * @param supportBar: XOHCL, reference to holds Zone Bar ... + * @param supportBox: XBoxZone, reference to holds Zone Box ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ... + * + * @return ( bool ) + */ + bool IsSupportTouched( + XOHCL &bar, + XOHCL &supportBar, + XBoxZone &supportBox, + int validationLength = 21, + int maxAllowedLoopback = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + supportBar.Clean(); + supportBox.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Support Exists ... + result = HasSupport( + bar, + supportBar, + validationLength, + maxAllowedLoopback // + ); + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + // Extract Support Box ... + result = ToSupportBox( + supportBar, + supportBox // + ); + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = + result && + bar.GetPreviousBar(pBar); + + // + // Chekc Price of Bar ... + result = + result && + pBar.low < supportBox.upper; + + // + // Cleanup Resources ... + if (!result) + { + // + supportBar.Clean(); + supportBox.Clean(); + } + pBar.Clean(); + + // + return result; + } + + /** + * Check for Price Touch Resistance Level ... + * + * @param bar: XOHCL, Specified Bar ... + * @param supportBar: XOHCL, reference to holds Zone Bar ... + * @param supportBox: XBoxZone, reference to holds Zone Box ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ... + * + * @return ( bool ) + */ + bool IsResistanceTouched( + XOHCL &bar, + XOHCL &resistanceBar, + XBoxZone &resistanceBox, + int validationLength = 21, + int maxAllowedLoopback = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + resistanceBar.Clean(); + resistanceBox.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Resistance Exists ... + result = HasResistance( + bar, + resistanceBar, + validationLength, + maxAllowedLoopback // + ); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + // Extract Resistance Box ... + result = ToResistanceBox( + resistanceBar, + resistanceBox // + ); + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = + result && + bar.GetPreviousBar(pBar); + + // + // Chekc Price of Bar ... + result = + result && + pBar.high > resistanceBox.lower; + + // + // Cleanup Resources ... + if (!result) + { + // + resistanceBar.Clean(); + resistanceBox.Clean(); + } + pBar.Clean(); + + // + return result; + } + + // + // Detectors ... + + /** + * Check Specified Bar is Peak or Vale ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param validationLength: int, Validation Length ... + * + * @return ( bool ) + */ + bool IsPV( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int validationLength = 7, + ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, // + ENUM_X_PRICE valePriceType = X_PRICE_LOW // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 2); + + // + // Validate ... + result = bar.IsValid() && + IsXValid(peakPriceType) && + IsXValid(valePriceType); + if (!result) + { + return result; + } + + // + int valeIndex = -1; + double vale = bar.FindLowest( + valeIndex, + validationLength, + valePriceType // + ); + double barVale = bar.GetPrice(valePriceType); + bool isVale = + NotEmptyZero(vale) && + NotEmptyZero(barVale) && + IsValidIndex(valeIndex) && + vale >= barVale; + + // + int peakIndex = -1; + double peak = bar.FindHighest( + peakIndex, + validationLength, + peakPriceType // + ); + double barPeak = bar.GetPrice(peakPriceType); + bool isPeak = + NotEmptyZero(peak) && + NotEmptyZero(barPeak) && + IsValidIndex(peakIndex) && + peak <= barPeak; + + // + result = (isVale && !isPeak) || + (isPeak && !isVale); + if (result) + { + // + dir = + isVale + ? X_DIRECTION_BULLISH + : isPeak + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + + // + return result; + } + + /** + * Check Specified Bar is Momentum Bar or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param requiredBars: int, bar range for approve Momentum ... + * @param approvedMultiplier: double, a Multipler for approve Momentum ... + * + * @return ( bool ) + */ + bool IsMomentumBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int requiredBars = 3, + double approvedMultiplier = 2 // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalizing ... + requiredBars = NormalizeInt(requiredBars, 3, 10); + approvedMultiplier = NormalizeDouble(approvedMultiplier, 2, 5); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Calculate Requirements ... + + // + XOHCL iBar; + bool has = false; + double rangeBody = 0; + int start = bar.Index() + 1; + int end = start + requiredBars; + for (int i = start; i < end; i++) + { + // + // Initialized Bar ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + + // + // Summarize Body Sizes ... + if (has) + { + rangeBody += iBar.GetBody(); + } + + // + iBar.Clean(); + } + + // + // Calculate Body Approvement ... + result = bar.GetBody() >= (approvedMultiplier * rangeBody); + if (!result) + { + return result; + } + + // + // Check Direction ... + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Engulfed Bar or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * + * @return ( bool ) + */ + bool IsEngulfedBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Calculate Requirements ... + + // + XOHCL iBar; + result = bar.GetPreviousBar(iBar); + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + // Check Prev Bar Must Inside Bar ... + result = bar.GetUp() > iBar.GetUp() && + bar.GetDown() < iBar.GetDown(); + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + // Check Directions ... + bool isBullish = + iBar.IsBearish() && + bar.IsBullish(); + bool isBearish = + iBar.IsBullish() && + bar.IsBearish(); + result = isBullish || isBearish; + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is True Gapped Bar or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param approvedPointMultiplier: double, Gap Validation Multiplier in Point ... + * + * @return ( bool ) + */ + bool IsTrueGapedBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + double approvedPointMultiplier = 1 // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalizing ... + approvedPointMultiplier = NormalizeDouble(approvedPointMultiplier, 1, 100); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Calculate Requirements ... + + // + XOHCL iBar; + result = bar.GetPreviousBar(iBar); + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + // Check Directions ... + bool isBullish = + iBar.IsBullish() && + bar.IsBullish(); + bool isBearish = + iBar.IsBearish() && + bar.IsBearish(); + result = isBullish || isBearish; + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + double point = GetPoints(bar.symbol); + double approvedGapSize = approvedPointMultiplier * point; + + // + // Check Gap Exists ... + result = + isBullish + ? bar.low > iBar.high + : iBar.low > bar.high; + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + // Validate Gap Size ... + double gapSize = isBullish + ? bar.low - iBar.high + : iBar.low - bar.high; + result = gapSize >= approvedGapSize; + if (!result) + { + // + iBar.Clean(); + return result; + } + + // + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Pinned Bar or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param shadowApprovedMultiplier: double, Shadow Size Approve Multiplier ... + * @param minimumPinBarRangeMultiplier: doubble, Range Size Approve Multiplier in Point ... + * @param forceDirection: bool, Apply Force Bar Type ... + * + * @return ( bool ) + */ + bool IsPinnedBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + double shadowApprovedMultiplier = 3, + double minimumPinBarRangeMultiplier = 4, + bool forceDirection = false // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Normalizing ... + shadowApprovedMultiplier = NormalizeDouble(shadowApprovedMultiplier, 2, 5); + minimumPinBarRangeMultiplier = NormalizeDouble(minimumPinBarRangeMultiplier, 2, 100); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Calculate Requirements ... + double body = bar.GetBody(); + double lowShadow = bar.GetLowShadow(); + double highShadow = bar.GetHighShadow(); + + // + // Check Directions ... + bool isBullish = + lowShadow > body && + lowShadow > highShadow && + lowShadow >= (body * shadowApprovedMultiplier); + bool isBearish = + highShadow > body && + highShadow > lowShadow && + highShadow > (body * shadowApprovedMultiplier); + result = isBullish || isBearish; + if (!result) + { + return result; + } + + // + // Checking Force Bar Type ... + if (forceDirection) + { + // + result = + isBullish + ? bar.IsBullish() + : bar.IsBearish(); + } + if (!result) + { + return result; + } + + // + // Check Range Validation ... + double point = GetPoints(bar.symbol); + double approvedRange = minimumPinBarRangeMultiplier * point; + result = bar.GetRange() >= approvedRange; + if (!result) + { + return result; + } + + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + + // + return result; + } + + /** + * Check Specified Bar has Star Pattern or not ... + * Morning Star => Bullish + * Evening Star => Bearish + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * + * @return ( bool ) + */ + bool IsStarPattern( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Get Requirements ... + XOHCL pBar, p2Bar; + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Check Directions ... + bool isBullish = + bar.IsBullish() && + p2Bar.IsBearish(); + bool isBearish = + bar.IsBearish() && + p2Bar.IsBullish(); + result = isBullish || isBearish; + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Checking Gap Exists Between Bars ... + result = + isBullish + ? p2Bar.GetDown() > pBar.GetUp() && + pBar.GetUp() < bar.GetDown() + : p2Bar.GetUp() < pBar.GetDown() && + pBar.GetDown() > bar.GetUp(); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Check Bar Close Validation ... + double barClosedApprovedPrice = p2Bar.GetDown() + ((p2Bar.GetUp() - p2Bar.GetDown()) / 2); + result = + isBullish + ? bar.close > barClosedApprovedPrice + : bar.close < barClosedApprovedPrice; + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Validating PBar Body and Shadow ... + double body = pBar.GetBody(); + double lowShadow = pBar.GetLowShadow(); + double highShadow = pBar.GetHighShadow(); + result = + body < bar.GetBody() && + body < p2Bar.GetBody() && + (isBullish + ? lowShadow > body && + lowShadow > highShadow + : highShadow > body && + highShadow > lowShadow); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar has Pirecing Pattern or not ... + * Piercing => Bullish + * Dark Cloud Cover => Bearish + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * + * @return ( bool ) + */ + bool IsPiercingPattern( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Check Directions ... + bool isBullish = + bar.IsBullish() && + pBar.IsBearish(); + bool isBearish = + bar.IsBearish() && + pBar.IsBullish(); + result = isBullish || isBearish; + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Check Bar Close ... + double barCloseApprovedPrice = pBar.GetDown() + ((pBar.GetUp() - pBar.GetDown()) / 2); + result = + isBullish + ? bar.close > barCloseApprovedPrice + : bar.close < barCloseApprovedPrice; + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + pBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar has Rising Pattern or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * + * @return ( bool ) + */ + bool IsRisingPattern( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Reading Required Bars ... + XOHCL iBar; + XOHCL bars[]; + bool has = false; + int start = bar.Index(); + int end = start + 5; + for (int i = start; i < end; i++) + { + // + // Initialized Bar ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (has) + { + // + AddRef( + iBar, + bars // + ); + } + + // + iBar.Clean(); + } + result = ArraySize(bars) == 5; + if (!result) + { + // + iBar.Clean(); + SpecifiedClean(bars); + + // + return result; + } + + // + // Check Directions ... + bool isBullish = + bars[0].IsBullish() && + bars[4].IsBullish() && + bars[1].IsBearish() && + bars[2].IsBearish() && + bars[3].IsBearish(); + bool isBearish = + bars[0].IsBearish() && + bars[4].IsBearish() && + bars[1].IsBullish() && + bars[2].IsBullish() && + bars[3].IsBullish(); + result = isBullish || isBearish; + if (!result) + { + // + iBar.Clean(); + SpecifiedClean(bars); + + // + return result; + } + + // + // Check Range Validation ... + double upper = bars[4].GetUp(); + double lower = bars[4].GetDown(); + + // + double max = MathMax(bars[1].GetUp(), bars[2].GetUp()); + max = MathMax(max, bars[3].GetUp()); + + // + double min = MathMin(bars[1].GetDown(), bars[2].GetDown()); + min = MathMin(min, bars[3].GetDown()); + + // + result = + max < upper && + min > lower && + (isBullish + ? bars[0].close > bars[4].GetUp() + : bars[0].close < bars[4].GetDown()); + if (!result) + { + // + iBar.Clean(); + SpecifiedClean(bars); + + // + return result; + } + + // + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + iBar.Clean(); + SpecifiedClean(bars); + + // + return result; + } + + /** + * Check Specified Bar has Flag Pattern or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param swingBar: XOHCL, Detected Swing Bar ... + * @param minimumPullbackBars: int, Minimum Shoulders of Swing Bar ... + * + * @return ( bool ) + */ + bool IsFlagPattern( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XOHCL &swingBar, + int minimumPullbackBars = 3 // + ) + { + // + bool result = false; + + // + // Prepare ... + swingBar.Clean(); + CleanDirection(dir); + + // + // Normalizing ... + minimumPullbackBars = NormalizeInt(minimumPullbackBars, 3, 10); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Reading Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Check Directions ... + bool isBullish = + bar.IsBullish() && + bar.close > pBar.GetUp(); + bool isBearish = + bar.IsBearish() && + bar.close < pBar.GetDown(); + result = isBullish || isBearish; + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Detect Swing Bar ... + ENUM_X_SWING_TYPE swingType = + isBullish + ? X_SWING_HIGH + : X_SWING_LOW; + result = + result && + IsXValid(swingType) && + bar.FindNextSwingBar( + swingType, + swingBar, + minimumPullbackBars // + ) && + (isBullish + ? swingBar.IsBullish() && + swingBar.high > pBar.high + : swingBar.IsBearish() && + swingBar.low < pBar.low); + if (!result) + { + // + pBar.Clean(); + swingBar.Clean(); + + // + return result; + } + + // + dir = bar.GetDirection(); + + // + // Get Result ... + result = HasDirection(dir); + + // + // Cleanup Resources ... + pBar.Clean(); + if (!result) + { + swingBar.Clean(); + } + + // + return result; + } + + /** + * Check Specified Bar has SignalKey Bar Pattern or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param shadowApprovedMultiplier: double, Shadow Size Approve Multiplier ... + * @param minimumPinBarRangeMultiplier: doubble, Range Size Approve Multiplier in Point ... + * @param forceDirection: bool, Apply Force Bar Type ... + * + * @return ( bool ) + */ + bool IsSignalKeyBarPattern( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + double shadowApprovedMultiplier = 3, + double minimumPinBarRangeMultiplier = 4, + bool forceDirection = false // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Get Requirements ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Chck Previous Bar must Pinned ... + result = IsPinnedBar( + pBar, + dir, + shadowApprovedMultiplier, + minimumPinBarRangeMultiplier, + forceDirection // + ); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Check Direction ... + bool isBullish = + bar.IsBullish() && + IsSpecifiedBullish(dir) && + bar.close > pBar.high; + bool isBearish = + bar.IsBearish() && + IsSpecifiedBearish(dir) && + bar.close < pBar.low; + result = isBullish || isBearish; + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + dir = bar.GetDirection(); + + // + result = HasDirection(dir); + + // + // Cleanup Resources ... + pBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar has Pullback Bar Pattern or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param zone: XBoxZone, refrence to hold detected zone ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param pullbackLength: int, min required indirectional bars to confirm pullback ... + * @param forceBreak: bool, force pullback bar breaks peak or vale of Zone ... + * + * @return ( bool ) + */ + bool IsPullbackPattern( + XOHCL &bar, + XBoxZone &zone, + ENUM_X_DIRECTION &dir, + int pullbackLength = 2, + bool forceBreak = false // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + CleanDirection(dir); + + // + // Normalize ... + pullbackLength = NormalizeInt(pullbackLength, 2); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // First Bar Direction ... + dir = bar.GetDirection(); + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + // Loop through Pullback Length ... + XOHCL iBar; + datetime from = NULL; + double max = EMPTY_VALUE; + double min = EMPTY_VALUE; + int start = bar.Index() + 1; + int end = start + pullbackLength; + for (int i = start; i < end; i++) + { + // + // Initialize Indexed Bar ... + iBar.Clean(); + result = bar.BarAt(i, iBar) && + iBar.GetDirection() == Opposit(dir); + if (!result) + { + break; + } + + // + // Calculate Max and Min ... + max = + !NotEmptyZero(max) + ? iBar.high + : MathMax(max, iBar.high); + min = + !NotEmptyZero(min) + ? iBar.low + : MathMin(min, iBar.low); + from = iBar.time; + } + + // + // Apply Force Break ... + if (result && + forceBreak) + { + // + result = + result && + NotEmptyZero(min) && + NotEmptyZero(max) && + (IsXBullish(dir) + ? bar.close > max + : bar.close < min); + } + + // + // Prepare Zone ... + if (result) + { + // + ToBox( + bar, + zone, + dir, + ToXString(X_BAR_PATTERN_PULLBACK) // + ); + zone.upper = max; + zone.lower = min; + zone.from = from; + zone.at = bar.time; + zone.to = bar.time; + + // + result = zone.IsValid(); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + + /** + * Check Market Has Consolidation Pattern or not ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param zone: XBoxZone, refrence to hold detected zone ... + * @param dir: ENUM_X_DIRECTION, reference to holds Detected Order Flow Direction ... + * @param validationLength: int, Validation Length ... + * @param breakPriceType: ENUM_X_PRICE, Specified Price Type to Breake Consolidation ... + * @param upperPriceType: ENUM_X_PRICE, Specified Price Type to Detected Upper of Consolidation ... + * @param lowerPriceType: ENUM_X_PRICE, Specified Price Type to Detected Lower of Consolidation ... + * + * @return ( bool ) + */ + bool IsConsolidationPattern( + XOHCL &bar, + XBoxZone &zone, + ENUM_X_DIRECTION &dir, + int validationLength = 5, + ENUM_X_PRICE breakPriceType = X_PRICE_CLOSE, + ENUM_X_PRICE upperPriceType = X_PRICE_HIGH, + ENUM_X_PRICE lowerPriceType = X_PRICE_LOW // + ) + { + // + // Descriptions: + // =============== + // Consolidation Zones Happens by Highest High and Lowest Low + // of Specified Range which Breakes From one Side ... + // + + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + CleanDirection(dir); + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 3); + + // + // Validate ... + result = bar.IsValid() && + IsXValid(lowerPriceType) && + IsXValid(upperPriceType) && + IsXValid(breakPriceType); + if (!result) + { + return result; + } + + // + // Define Requirements ... + XOHCL iBar; + bool has = false; + datetime to = NULL; + datetime from = NULL; + double iLow = EMPTY_VALUE; + bool hasLowShadow = false; + double lower = EMPTY_VALUE; + double upper = EMPTY_VALUE; + double iHigh = EMPTY_VALUE; + bool hasHighShadow = false; + double iPrice = EMPTY_VALUE; + bool isLowerBreaked = false; + bool isUpperBreaked = false; + + // + // Loop Through Bars ... + int barIndex = bar.Index(); + int idx = barIndex; + bool canLookup = IsValidIndex(idx); + while (canLookup) + { + // + // Initialize Indexed Bar ... + idx++; + iBar.Clean(); + result = bar.BarAt(idx, iBar); + if (!result) + { + break; + } + + // + // Update Time ... + if (idx == barIndex + 1) + { + to = iBar.time; + } + + // + // Extract Low and High Price ... + iLow = iBar.GetPrice(lowerPriceType); + iHigh = iBar.GetPrice(upperPriceType); + result = NotEmptyZero(iLow) && + NotEmptyZero(iHigh); + if (!result) + { + break; + } + + // + // Check Bar Has Low/High Shadow ... + hasLowShadow = iBar.GetLowShadow() > iBar.GetHighShadow(); + hasHighShadow = iBar.GetHighShadow() > iBar.GetLowShadow(); + + // + // Update Range Lower and Upper based on Shadows ... + + // + // Lower ... + if (hasLowShadow) + { + // + // Check Can Update ... + has = + !NotEmptyZero(lower) + ? true + : iLow < lower; + if (has) + { + lower = iLow; + } + } + + // + // Upper ... + if (hasHighShadow) + { + // + // Check Can Update ... + has = + !NotEmptyZero(upper) + ? true + : iHigh > upper; + if (has) + { + upper = iHigh; + } + } + + // + // Check Price Breakes ... + iPrice = iBar.GetPrice(breakPriceType); + result = NotEmptyZero(iPrice); + if (!result) + { + break; + } + + // + // Check Upper/Lower breakes ... + isLowerBreaked = iPrice < lower; + isUpperBreaked = iPrice > upper; + + // + canLookup = (!isLowerBreaked && !isUpperBreaked); + if (!canLookup) + { + break; + } + + // + from = iBar.time; + } + + // + // Validate Calculations ... + result = + // + IsXValid(to) && + IsXValid(from) && + from < to && + // + NotEmptyZero(lower) && + NotEmptyZero(upper) && + upper > lower + // + ; + + // + // Validate To Edge Breakes ... + if (result) + { + // + iPrice = bar.GetPrice(breakPriceType); + result = NotEmptyZero(iPrice); + + // + // Validate To Edge Breakes ... + if (result) + { + // + isUpperBreaked = iPrice > upper; + isLowerBreaked = iPrice < lower; + + // + // Validate To Break ... + result = isUpperBreaked || isLowerBreaked; + } + + // + // Prepare Direction ... + if (result) + { + // + dir = + isUpperBreaked + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Validate Direction ... + result = HasDirection(dir); + } + + // + // Prepare Zone ... + if (result) + { + // + zone.to = to; + zone.dir = dir; + zone.from = from; + zone.at = bar.time; + zone.upper = upper; + zone.lower = lower; + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION); + + // + // Validate Zone ... + result = zone.IsValid(); + + // + // Validate Zone Length ... + if (result) + { + result = zone.FromIndex() - zone.ToIndex() >= validationLength; + } + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + + /** + * Detect Order Flow ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param dir: ENUM_X_DIRECTION, reference to holds Detected Order Flow Direction ... + * @param orderFlow: XBoxZone, collection reference to holds Detected Order Flow ... + * @param orderFlowValidation: int, number of sequential Zones for Validate Order Flow ... + * @param containsOBs: bool, Specified to Use Order Blocks in Order Flow Detection ... + * @param containsFVGs: bool, Specified to Use Fair Value Gaps in Order Flow Detection ... + * @param containsSupportResistances: bool, Specified to Use Support and Resistances in Order Flow Detection ... + * @param zonesLoopback: int, Zone Detection Loopback ... + * @param zonesValidationLength: int, Zone Validation Length ... + * @param loopback: int, Max Allowed Loopback Bars for Collecting ... + * + * @return ( bool ) + */ + bool HasOrderFlow( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &orderFlow[], + int orderFlowValidation = 2, + bool containsOBs = false, + bool containsFVGs = true, + bool containsSupportResistances = false, + int zonesLoopback = 5, + int zonesValidationLength = 21, + int loopback = 100 // + ) + { + // + bool result = false; + + // + // Prepare ... + XClean(orderFlow); + CleanDirection(dir); + int maxRequiredZone = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + orderFlowValidation = NormalizeInt(orderFlowValidation, 1); + zonesValidationLength = NormalizeInt(zonesValidationLength, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Collectiong Zones ... + XBoxZone tmp; + XBoxZone tmps[]; + XBoxZone _zones[]; + XBoxZone bullishZones[]; + XBoxZone bearishZones[]; + int bullishZonesCount = 0; + int bearishZonesCount = 0; + + // + // Order Blocks ... + if (containsOBs) + { + // + XClean(tmps); + CollectOBs(bar, tmps, zonesLoopback, maxRequiredZone, loopback); + FillNotExists(_zones, tmps); + } + + // + // Fair Value Gaps ... + if (containsFVGs) + { + // + XClean(tmps); + CollectFVGs(bar, tmps, zonesLoopback, maxRequiredZone, loopback); + FillNotExists(_zones, tmps); + } + + // + // Support and Resistances ... + if (containsSupportResistances) + { + // + XClean(tmps); + CollectZones(bar, tmps, zonesLoopback, maxRequiredZone, loopback); + FillNotExists(_zones, tmps); + } + + // + // Validate Zones ... + result = HasChild(_zones); + + // + // Extract Only Validated Zones ... + if (result) + { + // + ValidateBoxes( + _zones, + bar.Index() // + ); + + // + result = HasChild(_zones); + } + + // + // Separate Zones Direction ... + if (result) + { + // + bullishZonesCount = ExtractByDirection(bullishZones, _zones, X_DIRECTION_BULLISH); + bearishZonesCount = ExtractByDirection(bearishZones, _zones, X_DIRECTION_BEARISH); + + // + result = IsValidSize(bullishZonesCount) || + IsValidSize(bearishZonesCount); + } + + // + // Looking for Sequences of Zones ... + if (result) + { + // + int idx = -1; + bool has = false; + XBoxZone bullOrderFlow[]; + XBoxZone bearOrderFlow[]; + + // + // Bullish OrderFlow ... + + // + // Sorting ... + Copy(bullishZones, bullOrderFlow); + Sort( + bullOrderFlow, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH, + orderFlowValidation + 1 // + ); + bool hasBullishOrderFlow = ArraySize(bullOrderFlow) >= orderFlowValidation; + if (hasBullishOrderFlow) + { + // + // Validate Order Flow ... + Copy(bullOrderFlow, tmps); + XClean(bullOrderFlow); + while (HasChild(tmps)) + { + // + tmp.Clean(); + tmp = tmps[0]; + ArrayRemove(tmps, 0, 1); + + // + idx = GetHighest(tmps); + has = !IsValidIndex(idx) + ? true + : tmps[idx].lower < tmp.lower; + if (has) + { + AddIfNotExists(tmp, bullOrderFlow); + } + } + + // + hasBullishOrderFlow = ArraySize(bullOrderFlow) >= orderFlowValidation; + } + + // + // Bearish OrderFlow ... + + // + // Sorting ... + Copy(bearishZones, bearOrderFlow); + Sort( + bearOrderFlow, + X_SORT_BY_DATE, + X_DIRECTION_BULLISH, + orderFlowValidation + 1 // + ); + bool hasBearishOrderFlow = ArraySize(bearOrderFlow) >= orderFlowValidation; + if (hasBearishOrderFlow) + { + // + // Validate Order Flow ... + Copy(bearOrderFlow, tmps); + XClean(bearOrderFlow); + while (HasChild(tmps)) + { + // + tmp.Clean(); + tmp = tmps[0]; + ArrayRemove(tmps, 0, 1); + + // + idx = GetLowest(tmps); + has = !IsValidIndex(idx) + ? true + : tmps[idx].upper > tmp.upper; + if (has) + { + AddIfNotExists(tmp, bearOrderFlow); + } + } + + // + hasBearishOrderFlow = ArraySize(bearOrderFlow) >= orderFlowValidation; + } + + // + result = hasBullishOrderFlow || + hasBearishOrderFlow; + + // + // Validate Order Flows ... + if (result) + { + // + has = (hasBullishOrderFlow && !hasBearishOrderFlow) || + (hasBearishOrderFlow && !hasBullishOrderFlow); + + // + // When only Have One Direction ... + if (has) + { + // + if (hasBullishOrderFlow) + { + // + dir = X_DIRECTION_BULLISH; + Copy(bullOrderFlow, orderFlow); + } + else if (hasBearishOrderFlow) + { + // + dir = X_DIRECTION_BEARISH; + Copy(bearOrderFlow, orderFlow); + } + } + // + // When Two Direction Exists ... + else + { + // + // Retrieve Oldest Of Bullish / Bearish ... + int oldestBullIDX = GetOldest(bullOrderFlow); + int oldestBearIDX = GetOldest(bearOrderFlow); + result = IsValidIndex(oldestBullIDX) && + IsValidIndex(oldestBearIDX); + if (result) + { + // + dir = + bullOrderFlow[oldestBullIDX].from > bearOrderFlow[oldestBearIDX].from + ? X_DIRECTION_BULLISH + : bearOrderFlow[oldestBearIDX].from > bullOrderFlow[oldestBullIDX].from + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + result = HasDirection(dir); + if (result) + { + // + if (IsXBullish(dir)) + { + Copy(bullOrderFlow, orderFlow); + } + else if (IsXBearish(dir)) + { + Copy(bearOrderFlow, orderFlow); + } + } + } + } + + // + XClean(bullOrderFlow); + XClean(bearOrderFlow); + + // + result = HasChild(orderFlow) && + HasDirection(dir); + } + + // + // Validate Price ... + if (result) + { + // + int idx = -1; + if (IsXBullish(dir)) + { + // + idx = GetHighest(orderFlow); + result = IsValidIndex(idx) && + bar.low > orderFlow[idx].upper; + } + else + { + // + idx = GetLowest(orderFlow); + result = IsValidIndex(idx) && + bar.high < orderFlow[idx].lower; + } + } + + // + // Update To Time of Order Flow ... + if (result) + { + UpdateToTime(orderFlow, bar.time); + } + + // + // Cleanup ... + if (!result) + { + // + XClean(orderFlow); + CleanDirection(dir); + } + tmp.Clean(); + XClean(tmps); + XClean(_zones); + XClean(bullishZones); + XClean(bearishZones); + + // + return result; + } + + // + // FVG ... + + /** + * Check For FVG Exists in Specified Loopback Period ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param fvg: XBoxZone, reference for Holding FVG ... + * @param maxLoopback: int, Max Allowed Loopback to Lookup FVG ... + * + * @return ( bool ) + */ + bool HasFVG( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &fvg, + int maxLoopback = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + fvg.Clean(); + CleanDirection(dir); + + // + // Normalize ... + maxLoopback = NormalizeInt(maxLoopback, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + int start = bar.Index(); + int end = start + maxLoopback; + for (int i = start; i < end; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!has) + { + continue; + } + + // + // Check iBar is FVG or not ... + has = barAnalyser.IsFVG( + iBar, + fvg, + true // Force Bar Type ... + ); + if (!has) + { + // + fvg.Clean(); + iBar.Clean(); + CleanDirection(dir); + + // + continue; + } + + // + iBar.Clean(); + dir = fvg.dir; + + // + break; + } + + // + // Check FVG Exists ... + result = fvg.IsValid(); + + // + // Check Direction Exists ... + result = + result && + HasDirection(dir); + + // + // Cleanup Resources ... + if (!result) + { + // + fvg.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + + // + // OB ... + + /** + * Check For OB Exists in Specified Loopback Period ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param ob: XBoxZone, reference for Holding OB ... + * @param maxLoopback: int, Max Allowed Loopback to Lookup OB ... + * + * @return ( bool ) + */ + bool HasOB( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &ob, + int maxLoopback = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + ob.Clean(); + CleanDirection(dir); + + // + // Normalize ... + maxLoopback = NormalizeInt(maxLoopback, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + int start = bar.Index(); + int end = start + maxLoopback; + for (int i = start; i < end; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!has) + { + continue; + } + + // + // Check iBar is OB or not ... + has = barAnalyser.IsOB( + iBar, + ob, + true, // Force FVG Bar Type ... + true // Force OB First Two Bar InDirection ... + ); + if (!has) + { + // + ob.Clean(); + iBar.Clean(); + CleanDirection(dir); + + // + continue; + } + + // + iBar.Clean(); + dir = ob.dir; + + // + break; + } + + // + // Check OB Exists ... + result = ob.IsValid(); + + // + // Check Direction Exists ... + result = + result && + HasDirection(dir); + + // + // Cleanup Resources ... + if (!result) + { + // + ob.Clean(); + CleanDirection(dir); + } + iBar.Clean(); + + // + return result; + } + + // + // Trending ... + + /** + * Check Trend Exists Based on Swings ... + * + * @param bar: XOHCL, Specified Bar ... + * @param dir: ENUM_X_DIRECTION a reference for Direction ... + * @param swings: XOHCL Array, Holds Swings ... + * @param numberOfSwings: int, Number of Swing Points for Detect Trend ... + * @param swingShoulders: int, Swing Shoulders Approvement Length ... + * + * @return ( bool ) + */ + bool HasSwingTrend( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XOHCL &swings[], + int numberOfSwings = 3, + int swingShoulders = 7 // + ) + { + // + bool result = false; + + // + // Prepare ... + CleanDirection(dir); + SpecifiedClean(swings); + + // + // Normalizing ... + numberOfSwings = NormalizeInt(numberOfSwings, 3, 10); + swingShoulders = NormalizeInt(swingShoulders, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Trend Direction ... + XOHCL iSwing; + int idx = -1; + bool has = false; + XOHCL swingLows[]; + XOHCL swingHighs[]; + int lastSwingLowIndex = bar.Index(); + int lastSwingHighIndex = bar.Index(); + while (ArraySize(swingLows) < numberOfSwings || ArraySize(swingHighs) < numberOfSwings) + { + // + bool canLookupSwingLow = ArraySize(swingLows) < numberOfSwings; + bool canLookupSwingHigh = ArraySize(swingHighs) < numberOfSwings; + if (!canLookupSwingLow && !canLookupSwingHigh) + { + break; + } + + // + // Handle Swing Lows ... + if (canLookupSwingLow) + { + // + iSwing.Clean(); + idx = FindXSwing( + X_SWING_LOW, + bar.symbol, + bar.period, + lastSwingLowIndex + 1, + swingShoulders // + ); + has = IsValidIndex(idx); + if (has) + { + // + has = iSwing.Init( + bar.symbol, + bar.period, + idx // + ); + if (has) + { + // + AddRef( + iSwing, + swingLows // + ); + + // + lastSwingLowIndex = idx; + } + } + } + + // + // Handle Swing Highs ... + if (canLookupSwingHigh) + { + // + iSwing.Clean(); + idx = FindXSwing( + X_SWING_HIGH, + bar.symbol, + bar.period, + lastSwingHighIndex + 1, + swingShoulders // + ); + has = IsValidIndex(idx); + if (has) + { + // + has = iSwing.Init( + bar.symbol, + bar.period, + idx // + ); + if (has) + { + // + AddRef( + iSwing, + swingHighs // + ); + + // + lastSwingHighIndex = idx; + } + } + } + } + + // + // Check Trend Based On Swings ... + + // + // Check Directions ... + + // + bool isBullish = false; + bool isBearish = false; + + // + datetime oldestSwingLow = NULL; + datetime oldestSwingHigh = NULL; + + // + // Checking Bullish Trend based on Swing Lows ... + int count = ArraySize(swingLows); + for (int i = 0; i < count - 1; i++) + { + // + has = swingLows[i].low > swingLows[i + 1].low; + isBullish = + !isBullish + ? has + : isBullish && has; + if (!isBullish) + { + break; + } + + // + datetime oldeTime = MathMin(swingLows[i].time, swingLows[i + 1].time); + oldestSwingLow = + !IsSpecifiedValid(oldestSwingLow) + ? oldeTime + : MathMin(oldestSwingLow, oldeTime); + } + + // + // Checking Bearish Trend based on Swing Highs ... + count = ArraySize(swingHighs); + for (int i = 0; i < count - 1; i++) + { + // + has = swingHighs[i].high < swingHighs[i + 1].high; + isBearish = + !isBearish + ? has + : isBearish && has; + if (!isBearish) + { + break; + } + + // + datetime oldeTime = MathMin(swingHighs[i].time, swingHighs[i + 1].time); + oldestSwingHigh = + !IsSpecifiedValid(oldestSwingHigh) + ? oldeTime + : MathMin(oldestSwingHigh, oldeTime); + } + + // + result = isBullish || isBearish; + if (!result) + { + // + iSwing.Clean(); + SpecifiedClean(swingLows); + SpecifiedClean(swingHighs); + + // + return result; + } + + // + if (isBullish && + isBearish && + IsSpecifiedValid(oldestSwingLow) && + IsSpecifiedValid(oldestSwingHigh)) + { + // + // Here we Have to Detect Newest Trend or Oldest Trend ... + isBullish = oldestSwingLow < oldestSwingHigh; + isBearish = oldestSwingHigh < oldestSwingLow; + } + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (!result) + { + // + iSwing.Clean(); + SpecifiedClean(swingLows); + SpecifiedClean(swingHighs); + + // + return result; + } + + // + if (isBullish) + { + // + Copy( + swingLows, + swings // + ); + + // + dir = X_DIRECTION_BULLISH; + } + else + { + // + Copy( + swingHighs, + swings // + ); + + // + dir = X_DIRECTION_BEARISH; + } + + // + iSwing.Clean(); + SpecifiedClean(swingLows); + SpecifiedClean(swingHighs); + + // + return result; + } + + /** + * Check Specified Bar Has Support or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param support: XOHCL, Supported Bar ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ... + * + * @return ( bool ) + */ + bool HasSupport( + XOHCL &bar, + XOHCL &support, + int validationLength = 21, + int maxAllowedLoopback = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + support.Clean(); + + // + // Normalizing ... + validationLength = NormalizeInt(validationLength, 7); + maxAllowedLoopback = NormalizeInt(maxAllowedLoopback, 21, 1500); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Find Support Swing ... + int idx = -1; + bool has = false; + int lookupIDX = bar.Index(); + while (!IsValidIndex(idx) && + lookupIDX < maxAllowedLoopback) + { + // + // Detect Swing ... + idx = FindXSwing( + X_SWING_LOW, + bar.symbol, + bar.period, + lookupIDX, + validationLength // + ); + has = IsValidIndex(idx); + if (!has) + { + // + lookupIDX++; + continue; + } + + // + // Retrieve Swing Bar ... + has = support.Init( + bar.symbol, + bar.period, + idx // + ); + if (!has) + { + // + idx = -1; + lookupIDX++; + support.Clean(); + continue; + } + + // + // Check Suppor Low Shadow ... + has = support.GetDown() < bar.low; + if (!has) + { + // + idx = -1; + lookupIDX++; + support.Clean(); + continue; + } + + // + if (IsValidIndex(idx)) + { + break; + } + } + + // + result = support.IsValid(); + + // + return result; + } + + /** + * Check Specified Bar Has Resistance or not ... + * + * @param bar: XOHCL, Specified Bar ... + * @param resistence: XOHCL, Resistanced Bar ... + * @param validationLength: int, Validation Length ... + * @param maxAllowedLoopback: int, Max Allowed Loopback to Detection ... + * + * @return ( bool ) + */ + bool HasResistance( + XOHCL &bar, + XOHCL &resistence, + int validationLength = 21, + int maxAllowedLoopback = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + resistence.Clean(); + + // + // Normalizing ... + validationLength = NormalizeInt(validationLength, 7); + maxAllowedLoopback = NormalizeInt(maxAllowedLoopback, 21, 1500); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Find Support Swing ... + int idx = -1; + bool has = false; + int lookupIDX = bar.Index(); + while (!IsValidIndex(idx) && + lookupIDX < maxAllowedLoopback) + { + // + // Detect Swing ... + idx = FindXSwing( + X_SWING_HIGH, + bar.symbol, + bar.period, + lookupIDX, + validationLength // + ); + has = IsValidIndex(idx); + if (!has) + { + // + lookupIDX++; + continue; + } + + // + // Retrieve Swing Bar ... + has = resistence.Init( + bar.symbol, + bar.period, + idx // + ); + if (!has) + { + // + idx = -1; + lookupIDX++; + resistence.Clean(); + continue; + } + + // + // Check Resistance High Shadow ... + has = resistence.GetUp() > bar.high; + if (!has) + { + // + idx = -1; + lookupIDX++; + resistence.Clean(); + continue; + } + + // + if (IsValidIndex(idx)) + { + break; + } + } + + // + result = resistence.IsValid(); + + // + return result; + } + + // + // Analysers ... + + /** + * Analyse Specified Bar ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param analysis: XPatternAnalysis, reference to holds Analysis result ... + * @param config: XPatternAnalysisConfig, reference to Provides Detector Configs ... + * + * @return ( bool ) + */ + bool AnalyseBarPatterns( + XOHCL &bar, + XPatternAnalysis &analysis, + XPatternAnalysisConfig &config // + ) + { + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + analysis.bar = bar; + analysis.time = TimeCurrent(); + + // + XOHCL iSwing; + XBoxZone iZone; + ENUM_X_DIRECTION iDir; + ENUM_X_BAR_PATTERN iPattern; + + // + bool has; + bool isBullish; + bool isBearish; + + // + bool canDetect; + bool canDetectBullish; + bool canDetectBearish; + + // + // Bars Detectors ... + + // + // XPV High Low Detection ... + canDetect = config.CanDetect(X_BAR_PATTERN_HIGH) || + config.CanDetect(X_BAR_PATTERN_LOW); + if (canDetect) + { + // + has = IsPV( + bar, + iDir, + config.pvValidationLength, + config.peakPriceType, + config.valePriceType // + ); + + // + canDetectBullish = config.CanDetect(X_BAR_PATTERN_LOW); + canDetectBearish = config.CanDetect(X_BAR_PATTERN_HIGH); + + // + isBullish = + has && + IsXBullish(iDir) && + canDetectBullish; + + // + isBearish = + has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + iPattern = + isBearish + ? X_BAR_PATTERN_HIGH + : X_BAR_PATTERN_LOW; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Momentum ... + iPattern = X_BAR_PATTERN_MOMENTUM; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsMomentumBar( + bar, + iDir, + config.momentumBarValidationLength, + config.momentumBarApprovedMultiplier // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Engulfed ... + iPattern = X_BAR_PATTERN_ENGULFED; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsEngulfedBar( + bar, + iDir // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // TrueGap ... + iPattern = X_BAR_PATTERN_TRUE_GAPED; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsTrueGapedBar( + bar, + iDir, + config.trueGapApprovedStrength // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Pinned ... + iPattern = X_BAR_PATTERN_PINNED; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsPinnedBar( + bar, + iDir, + config.pinBarShadowApprovedMultiplier, + config.pinBarRangeMultiplier, + config.pinBarForceDirection // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Pattern Detectors ... + + // + // Star ... + iPattern = X_BAR_PATTERN_STAR; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsStarPattern( + bar, + iDir // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Piercing ... + iPattern = X_BAR_PATTERN_PIERCING; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsPiercingPattern( + bar, + iDir // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Rising ... + iPattern = X_BAR_PATTERN_RISING; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsRisingPattern( + bar, + iDir // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Flag ... + iPattern = X_BAR_PATTERN_FLAG; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsFlagPattern( + bar, + iDir, + iSwing, + config.flagPatternPullbackLength // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + + // + analysis.flagSwing = iSwing; + } + } + + // + // SignalKey ... + iPattern = X_BAR_PATTERN_SIGNALKEY; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = IsSignalKeyBarPattern( + bar, + iDir, + config.pinBarShadowApprovedMultiplier, + config.pinBarRangeMultiplier, + config.pinBarForceDirection // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + IsXBullish(iDir) && + canDetectBullish; + isBearish = has && + IsXBearish(iDir) && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + } + + // + // Zone Detectors ... + + // + // OB ... + iPattern = X_BAR_PATTERN_OB; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = barAnalyser.IsOB( + bar, + iZone, + config.fvgForceType, + config.obForceTwoBar // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + iZone.IsBullish() && + canDetectBullish; + isBearish = has && + iZone.IsBearish() && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.ob = iZone; + } + } + + // + // FVG ... + iPattern = X_BAR_PATTERN_FVG; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = barAnalyser.IsFVG( + bar, + iZone, + config.fvgForceType // + ); + + // + canDetectBullish = config.CanDetect( + iPattern, + X_DIRECTION_BULLISH // + ); + canDetectBearish = config.CanDetect( + iPattern, + X_DIRECTION_BEARISH // + ); + + // + isBullish = has && + iZone.IsBullish() && + canDetectBullish; + isBearish = has && + iZone.IsBearish() && + canDetectBearish; + + // + canDetect = isBullish || + isBearish; + if (canDetect) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.fvg = iZone; + } + } + + // + // Support ... + iPattern = X_BAR_PATTERN_SUPPORT; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = HasSupport( + bar, + iSwing, + config.supportAndResistanceValidationLength, + config.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToSupportBox( + iSwing, + iZone, + bar.time, + config.supportAndResistanceValidationLength // + ); + if (has) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.support = iZone; + } + } + } + + // + // Resistance ... + iPattern = X_BAR_PATTERN_RESISTANCE; + canDetect = config.CanDetect(iPattern); + if (canDetect) + { + // + has = HasResistance( + bar, + iSwing, + config.supportAndResistanceValidationLength, + config.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToResistanceBox( + iSwing, + iZone, + bar.time, + config.supportAndResistanceValidationLength // + ); + if (has) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.resistance = iZone; + } + } + } + + // + // Validate Analysis ... + result = analysis.IsValid(); + + // + // Update Quarter ... + if (result) + { + // + // Retrieve Previous Bar ... + XOHCL pBar; + has = bar.GetPreviousBar(pBar); + if (has) + { + // + // Update Quarter ... + UpdateZones( + bar, + analysis.quarterActions, + config.quarterZonesValidationLength, // Zones Validation Length ... + config.quarterZonesRequiredToStart, // Zones Count to Start Processing ... + config.quarterZoneDetectionLoopback // Zones Detection Loopback ... + ); + + // + // Fill Quarter Props ... + analysis.majorSupport = majorSupport; + analysis.minorSupport = minorSupport; + analysis.quarter = CalculateQuarter(); + analysis.majorResistance = majorResistance; + analysis.minorResistance = minorResistance; + + // + // Update To Times ... + if (analysis.majorSupport.IsValid()) + { + analysis.majorSupport.to = bar.time; + } + if (analysis.minorSupport.IsValid()) + { + analysis.minorSupport.to = bar.time; + } + if (analysis.majorResistance.IsValid()) + { + analysis.majorResistance.to = bar.time; + } + if (analysis.minorResistance.IsValid()) + { + analysis.minorResistance.to = bar.time; + } + } + } + + // + // Cleanup Resources ... + iZone.Clean(); + iSwing.Clean(); + CleanDirection(iDir); + + // + return result; + } + + /** + * Update and Manage Support and Resistance Zones ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param actions: ENUM_X_DETECTOR_ZONE_ACTION, refernce collection to Notify happens actions ... + * @param validationLength: int, Validation Length for Zones ... + * @param requiredZones: int, Number of required Zones to collecting ... + * @param loopback: int, Max Allowed Loopback Bars for Collecting ... + * + * @return ( int ) + */ + int UpdateZones( + XOHCL &bar, + ENUM_X_DETECTOR_ZONE_ACTION &actions[], + int validationLength = 3, + int requiredZones = 10, + int loopback = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(actions); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 100); + requiredZones = NormalizeInt(requiredZones, 5); + validationLength = NormalizeInt(validationLength, 2); + + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return result; + } + + // + int barIndex = bar.Index(); + + // + // Collect or Manage Zones ... + XOHCL zoneBar; + XBoxZone iZone; + bool hasZone = HasChild(zones); + int zonesCount = ArraySize(zones); + int zoneDetectionLoopback = (validationLength * 2); + if (!hasZone) + { + // + XOHCL iBar; + int start = barIndex; + int end = barIndex + loopback; + for (int i = start; i < end; i++) + { + // + // Extract Detected Zones ... + iBar.Clean(); + has = bar.BarAt(i, iBar); + if (!has) + { + continue; + } + + // + // Check Support ... + iZone.Clean(); + zoneBar.Clean(); + has = HasSupport( + iBar, + zoneBar, + validationLength, // Zone Validation Length ... + zoneDetectionLoopback // Zone Detection Loopback ... + ); + has = has && + ToSupportBox(zoneBar, iZone, bar.time); + if (has) + { + // + AddIfNotExists( + iZone, + zones // + ); + } + + // + // Check Resistance ... + iZone.Clean(); + zoneBar.Clean(); + has = HasResistance( + iBar, + zoneBar, + validationLength, // Zone Validation Length ... + zoneDetectionLoopback // Zone Detection Loopback ... + ); + has = has && + ToResistanceBox(zoneBar, iZone, bar.time); + if (has) + { + // + AddIfNotExists( + iZone, + zones // + ); + } + + // + // Validate Number of Zones ... + zonesCount = ArraySize(zones); + if (zonesCount >= requiredZones) + { + break; + } + } + + // + iBar.Clean(); + iZone.Clean(); + zoneBar.Clean(); + + // + // Update Has Zones ... + hasZone = HasChild(zones); + zonesCount = ArraySize(zones); + } + + // + // Manage Exists Zones ... + if (hasZone) + { + // + // Update Zones To Time ... + UpdateToTime(zones, bar.time); + + // + // Validate Zones ... + CheckZones(bar, zones); + + // + // Remove Breaked Zones ... + RemoveBreakedZones(zones); + + // + hasZone = HasChild(zones); + zonesCount = ArraySize(zones); + } + + // + // Minimum Exists Zones for Detecting majors ... + int minNumberOfZonesForMajors = 5; + bool canLookupMajor = hasZone && + zonesCount >= minNumberOfZonesForMajors; + + // + // Supports ... + + // + // Check Zones Existances ... + bool hasMajorSupport = majorSupport.IsValid(); + bool hasMinorSupport = minorSupport.IsValid(); + + // + // Check Major Support State ... + if (hasMajorSupport) + { + // + XOHCL pBar; + has = bar.GetPreviousBar(pBar); + if (has) + { + // + bool isBreaked = pBar.close < majorSupport.lower; + if (isBreaked) + { + // + int idx = -1; + has = FindIndex(idx, majorSupport, zones); + if (has) + { + zones[idx].breakAt = pBar.time; + } + majorSupport.Clean(); + minorSupport.Clean(); + hasMajorSupport = false; + hasMinorSupport = false; + Add( + X_DETECTOR_ZONE_ACTION_MAJOR_SUPPORT_BREAKED, + actions // + ); + } + } + + // + pBar.Clean(); + } + + // + // Look For Major Support ... + if (!hasMajorSupport) + { + // + minorSupport.Clean(); + hasMinorSupport = false; + + // + // Lookup Major ... + if (canLookupMajor) + { + // + int idx = GetLowestByDir(zones, X_DIRECTION_BULLISH); + hasMajorSupport = IsValidIndex(idx) && !IsXValid(zones[idx].breakAt); + if (hasMajorSupport) + { + // + majorSupport = zones[idx]; + Add( + X_DETECTOR_ZONE_ACTION_MAJOR_SUPPORT_DETECTED, + actions // + ); + } + } + } + + // + // Resistances ... + + // + // Check Zones Existances ... + bool hasMajorResistance = majorResistance.IsValid(); + bool hasMinorResistance = minorResistance.IsValid(); + + // + // Check Major Resistance State ... + if (hasMajorResistance) + { + // + XOHCL pBar; + has = bar.GetPreviousBar(pBar); + if (has) + { + // + bool isBreaked = pBar.close > majorResistance.upper; + if (isBreaked) + { + // + int idx = -1; + has = FindIndex(idx, majorResistance, zones); + if (has) + { + zones[idx].breakAt = pBar.time; + } + majorResistance.Clean(); + minorResistance.Clean(); + hasMajorResistance = false; + hasMinorResistance = false; + Add( + X_DETECTOR_ZONE_ACTION_MAJOR_RESISTANCE_BREAKED, + actions // + ); + } + } + + // + pBar.Clean(); + } + + // + // Look For Major Resistance ... + if (!hasMajorResistance) + { + // + minorResistance.Clean(); + hasMinorResistance = false; + + // + // Lookup Major ... + if (canLookupMajor) + { + // + int idx = GetHighestByDir(zones, X_DIRECTION_BEARISH); + hasMajorResistance = IsValidIndex(idx); + if (hasMajorResistance) + { + // + majorResistance = zones[idx]; + Add( + X_DETECTOR_ZONE_ACTION_MAJOR_RESISTANCE_DETECTED, + actions // + ); + } + } + } + + // + // Check Majors Exixsts ... + has = hasMajorSupport && + hasMajorResistance; + if (has) + { + // + double quarter = CalculateQuarter(); + + // + // For Looking up Minor Support, we + // have to Ensure Major Support Exists ... + if (hasMajorSupport) + { + // + majorSupport.to = bar.time; + + // + // Look for Minor Support ... + if (!hasMinorSupport) + { + // + XBoxZone _supports[]; + int _supportsCount = ExtractByDirection( + _supports, + zones, + X_DIRECTION_BULLISH // + ); + _supportsCount = RemoveBreakedZones(_supports); + has = IsValidSize(_supportsCount); + if (has) + { + // + // Remove Major ... + Remove( + majorSupport, + _supports // + ); + + // + // Count Remain Zones ... + _supportsCount = ArraySize(_supports); + has = IsValidSize(_supportsCount); + if (has) + { + // + // Minors Selected by Youngest ... + int idx = quarter > 0 + ? GetYoungestBelow(quarter, _supports) + : GetYoungest(_supports); + hasMinorSupport = IsValidIndex(idx) && !IsXValid(_supports[idx].breakAt); + if (hasMinorSupport) + { + // + minorSupport = _supports[idx]; + minorSupport.to = bar.time; + minorSupport.from = minorSupport.at; + Add( + X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_DETECTED, + actions // + ); + } + } + } + + // + XClean(_supports); + } + + // + // Validate Minor Support Place ... + if (quarter > 0 && + hasMinorSupport) + { + // + hasMinorSupport = minorSupport.upper < quarter; + if (!hasMinorSupport) + { + // + int idx = -1; + has = FindIndex( + idx, + minorSupport, + zones // + ); + if (has) + { + zones[idx].breakAt = bar.time; + } + minorSupport.Clean(); + } + } + + // + // Refine exists Minor Support ... + if (hasMinorSupport) + { + // + minorSupport.to = bar.time; + + // + XOHCL pBar; + has = bar.GetPreviousBar(pBar); + if (has) + { + // + // Check Break ... + bool isBreaked = pBar.close < minorSupport.lower; + if (isBreaked) + { + // + minorSupport.Clean(); + Add( + X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_BREAKED, + actions // + ); + } + + // + // Check Test ... + bool isTested = !isBreaked && + pBar.low < minorSupport.upper && + pBar.low > minorSupport.lower && + bar.close > minorSupport.lower && + bar.open > minorSupport.lower; + if (isTested) + { + // + Add( + X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_RETESTED, + actions // + ); + } + + // + // Check Refine ... + bool canRefine = !isBreaked && + pBar.low < minorSupport.lower && + pBar.close > minorSupport.lower; + if (canRefine) + { + // + minorSupport.upper = minorSupport.lower; + minorSupport.lower = pBar.low; + Add( + pBar.time, + minorSupport.refines // + ); + Add( + X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_REFINED, + actions // + ); + } + + // + // Check New Minor Support ... + has = !isTested && + !canRefine; + if (has) + { + // + // Check Above Minor Support has Support ... + XBoxZone _supports[]; + int _supportsCount = ExtractByDirection( + _supports, + zones, + X_DIRECTION_BULLISH // + ); + Remove(majorSupport, _supports); + Remove(minorSupport, _supports); + RemoveBreakedZones(_supports); + _supportsCount = ArraySize(_supports); + has = IsValidSize(_supportsCount); + if (has) + { + // + int idx = GetLowestAfter(minorSupport.from, _supports); + hasMinorSupport = IsValidIndex(idx) && + (quarter <= 0 + ? true + : _supports[idx].upper < quarter); + if (hasMinorSupport) + { + // + minorSupport = _supports[idx]; + minorSupport.to = bar.time; + minorSupport.from = minorSupport.at; + Add( + X_DETECTOR_ZONE_ACTION_MINOR_SUPPORT_DETECTED, + actions // + ); + } + } + } + } + + // + pBar.Clean(); + } + } + + // + // For Looking up Minor Resistance, we + // have to Ensure Major Resistance Exists ... + if (hasMajorResistance) + { + // + majorResistance.to = bar.time; + + // + // Look for Minor Resistance ... + if (!hasMinorResistance) + { + // + XBoxZone _resistances[]; + int _resistancesCount = ExtractByDirection( + _resistances, + zones, + X_DIRECTION_BEARISH // + ); + _resistancesCount = RemoveBreakedZones(_resistances); + has = IsValidSize(_resistancesCount); + if (has) + { + // + // Remove Major ... + Remove( + majorResistance, + _resistances // + ); + + // + // Count Remain Zones ... + _resistancesCount = ArraySize(_resistances); + has = IsValidSize(_resistancesCount); + if (has) + { + // + // Minors Selected Youngest ... + int idx = GetYoungestAbove(quarter, _resistances); + hasMinorResistance = IsValidIndex(idx); + if (hasMinorResistance) + { + // + minorResistance = _resistances[idx]; + minorResistance.to = bar.time; + minorResistance.from = minorResistance.at; + Add( + X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_DETECTED, + actions // + ); + } + } + } + + // + XClean(_resistances); + } + + // + // Validate Minor Support Place ... + if (quarter > 0 && + hasMinorResistance) + { + // + hasMinorResistance = minorResistance.lower > quarter; + if (!hasMinorResistance) + { + // + int idx = -1; + has = FindIndex( + idx, + minorResistance, + zones // + ); + if (has) + { + zones[idx].breakAt = bar.time; + } + minorResistance.Clean(); + } + } + + // + // Refine exists Minor Resistance ... + if (hasMinorResistance) + { + // + minorResistance.to = bar.time; + + // + // Check Retesting ... + XOHCL pBar; + has = bar.GetPreviousBar(pBar); + if (has) + { + // + // Check Break ... + bool isBreaked = pBar.close > minorResistance.upper; + if (isBreaked) + { + // + minorResistance.Clean(); + Add( + X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_BREAKED, + actions // + ); + } + + // + // Check Test ... + bool isTested = !isBreaked && + pBar.high > minorResistance.lower && + pBar.high < minorResistance.upper && + bar.close < minorResistance.upper && + bar.open < minorResistance.upper; + if (isTested) + { + // + Add( + X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_RETESTED, + actions // + ); + } + + // + // Check Refine ... + bool canRefine = !isBreaked && + pBar.high > minorResistance.upper && + pBar.close < minorResistance.upper; + if (canRefine) + { + // + minorResistance.lower = minorResistance.upper; + minorResistance.upper = pBar.high; + Add( + pBar.time, + minorResistance.refines // + ); + Add( + X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_REFINED, + actions // + ); + } + + // + // Check New Minor Resistace ... + has = !isTested && + !canRefine; + if (has) + { + // + // Check Above Minor Resistance has Resistance ... + XBoxZone _resistances[]; + int _resistancesCount = ExtractByDirection( + _resistances, + zones, + X_DIRECTION_BEARISH // + ); + Remove(majorResistance, _resistances); + Remove(minorResistance, _resistances); + RemoveBreakedZones(_resistances); + _resistancesCount = ArraySize(_resistances); + has = IsValidSize(_resistancesCount); + if (has) + { + // + int idx = GetHighestAfter(minorResistance.from, _resistances); + hasMinorResistance = IsValidIndex(idx) && + (quarter <= 0 + ? true + : _resistances[idx].lower > quarter); + if (hasMinorResistance) + { + // + minorResistance = _resistances[idx]; + minorResistance.to = bar.time; + minorResistance.from = minorResistance.at; + Add( + X_DETECTOR_ZONE_ACTION_MINOR_RESISTANCE_DETECTED, + actions // + ); + } + } + } + } + + // + pBar.Clean(); + } + } + } + else + { + // + int idx = -1; + + // + has = minorSupport.IsValid() && + FindIndex( + idx, + minorSupport, + zones // + ); + if (has) + { + zones[idx].breakAt = bar.time; + } + minorSupport.Clean(); + hasMinorSupport = false; + + // + has = minorResistance.IsValid() && + FindIndex( + idx, + minorResistance, + zones // + ); + if (has) + { + zones[idx].breakAt = bar.time; + } + minorResistance.Clean(); + hasMinorResistance = false; + } + + // + // Check Bar Zones to Update Zones ... + + // + // Check Support ... + iZone.Clean(); + zoneBar.Clean(); + has = HasSupport( + bar, + zoneBar, + validationLength, // Zone Validation Length ... + zoneDetectionLoopback // Zone Detection Loopback ... + ); + has = has && + ToSupportBox(zoneBar, iZone, bar.time); + if (has) + { + // + AddIfNotExists( + iZone, + zones // + ); + } + + // + // Check Resistance ... + iZone.Clean(); + zoneBar.Clean(); + has = HasResistance( + bar, + zoneBar, + validationLength, // Zone Validation Length ... + zoneDetectionLoopback // Zone Detection Loopback ... + ); + has = has && + ToResistanceBox(zoneBar, iZone, bar.time); + if (has) + { + // + AddIfNotExists( + iZone, + zones // + ); + } + + // + // Actions Counting ... + result = ArraySize(actions); + + // + // Cleanup ... + iZone.Clean(); + zoneBar.Clean(); + + // + return result; + } + + int CollectOBs( + XOHCL &bar, + XBoxZone &dest[], + int zonesLoopback = 5, + int maxRequiredZone = 0, + int loopback = 100 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return result; + } + + // + XOHCL iBar; + XBoxZone iBox; + ENUM_X_DIRECTION iDir; + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + iBox.Clean(); + iDir = X_DIRECTION_NONE; + + // + has = bar.BarAt(i, iBar); + has = has && + HasOB(iBar, iDir, iBox, zonesLoopback); + if (has) + { + // + AddIfNotExists( + iBox, + dest // + ); + } + + // + has = maxRequiredZone <= 0 || + (maxRequiredZone > 0 && ArraySize(dest) < maxRequiredZone); + if (!has) + { + break; + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iBox.Clean(); + iDir = X_DIRECTION_NONE; + + // + return result; + } + + int CollectFVGs( + XOHCL &bar, + XBoxZone &dest[], + int zonesLoopback = 5, + int maxRequiredZone = 0, + int loopback = 100 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return result; + } + + // + XOHCL iBar; + XBoxZone iBox; + ENUM_X_DIRECTION iDir; + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + iBox.Clean(); + iDir = X_DIRECTION_NONE; + + // + has = bar.BarAt(i, iBar); + has = has && + HasFVG(iBar, iDir, iBox, zonesLoopback); + if (has) + { + // + AddIfNotExists( + iBox, + dest // + ); + } + + // + has = maxRequiredZone <= 0 || + (maxRequiredZone > 0 && ArraySize(dest) < maxRequiredZone); + if (!has) + { + break; + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iBox.Clean(); + iDir = X_DIRECTION_NONE; + + // + return result; + } + + int CollectZones( + XOHCL &bar, + XBoxZone &dest[], + int zonesLoopback = 5, + int zonesValidationLength = 21, + int maxRequiredZone = 0, + int loopback = 100 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 10); + zonesLoopback = NormalizeInt(zonesLoopback, 3); + maxRequiredZone = NormalizeInt(maxRequiredZone, 0); + zonesValidationLength = NormalizeInt(zonesValidationLength, 3); + + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return result; + } + + // + XOHCL iBar; + XBoxZone iBox; + XOHCL iZoneBar; + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + iBar.Clean(); + iBox.Clean(); + iZoneBar.Clean(); + + // + has = bar.BarAt(i, iBar); + if (!has) + { + continue; + } + + // + // Support ... + has = HasSupport(iBar, iZoneBar, zonesValidationLength, zonesLoopback); + if (has) + { + // + has = ToSupportBox(iZoneBar, iBox, bar.time, zonesValidationLength); + if (has) + { + // + AddIfNotExists( + iBox, + dest // + ); + } + } + + // + // Resistance ... + has = HasResistance(iBar, iZoneBar, zonesValidationLength, zonesLoopback); + if (has) + { + // + has = ToResistanceBox(iZoneBar, iBox, bar.time, zonesValidationLength); + if (has) + { + // + AddIfNotExists( + iBox, + dest // + ); + } + } + + // + has = maxRequiredZone <= 0 || + (maxRequiredZone > 0 && ArraySize(dest) < maxRequiredZone); + if (!has) + { + break; + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iBox.Clean(); + iZoneBar.Clean(); + + // + return result; + } + + /** + * Filter Zones ... + * + * @param bar: XOHCL, reference to Specified Filtering Bar ... + * @param source: XBoxZone, reference collection to hold's filtered zones ... + * @param filterDir: ENUM_X_DIRECTION, specified Filter Direction ... + * @param priceType: ENUM_X_PRICE, Specified Bar's Price type to Use for Filtering Zones ... + * @param forDir: ENUM_X_DIRECTION, Specified Zone's Direction to Handle Filtering ... + * + * @return ( int ) + */ + int FilterZones( + XOHCL &bar, + XBoxZone &source[], + ENUM_X_DIRECTION filterDir, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + // Prepare ... + XBoxZone tmp[]; + Copy( + source, + tmp // + ); + XClean(source); + + // + // Validate ... + bool has = bar.IsValid() && + HasChild(tmp) && + IsXValid(priceType) && + HasDirection(filterDir); + if (!has) + { + // + XClean(tmp); + return result; + } + + // + XBoxZone iBox; + double price = bar.GetPrice(priceType); + bool isBullish = IsXBullish(filterDir); + while (HasChild(tmp)) + { + // + iBox = tmp[0]; + ArrayRemove(tmp, 0, 1); + + // + has = + // + // Direction Pass ... + (!HasDirection(forDir) + ? true + : forDir == iBox.dir) + // + && + // + // Price Pass ... + (isBullish + ? price > iBox.lower + : price < iBox.upper); + if (has) + { + AddIfNotExists(iBox, source); + } + + // + iBox.Clean(); + } + + // + result = ArraySize(source); + + // + // Cleanup ... + XClean(tmp); + iBox.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + // Tools / Actions ... + + /** + * Check Zones and Manage them ... + * + * @param forBar: XOHCL, reference to Specified Bar ... + * @param _zones: XBoxZone, reference to Specified Zone Collection ... + * @param sortBy: X_SORT_BY_DATE, Sort Zones by ... + * @param sortDir: ENUM_X_DIRECTION, Sort Zones in Direction ... + * @param maxAllowed: int, Specified Max Allowed Zones ... + */ + void CheckZones( + XOHCL &forBar, + XBoxZone &_zones[], + ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, + ENUM_X_DIRECTION sortDir = X_DIRECTION_BEARISH, + int maxAllowed = 50 // + ) + { + // + // Normalize ... + maxAllowed = NormalizeInt(maxAllowed, 0); + + // + // Validate ... + bool has = forBar.IsValid() && + HasChild(_zones); + if (!has) + { + return; + } + + // + // Looping Through Zones ... + int count = ArraySize(_zones); + for (int i = 0; i < count; i++) + { + // + // Check Break ... + has = IsXValid(_zones[i].breakAt); + if (has) + { + continue; + } + + // + _zones[i].to = forBar.time; + + // + // Check for Test ... + has = IsTested( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].tests // + ); + } + + // + // Check for Inside ... + has = IsInside( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].insides // + ); + } + + // + // Check for Break ... + has = IsBreaked( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].breaks // + ); + } + + // + // Check for Act ... + has = IsActed( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].acteds // + ); + } + + // + // Check for FakeBreakes ... + has = IsFakeBreaked( + forBar, + _zones[i] // + ); + if (has) + { + // + Add( + forBar.time, + _zones[i].fakeBreaks // + ); + } + + // + // Check for Valid Breakes ... + has = IsValidBreaked( + forBar, + _zones[i] // + ); + if (has) + { + _zones[i].breakAt = forBar.time; + } + } + + // + // Apply Sort and Cleanup ... + Sort( + _zones, + sortBy, + sortDir, + maxAllowed // + ); + } + + // + // Private ... + private: + // + // Props ... + XCBarAnalyser *barAnalyser; + + // + // Helpers ... + + /** + * Clean Specified Referenced Direction ... + * + * @param dir: ENUM_X_DIRECTION + */ + void CleanDirection(ENUM_X_DIRECTION &dir) + { + dir = X_DIRECTION_NONE; + } +}; + +// \ No newline at end of file diff --git a/Documents/BKP/x-saherelm.xfima.helper copy 2.mq5 b/Documents/BKP/x-saherelm.xfima.helper copy 2.mq5 new file mode 100644 index 00000000..a175d65d --- /dev/null +++ b/Documents/BKP/x-saherelm.xfima.helper copy 2.mq5 @@ -0,0 +1,8413 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCXFIMAHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" +#include "../Classes/x-saherelm.x-market.pattern.class.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_XFIMA_BUFFERS +{ + // + // Plot Buffers ... + XFIMA_MA_FAST_LINE = 0, + XFIMA_MA_FAST_COLOR_LINE = 1, + XFIMA_MA_SLOW_LINE = 2, + XFIMA_MA_SLOW_COLOR_LINE = 3, + XFIMA_SAR_LINE = 4, + XFIMA_SAR_COLOR_LINE = 5, + XFIMA_PEAK_LINE = 6, + XFIMA_VALE_LINE = 7, + XFIMA_FIBO_UPPER_LINE = 8, + XFIMA_FIBO_MIDDLE_LINE = 9, + XFIMA_FIBO_LOWER_LINE = 10, + XFIMA_ZIGZAG_LINE = 11, + XFIMA_MA_BAND_UPPER_LINE = 12, + XFIMA_MA_BAND_LOWER_LINE = 13, + XFIMA_HK_OPEN_LINE = 14, + XFIMA_HK_HIGH_LINE = 15, + XFIMA_HK_LOW_LINE = 16, + XFIMA_HK_CLOSE_LINE = 17, + XFIMA_HK_COLOR_LINE = 18, + XFIMA_HK_BAND_UPPER_LINE = 19, + XFIMA_HK_BAND_LOWER_LINE = 20, + XFIMA_PB_BAND_UPPER_LINE = 21, + XFIMA_PB_BAND_LOWER_LINE = 22, + XFIMA_ATR_BAND_UPPER_LINE = 23, + XFIMA_ATR_BAND_LOWER_LINE = 24, + // + // Data Buffers ... + XFIMA_MA_FAST_STATE_LINE = 25, + XFIMA_MA_SLOW_STATE_LINE = 26, + XFIMA_SAR_STATE_LINE = 27, + XFIMA_SC_HH_LINE = 28, + XFIMA_SC_LL_LINE = 29, + XFIMA_MC_HH_LINE = 30, + XFIMA_MC_LL_LINE = 31, + XFIMA_LC_HH_LINE = 32, + XFIMA_LC_LL_LINE = 33, + XFIMA_HC_HH_LINE = 34, + XFIMA_HC_LL_LINE = 35, + XFIMA_ZIGZAG_HIGHS_LINE = 36, + XFIMA_ZIGZAG_HIGHS_TIME_LINE = 37, + XFIMA_ZIGZAG_LOWS_LINE = 38, + XFIMA_ZIGZAG_LOWS_TIME_LINE = 39, + XFIMA_HK_RAW_OPEN_LINE = 40, + XFIMA_HK_RAW_HIGH_LINE = 41, + XFIMA_HK_RAW_LOW_LINE = 42, + XFIMA_HK_RAW_CLOSE_LINE = 43, + XFIMA_PB_BAND_RAW_UPPER_LINE = 44, + XFIMA_PB_BAND_RAW_LOWER_LINE = 45, + XFIMA_ATR_LINE = 46, + XFIMA_ATR_BAND_RAW_UPPER_LINE = 47, + XFIMA_ATR_BAND_RAW_LOWER_LINE = 48, +}; + +// +// Input Models ... +struct XFIMAInputs +{ + // + // Props ... + + // + // Calculation ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Short Period + ENUM_TIMEFRAMES scPeriod; // Short Period + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Medium Period + ENUM_TIMEFRAMES mcPeriod; // Medium Period + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Long Period + ENUM_TIMEFRAMES lcPeriod; // Long Period + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Hind Period + ENUM_TIMEFRAMES hcPeriod; // Hind Period + ENUM_SERIESMODE upperMode; // Peak Method + ENUM_SERIESMODE lowerMode; // Vale Method + ENUM_X_FIBO_LEVELS fiboUpperZoneLevel; // Upper Zone Level + ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel; // Upper Zone Level + ENUM_X_FIBO_LEVELS fiboLowerZoneLevel; // Lower Zone Level + double sarStep; // SAR Step + double sarMax; // SAR Maximum + ENUM_MA_METHOD maMethod; // MA Method + ENUM_APPLIED_PRICE maAppliedTo; // MA Applied To + int maFastLength; // Fast MA Length + int maSlowLength; // Slow MA Length + int maBandLength; // MA Band Length + int zigzagDepth; // ZigZag Depth + int zigzagDeviation; // ZigZag Deviation + int zigzagBackStep; // ZigZag Back Step + ENUM_X_PRICE zigzagUppersMode; // ZigZag High Detect Mode + ENUM_X_PRICE zigzagLowersMode; // ZigZag Low Detect Mode + bool hkIgnoreShadows; // HK Remove noises + int hkSmoothingLength; // HK Smoothing Length + ENUM_X_MA_METHOD hkSmoothingMode; // HK Smoothing Method + int atrLength; // ATR Length + double atrMultiplier; // ATR Band Multiplier + int atrSmoothingLength; // ATR Smoothing Length + ENUM_X_PRICE atrUpperPriceType; // ATR Upper Zone Applied To + ENUM_X_PRICE atrLowerPriceType; // ATR Lower Zone Applied To + ENUM_X_MA_METHOD atrSmoothingMode; // ATR Smoothing Method + + // + // Presentation ... + bool showPV; // Show PV + bool showHK; // Show HK + bool showSAR; // Show Sar + bool showMAFast; // Show MA Fast + bool showMASlow; // Show MA Slow + bool showMABand; // Show MA Band + bool showHKBand; // Show HK Band + bool showATRBand; // Show ATR Band + bool showZigZag; // Show ZigZag + bool showFiboZone; // Show Fibo Zone + int startCalculationForLastBars; // Calculate Last n Bars + int sarArrowCode; // Parabolic Sar Arrow Code + int peakArrowCode; // Peaks Arrow Code + int valeArrowCode; // Vales Arrow Code + + // + // Constructor(s) ... + XFIMAInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // Calculations ... + scMethod = X_PERIOD_AUTO; // How to Find Short Period + scPeriod = NULL; // Short Period + mcMethod = X_PERIOD_AUTO; // How to Find Medium Period + mcPeriod = NULL; // Medium Period + lcMethod = X_PERIOD_AUTO; // How to Find Long Period + lcPeriod = NULL; // Long Period + hcMethod = X_PERIOD_AUTO; // How to Find Hind Period + hcPeriod = NULL; // Hind Period + upperMode = MODE_HIGH; // Peak Method + lowerMode = MODE_LOW; // Vale Method + fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level + fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Upper Zone Level + fiboLowerZoneLevel = X_FIBO_LEVEL_618; // Lower Zone Level + sarStep = 0.02; // SAR Step + sarMax = 0.2; // SAR Maximum + maMethod = MODE_EMA; // MA Method + maAppliedTo = PRICE_CLOSE; // MA Applied To + maFastLength = 7; // Fast MA Length + maSlowLength = 20; // Slow MA Length + maBandLength = 7; // MA Band Length + zigzagDepth = 12; // ZigZag Depth + zigzagDeviation = 5; // ZigZag Deviation + zigzagBackStep = 3; // ZigZag Back Step + zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode + zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode + hkIgnoreShadows = true; // HK Remove noises + hkSmoothingLength = 21; // HK Smoothing Length + hkSmoothingMode = X_MA_MODE_EMA; // HK Smoothing Method + atrLength = 14; // ATR Length + atrMultiplier = 1.5; // ATR Band Multiplier + atrSmoothingLength = 21; // ATR Smoothing Length + atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Zone Applied To + atrLowerPriceType = X_PRICE_LOW; // ATR Lower Zone Applied To + atrSmoothingMode = X_MA_MODE_EMA; // ATR Smoothing Method + + // + // Presentation ... + showPV = true; // Show PV + showHK = true; // Show HK + showSAR = true; // Show Sar + showMAFast = true; // Show MA Fast + showMASlow = true; // Show MA Slow + showMABand = true; // Show MA Band + showHKBand = true; // Show HK Band + showATRBand = true; // Show ATR Band + showZigZag = true; // Show ZigZag + showFiboZone = true; // Show Fibo Zone + startCalculationForLastBars = 1500; // Calculate Last n Bars + sarArrowCode = 159; // Parabolic Sar Arrow Code + peakArrowCode = 159; // Peaks Arrow Code + valeArrowCode = 159; // Vales Arrow Code + } + + // + // Hide all Visible Buffers ... + void Hide() + { + // + showPV = false; + showHK = false; + showSAR = false; + showMAFast = false; + showMASlow = false; + showMABand = false; + showHKBand = false; + showATRBand = false; + showZigZag = false; + showFiboZone = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + // MA ... + maFastLength >= 2 && + maSlowLength >= 2 && + maBandLength >= 2 && + maSlowLength > maFastLength && + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // ATR ... + atrLength > 0 && + atrMultiplier >= 1 && + IsXValid(atrUpperPriceType) && + IsXValid(atrLowerPriceType) && + // + // CYCLES ... + (IsSpecifiedValid(scMethod, scPeriod) && + IsSpecifiedValid(mcMethod, mcPeriod) && + IsSpecifiedValid(lcMethod, lcPeriod) && + IsSpecifiedValid(hcMethod, hcPeriod)) && + // + // ZIGZAG ... + zigzagDepth > 0 && + zigzagDeviation > 0 && + zigzagBackStep > 0 && + // + // Validate Upper Mode Detection ... + IsXValid(zigzagUppersMode) && + // + // Validate Lower Mode Detection ... + IsXValid(zigzagLowersMode) + // + ; + + // + return result; + } +}; + +// +// Conditions ... +struct XFIMAConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + datetime to; + datetime from; + XOHCL bars[]; + + // + // Buffers ... + double maFastBuffer[]; + double maFastColorBuffer[]; + double maFastStateBuffer[]; + double maSlowBuffer[]; + double maSlowColorBuffer[]; + double maSlowStateBuffer[]; + double maBandUpperBuffer[]; + double maBandLowerBuffer[]; + double sarBuffer[]; + double sarColorBuffer[]; + double sarStateBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double fiboUpperBuffer[]; + double fiboMiddleBuffer[]; + double fiboLowerBuffer[]; + double zigzagBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double highsBuffer[]; + double highsTimeBuffer[]; + double lowsBuffer[]; + double lowsTimeBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkLowBuffer[]; + double hkCloseBuffer[]; + double hkColorBuffer[]; + + // + // Conditions ... + + // + // Constructor ... + XFIMAConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + to = NULL; + from = NULL; + time = NULL; + symbol = NULL; + period = NULL; + + // + // Buffers ... + + // + SpecifiedClean(bars); + + // + SpecifiedClean(maFastBuffer); + SpecifiedClean(maFastColorBuffer); + SpecifiedClean(maFastStateBuffer); + SpecifiedClean(maSlowBuffer); + SpecifiedClean(maSlowColorBuffer); + SpecifiedClean(maSlowStateBuffer); + SpecifiedClean(maBandUpperBuffer); + SpecifiedClean(maBandLowerBuffer); + SpecifiedClean(sarBuffer); + SpecifiedClean(sarColorBuffer); + SpecifiedClean(sarStateBuffer); + SpecifiedClean(peakBuffer); + SpecifiedClean(valeBuffer); + SpecifiedClean(fiboUpperBuffer); + SpecifiedClean(fiboMiddleBuffer); + SpecifiedClean(fiboLowerBuffer); + SpecifiedClean(zigzagBuffer); + SpecifiedClean(sHHBuffer); + SpecifiedClean(sLLBuffer); + SpecifiedClean(mHHBuffer); + SpecifiedClean(mLLBuffer); + SpecifiedClean(lHHBuffer); + SpecifiedClean(lLLBuffer); + SpecifiedClean(hHHBuffer); + SpecifiedClean(hLLBuffer); + SpecifiedClean(highsBuffer); + SpecifiedClean(highsTimeBuffer); + SpecifiedClean(lowsBuffer); + SpecifiedClean(lowsTimeBuffer); + SpecifiedClean(hkOpenBuffer); + SpecifiedClean(hkHighBuffer); + SpecifiedClean(hkLowBuffer); + SpecifiedClean(hkCloseBuffer); + SpecifiedClean(hkColorBuffer); + + // + // Conditions ... + + // + ArraySetAsSeries(bars, true); + + // + ArraySetAsSeries(maFastBuffer, true); + ArraySetAsSeries(maFastColorBuffer, true); + ArraySetAsSeries(maFastStateBuffer, true); + ArraySetAsSeries(maSlowBuffer, true); + ArraySetAsSeries(maSlowColorBuffer, true); + ArraySetAsSeries(maSlowStateBuffer, true); + ArraySetAsSeries(maBandUpperBuffer, true); + ArraySetAsSeries(maBandLowerBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(sarColorBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(fiboUpperBuffer, true); + ArraySetAsSeries(fiboMiddleBuffer, true); + ArraySetAsSeries(fiboLowerBuffer, true); + ArraySetAsSeries(zigzagBuffer, false); // Fix this ... + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(highsBuffer, true); + ArraySetAsSeries(highsTimeBuffer, true); + ArraySetAsSeries(lowsBuffer, true); + ArraySetAsSeries(lowsTimeBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(hkColorBuffer, true); + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + return ""; + } + + /** + * Retrieve Unique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetToken(this); + } +}; + +// +// Class ... +class XCXFIMAHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + XCMarketPatternDetector *patternDetector; + + // + // Constructors ... + XCXFIMAHelper() + : XCBaseHelper(_Symbol, _Period) + { + patternDetector = new XCMarketPatternDetector(); + } + + // + // Deconstructor ... + ~XCXFIMAHelper() + { + // + delete patternDetector; + ZeroMemory(patternDetector); + } + + // + // Tools ... + + // + // Initialize Helper Cleass ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XFIMAInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xfima", + "", // Calculation ... + mInputs.scMethod, + mInputs.scPeriod, + mInputs.mcMethod, + mInputs.mcPeriod, + mInputs.lcMethod, + mInputs.lcPeriod, + mInputs.hcMethod, + mInputs.hcPeriod, + mInputs.upperMode, + mInputs.lowerMode, + mInputs.fiboUpperZoneLevel, + mInputs.fiboMiddleZoneLevel, + mInputs.fiboLowerZoneLevel, + mInputs.sarStep, + mInputs.sarMax, + mInputs.maMethod, + mInputs.maAppliedTo, + mInputs.maFastLength, + mInputs.maSlowLength, + mInputs.maBandLength, + mInputs.zigzagDepth, + mInputs.zigzagDeviation, + mInputs.zigzagBackStep, + mInputs.zigzagUppersMode, + mInputs.zigzagLowersMode, + mInputs.hkIgnoreShadows, + mInputs.hkSmoothingLength, + mInputs.hkSmoothingMode, + mInputs.atrLength, + mInputs.atrMultiplier, + mInputs.atrSmoothingLength, + mInputs.atrUpperPriceType, + mInputs.atrLowerPriceType, + mInputs.atrSmoothingMode, + "", // Presentation ... + mInputs.showPV, + mInputs.showHK, + mInputs.showSAR, + mInputs.showMAFast, + mInputs.showMASlow, + mInputs.showMABand, + mInputs.showHKBand, + mInputs.showATRBand, + mInputs.showZigZag, + mInputs.showFiboZone, + mInputs.startCalculationForLastBars, + mInputs.sarArrowCode, + mInputs.peakArrowCode, + mInputs.valeArrowCode + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XFIMAInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XFIMAInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs // + ); + } + + // + // Tools ... + + // + bool GetConditions( + XFIMAConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + // Filling Bars ... + int barsCount = GetBars( + conditions.bars, + mSymbol, + mPeriod, + barIndex, + loopback // + ); + result = barsCount == loopback; + if (!result) + { + // + conditions.Clean(); + + // + return result; + } + + // + int zIDX = 0; + int cIDX = 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + conditions.to = conditions.bars[0].time; + conditions.from = conditions.bars[ArraySize(conditions.bars) - 1].time; + + // + int zIndex = barIndex; + + // + // Buffers ... + + // + CopyMAFast( + zIndex, + loopback, + conditions.maFastBuffer // + ); + + // + CopyMAFastState( + zIndex, + loopback, + conditions.maFastStateBuffer // + ); + + // + CopyMASlow( + zIndex, + loopback, + conditions.maSlowBuffer // + ); + + // + CopyMASlowState( + zIndex, + loopback, + conditions.maSlowStateBuffer // + ); + + // + CopyMABandUpper( + zIndex, + loopback, + conditions.maBandUpperBuffer // + ); + + // + CopyMABandLower( + zIndex, + loopback, + conditions.maBandLowerBuffer // + ); + + // + CopySar( + zIndex, + loopback, + conditions.sarBuffer // + ); + + // + CopySarState( + zIndex, + loopback, + conditions.sarStateBuffer // + ); + + // + CopyPeak( + zIndex, + loopback, + conditions.peakBuffer // + ); + + // + CopyVale( + zIndex, + loopback, + conditions.valeBuffer // + ); + + // + CopyFiboUpper( + zIndex, + loopback, + conditions.fiboUpperBuffer // + ); + + // + CopyFiboMiddle( + zIndex, + loopback, + conditions.fiboMiddleBuffer // + ); + + // + CopyFiboLower( + zIndex, + loopback, + conditions.fiboLowerBuffer // + ); + + // + CopyZigZag( + zIndex, + loopback, + conditions.zigzagBuffer // + ); + + // + CopySHH( + zIndex, + loopback, + conditions.sHHBuffer // + ); + + // + CopySLL( + zIndex, + loopback, + conditions.sLLBuffer // + ); + + // + CopyMHH( + zIndex, + loopback, + conditions.mHHBuffer // + ); + + // + CopyMLL( + zIndex, + loopback, + conditions.mLLBuffer // + ); + + // + CopyLHH( + zIndex, + loopback, + conditions.lHHBuffer // + ); + + // + CopyLLL( + zIndex, + loopback, + conditions.lLLBuffer // + ); + + // + CopyHHH( + zIndex, + loopback, + conditions.hHHBuffer // + ); + + // + CopyHLL( + zIndex, + loopback, + conditions.hLLBuffer // + ); + + // + CopyHKOpen( + zIndex, + loopback, + conditions.hkOpenBuffer // + ); + + // + CopyHKHigh( + zIndex, + loopback, + conditions.hkHighBuffer // + ); + + // + CopyHKLow( + zIndex, + loopback, + conditions.hkLowBuffer // + ); + + // + CopyHKClose( + zIndex, + loopback, + conditions.hkCloseBuffer // + ); + + // + CopyHKColor( + zIndex, + loopback, + conditions.hkColorBuffer // + ); + + // + // Conditions ... + + // + return result; + } + + // + // Pivot Actions ... + + /** + * Check Specified Bar has MA Cross or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... + * + * @return ( bool ) + */ + bool HasMACross( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + double validCrossDiffMultiplier = 1 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double fast[]; + int fastCount = CopyMAFast(barIndex, 2, fast); + + // + double slow[]; + int slowCount = CopyMASlow(barIndex, 2, slow); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + int count = MathMin(fastCount, slowCount); + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + bool notEmpty = + NotEmptyZero(fast[0]) && + NotEmptyZero(fast[1]) && + NotEmptyZero(slow[0]) && + NotEmptyZero(slow[1]); + + // + isBullish = + notEmpty && + fast[0] > slow[0] && + fast[1] < slow[1]; + + // + isBearish = + notEmpty && + fast[0] < slow[0] && + fast[1] > slow[1]; + + // + result = + isBullish || + isBearish; + + // + // Validate Direction Change ... + if (result && + validCrossDiffMultiplier > 0) + { + // + double _points = GetPoints(GetSymbol()); + double diff = MathAbs(fast[0] - slow[0]); + + // + result = diff >= (validCrossDiffMultiplier * _points); + } + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + + // + return result; + } + + /** + * Check Specified Bar Price is In Boundary or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsInBoundary( + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Bar ... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + double value = bar.GetPrice(priceType); + + // + // Read Boundary Values ... + double min; + double max; + result = GetBoundaryValues(min, max, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + result = value < max && + value > min; + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar Price is Over Boundary Min ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsOverBoundaryMin( + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Boundary ... + double min; + double max; + result = GetBoundaryValues(min, max, barIndex); + if (!result) + { + return result; + } + + // + // Retrieve Bar .... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + double value = bar.GetPrice(priceType); + + // + result = value > min; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar Price is Under Boundary Max ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsUnderBoundaryMax( + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Boundary ... + double min; + double max; + result = GetBoundaryValues(min, max, barIndex); + if (!result) + { + return result; + } + + // + // Retrieve Bar .... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + double value = bar.GetPrice(priceType); + + // + result = value < max; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Boundary Fake Breaked or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param overMaxPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * @param underMinPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * + * @return ( bool ) + */ + bool IsBoundaryFakeBreaked( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + ENUM_X_PRICE overMaxPriceType = X_PRICE_NONE, + ENUM_X_PRICE underMinPriceType = X_PRICE_NONE // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(overMaxPriceType)) + { + overMaxPriceType = X_PRICE_CLOSE; + } + if (!IsXValid(underMinPriceType)) + { + underMinPriceType = X_PRICE_CLOSE; + } + + // + // Initial Bars ... + XOHCL bar; + XOHCL pBar; + double min; + double max; + double pMin; + double pMax; + double boundaryValues[]; + result = + bar.Init( + mSymbol, + mPeriod, + barIndex // + ) && + bar.GetPreviousBar(pBar) && + GetBoundaryValues(min, max, barIndex) && + GetBoundaryValues(pMin, pMax, barIndex + 1) && + FillBoundaryValues(boundaryValues, barIndex) > 0; + + // + bool isBullish = + result && + pBar.IsBearish() && + bar.IsBullish() && + pBar.GetPrice(underMinPriceType) < pMin && + bar.GetPrice(underMinPriceType) > min && + (bar.GetPrice(underMinPriceType) > FindLesserThan(max, boundaryValues) || + bar.GetPrice(underMinPriceType) > FindBiggerThan(min + ((max - min) / 2), boundaryValues)); + + // + bool isBearish = + result && + pBar.IsBullish() && + bar.IsBearish() && + pBar.GetPrice(overMaxPriceType) > pMax && + bar.GetPrice(overMaxPriceType) < max && + (bar.GetPrice(overMaxPriceType) < FindBiggerThan(min, boundaryValues) || + bar.GetPrice(overMaxPriceType) < FindLesserThan(min + ((max - min) / 2), boundaryValues)); + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Cleanup ... + bar.Clean(); + pBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar's Price in Hot Place or Not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param overMaxPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * @param underMinPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... + * + * @return ( bool ) + */ + bool IsInHotPlace( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + ENUM_X_PRICE overMaxPriceType = X_PRICE_NONE, + ENUM_X_PRICE underMinPriceType = X_PRICE_NONE // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + if (!IsXValid(overMaxPriceType)) + { + overMaxPriceType = X_PRICE_LOW; + } + if (!IsXValid(underMinPriceType)) + { + underMinPriceType = X_PRICE_HIGH; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Initialize Bar ... + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double overMaxPrice = bar.GetPrice(overMaxPriceType); + double underMinPrice = bar.GetPrice(underMinPriceType); + + // + // Reading Boundary Value ... + double min; + double max; + result = GetBoundaryValues( + min, + max, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + bool isBullish = underMinPrice < min; + bool isBearish = overMaxPrice > max; + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + bar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar price Crossed in Boundary or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to hold Crossed in Dir ... + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsCrossedInBoundary( + ENUM_X_DIRECTION &dir, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + int pBarIndex = barIndex + 1; + + // + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Check PrevBar Is in Hot Place ... + result = IsInHotPlace( + dir, + pBarIndex, + X_PRICE_LOW, + X_PRICE_HIGH // + ); + if (!result) + { + // + dir = X_DIRECTION_NONE; + + // + return result; + } + + // + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + // Current Bar must Into Boundary ... + result = IsInBoundary(priceType, barIndex); + if (!result) + { + dir = X_DIRECTION_NONE; + } + + // + result = HasDirection(dir); + + // + return result; + } + + /** + * Check Specified Bar price Crossed out Boundary or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to hold Crossed in Dir ... + * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsCrossedOutBoundary( + ENUM_X_DIRECTION &dir, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + int pBarIndex = barIndex + 1; + + // + if (!IsXValid(priceType)) + { + priceType = X_PRICE_CLOSE; + } + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Prev Bar Must in Boundary ... + bool isBullish = IsInBoundary(X_PRICE_LOW, pBarIndex); + bool isBearish = IsInBoundary(X_PRICE_HIGH, pBarIndex); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Current Bar must Out of Boundary ... + + XOHCL bar; + result = bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + + // + isBullish = + result && + isBullish && + bar.IsBullish() && + !IsInBoundary(priceType, barIndex); + + // + isBearish = + result && + isBearish && + bar.IsBearish() && + !IsInBoundary(priceType, barIndex); + + // + result = isBullish || + isBearish; + if (!result) + { + // + bar.Clean(); + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = HasDirection(dir); + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar has Boundary Trend or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasBoundaryTrend( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double fast = GetMAFast(barIndex); + double slow = GetMASlow(barIndex); + + // + double maBandUpper = GetMABandUpper(barIndex); + double maBandLower = GetMABandLower(barIndex); + + // + double pbBandUpper = GetPBBandUpper(barIndex); + double pbBandLower = GetPBBandLower(barIndex); + + // + double hkBandUpper = GetHKBandUpper(barIndex); + double hkBandLower = GetHKBandLower(barIndex); + + // + result = + NotEmptyZero(fast) && + NotEmptyZero(slow) && + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower); + if (!result) + { + return result; + } + + // + bool isBullish = + fast > hkBandLower && + slow > hkBandLower && + maBandUpper > hkBandLower && + maBandLower > hkBandLower && + pbBandUpper > hkBandLower && + pbBandLower > hkBandLower; + bool isBearish = + fast < hkBandUpper && + slow < hkBandUpper && + maBandUpper < hkBandUpper && + maBandLower < hkBandUpper && + pbBandUpper < hkBandUpper && + pbBandLower < hkBandUpper; + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + /** + * Check Specified Bar has Boundary Trend Switched or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasBoundarySwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + result = HasBoundaryTrend( + dir, + barIndex // + ); + if (!result) + { + return result; + } + bool isBullish = IsXBullish(dir); + bool isBearish = IsXBearish(dir); + + // + result = HasBoundaryTrend( + dir, + barIndex + 1 // + ); + if (!result) + { + return result; + } + bool isPBullish = IsXBullish(dir); + bool isPBearish = IsXBearish(dir); + + // + bool isSwitchedToBullish = + isBullish && !isPBullish; + bool isSwitchedToBearish = + isBearish && !isPBearish; + result = isSwitchedToBullish || + isSwitchedToBearish; + if (result) + { + // + dir = isSwitchedToBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + /** + * Check Fibo Section is Changed or not ... + * + * @param dir: reference to hold section change direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsFiboSectionChanged( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + // Reading Values ... + + // + double iFiboUpper = GetFiboUpper(barIndex); + double pFiboUpper = GetFiboUpper(barIndex + 1); + + // + double iFiboMiddle = GetFiboMiddle(barIndex); + double pFiboMiddle = GetFiboMiddle(barIndex + 1); + + // + double iFiboLower = GetFiboLower(barIndex); + double pFiboLower = GetFiboLower(barIndex + 1); + + // + isBullish = iFiboLower >= pFiboMiddle && + iFiboMiddle >= pFiboUpper; + isBearish = iFiboUpper <= pFiboMiddle && + iFiboMiddle <= pFiboLower; + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (!result) + { + return result; + } + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + /** + * Check for Fibo Push Exists or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to hold result ... + * @param barIndex: int, Specified Bar Index ... + * @param validationLength: int, Validation Length ... + * + * @return ( bool ) + */ + bool HasFiboPush( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + int validationLength = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 3); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + XOHCL iBar; + bool isBullish = false; + bool isBearish = false; + + // + double iFiboUpper = EMPTY_VALUE; + double pFiboUpper = EMPTY_VALUE; + + // + double iFiboMiddle = EMPTY_VALUE; + double pFiboMiddle = EMPTY_VALUE; + + // + double iFiboLower = EMPTY_VALUE; + double pFiboLower = EMPTY_VALUE; + + // + // Check Zone Validation ... + int start = barIndex; + int end = start + validationLength; + for (int i = start; i < end; i++) + { + // + // Reading Values ... + + // + iFiboUpper = GetFiboUpper(i); + pFiboUpper = GetFiboUpper(i + 1); + + // + iFiboMiddle = GetFiboMiddle(i); + pFiboMiddle = GetFiboMiddle(i + 1); + + // + iFiboLower = GetFiboLower(i); + pFiboLower = GetFiboLower(i + 1); + + // + result = iFiboUpper == pFiboUpper; + if (!result) + { + break; + } + } + + // + if (result) + { + // + result = iBar.Init( + mSymbol, + mPeriod, + barIndex // + ); + + // + if (result) + { + // + iFiboUpper = GetFiboUpper(barIndex); + iFiboMiddle = GetFiboMiddle(barIndex); + iFiboLower = GetFiboLower(barIndex); + + // + isBullish = iBar.IsBullish() && + iBar.close > iFiboLower && + iBar.low < iFiboLower; + isBearish = iBar.IsBearish() && + iBar.close < iFiboUpper && + iBar.high > iFiboUpper; + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; + } + + /** + * Check Has Higher Low Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ + bool HasZigZagHigherLow( + int barIndex = 0, + bool forceBarValidation = false // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsVale(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot vales[]; + count = ExtractPivots( + vales, + pivots, + X_PIVOT_TYPE_VALE // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + vales[0].value > vales[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open > vales[0].value && + bar.close > vales[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; + } + + /** + * Check Has Lower Low Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ + bool HasZigZagLowerLow( + int barIndex = 0, + bool forceBarValidation = false // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsVale(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot vales[]; + count = ExtractPivots( + vales, + pivots, + X_PIVOT_TYPE_VALE // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + vales[0].value < vales[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open < vales[0].value && + bar.close < vales[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(vales); + XClean(pivots); + + // + return result; + } + + /** + * Check Has Higher High Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ + bool HasZigZagHigherHigh( + int barIndex = 0, + bool forceBarValidation = false // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsPeak(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot peaks[]; + count = ExtractPivots( + peaks, + pivots, + X_PIVOT_TYPE_PEAK // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + peaks[0].value > peaks[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open > peaks[0].value && + bar.close > peaks[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; + } + + /** + * Check Has Lower High Based On ZigZag ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ + bool HasZigZagLowerHigh( + int barIndex = 0, + bool forceBarValidation = false // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + XOHCL bar; + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsPeak(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot peaks[]; + count = ExtractPivots( + peaks, + pivots, + X_PIVOT_TYPE_PEAK // + ); + result = IsValidSize(count) && + count >= 2; + if (!result) + { + // + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; + } + + // + // Check Result ... + result = + peaks[0].value < peaks[1].value; + if (forceBarValidation) + { + // + result = + result && + bar.open < peaks[0].value && + bar.close < peaks[0].value; + } + + // + // Cleanup ... + bar.Clean(); + XClean(peaks); + XClean(pivots); + + // + return result; + } + + // + // SAR ... + + /** + * Check Specified Bar has SAR Switch or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasSARSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double sars[]; + int count = CopySarState(barIndex, 2, sars); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + isBullish = + sars[0] >= 1 && + sars[1] <= -1; + + // + isBearish = + sars[0] <= -1 && + sars[1] >= 1; + + // + result = + isBullish || + isBearish; + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(sars); + + // + return result; + } + + bool IsSarBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = GetSarState(barIndex); + result = state >= 1; + + // + return result; + } + + bool IsSarBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = GetSarState(barIndex); + result = state <= -1; + + // + return result; + } + + bool IsSarSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + int pBarIndex = barIndex + 1; + + // + bool isBullish = IsSarBullish(barIndex); + bool isPBullish = IsSarBullish(pBarIndex); + + // + result = isBullish && + !isPBullish; + + // + return result; + } + + bool IsSarSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + int pBarIndex = barIndex + 1; + + // + bool isBearish = IsSarBearish(barIndex); + bool isPBearish = IsSarBearish(pBarIndex); + + // + result = isBearish && + !isPBearish; + + // + return result; + } + + // + // PV ... + + bool IsPeakSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double iC = GetPeak(barIndex); + double iP = GetPeak(barIndex + 1); + + // + result = iC == iP && + NotEmptyZero(iC); + + // + return result; + } + + bool IsValeSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double iC = GetVale(barIndex); + double iP = GetVale(barIndex + 1); + + // + result = iC == iP && + NotEmptyZero(iC); + + // + return result; + } + + /** + * Check Peak Happens over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsPeakOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iPeak = GetPeak(barIndex); + double pPeak = GetPeak(barIndex + 1); + + // + result = NotEmptyZero(iPeak) && + iPeak > pPeak; + + // + return result; + } + + /** + * Check Vale Happens over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsValeOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iVale = GetVale(barIndex); + double pVale = GetVale(barIndex + 1); + + // + result = NotEmptyZero(iVale) && + iVale > pVale; + + // + return result; + } + + /** + * Check Peak Happens under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsPeakUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iPeak = GetPeak(barIndex); + double pPeak = GetPeak(barIndex + 1); + + // + result = NotEmptyZero(iPeak) && + iPeak < pPeak; + + // + return result; + } + + /** + * Check Vale Happens under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsValeUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iVale = GetVale(barIndex); + double pVale = GetVale(barIndex + 1); + + // + result = NotEmptyZero(iVale) && + iVale < pVale; + + // + return result; + } + + /** + * Detect Last Peak Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastPeakOverLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsPeakOverLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Peak Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastPeakUnderLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsPeakUnderLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Vale Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastValeOverLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsValeOverLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Vale Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastValeUnderLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsValeUnderLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Count Same Peaks ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountSamePeaks( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + double iPeak = EMPTY_VALUE; + double peak = GetPeak(barIndex); + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + iPeak = GetPeak(idx); + has = peak == iPeak; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Same Vales ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountSameVales( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + double iVale = EMPTY_VALUE; + double vale = GetVale(barIndex); + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + iVale = GetVale(idx); + has = vale == iVale; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + bool HasPVConsolidationZone( + XBoxZone &zone, + int barIndex = 0, + bool forcePVBreak = false, + bool forceHasSarSwitch = false // + ) + { + // + bool result = false; + + // + // Prepare ... + zone.Clean(); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + bool isPeakSame = IsPeakSame(barIndex); + bool isValeSame = IsValeSame(barIndex); + result = !(isPeakSame && + isValeSame); + if (!result) + { + return result; + } + + // + double iPeak = EMPTY_VALUE; + double iVale = EMPTY_VALUE; + + // + int idx = barIndex; + bool canLookup = true; + while (canLookup) + { + // + idx++; + isPeakSame = IsPeakSame(idx); + isValeSame = IsValeSame(idx); + result = isPeakSame && + isValeSame; + if (!result) + { + // + zone.from = GetBarTime(mSymbol, mPeriod, idx); + break; + } + + // + if (idx == barIndex + 1) + { + // + zone.to = GetBarTime( + mSymbol, + mPeriod, + idx // + ); + } + + // + zone.from = GetBarTime( + mSymbol, + mPeriod, + idx // + ); + + // + iPeak = GetPeak(idx); + iVale = GetVale(idx); + + // + zone.lower = + !NotEmptyZero(zone.lower) + ? iVale + : MathMin(zone.lower, iVale); + + // + zone.upper = + !NotEmptyZero(zone.upper) + ? iPeak + : MathMax(zone.upper, iPeak); + } + + // + // Validating Zone Params ... + result = + // + IsXValid(zone.to) && + IsXValid(zone.from) && + zone.from < zone.to && + // + NotEmptyZero(zone.lower) && + NotEmptyZero(zone.upper) && + zone.upper > zone.lower + // + ; + + // + // Prepare Zone ... + if (result) + { + // + iPeak = GetPeak(barIndex); + iVale = GetVale(barIndex); + bool isPeakOverLast = IsPeakOverLast(barIndex); + bool isValeUnderLast = IsValeUnderLast(barIndex); + bool isValeBreak = iVale < zone.lower; + bool isPeakBreak = iPeak > zone.upper; + bool isPVBreak = isPeakBreak || + isValeBreak; + + // + zone.at = GetBarTime(mSymbol, mPeriod, barIndex); + zone.symbol = mSymbol; + zone.period = mPeriod; + zone.dir = (isPeakOverLast && !isValeUnderLast && isPVBreak) + ? X_DIRECTION_BULLISH + : (isValeUnderLast && !isPeakOverLast && isPVBreak) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION); + + // + // Refine Zone Upper and Lower ... + if (zone.IsValid()) + { + // + XOHCL iBar; + int zoneLoopback = zone.FromIndex() - zone.ToIndex(); + result = zone.ToBar(iBar) && + IsValidSize(zoneLoopback); + if (result) + { + // + double zoneLL = iBar.FindLowest(zoneLoopback, MODE_LOW); + double zoneHH = iBar.FindHighest(zoneLoopback, MODE_HIGH); + result = NotEmptyZero(zoneLL) && + NotEmptyZero(zoneHH); + if (result) + { + // + zone.lower = zone.lower == zoneLL + ? zone.lower + : MathMax(zone.lower, zoneLL); + + // + zone.upper = zone.upper == zoneHH + ? zone.upper + : MathMin(zone.upper, zoneHH); + } + } + + // + iBar.Clean(); + } + + // + // Validate ... + result = zone.IsValid(); + } + + // + // Validate Zones From ... + if (result) + { + // + int idx = zone.FromIndex(); + + // + iPeak = GetPeak(idx); + iVale = GetVale(idx); + + // + bool isValeOverLast = IsValeOverLast(idx); + bool isPeakUnderLast = IsPeakUnderLast(idx); + + // + result = + result && + (zone.IsBullish() + ? !isPeakUnderLast + : zone.IsBearish() + ? !isValeOverLast + : false); + } + + // + // Apply Forces ... + + // + // PV Break ... + // Peak or Vale must Breaked at Bar ... + if (result && forcePVBreak) + { + // + bool isPVBreaked = + (zone.IsBullish() && IsPeakOverLast(barIndex)) || + (zone.IsBearish() && IsValeUnderLast(barIndex)); + + // + result = result && + isPVBreaked; + } + + // + // Other Loop based Forces ... + if (result && (forceHasSarSwitch)) + { + + // + bool hasSarSwitch = false; + + // + int start = zone.ToIndex(); + int end = zone.FromIndex(); + for (int i = start; i <= end; i++) + { + // + // Check Sar Switches ... + if (forceHasSarSwitch && !hasSarSwitch) + { + // + hasSarSwitch = + zone.IsBullish() + ? IsSarSwitchedToBullish(i) + : IsSarSwitchedToBearish(i); + } + } + + // + // Validate Forces ... + if (forceHasSarSwitch) + { + // + result = + result && + hasSarSwitch; + } + } + + // + // Cleanup ... + if (!result) + { + zone.Clean(); + } + + // + return result; + } + + // + // HK ... + + /** + * Check Specified Bar has HK Switch or not ... + * + * @param dir: reference for holds cross Direction ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasHKSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + double open[]; + int openCount = CopyHKOpen(barIndex, 2, open); + + // + double close[]; + int closeCount = CopyHKClose(barIndex, 2, close); + + // + bool isBullish = false; + bool isBearish = false; + + // + // Validate Readed Values ... + int count = MathMin(openCount, closeCount); + result = IsValidSize(count) && count >= 2; + if (result) + { + // + // Detect Direction Change ... + + // + bool notEmpty = + NotEmptyZero(open[0]) && + NotEmptyZero(open[1]) && + NotEmptyZero(close[0]) && + NotEmptyZero(close[1]); + + // + isBullish = + notEmpty && + open[0] < close[0] && + open[1] > close[1]; + + // + isBearish = + notEmpty && + open[0] > close[0] && + open[1] < close[1]; + + // + result = + isBullish || + isBearish; + } + + // + if (result) + { + // + // Setting Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Cleanup Resources ... + XClean(open); + XClean(close); + + // + return result; + } + + /** + * Check Specified Bar has HK Band Based Trend or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to holds trend direction, if exists ... + * @param barIndex: int, Specified Bar Index ... + * @param validationLength: int, validation of trend ... + * + * @return ( bool ) + */ + bool HasHKBasedTrend( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + int validationLength = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 1); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Define Requirements ... + XOHCL iBar; + double hkUpper; + double hkLower; + bool has = false; + int bullishCount = 0; + int bearishCount = 0; + bool isBullish = false; + bool isBearish = false; + + // + // Count Bullish/Bearish Directions ... + int start = barIndex + 1; + int end = start + validationLength; + for (int i = start; i < end; i++) + { + // + // Reading Requirements ... + + // + // Read Indexed Bar ... + iBar.Clean(); + result = iBar.Init( + mSymbol, + mPeriod, + i // + ); + if (!result) + { + break; + } + + // + // Reading Values ... + hkUpper = GetHKBandUpper(i); + hkLower = GetHKBandLower(i); + result = NotEmptyZero(hkUpper) && + NotEmptyZero(hkLower); + if (!result) + { + return result; + } + + // + // Check Trend ... + + // + // Bullish ... + isBullish = iBar.low > hkLower; + if (isBullish) + { + bullishCount++; + } + + // + // Bearish ... + isBearish = iBar.high < hkUpper; + if (isBearish) + { + bearishCount++; + } + + // + iBar.Clean(); + + // + } + + // + // Validate Results ... + isBullish = + bullishCount >= validationLength; + isBearish = + bearishCount >= validationLength; + + // + result = (isBullish && !isBearish) || + (isBearish && !isBullish); + + // + // Setting Direction if Has Trend ... + if (result) + { + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar has HK Band Based Trend Switch or not ... + * + * @param dir: ENUM_X_DIRECTION, reference to holds trend direction, if exists ... + * @param barIndex: int, Specified Bar Index ... + * @param validationLength: int, validation of trend ... + * + * @return ( bool ) + */ + bool IsHKBasedTrendSwitch( + ENUM_X_DIRECTION &dir, + int barIndex = 0, + int validationLength = 5 // + ) + { + // + bool result = false; + + // + // Prepare ... + dir = X_DIRECTION_NONE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + validationLength = NormalizeInt(validationLength, 1); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + bool hasTrend = HasHKBasedTrend( + dir, + barIndex, + validationLength // + ); + bool isBullish = hasTrend && + IsXBullish(dir); + bool isBearish = hasTrend && + IsXBearish(dir); + + // + bool hasPTrend = HasHKBasedTrend( + dir, + barIndex + 1, + validationLength // + ); + bool isPBullish = hasPTrend && + IsXBullish(dir); + bool isPBearish = hasPTrend && + IsXBearish(dir); + + // + dir = X_DIRECTION_NONE; + + // + // Checking Result ... + isBullish = isBullish && !isPBullish; + isBearish = isBearish && !isPBearish; + + // + result = + (isBullish && !isBearish) || + (isBearish && !isBullish); + if (result) + { + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup ... + + // + return result; + } + + /** + * Check if Price Over HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsOverHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandUpper(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check if Price Over HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsOverHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandLower(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check if Price Under HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsUnderHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandUpper(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check if Price Under HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsUnderHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + XOHCL bar; + result = bar.Init(mSymbol, mPeriod, barIndex); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + double price = bar.GetPrice(priceType); + double value = GetHKBandLower(barIndex); + result = NotEmptyZero(price) && + NotEmptyZero(value) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price Switched Over HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsSwitchedOverHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsOverHKBandUpper(priceType, barIndex); + bool isPBarPassed = !IsOverHKBandUpper(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; + } + + /** + * Check Price Switched Under HK Band Upper or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsSwitchedUnderHKBandUpper( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsUnderHKBandUpper(priceType, barIndex); + bool isPBarPassed = !IsUnderHKBandUpper(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; + } + + /** + * Check Price Switched Over HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsSwitchedOverHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_LOW, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsOverHKBandLower(priceType, barIndex); + bool isPBarPassed = !IsOverHKBandLower(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; + } + + /** + * Check Price Switched Under HK Band Lower or not ... + * + * @param priceType: ENUM_X_PRICE, Specified Price type ... + * @param barIndex: int, Specified Bar index ... + * + * @return ( bool ) + */ + bool IsSwitchedUnderHKBandLower( + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int pBarIndex = barIndex + 1; + bool isBarPassed = IsUnderHKBandLower(priceType, barIndex); + bool isPBarPassed = !IsUnderHKBandLower(priceType, pBarIndex); + + // + result = isBarPassed && isPBarPassed; + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastOverHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsOverHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastUnderHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsUnderHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastOverHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsOverHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band ... + * + * @param index: int, reference to holds index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastUnderHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsUnderHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSwitchedOverHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedOverHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSwitchedUnderHKBandUpper( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedUnderHKBandUpper(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSwitchedOverHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedOverHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Detect Previous HK Band Switch ... + * + * @param index: int, reference to holds switched index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastSwitchedUnderHKBandLower( + int &index, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + // Do ... + + // + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsSwitchedUnderHKBandLower(priceType, idx); + if (result) + { + // + index = idx - 1; + break; + } + } + + // + result = IsValidIndex(index); + + // + // Cleanup ... + + // + return result; + } + + /** + * Count Over HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountOverHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(mSymbol, mPeriod, idx); + if (!has) + { + break; + } + + // + iValue = GetHKBandLower(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice > iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Under HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountUnderHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(mSymbol, mPeriod, idx); + if (!has) + { + break; + } + + // + iValue = GetHKBandLower(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice < iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Over HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountOverHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(mSymbol, mPeriod, idx); + if (!has) + { + break; + } + + // + iValue = GetHKBandUpper(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice > iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Under HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountUnderHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(mSymbol, mPeriod, idx); + if (!has) + { + break; + } + + // + iValue = GetHKBandUpper(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice < iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + // + // ZigZag Pivots With Liquidity ... + + /** + * Check ZigZag has Lower Low by Liquidity or Not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ + bool HasZigZagLowerLowByLiquidity( + int barIndex = 0, + bool forceBarValidation = false // + ) + { + // + bool result = false; + + // + // Normalize ... + XOHCL bar; + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsVale(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot selected[]; + count = ExtractPivots( + selected, + pivots, + X_PIVOT_TYPE_VALE // + ); + result = IsValidSize(count) && + count >= 3; + if (!result) + { + // + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; + } + + // + // Do Calculations ... + result = + // + // Check Pivot ... + selected[0].value < selected[1].value && + // + // Check Liquidity ... + selected[1].value > selected[2].value && + // + // Check Bar Place ... + (!forceBarValidation + ? true + : bar.open > selected[0].value && + bar.close > selected[0].value); + + // + // Cleanup ... + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; + } + + /** + * Check ZigZag has Higher High by Liquidity or Not ... + * + * @param barIndex: int, Specified Bar Index ... + * @param forceBarValidation: bool, Force Bar Price based on Pivot ... + * + * @return ( bool ) + */ + bool HasZigZagHigherHighByLiquidity( + int barIndex = 0, + bool forceBarValidation = false // + ) + { + // + bool result = false; + + // + // Normalize ... + XOHCL bar; + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + bar.Init( + mSymbol, + mPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + // Extract Pivots ... + XPivot pivots[]; + int count = ExtractZigZagPivots( + pivots, + barIndex, + 10, + 200 // + ); + + // + // Validate Pivots and Nearest Pivot is Low ... + result = IsValidSize(count) && + pivots[0].IsPeak(); + if (!result) + { + // + bar.Clean(); + XClean(pivots); + + // + return result; + } + + // + // Extract Directional Pivots ... + XPivot selected[]; + count = ExtractPivots( + selected, + pivots, + X_PIVOT_TYPE_PEAK // + ); + result = IsValidSize(count) && + count >= 3; + if (!result) + { + // + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; + } + + // + // Do Calculations ... + result = + // + // Check Pivot ... + selected[0].value > selected[1].value && + // + // Check Liquidity ... + selected[1].value < selected[2].value && + // + // Check Bar Place ... + (!forceBarValidation + ? true + : bar.open < selected[0].value && + bar.close < selected[0].value); + + // + // Cleanup ... + bar.Clean(); + XClean(pivots); + XClean(selected); + + // + return result; + } + + // + // Extractions ... + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( int ) + */ + int ExtractPVPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + bool lookupPeaks = true; + bool lookupVales = true; + + // + XOHCL iBar; + XPivot iPivot; + bool has = false; + int idx = barIndex - 1; + int samePeaksCount = 0; + int sameValesCount = 0; + double tmpPeaksBuffer[]; + double tmpValesBuffer[]; + string symbol = GetSymbol(); + double iPValue = EMPTY_VALUE; + double iVValue = EMPTY_VALUE; + double pPValue = EMPTY_VALUE; + double pVValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + if (!has) + { + continue; + } + + // + // Detecting ... + + // + // Peak ... + if (lookupPeaks) + { + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_PEAK_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpPeaksBuffer // Buffer ... + ); + ArraySetAsSeries(tmpPeaksBuffer, true); + + // + // Reading Values ... + iPValue = tmpPeaksBuffer[0]; + pPValue = tmpPeaksBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iPValue)) + { + // + // Check New Peak ... + has = + !NotEmptyZero(pPValue) + ? true + : iPValue != pPValue; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + iPValue == iBar.high + ? X_PIVOT_TYPE_PEAK + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // Check Validation Length ... + has = + has && + (validationLength <= 0 + ? true + : samePeaksCount >= validationLength); + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iPValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_PV); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + samePeaksCount = 0; + } + else if (iPValue == pPValue) + { + samePeaksCount++; + } + } + } + + // + // Vale ... + if (lookupVales) + { + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_VALE_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpValesBuffer // Buffer ... + ); + ArraySetAsSeries(tmpValesBuffer, true); + + // + // Reading Values ... + iVValue = tmpValesBuffer[0]; + pVValue = tmpValesBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iVValue)) + { + // + // Check New Vale ... + has = + !NotEmptyZero(pVValue) + ? true + : iVValue != pVValue; + if (has) + { + // + // Calculate and Validate Type ... + // Vales Only Valid when Confirmed by Bar Low ... + iType = + iVValue == iBar.low + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + // Check Validation Length ... + has = + has && + (validationLength <= 0 + ? true + : sameValesCount >= validationLength); + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iVValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_PV); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + sameValesCount = 0; + } + else if (iVValue == pVValue) + { + sameValesCount++; + } + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpPeaksBuffer); + SpecifiedClean(tmpValesBuffer); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractMAPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + double validCrossDiffMultiplier = 1, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + double fast[]; + double slow[]; + XPivot iPivot; + int count = 0; + bool has = false; + int idx = barIndex - 1; + datetime iPivotTime = NULL; + string symbol = GetSymbol(); + double iFValue = EMPTY_VALUE; + double pFValue = EMPTY_VALUE; + double iSValue = EMPTY_VALUE; + double pSValue = EMPTY_VALUE; + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + double iSelectedValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + XClean(fast); + XClean(slow); + iPivot.Clean(); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Reading Buffer ... + int fastCount = CopyMAFast(idx, 2, fast); + int slowCount = CopyMASlow(idx, 2, slow); + count = MathMin(fastCount, slowCount); + has = IsValidSize(count); + + // + // Reading Values ... + + // + iFValue = fast[0]; + pFValue = fast[1]; + + // + iSValue = slow[0]; + pSValue = slow[1]; + + // + // Validate Value ... + has = + HasMACross( + iDir, + idx, + validCrossDiffMultiplier // + ) && + NotEmptyZero(iFValue) && + NotEmptyZero(iSValue) && + NotEmptyZero(pFValue) && + NotEmptyZero(pSValue); + if (has) + { + // + // Check Direction Changed ... + isSwitchedToBullish = IsXBullish(iDir); + isSwitchedToBearish = IsXBearish(iDir); + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + iPivotTime = GetBarTime( + symbol, + period, + idx // + ); + + // + // Select Value based on Pivot Type ... + iSelectedValue = IsXPeak(iType) + ? MathMax(iFValue, iSValue) + : MathMin(iFValue, iSValue); + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iSelectedValue, + iPivotTime, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_MA_CROSS); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + iPivot.Clean(); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + XClean(fast); + XClean(slow); + iPivot.Clean(); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractHKPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + double open[]; + XPivot iPivot; + int count = 0; + double close[]; + bool has = false; + int idx = barIndex - 1; + datetime iPivotTime = NULL; + string symbol = GetSymbol(); + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + double iSelectedValue = EMPTY_VALUE; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + XClean(open); + XClean(close); + iPivot.Clean(); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Reading Buffer ... + int openCount = CopyHKOpen(idx, 2, open); + int closeCount = CopyHKClose(idx, 2, close); + count = MathMin(openCount, closeCount); + has = IsValidSize(count); + + // + // Validate Value ... + has = + HasHKSwitch( + iDir, + idx // + ) && + NotEmptyZero(open[0]) && + NotEmptyZero(open[1]) && + NotEmptyZero(close[0]) && + NotEmptyZero(close[1]); + if (has) + { + // + // Check Direction Changed ... + isSwitchedToBullish = IsXBullish(iDir); + isSwitchedToBearish = IsXBearish(iDir); + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_HK); + + // + iPivotTime = GetBarTime( + symbol, + period, + idx // + ); + + // + // Select Value based on Pivot Type ... + iSelectedValue = IsXPeak(iType) + ? MathMax(open[0], close[0]) + : MathMin(open[0], close[0]); + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iSelectedValue, + iPivotTime, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + XClean(open); + XClean(close); + iPivot.Clean(); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + XClean(open); + XClean(close); + iPivot.Clean(); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractSARPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + XOHCL iBar; + XOHCL pBar; + XPivot iPivot; + bool has = false; + double tmpSarBuffer[]; + int idx = barIndex - 1; + string symbol = GetSymbol(); + double iValue = EMPTY_VALUE; + double pValue = EMPTY_VALUE; + bool isSwitchedToBullish = false; + bool isSwitchedToBearish = false; + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + has = + has && + iBar.GetPreviousBar(pBar); + if (!has) + { + continue; + } + + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_SAR_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 2, // Number of Requirements ... + tmpSarBuffer // Buffer ... + ); + ArraySetAsSeries(tmpSarBuffer, true); + + // + // Reading Values ... + iValue = tmpSarBuffer[0]; + pValue = tmpSarBuffer[1]; + + // + // Validate Value ... + if (NotEmptyZero(iValue)) + { + // + // Check Sar Direction Changed ... + isSwitchedToBullish = iValue < iBar.low && + pValue > pBar.high; + isSwitchedToBearish = iValue > iBar.high && + pValue < pBar.low; + has = + isSwitchedToBullish || + isSwitchedToBearish; + if (has) + { + // + // Calculate and Validate Type ... + // Peaks Only Valid when Confirmed by Bar High ... + iType = + isSwitchedToBearish + ? X_PIVOT_TYPE_PEAK + : isSwitchedToBullish + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + + // + // Calculate and Validate Dir ... + iDir = IsXPeak(iType) + ? X_DIRECTION_BEARISH + : IsXVale(iType) + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + has = has && + HasDirection(iDir); + + // + if (has) + { + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_SAR_SWITCH); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + } + + // + // Cleanup Resources ... + iPivot.Clean(); + } + } + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + pBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpSarBuffer); + + // + return result; + } + + /** + * Extract Specified Kind of Pivots ... + * + * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( int ) + */ + int ExtractZigZagPivots( + XPivot &pivots[], + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(pivots); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + if (mHandler == INVALID_HANDLE) + { + return result; + } + + // + XOHCL iBar; + XPivot iPivot; + bool has = false; + int idx = barIndex - 1; + double tmpZigZagBuffer[]; + double iValue = EMPTY_VALUE; + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; + int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; + while (idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots) + { + // + idx++; + + // + // Prepare ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Ignore First Item ... + if (idx == barIndex) + { + continue; + } + + // + // Initialize Bar ... + has = iBar.Init( + symbol, + period, + idx // + ); + if (!has) + { + continue; + } + + // + // Reading Buffer ... + CopyBuffer( + mHandler, // Handler ... + XFIMA_ZIGZAG_LINE, // Handler Buffer Number ... + idx, // Bar Index ... + 1, // Number of Requirements ... + tmpZigZagBuffer // Buffer ... + ); + ArraySetAsSeries(tmpZigZagBuffer, true); + + // + // Read and Validate Value ... + iValue = tmpZigZagBuffer[0]; + has = NotEmptyZero(iValue); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Calculate and Validate Type ... + iType = + iValue == iBar.high + ? X_PIVOT_TYPE_PEAK + : iValue == iBar.low + ? X_PIVOT_TYPE_VALE + : X_PIVOT_TYPE_NONE; + has = IsXValid(iType); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Calculate and Validate Dir ... + iDir = + IsXVale(iType) + ? X_DIRECTION_BULLISH + : IsXPeak(iType) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(iDir); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + continue; + } + + // + // Initialize and Validate Pivot ... + has = iPivot.Init( + iValue, + iBar.time, + symbol, + iDir, + period, + iType // + ); + if (has) + { + // + iPivot.prefix = ToXString(XFIMA_PIVOT_ZIGZAG); + + // + // Add Pivot to Collection only if not Exists ... + AddIfNotExists( + iPivot, + pivots // + ); + } + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Check Moving Forward Condition ... + has = + idx < maxAllowed && + ArraySize(pivots) < requiredNumberOFPivots; + if (!has) + { + break; + } + } + + // + result = ArraySize(pivots); + + // + // Cleanup Resources ... + iBar.Clean(); + iPivot.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + return result; + } + + /** + * Extract Validated Zones ... + * + * @param zones: XBoxZone, collection reference to holds results ... + * @param barIndex: int, Specified Bar Index ... + * @param requiredNumberOFZones: int, required Number of Zones ... + * @param breakValidLength: int, Breake Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * @param shadowMultiplier: double a Shadow Multiplier for Validation ... + * @param validationStrength: double, Minimum Strngth Multiplier in Point to Validate ... + * @param validationLength: int, Validation Length of Zones ... + * @param maxAllowedLoopbackLength: int, max Allowed Loopback Length ... + * + * @return ( int ) + */ + int ExtractHKZones( + XBoxZone &zones[], + int barIndex = 0, + int requiredNumberOFZones = 50, + int breakValidLength = 3, + bool validateFakeBreakes = true, + double shadowMultiplier = 3, + double validationStrength = 1, + int validationLength = 21, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + SpecifiedClean(zones); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + validationLength = NormalizeInt(validationLength, 7); + shadowMultiplier = NormalizeDouble(shadowMultiplier, 1); + validationStrength = NormalizeDouble(validationStrength, 1); + requiredNumberOFZones = NormalizeInt(requiredNumberOFZones, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 100); + + // + // Reading Values ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + double minAllowedStrength = (validationStrength * GetPoints(symbol)); + + // + int count = 0; + XBoxZone zone; + bool has = false; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + double up = EMPTY_VALUE; + double low = EMPTY_VALUE; + double open = EMPTY_VALUE; + double high = EMPTY_VALUE; + double down = EMPTY_VALUE; + double body = EMPTY_VALUE; + double close = EMPTY_VALUE; + double range = EMPTY_VALUE; + bool lowShadowPassed = false; + bool highShadowPassed = false; + double lowShadow = EMPTY_VALUE; + double highShadow = EMPTY_VALUE; + double startHKLow = EMPTY_VALUE; + double startHKOpen = EMPTY_VALUE; + double startHKHigh = EMPTY_VALUE; + double startHKClose = EMPTY_VALUE; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + int end = start + maxAllowedLoopbackLength; + for (int i = start; i < end; i++) + { + // + // Cleanup ... + zone.Clean(); + dir = X_DIRECTION_NONE; + + // + // Reading HK Buffesr ... + low = GetHKLow(i); + open = GetHKOpen(i); + high = GetHKHigh(i); + close = GetHKClose(i); + + // + // Initialized Start Bar ... + if (i == start) + { + // + startHKLow = low; + startHKOpen = open; + startHKHigh = high; + startHKClose = close; + } + + // + // Check Direction ... + isBullish = open < close; + isBearish = open > close; + dir = + (isBullish && !isBearish) + ? X_DIRECTION_BULLISH + : (isBearish && !isBullish) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(dir); + if (!has) + { + continue; + } + + // + // Calculate Requirements for Processing ... + up = isBullish + ? close + : open; + down = isBullish + ? open + : close; + body = MathAbs(up - down); + range = high - low; + highShadow = high - up; + lowShadow = down - low; + + // + // Detecting Shadows ... + + // + // Low Shadow ... + lowShadowPassed = lowShadow >= (shadowMultiplier * highShadow); + + // + // High Shadow ... + highShadowPassed = highShadow >= (shadowMultiplier * lowShadow); + + // + has = (lowShadowPassed && !highShadowPassed) || + (highShadowPassed && !lowShadowPassed); + if (!has) + { + continue; + } + + // + // Filling Zone ... + + // + zone.symbol = symbol; + zone.period = period; + zone.from = GetBarTime( + zone.symbol, + zone.period, + i // + ); + zone.dir = lowShadowPassed + ? X_DIRECTION_BULLISH + : highShadowPassed + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + zone.upper = + IsXBullish(zone.dir) + ? down + : IsXBearish(zone.dir) + ? high + : EMPTY_VALUE; + + // + zone.lower = + IsXBullish(zone.dir) + ? low + : IsXBearish(zone.dir) + ? up + : EMPTY_VALUE; + + // + zone.to = TimeCurrent(); + zone.type = ToXString(XFIMA_PIVOT_HK) + "_" + (IsXBullish(zone.dir) ? "Support" : IsXBearish(zone.dir) ? "Resistance" + : ""); + + // + // Validate ... + has = + zone.IsValid() && + HasDirection(zone.dir) && + NotEmptyZero(zone.upper) && + NotEmptyZero(zone.lower) && + (zone.IsBullish() + ? startHKLow > zone.upper + : startHKHigh < zone.lower) && + (zone.upper - zone.lower) >= minAllowedStrength && + ValidateHKZone(zone, validationLength, breakValidLength, validateFakeBreakes); + if (has) + { + // + AddIfNotExists( + zone, + zones // + ); + } + + // + // Cleanup Resources ... + zone.Clean(); + + // + // Validating ... + result = ArraySize(zones); + has = IsValidSize(result) && + result >= requiredNumberOFZones; + if (has) + { + break; + } + } + + // + // Cleanup Resources ... + zone.Clean(); + + // + return result; + } + + // + // Values Retrievers ... + + /** + * Filling Specified Bar index Boundary Values ... + * + * @param dest: double, reference collection to hold boundary Values ... + * @param barIndex: int, Specified Bar's Index ... + * @param containsFastSlow: bool, Contains XMA Fast / Slow ... + * @param containsMABand: bool, Contains XMA Boundary Upper / Lower ... + * @param containsHKBound: bool, Contains XHK Boundary Upper / Lower ... + * @param containsPBBand: bool, Contains XPB Boundary Upper / Lower ... + * @param containsFiboLevels: nool, Contains XFIBO Levels ... + * + * @return ( int ) + */ + int FillBoundaryValues( + double &dest[], + int barIndex = 0, + bool containsFastSlow = true, + bool containsMABand = true, + bool containsHKBound = true, + bool containsPBBand = true, + bool containsFiboLevels = false // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // Read and Validate Values ... + + // + double fast = GetMAFast(barIndex); + double slow = GetMASlow(barIndex); + + // + double maBandUpper = GetMABandUpper(barIndex); + double maBandLower = GetMABandLower(barIndex); + + // + double pbBandUpper = GetPBBandUpper(barIndex); + double pbBandLower = GetPBBandLower(barIndex); + + // + double hkBandUpper = GetHKBandUpper(barIndex); + double hkBandLower = GetHKBandLower(barIndex); + + // + double fiboUpper = GetFiboUpper(barIndex); + double fiboLower = GetFiboLower(barIndex); + double fiboMiddle = GetFiboMiddle(barIndex); + + // + has = + NotEmptyZero(fast) && + NotEmptyZero(slow) && + NotEmptyZero(fiboLower) && + NotEmptyZero(fiboUpper) && + NotEmptyZero(fiboMiddle) && + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower); + if (!has) + { + return result; + } + + // + // Fill Dest ... + + // + // XMA Fast / Slow ... + if (containsFastSlow) + { + // + Add(fast, dest); + Add(slow, dest); + } + + // + // XMA Bound ... + if (containsMABand) + { + // + Add(maBandUpper, dest); + Add(maBandLower, dest); + } + + // + // XHK Band ... + if (containsHKBound) + { + // + Add(hkBandUpper, dest); + Add(hkBandLower, dest); + } + + // + // XPB Band ... + if (containsPBBand) + { + // + Add(pbBandUpper, dest); + Add(pbBandLower, dest); + } + + // + // XFIBO Zones ... + if (containsFiboLevels) + { + // + Add(fiboLower, dest); + Add(fiboUpper, dest); + Add(fiboMiddle, dest); + } + + // + result = ArraySize(dest); + + // + return result; + } + + /** + * Retrieve Fast, Slow, MA Band Upper/Lower, HK Band Upper/Lower and PB Band Upper/Lower Min/Max ... + * + * @param min: double, minimum value ... + * @param max: double, maximum value ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool GetBoundaryValues( + double &min, + double &max, + int barIndex = 0, + bool containsFastSlow = true, + bool containsMABand = true, + bool containsHKBound = true, + bool containsPBBand = true, + bool containsFiboLevels = false // + ) + { + // + bool result = false; + + // + // Prepare ... + min = EMPTY_VALUE; + max = EMPTY_VALUE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double fast = GetMAFast(barIndex); + double slow = GetMASlow(barIndex); + + // + double maBandUpper = GetMABandUpper(barIndex); + double maBandLower = GetMABandLower(barIndex); + + // + double pbBandUpper = GetPBBandUpper(barIndex); + double pbBandLower = GetPBBandLower(barIndex); + + // + double hkBandUpper = GetHKBandUpper(barIndex); + double hkBandLower = GetHKBandLower(barIndex); + + // + double fiboUpper = GetFiboUpper(barIndex); + double fiboLower = GetFiboLower(barIndex); + double fiboMiddle = GetFiboMiddle(barIndex); + + // + result = + NotEmptyZero(fast) && + NotEmptyZero(slow) && + NotEmptyZero(fiboLower) && + NotEmptyZero(fiboUpper) && + NotEmptyZero(fiboMiddle) && + NotEmptyZero(maBandUpper) && + NotEmptyZero(maBandLower) && + NotEmptyZero(pbBandUpper) && + NotEmptyZero(pbBandLower) && + NotEmptyZero(hkBandUpper) && + NotEmptyZero(hkBandLower); + if (!result) + { + return result; + } + + // + double values[]; + + // + if (containsFastSlow) + { + // + Add(fast, values); + Add(slow, values); + } + + // + if (containsMABand) + { + // + Add(maBandUpper, values); + Add(maBandLower, values); + } + + // + if (containsHKBound) + { + // + Add(hkBandUpper, values); + Add(hkBandLower, values); + } + + // + if (containsPBBand) + { + // + Add(pbBandUpper, values); + Add(pbBandLower, values); + } + + // + if (containsFiboLevels) + { + // + Add(fiboLower, values); + Add(fiboUpper, values); + Add(fiboMiddle, values); + } + + // + result = HasChild(values); + if (!result) + { + return result; + } + + // + min = GetMin(values); + max = GetMax(values); + + // + result = + NotEmptyZero(min) && + NotEmptyZero(max) && + min < max; + + // + return result; + } + + // + // Fast MA ... + + // + double GetMAFast( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_FAST_LINE, + barIndex // + ); + } + + // + int CopyMAFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_FAST_LINE, + start, + count, + asSeries // + ); + } + + // + // Fast MA State ... + + // + double GetMAFastState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_FAST_STATE_LINE, + barIndex // + ); + } + + // + int CopyMAFastState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_FAST_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // Slow MA ... + + // + double GetMASlow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_SLOW_LINE, + barIndex // + ); + } + + // + int CopyMASlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_SLOW_LINE, + start, + count, + asSeries // + ); + } + + // + // Slow MA State ... + + // + double GetMASlowState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_SLOW_STATE_LINE, + barIndex // + ); + } + + // + int CopyMASlowState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_SLOW_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // Upper MA ... + + // + double GetMABandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyMABandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower MA ... + + // + double GetMABandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MA_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyMABandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MA_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // XPB ... + + // + // Upper PB ... + + // + double GetPBBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PB_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyPBBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PB_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower PB ... + + // + double GetPBBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PB_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyPBBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PB_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // Upper PB ... + + // + double GetPBRawBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PB_BAND_RAW_UPPER_LINE, + barIndex // + ); + } + + // + int CopyPBRawBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PB_BAND_RAW_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower PB ... + + // + double GetPBRawBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PB_BAND_RAW_LOWER_LINE, + barIndex // + ); + } + + // + int CopyPBRawBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PB_BAND_RAW_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // XATR ... + + // + // Upper ATR ... + + // + double GetATRBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyATRBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower ATR ... + + // + double GetATRBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyATRBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_LINE, + barIndex // + ); + } + + // + int CopyATR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_LINE, + start, + count, + asSeries // + ); + } + + // + // Upper ATR ... + + // + double GetATRRawBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_RAW_UPPER_LINE, + barIndex // + ); + } + + // + int CopyATRRawBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_RAW_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower ATR ... + + // + double GetATRRawBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_RAW_LOWER_LINE, + barIndex // + ); + } + + // + int CopyATRRawBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_RAW_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // SAR ... + + // + double GetSar( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SAR_LINE, + barIndex // + ); + } + + // + int CopySar( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SAR_LINE, + start, + count, + asSeries // + ); + } + + // + // SAR State ... + + // + double GetSarState( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SAR_STATE_LINE, + barIndex // + ); + } + + // + int CopySarState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SAR_STATE_LINE, + start, + count, + asSeries // + ); + } + + // + // PEAK ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_PEAK_LINE, + barIndex // + ); + } + + // + int CopyPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_PEAK_LINE, + start, + count, + asSeries // + ); + } + + // + // VALE ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_VALE_LINE, + barIndex // + ); + } + + // + int CopyVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_VALE_LINE, + start, + count, + asSeries // + ); + } + + // + // FIBO Zone ... + + // + // FIBO Upper ... + + // + double GetFiboUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_FIBO_UPPER_LINE, + barIndex // + ); + } + + // + int CopyFiboUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_FIBO_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // FIBO Middle ... + + // + double GetFiboMiddle( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_FIBO_MIDDLE_LINE, + barIndex // + ); + } + + // + int CopyFiboMiddle( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_FIBO_MIDDLE_LINE, + start, + count, + asSeries // + ); + } + + // + // FIBO Lower ... + + // + double GetFiboLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_FIBO_LOWER_LINE, + barIndex // + ); + } + + // + int CopyFiboLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_FIBO_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // ZigZag ... + + // + double GetZigZag( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ZIGZAG_LINE, + barIndex // + ); + } + + // + int CopyZigZag( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ZIGZAG_LINE, + start, + count, + asSeries // + ); + } + + // + // CYCLES Range ... + + // + // SHORT ... + + // + // HH ... + + // + double GetSHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SC_HH_LINE, + barIndex // + ); + } + + // + int CopySHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetSLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_SC_LL_LINE, + barIndex // + ); + } + + // + int CopySLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_SC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // MEDIUM ... + + // + // HH ... + + // + double GetMHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MC_HH_LINE, + barIndex // + ); + } + + // + int CopyMHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetMLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_MC_LL_LINE, + barIndex // + ); + } + + // + int CopyMLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_MC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // LONG ... + + // + // HH ... + + // + double GetLHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_LC_HH_LINE, + barIndex // + ); + } + + // + int CopyLHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_LC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetLLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_LC_LL_LINE, + barIndex // + ); + } + + // + int CopyLLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_LC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // HIND ... + + // + // HH ... + + // + double GetHHH( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HC_HH_LINE, + barIndex // + ); + } + + // + int CopyHHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HC_HH_LINE, + start, + count, + asSeries // + ); + } + + // + // LL ... + + // + double GetHLL( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HC_LL_LINE, + barIndex // + ); + } + + // + int CopyHLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HC_LL_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK ... + + // + // XHK Open ... + + // + double GetHKOpen( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_OPEN_LINE, + barIndex // + ); + } + + // + int CopyHKOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_OPEN_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK High ... + + // + double GetHKHigh( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_HIGH_LINE, + barIndex // + ); + } + + // + int CopyHKHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_HIGH_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Low ... + + // + double GetHKLow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_LOW_LINE, + barIndex // + ); + } + + // + int CopyHKLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_LOW_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Close ... + + // + double GetHKClose( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_CLOSE_LINE, + barIndex // + ); + } + + // + int CopyHKClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_CLOSE_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Color ... + + // + double GetHKColor( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_COLOR_LINE, + barIndex // + ); + } + + // + int CopyHKColor( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_COLOR_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Raw ... + + // + // XHK Raw Open ... + + // + double GetHKRawOpen( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_RAW_OPEN_LINE, + barIndex // + ); + } + + // + int CopyHKRawOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_RAW_OPEN_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Raw High ... + + // + double GetHKRawHigh( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_RAW_HIGH_LINE, + barIndex // + ); + } + + // + int CopyHKRawHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_RAW_HIGH_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Raw Low ... + + // + double GetHKRawLow( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_RAW_LOW_LINE, + barIndex // + ); + } + + // + int CopyHKRawLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_RAW_LOW_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Raw Close ... + + // + double GetHKRawClose( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_RAW_CLOSE_LINE, + barIndex // + ); + } + + // + int CopyHKRawClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_RAW_CLOSE_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Band ... + + // + // XHK Band Upper ... + + // + double GetHKBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyHKBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // XHK Band Lower ... + + // + double GetHKBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_HK_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyHKBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_HK_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + XFIMAInputs mInputs; // Inputs ... + + // + // XHK Helper ... + + /** + * Validate HK Zone ... + * + * @param zone: XBoxZone, reference to Specified Zone ... + * @param validationLength: int, Validation Length of Zones ... + * @param breakValidLength: int, Break Validation Length of Zones ... + * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... + * + * @return ( bool ) + */ + bool ValidateHKZone( + XBoxZone &zone, + int validationLength = 1, + int breakValidLength = 3, + bool validateFakeBreakes = true // + ) + { + // + bool result = false; + + // + // Normalize ... + validationLength = NormalizeInt(validationLength, 1); + breakValidLength = NormalizeInt(breakValidLength, 2); + + // + // Validate ... + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + // Requirements ... + double low = EMPTY_VALUE; + double open = EMPTY_VALUE; + double high = EMPTY_VALUE; + double close = EMPTY_VALUE; + + // + int count = 0; + int start = zone.FromIndex() + 1; + int end = start + validationLength; + + // + // Validate Before ... + for (int i = start; i < end; i++) + { + // + // Reading HK ... + low = GetHKLow(i); + high = GetHKHigh(i); + result = + NotEmptyZero(low) && + NotEmptyZero(high); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? low > zone.lower + : high < zone.upper; + if (!result) + { + break; + } + } + + // + // Validating After ... + if (result) + { + // + start = zone.ToIndex() + 1; + count = zone.FromIndex() - start; + end = start + count; + for (int i = start; i < end; i++) + { + // + // Read HK ... + low = GetHKLow(i); + high = GetHKHigh(i); + result = + NotEmptyZero(low) && + NotEmptyZero(high); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? low > zone.lower + : high < zone.upper; + if (!result) + { + // + // Check For Fake Breake ... + if (validateFakeBreakes && breakValidLength > 0) + { + // + result = i - 1 >= 0; + if (result) + { + // + for (int j = i - 1; j >= zone.ToIndex(); j--) + { + // + // Reading HK ... + close = GetHKClose(j); + result = NotEmptyZero(close); + if (!result) + { + break; + } + + // + result = zone.IsBullish() + ? close > zone.upper + : close < zone.lower; + if (result) + { + // + result = MathAbs(j - i) <= breakValidLength; + if (result) + { + break; + } + } + } + } + } + + // + if (!result) + { + break; + } + } + } + } + + // + // Cleanup Resource ... + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/Documents/BKP/x-saherelm.xfima.lib copy 2.mq5 b/Documents/BKP/x-saherelm.xfima.lib copy 2.mq5 new file mode 100644 index 00000000..279edaeb --- /dev/null +++ b/Documents/BKP/x-saherelm.xfima.lib copy 2.mq5 @@ -0,0 +1,567 @@ +/////////////////////////////////////////////////////// +// +// 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 "../../Classes/x-saherelm.x-cobject.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.parser.class.mq5" +#include "../../Libraries/x-saherelm.x-pivot.analysis.lib.mq5" + +// +// Definitions ... + +/** + * XFIMA Base Market Structure ... + * AnalyseMarket result ... + **/ +struct XFIMAMarketStructure +{ + // + XOHCL bar; // Spacified Start Bar for Analysing ... + XPatternAnalysis barAnalysis; // Structure Bar Pattern Analysis ... + + // + XPivotAnalysis pvAnalysis; // PV Pivot Analysis Result ... + XPivotAnalysis zgAnalysis; // ZG Pivot Analysis Result ... + + // + XPatternAnalysis barsAnalysis[]; // Anaysed Bars ... + + // + // Constructor ... + XFIMAMarketStructure() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + bar.Clean(); + barAnalysis.Clean(); + + // + pvAnalysis.Clean(); + zgAnalysis.Clean(); + XClean(barsAnalysis); + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = bar.IsValid() && + barAnalysis.IsValid(); + + // + return result; + } + + // + // Collectors ... + + /** + * Collect Required Zones from Structure ... + * + * @param dest: XBoxZone, reference collection to holds result ... + * @param forDir: ENUM_X_DIRECTION, Specified Collectiong ones Direction ... + * @param containsOB: bool, Contains OB Zones ... + * @param containsFVG: bool, Contains FVG Zones ... + * + * @return ( int ) + */ + int CollectZones( + XBoxZone &dest[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + bool containsOB = false, + bool containsFVG = false // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + bool canCollectBullish = + IsXBullish(forDir) || + !HasDirection(forDir); + + // + bool canCollectBearish = + IsXBearish(forDir) || + !HasDirection(forDir); + + // + int count = 0; + XBoxZone tmpBox; + + // + // Check Analysis ... + + // + // XPV ... + has = pvAnalysis.IsValid(); + if (has) + { + // + // Support ... + tmpBox.Clean(); + has = pvAnalysis.HasSupportBox(tmpBox); + if (has && canCollectBullish) + { + // + AddIfNotExists( + tmpBox, + dest // + ); + } + + // + // Resistance ... + tmpBox.Clean(); + has = pvAnalysis.HasResistanceBox(tmpBox); + if (has && canCollectBearish) + { + // + AddIfNotExists( + tmpBox, + dest // + ); + } + } + + // + // XZG ... + has = zgAnalysis.IsValid(); + if (has) + { + // + // Support ... + tmpBox.Clean(); + has = zgAnalysis.HasSupportBox(tmpBox); + if (has && canCollectBullish) + { + // + AddIfNotExists( + tmpBox, + dest // + ); + } + + // + // Resistance ... + tmpBox.Clean(); + has = zgAnalysis.HasResistanceBox(tmpBox); + if (has && canCollectBearish) + { + // + AddIfNotExists( + tmpBox, + dest // + ); + } + } + + // + // Bar Patterns ... + has = HasChild(barsAnalysis); + if (has) + { + // + count = ArraySize(barsAnalysis); + for (int i = 0; i < count; i++) + { + // + // Support ... + has = barsAnalysis[i].IsSupport(); + if (has && canCollectBullish) + { + // + AddIfNotExists( + barsAnalysis[i].support, + dest // + ); + } + + // + // Resistance ... + has = barsAnalysis[i].IsResistance(); + if (has && canCollectBearish) + { + // + AddIfNotExists( + barsAnalysis[i].resistance, + dest // + ); + } + + // + // OB ... + if (containsOB) + { + // + has = barsAnalysis[i].IsOB(); + if (has) + { + // + has = (canCollectBullish && barsAnalysis[i].ob.IsBullish()) || + (canCollectBearish && barsAnalysis[i].ob.IsBearish()); + if (has) + { + // + AddIfNotExists( + barsAnalysis[i].ob, + dest // + ); + } + } + } + + // + // FVG ... + if (containsFVG) + { + has = barsAnalysis[i].IsFVG(); + if (has) + { + // + has = (canCollectBullish && barsAnalysis[i].fvg.IsBullish()) || + (canCollectBearish && barsAnalysis[i].fvg.IsBearish()); + if (has) + { + // + AddIfNotExists( + barsAnalysis[i].fvg, + dest // + ); + } + } + } + } + } + + // + result = ArraySize(dest); + has = IsValidSize(result); + if (has) + { + // + // Update To Time ... + // and also we Can Validate Zones Here ... + datetime cTime = TimeCurrent(); + for (int i = 0; i < result; i++) + { + dest[i].to = cTime; + } + } + + // + // Cleanup ... + tmpBox.Clean(); + + // + return result; + } + + // +}; + +struct XFIMAMarketStructureConfig +{ + // + // Props ... + + // + // Detector Flags ... + + // + bool analysePVPivots; // Analyse PV Pivots ... + bool analyseZGPivots; // Analyse ZG Pivots ... + + // + bool analyseBarPatterns; // Analyse Bar Patterns ... + + // + // Detector Configs ... + + // + int loopback; // Max Allowed Looping Back Length ... + int requiredPivots; // Required Extracted Pivots for Analysis ... + + // + int pvPivotsValidationLength; // PV Pivots Validation Length ... + double maCrossValidationDiffMultiplier; // a Point Distance to Validate MA Crosses ... + + // + XPatternAnalysisConfig barsAnalysisConfig; // Bars Analyser Config ... + + // + // Constructor ... + XFIMAMarketStructureConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * This function fulfills the will of the developer + */ + void Clean() + { + // + // Detector Flags ... + analysePVPivots = false; + analyseZGPivots = false; + analyseBarPatterns = false; + + // + // Configure Detectors ... + loopback = 0; + requiredPivots = 0; + pvPivotsValidationLength = 0; + maCrossValidationDiffMultiplier = 0; + + // + barsAnalysisConfig.Clean(); + + // + ZeroMemory(this); + } + + /** + * Default Configurations ... + */ + void Default() + { + // + // Detector Flags ... + analysePVPivots = true; + analyseZGPivots = true; + analyseBarPatterns = true; + + // + // Configure Detectors ... + loopback = 200; + requiredPivots = 10; + pvPivotsValidationLength = 5; + maCrossValidationDiffMultiplier = 4; + + // + barsAnalysisConfig.Default(); + barsAnalysisConfig.FullPattern(); + } + + /** + * No Draw Abilioty ... + */ + void Off() + { + // + // Detector Flags ... + analysePVPivots = false; + analyseZGPivots = false; + analyseBarPatterns = false; + } + + /** + * Full Draw Abilioty ... + */ + void Full() + { + // + // Detector Flags ... + analysePVPivots = true; + analyseZGPivots = true; + analyseBarPatterns = true; + } + + // +}; + +/** + * Configure Market Structure Drawer ... + **/ +struct XFIMAMarketStructureDrawerConfig +{ + // + // Props ... + + // + bool drawPVAnalysis; + bool drawZGAnalysis; + bool drawBarsAnalysis; + + // + XPOIDrawConfig drawConfig; + XPivotAnalysisDrawConfig pivotAnalysisDrawConfig; + XPatternAnalysisDrawConfig barAnalysisDrawConfig; + + // + // Constructor ... + XFIMAMarketStructureDrawerConfig() + { + Clean(); + } + + // + // Tools ... + + /** + * This function fulfills the will of the developer + */ + void Clean() + { + // + // Drawing Flags ... + + // + drawPVAnalysis = false; + drawZGAnalysis = false; + drawBarsAnalysis = false; + + // + // Drawing Configs ... + drawConfig.Clean(); + barAnalysisDrawConfig.Clean(); + pivotAnalysisDrawConfig.Clean(); + + // + ZeroMemory(this); + } + + /** + * Default Configurations ... + */ + void Default() + { + // + // Drawing Flags ... + + // + drawPVAnalysis = true; + drawZGAnalysis = true; + drawBarsAnalysis = true; + + // + // Drawing Configs ... + drawConfig.Default(); + pivotAnalysisDrawConfig.Default(); + + // + barAnalysisDrawConfig.Default(); + barAnalysisDrawConfig.Full(); + XClean(barAnalysisDrawConfig.allowedDrawZones); + Add( + X_BAR_PATTERN_SUPPORT, + barAnalysisDrawConfig.allowedDrawZones); + Add( + X_BAR_PATTERN_RESISTANCE, + barAnalysisDrawConfig.allowedDrawZones); + } + + /** + * No Draw Abilioty ... + */ + void Off() + { + // + // Drawing Flags ... + + // + drawPVAnalysis = false; + drawZGAnalysis = false; + drawBarsAnalysis = false; + + // + // Drawing Configs ... + barAnalysisDrawConfig.Off(); + pivotAnalysisDrawConfig.Off(); + } + + /** + * Full Draw Abilioty ... + */ + void Full() + { + // + // Drawing Flags ... + + // + drawPVAnalysis = false; + drawZGAnalysis = false; + drawBarsAnalysis = false; + + // + // Drawing Configs ... + barAnalysisDrawConfig.Full(); + pivotAnalysisDrawConfig.Full(); + } + + void ApplyDrawConfig() + { + // + barAnalysisDrawConfig.drawConfig = drawConfig; + barAnalysisDrawConfig.ConfigureQuarterDraws(); + pivotAnalysisDrawConfig.drawConfig = drawConfig; + } + + void ApplyDrawConfig(XPOIDrawConfig &_drawConfig) + { + // + drawConfig = _drawConfig; + ApplyDrawConfig(); + } + + // +}; + +// \ No newline at end of file diff --git a/Documents/BKP/x-saherelm.xfima.x-poi.detector.class.mq5 b/Documents/BKP/x-saherelm.xfima.x-poi.detector.class.mq5 new file mode 100644 index 00000000..ac1fcbd5 --- /dev/null +++ b/Documents/BKP/x-saherelm.xfima.x-poi.detector.class.mq5 @@ -0,0 +1,495 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMAPoiDetector ... +// Description: XFIMA POI Detector Class ... +// +// +// 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 XFIMA POI Detector Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-market.pattern.class.mq5" +#include "../Libraries/x-saherelm.xfima.lib.mq5" + +// +// Implementation ... +class XCXFIMAPOIDetector : public XCMarketPatternDetector +{ + // + // Public ... + public: + // + // Props ... + XCBarAnalyser *barAnalyser; // Bar Analyser ... + XCXFIMAHelper *fimaHelper; // XFIMA Helper ... + + // + // Constructor ... + XCXFIMAPOIDetector( + XCXFIMAHelper *_fimaHelper // + ) : XCMarketPatternDetector() + { + // + barAnalyser = new XCBarAnalyser(); + fimaHelper = _fimaHelper; + } + + // + // Deconstructor ... + ~XCXFIMAPOIDetector() + { + Destroy(); + } + + // + // Actions and Tools ... + + // + // Pivot Analysors ... + + /** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( bool ) + */ + bool AnalysePVPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractPVPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength, // Max Allowed Loopback ... + validationLength // Validation Length ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XPV", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; + } + + /** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * + * @return ( bool ) + */ + bool AnalyseMAPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500, + int validationLength = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractMAPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength, // Max Allowed Loopback ... + validationLength // Validation Length ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XMA", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; + } + + /** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( bool ) + */ + bool AnalyseSARPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractSARPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength // Max Allowed Loopback ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XSAR", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; + } + + /** + * Analyse Market based on Specified Kind of Pivots ... + * + * @param analysis: XPivotAnalysis, reference to hold result ... + * @param barIndex: int, Bar Index ... + * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... + * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * + * @return ( bool ) + */ + bool AnalyseZigZagPivots( + XPivotAnalysis &analysis, + int barIndex = 0, + int requiredNumberOFPivots = 50, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Reading Pivots ... + XPivot pivots[]; + int count = fimaHelper.ExtractZigZagPivots( + pivots, // Result ... + barIndex, // Bar Index ... + requiredNumberOFPivots, // Required Number of Pivots ... + maxAllowedLoopbackLength // Max Allowed Loopback ... + ); + result = IsValidSize(count); + if (!result) + { + // + SpecifiedClean(pivots); + return result; + } + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + + // + // Initialize Analysis ... + result = analysis.Init( + "XFIMA_XZG", + symbol, + period, + pivots // + ); + + // + // Cleanup Resources ... + if (!result) + { + analysis.Clean(); + } + SpecifiedClean(pivots); + + // + return result; + } + + /** + * Destroy ... + */ + void Destroy() + { + // + delete barAnalyser; + ZeroMemory(barAnalyser); + } + + // + // Testers ... + + /** + * Analyse Market based on Specified Bar ... + * + * @param structure: XFIMAMarketStructure, reference to holds result ... + * @param config: XFIMAMarketStructureConfig, reference to Configure Detector ... + * @param barIndex: int, Bar Index ... + */ + void AnalyseMarket( + XFIMAMarketStructure &structure, + XFIMAMarketStructureConfig &config, + int barIndex = 0 // + ) + { + // + // Prepare ... + structure.Clean(); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + bool has = false; + + // + string symbol = fimaHelper.GetSymbol(); + ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + has = structure.bar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + structure.Clean(); + return; + } + + // + // Reading Bar Patterns ... + XOHCL iBar; + XPatternAnalysis iPatternAnalysis; + for (int i = barIndex; i < barIndex + config.loopback; i++) + { + // + // Cleanup ... + iBar.Clean(); + iPatternAnalysis.Clean(); + + // + // Initialize Indexed Bar ... + // + has = structure.bar.BarAt(i, iBar); + if (!has) + { + break; + } + + // + // Analyse Indexed Bar ... + has = AnalyseBarPatterns(iBar, iPatternAnalysis, config.barsAnalysisConfig); + if (has) + { + // + AddRef( + iPatternAnalysis, + structure.barsAnalysis // + ); + + // + if (i == barIndex) + { + structure.barAnalysis = iPatternAnalysis; + } + } + + // + // Check Satisfied ... + has = ArraySize(structure.barsAnalysis) >= config.requiredPivots; + if (has) + { + break; + } + } + + // + // Handle Pivot Analysis ... + + // + // XPV ... + if (config.analysePVPivots) + { + // + // Reading Pivots ... + has = AnalysePVPivots( + structure.pvAnalysis, + barIndex, + config.requiredPivots, + config.loopback, + config.pvPivotsValidationLength // + ); + if (!has) + { + structure.pvAnalysis.Clean(); + } + } + + // + // XZG ... + if (config.analyseZGPivots) + { + // + // Reading Pivots ... + has = AnalyseZigZagPivots( + structure.zgAnalysis, + barIndex, + config.requiredPivots, + config.loopback // + ); + if (!has) + { + structure.zgAnalysis.Clean(); + } + } + + // + // Cleanup ... + iBar.Clean(); + iPatternAnalysis.Clean(); + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Private ... + private: + // + + // +}; + +// \ No newline at end of file diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 index 58492c64..fabb2c5c 100644 --- a/Experts/x-saherelm.xfima.backtester.ea.mq5 +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -111,7 +111,7 @@ input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To input int maFastLength = 7; // Fast MA Length input int maSlowLength = 20; // Slow MA Length -input int maBondLength = 7; // MA Bond Length +input int maBandLength = 7; // MA Band Length input int zigzagDepth = 12; // ZigZag Depth input int zigzagDeviation = 5; // ZigZag Deviation input int zigzagBackStep = 3; // ZigZag Back Step @@ -137,8 +137,8 @@ input bool showSAR = false; // Show Sar input bool showBars = true; // Show Bars input bool showMAFast = false; // Show MA Fast input bool showMASlow = false; // Show MA Slow -input bool showMABond = false; // Show MA Bond -input bool showHKBond = false; // Show HK Bond +input bool showMABand = false; // Show MA Band +input bool showHKBand = false; // Show HK Band input bool showBarTime = true; // Show Bar Time input bool showZigZag = false; // Show ZigZag input bool showFiboZone = false; // Show Fibo Zone @@ -312,7 +312,7 @@ int OnInit() fimaInputs.maAppliedTo = maAppliedTo; fimaInputs.maFastLength = maFastLength; fimaInputs.maSlowLength = maSlowLength; - fimaInputs.maBondLength = maBondLength; + fimaInputs.maBandLength = maBandLength; fimaInputs.zigzagDepth = zigzagDepth; fimaInputs.zigzagDeviation = zigzagDeviation; fimaInputs.zigzagBackStep = zigzagBackStep; @@ -326,8 +326,8 @@ int OnInit() fimaInputs.showSAR = showSAR; fimaInputs.showMAFast = showMAFast; fimaInputs.showMASlow = showMASlow; - fimaInputs.showMABond = showMABond; - fimaInputs.showHKBond = showHKBond; + fimaInputs.showMABand = showMABand; + fimaInputs.showHKBand = showHKBand; fimaInputs.showZigZag = showZigZag; fimaInputs.showFiboZone = showFiboZone; fimaInputs.startCalculationForLastBars = startCalculationForLastBars; @@ -354,7 +354,7 @@ int OnInit() // Configure Signaller ... fima1Signaller.ignoreTargets = false; fima1Signaller.slAdditionDistance = 30; - fima1Signaller.maxAllowedRiskDistance = 200; + fima1Signaller.maxAllowedRiskDistance = 350; fima1Signaller.AddOnSignalEventHandler(OnSignalTriggered); // diff --git a/Helpers/x-saherelm.xfima.helper.mq5 b/Helpers/x-saherelm.xfima.helper.mq5 index bb31cbe5..c940415c 100644 --- a/Helpers/x-saherelm.xfima.helper.mq5 +++ b/Helpers/x-saherelm.xfima.helper.mq5 @@ -30,138 +30,6 @@ // // Definitions ... -enum ENUM_XFIMA_PIVOTS -{ - XFIMA_PIVOT_NONE = 0, - XFIMA_PIVOT_PV = 1, - XFIMA_PIVOT_HK = 2, - XFIMA_PIVOT_ZIGZAG = 3, - XFIMA_PIVOT_MA_CROSS = 4, - XFIMA_PIVOT_HK_SWITCH = 5, - XFIMA_PIVOT_SAR_SWITCH = 6, - XFIMA_PIVOT_BOUNDARY_SWITCH = 7, -}; - -bool IsXValid(ENUM_XFIMA_PIVOTS value) -{ - // - bool result = false; - - // - result = value != XFIMA_PIVOT_NONE; - - // - return result; -} - -string ToXString(ENUM_XFIMA_PIVOTS value) -{ - // - string result = NULL; - - // - if (!IsXValid(value)) - { - return result; - } - - // - switch (value) - { - // - case XFIMA_PIVOT_NONE: - result = "NONE"; - break; - - // - case XFIMA_PIVOT_PV: - result = "XPV"; - break; - - // - case XFIMA_PIVOT_HK: - result = "XHK"; - break; - - // - case XFIMA_PIVOT_ZIGZAG: - result = "XZGP"; - break; - - // - case XFIMA_PIVOT_MA_CROSS: - result = "XMACRS"; - break; - - // - case XFIMA_PIVOT_HK_SWITCH: - result = "XHKSWCH"; - break; - - // - case XFIMA_PIVOT_SAR_SWITCH: - result = "XSARSWCH"; - break; - - // - case XFIMA_PIVOT_BOUNDARY_SWITCH: - result = "XBNDSWCH"; - break; - } - - // - return result; -} - -ENUM_XFIMA_PIVOTS ToXFIMAPivots(string value) -{ - // - ENUM_XFIMA_PIVOTS result = XFIMA_PIVOT_NONE; - - // - if (!IsXValid(value)) - { - return result; - } - - // - if (value == ToXString(XFIMA_PIVOT_NONE)) - { - result = XFIMA_PIVOT_NONE; - } - else if (value == ToXString(XFIMA_PIVOT_PV)) - { - result = XFIMA_PIVOT_PV; - } - else if (value == ToXString(XFIMA_PIVOT_HK)) - { - result = XFIMA_PIVOT_HK; - } - else if (value == ToXString(XFIMA_PIVOT_ZIGZAG)) - { - result = XFIMA_PIVOT_ZIGZAG; - } - else if (value == ToXString(XFIMA_PIVOT_MA_CROSS)) - { - result = XFIMA_PIVOT_MA_CROSS; - } - else if (value == ToXString(XFIMA_PIVOT_HK_SWITCH)) - { - result = XFIMA_PIVOT_HK_SWITCH; - } - else if (value == ToXString(XFIMA_PIVOT_SAR_SWITCH)) - { - result = XFIMA_PIVOT_SAR_SWITCH; - } - else if (value == ToXString(XFIMA_PIVOT_BOUNDARY_SWITCH)) - { - result = XFIMA_PIVOT_BOUNDARY_SWITCH; - } - - // - return result; -} - // // Buffers ... enum ENUM_XFIMA_BUFFERS @@ -180,40 +48,45 @@ enum ENUM_XFIMA_BUFFERS XFIMA_FIBO_MIDDLE_LINE = 9, XFIMA_FIBO_LOWER_LINE = 10, XFIMA_ZIGZAG_LINE = 11, - XFIMA_MA_BOND_UPPER_LINE = 12, - XFIMA_MA_BOND_LOWER_LINE = 13, + XFIMA_MA_BAND_UPPER_LINE = 12, + XFIMA_MA_BAND_LOWER_LINE = 13, XFIMA_HK_OPEN_LINE = 14, XFIMA_HK_HIGH_LINE = 15, XFIMA_HK_LOW_LINE = 16, XFIMA_HK_CLOSE_LINE = 17, XFIMA_HK_COLOR_LINE = 18, - XFIMA_HK_BOND_UPPER_LINE = 19, - XFIMA_HK_BOND_LOWER_LINE = 20, - XFIMA_PB_BOND_UPPER_LINE = 21, - XFIMA_PB_BOND_LOWER_LINE = 22, + XFIMA_HK_BAND_UPPER_LINE = 19, + XFIMA_HK_BAND_LOWER_LINE = 20, + XFIMA_PB_BAND_UPPER_LINE = 21, + XFIMA_PB_BAND_LOWER_LINE = 22, + XFIMA_ATR_BAND_UPPER_LINE = 23, + XFIMA_ATR_BAND_LOWER_LINE = 24, // // Data Buffers ... - XFIMA_MA_FAST_STATE_LINE = 23, - XFIMA_MA_SLOW_STATE_LINE = 24, - XFIMA_SAR_STATE_LINE = 25, - XFIMA_SC_HH_LINE = 26, - XFIMA_SC_LL_LINE = 27, - XFIMA_MC_HH_LINE = 28, - XFIMA_MC_LL_LINE = 29, - XFIMA_LC_HH_LINE = 30, - XFIMA_LC_LL_LINE = 31, - XFIMA_HC_HH_LINE = 32, - XFIMA_HC_LL_LINE = 33, - XFIMA_ZIGZAG_HIGHS_LINE = 34, - XFIMA_ZIGZAG_HIGHS_TIME_LINE = 35, - XFIMA_ZIGZAG_LOWS_LINE = 36, - XFIMA_ZIGZAG_LOWS_TIME_LINE = 37, - XFIMA_HK_RAW_OPEN_LINE = 38, - XFIMA_HK_RAW_HIGH_LINE = 39, - XFIMA_HK_RAW_LOW_LINE = 40, - XFIMA_HK_RAW_CLOSE_LINE = 41, - XFIMA_PB_BOND_RAW_UPPER_LINE = 42, - XFIMA_PB_BOND_RAW_LOWER_LINE = 43, + XFIMA_MA_FAST_STATE_LINE = 25, + XFIMA_MA_SLOW_STATE_LINE = 26, + XFIMA_SAR_STATE_LINE = 27, + XFIMA_SC_HH_LINE = 28, + XFIMA_SC_LL_LINE = 29, + XFIMA_MC_HH_LINE = 30, + XFIMA_MC_LL_LINE = 31, + XFIMA_LC_HH_LINE = 32, + XFIMA_LC_LL_LINE = 33, + XFIMA_HC_HH_LINE = 34, + XFIMA_HC_LL_LINE = 35, + XFIMA_ZIGZAG_HIGHS_LINE = 36, + XFIMA_ZIGZAG_HIGHS_TIME_LINE = 37, + XFIMA_ZIGZAG_LOWS_LINE = 38, + XFIMA_ZIGZAG_LOWS_TIME_LINE = 39, + XFIMA_HK_RAW_OPEN_LINE = 40, + XFIMA_HK_RAW_HIGH_LINE = 41, + XFIMA_HK_RAW_LOW_LINE = 42, + XFIMA_HK_RAW_CLOSE_LINE = 43, + XFIMA_PB_BAND_RAW_UPPER_LINE = 44, + XFIMA_PB_BAND_RAW_LOWER_LINE = 45, + XFIMA_ATR_LINE = 46, + XFIMA_ATR_BAND_RAW_UPPER_LINE = 47, + XFIMA_ATR_BAND_RAW_LOWER_LINE = 48, }; // @@ -244,7 +117,7 @@ struct XFIMAInputs ENUM_APPLIED_PRICE maAppliedTo; // MA Applied To int maFastLength; // Fast MA Length int maSlowLength; // Slow MA Length - int maBondLength; // MA Bond Length + int maBandLength; // MA Band Length int zigzagDepth; // ZigZag Depth int zigzagDeviation; // ZigZag Deviation int zigzagBackStep; // ZigZag Back Step @@ -253,20 +126,27 @@ struct XFIMAInputs bool hkIgnoreShadows; // HK Remove noises int hkSmoothingLength; // HK Smoothing Length ENUM_X_MA_METHOD hkSmoothingMode; // HK Smoothing Method + int atrLength; // ATR Length + double atrMultiplier; // ATR Band Multiplier + int atrSmoothingLength; // ATR Smoothing Length + ENUM_X_PRICE atrUpperPriceType; // ATR Upper Zone Applied To + ENUM_X_PRICE atrLowerPriceType; // ATR Lower Zone Applied To + ENUM_X_MA_METHOD atrSmoothingMode; // ATR Smoothing Method // // Presentation ... bool showPV; // Show PV bool showHK; // Show HK - bool showSAR; // Show Sar + bool showSAR; // Show SAR bool showMAFast; // Show MA Fast bool showMASlow; // Show MA Slow - bool showMABond; // Show MA Bond - bool showHKBond; // Show HK Bond + bool showMABand; // Show MA Band + bool showHKBand; // Show HK Band + bool showATRBand; // Show ATR Band bool showZigZag; // Show ZigZag bool showFiboZone; // Show Fibo Zone int startCalculationForLastBars; // Calculate Last n Bars - int sarArrowCode; // Parabolic Sar Arrow Code + int sarArrowCode; // Parabolic SAR Arrow Code int peakArrowCode; // Peaks Arrow Code int valeArrowCode; // Vales Arrow Code @@ -312,7 +192,7 @@ struct XFIMAInputs maAppliedTo = PRICE_CLOSE; // MA Applied To maFastLength = 7; // Fast MA Length maSlowLength = 20; // Slow MA Length - maBondLength = 7; // MA Bond Length + maBandLength = 7; // MA Band Length zigzagDepth = 12; // ZigZag Depth zigzagDeviation = 5; // ZigZag Deviation zigzagBackStep = 3; // ZigZag Back Step @@ -321,20 +201,27 @@ struct XFIMAInputs hkIgnoreShadows = true; // HK Remove noises hkSmoothingLength = 21; // HK Smoothing Length hkSmoothingMode = X_MA_MODE_EMA; // HK Smoothing Method + atrLength = 14; // ATR Length + atrMultiplier = 1.5; // ATR Band Multiplier + atrSmoothingLength = 21; // ATR Smoothing Length + atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Zone Applied To + atrLowerPriceType = X_PRICE_LOW; // ATR Lower Zone Applied To + atrSmoothingMode = X_MA_MODE_EMA; // ATR Smoothing Method // // Presentation ... showPV = true; // Show PV showHK = true; // Show HK - showSAR = true; // Show Sar + showSAR = true; // Show SAR showMAFast = true; // Show MA Fast showMASlow = true; // Show MA Slow - showMABond = true; // Show MA Bond - showHKBond = true; // Show HK Bond + showMABand = true; // Show MA Band + showHKBand = true; // Show HK Band + showATRBand = true; // Show ATR Band showZigZag = true; // Show ZigZag showFiboZone = true; // Show Fibo Zone startCalculationForLastBars = 1500; // Calculate Last n Bars - sarArrowCode = 159; // Parabolic Sar Arrow Code + sarArrowCode = 159; // Parabolic SAR Arrow Code peakArrowCode = 159; // Peaks Arrow Code valeArrowCode = 159; // Vales Arrow Code } @@ -349,8 +236,9 @@ struct XFIMAInputs showSAR = false; showMAFast = false; showMASlow = false; - showMABond = false; - showHKBond = false; + showMABand = false; + showHKBand = false; + showATRBand = false; showZigZag = false; showFiboZone = false; } @@ -368,7 +256,7 @@ struct XFIMAInputs // MA ... maFastLength >= 2 && maSlowLength >= 2 && - maBondLength >= 2 && + maBandLength >= 2 && maSlowLength > maFastLength && // // SAR ... @@ -376,6 +264,12 @@ struct XFIMAInputs sarStep > 0 && sarMax > sarStep && // + // ATR ... + atrLength > 0 && + atrMultiplier >= 1 && + IsXValid(atrUpperPriceType) && + IsXValid(atrLowerPriceType) && + // // CYCLES ... (IsSpecifiedValid(scMethod, scPeriod) && IsSpecifiedValid(mcMethod, mcPeriod) && @@ -423,8 +317,8 @@ struct XFIMAConditions double maSlowBuffer[]; double maSlowColorBuffer[]; double maSlowStateBuffer[]; - double maBondUpperBuffer[]; - double maBondLowerBuffer[]; + double maBandUpperBuffer[]; + double maBandLowerBuffer[]; double sarBuffer[]; double sarColorBuffer[]; double sarStateBuffer[]; @@ -491,8 +385,8 @@ struct XFIMAConditions SpecifiedClean(maSlowBuffer); SpecifiedClean(maSlowColorBuffer); SpecifiedClean(maSlowStateBuffer); - SpecifiedClean(maBondUpperBuffer); - SpecifiedClean(maBondLowerBuffer); + SpecifiedClean(maBandUpperBuffer); + SpecifiedClean(maBandLowerBuffer); SpecifiedClean(sarBuffer); SpecifiedClean(sarColorBuffer); SpecifiedClean(sarStateBuffer); @@ -533,8 +427,8 @@ struct XFIMAConditions ArraySetAsSeries(maSlowBuffer, true); ArraySetAsSeries(maSlowColorBuffer, true); ArraySetAsSeries(maSlowStateBuffer, true); - ArraySetAsSeries(maBondUpperBuffer, true); - ArraySetAsSeries(maBondLowerBuffer, true); + ArraySetAsSeries(maBandUpperBuffer, true); + ArraySetAsSeries(maBandLowerBuffer, true); ArraySetAsSeries(sarBuffer, true); ArraySetAsSeries(sarColorBuffer, true); ArraySetAsSeries(sarStateBuffer, true); @@ -693,7 +587,7 @@ class XCXFIMAHelper : public XCBaseHelper mInputs.maAppliedTo, mInputs.maFastLength, mInputs.maSlowLength, - mInputs.maBondLength, + mInputs.maBandLength, mInputs.zigzagDepth, mInputs.zigzagDeviation, mInputs.zigzagBackStep, @@ -702,14 +596,21 @@ class XCXFIMAHelper : public XCBaseHelper mInputs.hkIgnoreShadows, mInputs.hkSmoothingLength, mInputs.hkSmoothingMode, + mInputs.atrLength, + mInputs.atrMultiplier, + mInputs.atrSmoothingLength, + mInputs.atrUpperPriceType, + mInputs.atrLowerPriceType, + mInputs.atrSmoothingMode, "", // Presentation ... mInputs.showPV, mInputs.showHK, mInputs.showSAR, mInputs.showMAFast, mInputs.showMASlow, - mInputs.showMABond, - mInputs.showHKBond, + mInputs.showMABand, + mInputs.showHKBand, + mInputs.showATRBand, mInputs.showZigZag, mInputs.showFiboZone, mInputs.startCalculationForLastBars, @@ -843,28 +744,28 @@ class XCXFIMAHelper : public XCBaseHelper ); // - CopyMABondUpper( + CopyMABandUpper( zIndex, loopback, - conditions.maBondUpperBuffer // + conditions.maBandUpperBuffer // ); // - CopyMABondLower( + CopyMABandLower( zIndex, loopback, - conditions.maBondLowerBuffer // + conditions.maBandLowerBuffer // ); // - CopySar( + CopySAR( zIndex, loopback, conditions.sarBuffer // ); // - CopySarState( + CopySARState( zIndex, loopback, conditions.sarStateBuffer // @@ -1010,5918 +911,6 @@ class XCXFIMAHelper : public XCBaseHelper return result; } - // - // Pivot Actions ... - - /** - * Check Specified Bar has MA Cross or not ... - * - * @param dir: reference for holds cross Direction ... - * @param barIndex: int, Specified Bar Index ... - * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... - * - * @return ( bool ) - */ - bool HasMACross( - ENUM_X_DIRECTION &dir, - int barIndex = 0, - double validCrossDiffMultiplier = 1 // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeInt(barIndex, 0); - validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - double fast[]; - int fastCount = CopyMAFast(barIndex, 2, fast); - - // - double slow[]; - int slowCount = CopyMASlow(barIndex, 2, slow); - - // - bool isBullish = false; - bool isBearish = false; - - // - // Validate Readed Values ... - int count = MathMin(fastCount, slowCount); - result = IsValidSize(count) && count >= 2; - if (result) - { - // - // Detect Direction Change ... - - // - bool notEmpty = - NotEmptyZero(fast[0]) && - NotEmptyZero(fast[1]) && - NotEmptyZero(slow[0]) && - NotEmptyZero(slow[1]); - - // - isBullish = - notEmpty && - fast[0] > slow[0] && - fast[1] < slow[1]; - - // - isBearish = - notEmpty && - fast[0] < slow[0] && - fast[1] > slow[1]; - - // - result = - isBullish || - isBearish; - - // - // Validate Direction Change ... - if (result && - validCrossDiffMultiplier > 0) - { - // - double _points = GetPoints(GetSymbol()); - double diff = MathAbs(fast[0] - slow[0]); - - // - result = diff >= (validCrossDiffMultiplier * _points); - } - } - - // - if (result) - { - // - // Setting Direction ... - dir = - isBullish - ? X_DIRECTION_BULLISH - : isBearish - ? X_DIRECTION_BEARISH - : X_DIRECTION_NONE; - } - - // - // Cleanup Resources ... - XClean(fast); - XClean(slow); - - // - return result; - } - - /** - * Check Specified Bar Price is In Boundary or not ... - * - * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool IsInBoundary( - ENUM_X_PRICE priceType = X_PRICE_CLOSE, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - if (!IsXValid(priceType)) - { - priceType = X_PRICE_CLOSE; - } - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Retrieve Bar ... - XOHCL bar; - result = bar.Init( - mSymbol, - mPeriod, - barIndex // - ); - if (!result) - { - // - bar.Clean(); - return result; - } - double value = bar.GetPrice(priceType); - - // - // Read Boundary Values ... - double min; - double max; - result = GetBoundaryValues(min, max, barIndex); - if (!result) - { - // - bar.Clean(); - return result; - } - - // - result = value < max && - value > min; - - // - // Cleanup Resources ... - bar.Clean(); - - // - return result; - } - - /** - * Check Specified Bar Price is Over Boundary Min ... - * - * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool IsOverBoundaryMin( - ENUM_X_PRICE priceType = X_PRICE_CLOSE, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - if (!IsXValid(priceType)) - { - priceType = X_PRICE_CLOSE; - } - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Retrieve Boundary ... - double min; - double max; - result = GetBoundaryValues(min, max, barIndex); - if (!result) - { - return result; - } - - // - // Retrieve Bar .... - XOHCL bar; - result = bar.Init( - mSymbol, - mPeriod, - barIndex // - ); - if (!result) - { - // - bar.Clean(); - return result; - } - double value = bar.GetPrice(priceType); - - // - result = value > min; - - // - // Cleanup ... - bar.Clean(); - - // - return result; - } - - /** - * Check Specified Bar Price is Under Boundary Max ... - * - * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool IsUnderBoundaryMax( - ENUM_X_PRICE priceType = X_PRICE_CLOSE, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - if (!IsXValid(priceType)) - { - priceType = X_PRICE_CLOSE; - } - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Retrieve Boundary ... - double min; - double max; - result = GetBoundaryValues(min, max, barIndex); - if (!result) - { - return result; - } - - // - // Retrieve Bar .... - XOHCL bar; - result = bar.Init( - mSymbol, - mPeriod, - barIndex // - ); - if (!result) - { - // - bar.Clean(); - return result; - } - double value = bar.GetPrice(priceType); - - // - result = value < max; - - // - // Cleanup ... - bar.Clean(); - - // - return result; - } - - /** - * Check Boundary Fake Breaked or not ... - * - * @param dir: reference for holds cross Direction ... - * @param barIndex: int, Specified Bar Index ... - * @param overMaxPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... - * @param underMinPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... - * - * @return ( bool ) - */ - bool IsBoundaryFakeBreaked( - ENUM_X_DIRECTION &dir, - int barIndex = 0, - ENUM_X_PRICE overMaxPriceType = X_PRICE_NONE, - ENUM_X_PRICE underMinPriceType = X_PRICE_NONE // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - if (!IsXValid(overMaxPriceType)) - { - overMaxPriceType = X_PRICE_CLOSE; - } - if (!IsXValid(underMinPriceType)) - { - underMinPriceType = X_PRICE_CLOSE; - } - - // - // Initial Bars ... - XOHCL bar; - XOHCL pBar; - double min; - double max; - double pMin; - double pMax; - double boundaryValues[]; - result = - bar.Init( - mSymbol, - mPeriod, - barIndex // - ) && - bar.GetPreviousBar(pBar) && - GetBoundaryValues(min, max, barIndex) && - GetBoundaryValues(pMin, pMax, barIndex + 1) && - FillBoundaryValues(boundaryValues, barIndex) > 0; - - // - bool isBullish = - result && - pBar.IsBearish() && - bar.IsBullish() && - pBar.GetPrice(underMinPriceType) < pMin && - bar.GetPrice(underMinPriceType) > min && - (bar.GetPrice(underMinPriceType) > FindLesserThan(max, boundaryValues) || - bar.GetPrice(underMinPriceType) > FindBiggerThan(min + ((max - min) / 2), boundaryValues)); - - // - bool isBearish = - result && - pBar.IsBullish() && - bar.IsBearish() && - pBar.GetPrice(overMaxPriceType) > pMax && - bar.GetPrice(overMaxPriceType) < max && - (bar.GetPrice(overMaxPriceType) < FindBiggerThan(min, boundaryValues) || - bar.GetPrice(overMaxPriceType) < FindLesserThan(min + ((max - min) / 2), boundaryValues)); - - // - result = isBullish || - isBearish; - if (!result) - { - return result; - } - - // - dir = - isBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - - // - // Cleanup ... - bar.Clean(); - pBar.Clean(); - - // - return result; - } - - /** - * Check Specified Bar's Price in Hot Place or Not ... - * - * @param dir: reference for holds cross Direction ... - * @param barIndex: int, Specified Bar Index ... - * @param overMaxPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... - * @param underMinPriceType: ENUM_X_PRICE, which price of Specified bar to Check ... - * - * @return ( bool ) - */ - bool IsInHotPlace( - ENUM_X_DIRECTION &dir, - int barIndex = 0, - ENUM_X_PRICE overMaxPriceType = X_PRICE_NONE, - ENUM_X_PRICE underMinPriceType = X_PRICE_NONE // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - if (!IsXValid(overMaxPriceType)) - { - overMaxPriceType = X_PRICE_LOW; - } - if (!IsXValid(underMinPriceType)) - { - underMinPriceType = X_PRICE_HIGH; - } - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Initialize Bar ... - XOHCL bar; - result = bar.Init( - mSymbol, - mPeriod, - barIndex); - if (!result) - { - // - bar.Clean(); - return result; - } - - // - double overMaxPrice = bar.GetPrice(overMaxPriceType); - double underMinPrice = bar.GetPrice(underMinPriceType); - - // - // Reading Boundary Value ... - double min; - double max; - result = GetBoundaryValues( - min, - max, - barIndex // - ); - if (!result) - { - // - bar.Clean(); - return result; - } - - // - bool isBullish = underMinPrice < min; - bool isBearish = overMaxPrice > max; - - // - result = (isBullish && !isBearish) || - (isBearish && !isBullish); - if (result) - { - // - dir = - isBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - } - - // - // Cleanup Resources ... - bar.Clean(); - - // - return result; - } - - /** - * Check Specified Bar price Crossed in Boundary or not ... - * - * @param dir: ENUM_X_DIRECTION, reference to hold Crossed in Dir ... - * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool IsCrossedInBoundary( - ENUM_X_DIRECTION &dir, - ENUM_X_PRICE priceType = X_PRICE_CLOSE, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - int pBarIndex = barIndex + 1; - - // - if (!IsXValid(priceType)) - { - priceType = X_PRICE_CLOSE; - } - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Check PrevBar Is in Hot Place ... - result = IsInHotPlace( - dir, - pBarIndex, - X_PRICE_LOW, - X_PRICE_HIGH // - ); - if (!result) - { - // - dir = X_DIRECTION_NONE; - - // - return result; - } - - // - bool isBullish = IsXBullish(dir); - bool isBearish = IsXBearish(dir); - - // - // Current Bar must Into Boundary ... - result = IsInBoundary(priceType, barIndex); - if (!result) - { - dir = X_DIRECTION_NONE; - } - - // - result = HasDirection(dir); - - // - return result; - } - - /** - * Check Specified Bar price Crossed out Boundary or not ... - * - * @param dir: ENUM_X_DIRECTION, reference to hold Crossed in Dir ... - * @param priceType: ENUM_X_PRICE, Specified Price type of Bar ... - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool IsCrossedOutBoundary( - ENUM_X_DIRECTION &dir, - ENUM_X_PRICE priceType = X_PRICE_CLOSE, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - int pBarIndex = barIndex + 1; - - // - if (!IsXValid(priceType)) - { - priceType = X_PRICE_CLOSE; - } - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Prev Bar Must in Boundary ... - bool isBullish = IsInBoundary(X_PRICE_LOW, pBarIndex); - bool isBearish = IsInBoundary(X_PRICE_HIGH, pBarIndex); - result = isBullish || - isBearish; - if (!result) - { - return result; - } - - // - // Current Bar must Out of Boundary ... - - XOHCL bar; - result = bar.Init( - mSymbol, - mPeriod, - barIndex // - ); - - // - isBullish = - result && - isBullish && - bar.IsBullish() && - !IsInBoundary(priceType, barIndex); - - // - isBearish = - result && - isBearish && - bar.IsBearish() && - !IsInBoundary(priceType, barIndex); - - // - result = isBullish || - isBearish; - if (!result) - { - // - bar.Clean(); - return result; - } - - // - dir = isBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - - // - result = HasDirection(dir); - - // - // Cleanup ... - bar.Clean(); - - // - return result; - } - - /** - * Check Specified Bar has Boundary Trend or not ... - * - * @param dir: reference for holds cross Direction ... - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool HasBoundaryTrend( - ENUM_X_DIRECTION &dir, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - double fast = GetMAFast(barIndex); - double slow = GetMASlow(barIndex); - - // - double maBondUpper = GetMABondUpper(barIndex); - double maBondLower = GetMABondLower(barIndex); - - // - double pbBondUpper = GetPBBondUpper(barIndex); - double pbBondLower = GetPBBondLower(barIndex); - - // - double hkBondUpper = GetHKBondUpper(barIndex); - double hkBondLower = GetHKBondLower(barIndex); - - // - result = - NotEmptyZero(fast) && - NotEmptyZero(slow) && - NotEmptyZero(maBondUpper) && - NotEmptyZero(maBondLower) && - NotEmptyZero(hkBondUpper) && - NotEmptyZero(hkBondLower) && - NotEmptyZero(pbBondUpper) && - NotEmptyZero(pbBondLower); - if (!result) - { - return result; - } - - // - bool isBullish = - fast > hkBondLower && - slow > hkBondLower && - maBondUpper > hkBondLower && - maBondLower > hkBondLower && - pbBondUpper > hkBondLower && - pbBondLower > hkBondLower; - bool isBearish = - fast < hkBondUpper && - slow < hkBondUpper && - maBondUpper < hkBondUpper && - maBondLower < hkBondUpper && - pbBondUpper < hkBondUpper && - pbBondLower < hkBondUpper; - - // - result = (isBullish && !isBearish) || - (isBearish && !isBullish); - if (result) - { - // - dir = - isBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - } - - // - return result; - } - - /** - * Check Specified Bar has Boundary Trend Switched or not ... - * - * @param dir: reference for holds cross Direction ... - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool HasBoundarySwitch( - ENUM_X_DIRECTION &dir, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - result = HasBoundaryTrend( - dir, - barIndex // - ); - if (!result) - { - return result; - } - bool isBullish = IsXBullish(dir); - bool isBearish = IsXBearish(dir); - - // - result = HasBoundaryTrend( - dir, - barIndex + 1 // - ); - if (!result) - { - return result; - } - bool isPBullish = IsXBullish(dir); - bool isPBearish = IsXBearish(dir); - - // - bool isSwitchedToBullish = - isBullish && !isPBullish; - bool isSwitchedToBearish = - isBearish && !isPBearish; - result = isSwitchedToBullish || - isSwitchedToBearish; - if (result) - { - // - dir = isSwitchedToBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - } - - // - return result; - } - - /** - * Check Fibo Section is Changed or not ... - * - * @param dir: reference to hold section change direction ... - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool IsFiboSectionChanged( - ENUM_X_DIRECTION &dir, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - bool isBullish = false; - bool isBearish = false; - - // - // Reading Values ... - - // - double iFiboUpper = GetFiboUpper(barIndex); - double pFiboUpper = GetFiboUpper(barIndex + 1); - - // - double iFiboMiddle = GetFiboMiddle(barIndex); - double pFiboMiddle = GetFiboMiddle(barIndex + 1); - - // - double iFiboLower = GetFiboLower(barIndex); - double pFiboLower = GetFiboLower(barIndex + 1); - - // - isBullish = iFiboLower >= pFiboMiddle && - iFiboMiddle >= pFiboUpper; - isBearish = iFiboUpper <= pFiboMiddle && - iFiboMiddle <= pFiboLower; - result = (isBullish && !isBearish) || - (isBearish && !isBullish); - if (!result) - { - return result; - } - - // - dir = - isBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - - // - return result; - } - - /** - * Check for Fibo Push Exists or not ... - * - * @param dir: ENUM_X_DIRECTION, reference to hold result ... - * @param barIndex: int, Specified Bar Index ... - * @param validationLength: int, Validation Length ... - * - * @return ( bool ) - */ - bool HasFiboPush( - ENUM_X_DIRECTION &dir, - int barIndex = 0, - int validationLength = 5 // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - validationLength = NormalizeInt(validationLength, 3); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Define Requirements ... - - // - XOHCL iBar; - bool isBullish = false; - bool isBearish = false; - - // - double iFiboUpper = EMPTY_VALUE; - double pFiboUpper = EMPTY_VALUE; - - // - double iFiboMiddle = EMPTY_VALUE; - double pFiboMiddle = EMPTY_VALUE; - - // - double iFiboLower = EMPTY_VALUE; - double pFiboLower = EMPTY_VALUE; - - // - // Check Zone Validation ... - int start = barIndex; - int end = start + validationLength; - for (int i = start; i < end; i++) - { - // - // Reading Values ... - - // - iFiboUpper = GetFiboUpper(i); - pFiboUpper = GetFiboUpper(i + 1); - - // - iFiboMiddle = GetFiboMiddle(i); - pFiboMiddle = GetFiboMiddle(i + 1); - - // - iFiboLower = GetFiboLower(i); - pFiboLower = GetFiboLower(i + 1); - - // - result = iFiboUpper == pFiboUpper; - if (!result) - { - break; - } - } - - // - if (result) - { - // - result = iBar.Init( - mSymbol, - mPeriod, - barIndex // - ); - - // - if (result) - { - // - iFiboUpper = GetFiboUpper(barIndex); - iFiboMiddle = GetFiboMiddle(barIndex); - iFiboLower = GetFiboLower(barIndex); - - // - isBullish = iBar.IsBullish() && - iBar.close > iFiboLower && - iBar.low < iFiboLower; - isBearish = iBar.IsBearish() && - iBar.close < iFiboUpper && - iBar.high > iFiboUpper; - result = (isBullish && !isBearish) || - (isBearish && !isBullish); - if (result) - { - // - dir = - isBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - } - } - } - - // - // Cleanup Resources ... - iBar.Clean(); - - // - return result; - } - - /** - * Check Has Higher Low Based On ZigZag ... - * - * @param barIndex: int, Specified Bar Index ... - * @param forceBarValidation: bool, Force Bar Price based on Pivot ... - * - * @return ( bool ) - */ - bool HasZigZagHigherLow( - int barIndex = 0, - bool forceBarValidation = false // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - XOHCL bar; - result = IsValid() && - bar.Init( - mSymbol, - mPeriod, - barIndex // - ); - if (!result) - { - // - bar.Clean(); - - // - return result; - } - - // - // Extract Pivots ... - XPivot pivots[]; - int count = ExtractZigZagPivots( - pivots, - barIndex, - 10, - 200 // - ); - - // - // Validate Pivots and Nearest Pivot is Low ... - result = IsValidSize(count) && - pivots[0].IsVale(); - if (!result) - { - // - bar.Clean(); - XClean(pivots); - - // - return result; - } - - // - // Extract Directional Pivots ... - XPivot vales[]; - count = ExtractPivots( - vales, - pivots, - X_PIVOT_TYPE_VALE // - ); - result = IsValidSize(count) && - count >= 2; - if (!result) - { - // - bar.Clean(); - XClean(vales); - XClean(pivots); - - // - return result; - } - - // - // Check Result ... - result = - vales[0].value > vales[1].value; - if (forceBarValidation) - { - // - result = - result && - bar.open > vales[0].value && - bar.close > vales[0].value; - } - - // - // Cleanup ... - bar.Clean(); - XClean(vales); - XClean(pivots); - - // - return result; - } - - /** - * Check Has Lower Low Based On ZigZag ... - * - * @param barIndex: int, Specified Bar Index ... - * @param forceBarValidation: bool, Force Bar Price based on Pivot ... - * - * @return ( bool ) - */ - bool HasZigZagLowerLow( - int barIndex = 0, - bool forceBarValidation = false // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - XOHCL bar; - result = IsValid() && - bar.Init( - mSymbol, - mPeriod, - barIndex // - ); - if (!result) - { - // - bar.Clean(); - - // - return result; - } - - // - // Extract Pivots ... - XPivot pivots[]; - int count = ExtractZigZagPivots( - pivots, - barIndex, - 10, - 200 // - ); - - // - // Validate Pivots and Nearest Pivot is Low ... - result = IsValidSize(count) && - pivots[0].IsVale(); - if (!result) - { - // - bar.Clean(); - XClean(pivots); - - // - return result; - } - - // - // Extract Directional Pivots ... - XPivot vales[]; - count = ExtractPivots( - vales, - pivots, - X_PIVOT_TYPE_VALE // - ); - result = IsValidSize(count) && - count >= 2; - if (!result) - { - // - bar.Clean(); - XClean(vales); - XClean(pivots); - - // - return result; - } - - // - // Check Result ... - result = - vales[0].value < vales[1].value; - if (forceBarValidation) - { - // - result = - result && - bar.open < vales[0].value && - bar.close < vales[0].value; - } - - // - // Cleanup ... - bar.Clean(); - XClean(vales); - XClean(pivots); - - // - return result; - } - - /** - * Check Has Higher High Based On ZigZag ... - * - * @param barIndex: int, Specified Bar Index ... - * @param forceBarValidation: bool, Force Bar Price based on Pivot ... - * - * @return ( bool ) - */ - bool HasZigZagHigherHigh( - int barIndex = 0, - bool forceBarValidation = false // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - XOHCL bar; - result = IsValid() && - bar.Init( - mSymbol, - mPeriod, - barIndex // - ); - if (!result) - { - // - bar.Clean(); - - // - return result; - } - - // - // Extract Pivots ... - XPivot pivots[]; - int count = ExtractZigZagPivots( - pivots, - barIndex, - 10, - 200 // - ); - - // - // Validate Pivots and Nearest Pivot is Low ... - result = IsValidSize(count) && - pivots[0].IsPeak(); - if (!result) - { - // - bar.Clean(); - XClean(pivots); - - // - return result; - } - - // - // Extract Directional Pivots ... - XPivot peaks[]; - count = ExtractPivots( - peaks, - pivots, - X_PIVOT_TYPE_PEAK // - ); - result = IsValidSize(count) && - count >= 2; - if (!result) - { - // - bar.Clean(); - XClean(peaks); - XClean(pivots); - - // - return result; - } - - // - // Check Result ... - result = - peaks[0].value > peaks[1].value; - if (forceBarValidation) - { - // - result = - result && - bar.open > peaks[0].value && - bar.close > peaks[0].value; - } - - // - // Cleanup ... - bar.Clean(); - XClean(peaks); - XClean(pivots); - - // - return result; - } - - /** - * Check Has Lower High Based On ZigZag ... - * - * @param barIndex: int, Specified Bar Index ... - * @param forceBarValidation: bool, Force Bar Price based on Pivot ... - * - * @return ( bool ) - */ - bool HasZigZagLowerHigh( - int barIndex = 0, - bool forceBarValidation = false // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - XOHCL bar; - result = IsValid() && - bar.Init( - mSymbol, - mPeriod, - barIndex // - ); - if (!result) - { - // - bar.Clean(); - - // - return result; - } - - // - // Extract Pivots ... - XPivot pivots[]; - int count = ExtractZigZagPivots( - pivots, - barIndex, - 10, - 200 // - ); - - // - // Validate Pivots and Nearest Pivot is Low ... - result = IsValidSize(count) && - pivots[0].IsPeak(); - if (!result) - { - // - bar.Clean(); - XClean(pivots); - - // - return result; - } - - // - // Extract Directional Pivots ... - XPivot peaks[]; - count = ExtractPivots( - peaks, - pivots, - X_PIVOT_TYPE_PEAK // - ); - result = IsValidSize(count) && - count >= 2; - if (!result) - { - // - bar.Clean(); - XClean(peaks); - XClean(pivots); - - // - return result; - } - - // - // Check Result ... - result = - peaks[0].value < peaks[1].value; - if (forceBarValidation) - { - // - result = - result && - bar.open < peaks[0].value && - bar.close < peaks[0].value; - } - - // - // Cleanup ... - bar.Clean(); - XClean(peaks); - XClean(pivots); - - // - return result; - } - - // - // SAR ... - - /** - * Check Specified Bar has SAR Switch or not ... - * - * @param dir: reference for holds cross Direction ... - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool HasSARSwitch( - ENUM_X_DIRECTION &dir, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeInt(barIndex, 0); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - double sars[]; - int count = CopySarState(barIndex, 2, sars); - - // - bool isBullish = false; - bool isBearish = false; - - // - // Validate Readed Values ... - result = IsValidSize(count) && count >= 2; - if (result) - { - // - // Detect Direction Change ... - - // - isBullish = - sars[0] >= 1 && - sars[1] <= -1; - - // - isBearish = - sars[0] <= -1 && - sars[1] >= 1; - - // - result = - isBullish || - isBearish; - } - - // - if (result) - { - // - // Setting Direction ... - dir = - isBullish - ? X_DIRECTION_BULLISH - : isBearish - ? X_DIRECTION_BEARISH - : X_DIRECTION_NONE; - } - - // - // Cleanup Resources ... - XClean(sars); - - // - return result; - } - - bool IsSarBullish(int barIndex = 0) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - double state = GetSarState(barIndex); - result = state >= 1; - - // - return result; - } - - bool IsSarBearish(int barIndex = 0) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - double state = GetSarState(barIndex); - result = state <= -1; - - // - return result; - } - - bool IsSarSwitchedToBullish(int barIndex = 0) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - int pBarIndex = barIndex + 1; - - // - bool isBullish = IsSarBullish(barIndex); - bool isPBullish = IsSarBullish(pBarIndex); - - // - result = isBullish && - !isPBullish; - - // - return result; - } - - bool IsSarSwitchedToBearish(int barIndex = 0) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - int pBarIndex = barIndex + 1; - - // - bool isBearish = IsSarBearish(barIndex); - bool isPBearish = IsSarBearish(pBarIndex); - - // - result = isBearish && - !isPBearish; - - // - return result; - } - - // - // PV ... - - bool IsPeakSame(int barIndex = 0) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - double iC = GetPeak(barIndex); - double iP = GetPeak(barIndex + 1); - - // - result = iC == iP && - NotEmptyZero(iC); - - // - return result; - } - - bool IsValeSame(int barIndex = 0) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - double iC = GetVale(barIndex); - double iP = GetVale(barIndex + 1); - - // - result = iC == iP && - NotEmptyZero(iC); - - // - return result; - } - - /** - * Check Peak Happens over Last ... - * - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool IsPeakOverLast(int barIndex = 0) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Reading Values ... - - // - double iPeak = GetPeak(barIndex); - double pPeak = GetPeak(barIndex + 1); - - // - result = NotEmptyZero(iPeak) && - iPeak > pPeak; - - // - return result; - } - - /** - * Check Vale Happens over Last ... - * - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool IsValeOverLast(int barIndex = 0) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Reading Values ... - - // - double iVale = GetVale(barIndex); - double pVale = GetVale(barIndex + 1); - - // - result = NotEmptyZero(iVale) && - iVale > pVale; - - // - return result; - } - - /** - * Check Peak Happens under Last ... - * - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool IsPeakUnderLast(int barIndex = 0) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Reading Values ... - - // - double iPeak = GetPeak(barIndex); - double pPeak = GetPeak(barIndex + 1); - - // - result = NotEmptyZero(iPeak) && - iPeak < pPeak; - - // - return result; - } - - /** - * Check Vale Happens under Last ... - * - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool IsValeUnderLast(int barIndex = 0) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Reading Values ... - - // - double iVale = GetVale(barIndex); - double pVale = GetVale(barIndex + 1); - - // - result = NotEmptyZero(iVale) && - iVale < pVale; - - // - return result; - } - - /** - * Detect Last Peak Change ... - * - * @param index: int, reference to hold change index ... - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( bool ) - */ - bool FindLastPeakOverLast( - int &index, - int barIndex = 0, - int loopback = 500 // - ) - { - // - bool result = false; - - // - // Prepare ... - index = -1; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Loop ... - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - result = IsPeakOverLast(idx); - if (result) - { - // - index = idx; - break; - } - } - - // - result = IsValidIndex(index); - - // - return result; - } - - /** - * Detect Last Peak Change ... - * - * @param index: int, reference to hold change index ... - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( bool ) - */ - bool FindLastPeakUnderLast( - int &index, - int barIndex = 0, - int loopback = 500 // - ) - { - // - bool result = false; - - // - // Prepare ... - index = -1; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Loop ... - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - result = IsPeakUnderLast(idx); - if (result) - { - // - index = idx; - break; - } - } - - // - result = IsValidIndex(index); - - // - return result; - } - - /** - * Detect Last Vale Change ... - * - * @param index: int, reference to hold change index ... - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( bool ) - */ - bool FindLastValeOverLast( - int &index, - int barIndex = 0, - int loopback = 500 // - ) - { - // - bool result = false; - - // - // Prepare ... - index = -1; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Loop ... - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - result = IsValeOverLast(idx); - if (result) - { - // - index = idx; - break; - } - } - - // - result = IsValidIndex(index); - - // - return result; - } - - /** - * Detect Last Vale Change ... - * - * @param index: int, reference to hold change index ... - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( bool ) - */ - bool FindLastValeUnderLast( - int &index, - int barIndex = 0, - int loopback = 500 // - ) - { - // - bool result = false; - - // - // Prepare ... - index = -1; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Loop ... - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - result = IsValeUnderLast(idx); - if (result) - { - // - index = idx; - break; - } - } - - // - result = IsValidIndex(index); - - // - return result; - } - - /** - * Count Same Peaks ... - * - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( int ) - */ - int CountSamePeaks( - int barIndex = 0, - int loopback = 500 // - ) - { - // - int result = 0; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - bool has = IsValid(); - if (!has) - { - return result; - } - - // - double iPeak = EMPTY_VALUE; - double peak = GetPeak(barIndex); - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - iPeak = GetPeak(idx); - has = peak == iPeak; - if (has) - { - result++; - } - if (!has) - { - break; - } - } - - // - return result; - } - - /** - * Count Same Vales ... - * - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( int ) - */ - int CountSameVales( - int barIndex = 0, - int loopback = 500 // - ) - { - // - int result = 0; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - bool has = IsValid(); - if (!has) - { - return result; - } - - // - double iVale = EMPTY_VALUE; - double vale = GetVale(barIndex); - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - iVale = GetVale(idx); - has = vale == iVale; - if (has) - { - result++; - } - if (!has) - { - break; - } - } - - // - return result; - } - - bool HasPVConsolidationZone( - XBoxZone &zone, - int barIndex = 0, - bool forcePVBreak = false, - bool forceHasSarSwitch = false // - ) - { - // - bool result = false; - - // - // Prepare ... - zone.Clean(); - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Do ... - - // - bool isPeakSame = IsPeakSame(barIndex); - bool isValeSame = IsValeSame(barIndex); - result = !(isPeakSame && - isValeSame); - if (!result) - { - return result; - } - - // - double iPeak = EMPTY_VALUE; - double iVale = EMPTY_VALUE; - - // - int idx = barIndex; - bool canLookup = true; - while (canLookup) - { - // - idx++; - isPeakSame = IsPeakSame(idx); - isValeSame = IsValeSame(idx); - result = isPeakSame && - isValeSame; - if (!result) - { - // - zone.from = GetBarTime(mSymbol, mPeriod, idx); - break; - } - - // - if (idx == barIndex + 1) - { - // - zone.to = GetBarTime( - mSymbol, - mPeriod, - idx // - ); - } - - // - zone.from = GetBarTime( - mSymbol, - mPeriod, - idx // - ); - - // - iPeak = GetPeak(idx); - iVale = GetVale(idx); - - // - zone.lower = - !NotEmptyZero(zone.lower) - ? iVale - : MathMin(zone.lower, iVale); - - // - zone.upper = - !NotEmptyZero(zone.upper) - ? iPeak - : MathMax(zone.upper, iPeak); - } - - // - // Validating Zone Params ... - result = - // - IsXValid(zone.to) && - IsXValid(zone.from) && - zone.from < zone.to && - // - NotEmptyZero(zone.lower) && - NotEmptyZero(zone.upper) && - zone.upper > zone.lower - // - ; - - // - // Prepare Zone ... - if (result) - { - // - iPeak = GetPeak(barIndex); - iVale = GetVale(barIndex); - bool isPeakOverLast = IsPeakOverLast(barIndex); - bool isValeUnderLast = IsValeUnderLast(barIndex); - bool isValeBreak = iVale < zone.lower; - bool isPeakBreak = iPeak > zone.upper; - bool isPVBreak = isPeakBreak || - isValeBreak; - - // - zone.at = GetBarTime(mSymbol, mPeriod, barIndex); - zone.symbol = mSymbol; - zone.period = mPeriod; - zone.dir = (isPeakOverLast && !isValeUnderLast && isPVBreak) - ? X_DIRECTION_BULLISH - : (isValeUnderLast && !isPeakOverLast && isPVBreak) - ? X_DIRECTION_BEARISH - : X_DIRECTION_NONE; - zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION); - - // - // Refine Zone Upper and Lower ... - if (zone.IsValid()) - { - // - XOHCL iBar; - int zoneLoopback = zone.FromIndex() - zone.ToIndex(); - result = zone.ToBar(iBar) && - IsValidSize(zoneLoopback); - if (result) - { - // - double zoneLL = iBar.FindLowest(zoneLoopback, MODE_LOW); - double zoneHH = iBar.FindHighest(zoneLoopback, MODE_HIGH); - result = NotEmptyZero(zoneLL) && - NotEmptyZero(zoneHH); - if (result) - { - // - zone.lower = zone.lower == zoneLL - ? zone.lower - : MathMax(zone.lower, zoneLL); - - // - zone.upper = zone.upper == zoneHH - ? zone.upper - : MathMin(zone.upper, zoneHH); - } - } - - // - iBar.Clean(); - } - - // - // Validate ... - result = zone.IsValid(); - } - - // - // Validate Zones From ... - if (result) - { - // - int idx = zone.FromIndex(); - - // - iPeak = GetPeak(idx); - iVale = GetVale(idx); - - // - bool isValeOverLast = IsValeOverLast(idx); - bool isPeakUnderLast = IsPeakUnderLast(idx); - - // - result = - result && - (zone.IsBullish() - ? !isPeakUnderLast - : zone.IsBearish() - ? !isValeOverLast - : false); - } - - // - // Apply Forces ... - - // - // PV Break ... - // Peak or Vale must Breaked at Bar ... - if (result && forcePVBreak) - { - // - bool isPVBreaked = - (zone.IsBullish() && IsPeakOverLast(barIndex)) || - (zone.IsBearish() && IsValeUnderLast(barIndex)); - - // - result = result && - isPVBreaked; - } - - // - // Other Loop based Forces ... - if (result && (forceHasSarSwitch)) - { - - // - bool hasSarSwitch = false; - - // - int start = zone.ToIndex(); - int end = zone.FromIndex(); - for (int i = start; i <= end; i++) - { - // - // Check Sar Switches ... - if (forceHasSarSwitch && !hasSarSwitch) - { - // - hasSarSwitch = - zone.IsBullish() - ? IsSarSwitchedToBullish(i) - : IsSarSwitchedToBearish(i); - } - } - - // - // Validate Forces ... - if (forceHasSarSwitch) - { - // - result = - result && - hasSarSwitch; - } - } - - // - // Cleanup ... - if (!result) - { - zone.Clean(); - } - - // - return result; - } - - // - // HK ... - - /** - * Check Specified Bar has HK Switch or not ... - * - * @param dir: reference for holds cross Direction ... - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool HasHKSwitch( - ENUM_X_DIRECTION &dir, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeInt(barIndex, 0); - - // - double open[]; - int openCount = CopyHKOpen(barIndex, 2, open); - - // - double close[]; - int closeCount = CopyHKClose(barIndex, 2, close); - - // - bool isBullish = false; - bool isBearish = false; - - // - // Validate Readed Values ... - int count = MathMin(openCount, closeCount); - result = IsValidSize(count) && count >= 2; - if (result) - { - // - // Detect Direction Change ... - - // - bool notEmpty = - NotEmptyZero(open[0]) && - NotEmptyZero(open[1]) && - NotEmptyZero(close[0]) && - NotEmptyZero(close[1]); - - // - isBullish = - notEmpty && - open[0] < close[0] && - open[1] > close[1]; - - // - isBearish = - notEmpty && - open[0] > close[0] && - open[1] < close[1]; - - // - result = - isBullish || - isBearish; - } - - // - if (result) - { - // - // Setting Direction ... - dir = - isBullish - ? X_DIRECTION_BULLISH - : isBearish - ? X_DIRECTION_BEARISH - : X_DIRECTION_NONE; - } - - // - // Cleanup Resources ... - XClean(open); - XClean(close); - - // - return result; - } - - /** - * Check Specified Bar has HK Bond Based Trend or not ... - * - * @param dir: ENUM_X_DIRECTION, reference to holds trend direction, if exists ... - * @param barIndex: int, Specified Bar Index ... - * @param validationLength: int, validation of trend ... - * - * @return ( bool ) - */ - bool HasHKBasedTrend( - ENUM_X_DIRECTION &dir, - int barIndex = 0, - int validationLength = 5 // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - validationLength = NormalizeInt(validationLength, 1); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Do ... - - // - // Define Requirements ... - XOHCL iBar; - double hkUpper; - double hkLower; - bool has = false; - int bullishCount = 0; - int bearishCount = 0; - bool isBullish = false; - bool isBearish = false; - - // - // Count Bullish/Bearish Directions ... - int start = barIndex + 1; - int end = start + validationLength; - for (int i = start; i < end; i++) - { - // - // Reading Requirements ... - - // - // Read Indexed Bar ... - iBar.Clean(); - result = iBar.Init( - mSymbol, - mPeriod, - i // - ); - if (!result) - { - break; - } - - // - // Reading Values ... - hkUpper = GetHKBondUpper(i); - hkLower = GetHKBondLower(i); - result = NotEmptyZero(hkUpper) && - NotEmptyZero(hkLower); - if (!result) - { - return result; - } - - // - // Check Trend ... - - // - // Bullish ... - isBullish = iBar.low > hkLower; - if (isBullish) - { - bullishCount++; - } - - // - // Bearish ... - isBearish = iBar.high < hkUpper; - if (isBearish) - { - bearishCount++; - } - - // - iBar.Clean(); - - // - } - - // - // Validate Results ... - isBullish = - bullishCount >= validationLength; - isBearish = - bearishCount >= validationLength; - - // - result = (isBullish && !isBearish) || - (isBearish && !isBullish); - - // - // Setting Direction if Has Trend ... - if (result) - { - // - dir = isBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - } - - // - // Cleanup ... - iBar.Clean(); - - // - return result; - } - - /** - * Check Specified Bar has HK Bond Based Trend Switch or not ... - * - * @param dir: ENUM_X_DIRECTION, reference to holds trend direction, if exists ... - * @param barIndex: int, Specified Bar Index ... - * @param validationLength: int, validation of trend ... - * - * @return ( bool ) - */ - bool IsHKBasedTrendSwitch( - ENUM_X_DIRECTION &dir, - int barIndex = 0, - int validationLength = 5 // - ) - { - // - bool result = false; - - // - // Prepare ... - dir = X_DIRECTION_NONE; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - validationLength = NormalizeInt(validationLength, 1); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - // Do ... - - // - bool hasTrend = HasHKBasedTrend( - dir, - barIndex, - validationLength // - ); - bool isBullish = hasTrend && - IsXBullish(dir); - bool isBearish = hasTrend && - IsXBearish(dir); - - // - bool hasPTrend = HasHKBasedTrend( - dir, - barIndex + 1, - validationLength // - ); - bool isPBullish = hasPTrend && - IsXBullish(dir); - bool isPBearish = hasPTrend && - IsXBearish(dir); - - // - dir = X_DIRECTION_NONE; - - // - // Checking Result ... - isBullish = isBullish && !isPBullish; - isBearish = isBearish && !isPBearish; - - // - result = - (isBullish && !isBearish) || - (isBearish && !isBullish); - if (result) - { - // - dir = isBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - } - - // - // Cleanup ... - - // - return result; - } - - /** - * Check if Price Over HK Bond Upper or not ... - * - * @param priceType: ENUM_X_PRICE, Specified Price type ... - * @param barIndex: int, Specified Bar index ... - * - * @return ( bool ) - */ - bool IsOverHKBondUpper( - ENUM_X_PRICE priceType = X_PRICE_LOW, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - XOHCL bar; - result = bar.Init(mSymbol, mPeriod, barIndex); - if (!result) - { - // - bar.Clean(); - return result; - } - - // - double price = bar.GetPrice(priceType); - double value = GetHKBondUpper(barIndex); - result = NotEmptyZero(price) && - NotEmptyZero(value) && - price > value; - - // - // Cleanup ... - bar.Clean(); - - // - return result; - } - - /** - * Check if Price Over HK Bond Lower or not ... - * - * @param priceType: ENUM_X_PRICE, Specified Price type ... - * @param barIndex: int, Specified Bar index ... - * - * @return ( bool ) - */ - bool IsOverHKBondLower( - ENUM_X_PRICE priceType = X_PRICE_LOW, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - XOHCL bar; - result = bar.Init(mSymbol, mPeriod, barIndex); - if (!result) - { - // - bar.Clean(); - return result; - } - - // - double price = bar.GetPrice(priceType); - double value = GetHKBondLower(barIndex); - result = NotEmptyZero(price) && - NotEmptyZero(value) && - price > value; - - // - // Cleanup ... - bar.Clean(); - - // - return result; - } - - /** - * Check if Price Under HK Bond Upper or not ... - * - * @param priceType: ENUM_X_PRICE, Specified Price type ... - * @param barIndex: int, Specified Bar index ... - * - * @return ( bool ) - */ - bool IsUnderHKBondUpper( - ENUM_X_PRICE priceType = X_PRICE_HIGH, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - XOHCL bar; - result = bar.Init(mSymbol, mPeriod, barIndex); - if (!result) - { - // - bar.Clean(); - return result; - } - - // - double price = bar.GetPrice(priceType); - double value = GetHKBondUpper(barIndex); - result = NotEmptyZero(price) && - NotEmptyZero(value) && - price < value; - - // - // Cleanup ... - bar.Clean(); - - // - return result; - } - - /** - * Check if Price Under HK Bond Lower or not ... - * - * @param priceType: ENUM_X_PRICE, Specified Price type ... - * @param barIndex: int, Specified Bar index ... - * - * @return ( bool ) - */ - bool IsUnderHKBondLower( - ENUM_X_PRICE priceType = X_PRICE_HIGH, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - XOHCL bar; - result = bar.Init(mSymbol, mPeriod, barIndex); - if (!result) - { - // - bar.Clean(); - return result; - } - - // - double price = bar.GetPrice(priceType); - double value = GetHKBondLower(barIndex); - result = NotEmptyZero(price) && - NotEmptyZero(value) && - price < value; - - // - // Cleanup ... - bar.Clean(); - - // - return result; - } - - /** - * Check Price Switched Over HK Bond Upper or not ... - * - * @param priceType: ENUM_X_PRICE, Specified Price type ... - * @param barIndex: int, Specified Bar index ... - * - * @return ( bool ) - */ - bool IsSwitchedOverHKBondUpper( - ENUM_X_PRICE priceType = X_PRICE_HIGH, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - int pBarIndex = barIndex + 1; - bool isBarPassed = IsOverHKBondUpper(priceType, barIndex); - bool isPBarPassed = !IsOverHKBondUpper(priceType, pBarIndex); - - // - result = isBarPassed && isPBarPassed; - - // - // Cleanup ... - - // - return result; - } - - /** - * Check Price Switched Under HK Bond Upper or not ... - * - * @param priceType: ENUM_X_PRICE, Specified Price type ... - * @param barIndex: int, Specified Bar index ... - * - * @return ( bool ) - */ - bool IsSwitchedUnderHKBondUpper( - ENUM_X_PRICE priceType = X_PRICE_LOW, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - int pBarIndex = barIndex + 1; - bool isBarPassed = IsUnderHKBondUpper(priceType, barIndex); - bool isPBarPassed = !IsUnderHKBondUpper(priceType, pBarIndex); - - // - result = isBarPassed && isPBarPassed; - - // - // Cleanup ... - - // - return result; - } - - /** - * Check Price Switched Over HK Bond Lower or not ... - * - * @param priceType: ENUM_X_PRICE, Specified Price type ... - * @param barIndex: int, Specified Bar index ... - * - * @return ( bool ) - */ - bool IsSwitchedOverHKBondLower( - ENUM_X_PRICE priceType = X_PRICE_LOW, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - int pBarIndex = barIndex + 1; - bool isBarPassed = IsOverHKBondLower(priceType, barIndex); - bool isPBarPassed = !IsOverHKBondLower(priceType, pBarIndex); - - // - result = isBarPassed && isPBarPassed; - - // - // Cleanup ... - - // - return result; - } - - /** - * Check Price Switched Under HK Bond Lower or not ... - * - * @param priceType: ENUM_X_PRICE, Specified Price type ... - * @param barIndex: int, Specified Bar index ... - * - * @return ( bool ) - */ - bool IsSwitchedUnderHKBondLower( - ENUM_X_PRICE priceType = X_PRICE_HIGH, - int barIndex = 0 // - ) - { - // - bool result = false; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - int pBarIndex = barIndex + 1; - bool isBarPassed = IsUnderHKBondLower(priceType, barIndex); - bool isPBarPassed = !IsUnderHKBondLower(priceType, pBarIndex); - - // - result = isBarPassed && isPBarPassed; - - // - // Cleanup ... - - // - return result; - } - - /** - * Detect Previous HK Bond ... - * - * @param index: int, reference to holds index ... - * @param priceType: ENUM_X_PRICE, Specified Price Type ... - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( bool ) - */ - bool FindLastOverHKBondUpper( - int &index, - ENUM_X_PRICE priceType = X_PRICE_HIGH, - int barIndex = 0, - int loopback = 500 // - ) - { - // - bool result = false; - - // - // Prepare ... - index = -1; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - result = IsOverHKBondUpper(priceType, idx); - if (result) - { - // - index = idx - 1; - break; - } - } - - // - result = IsValidIndex(index); - - // - // Cleanup ... - - // - return result; - } - - /** - * Detect Previous HK Bond ... - * - * @param index: int, reference to holds index ... - * @param priceType: ENUM_X_PRICE, Specified Price Type ... - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( bool ) - */ - bool FindLastUnderHKBondUpper( - int &index, - ENUM_X_PRICE priceType = X_PRICE_HIGH, - int barIndex = 0, - int loopback = 500 // - ) - { - // - bool result = false; - - // - // Prepare ... - index = -1; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - result = IsUnderHKBondUpper(priceType, idx); - if (result) - { - // - index = idx - 1; - break; - } - } - - // - result = IsValidIndex(index); - - // - // Cleanup ... - - // - return result; - } - - /** - * Detect Previous HK Bond ... - * - * @param index: int, reference to holds index ... - * @param priceType: ENUM_X_PRICE, Specified Price Type ... - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( bool ) - */ - bool FindLastOverHKBondLower( - int &index, - ENUM_X_PRICE priceType = X_PRICE_HIGH, - int barIndex = 0, - int loopback = 500 // - ) - { - // - bool result = false; - - // - // Prepare ... - index = -1; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - result = IsOverHKBondLower(priceType, idx); - if (result) - { - // - index = idx - 1; - break; - } - } - - // - result = IsValidIndex(index); - - // - // Cleanup ... - - // - return result; - } - - /** - * Detect Previous HK Bond ... - * - * @param index: int, reference to holds index ... - * @param priceType: ENUM_X_PRICE, Specified Price Type ... - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( bool ) - */ - bool FindLastUnderHKBondLower( - int &index, - ENUM_X_PRICE priceType = X_PRICE_HIGH, - int barIndex = 0, - int loopback = 500 // - ) - { - // - bool result = false; - - // - // Prepare ... - index = -1; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - result = IsUnderHKBondLower(priceType, idx); - if (result) - { - // - index = idx - 1; - break; - } - } - - // - result = IsValidIndex(index); - - // - // Cleanup ... - - // - return result; - } - - /** - * Detect Previous HK Bond Switch ... - * - * @param index: int, reference to holds switched index ... - * @param priceType: ENUM_X_PRICE, Specified Price Type ... - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( bool ) - */ - bool FindLastSwitchedOverHKBondUpper( - int &index, - ENUM_X_PRICE priceType = X_PRICE_HIGH, - int barIndex = 0, - int loopback = 500 // - ) - { - // - bool result = false; - - // - // Prepare ... - index = -1; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - result = IsSwitchedOverHKBondUpper(priceType, idx); - if (result) - { - // - index = idx - 1; - break; - } - } - - // - result = IsValidIndex(index); - - // - // Cleanup ... - - // - return result; - } - - /** - * Detect Previous HK Bond Switch ... - * - * @param index: int, reference to holds switched index ... - * @param priceType: ENUM_X_PRICE, Specified Price Type ... - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( bool ) - */ - bool FindLastSwitchedUnderHKBondUpper( - int &index, - ENUM_X_PRICE priceType = X_PRICE_HIGH, - int barIndex = 0, - int loopback = 500 // - ) - { - // - bool result = false; - - // - // Prepare ... - index = -1; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - result = IsSwitchedUnderHKBondUpper(priceType, idx); - if (result) - { - // - index = idx - 1; - break; - } - } - - // - result = IsValidIndex(index); - - // - // Cleanup ... - - // - return result; - } - - /** - * Detect Previous HK Bond Switch ... - * - * @param index: int, reference to holds switched index ... - * @param priceType: ENUM_X_PRICE, Specified Price Type ... - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( bool ) - */ - bool FindLastSwitchedOverHKBondLower( - int &index, - ENUM_X_PRICE priceType = X_PRICE_HIGH, - int barIndex = 0, - int loopback = 500 // - ) - { - // - bool result = false; - - // - // Prepare ... - index = -1; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - result = IsSwitchedOverHKBondLower(priceType, idx); - if (result) - { - // - index = idx - 1; - break; - } - } - - // - result = IsValidIndex(index); - - // - // Cleanup ... - - // - return result; - } - - /** - * Detect Previous HK Bond Switch ... - * - * @param index: int, reference to holds switched index ... - * @param priceType: ENUM_X_PRICE, Specified Price Type ... - * @param barIndex: int, Specified Bar Index ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( bool ) - */ - bool FindLastSwitchedUnderHKBondLower( - int &index, - ENUM_X_PRICE priceType = X_PRICE_HIGH, - int barIndex = 0, - int loopback = 500 // - ) - { - // - bool result = false; - - // - // Prepare ... - index = -1; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - IsXValid(priceType); - if (!result) - { - return result; - } - - // - // Do ... - - // - int idx = barIndex; - while (idx < barIndex + loopback) - { - // - idx++; - result = IsSwitchedUnderHKBondLower(priceType, idx); - if (result) - { - // - index = idx - 1; - break; - } - } - - // - result = IsValidIndex(index); - - // - // Cleanup ... - - // - return result; - } - - /** - * Count Over HK Bond Bars ... - * - * @param barIndex: int, Specified Bar Index ... - * @param priceType: ENUM_X_PRICE, Specified Price Type ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( int ) - */ - int CountOverHKBondLower( - int barIndex = 0, - ENUM_X_PRICE priceType = X_PRICE_CLOSE, - int loopback = 500 // - ) - { - // - int result = 0; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - bool has = IsValid() && - IsXValid(priceType); - if (!has) - { - return result; - } - - // - XOHCL iBar; - int idx = barIndex; - double iValue = EMPTY_VALUE; - double iPrice = EMPTY_VALUE; - while (idx < barIndex + loopback) - { - // - idx++; - iBar.Clean(); - has = iBar.Init(mSymbol, mPeriod, idx); - if (!has) - { - break; - } - - // - iValue = GetHKBondLower(idx); - iPrice = iBar.GetPrice(priceType); - - // - has = iPrice > iValue; - if (has) - { - result++; - } - if (!has) - { - break; - } - } - - // - return result; - } - - /** - * Count Under HK Bond Bars ... - * - * @param barIndex: int, Specified Bar Index ... - * @param priceType: ENUM_X_PRICE, Specified Price Type ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( int ) - */ - int CountUnderHKBondLower( - int barIndex = 0, - ENUM_X_PRICE priceType = X_PRICE_CLOSE, - int loopback = 500 // - ) - { - // - int result = 0; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - bool has = IsValid() && - IsXValid(priceType); - if (!has) - { - return result; - } - - // - XOHCL iBar; - int idx = barIndex; - double iValue = EMPTY_VALUE; - double iPrice = EMPTY_VALUE; - while (idx < barIndex + loopback) - { - // - idx++; - iBar.Clean(); - has = iBar.Init(mSymbol, mPeriod, idx); - if (!has) - { - break; - } - - // - iValue = GetHKBondLower(idx); - iPrice = iBar.GetPrice(priceType); - - // - has = iPrice < iValue; - if (has) - { - result++; - } - if (!has) - { - break; - } - } - - // - return result; - } - - /** - * Count Over HK Bond Bars ... - * - * @param barIndex: int, Specified Bar Index ... - * @param priceType: ENUM_X_PRICE, Specified Price Type ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( int ) - */ - int CountOverHKBondUpper( - int barIndex = 0, - ENUM_X_PRICE priceType = X_PRICE_CLOSE, - int loopback = 500 // - ) - { - // - int result = 0; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - bool has = IsValid() && - IsXValid(priceType); - if (!has) - { - return result; - } - - // - XOHCL iBar; - int idx = barIndex; - double iValue = EMPTY_VALUE; - double iPrice = EMPTY_VALUE; - while (idx < barIndex + loopback) - { - // - idx++; - iBar.Clean(); - has = iBar.Init(mSymbol, mPeriod, idx); - if (!has) - { - break; - } - - // - iValue = GetHKBondUpper(idx); - iPrice = iBar.GetPrice(priceType); - - // - has = iPrice > iValue; - if (has) - { - result++; - } - if (!has) - { - break; - } - } - - // - return result; - } - - /** - * Count Under HK Bond Bars ... - * - * @param barIndex: int, Specified Bar Index ... - * @param priceType: ENUM_X_PRICE, Specified Price Type ... - * @param loopback: int, Max Allowed Loopback Length ... - * - * @return ( int ) - */ - int CountUnderHKBondUpper( - int barIndex = 0, - ENUM_X_PRICE priceType = X_PRICE_CLOSE, - int loopback = 500 // - ) - { - // - int result = 0; - - // - // Normalize ... - loopback = NormalizeInt(loopback, 50); - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - bool has = IsValid() && - IsXValid(priceType); - if (!has) - { - return result; - } - - // - XOHCL iBar; - int idx = barIndex; - double iValue = EMPTY_VALUE; - double iPrice = EMPTY_VALUE; - while (idx < barIndex + loopback) - { - // - idx++; - iBar.Clean(); - has = iBar.Init(mSymbol, mPeriod, idx); - if (!has) - { - break; - } - - // - iValue = GetHKBondUpper(idx); - iPrice = iBar.GetPrice(priceType); - - // - has = iPrice < iValue; - if (has) - { - result++; - } - if (!has) - { - break; - } - } - - // - return result; - } - - // - // ZigZag Pivots With Liquidity ... - - /** - * Check ZigZag has Lower Low by Liquidity or Not ... - * - * @param barIndex: int, Specified Bar Index ... - * @param forceBarValidation: bool, Force Bar Price based on Pivot ... - * - * @return ( bool ) - */ - bool HasZigZagLowerLowByLiquidity( - int barIndex = 0, - bool forceBarValidation = false // - ) - { - // - bool result = false; - - // - // Normalize ... - XOHCL bar; - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - bar.Init( - mSymbol, - mPeriod, - barIndex // - ); - if (!result) - { - // - bar.Clean(); - return result; - } - - // - // Extract Pivots ... - XPivot pivots[]; - int count = ExtractZigZagPivots( - pivots, - barIndex, - 10, - 200 // - ); - - // - // Validate Pivots and Nearest Pivot is Low ... - result = IsValidSize(count) && - pivots[0].IsVale(); - if (!result) - { - // - bar.Clean(); - XClean(pivots); - - // - return result; - } - - // - // Extract Directional Pivots ... - XPivot selected[]; - count = ExtractPivots( - selected, - pivots, - X_PIVOT_TYPE_VALE // - ); - result = IsValidSize(count) && - count >= 3; - if (!result) - { - // - bar.Clean(); - XClean(pivots); - XClean(selected); - - // - return result; - } - - // - // Do Calculations ... - result = - // - // Check Pivot ... - selected[0].value < selected[1].value && - // - // Check Liquidity ... - selected[1].value > selected[2].value && - // - // Check Bar Place ... - (!forceBarValidation - ? true - : bar.open > selected[0].value && - bar.close > selected[0].value); - - // - // Cleanup ... - bar.Clean(); - XClean(pivots); - XClean(selected); - - // - return result; - } - - /** - * Check ZigZag has Higher High by Liquidity or Not ... - * - * @param barIndex: int, Specified Bar Index ... - * @param forceBarValidation: bool, Force Bar Price based on Pivot ... - * - * @return ( bool ) - */ - bool HasZigZagHigherHighByLiquidity( - int barIndex = 0, - bool forceBarValidation = false // - ) - { - // - bool result = false; - - // - // Normalize ... - XOHCL bar; - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid() && - bar.Init( - mSymbol, - mPeriod, - barIndex // - ); - if (!result) - { - // - bar.Clean(); - return result; - } - - // - // Extract Pivots ... - XPivot pivots[]; - int count = ExtractZigZagPivots( - pivots, - barIndex, - 10, - 200 // - ); - - // - // Validate Pivots and Nearest Pivot is Low ... - result = IsValidSize(count) && - pivots[0].IsPeak(); - if (!result) - { - // - bar.Clean(); - XClean(pivots); - - // - return result; - } - - // - // Extract Directional Pivots ... - XPivot selected[]; - count = ExtractPivots( - selected, - pivots, - X_PIVOT_TYPE_PEAK // - ); - result = IsValidSize(count) && - count >= 3; - if (!result) - { - // - bar.Clean(); - XClean(pivots); - XClean(selected); - - // - return result; - } - - // - // Do Calculations ... - result = - // - // Check Pivot ... - selected[0].value > selected[1].value && - // - // Check Liquidity ... - selected[1].value < selected[2].value && - // - // Check Bar Place ... - (!forceBarValidation - ? true - : bar.open < selected[0].value && - bar.close < selected[0].value); - - // - // Cleanup ... - bar.Clean(); - XClean(pivots); - XClean(selected); - - // - return result; - } - - // - // Extractions ... - - /** - * Extract Specified Kind of Pivots ... - * - * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... - * @param barIndex: int, Specified Bar Index ... - * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... - * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... - * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... - * - * @return ( int ) - */ - int ExtractPVPivots( - XPivot &pivots[], - int barIndex = 0, - int requiredNumberOFPivots = 50, - int maxAllowedLoopbackLength = 1500, - int validationLength = 0 // - ) - { - // - int result = 0; - - // - // Prepare ... - SpecifiedClean(pivots); - - // - // Normalize ... - barIndex = NormalizeInt(barIndex, 0); - validationLength = NormalizeInt(validationLength, 0); - requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); - maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); - - // - // Validate ... - if (mHandler == INVALID_HANDLE) - { - return result; - } - - // - bool lookupPeaks = true; - bool lookupVales = true; - - // - XOHCL iBar; - XPivot iPivot; - bool has = false; - int idx = barIndex - 1; - int samePeaksCount = 0; - int sameValesCount = 0; - double tmpPeaksBuffer[]; - double tmpValesBuffer[]; - string symbol = GetSymbol(); - double iPValue = EMPTY_VALUE; - double iVValue = EMPTY_VALUE; - double pPValue = EMPTY_VALUE; - double pVValue = EMPTY_VALUE; - ENUM_TIMEFRAMES period = GetPeriod(); - ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; - ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; - int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; - while (idx < maxAllowed && - ArraySize(pivots) < requiredNumberOFPivots) - { - // - idx++; - - // - // Prepare ... - iBar.Clean(); - iPivot.Clean(); - SpecifiedClean(tmpPeaksBuffer); - SpecifiedClean(tmpValesBuffer); - - // - // Ignore First Item ... - if (idx == barIndex) - { - continue; - } - - // - // Initialize Bar ... - has = iBar.Init( - symbol, - period, - idx // - ); - if (!has) - { - continue; - } - - // - // Detecting ... - - // - // Peak ... - if (lookupPeaks) - { - // - // Reading Buffer ... - CopyBuffer( - mHandler, // Handler ... - XFIMA_PEAK_LINE, // Handler Buffer Number ... - idx, // Bar Index ... - 2, // Number of Requirements ... - tmpPeaksBuffer // Buffer ... - ); - ArraySetAsSeries(tmpPeaksBuffer, true); - - // - // Reading Values ... - iPValue = tmpPeaksBuffer[0]; - pPValue = tmpPeaksBuffer[1]; - - // - // Validate Value ... - if (NotEmptyZero(iPValue)) - { - // - // Check New Peak ... - has = - !NotEmptyZero(pPValue) - ? true - : iPValue != pPValue; - if (has) - { - // - // Calculate and Validate Type ... - // Peaks Only Valid when Confirmed by Bar High ... - iType = - iPValue == iBar.high - ? X_PIVOT_TYPE_PEAK - : X_PIVOT_TYPE_NONE; - has = IsXValid(iType); - - // - // Calculate and Validate Dir ... - iDir = IsXPeak(iType) - ? X_DIRECTION_BEARISH - : X_DIRECTION_NONE; - has = has && - HasDirection(iDir); - - // - // Check Validation Length ... - has = - has && - (validationLength <= 0 - ? true - : samePeaksCount >= validationLength); - if (has) - { - // - // Initialize and Validate Pivot ... - has = iPivot.Init( - iPValue, - iBar.time, - symbol, - iDir, - period, - iType // - ); - if (has) - { - // - iPivot.prefix = ToXString(XFIMA_PIVOT_PV); - - // - // Add Pivot to Collection only if not Exists ... - AddIfNotExists( - iPivot, - pivots // - ); - } - } - - // - // Cleanup Resources ... - iPivot.Clean(); - samePeaksCount = 0; - } - else if (iPValue == pPValue) - { - samePeaksCount++; - } - } - } - - // - // Vale ... - if (lookupVales) - { - // - // Reading Buffer ... - CopyBuffer( - mHandler, // Handler ... - XFIMA_VALE_LINE, // Handler Buffer Number ... - idx, // Bar Index ... - 2, // Number of Requirements ... - tmpValesBuffer // Buffer ... - ); - ArraySetAsSeries(tmpValesBuffer, true); - - // - // Reading Values ... - iVValue = tmpValesBuffer[0]; - pVValue = tmpValesBuffer[1]; - - // - // Validate Value ... - if (NotEmptyZero(iVValue)) - { - // - // Check New Vale ... - has = - !NotEmptyZero(pVValue) - ? true - : iVValue != pVValue; - if (has) - { - // - // Calculate and Validate Type ... - // Vales Only Valid when Confirmed by Bar Low ... - iType = - iVValue == iBar.low - ? X_PIVOT_TYPE_VALE - : X_PIVOT_TYPE_NONE; - has = IsXValid(iType); - - // - // Calculate and Validate Dir ... - iDir = IsXVale(iType) - ? X_DIRECTION_BULLISH - : X_DIRECTION_NONE; - has = has && - HasDirection(iDir); - - // - // Check Validation Length ... - has = - has && - (validationLength <= 0 - ? true - : sameValesCount >= validationLength); - if (has) - { - // - // Initialize and Validate Pivot ... - has = iPivot.Init( - iVValue, - iBar.time, - symbol, - iDir, - period, - iType // - ); - if (has) - { - // - iPivot.prefix = ToXString(XFIMA_PIVOT_PV); - - // - // Add Pivot to Collection only if not Exists ... - AddIfNotExists( - iPivot, - pivots // - ); - } - } - - // - // Cleanup Resources ... - iPivot.Clean(); - sameValesCount = 0; - } - else if (iVValue == pVValue) - { - sameValesCount++; - } - } - } - - // - // Cleanup Resources ... - iBar.Clean(); - iPivot.Clean(); - SpecifiedClean(tmpPeaksBuffer); - SpecifiedClean(tmpValesBuffer); - - // - // Check Moving Forward Condition ... - has = - idx < maxAllowed && - ArraySize(pivots) < requiredNumberOFPivots; - if (!has) - { - break; - } - } - - // - result = ArraySize(pivots); - - // - // Cleanup Resources ... - iBar.Clean(); - iPivot.Clean(); - SpecifiedClean(tmpPeaksBuffer); - SpecifiedClean(tmpValesBuffer); - - // - return result; - } - - /** - * Extract Specified Kind of Pivots ... - * - * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... - * @param barIndex: int, Specified Bar Index ... - * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... - * @param validCrossDiffMultiplier: double, validate diff between MAs on Cross happens ... - * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... - * - * @return ( int ) - */ - int ExtractMAPivots( - XPivot &pivots[], - int barIndex = 0, - int requiredNumberOFPivots = 50, - double validCrossDiffMultiplier = 1, - int maxAllowedLoopbackLength = 1500 // - ) - { - // - int result = 0; - - // - // Prepare ... - SpecifiedClean(pivots); - - // - // Normalize ... - barIndex = NormalizeInt(barIndex, 0); - requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); - maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); - validCrossDiffMultiplier = NormalizeDouble(validCrossDiffMultiplier, 0); - - // - // Validate ... - if (mHandler == INVALID_HANDLE) - { - return result; - } - - // - double fast[]; - double slow[]; - XPivot iPivot; - int count = 0; - bool has = false; - int idx = barIndex - 1; - datetime iPivotTime = NULL; - string symbol = GetSymbol(); - double iFValue = EMPTY_VALUE; - double pFValue = EMPTY_VALUE; - double iSValue = EMPTY_VALUE; - double pSValue = EMPTY_VALUE; - bool isSwitchedToBullish = false; - bool isSwitchedToBearish = false; - double iSelectedValue = EMPTY_VALUE; - ENUM_TIMEFRAMES period = GetPeriod(); - ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; - ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; - int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; - while (idx < maxAllowed && - ArraySize(pivots) < requiredNumberOFPivots) - { - // - idx++; - - // - // Prepare ... - XClean(fast); - XClean(slow); - iPivot.Clean(); - - // - // Ignore First Item ... - if (idx == barIndex) - { - continue; - } - - // - // Reading Buffer ... - int fastCount = CopyMAFast(idx, 2, fast); - int slowCount = CopyMASlow(idx, 2, slow); - count = MathMin(fastCount, slowCount); - has = IsValidSize(count); - - // - // Reading Values ... - - // - iFValue = fast[0]; - pFValue = fast[1]; - - // - iSValue = slow[0]; - pSValue = slow[1]; - - // - // Validate Value ... - has = - HasMACross( - iDir, - idx, - validCrossDiffMultiplier // - ) && - NotEmptyZero(iFValue) && - NotEmptyZero(iSValue) && - NotEmptyZero(pFValue) && - NotEmptyZero(pSValue); - if (has) - { - // - // Check Direction Changed ... - isSwitchedToBullish = IsXBullish(iDir); - isSwitchedToBearish = IsXBearish(iDir); - has = - isSwitchedToBullish || - isSwitchedToBearish; - if (has) - { - // - // Calculate and Validate Type ... - // Peaks Only Valid when Confirmed by Bar High ... - iType = - isSwitchedToBearish - ? X_PIVOT_TYPE_PEAK - : isSwitchedToBullish - ? X_PIVOT_TYPE_VALE - : X_PIVOT_TYPE_NONE; - has = IsXValid(iType); - - // - // Calculate and Validate Dir ... - iDir = IsXPeak(iType) - ? X_DIRECTION_BEARISH - : IsXVale(iType) - ? X_DIRECTION_BULLISH - : X_DIRECTION_NONE; - has = has && - HasDirection(iDir); - - // - if (has) - { - // - iPivotTime = GetBarTime( - symbol, - period, - idx // - ); - - // - // Select Value based on Pivot Type ... - iSelectedValue = IsXPeak(iType) - ? MathMax(iFValue, iSValue) - : MathMin(iFValue, iSValue); - - // - // Initialize and Validate Pivot ... - has = iPivot.Init( - iSelectedValue, - iPivotTime, - symbol, - iDir, - period, - iType // - ); - if (has) - { - // - iPivot.prefix = ToXString(XFIMA_PIVOT_MA_CROSS); - - // - // Add Pivot to Collection only if not Exists ... - AddIfNotExists( - iPivot, - pivots // - ); - } - } - - // - // Cleanup Resources ... - iPivot.Clean(); - } - } - - // - // Cleanup Resources ... - XClean(fast); - XClean(slow); - iPivot.Clean(); - - // - // Check Moving Forward Condition ... - has = - idx < maxAllowed && - ArraySize(pivots) < requiredNumberOFPivots; - if (!has) - { - break; - } - } - - // - result = ArraySize(pivots); - - // - // Cleanup Resources ... - XClean(fast); - XClean(slow); - iPivot.Clean(); - - // - return result; - } - - /** - * Extract Specified Kind of Pivots ... - * - * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... - * @param barIndex: int, Specified Bar Index ... - * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... - * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... - * - * @return ( int ) - */ - int ExtractHKPivots( - XPivot &pivots[], - int barIndex = 0, - int requiredNumberOFPivots = 50, - int maxAllowedLoopbackLength = 1500 // - ) - { - // - int result = 0; - - // - // Prepare ... - SpecifiedClean(pivots); - - // - // Normalize ... - barIndex = NormalizeInt(barIndex, 0); - requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); - maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); - - // - // Validate ... - if (mHandler == INVALID_HANDLE) - { - return result; - } - - // - double open[]; - XPivot iPivot; - int count = 0; - double close[]; - bool has = false; - int idx = barIndex - 1; - datetime iPivotTime = NULL; - string symbol = GetSymbol(); - bool isSwitchedToBullish = false; - bool isSwitchedToBearish = false; - double iSelectedValue = EMPTY_VALUE; - ENUM_TIMEFRAMES period = GetPeriod(); - ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; - ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; - int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; - while (idx < maxAllowed && - ArraySize(pivots) < requiredNumberOFPivots) - { - // - idx++; - - // - // Prepare ... - XClean(open); - XClean(close); - iPivot.Clean(); - - // - // Ignore First Item ... - if (idx == barIndex) - { - continue; - } - - // - // Reading Buffer ... - int openCount = CopyHKOpen(idx, 2, open); - int closeCount = CopyHKClose(idx, 2, close); - count = MathMin(openCount, closeCount); - has = IsValidSize(count); - - // - // Validate Value ... - has = - HasHKSwitch( - iDir, - idx // - ) && - NotEmptyZero(open[0]) && - NotEmptyZero(open[1]) && - NotEmptyZero(close[0]) && - NotEmptyZero(close[1]); - if (has) - { - // - // Check Direction Changed ... - isSwitchedToBullish = IsXBullish(iDir); - isSwitchedToBearish = IsXBearish(iDir); - has = - isSwitchedToBullish || - isSwitchedToBearish; - if (has) - { - // - // Calculate and Validate Type ... - // Peaks Only Valid when Confirmed by Bar High ... - iType = - isSwitchedToBearish - ? X_PIVOT_TYPE_PEAK - : isSwitchedToBullish - ? X_PIVOT_TYPE_VALE - : X_PIVOT_TYPE_NONE; - has = IsXValid(iType); - - // - // Calculate and Validate Dir ... - iDir = IsXPeak(iType) - ? X_DIRECTION_BEARISH - : IsXVale(iType) - ? X_DIRECTION_BULLISH - : X_DIRECTION_NONE; - has = has && - HasDirection(iDir); - - // - if (has) - { - // - iPivot.prefix = ToXString(XFIMA_PIVOT_HK); - - // - iPivotTime = GetBarTime( - symbol, - period, - idx // - ); - - // - // Select Value based on Pivot Type ... - iSelectedValue = IsXPeak(iType) - ? MathMax(open[0], close[0]) - : MathMin(open[0], close[0]); - - // - // Initialize and Validate Pivot ... - has = iPivot.Init( - iSelectedValue, - iPivotTime, - symbol, - iDir, - period, - iType // - ); - if (has) - { - // - // Add Pivot to Collection only if not Exists ... - AddIfNotExists( - iPivot, - pivots // - ); - } - } - - // - // Cleanup Resources ... - iPivot.Clean(); - } - } - - // - // Cleanup Resources ... - XClean(open); - XClean(close); - iPivot.Clean(); - - // - // Check Moving Forward Condition ... - has = - idx < maxAllowed && - ArraySize(pivots) < requiredNumberOFPivots; - if (!has) - { - break; - } - } - - // - result = ArraySize(pivots); - - // - // Cleanup Resources ... - XClean(open); - XClean(close); - iPivot.Clean(); - - // - return result; - } - - /** - * Extract Specified Kind of Pivots ... - * - * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... - * @param barIndex: int, Specified Bar Index ... - * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... - * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... - * - * @return ( int ) - */ - int ExtractSARPivots( - XPivot &pivots[], - int barIndex = 0, - int requiredNumberOFPivots = 50, - int maxAllowedLoopbackLength = 1500 // - ) - { - // - int result = 0; - - // - // Prepare ... - SpecifiedClean(pivots); - - // - // Normalize ... - barIndex = NormalizeInt(barIndex, 0); - requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); - maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); - - // - // Validate ... - if (mHandler == INVALID_HANDLE) - { - return result; - } - - // - XOHCL iBar; - XOHCL pBar; - XPivot iPivot; - bool has = false; - double tmpSarBuffer[]; - int idx = barIndex - 1; - string symbol = GetSymbol(); - double iValue = EMPTY_VALUE; - double pValue = EMPTY_VALUE; - bool isSwitchedToBullish = false; - bool isSwitchedToBearish = false; - ENUM_TIMEFRAMES period = GetPeriod(); - ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; - ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; - int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; - while (idx < maxAllowed && - ArraySize(pivots) < requiredNumberOFPivots) - { - // - idx++; - - // - // Prepare ... - iBar.Clean(); - pBar.Clean(); - iPivot.Clean(); - SpecifiedClean(tmpSarBuffer); - - // - // Ignore First Item ... - if (idx == barIndex) - { - continue; - } - - // - // Initialize Bar ... - has = iBar.Init( - symbol, - period, - idx // - ); - has = - has && - iBar.GetPreviousBar(pBar); - if (!has) - { - continue; - } - - // - // Reading Buffer ... - CopyBuffer( - mHandler, // Handler ... - XFIMA_SAR_LINE, // Handler Buffer Number ... - idx, // Bar Index ... - 2, // Number of Requirements ... - tmpSarBuffer // Buffer ... - ); - ArraySetAsSeries(tmpSarBuffer, true); - - // - // Reading Values ... - iValue = tmpSarBuffer[0]; - pValue = tmpSarBuffer[1]; - - // - // Validate Value ... - if (NotEmptyZero(iValue)) - { - // - // Check Sar Direction Changed ... - isSwitchedToBullish = iValue < iBar.low && - pValue > pBar.high; - isSwitchedToBearish = iValue > iBar.high && - pValue < pBar.low; - has = - isSwitchedToBullish || - isSwitchedToBearish; - if (has) - { - // - // Calculate and Validate Type ... - // Peaks Only Valid when Confirmed by Bar High ... - iType = - isSwitchedToBearish - ? X_PIVOT_TYPE_PEAK - : isSwitchedToBullish - ? X_PIVOT_TYPE_VALE - : X_PIVOT_TYPE_NONE; - has = IsXValid(iType); - - // - // Calculate and Validate Dir ... - iDir = IsXPeak(iType) - ? X_DIRECTION_BEARISH - : IsXVale(iType) - ? X_DIRECTION_BULLISH - : X_DIRECTION_NONE; - has = has && - HasDirection(iDir); - - // - if (has) - { - // - // Initialize and Validate Pivot ... - has = iPivot.Init( - iValue, - iBar.time, - symbol, - iDir, - period, - iType // - ); - if (has) - { - // - iPivot.prefix = ToXString(XFIMA_PIVOT_SAR_SWITCH); - - // - // Add Pivot to Collection only if not Exists ... - AddIfNotExists( - iPivot, - pivots // - ); - } - } - - // - // Cleanup Resources ... - iPivot.Clean(); - } - } - - // - // Cleanup Resources ... - iBar.Clean(); - pBar.Clean(); - iPivot.Clean(); - SpecifiedClean(tmpSarBuffer); - - // - // Check Moving Forward Condition ... - has = - idx < maxAllowed && - ArraySize(pivots) < requiredNumberOFPivots; - if (!has) - { - break; - } - } - - // - result = ArraySize(pivots); - - // - // Cleanup Resources ... - iBar.Clean(); - pBar.Clean(); - iPivot.Clean(); - SpecifiedClean(tmpSarBuffer); - - // - return result; - } - - /** - * Extract Specified Kind of Pivots ... - * - * @param pivots: XPivot, refrence Collection to hold Extracted pivots ... - * @param barIndex: int, Specified Bar Index ... - * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... - * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... - * - * @return ( int ) - */ - int ExtractZigZagPivots( - XPivot &pivots[], - int barIndex = 0, - int requiredNumberOFPivots = 50, - int maxAllowedLoopbackLength = 1500 // - ) - { - // - int result = 0; - - // - // Prepare ... - SpecifiedClean(pivots); - - // - // Normalize ... - barIndex = NormalizeInt(barIndex, 0); - requiredNumberOFPivots = NormalizeInt(requiredNumberOFPivots, 2); - maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); - - // - // Validate ... - if (mHandler == INVALID_HANDLE) - { - return result; - } - - // - XOHCL iBar; - XPivot iPivot; - bool has = false; - int idx = barIndex - 1; - double tmpZigZagBuffer[]; - double iValue = EMPTY_VALUE; - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); - ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; - ENUM_X_PIVOT_TYPE iType = X_PIVOT_TYPE_NONE; - int maxAllowed = barIndex + maxAllowedLoopbackLength - 1; - while (idx < maxAllowed && - ArraySize(pivots) < requiredNumberOFPivots) - { - // - idx++; - - // - // Prepare ... - iBar.Clean(); - iPivot.Clean(); - SpecifiedClean(tmpZigZagBuffer); - - // - // Ignore First Item ... - if (idx == barIndex) - { - continue; - } - - // - // Initialize Bar ... - has = iBar.Init( - symbol, - period, - idx // - ); - if (!has) - { - continue; - } - - // - // Reading Buffer ... - CopyBuffer( - mHandler, // Handler ... - XFIMA_ZIGZAG_LINE, // Handler Buffer Number ... - idx, // Bar Index ... - 1, // Number of Requirements ... - tmpZigZagBuffer // Buffer ... - ); - ArraySetAsSeries(tmpZigZagBuffer, true); - - // - // Read and Validate Value ... - iValue = tmpZigZagBuffer[0]; - has = NotEmptyZero(iValue); - if (!has) - { - // - iBar.Clean(); - SpecifiedClean(tmpZigZagBuffer); - continue; - } - - // - // Calculate and Validate Type ... - iType = - iValue == iBar.high - ? X_PIVOT_TYPE_PEAK - : iValue == iBar.low - ? X_PIVOT_TYPE_VALE - : X_PIVOT_TYPE_NONE; - has = IsXValid(iType); - if (!has) - { - // - iBar.Clean(); - SpecifiedClean(tmpZigZagBuffer); - continue; - } - - // - // Calculate and Validate Dir ... - iDir = - IsXVale(iType) - ? X_DIRECTION_BULLISH - : IsXPeak(iType) - ? X_DIRECTION_BEARISH - : X_DIRECTION_NONE; - has = HasDirection(iDir); - if (!has) - { - // - iBar.Clean(); - SpecifiedClean(tmpZigZagBuffer); - continue; - } - - // - // Initialize and Validate Pivot ... - has = iPivot.Init( - iValue, - iBar.time, - symbol, - iDir, - period, - iType // - ); - if (has) - { - // - iPivot.prefix = ToXString(XFIMA_PIVOT_ZIGZAG); - - // - // Add Pivot to Collection only if not Exists ... - AddIfNotExists( - iPivot, - pivots // - ); - } - - // - // Cleanup Resources ... - iBar.Clean(); - iPivot.Clean(); - SpecifiedClean(tmpZigZagBuffer); - - // - // Check Moving Forward Condition ... - has = - idx < maxAllowed && - ArraySize(pivots) < requiredNumberOFPivots; - if (!has) - { - break; - } - } - - // - result = ArraySize(pivots); - - // - // Cleanup Resources ... - iBar.Clean(); - iPivot.Clean(); - SpecifiedClean(tmpZigZagBuffer); - - // - return result; - } - - /** - * Extract Validated Zones ... - * - * @param zones: XBoxZone, collection reference to holds results ... - * @param barIndex: int, Specified Bar Index ... - * @param requiredNumberOFZones: int, required Number of Zones ... - * @param breakValidLength: int, Breake Validation Length of Zones ... - * @param validateFakeBreakes: bool, Validation Fake Breaked Zones ... - * @param shadowMultiplier: double a Shadow Multiplier for Validation ... - * @param validationStrength: double, Minimum Strngth Multiplier in Point to Validate ... - * @param validationLength: int, Validation Length of Zones ... - * @param maxAllowedLoopbackLength: int, max Allowed Loopback Length ... - * - * @return ( int ) - */ - int ExtractHKZones( - XBoxZone &zones[], - int barIndex = 0, - int requiredNumberOFZones = 50, - int breakValidLength = 3, - bool validateFakeBreakes = true, - double shadowMultiplier = 3, - double validationStrength = 1, - int validationLength = 21, - int maxAllowedLoopbackLength = 1500 // - ) - { - // - int result = 0; - - // - // Prepare ... - SpecifiedClean(zones); - - // - // Normalize ... - barIndex = NormalizeInt(barIndex, 0); - validationLength = NormalizeInt(validationLength, 7); - shadowMultiplier = NormalizeDouble(shadowMultiplier, 1); - validationStrength = NormalizeDouble(validationStrength, 1); - requiredNumberOFZones = NormalizeInt(requiredNumberOFZones, 5); - maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 100); - - // - // Reading Values ... - - // - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); - double minAllowedStrength = (validationStrength * GetPoints(symbol)); - - // - int count = 0; - XBoxZone zone; - bool has = false; - int start = barIndex; - bool isBullish = false; - bool isBearish = false; - double up = EMPTY_VALUE; - double low = EMPTY_VALUE; - double open = EMPTY_VALUE; - double high = EMPTY_VALUE; - double down = EMPTY_VALUE; - double body = EMPTY_VALUE; - double close = EMPTY_VALUE; - double range = EMPTY_VALUE; - bool lowShadowPassed = false; - bool highShadowPassed = false; - double lowShadow = EMPTY_VALUE; - double highShadow = EMPTY_VALUE; - double startHKLow = EMPTY_VALUE; - double startHKOpen = EMPTY_VALUE; - double startHKHigh = EMPTY_VALUE; - double startHKClose = EMPTY_VALUE; - ENUM_X_DIRECTION dir = X_DIRECTION_NONE; - int end = start + maxAllowedLoopbackLength; - for (int i = start; i < end; i++) - { - // - // Cleanup ... - zone.Clean(); - dir = X_DIRECTION_NONE; - - // - // Reading HK Buffesr ... - low = GetHKLow(i); - open = GetHKOpen(i); - high = GetHKHigh(i); - close = GetHKClose(i); - - // - // Initialized Start Bar ... - if (i == start) - { - // - startHKLow = low; - startHKOpen = open; - startHKHigh = high; - startHKClose = close; - } - - // - // Check Direction ... - isBullish = open < close; - isBearish = open > close; - dir = - (isBullish && !isBearish) - ? X_DIRECTION_BULLISH - : (isBearish && !isBullish) - ? X_DIRECTION_BEARISH - : X_DIRECTION_NONE; - has = HasDirection(dir); - if (!has) - { - continue; - } - - // - // Calculate Requirements for Processing ... - up = isBullish - ? close - : open; - down = isBullish - ? open - : close; - body = MathAbs(up - down); - range = high - low; - highShadow = high - up; - lowShadow = down - low; - - // - // Detecting Shadows ... - - // - // Low Shadow ... - lowShadowPassed = lowShadow >= (shadowMultiplier * highShadow); - - // - // High Shadow ... - highShadowPassed = highShadow >= (shadowMultiplier * lowShadow); - - // - has = (lowShadowPassed && !highShadowPassed) || - (highShadowPassed && !lowShadowPassed); - if (!has) - { - continue; - } - - // - // Filling Zone ... - - // - zone.symbol = symbol; - zone.period = period; - zone.from = GetBarTime( - zone.symbol, - zone.period, - i // - ); - zone.dir = lowShadowPassed - ? X_DIRECTION_BULLISH - : highShadowPassed - ? X_DIRECTION_BEARISH - : X_DIRECTION_NONE; - - // - zone.upper = - IsXBullish(zone.dir) - ? down - : IsXBearish(zone.dir) - ? high - : EMPTY_VALUE; - - // - zone.lower = - IsXBullish(zone.dir) - ? low - : IsXBearish(zone.dir) - ? up - : EMPTY_VALUE; - - // - zone.to = TimeCurrent(); - zone.type = ToXString(XFIMA_PIVOT_HK) + "_" + (IsXBullish(zone.dir) ? "Support" : IsXBearish(zone.dir) ? "Resistance" - : ""); - - // - // Validate ... - has = - zone.IsValid() && - HasDirection(zone.dir) && - NotEmptyZero(zone.upper) && - NotEmptyZero(zone.lower) && - (zone.IsBullish() - ? startHKLow > zone.upper - : startHKHigh < zone.lower) && - (zone.upper - zone.lower) >= minAllowedStrength && - ValidateHKZone(zone, validationLength, breakValidLength, validateFakeBreakes); - if (has) - { - // - AddIfNotExists( - zone, - zones // - ); - } - - // - // Cleanup Resources ... - zone.Clean(); - - // - // Validating ... - result = ArraySize(zones); - has = IsValidSize(result) && - result >= requiredNumberOFZones; - if (has) - { - break; - } - } - - // - // Cleanup Resources ... - zone.Clean(); - - // - return result; - } - - // - // Values Retrievers ... - - /** - * Filling Specified Bar index Boundary Values ... - * - * @param dest: double, reference collection to hold boundary Values ... - * @param barIndex: int, Specified Bar's Index ... - * @param containsFastSlow: bool, Contains XMA Fast / Slow ... - * @param containsMABond: bool, Contains XMA Boundary Upper / Lower ... - * @param containsHKBound: bool, Contains XHK Boundary Upper / Lower ... - * @param containsPBBond: bool, Contains XPB Boundary Upper / Lower ... - * @param containsFiboLevels: nool, Contains XFIBO Levels ... - * - * @return ( int ) - */ - int FillBoundaryValues( - double &dest[], - int barIndex = 0, - bool containsFastSlow = true, - bool containsMABond = true, - bool containsHKBound = true, - bool containsPBBond = true, - bool containsFiboLevels = false // - ) - { - // - int result = 0; - - // - // Prepare ... - XClean(dest); - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - bool has = IsValid(); - if (!has) - { - return result; - } - - // - // Read and Validate Values ... - - // - double fast = GetMAFast(barIndex); - double slow = GetMASlow(barIndex); - - // - double maBondUpper = GetMABondUpper(barIndex); - double maBondLower = GetMABondLower(barIndex); - - // - double pbBondUpper = GetPBBondUpper(barIndex); - double pbBondLower = GetPBBondLower(barIndex); - - // - double hkBondUpper = GetHKBondUpper(barIndex); - double hkBondLower = GetHKBondLower(barIndex); - - // - double fiboUpper = GetFiboUpper(barIndex); - double fiboLower = GetFiboLower(barIndex); - double fiboMiddle = GetFiboMiddle(barIndex); - - // - has = - NotEmptyZero(fast) && - NotEmptyZero(slow) && - NotEmptyZero(fiboLower) && - NotEmptyZero(fiboUpper) && - NotEmptyZero(fiboMiddle) && - NotEmptyZero(maBondUpper) && - NotEmptyZero(maBondLower) && - NotEmptyZero(pbBondUpper) && - NotEmptyZero(pbBondLower) && - NotEmptyZero(hkBondUpper) && - NotEmptyZero(hkBondLower); - if (!has) - { - return result; - } - - // - // Fill Dest ... - - // - // XMA Fast / Slow ... - if (containsFastSlow) - { - // - Add(fast, dest); - Add(slow, dest); - } - - // - // XMA Bound ... - if (containsMABond) - { - // - Add(maBondUpper, dest); - Add(maBondLower, dest); - } - - // - // XHK Bond ... - if (containsHKBound) - { - // - Add(hkBondUpper, dest); - Add(hkBondLower, dest); - } - - // - // XPB Bond ... - if (containsPBBond) - { - // - Add(pbBondUpper, dest); - Add(pbBondLower, dest); - } - - // - // XFIBO Zones ... - if (containsFiboLevels) - { - // - Add(fiboLower, dest); - Add(fiboUpper, dest); - Add(fiboMiddle, dest); - } - - // - result = ArraySize(dest); - - // - return result; - } - - /** - * Retrieve Fast, Slow, MA Bond Upper/Lower, HK Bond Upper/Lower and PB Bond Upper/Lower Min/Max ... - * - * @param min: double, minimum value ... - * @param max: double, maximum value ... - * @param barIndex: int, Specified Bar Index ... - * - * @return ( bool ) - */ - bool GetBoundaryValues( - double &min, - double &max, - int barIndex = 0, - bool containsFastSlow = true, - bool containsMABond = true, - bool containsHKBound = true, - bool containsPBBond = true, - bool containsFiboLevels = false // - ) - { - // - bool result = false; - - // - // Prepare ... - min = EMPTY_VALUE; - max = EMPTY_VALUE; - - // - // Normalize ... - barIndex = NormalizeBarIndex(barIndex); - - // - // Validate ... - result = IsValid(); - if (!result) - { - return result; - } - - // - double fast = GetMAFast(barIndex); - double slow = GetMASlow(barIndex); - - // - double maBondUpper = GetMABondUpper(barIndex); - double maBondLower = GetMABondLower(barIndex); - - // - double pbBondUpper = GetPBBondUpper(barIndex); - double pbBondLower = GetPBBondLower(barIndex); - - // - double hkBondUpper = GetHKBondUpper(barIndex); - double hkBondLower = GetHKBondLower(barIndex); - - // - double fiboUpper = GetFiboUpper(barIndex); - double fiboLower = GetFiboLower(barIndex); - double fiboMiddle = GetFiboMiddle(barIndex); - - // - result = - NotEmptyZero(fast) && - NotEmptyZero(slow) && - NotEmptyZero(fiboLower) && - NotEmptyZero(fiboUpper) && - NotEmptyZero(fiboMiddle) && - NotEmptyZero(maBondUpper) && - NotEmptyZero(maBondLower) && - NotEmptyZero(pbBondUpper) && - NotEmptyZero(pbBondLower) && - NotEmptyZero(hkBondUpper) && - NotEmptyZero(hkBondLower); - if (!result) - { - return result; - } - - // - double values[]; - - // - if (containsFastSlow) - { - // - Add(fast, values); - Add(slow, values); - } - - // - if (containsMABond) - { - // - Add(maBondUpper, values); - Add(maBondLower, values); - } - - // - if (containsHKBound) - { - // - Add(hkBondUpper, values); - Add(hkBondLower, values); - } - - // - if (containsPBBond) - { - // - Add(pbBondUpper, values); - Add(pbBondLower, values); - } - - // - if (containsFiboLevels) - { - // - Add(fiboLower, values); - Add(fiboUpper, values); - Add(fiboMiddle, values); - } - - // - result = HasChild(values); - if (!result) - { - return result; - } - - // - min = GetMin(values); - max = GetMax(values); - - // - result = - NotEmptyZero(min) && - NotEmptyZero(max) && - min < max; - - // - return result; - } - // // Fast MA ... @@ -7058,19 +1047,19 @@ class XCXFIMAHelper : public XCBaseHelper // Upper MA ... // - double GetMABondUpper( + double GetMABandUpper( int barIndex // Bar Index ) { // return ReadValue( - (int)XFIMA_MA_BOND_UPPER_LINE, + (int)XFIMA_MA_BAND_UPPER_LINE, barIndex // ); } // - int CopyMABondUpper( + int CopyMABandUpper( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -7080,7 +1069,7 @@ class XCXFIMAHelper : public XCBaseHelper // return ReadValues( buffer, - (int)XFIMA_MA_BOND_UPPER_LINE, + (int)XFIMA_MA_BAND_UPPER_LINE, start, count, asSeries // @@ -7091,19 +1080,19 @@ class XCXFIMAHelper : public XCBaseHelper // Lower MA ... // - double GetMABondLower( + double GetMABandLower( int barIndex // Bar Index ) { // return ReadValue( - (int)XFIMA_MA_BOND_LOWER_LINE, + (int)XFIMA_MA_BAND_LOWER_LINE, barIndex // ); } // - int CopyMABondLower( + int CopyMABandLower( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -7113,7 +1102,7 @@ class XCXFIMAHelper : public XCBaseHelper // return ReadValues( buffer, - (int)XFIMA_MA_BOND_LOWER_LINE, + (int)XFIMA_MA_BAND_LOWER_LINE, start, count, asSeries // @@ -7127,19 +1116,19 @@ class XCXFIMAHelper : public XCBaseHelper // Upper PB ... // - double GetPBBondUpper( + double GetPBBandUpper( int barIndex // Bar Index ) { // return ReadValue( - (int)XFIMA_PB_BOND_UPPER_LINE, + (int)XFIMA_PB_BAND_UPPER_LINE, barIndex // ); } // - int CopyPBBondUpper( + int CopyPBBandUpper( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -7149,7 +1138,7 @@ class XCXFIMAHelper : public XCBaseHelper // return ReadValues( buffer, - (int)XFIMA_PB_BOND_UPPER_LINE, + (int)XFIMA_PB_BAND_UPPER_LINE, start, count, asSeries // @@ -7160,19 +1149,19 @@ class XCXFIMAHelper : public XCBaseHelper // Lower PB ... // - double GetPBBondLower( + double GetPBBandLower( int barIndex // Bar Index ) { // return ReadValue( - (int)XFIMA_PB_BOND_LOWER_LINE, + (int)XFIMA_PB_BAND_LOWER_LINE, barIndex // ); } // - int CopyPBBondLower( + int CopyPBBandLower( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -7182,7 +1171,7 @@ class XCXFIMAHelper : public XCBaseHelper // return ReadValues( buffer, - (int)XFIMA_PB_BOND_LOWER_LINE, + (int)XFIMA_PB_BAND_LOWER_LINE, start, count, asSeries // @@ -7193,19 +1182,19 @@ class XCXFIMAHelper : public XCBaseHelper // Upper PB ... // - double GetPBRawBondUpper( + double GetPBRawBandUpper( int barIndex // Bar Index ) { // return ReadValue( - (int)XFIMA_PB_BOND_RAW_UPPER_LINE, + (int)XFIMA_PB_BAND_RAW_UPPER_LINE, barIndex // ); } // - int CopyPBRawBondUpper( + int CopyPBRawBandUpper( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -7215,7 +1204,7 @@ class XCXFIMAHelper : public XCBaseHelper // return ReadValues( buffer, - (int)XFIMA_PB_BOND_RAW_UPPER_LINE, + (int)XFIMA_PB_BAND_RAW_UPPER_LINE, start, count, asSeries // @@ -7226,19 +1215,19 @@ class XCXFIMAHelper : public XCBaseHelper // Lower PB ... // - double GetPBRawBondLower( + double GetPBRawBandLower( int barIndex // Bar Index ) { // return ReadValue( - (int)XFIMA_PB_BOND_RAW_LOWER_LINE, + (int)XFIMA_PB_BAND_RAW_LOWER_LINE, barIndex // ); } // - int CopyPBRawBondLower( + int CopyPBRawBandLower( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -7248,7 +1237,175 @@ class XCXFIMAHelper : public XCBaseHelper // return ReadValues( buffer, - (int)XFIMA_PB_BOND_RAW_LOWER_LINE, + (int)XFIMA_PB_BAND_RAW_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // XATR ... + + // + // Upper ATR ... + + // + double GetATRBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_UPPER_LINE, + barIndex // + ); + } + + // + int CopyATRBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower ATR ... + + // + double GetATRBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_LOWER_LINE, + barIndex // + ); + } + + // + int CopyATRBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_LOWER_LINE, + start, + count, + asSeries // + ); + } + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_LINE, + barIndex // + ); + } + + // + int CopyATR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_LINE, + start, + count, + asSeries // + ); + } + + // + // Upper ATR ... + + // + double GetATRRawBandUpper( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_RAW_UPPER_LINE, + barIndex // + ); + } + + // + int CopyATRRawBandUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_RAW_UPPER_LINE, + start, + count, + asSeries // + ); + } + + // + // Lower ATR ... + + // + double GetATRRawBandLower( + int barIndex // Bar Index + ) + { + // + return ReadValue( + (int)XFIMA_ATR_BAND_RAW_LOWER_LINE, + barIndex // + ); + } + + // + int CopyATRRawBandLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool asSeries = true // As Series Flag + ) + { + // + return ReadValues( + buffer, + (int)XFIMA_ATR_BAND_RAW_LOWER_LINE, start, count, asSeries // @@ -7259,7 +1416,7 @@ class XCXFIMAHelper : public XCBaseHelper // SAR ... // - double GetSar( + double GetSAR( int barIndex // Bar Index ) { @@ -7271,7 +1428,7 @@ class XCXFIMAHelper : public XCBaseHelper } // - int CopySar( + int CopySAR( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -7292,7 +1449,7 @@ class XCXFIMAHelper : public XCBaseHelper // SAR State ... // - double GetSarState( + double GetSARState( int barIndex // Bar Index ) { @@ -7304,7 +1461,7 @@ class XCXFIMAHelper : public XCBaseHelper } // - int CopySarState( + int CopySARState( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -8105,25 +2262,25 @@ class XCXFIMAHelper : public XCBaseHelper } // - // XHK Bond ... + // XHK Band ... // - // XHK Bond Upper ... + // XHK Band Upper ... // - double GetHKBondUpper( + double GetHKBandUpper( int barIndex // Bar Index ) { // return ReadValue( - (int)XFIMA_HK_BOND_UPPER_LINE, + (int)XFIMA_HK_BAND_UPPER_LINE, barIndex // ); } // - int CopyHKBondUpper( + int CopyHKBandUpper( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -8133,7 +2290,7 @@ class XCXFIMAHelper : public XCBaseHelper // return ReadValues( buffer, - (int)XFIMA_HK_BOND_UPPER_LINE, + (int)XFIMA_HK_BAND_UPPER_LINE, start, count, asSeries // @@ -8141,22 +2298,22 @@ class XCXFIMAHelper : public XCBaseHelper } // - // XHK Bond Lower ... + // XHK Band Lower ... // - double GetHKBondLower( + double GetHKBandLower( int barIndex // Bar Index ) { // return ReadValue( - (int)XFIMA_HK_BOND_LOWER_LINE, + (int)XFIMA_HK_BAND_LOWER_LINE, barIndex // ); } // - int CopyHKBondLower( + int CopyHKBandLower( int start, // Start int count, // Number of Items for read double &buffer[], // Dest Buffer @@ -8166,7 +2323,7 @@ class XCXFIMAHelper : public XCBaseHelper // return ReadValues( buffer, - (int)XFIMA_HK_BOND_LOWER_LINE, + (int)XFIMA_HK_BAND_LOWER_LINE, start, count, asSeries // diff --git a/Indicators/x-saherelm.xfima.mq5 b/Indicators/x-saherelm.xfima.mq5 index e085725c..4ecda4ca 100644 --- a/Indicators/x-saherelm.xfima.mq5 +++ b/Indicators/x-saherelm.xfima.mq5 @@ -83,7 +83,7 @@ input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To input int maFastLength = 7; // Fast MA Length input int maSlowLength = 21; // Slow MA Length -input int maBondLength = 21; // MA Bond Length +input int maBandLength = 21; // MA Band Length input int zigzagDepth = 12; // ZigZag Depth input int zigzagDeviation = 5; // ZigZag Deviation input int zigzagBackStep = 3; // ZigZag Back Step @@ -92,6 +92,12 @@ input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // ZigZag Low D input bool hkIgnoreShadows = true; // HK Remove noises input int hkSmoothingLength = 21; // HK Smoothing Length input ENUM_X_MA_METHOD hkSmoothingMode = X_MA_MODE_EMA; // HK Smoothing Method +input int atrLength = 14; // ATR Length +input double atrMultiplier = 1.5; // ATR Band Multiplier +input int atrSmoothingLength = 21; // ATR Smoothing Length +input ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Zone Applied To +input ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // ATR Lower Zone Applied To +input ENUM_X_MA_METHOD atrSmoothingMode = X_MA_MODE_EMA; // ATR Smoothing Method // // Presentation ... @@ -101,8 +107,9 @@ input bool showHK = true; // Show HK input bool showSAR = true; // Show Sar input bool showMAFast = true; // Show MA Fast input bool showMASlow = true; // Show MA Slow -input bool showMABond = true; // Show MA Bond -input bool showHKBond = true; // Show HK Bond +input bool showMABand = true; // Show MA Band +input bool showHKBand = true; // Show HK Band +input bool showATRBand = true; // Show ATR Band input bool showZigZag = true; // Show ZigZag input bool showFiboZone = true; // Show Fibo Zone @@ -138,8 +145,8 @@ input int valeArrowCode = 159; // Vales Arrow Code #property indicator_chart_window // -#property indicator_buffers 44 -#property indicator_plots 16 +#property indicator_buffers 49 +#property indicator_plots 18 // // Plot Buffers ... @@ -160,7 +167,7 @@ double maFastColorBuffer[]; #property indicator_label1 "FastMA" #property indicator_type1 DRAW_COLOR_LINE #property indicator_color1 CLR_NONE, clrLime, clrLime, clrLime // clrYellow, clrOrangeRed, clrGray -#property indicator_width1 3 +#property indicator_width1 2 // // Slow MA ... @@ -178,7 +185,7 @@ double maSlowColorBuffer[]; #property indicator_label2 "SlowMA" #property indicator_type2 DRAW_COLOR_LINE #property indicator_color2 CLR_NONE, clrRed, clrRed, clrRed // clrLime, clrRed, clrGray -#property indicator_width2 3 +#property indicator_width2 2 // // SAR ... @@ -286,29 +293,29 @@ double zigzagBuffer[]; // MA Upper ... // -#define maBondUpperBufferIndex 12 -double maBondUpperBuffer[]; +#define maBandUpperBufferIndex 12 +double maBandUpperBuffer[]; // -#define maBondUpperBufferPlotIndex 9 +#define maBandUpperBufferPlotIndex 9 #property indicator_label10 "UpperMA" #property indicator_type10 DRAW_LINE #property indicator_color10 clrLime -#property indicator_width10 3 +#property indicator_width10 2 // // MA Lower ... // -#define maBondLowerBufferIndex 13 -double maBondLowerBuffer[]; +#define maBandLowerBufferIndex 13 +double maBandLowerBuffer[]; // -#define maBondLowerBufferPlotIndex 10 +#define maBandLowerBufferPlotIndex 10 #property indicator_label11 "LowerMA" #property indicator_type11 DRAW_LINE #property indicator_color11 clrRed -#property indicator_width11 3 +#property indicator_width11 2 // // XHK ... @@ -340,60 +347,88 @@ double hkColorBuffer[]; #property indicator_color12 CLR_NONE, clrAqua, clrMagenta, clrGray // -#define hkBondUpperBufferIndex 19 -double hkBondUpperBuffer[]; +#define hkBandUpperBufferIndex 19 +double hkBandUpperBuffer[]; // -#define hkBondUpperBufferPlotIndex 12 +#define hkBandUpperBufferPlotIndex 12 #property indicator_label13 "UpperHK" #property indicator_type13 DRAW_LINE #property indicator_color13 clrAqua -#property indicator_width13 3 +#property indicator_width13 2 // -#define hkBondLowerBufferIndex 20 -double hkBondLowerBuffer[]; +#define hkBandLowerBufferIndex 20 +double hkBandLowerBuffer[]; // -#define hkBondLowerBufferPlotIndex 13 +#define hkBandLowerBufferPlotIndex 13 #property indicator_label14 "LowerHK" #property indicator_type14 DRAW_LINE #property indicator_color14 clrMagenta -#property indicator_width14 3 +#property indicator_width14 2 // // PB Upper ... // -#define pbBondUpperBufferIndex 21 -double pbBondUpperBuffer[]; +#define pbBandUpperBufferIndex 21 +double pbBandUpperBuffer[]; // -#define pbBondUpperBufferPlotIndex 14 +#define pbBandUpperBufferPlotIndex 14 #property indicator_label15 "UpperPB" #property indicator_type15 DRAW_LINE #property indicator_color15 clrRoyalBlue -#property indicator_width15 3 +#property indicator_width15 2 // // PB Lower ... // -#define pbBondLowerBufferIndex 22 -double pbBondLowerBuffer[]; +#define pbBandLowerBufferIndex 22 +double pbBandLowerBuffer[]; // -#define pbBondLowerBufferPlotIndex 15 +#define pbBandLowerBufferPlotIndex 15 #property indicator_label16 "LowerPB" #property indicator_type16 DRAW_LINE -#property indicator_color16 clrOrangeRed -#property indicator_width16 3 +#property indicator_color16 clrRoyalBlue +#property indicator_width16 2 + +// +// ATR Upper ... + +// +#define atrBandUpperBufferIndex 23 +double atrBandUpperBuffer[]; + +// +#define atrBandUpperBufferPlotIndex 16 +#property indicator_label17 "UpperATR" +#property indicator_type17 DRAW_LINE +#property indicator_color17 clrOrange +#property indicator_width17 2 + +// +// ATR Lower ... + +// +#define atrBandLowerBufferIndex 24 +double atrBandLowerBuffer[]; + +// +#define atrBandLowerBufferPlotIndex 17 +#property indicator_label18 "LowerATR" +#property indicator_type18 DRAW_LINE +#property indicator_color18 clrOrange +#property indicator_width18 2 // // Data Buffers ... // -#define mLastBufferIndex 22 +#define mLastBufferIndex 24 // // MA ... @@ -502,12 +537,27 @@ double hkRawCloseBuffer[]; // XPB Data ... // -#define pbBondRawUpperBufferIndex mLastBufferIndex + 20 -double pbBondRawUpperBuffer[]; +#define pbBandRawUpperBufferIndex mLastBufferIndex + 20 +double pbBandRawUpperBuffer[]; // -#define pbBondRawLowerBufferIndex mLastBufferIndex + 21 -double pbBondRawLowerBuffer[]; +#define pbBandRawLowerBufferIndex mLastBufferIndex + 21 +double pbBandRawLowerBuffer[]; + +// +// XATR Data ... + +// +#define atrBufferIndex mLastBufferIndex + 22 +double atrBuffer[]; + +// +#define atrBandRawUpperBufferIndex mLastBufferIndex + 23 +double atrBandRawUpperBuffer[]; + +// +#define atrBandRawLowerBufferIndex mLastBufferIndex + 24 +double atrBandRawLowerBuffer[]; // // Variables, Properties and etc ... @@ -534,6 +584,7 @@ ENUM_TIMEFRAMES mHCPeriod = NULL; // int sarHandler = INVALID_HANDLE; +int atrHandler = INVALID_HANDLE; int maFastHandler = INVALID_HANDLE; int maSlowHandler = INVALID_HANDLE; int maUpperHandler = INVALID_HANDLE; @@ -662,6 +713,7 @@ void OnDeinit(const int reason) // // De Initialize all Handlers and etc ... IndicatorRelease(sarHandler); + IndicatorRelease(atrHandler); IndicatorRelease(maFastHandler); IndicatorRelease(maSlowHandler); IndicatorRelease(maUpperHandler); @@ -739,6 +791,10 @@ int OnCalculate( // SAR ... int sarCalculatedBars = BarsCalculated(sarHandler); + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + // bool isPassedRequiredCalculatedBars = // @@ -749,7 +805,10 @@ int OnCalculate( maLowerCalculatedBars >= maxLength && // // SAR ... - sarCalculatedBars >= maxLength + sarCalculatedBars >= maxLength && + // + // ATR ... + atrCalculatedBars >= maxLength // ; if (!isPassedRequiredCalculatedBars) @@ -769,13 +828,17 @@ int OnCalculate( // MA ... int copiedMAFasts = CopyBuffer(maFastHandler, MAIN_LINE, 0, limit, maFastBuffer); int copiedMASlows = CopyBuffer(maSlowHandler, MAIN_LINE, 0, limit, maSlowBuffer); - int copiedMAUppers = CopyBuffer(maUpperHandler, MAIN_LINE, 0, limit, maBondUpperBuffer); - int copiedMALowers = CopyBuffer(maLowerHandler, MAIN_LINE, 0, limit, maBondLowerBuffer); + int copiedMAUppers = CopyBuffer(maUpperHandler, MAIN_LINE, 0, limit, maBandUpperBuffer); + int copiedMALowers = CopyBuffer(maLowerHandler, MAIN_LINE, 0, limit, maBandLowerBuffer); // // SAR ... int copiedSARs = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + // + // ATR ... + int copiedATRs = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + // // Validate Copied Items ... bool isPassedRequiredCopiedItems = @@ -787,7 +850,10 @@ int OnCalculate( copiedMALowers >= limit && // // SAR ... - copiedSARs >= limit + copiedSARs >= limit && + // + // ATR ... + copiedATRs >= limit // ; if (!isPassedRequiredCopiedItems) @@ -846,7 +912,7 @@ bool ValidateInputs() // MA ... maFastLength >= 2 && maSlowLength >= 2 && - maBondLength >= 2 && + maBandLength >= 2 && maSlowLength > maFastLength && // // SAR ... @@ -854,6 +920,12 @@ bool ValidateInputs() sarStep > 0 && sarMax > sarStep && // + // ATR ... + atrLength > 0 && + atrMultiplier >= 1 && + IsXValid(atrUpperPriceType) && + IsXValid(atrLowerPriceType) && + // // CYCLES ... (IsValid(scMethod, scPeriod) && IsValid(mcMethod, mcPeriod) && @@ -893,7 +965,8 @@ int ExtractMaxLengthOfInputs() result = MathMax(result, mHCLength); result = MathMax(result, maFastLength); result = MathMax(result, maSlowLength); - result = MathMax(result, maBondLength); + result = MathMax(result, maBandLength); + result = MathMax(result, atrLength); // return result; @@ -1039,63 +1112,63 @@ void DefineBuffers() PlotIndexSetDouble(zigzagBufferPlotIndex, PLOT_EMPTY_VALUE, 0); // - // MA Bond ... + // MA Band ... // - ENUM_DRAW_TYPE maBondDrawType = showMABond ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE maBandDrawType = showMABand ? DRAW_LINE : DRAW_NONE; // - // Upper Bond ... + // Upper Band ... // - ArraySetAsSeries(maBondUpperBuffer, true); - SetIndexBuffer(maBondUpperBufferIndex, maBondUpperBuffer, INDICATOR_DATA); + ArraySetAsSeries(maBandUpperBuffer, true); + SetIndexBuffer(maBandUpperBufferIndex, maBandUpperBuffer, INDICATOR_DATA); // - PlotIndexSetInteger(maBondUpperBufferPlotIndex, PLOT_SHOW_DATA, showMABond); - PlotIndexSetInteger(maBondUpperBufferPlotIndex, PLOT_DRAW_TYPE, maBondDrawType); - PlotIndexSetInteger(maBondUpperBufferPlotIndex, PLOT_DRAW_BEGIN, 0); - PlotIndexSetDouble(maBondUpperBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(maBandUpperBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(maBandUpperBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + PlotIndexSetInteger(maBandUpperBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(maBandUpperBufferPlotIndex, PLOT_EMPTY_VALUE, 0); // - // Lower Bond ... + // Lower Band ... // - ArraySetAsSeries(maBondLowerBuffer, true); - SetIndexBuffer(maBondLowerBufferIndex, maBondLowerBuffer, INDICATOR_DATA); + ArraySetAsSeries(maBandLowerBuffer, true); + SetIndexBuffer(maBandLowerBufferIndex, maBandLowerBuffer, INDICATOR_DATA); // - PlotIndexSetInteger(maBondLowerBufferPlotIndex, PLOT_SHOW_DATA, showMABond); - PlotIndexSetInteger(maBondLowerBufferPlotIndex, PLOT_DRAW_TYPE, maBondDrawType); - PlotIndexSetInteger(maBondLowerBufferPlotIndex, PLOT_DRAW_BEGIN, 0); - PlotIndexSetDouble(maBondLowerBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(maBandLowerBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(maBandLowerBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + PlotIndexSetInteger(maBandLowerBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(maBandLowerBufferPlotIndex, PLOT_EMPTY_VALUE, 0); // - // XPB Bond ... + // XPB Band ... // - // Upper Bond ... + // Upper Band ... // - ArraySetAsSeries(pbBondUpperBuffer, true); - SetIndexBuffer(pbBondUpperBufferIndex, pbBondUpperBuffer, INDICATOR_DATA); + ArraySetAsSeries(pbBandUpperBuffer, true); + SetIndexBuffer(pbBandUpperBufferIndex, pbBandUpperBuffer, INDICATOR_DATA); // - PlotIndexSetInteger(pbBondUpperBufferPlotIndex, PLOT_SHOW_DATA, showMABond); - PlotIndexSetInteger(pbBondUpperBufferPlotIndex, PLOT_DRAW_TYPE, maBondDrawType); - PlotIndexSetDouble(pbBondUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(pbBandUpperBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(pbBandUpperBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + PlotIndexSetDouble(pbBandUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); // - // Lower Bond ... + // Lower Band ... // - ArraySetAsSeries(pbBondLowerBuffer, true); - SetIndexBuffer(pbBondLowerBufferIndex, pbBondLowerBuffer, INDICATOR_DATA); + ArraySetAsSeries(pbBandLowerBuffer, true); + SetIndexBuffer(pbBandLowerBufferIndex, pbBandLowerBuffer, INDICATOR_DATA); // - PlotIndexSetInteger(pbBondLowerBufferPlotIndex, PLOT_SHOW_DATA, showMABond); - PlotIndexSetInteger(pbBondLowerBufferPlotIndex, PLOT_DRAW_TYPE, maBondDrawType); - PlotIndexSetDouble(pbBondLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(pbBandLowerBufferPlotIndex, PLOT_SHOW_DATA, showMABand); + PlotIndexSetInteger(pbBandLowerBufferPlotIndex, PLOT_DRAW_TYPE, maBandDrawType); + PlotIndexSetDouble(pbBandLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); // // XHK ... @@ -1131,29 +1204,54 @@ void DefineBuffers() SetIndexBuffer(hkCloseBufferIndex, hkCloseBuffer, INDICATOR_DATA); // - // XHK Bond ... + // XHK Band ... // - ENUM_DRAW_TYPE hkBondDrawType = showHKBond ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE hkBandDrawType = showHKBand ? DRAW_LINE : DRAW_NONE; // // Upper ... - ArraySetAsSeries(hkBondUpperBuffer, true); - SetIndexBuffer(hkBondUpperBufferIndex, hkBondUpperBuffer, INDICATOR_DATA); + ArraySetAsSeries(hkBandUpperBuffer, true); + SetIndexBuffer(hkBandUpperBufferIndex, hkBandUpperBuffer, INDICATOR_DATA); // - PlotIndexSetInteger(hkBondUpperBufferPlotIndex, PLOT_SHOW_DATA, showHKBond); - PlotIndexSetInteger(hkBondUpperBufferPlotIndex, PLOT_DRAW_TYPE, hkBondDrawType); - PlotIndexSetDouble(hkBondUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(hkBandUpperBufferPlotIndex, PLOT_SHOW_DATA, showHKBand); + PlotIndexSetInteger(hkBandUpperBufferPlotIndex, PLOT_DRAW_TYPE, hkBandDrawType); + PlotIndexSetDouble(hkBandUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); // // Lower ... - ArraySetAsSeries(hkBondLowerBuffer, true); - SetIndexBuffer(hkBondLowerBufferIndex, hkBondLowerBuffer, INDICATOR_DATA); + ArraySetAsSeries(hkBandLowerBuffer, true); + SetIndexBuffer(hkBandLowerBufferIndex, hkBandLowerBuffer, INDICATOR_DATA); // - PlotIndexSetInteger(hkBondLowerBufferPlotIndex, PLOT_SHOW_DATA, showHKBond); - PlotIndexSetInteger(hkBondLowerBufferPlotIndex, PLOT_DRAW_TYPE, hkBondDrawType); - PlotIndexSetDouble(hkBondLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(hkBandLowerBufferPlotIndex, PLOT_SHOW_DATA, showHKBand); + PlotIndexSetInteger(hkBandLowerBufferPlotIndex, PLOT_DRAW_TYPE, hkBandDrawType); + PlotIndexSetDouble(hkBandLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // XATR Band ... + // + ENUM_DRAW_TYPE atrBandDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + + // + // Upper ... + ArraySetAsSeries(atrBandUpperBuffer, true); + SetIndexBuffer(atrBandUpperBufferIndex, atrBandUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(atrBandUpperBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrBandUpperBufferPlotIndex, PLOT_DRAW_TYPE, atrBandDrawType); + PlotIndexSetDouble(atrBandUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Lower ... + ArraySetAsSeries(atrBandLowerBuffer, true); + SetIndexBuffer(atrBandLowerBufferIndex, atrBandLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(atrBandLowerBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrBandLowerBufferPlotIndex, PLOT_DRAW_TYPE, atrBandDrawType); + PlotIndexSetDouble(atrBandLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); // // Data Buffers ... @@ -1250,12 +1348,27 @@ void DefineBuffers() // XPB Data ... // - ArraySetAsSeries(pbBondRawUpperBuffer, true); - SetIndexBuffer(pbBondRawUpperBufferIndex, pbBondRawUpperBuffer, INDICATOR_CALCULATIONS); + ArraySetAsSeries(pbBandRawUpperBuffer, true); + SetIndexBuffer(pbBandRawUpperBufferIndex, pbBandRawUpperBuffer, INDICATOR_CALCULATIONS); // - ArraySetAsSeries(pbBondRawLowerBuffer, true); - SetIndexBuffer(pbBondRawLowerBufferIndex, pbBondRawLowerBuffer, INDICATOR_CALCULATIONS); + ArraySetAsSeries(pbBandRawLowerBuffer, true); + SetIndexBuffer(pbBandRawLowerBufferIndex, pbBandRawLowerBuffer, INDICATOR_CALCULATIONS); + + // + // XATR Data ... + + // + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrBandRawUpperBuffer, true); + SetIndexBuffer(atrBandRawUpperBufferIndex, atrBandRawUpperBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrBandRawLowerBuffer, true); + SetIndexBuffer(atrBandRawLowerBufferIndex, atrBandRawLowerBuffer, INDICATOR_CALCULATIONS); // } @@ -1418,11 +1531,11 @@ bool InitRequirements() } // - // MA Bond Upper ... + // MA Band Upper ... maUpperHandler = iMA( _Symbol, _Period, - maBondLength, + maBandLength, 0, maMethod, PRICE_HIGH // @@ -1434,11 +1547,11 @@ bool InitRequirements() } // - // MA Bond Lower ... + // MA Band Lower ... maLowerHandler = iMA( _Symbol, _Period, - maBondLength, + maBandLength, 0, maMethod, PRICE_LOW // @@ -1463,6 +1576,19 @@ bool InitRequirements() return result; } + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + result = atrHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + // mDrawer = new XCPOIDrawer(); @@ -1620,6 +1746,19 @@ void CalculateValues( tickVolume // ); + // + // XATR ... + CalculateATR( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + // // Fast MA ... double iFastMa = maFastBuffer[barIndex]; @@ -1718,15 +1857,15 @@ void CalculateValues( double iPBLower = MathMin(close[barIndex], open[barIndex]); // - pbBondUpperBuffer[barIndex] = iPBUpper; - pbBondRawUpperBuffer[barIndex] = iPBUpper; + pbBandUpperBuffer[barIndex] = iPBUpper; + pbBandRawUpperBuffer[barIndex] = iPBUpper; // - pbBondLowerBuffer[barIndex] = iPBLower; - pbBondRawLowerBuffer[barIndex] = iPBLower; + pbBandLowerBuffer[barIndex] = iPBLower; + pbBandRawLowerBuffer[barIndex] = iPBLower; // - if (IsXValid(iPBMethod) && maBondLength > 0) + if (IsXValid(iPBMethod) && maBandLength > 0) { // // XPB Upper ... @@ -1734,9 +1873,9 @@ void CalculateValues( ratesTotal, prevCalculated, barIndex, - maBondLength, - pbBondRawUpperBuffer, - pbBondUpperBuffer, + maBandLength, + pbBandRawUpperBuffer, + pbBandUpperBuffer, iPBMethod // ); @@ -1746,9 +1885,9 @@ void CalculateValues( ratesTotal, prevCalculated, barIndex, - maBondLength, - pbBondRawLowerBuffer, - pbBondLowerBuffer, + maBandLength, + pbBandRawLowerBuffer, + pbBandLowerBuffer, iPBMethod // ); } @@ -2334,8 +2473,8 @@ void CalculateHKBar( } // - hkBondUpperBuffer[barIndex] = hkHighBuffer[barIndex]; - hkBondLowerBuffer[barIndex] = hkLowBuffer[barIndex]; + hkBandUpperBuffer[barIndex] = hkHighBuffer[barIndex]; + hkBandLowerBuffer[barIndex] = hkLowBuffer[barIndex]; // // Calculate HK Color ... @@ -2351,6 +2490,93 @@ void CalculateHKBar( : hideColorIDX; } +// +void CalculateATR( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iAtr = atrBuffer[barIndex]; + double iAppliedAtr = atrMultiplier <= 0 + ? iAtr + : atrMultiplier * iAtr; + double iUpperPrice = GetAppliedPrice( + atrUpperPriceType, + open, + high, + low, + close, + barIndex // + ); + double iLowerPrice = GetAppliedPrice( + atrLowerPriceType, + open, + high, + low, + close, + barIndex // + ); + double iPriceMid = iLowerPrice + ((iUpperPrice - iLowerPrice) / 2); + + // + double iUpperAtr = iPriceMid + iAppliedAtr; + double iLowerAtr = iPriceMid - iAppliedAtr; + + // + atrBandRawUpperBuffer[barIndex] = iUpperAtr; + atrBandRawLowerBuffer[barIndex] = iLowerAtr; + + // + // Check Can Smooth Atr ... + if (IsXValid(atrSmoothingMode) && + atrSmoothingLength > 0) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + atrSmoothingLength, + atrBandRawUpperBuffer, + atrBandUpperBuffer, + atrSmoothingMode // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + atrSmoothingLength, + atrBandRawLowerBuffer, + atrBandLowerBuffer, + atrSmoothingMode // + ); + } + else + { + // + atrBandUpperBuffer[barIndex] = iUpperAtr; + atrBandLowerBuffer[barIndex] = iLowerAtr; + } +} + // void CalculateCycleRanges( int barIndex, diff --git a/Libraries/x-saherelm.x-pivot.analysis.lib.mq5 b/Libraries/x-saherelm.x-pivot.analysis.lib.mq5 index 7acdef3d..fd1afedc 100644 --- a/Libraries/x-saherelm.x-pivot.analysis.lib.mq5 +++ b/Libraries/x-saherelm.x-pivot.analysis.lib.mq5 @@ -2452,6 +2452,64 @@ struct XPatternAnalysis return result; } + /** + * Extract All Exists Patterns Pivots ... + * + * @param dest: XPivot, collection reference to holds Extracted Patterns ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction of Extractions ... + * + * @return ( int ) + */ + int GetPatterns( + XPivot &dest[], + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Validate ... + bool has = IsValid() && + HasChild(patterns); + if (!has) + { + return result; + } + + // + // Do ... + XOHCL iBar; + XPivot iPivot; + XBoxZone iZone; + int count = ArraySize(patterns); + for (int i = 0; i < count; i++) + { + // + has = GetPattern(iBar, iPivot, iZone, patterns[i], forDir); + if (has) + { + AddIfNotExists(iPivot, dest); + } + } + + // + result = ArraySize(dest); + + // + // Cleanup ... + iBar.Clean(); + iZone.Clean(); + iPivot.Clean(); + + // + return result; + } + // }; @@ -2460,12 +2518,6 @@ struct XPatternAnalysisConfig // // Props ... - // - // Quarter ... - int quarterZonesRequiredToStart; - int quarterZoneDetectionLoopback; - int quarterZonesValidationLength; - // // PV ... int pvValidationLength; @@ -2523,12 +2575,6 @@ struct XPatternAnalysisConfig */ void Clean() { - // - // Quarter ... - quarterZonesRequiredToStart = 0; - quarterZoneDetectionLoopback = 0; - quarterZonesValidationLength = 0; - // // PV ... pvValidationLength = 0; @@ -2580,12 +2626,6 @@ struct XPatternAnalysisConfig */ void Default() { - // - // Quarter ... - quarterZonesRequiredToStart = 20; - quarterZonesValidationLength = 3; - quarterZoneDetectionLoopback = 1500; - // // PV ... pvValidationLength = 5; @@ -3073,4 +3113,51 @@ struct XPatternAnalysisDrawConfig } }; +// +// Extensions ... + +bool FindByTime( + int &index, + datetime time, + XPatternAnalysis &source[] // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Validate ... + result = IsXValid(time) && + HasChild(source); + if (!result) + { + return result; + } + + // + // Do ... + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + result = source[i].bar.time == time; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + // \ No newline at end of file diff --git a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 index 36f7b047..97d9ded2 100644 --- a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -2271,6 +2271,7 @@ void SortBar( //+------------------------------------------------------------------+ //| Extraction | //+------------------------------------------------------------------+ + /** * Extract Specific Types of Pivots From a Collection ... * @@ -2329,6 +2330,61 @@ int ExtractPivots( return result; } +/** + * Extract Same Time Pivots ... + * + * @param item: XPivot, reference to Specified Pivot for Detect Same Times ... + * @param dest: XPivot, collection reference to holds Same Times Pivots ... + * @param source: XPivot, collection reference to Provide Data Source ... + * + * @return ( int ) + */ +int ExtractSameTimePivots( + XPivot &item, + XPivot &dest[], + XPivot &source[] // +) +{ + // + int result = 0; + + // + // Prepare ... + XClean(dest); + + // + // Validate ... + bool has = HasChild(source) && + item.IsValid(); + if (!has) + { + return result; + } + + // + // Do ... + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + has = item.time == source[i].time; + if (has) + { + AddIfNotExists(source[i], dest); + } + } + + // + // Add item as a Child ... + AddIfNotExists(item, dest); + + // + result = ArraySize(dest); + + // + return result; +} + /** * Extract Pivots Data for Linear Regression Calculations ... * diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index 4cf71b61..79eb33f1 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -333,9 +333,9 @@ enum ENUM_X_DETECTOR_ZONE_ACTION /** * Validate an ENUM member ... - * + * * @param value: ENUM_X_DETECTOR_ZONE_ACTION ... - * + * * @return ( bool ) */ bool IsXValid(ENUM_X_DETECTOR_ZONE_ACTION value) @@ -636,6 +636,15 @@ struct XPivot symbol == item.symbol && period == item.period; + // + if (result && IsXValid(prefix)) + { + // + result = + result && + prefix == item.prefix; + } + // return result; } diff --git a/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 new file mode 100644 index 00000000..41e24005 --- /dev/null +++ b/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 @@ -0,0 +1,2729 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Parser Class Library +// ---------------------------------------------------- +// Name: XCXFIMAHelperParser +// Description: provides all Indicator +// Helper Parse requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Helpers/x-saherelm.xfima.helper.mq5" + +// +// Definitions ... + +// +// Implementation ... + +class XCXFIMAHelperParser : XCBase +{ + // + // Public ... + public: + // + string symbol; + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XCXFIMAHelperParser(XCXFIMAHelper *_helper) + { + // + helper = _helper; + symbol = _helper.GetSymbol(); + period = _helper.GetPeriod(); + } + + // + // Deconstructor ... + ~XCXFIMAHelperParser() + { + ZeroMemory(helper); + } + + // + // Tools ... + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = helper != NULL && + helper.IsValid() && + IsXValid(symbol) && + IsXValid(period); + + // + return result; + } + + /** + * Normalize Bar Index ... + * + * @param barIndex: int, Provided Bar Index ... + * + * @return ( int ) + */ + int NormalizeBarIndex(int barIndex = 0) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + result = helper.NormalizeBarIndex(barIndex); + + // + return result; + } + + // + // Parsers ... + + // + // XSAR ... + + /** + * Check SAR is Bullish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSARBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetSARState(barIndex); + result = state >= 1; + + // + return result; + } + + /** + * Check SAR is Bearish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSARBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double state = helper.GetSARState(barIndex); + result = state <= -1; + + // + return result; + } + + /** + * Check SAR is Switched to Bullish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSARSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + int pBarIndex = barIndex + 1; + + // + bool isBullish = IsSARBullish(barIndex); + bool isPBullish = IsSARBullish(pBarIndex); + + // + result = isBullish && + !isPBullish; + + // + return result; + } + + /** + * Check SAR is Switched to Bearish or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsSARSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + int pBarIndex = barIndex + 1; + + // + bool isBearish = IsSARBearish(barIndex); + bool isPBearish = IsSARBearish(pBarIndex); + + // + result = isBearish && + !isPBearish; + + // + return result; + } + + /** + * Count Bullish SAR(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBullishSARs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsSARBullish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Bearish SAR(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBearishSARs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsSARBearish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + // + // XMA ... + + /** + * Check Fast Ma Over Slow or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastOverSlow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iFast = helper.GetMAFast(barIndex); + double iSlow = helper.GetMASlow(barIndex); + + // + result = iFast > iSlow; + + // + return result; + } + + /** + * Check Fast Ma Under Slow or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastUnderSlow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iFast = helper.GetMAFast(barIndex); + double iSlow = helper.GetMASlow(barIndex); + + // + result = iFast < iSlow; + + // + return result; + } + + /** + * Check Fast Ma Over Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iFast = helper.GetMAFast(barIndex); + double pFast = helper.GetMAFast(barIndex + 1); + + // + result = iFast > pFast; + + // + return result; + } + + /** + * Check Slow Ma Over Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMASlowOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iSlow = helper.GetMASlow(barIndex); + double pSlow = helper.GetMASlow(barIndex + 1); + + // + result = iSlow > pSlow; + + // + return result; + } + + /** + * Check Fast Ma Under Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iFast = helper.GetMAFast(barIndex); + double pFast = helper.GetMAFast(barIndex + 1); + + // + result = iFast < pFast; + + // + return result; + } + + /** + * Check Slow Ma Under Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMASlowUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iSlow = helper.GetMASlow(barIndex); + double pSlow = helper.GetMASlow(barIndex + 1); + + // + result = iSlow < pSlow; + + // + return result; + } + + /** + * Check MA Fast is Crossed Over Slow or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastCrossedOverSlow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isFastOverSlow = IsMAFastOverSlow(barIndex); + bool isPFastOverSlow = IsMAFastOverSlow(barIndex + 1); + + // + result = isFastOverSlow && + !isPFastOverSlow; + + // + return result; + } + + /** + * Check MA Fast is Crossed Under Slow or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastCrossedUnderSlow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isFastUnderSlow = IsMAFastUnderSlow(barIndex); + bool isPFastUnderSlow = IsMAFastUnderSlow(barIndex + 1); + + // + result = isFastUnderSlow && + !isPFastUnderSlow; + + // + return result; + } + + /** + * Check MA Fast is Crossed Over Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastCrossedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isFastOverLast = IsMAFastOverLast(barIndex); + bool isPFastOverLast = IsMAFastOverLast(barIndex + 1); + + // + result = isFastOverLast && + !isPFastOverLast; + + // + return result; + } + + /** + * Check MA Fast is Crossed Under Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMAFastCrossedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isFastUnderLast = IsMAFastUnderLast(barIndex); + bool isPFastUnderLast = IsMAFastUnderLast(barIndex + 1); + + // + result = isFastUnderLast && + !isPFastUnderLast; + + // + return result; + } + + /** + * Check MA Slow is Crossed Over Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMASlowCrossedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isSlowOverLast = IsMASlowOverLast(barIndex); + bool isPSlowOverLast = IsMASlowOverLast(barIndex + 1); + + // + result = isSlowOverLast && + !isPSlowOverLast; + + // + return result; + } + + /** + * Check MA Slow is Crossed Under Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMASlowCrossedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isSlowUnderLast = IsMASlowUnderLast(barIndex); + bool isPSlowUnderLast = IsMASlowUnderLast(barIndex + 1); + + // + result = isSlowUnderLast && + !isPSlowUnderLast; + + // + return result; + } + + /** + * Check MA Fast and Slow Crossed Over Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMACrossedOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isFastCrossedOverLast = IsMAFastCrossedOverLast(barIndex); + bool isSlowCrossedOverLast = IsMASlowCrossedOverLast(barIndex); + + // + result = isFastCrossedOverLast && + isSlowCrossedOverLast; + + // + return result; + } + + /** + * Check MA Fast and Slow Crossed Under Last or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsMACrossedUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool isFastCrossedUnderLast = IsMAFastCrossedUnderLast(barIndex); + bool isSlowCrossedUnderLast = IsMASlowCrossedUnderLast(barIndex); + + // + result = isFastCrossedUnderLast && + isSlowCrossedUnderLast; + + // + return result; + } + + /** + * Count MA Fast Over Slows ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMAFastOverSlows( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMAFastOverSlow(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count MA Fast Under Slows ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMAFastUnderSlows( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMAFastUnderSlow(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count MA Fast Over Lasts ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMAFastOverLasts( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMAFastOverLast(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count MA Fast Under Lasts ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMAFastUnderLasts( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMAFastUnderLast(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count MA Slow Over Lasts ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMASlowOverLasts( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMASlowOverLast(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count MA Slow Under Lasts ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountMASlowUnderLasts( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsMASlowUnderLast(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Over MA Fast Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountOverMAFastBars( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_LOW, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + // DO ... + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetMAFast(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice > iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Count Under MA Fast Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountUnderMAFastBars( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + // DO ... + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetMAFast(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice < iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Count Over MA Slow Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountOverMASlowBars( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_LOW, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + // DO ... + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetMASlow(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice > iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Count Under MA Slow Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountUnderMASlowBars( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_HIGH, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + // DO ... + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetMASlow(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice < iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + // + // XHK ... + + /** + * Check HK is Bullish or not ... + * + * @param barIndex: int, Specified BarIndex ... + * + * @return ( bool ) + */ + bool IsHKBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iO = helper.GetHKOpen(barIndex); + double iC = helper.GetHKClose(barIndex); + + // + result = + NotEmptyZero(iO) && + NotEmptyZero(iC) && + iC > iO; + + // + return result; + } + + /** + * Check HK is Bearish or not ... + * + * @param barIndex: int, Specified BarIndex ... + * + * @return ( bool ) + */ + bool IsHKBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + double iO = helper.GetHKOpen(barIndex); + double iC = helper.GetHKClose(barIndex); + + // + result = + NotEmptyZero(iO) && + NotEmptyZero(iC) && + iC < iO; + + // + return result; + } + + /** + * Check HK is Switched to Bullish or not ... + * + * @param barIndex: int, Specified BarIndex ... + * + * @return ( bool ) + */ + bool IsHKSwitchedToBullish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool is = IsHKBullish(barIndex); + bool isP = IsHKBullish(barIndex + 1); + + // + result = is && + !isP; + + // + return result; + } + + /** + * Check HK is Switched to Bearish or not ... + * + * @param barIndex: int, Specified BarIndex ... + * + * @return ( bool ) + */ + bool IsHKSwitchedToBearish(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + bool is = IsHKBearish(barIndex); + bool isP = IsHKBearish(barIndex + 1); + + // + result = is && + !isP; + + // + return result; + } + + /** + * Count Bullish HK(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBullishHKs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsHKBullish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Bearish HK(s) ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountBearishHKs( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // DO ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + has = IsHKBearish(idx); + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Over HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountOverHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetHKBandLower(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice > iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Count Under HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountUnderHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetHKBandLower(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice < iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Count Over HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountOverHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetHKBandUpper(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice > iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Count Under HK Band Bars ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountUnderHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid() && + IsXValid(priceType); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex; + double iValue = EMPTY_VALUE; + double iPrice = EMPTY_VALUE; + while (idx < barIndex + loopback) + { + // + idx++; + iBar.Clean(); + has = iBar.Init(symbol, period, idx); + if (!has) + { + break; + } + + // + iValue = helper.GetHKBandUpper(idx); + iPrice = iBar.GetPrice(priceType); + + // + has = iPrice < iValue; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + // + // XPV ... + + /** + * Check Peak Same as Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsPeakSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double iC = helper.GetPeak(barIndex); + double iP = helper.GetPeak(barIndex + 1); + + // + result = iC == iP && + NotEmptyZero(iC); + + // + return result; + } + + /** + * Check Vale Same as Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsValeSame(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + double iC = helper.GetVale(barIndex); + double iP = helper.GetVale(barIndex + 1); + + // + result = iC == iP && + NotEmptyZero(iC); + + // + return result; + } + + /** + * Count Same Peaks ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountSamePeaks( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + double iPeak = EMPTY_VALUE; + double peak = helper.GetPeak(barIndex); + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + iPeak = helper.GetPeak(idx); + has = peak == iPeak; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Count Same Vales ... + * + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( int ) + */ + int CountSameVales( + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + double iVale = EMPTY_VALUE; + double vale = helper.GetVale(barIndex); + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + iVale = helper.GetVale(idx); + has = vale == iVale; + if (has) + { + result++; + } + if (!has) + { + break; + } + } + + // + return result; + } + + /** + * Check Peak Happens over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsPeakOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iPeak = helper.GetPeak(barIndex); + double pPeak = helper.GetPeak(barIndex + 1); + + // + result = NotEmptyZero(iPeak) && + iPeak > pPeak; + + // + return result; + } + + /** + * Check Vale Happens over Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsValeOverLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iVale = helper.GetVale(barIndex); + double pVale = helper.GetVale(barIndex + 1); + + // + result = NotEmptyZero(iVale) && + iVale > pVale; + + // + return result; + } + + /** + * Check Peak Happens under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsPeakUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iPeak = helper.GetPeak(barIndex); + double pPeak = helper.GetPeak(barIndex + 1); + + // + result = NotEmptyZero(iPeak) && + iPeak < pPeak; + + // + return result; + } + + /** + * Check Vale Happens under Last ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsValeUnderLast(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Reading Values ... + + // + double iVale = helper.GetVale(barIndex); + double pVale = helper.GetVale(barIndex + 1); + + // + result = NotEmptyZero(iVale) && + iVale < pVale; + + // + return result; + } + + /** + * Detect Last Peak Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastPeakOverLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsPeakOverLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Peak Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastPeakUnderLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsPeakUnderLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Vale Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastValeOverLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsValeOverLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Detect Last Vale Change ... + * + * @param index: int, reference to hold change index ... + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Max Allowed Loopback Length ... + * + * @return ( bool ) + */ + bool FindLastValeUnderLast( + int &index, + int barIndex = 0, + int loopback = 500 // + ) + { + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Loop ... + int idx = barIndex; + while (idx < barIndex + loopback) + { + // + idx++; + result = IsValeUnderLast(idx); + if (result) + { + // + index = idx; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + // + // XZG ... + + /** + * Check ZigZag has Value and Read it ... + * + * @param value: double, reference to holds value ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool HasZG( + double &value, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Prepare ... + value = EMPTY_VALUE; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + value = helper.GetZigZag(barIndex); + + // + result = NotEmptyZero(value); + + // + return result; + } + + /** + * Check ZG is Low or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsZGLow(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Reading Value ... + double iValue; + result = HasZG(iValue, barIndex); + if (!result) + { + return result; + } + + // + // Reading Value ... + XOHCL iBar; + result = iBar.Init(symbol, period, barIndex); + result = result && + iBar.low == iValue; + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + /** + * Check ZG is High or not ... + * + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ + bool IsZGHigh(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Do ... + + // + // Reading Value ... + double iValue; + result = HasZG(iValue, barIndex); + if (!result) + { + return result; + } + + // + // Reading Value ... + XOHCL iBar; + result = iBar.Init(symbol, period, barIndex); + result = result && + iBar.high == iValue; + + // + // Cleanup ... + iBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + XCXFIMAHelper *helper; + + // +}; + +// diff --git a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 index 7f354d83..83495139 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -24,6 +24,7 @@ // Imports ... #include "../../Classes/x-saherelm.x-signaller.class.mq5" #include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.parser.class.mq5" #include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" #include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" @@ -45,6 +46,7 @@ class XCXFIMABaseSignaller : public XCBaseSignaller XFIMAInputs fimaInputs; // XFIMA Inputs ... XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... + XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ... XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... XFIMAMarketStructureConfig structureConfig; // XFIMA Market Structure Detector Config ... XFIMAMarketStructureDrawerConfig structureDrawConfig; // XFIMA Market Structure Draw Config ... @@ -92,9 +94,13 @@ class XCXFIMABaseSignaller : public XCBaseSignaller } } + // + // Instantiate XFIMA Helper Parser ... + fimaParser = new XCXFIMAHelperParser(fimaHelper); + // poiDrawer = new XCXFIMAPOIDrawer(); - poiDetector = new XCXFIMAPOIDetector(fimaHelper); + poiDetector = new XCXFIMAPOIDetector(fimaHelper, fimaParser); // // Configure ... @@ -556,25 +562,17 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // Draw Flags ... bool draw = true; bool drawZone = true; - bool drawOrderFlow = true; + bool drawMarketStructurePivots = true; + bool drawMarketStructureAnalysis = true; + bool drawMarketStructureOrderFlow = true; XPOIDrawConfig iDrawConfig; // // Signal Checking ... // - // Detecting OrderFlow ... - XBoxZone orderFlow[]; - ENUM_X_DIRECTION orderFlowDir; - bool hasOrderFlow = poiDetector.HasOrderFlow( - bar, - orderFlowDir, - orderFlow, - 2, - false, // Contains OB ... - true, // Contains FVG ... - false // Contains Support and Resistances ... - ); + // Analyse Market Strucutre ... + XFIMAMarketStructure marketStructure; // // Signaller 1 ... @@ -660,14 +658,24 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller if (result && validateByOrderFlow) { // - bool isBullish = hasOrderFlow && - IsXBullish(dir) && - IsXBullish(orderFlowDir); + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) + { + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } // - bool isBearish = hasOrderFlow && - IsXBearish(dir) && - IsXBearish(orderFlowDir); + bool isBullish = IsXBullish(dir) && + marketStructure.HasBullishOrderFlow(); + + // + bool isBearish = IsXBearish(dir) && + marketStructure.HasBearishOrderFlow(); // // Summarizing result ... @@ -749,7 +757,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // // Partial Close on TP 1 ... - if (hasPartialCloseOnTp1 && tp > tp1) + if (hasPartialCloseOnTp1) { // iTarget.Clean(); @@ -814,10 +822,52 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller } // - // Draw Order Flow ... - if (drawOrderFlow && HasChild(orderFlow)) + // Draw Market Structure ... + // + // Analyse Market Structure if Required ... + if (!marketStructure.IsValid()) { - poiDrawer.DrawZones(orderFlow, iDrawConfig); + // + poiDetector.AnalyseMarket( + marketStructure, + structureConfig, + bar.Index() // + ); + } + if (marketStructure.IsValid()) + { + // + // Order Flow ... + if (drawMarketStructureOrderFlow && marketStructure.HasOrderFlow()) + { + poiDrawer.DrawZones(marketStructure.orderFlow, iDrawConfig); + } + + // + // Pivots ... + if (drawMarketStructurePivots) + { + // + XPivot pivots[]; + int pivotsCount = marketStructure.CollectPivots( + pivots, + true // Contains Patterns ... + ); + if (IsValidSize(pivotsCount)) + { + poiDrawer.DrawPivots(pivots, iDrawConfig); + } + + // + XClean(pivots); + } + + // + // Analysis ... + if (drawMarketStructureAnalysis) + { + // + } } // @@ -841,6 +891,11 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller DebugBreak(); } + // + // Cleanup ... + iDrawConfig.Clean(); + marketStructure.Clean(); + // return result; } @@ -918,13 +973,13 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller } // - // Reading HK Bond ... + // Reading HK Band ... // - double pHKBondUpper = fimaHelper.GetHKBondUpper(pBar.Index()); - double pHKBondLower = fimaHelper.GetHKBondLower(pBar.Index()); - int overHKBondUpperCount = fimaHelper.CountOverHKBondUpper(pullBackStartBar, X_PRICE_LOW); - int underHKBondLowerCount = fimaHelper.CountUnderHKBondLower(pullBackStartBar, X_PRICE_HIGH); + double pHKBandUpper = fimaHelper.GetHKBandUpper(pBar.Index()); + double pHKBandLower = fimaHelper.GetHKBandLower(pBar.Index()); + int overHKBandUpperCount = fimaParser.CountOverHKBandUpper(pullBackStartBar, X_PRICE_LOW); + int underHKBandLowerCount = fimaParser.CountUnderHKBandLower(pullBackStartBar, X_PRICE_HIGH); // // Reading PV Requirements ... @@ -934,10 +989,10 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller int lastValeUnderLastIDX = -1; double pPeak = fimaHelper.GetPeak(pBar.Index()); double pVale = fimaHelper.GetVale(pBar.Index()); - int samePeaks = fimaHelper.CountSamePeaks(pBar.Index()); - int sameVales = fimaHelper.CountSameVales(pBar.Index()); - fimaHelper.FindLastPeakOverLast(lastPeakOverLastIDX, pBar.Index()); - fimaHelper.FindLastValeUnderLast(lastValeUnderLastIDX, pBar.Index()); + int samePeaks = fimaParser.CountSamePeaks(pBar.Index()); + int sameVales = fimaParser.CountSameVales(pBar.Index()); + fimaParser.FindLastPeakOverLast(lastPeakOverLastIDX, pBar.Index()); + fimaParser.FindLastValeUnderLast(lastValeUnderLastIDX, pBar.Index()); // // Reading pBar Patterns ... @@ -1040,7 +1095,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller hasBullishInside && isPullbackBullish && isPBarHasBullishPatterns && - fimaHelper.IsSarBullish(pBar.Index()) && + fimaParser.IsSARBullish(pBar.Index()) && (pVale >= affectedZonesBullish[insideBullishIDX].lower && pVale <= affectedZonesBullish[insideBullishIDX].upper) // @@ -1052,7 +1107,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller hasBearishInside && isPullbackBearish && isPBarHasBearishPatterns && - fimaHelper.IsSarBearish(pBar.Index()) && + fimaParser.IsSARBearish(pBar.Index()) && (pPeak >= affectedZonesBearish[insideBearishIDX].lower && pPeak <= affectedZonesBearish[insideBearishIDX].upper) // @@ -1064,24 +1119,6 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller isBearish; if (result) { - // - if (isBullish) - { - // - poiDrawer.DrawZone( - affectedZonesBullish[insideBullishIDX], - structureDrawConfig.drawConfig // - ); - } - else - { - // - poiDrawer.DrawZone( - affectedZonesBearish[insideBearishIDX], - structureDrawConfig.drawConfig // - ); - } - // dir = isBullish @@ -1238,10 +1275,10 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller double pVale = fimaHelper.GetVale(pBar.Index()); double p2Peak = fimaHelper.GetPeak(p2Bar.Index()); double p2Vale = fimaHelper.GetVale(p2Bar.Index()); - bool isPPeakOverLast = fimaHelper.IsPeakOverLast(pBar.Index()); - bool isPValeUnderLast = fimaHelper.IsValeUnderLast(pBar.Index()); - bool isP2PeakOverLast = fimaHelper.IsPeakOverLast(p2Bar.Index()); - bool isP2ValeUnderLast = fimaHelper.IsValeUnderLast(p2Bar.Index()); + bool isPPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); + bool isPValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); + bool isP2PeakOverLast = fimaParser.IsPeakOverLast(p2Bar.Index()); + bool isP2ValeUnderLast = fimaParser.IsValeUnderLast(p2Bar.Index()); bool isPeakOverLast = isPPeakOverLast || isP2PeakOverLast; bool isValeUnderLast = isPValeUnderLast || @@ -1473,7 +1510,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // XFIMA Consolidation ... // - bool isConsolidation = fimaHelper.HasPVConsolidationZone( + bool isConsolidation = poiDetector.DetectPVConsolidationZone( zone, pBar.Index(), true, // Force PV Break ... @@ -1707,12 +1744,6 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // result = isBullish || isBearish; - if (result) - { - // - poiDrawer.DrawZones(orderFlow, structureDrawConfig.drawConfig); - Print("OrderFlow Detected ..."); - } // isBullish = diff --git a/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 index ac1fcbd5..46b05e54 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 @@ -27,6 +27,131 @@ #include "../../Classes/x-saherelm.x-market.pattern.class.mq5" #include "../Libraries/x-saherelm.xfima.lib.mq5" +// +// Definitions ... + +enum ENUM_XFIMA_PIVOTS +{ + XFIMA_PIVOT_NONE = 0, + XFIMA_PIVOT_PV = 1, + XFIMA_PIVOT_ZIGZAG = 2, + XFIMA_PIVOT_MA_CROSS = 3, + XFIMA_PIVOT_HK_SWITCH = 4, + XFIMA_PIVOT_SAR_SWITCH = 5, + XFIMA_PIVOT_BOUNDARY_SWITCH = 6, +}; + +bool IsXValid(ENUM_XFIMA_PIVOTS value) +{ + // + bool result = false; + + // + result = value != XFIMA_PIVOT_NONE; + + // + return result; +} + +string ToXString(ENUM_XFIMA_PIVOTS value) +{ + // + string result = NULL; + + // + if (!IsXValid(value)) + { + return result; + } + + // + switch (value) + { + // + case XFIMA_PIVOT_NONE: + result = "NONE"; + break; + + // + case XFIMA_PIVOT_PV: + result = "XPV"; + break; + + // + case XFIMA_PIVOT_ZIGZAG: + result = "XZGP"; + break; + + // + case XFIMA_PIVOT_MA_CROSS: + result = "XMACRS"; + break; + + // + case XFIMA_PIVOT_HK_SWITCH: + result = "XHKSWCH"; + break; + + // + case XFIMA_PIVOT_SAR_SWITCH: + result = "XSARSWCH"; + break; + + // + case XFIMA_PIVOT_BOUNDARY_SWITCH: + result = "XBNDSWCH"; + break; + } + + // + return result; +} + +ENUM_XFIMA_PIVOTS ToXFIMAPivots(string value) +{ + // + ENUM_XFIMA_PIVOTS result = XFIMA_PIVOT_NONE; + + // + if (!IsXValid(value)) + { + return result; + } + + // + if (value == ToXString(XFIMA_PIVOT_NONE)) + { + result = XFIMA_PIVOT_NONE; + } + else if (value == ToXString(XFIMA_PIVOT_PV)) + { + result = XFIMA_PIVOT_PV; + } + else if (value == ToXString(XFIMA_PIVOT_ZIGZAG)) + { + result = XFIMA_PIVOT_ZIGZAG; + } + else if (value == ToXString(XFIMA_PIVOT_MA_CROSS)) + { + result = XFIMA_PIVOT_MA_CROSS; + } + else if (value == ToXString(XFIMA_PIVOT_HK_SWITCH)) + { + result = XFIMA_PIVOT_HK_SWITCH; + } + else if (value == ToXString(XFIMA_PIVOT_SAR_SWITCH)) + { + result = XFIMA_PIVOT_SAR_SWITCH; + } + else if (value == ToXString(XFIMA_PIVOT_BOUNDARY_SWITCH)) + { + result = XFIMA_PIVOT_BOUNDARY_SWITCH; + } + + // + return result; +} + // // Implementation ... class XCXFIMAPOIDetector : public XCMarketPatternDetector @@ -36,18 +161,31 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector public: // // Props ... - XCBarAnalyser *barAnalyser; // Bar Analyser ... - XCXFIMAHelper *fimaHelper; // XFIMA Helper ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + XCBarAnalyser *barAnalyser; // Bar Analyser ... + XCXFIMAHelper *fimaHelper; // XFIMA Helper ... + XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ... // // Constructor ... XCXFIMAPOIDetector( - XCXFIMAHelper *_fimaHelper // + XCXFIMAHelper *_fimaHelper, + XCXFIMAHelperParser *_fimaParser // ) : XCMarketPatternDetector() { // barAnalyser = new XCBarAnalyser(); fimaHelper = _fimaHelper; + fimaParser = _fimaParser; + + // + symbol = fimaHelper.GetSymbol(); + period = fimaHelper.GetPeriod(); } // @@ -61,25 +199,26 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector // Actions and Tools ... // - // Pivot Analysors ... + // Detectors ... + + // + // XPV ... /** - * Analyse Market based on Specified Kind of Pivots ... + * Check Conditions to Detecte XPV based Consolidation Zone ... * - * @param analysis: XPivotAnalysis, reference to hold result ... - * @param barIndex: int, Bar Index ... - * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... - * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... - * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * @param zone: XBoxZone, reference to holds detected zone ... + * @param barIndex: int, Specified Bar Index ... + * @param forcePVBreak: bool, force to has PV Side Break ... + * @param forceHasSarSwitch: bool, force to has SAR Switche ... * * @return ( bool ) */ - bool AnalysePVPivots( - XPivotAnalysis &analysis, + bool DetectPVConsolidationZone( + XBoxZone &zone, int barIndex = 0, - int requiredNumberOFPivots = 50, - int maxAllowedLoopbackLength = 1500, - int validationLength = 0 // + bool forcePVBreak = false, + bool forceHasSarSwitch = false // ) { // @@ -87,68 +226,274 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector // // Prepare ... - analysis.Clean(); + zone.Clean(); // - // Reading Pivots ... - XPivot pivots[]; - int count = fimaHelper.ExtractPVPivots( - pivots, // Result ... - barIndex, // Bar Index ... - requiredNumberOFPivots, // Required Number of Pivots ... - maxAllowedLoopbackLength, // Max Allowed Loopback ... - validationLength // Validation Length ... - ); - result = IsValidSize(count); + // Normalize ... + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + result = fimaParser.IsValid(); if (!result) { - // - SpecifiedClean(pivots); return result; } // - string symbol = fimaHelper.GetSymbol(); - ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + // Do ... // - // Initialize Analysis ... - result = analysis.Init( - "XFIMA_XPV", - symbol, - period, - pivots // - ); - - // - // Cleanup Resources ... + bool isPeakSame = fimaParser.IsPeakSame(barIndex); + bool isValeSame = fimaParser.IsValeSame(barIndex); + result = !(isPeakSame && + isValeSame); if (!result) { - analysis.Clean(); + return result; + } + + // + double iPeak = EMPTY_VALUE; + double iVale = EMPTY_VALUE; + + // + int idx = barIndex; + bool canLookup = true; + while (canLookup) + { + // + idx++; + isPeakSame = fimaParser.IsPeakSame(idx); + isValeSame = fimaParser.IsValeSame(idx); + result = isPeakSame && + isValeSame; + if (!result) + { + // + zone.from = GetBarTime(symbol, period, idx); + break; + } + + // + if (idx == barIndex + 1) + { + // + zone.to = GetBarTime( + symbol, + period, + idx // + ); + } + + // + zone.from = GetBarTime( + symbol, + period, + idx // + ); + + // + iPeak = fimaHelper.GetPeak(idx); + iVale = fimaHelper.GetVale(idx); + + // + zone.lower = + !NotEmptyZero(zone.lower) + ? iVale + : MathMin(zone.lower, iVale); + + // + zone.upper = + !NotEmptyZero(zone.upper) + ? iPeak + : MathMax(zone.upper, iPeak); + } + + // + // Validating Zone Params ... + result = + // + IsXValid(zone.to) && + IsXValid(zone.from) && + zone.from < zone.to && + // + NotEmptyZero(zone.lower) && + NotEmptyZero(zone.upper) && + zone.upper > zone.lower + // + ; + + // + // Prepare Zone ... + if (result) + { + // + iPeak = fimaHelper.GetPeak(barIndex); + iVale = fimaHelper.GetVale(barIndex); + bool isPeakOverLast = fimaParser.IsPeakOverLast(barIndex); + bool isValeUnderLast = fimaParser.IsValeUnderLast(barIndex); + bool isValeBreak = iVale < zone.lower; + bool isPeakBreak = iPeak > zone.upper; + bool isPVBreak = isPeakBreak || + isValeBreak; + + // + zone.at = GetBarTime(symbol, period, barIndex); + zone.symbol = symbol; + zone.period = period; + zone.dir = (isPeakOverLast && !isValeUnderLast && isPVBreak) + ? X_DIRECTION_BULLISH + : (isValeUnderLast && !isPeakOverLast && isPVBreak) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + zone.type = ToXString(X_BAR_PATTERN_CONSOLIDATION); + + // + // Refine Zone Upper and Lower ... + if (zone.IsValid()) + { + // + XOHCL iBar; + int zoneLoopback = zone.FromIndex() - zone.ToIndex(); + result = zone.ToBar(iBar) && + IsValidSize(zoneLoopback); + if (result) + { + // + double zoneLL = iBar.FindLowest(zoneLoopback, MODE_LOW); + double zoneHH = iBar.FindHighest(zoneLoopback, MODE_HIGH); + result = NotEmptyZero(zoneLL) && + NotEmptyZero(zoneHH); + if (result) + { + // + zone.lower = zone.lower == zoneLL + ? zone.lower + : MathMax(zone.lower, zoneLL); + + // + zone.upper = zone.upper == zoneHH + ? zone.upper + : MathMin(zone.upper, zoneHH); + } + } + + // + iBar.Clean(); + } + + // + // Validate ... + result = zone.IsValid(); + } + + // + // Validate Zones From ... + if (result) + { + // + int idx = zone.FromIndex(); + + // + iPeak = fimaHelper.GetPeak(idx); + iVale = fimaHelper.GetVale(idx); + + // + bool isValeOverLast = fimaParser.IsValeOverLast(idx); + bool isPeakUnderLast = fimaParser.IsPeakUnderLast(idx); + + // + result = + result && + (zone.IsBullish() + ? !isPeakUnderLast + : zone.IsBearish() + ? !isValeOverLast + : false); + } + + // + // Apply Forces ... + + // + // PV Break ... + // Peak or Vale must Breaked at Bar ... + if (result && forcePVBreak) + { + // + bool isPVBreaked = + (zone.IsBullish() && fimaParser.IsPeakOverLast(barIndex)) || + (zone.IsBearish() && fimaParser.IsValeUnderLast(barIndex)); + + // + result = result && + isPVBreaked; + } + + // + // Other Loop based Forces ... + if (result && (forceHasSarSwitch)) + { + + // + bool hasSarSwitch = false; + + // + int start = zone.ToIndex(); + int end = zone.FromIndex(); + for (int i = start; i <= end; i++) + { + // + // Check Sar Switches ... + if (forceHasSarSwitch && !hasSarSwitch) + { + // + hasSarSwitch = + zone.IsBullish() + ? fimaParser.IsSARSwitchedToBullish(i) + : fimaParser.IsSARSwitchedToBearish(i); + } + } + + // + // Validate Forces ... + if (forceHasSarSwitch) + { + // + result = + result && + hasSarSwitch; + } + } + + // + // Cleanup ... + if (!result) + { + zone.Clean(); } - SpecifiedClean(pivots); // return result; } + // + // Analysors ... + /** - * Analyse Market based on Specified Kind of Pivots ... + * Analyse Market ... * - * @param analysis: XPivotAnalysis, reference to hold result ... - * @param barIndex: int, Bar Index ... - * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... - * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... - * @param validationLength: int, Specified Pivots Validation Length ignore if <= 0 ... + * @param structure: XFIMAMarketStructure, reference to holds Market Strucutre ... + * @param config: XFIMAMarketStructureConfig, reference to Provide Structure Analyse Config ... + * @param barIndex: int, Specified Bar Index ... * * @return ( bool ) */ - bool AnalyseMAPivots( - XPivotAnalysis &analysis, - int barIndex = 0, - int requiredNumberOFPivots = 50, - int maxAllowedLoopbackLength = 1500, - int validationLength = 0 // + bool AnalyseMarket( + XFIMAMarketStructure &structure, + XFIMAMarketStructureConfig &config, + int barIndex = 0 // ) { // @@ -156,183 +501,930 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector // // Prepare ... - analysis.Clean(); + structure.Clean(); // - // Reading Pivots ... - XPivot pivots[]; - int count = fimaHelper.ExtractMAPivots( - pivots, // Result ... - barIndex, // Bar Index ... - requiredNumberOFPivots, // Required Number of Pivots ... - maxAllowedLoopbackLength, // Max Allowed Loopback ... - validationLength // Validation Length ... - ); - result = IsValidSize(count); + // Normalize ... + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + result = fimaParser.IsValid(); if (!result) { - // - SpecifiedClean(pivots); return result; } // - string symbol = fimaHelper.GetSymbol(); - ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); + // Do ... + int idx = -1; + XOHCL tmpBar; + datetime fromTime = NULL; + XPatternAnalysis tmpBarAnalysis; // - // Initialize Analysis ... - result = analysis.Init( - "XFIMA_XMA", - symbol, - period, - pivots // + // Initialize Indexed Bar ... + result = structure.bar.Init(symbol, period, barIndex); + + // + // Analyse Bar Patterns ... + if (result) + { + // + result = AnalyseBarPatterns( + structure.bar, + structure.barAnalysis, + config.barsAnalysisConfig // + ); + } + + // + // Analyse Pivots ... + + // + // XPV ... + CollectPVPivots( + structure.pvPivots, + barIndex, + config.requiredPivots, + config.loopback // ); // - // Cleanup Resources ... + // XMA ... + CollectMAPivots( + structure.maPivots, + barIndex, + config.requiredPivots, + config.loopback // + ); + + // + // XZG ... + CollectZGPivots( + structure.zgPivots, + barIndex, + config.requiredPivots, + config.loopback // + ); + + // + // XHK ... + CollectHKPivots( + structure.hkPivots, + barIndex, + config.requiredPivots, + config.loopback // + ); + + // + // XSAR ... + CollectSARPivots( + structure.sarPivots, + barIndex, + config.requiredPivots, + config.loopback // + ); + + // + // XPV Analysis ... + if (result && config.analysePVPivots) + { + // + result = HasChild(structure.pvPivots); + + // + // Check Oldest ... + idx = GetOldest(structure.pvPivots); + result = IsValidIndex(idx); + if (result) + { + // + fromTime = + !IsXValid(fromTime) + ? structure.pvPivots[idx].time + : MathMin(fromTime, structure.pvPivots[idx].time); + } + + // + // Initialize Analysis ... + if (result) + { + // + result = structure.pvAnalysis.Init( + ToXString(XFIMA_PIVOT_PV), + symbol, + period, + structure.pvPivots // + ); + } + } + + // + // XZG Analysis ... + if (result && config.analyseZGPivots) + { + // + result = HasChild(structure.zgPivots); + + // + // Check Oldest ... + idx = GetOldest(structure.zgPivots); + result = IsValidIndex(idx); + if (result) + { + // + fromTime = + !IsXValid(fromTime) + ? structure.zgPivots[idx].time + : MathMin(fromTime, structure.zgPivots[idx].time); + } + + // + // Initialize Analysis ... + if (result) + { + // + result = structure.zgAnalysis.Init( + ToXString(XFIMA_PIVOT_ZIGZAG), + symbol, + period, + structure.zgPivots // + ); + } + } + + // + // XHK Analysis ... + if (result && config.analyseHKPivots) + { + // + result = HasChild(structure.hkPivots); + + // + // Check Oldest ... + idx = GetOldest(structure.hkPivots); + result = IsValidIndex(idx); + if (result) + { + // + fromTime = + !IsXValid(fromTime) + ? structure.hkPivots[idx].time + : MathMin(fromTime, structure.hkPivots[idx].time); + } + + // + // Initialize Analysis ... + if (result) + { + // + result = structure.hkAnalysis.Init( + ToXString(XFIMA_PIVOT_HK_SWITCH), + symbol, + period, + structure.hkPivots // + ); + } + } + + // + // XMA Analysis ... + if (result && config.analyseMAPivots) + { + result = HasChild(structure.maPivots); + + // + // Check Oldest ... + idx = GetOldest(structure.maPivots); + result = IsValidIndex(idx); + if (result) + { + // + fromTime = + !IsXValid(fromTime) + ? structure.maPivots[idx].time + : MathMin(fromTime, structure.maPivots[idx].time); + } + + // + // Initialize Analysis ... + if (result) + { + // + result = structure.maAnalysis.Init( + ToXString(XFIMA_PIVOT_MA_CROSS), + symbol, + period, + structure.maPivots // + ); + } + } + + // + // XSAR Analysis ... + if (result && config.analyseSARPivots) + { + // + result = HasChild(structure.sarPivots); + + // + // Check Oldest ... + idx = GetOldest(structure.sarPivots); + result = IsValidIndex(idx); + if (result) + { + // + fromTime = + !IsXValid(fromTime) + ? structure.sarPivots[idx].time + : MathMin(fromTime, structure.sarPivots[idx].time); + } + + // + // Initialize Analysis ... + if (result) + { + // + result = structure.sarAnalysis.Init( + ToXString(XFIMA_PIVOT_SAR_SWITCH), + symbol, + period, + structure.sarPivots // + ); + } + } + + // + // Order Flow ... + if (result && config.detectOrderFlow) + { + // + HasOrderFlow( + structure.bar, + structure.orderFlowDir, + structure.orderFlow, + config.orderFlowValidation, + config.orderFlowUseOB, + config.orderFlowUseFVG, + config.orderFlowUseSupportAndResistance, + config.barsAnalysisConfig.supportAndResistanceLoopbackLength, + config.barsAnalysisConfig.supportAndResistanceValidationLength, + config.loopback // + ); + } + + // + // Analyse Bar Patterns ... + if (result && config.analyseBarPatterns) + { + // + // Collect Pivots ... + XPivot tmps[]; + Copy(structure.pvPivots, tmps, false); + Copy(structure.zgPivots, tmps, false); + Copy(structure.hkPivots, tmps, false); + Copy(structure.maPivots, tmps, false); + Copy(structure.sarPivots, tmps, false); + + // + XPivot sames[]; + XPivot tmpPivot; + int samesCount = 0; + while (HasChild(tmps)) + { + // + tmpPivot.Clean(); + tmpPivot = tmps[0]; + ArrayRemove(tmps, 0, 1); + + // + XClean(sames); + samesCount = ExtractSameTimePivots(tmpPivot, sames, tmps); + if (HasChild(sames)) + { + // + tmpBar.Clean(); + if (sames[0].GetBar(tmpBar)) + { + // + tmpBarAnalysis.Clean(); + if (AnalyseBarPatterns(tmpBar, tmpBarAnalysis, config.barsAnalysisConfig)) + { + // + AddRef(tmpBarAnalysis, structure.barsAnalysis); + } + } + + // + Removes(sames, tmps); + } + } + + // + // Bars Analysis Exists ... + result = HasChild(structure.barsAnalysis); + + // + // Cleanup ... + XClean(tmps); + XClean(sames); + tmpPivot.Clean(); + } + + // + // Cleanup ... if (!result) { - analysis.Clean(); + structure.Clean(); } - SpecifiedClean(pivots); + + // + return result; + } + + // + // Collectors ... + + /** + * Collect ZigZag Pivots ... + * + * @param pivots: XPivot, reference collection to holds Detected Pivots ... + * @param barIndex: int, Specified Start Bar Index ... + * @param count: int, Specified number of required Pivots ... + * @param loopback: int, Max Allowed Loopback length for Detection ... + * + * @return ( int ) + */ + int CollectZGPivots( + XPivot &pivots[], + int barIndex = 0, + int count = 50, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(pivots); + + // + // Normalize ... + count = NormalizeInt(count, 0); + loopback = NormalizeInt(loopback, 50); + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = fimaParser.IsValid(); + if (!has) + { + return result; + } + + // + // Do ... + XOHCL bar; + XPivot pivot; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + int end = start + loopback; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + for (int i = start; i < end; i++) + { + // + isBullish = fimaParser.IsZGLow(i); + isBearish = fimaParser.IsZGHigh(i); + + // + has = isBullish || isBearish; + if (has) + { + // + // Specified Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Indexed Bar ... + // Validate it, and Converts it to Pivot ... + bar.Clean(); + has = bar.Init(symbol, period, i); + has = has && + ToPivot( + bar, + pivot, + dir, + ToXString(XFIMA_PIVOT_ZIGZAG) // + ); + if (has) + { + // + // Add Detected Pivot ... + AddIfNotExists(pivot, pivots); + } + + // + has = count <= 0 + ? false + : ArraySize(pivots) >= count; + if (has) + { + break; + } + } + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); // return result; } /** - * Analyse Market based on Specified Kind of Pivots ... + * Collect MA Pivots ... * - * @param analysis: XPivotAnalysis, reference to hold result ... - * @param barIndex: int, Bar Index ... - * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... - * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param pivots: XPivot, reference collection to holds Detected Pivots ... + * @param barIndex: int, Specified Start Bar Index ... + * @param count: int, Specified number of required Pivots ... + * @param loopback: int, Max Allowed Loopback length for Detection ... * - * @return ( bool ) + * @return ( int ) */ - bool AnalyseSARPivots( - XPivotAnalysis &analysis, + int CollectMAPivots( + XPivot &pivots[], int barIndex = 0, - int requiredNumberOFPivots = 50, - int maxAllowedLoopbackLength = 1500 // + int count = 50, + int loopback = 500 // ) { // - bool result = false; + int result = 0; // // Prepare ... - analysis.Clean(); + XClean(pivots); // - // Reading Pivots ... - XPivot pivots[]; - int count = fimaHelper.ExtractSARPivots( - pivots, // Result ... - barIndex, // Bar Index ... - requiredNumberOFPivots, // Required Number of Pivots ... - maxAllowedLoopbackLength // Max Allowed Loopback ... - ); - result = IsValidSize(count); - if (!result) + // Normalize ... + count = NormalizeInt(count, 0); + loopback = NormalizeInt(loopback, 50); + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = fimaParser.IsValid(); + if (!has) { - // - SpecifiedClean(pivots); return result; } // - string symbol = fimaHelper.GetSymbol(); - ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); - - // - // Initialize Analysis ... - result = analysis.Init( - "XFIMA_XSAR", - symbol, - period, - pivots // - ); - - // - // Cleanup Resources ... - if (!result) + // Do ... + XOHCL bar; + XPivot pivot; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + int end = start + loopback; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + for (int i = start; i < end; i++) { - analysis.Clean(); + // + isBullish = fimaParser.IsMAFastCrossedOverSlow(i); + isBearish = fimaParser.IsMAFastCrossedUnderSlow(i); + + // + has = isBullish || isBearish; + if (has) + { + // + // Specified Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Indexed Bar ... + // Validate it, and Converts it to Pivot ... + bar.Clean(); + has = bar.Init(symbol, period, i); + has = has && + ToPivot( + bar, + pivot, + dir, + ToXString(XFIMA_PIVOT_MA_CROSS) // + ); + if (has) + { + // + // Replace MA Values ... + pivot.value = + isBullish + ? fimaHelper.GetMASlow(barIndex) + : fimaHelper.GetMAFast(barIndex); + + // + // Add Detected Pivot ... + AddIfNotExists(pivot, pivots); + } + + // + has = count <= 0 + ? false + : ArraySize(pivots) >= count; + if (has) + { + break; + } + } + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); } - SpecifiedClean(pivots); + + // + result = ArraySize(pivots); + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); // return result; } /** - * Analyse Market based on Specified Kind of Pivots ... + * Collect HK Pivots ... * - * @param analysis: XPivotAnalysis, reference to hold result ... - * @param barIndex: int, Bar Index ... - * @param requiredNumberOFPivots: int, Specified which Number of Pivots must be Extracted ... - * @param maxAllowedLoopbackLength: int, Specified Maximum Loopback Length for Pivot Extraction ... + * @param pivots: XPivot, reference collection to holds Detected Pivots ... + * @param barIndex: int, Specified Start Bar Index ... + * @param count: int, Specified number of required Pivots ... + * @param loopback: int, Max Allowed Loopback length for Detection ... * - * @return ( bool ) + * @return ( int ) */ - bool AnalyseZigZagPivots( - XPivotAnalysis &analysis, + int CollectHKPivots( + XPivot &pivots[], int barIndex = 0, - int requiredNumberOFPivots = 50, - int maxAllowedLoopbackLength = 1500 // + int count = 50, + int loopback = 500 // ) { // - bool result = false; + int result = 0; // // Prepare ... - analysis.Clean(); + XClean(pivots); // - // Reading Pivots ... - XPivot pivots[]; - int count = fimaHelper.ExtractZigZagPivots( - pivots, // Result ... - barIndex, // Bar Index ... - requiredNumberOFPivots, // Required Number of Pivots ... - maxAllowedLoopbackLength // Max Allowed Loopback ... - ); - result = IsValidSize(count); - if (!result) + // Normalize ... + count = NormalizeInt(count, 0); + loopback = NormalizeInt(loopback, 50); + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = fimaParser.IsValid(); + if (!has) { - // - SpecifiedClean(pivots); return result; } // - string symbol = fimaHelper.GetSymbol(); - ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); - - // - // Initialize Analysis ... - result = analysis.Init( - "XFIMA_XZG", - symbol, - period, - pivots // - ); - - // - // Cleanup Resources ... - if (!result) + // Do ... + XOHCL bar; + XPivot pivot; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + int end = start + loopback; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + for (int i = start; i < end; i++) { - analysis.Clean(); + // + isBullish = fimaParser.IsHKSwitchedToBullish(i); + isBearish = fimaParser.IsHKSwitchedToBearish(i); + + // + has = isBullish || isBearish; + if (has) + { + // + // Specified Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Indexed Bar ... + // Validate it, and Converts it to Pivot ... + bar.Clean(); + has = bar.Init(symbol, period, i); + has = has && + ToPivot( + bar, + pivot, + dir, + ToXString(XFIMA_PIVOT_HK_SWITCH) // + ); + if (has) + { + // + // Replace Value ... + pivot.value = + isBullish + ? fimaHelper.GetHKLow(i) + : fimaHelper.GetHKHigh(i); + + // + // Add Detected Pivot ... + AddIfNotExists(pivot, pivots); + } + + // + has = count <= 0 + ? false + : ArraySize(pivots) >= count; + if (has) + { + break; + } + } + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); } - SpecifiedClean(pivots); + + // + result = ArraySize(pivots); + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); // return result; } + /** + * Collect PV Pivots ... + * + * @param pivots: XPivot, reference collection to holds Detected Pivots ... + * @param barIndex: int, Specified Start Bar Index ... + * @param count: int, Specified number of required Pivots ... + * @param loopback: int, Max Allowed Loopback length for Detection ... + * + * @return ( int ) + */ + int CollectPVPivots( + XPivot &pivots[], + int barIndex = 0, + int count = 50, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(pivots); + + // + // Normalize ... + count = NormalizeInt(count, 0); + loopback = NormalizeInt(loopback, 50); + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = fimaParser.IsValid(); + if (!has) + { + return result; + } + + // + // Do ... + XOHCL bar; + XPivot pivot; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + int end = start + loopback; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + for (int i = start; i < end; i++) + { + // + isBullish = fimaParser.IsPeakOverLast(i); + isBearish = fimaParser.IsValeUnderLast(i); + + // + has = isBullish || isBearish; + if (has) + { + // + // Specified Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Indexed Bar ... + // Validate it, and Converts it to Pivot ... + bar.Clean(); + has = bar.Init(symbol, period, i); + has = has && + ToPivot( + bar, + pivot, + dir, + ToXString(XFIMA_PIVOT_PV) // + ); + if (has) + { + // + // Replace Value ... + pivot.value = + isBullish + ? fimaHelper.GetHKLow(i) + : fimaHelper.GetHKHigh(i); + + // + // Add Detected Pivot ... + AddIfNotExists(pivot, pivots); + } + + // + has = count <= 0 + ? false + : ArraySize(pivots) >= count; + if (has) + { + break; + } + } + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + + // + return result; + } + + /** + * Collect SAR Pivots ... + * + * @param pivots: XPivot, reference collection to holds Detected Pivots ... + * @param barIndex: int, Specified Start Bar Index ... + * @param count: int, Specified number of required Pivots ... + * @param loopback: int, Max Allowed Loopback length for Detection ... + * + * @return ( int ) + */ + int CollectSARPivots( + XPivot &pivots[], + int barIndex = 0, + int count = 50, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(pivots); + + // + // Normalize ... + count = NormalizeInt(count, 0); + loopback = NormalizeInt(loopback, 50); + barIndex = fimaParser.NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = fimaParser.IsValid(); + if (!has) + { + return result; + } + + // + // Do ... + XOHCL bar; + XPivot pivot; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + int end = start + loopback; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + for (int i = start; i < end; i++) + { + // + isBullish = fimaParser.IsSARSwitchedToBullish(i); + isBearish = fimaParser.IsSARSwitchedToBearish(i); + + // + has = isBullish || isBearish; + if (has) + { + // + // Specified Direction ... + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Indexed Bar ... + // Validate it, and Converts it to Pivot ... + bar.Clean(); + has = bar.Init(symbol, period, i); + has = has && + ToPivot( + bar, + pivot, + dir, + ToXString(XFIMA_PIVOT_SAR_SWITCH) // + ); + if (has) + { + // + // Add Detected Pivot ... + AddIfNotExists(pivot, pivots); + } + + // + has = count <= 0 + ? false + : ArraySize(pivots) >= count; + if (has) + { + break; + } + } + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + // Cleanup ... + bar.Clean(); + pivot.Clean(); + + // + return result; + } + + // + // Others ... + /** * Destroy ... */ @@ -341,143 +1433,15 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector // delete barAnalyser; ZeroMemory(barAnalyser); + + // + ZeroMemory(fimaHelper); + ZeroMemory(fimaParser); } // // Testers ... - /** - * Analyse Market based on Specified Bar ... - * - * @param structure: XFIMAMarketStructure, reference to holds result ... - * @param config: XFIMAMarketStructureConfig, reference to Configure Detector ... - * @param barIndex: int, Bar Index ... - */ - void AnalyseMarket( - XFIMAMarketStructure &structure, - XFIMAMarketStructureConfig &config, - int barIndex = 0 // - ) - { - // - // Prepare ... - structure.Clean(); - - // - // Normalize ... - barIndex = NormalizeInt(barIndex, 0); - - // - bool has = false; - - // - string symbol = fimaHelper.GetSymbol(); - ENUM_TIMEFRAMES period = fimaHelper.GetPeriod(); - has = structure.bar.Init( - symbol, - period, - barIndex // - ); - if (!has) - { - // - structure.Clean(); - return; - } - - // - // Reading Bar Patterns ... - XOHCL iBar; - XPatternAnalysis iPatternAnalysis; - for (int i = barIndex; i < barIndex + config.loopback; i++) - { - // - // Cleanup ... - iBar.Clean(); - iPatternAnalysis.Clean(); - - // - // Initialize Indexed Bar ... - // - has = structure.bar.BarAt(i, iBar); - if (!has) - { - break; - } - - // - // Analyse Indexed Bar ... - has = AnalyseBarPatterns(iBar, iPatternAnalysis, config.barsAnalysisConfig); - if (has) - { - // - AddRef( - iPatternAnalysis, - structure.barsAnalysis // - ); - - // - if (i == barIndex) - { - structure.barAnalysis = iPatternAnalysis; - } - } - - // - // Check Satisfied ... - has = ArraySize(structure.barsAnalysis) >= config.requiredPivots; - if (has) - { - break; - } - } - - // - // Handle Pivot Analysis ... - - // - // XPV ... - if (config.analysePVPivots) - { - // - // Reading Pivots ... - has = AnalysePVPivots( - structure.pvAnalysis, - barIndex, - config.requiredPivots, - config.loopback, - config.pvPivotsValidationLength // - ); - if (!has) - { - structure.pvAnalysis.Clean(); - } - } - - // - // XZG ... - if (config.analyseZGPivots) - { - // - // Reading Pivots ... - has = AnalyseZigZagPivots( - structure.zgAnalysis, - barIndex, - config.requiredPivots, - config.loopback // - ); - if (!has) - { - structure.zgAnalysis.Clean(); - } - } - - // - // Cleanup ... - iBar.Clean(); - iPatternAnalysis.Clean(); - } - // // Protected ... protected: diff --git a/XFIMAEA/Classes/x-saherelm.xfima.x-poi.drawer.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.x-poi.drawer.class.mq5 index c3cfb0d0..e7b785eb 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.x-poi.drawer.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.x-poi.drawer.class.mq5 @@ -702,79 +702,6 @@ class XCXFIMAPOIDrawer : public XCPOIDrawer } } - /** - * Draw Specified Market Structure Based on Given Configs ... - * - * @param structure: XFIMAMarketStructure, reference to Provide Specifid Market Structure ... - * @param config: XFIMAMarketStructureDrawerConfig, reference to Provide Drawing Configurations ... - */ - void DrawMarketStructure( - XFIMAMarketStructure &structure, - XFIMAMarketStructureDrawerConfig &config // - ) - { - // - // Validate ... - bool has = structure.IsValid(); - if (!has) - { - return; - } - - // - // PV Analysis ... - if (config.drawPVAnalysis) - { - // - has = structure.pvAnalysis.IsValid(); - if (has) - { - // - DrawPivotAnalysis( - structure.pvAnalysis, - config.pivotAnalysisDrawConfig // - ); - } - } - - // - // ZG Analysis ... - if (config.drawZGAnalysis) - { - // - has = structure.zgAnalysis.IsValid(); - if (has) - { - // - DrawPivotAnalysis( - structure.zgAnalysis, - config.pivotAnalysisDrawConfig // - ); - } - } - - // - // Bars Analysis ... - if (config.drawBarsAnalysis) - { - // - int count = ArraySize(structure.barsAnalysis); - has = IsValidSize(count); - if (has) - { - // - for (int i = 0; i < count; i++) - { - // - DrawPatternAnalysis( - structure.barsAnalysis[i], - config.barAnalysisDrawConfig // - ); - } - } - } - } - // }; diff --git a/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 b/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 index 80295457..2aca77f4 100644 --- a/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 +++ b/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 @@ -25,6 +25,7 @@ #include "../../Classes/x-saherelm.x-cobject.class.mq5" #include "../../Helpers/x-saherelm.xfima.helper.mq5" #include "../../Libraries/x-saherelm.x-pivot.analysis.lib.mq5" +#include "../Classes/x-saherelm.xfima.parser.class.mq5" // // Definitions ... @@ -40,8 +41,22 @@ struct XFIMAMarketStructure XPatternAnalysis barAnalysis; // Structure Bar Pattern Analysis ... // - XPivotAnalysis pvAnalysis; // PV Pivot Analysis Result ... - XPivotAnalysis zgAnalysis; // ZG Pivot Analysis Result ... + XBoxZone orderFlow[]; // Specified Order Flow Zones ... + ENUM_X_DIRECTION orderFlowDir; // Specified Order Flow Direction ... + + // + XPivot pvPivots[]; // XPV Pivots ... + XPivot zgPivots[]; // XZG Pivots ... + XPivot maPivots[]; // XMA Pivots ... + XPivot hkPivots[]; // XHK Pivots ... + XPivot sarPivots[]; // XSAR Pivots ... + + // + XPivotAnalysis pvAnalysis; // XPV Pivot Analysis Result ... + XPivotAnalysis zgAnalysis; // XZG Pivot Analysis Result ... + XPivotAnalysis maAnalysis; // XMA Pivot Analysis Result ... + XPivotAnalysis hkAnalysis; // XHK Pivot Analysis Result ... + XPivotAnalysis sarAnalysis; // XSAR Pivot Analysis Result ... // XPatternAnalysis barsAnalysis[]; // Anaysed Bars ... @@ -65,11 +80,27 @@ struct XFIMAMarketStructure bar.Clean(); barAnalysis.Clean(); + // + XClean(pvPivots); + XClean(zgPivots); + XClean(maPivots); + XClean(hkPivots); + XClean(sarPivots); + // pvAnalysis.Clean(); zgAnalysis.Clean(); + maAnalysis.Clean(); + hkAnalysis.Clean(); + sarAnalysis.Clean(); + + // XClean(barsAnalysis); + // + XClean(orderFlow); + orderFlowDir = X_DIRECTION_NONE; + // ZeroMemory(this); } @@ -85,31 +116,73 @@ struct XFIMAMarketStructure bool result = false; // - result = bar.IsValid() && - barAnalysis.IsValid(); + result = bar.IsValid() && + barAnalysis.IsValid(); // return result; } + // + // Checkers ... + + /** + * Check Market Strucutre Has Order Flow or not ... + * + * @return ( bool ) + */ + bool HasOrderFlow() + { + // + bool result = false; + + // + result = IsValid() && + HasChild(orderFlow) && + HasDirection(orderFlowDir); + + // + return result; + } + + /** + * Check Market Structure Has Bullish Order Flow or not ... + * + * @return ( bool ) + */ + bool HasBullishOrderFlow() + { + return HasOrderFlow() && + IsXBullish(orderFlowDir); + } + + /** + * Check Market Structure Has Bearish Order Flow or not ... + * + * @return ( bool ) + */ + bool HasBearishOrderFlow() + { + return HasOrderFlow() && + IsXBearish(orderFlowDir); + } + // // Collectors ... /** - * Collect Required Zones from Structure ... + * Collect all Pivots ... * - * @param dest: XBoxZone, reference collection to holds result ... - * @param forDir: ENUM_X_DIRECTION, Specified Collectiong ones Direction ... - * @param containsOB: bool, Contains OB Zones ... - * @param containsFVG: bool, Contains FVG Zones ... + * @param dest: XPivot, collection reference to holds result ... + * @param containsPatterns: bool, Specified to Add Pivots Bar Directionl Patterns ... + * @param forDir: ENUM_X_DIRECTION, Specified Extraction Direction ... * * @return ( int ) */ - int CollectZones( - XBoxZone &dest[], - ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, - bool containsOB = false, - bool containsFVG = false // + int CollectPivots( + XPivot &dest[], + bool containsPatterns = false, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // ) { // @@ -120,7 +193,7 @@ struct XFIMAMarketStructure XClean(dest); // - // Validate ... + // Normalize ... bool has = IsValid(); if (!has) { @@ -128,182 +201,80 @@ struct XFIMAMarketStructure } // - bool canCollectBullish = - IsXBullish(forDir) || - !HasDirection(forDir); + // Do ... // - bool canCollectBearish = - IsXBearish(forDir) || - !HasDirection(forDir); + Copy(pvPivots, dest, false); + Copy(hkPivots, dest, false); + Copy(maPivots, dest, false); + Copy(zgPivots, dest, false); + Copy(sarPivots, dest, false); // - int count = 0; - XBoxZone tmpBox; - - // - // Check Analysis ... - - // - // XPV ... - has = pvAnalysis.IsValid(); - if (has) + // Apply Direction Filtering ... + if (HasDirection(forDir)) { // - // Support ... - tmpBox.Clean(); - has = pvAnalysis.HasSupportBox(tmpBox); - if (has && canCollectBullish) - { - // - AddIfNotExists( - tmpBox, - dest // - ); - } - - // - // Resistance ... - tmpBox.Clean(); - has = pvAnalysis.HasResistanceBox(tmpBox); - if (has && canCollectBearish) - { - // - AddIfNotExists( - tmpBox, - dest // - ); - } + XPivot tmps[]; + ExtractByDirection( + tmps, + dest, + forDir // + ); + XClean(dest); + Copy(tmps, dest); + XClean(tmps); } // - // XZG ... - has = zgAnalysis.IsValid(); - if (has) + // Contains Pattern Pivots ... + if (containsPatterns && HasChild(dest) && HasChild(barsAnalysis)) { // - // Support ... - tmpBox.Clean(); - has = zgAnalysis.HasSupportBox(tmpBox); - if (has && canCollectBullish) - { - // - AddIfNotExists( - tmpBox, - dest // - ); - } + XPivot tmp; + int idx = -1; + XPivot tmps[]; + XPivot sames[]; + XPivot patterns[]; + Copy(dest, tmps); + XClean(dest); // - // Resistance ... - tmpBox.Clean(); - has = zgAnalysis.HasResistanceBox(tmpBox); - if (has && canCollectBearish) + while (HasChild(tmps)) { // - AddIfNotExists( - tmpBox, - dest // - ); - } - } - - // - // Bar Patterns ... - has = HasChild(barsAnalysis); - if (has) - { - // - count = ArraySize(barsAnalysis); - for (int i = 0; i < count; i++) - { - // - // Support ... - has = barsAnalysis[i].IsSupport(); - if (has && canCollectBullish) - { - // - AddIfNotExists( - barsAnalysis[i].support, - dest // - ); - } + tmp.Clean(); + tmp = tmps[0]; + ArrayRemove(tmps, 0, 1); // - // Resistance ... - has = barsAnalysis[i].IsResistance(); - if (has && canCollectBearish) + XClean(sames); + ExtractSameTimePivots(tmp, sames, tmps); + if (HasChild(sames)) { // - AddIfNotExists( - barsAnalysis[i].resistance, - dest // - ); - } - - // - // OB ... - if (containsOB) - { - // - has = barsAnalysis[i].IsOB(); + has = FindByTime(idx, tmp.time, barsAnalysis); if (has) { // - has = (canCollectBullish && barsAnalysis[i].ob.IsBullish()) || - (canCollectBearish && barsAnalysis[i].ob.IsBearish()); - if (has) - { - // - AddIfNotExists( - barsAnalysis[i].ob, - dest // - ); - } + barsAnalysis[idx].GetPatterns(patterns, sames[0].dir); + Copy(patterns, dest, false); } - } - // - // FVG ... - if (containsFVG) - { - has = barsAnalysis[i].IsFVG(); - if (has) - { - // - has = (canCollectBullish && barsAnalysis[i].fvg.IsBullish()) || - (canCollectBearish && barsAnalysis[i].fvg.IsBearish()); - if (has) - { - // - AddIfNotExists( - barsAnalysis[i].fvg, - dest // - ); - } - } + // + Copy(sames, dest, false); + Removes(sames, tmps); } } + + // + XClean(tmps); + XClean(sames); + XClean(patterns); } // result = ArraySize(dest); - has = IsValidSize(result); - if (has) - { - // - // Update To Time ... - // and also we Can Validate Zones Here ... - datetime cTime = TimeCurrent(); - for (int i = 0; i < result; i++) - { - dest[i].to = cTime; - } - } - - // - // Cleanup ... - tmpBox.Clean(); // return result; @@ -312,6 +283,9 @@ struct XFIMAMarketStructure // }; +/** + * Configure How to Detect Market Structure ... + **/ struct XFIMAMarketStructureConfig { // @@ -321,12 +295,18 @@ struct XFIMAMarketStructureConfig // Detector Flags ... // - bool analysePVPivots; // Analyse PV Pivots ... - bool analyseZGPivots; // Analyse ZG Pivots ... + bool analysePVPivots; // Analyse PV Pivots ... + bool analyseZGPivots; // Analyse ZG Pivots ... + bool analyseHKPivots; // Analyse HK Pivots ... + bool analyseMAPivots; // Analyse MA Pivots ... + bool analyseSARPivots; // Analyse SAR Pivots ... // bool analyseBarPatterns; // Analyse Bar Patterns ... + // + bool detectOrderFlow; // Detect Order Flow ... + // // Detector Configs ... @@ -335,8 +315,10 @@ struct XFIMAMarketStructureConfig int requiredPivots; // Required Extracted Pivots for Analysis ... // - int pvPivotsValidationLength; // PV Pivots Validation Length ... - double maCrossValidationDiffMultiplier; // a Point Distance to Validate MA Crosses ... + int orderFlowValidation; // Order Flow Sequential Validation ... + bool orderFlowUseOB; // Order Flow Use Order Blocks ... + bool orderFlowUseFVG; // Order Flow Use Fair Value Gaps ... + bool orderFlowUseSupportAndResistance; // Order Flow Use Support and Resistance (s) ... // XPatternAnalysisConfig barsAnalysisConfig; // Bars Analyser Config ... @@ -358,16 +340,24 @@ struct XFIMAMarketStructureConfig { // // Detector Flags ... + detectOrderFlow = false; analysePVPivots = false; analyseZGPivots = false; + analyseHKPivots = false; + analyseMAPivots = false; + analyseSARPivots = false; analyseBarPatterns = false; // // Configure Detectors ... loopback = 0; requiredPivots = 0; - pvPivotsValidationLength = 0; - maCrossValidationDiffMultiplier = 0; + + // + orderFlowValidation = 0; + orderFlowUseOB = false; + orderFlowUseFVG = false; + orderFlowUseSupportAndResistance = false; // barsAnalysisConfig.Clean(); @@ -383,20 +373,32 @@ struct XFIMAMarketStructureConfig { // // Detector Flags ... + detectOrderFlow = true; analysePVPivots = true; analyseZGPivots = true; + analyseHKPivots = true; + analyseMAPivots = true; + analyseSARPivots = true; analyseBarPatterns = true; // // Configure Detectors ... loopback = 200; requiredPivots = 10; - pvPivotsValidationLength = 5; - maCrossValidationDiffMultiplier = 4; + + // + orderFlowValidation = 2; + orderFlowUseOB = false; + orderFlowUseFVG = true; + orderFlowUseSupportAndResistance = false; // barsAnalysisConfig.Default(); barsAnalysisConfig.FullPattern(); + + // + barsAnalysisConfig.supportAndResistanceLoopbackLength = 5; + barsAnalysisConfig.supportAndResistanceValidationLength = 11; } /** @@ -406,8 +408,12 @@ struct XFIMAMarketStructureConfig { // // Detector Flags ... + detectOrderFlow = false; analysePVPivots = false; analyseZGPivots = false; + analyseHKPivots = false; + analyseMAPivots = false; + analyseSARPivots = false; analyseBarPatterns = false; } @@ -418,8 +424,12 @@ struct XFIMAMarketStructureConfig { // // Detector Flags ... + detectOrderFlow = true; analysePVPivots = true; analyseZGPivots = true; + analyseHKPivots = true; + analyseMAPivots = true; + analyseSARPivots = true; analyseBarPatterns = true; } @@ -437,6 +447,9 @@ struct XFIMAMarketStructureDrawerConfig // bool drawPVAnalysis; bool drawZGAnalysis; + bool drawMAAnalysis; + bool drawHKAnalysis; + bool drawSARAnalysis; bool drawBarsAnalysis; // @@ -465,6 +478,9 @@ struct XFIMAMarketStructureDrawerConfig // drawPVAnalysis = false; drawZGAnalysis = false; + drawMAAnalysis = false; + drawHKAnalysis = false; + drawSARAnalysis = false; drawBarsAnalysis = false; // @@ -488,6 +504,9 @@ struct XFIMAMarketStructureDrawerConfig // drawPVAnalysis = true; drawZGAnalysis = true; + drawMAAnalysis = true; + drawHKAnalysis = true; + drawSARAnalysis = true; drawBarsAnalysis = true; // @@ -518,6 +537,9 @@ struct XFIMAMarketStructureDrawerConfig // drawPVAnalysis = false; drawZGAnalysis = false; + drawMAAnalysis = false; + drawHKAnalysis = false; + drawSARAnalysis = false; drawBarsAnalysis = false; // @@ -535,9 +557,12 @@ struct XFIMAMarketStructureDrawerConfig // Drawing Flags ... // - drawPVAnalysis = false; - drawZGAnalysis = false; - drawBarsAnalysis = false; + drawPVAnalysis = true; + drawZGAnalysis = true; + drawMAAnalysis = true; + drawHKAnalysis = true; + drawSARAnalysis = true; + drawBarsAnalysis = true; // // Drawing Configs ...