From a03613f4cd141bd273e01fde497fefb4685f0bb8 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 6 Oct 2025 14:39:44 +0330 Subject: [PATCH] last works on Peak and Vales ... --- Classes/x-saherelm.x-market.pattern.class.mq5 | 492 +++++- Documents/BKP/signaller.xfima.drawing.tmp.mq5 | 208 +++ Helpers/x-saherelm.xfima.helper.mq5 | 8 +- Libraries/x-saherelm.x-ohcl.lib.mq5 | 605 +++++++ Libraries/x-saherelm.x-pivot.analysis.lib.mq5 | 998 ++++++++++++ Libraries/x-saherelm.x-poi.extensions.lib.mq5 | 1409 ++++++++++------- Libraries/x-saherelm.x-poi.lib.mq5 | 22 +- .../x-saherelm.xfima.signaller.class.mq5 | 829 +++++++--- .../x-saherelm.xfima.x-poi.detector.class.mq5 | 4 +- 9 files changed, 3806 insertions(+), 769 deletions(-) create mode 100644 Documents/BKP/signaller.xfima.drawing.tmp.mq5 diff --git a/Classes/x-saherelm.x-market.pattern.class.mq5 b/Classes/x-saherelm.x-market.pattern.class.mq5 index 60d9b135..73a27ce0 100644 --- a/Classes/x-saherelm.x-market.pattern.class.mq5 +++ b/Classes/x-saherelm.x-market.pattern.class.mq5 @@ -24,6 +24,7 @@ #include "../Classes/x-saherelm.base.class.mq5" #include "../Classes/x-saherelm.x-bar.analyser.class.mq5" #include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-pivot.analysis.lib.mq5" #include "../Libraries/x-saherelm.x-poi.lib.mq5" // @@ -715,7 +716,7 @@ class XCMarketPatternDetector : public XCBase * * @return ( bool ) */ - bool IsStartPattern( + bool IsStarPattern( XOHCL &bar, ENUM_X_DIRECTION &dir // ) @@ -1074,7 +1075,6 @@ class XCMarketPatternDetector : public XCBase * @param dir: ENUM_X_DIRECTION a reference for Direction ... * @param swingBar: XOHCL, Detected Swing Bar ... * @param minimumPullbackBars: int, Minimum Shoulders of Swing Bar ... - * @param minimumPullbackBars: int, Minimum Shoulders of Swing Bar ... * * @return ( bool ) */ @@ -1967,6 +1967,494 @@ class XCMarketPatternDetector : public XCBase return result; } + // + // Analysers ... + + /** + * Analyse Specified Bar ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param analysis: XPatternAnalysis, reference to holds Analysis result ... + * @param pvValidationLength: int, Validation Length for Peak and Vale Detection ... + * @param peakPriceType: ENUM_X_PRICE, Specified Price for Peak (High) Detection ... + * @param valePriceType: ENUM_X_PRICE, Specified Price for Vale (Low) Detection ... + * @param momentumBarValidationLength: int, bar range for approve Momentum ... + * @param momentumBarApprovedMultiplier: double, a Multipler for approve Momentum ... + * @param trueGapApprovedStrength: double, Gap Validation Multiplier in Point ... + * @param pinBarShadowApprovedMultiplier: double, PinBar Shadow Size Approve Multiplier ... + * @param pinBarRangeMultiplier: doubble, PinBar Range Size Approve Multiplier in Point ... + * @param pinBarForceDirection: bool, PinBar Apply Force Bar Type ... + * @param flagPatternPullbackLength: int, Minimum Shoulders of FlagPattern's Swing Bar ... + * @param fvgForceType: bool, Force FVG to Have Same type Bars ... + * @param obForceTwoBar: bool, Force OB to has atleast two indirectional Bars ... + * @param supportAndResistanceValidationLength: int, Support and Resistance Validation Length ... + * @param supportAndResistanceLoopbackLength: int, Support and Resistance Detection Loopback ... + * + * @return ( bool ) + */ + bool AnalyseBarPatterns( + XOHCL &bar, + XPatternAnalysis &analysis, + // + // PV ... + int pvValidationLength = 7, + ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE valePriceType = X_PRICE_LOW, + // + // Momentum ... + int momentumBarValidationLength = 3, + double momentumBarApprovedMultiplier = 3, + // + // TrueGap ... + double trueGapApprovedStrength = 2, + // + // Pin ... + double pinBarShadowApprovedMultiplier = 3, + double pinBarRangeMultiplier = 4, + bool pinBarForceDirection = false, + // + // Flag ... + int flagPatternPullbackLength = 3, + // + // FVG ... + bool fvgForceType = false, + // + // OB ... + bool obForceTwoBar = false, + // + // Support and Resistance ... + int supportAndResistanceValidationLength = 21, + int supportAndResistanceLoopbackLength = 50 // + ) + { + // + bool result = false; + + // + // Prepare ... + analysis.Clean(); + + // + // Normalize ... + // + pvValidationLength = NormalizeInt(pvValidationLength, 2); + + // + momentumBarValidationLength = NormalizeInt(momentumBarValidationLength, 2); + momentumBarApprovedMultiplier = NormalizeDouble(momentumBarApprovedMultiplier, 1); + + // + trueGapApprovedStrength = NormalizeDouble(trueGapApprovedStrength, 1); + + // + pinBarRangeMultiplier = NormalizeDouble(pinBarRangeMultiplier, 4); + pinBarShadowApprovedMultiplier = NormalizeDouble(pinBarShadowApprovedMultiplier, 3); + + // + flagPatternPullbackLength = NormalizeInt(flagPatternPullbackLength, 3); + + // + supportAndResistanceLoopbackLength = NormalizeInt(supportAndResistanceLoopbackLength, 10); + supportAndResistanceValidationLength = NormalizeInt(supportAndResistanceValidationLength, 10); + + // + // 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; + + // + // Bars Detectors ... + + // + // XPV High Low Detection ... + bool isPV = IsPV( + bar, + iDir, + pvValidationLength, + peakPriceType, + valePriceType // + ); + bool isHigh = isPV && + IsXBearish(iDir); + bool isLow = isPV && + IsXBullish(iDir); + if (isPV) + { + // + iPattern = + isHigh + ? X_BAR_PATTERN_HIGH + : X_BAR_PATTERN_LOW; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + + // + // Momentum ... + bool isMomentum = IsMomentumBar( + bar, + iDir, + momentumBarValidationLength, + momentumBarApprovedMultiplier // + ); + bool isBullishMomentum = isMomentum && + IsXBullish(iDir); + bool isBearishMomentum = isMomentum && + IsXBearish(iDir); + if (isMomentum) + { + // + iPattern = X_BAR_PATTERN_MOMENTUM; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + + // + // Engulfed ... + bool isEngulfed = IsEngulfedBar( + bar, + iDir // + ); + bool isBullishEngulfed = isEngulfed && + IsXBullish(iDir); + bool isBearishEngulfed = isEngulfed && + IsXBearish(iDir); + if (isEngulfed) + { + // + iPattern = X_BAR_PATTERN_ENGULFED; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + + // + // TrueGap ... + bool isTrueGaped = IsTrueGapedBar( + bar, + iDir, + trueGapApprovedStrength // + ); + bool isBullishTrueGaped = isTrueGaped && + IsXBullish(iDir); + bool isBearishTrueGaped = isTrueGaped && + IsXBearish(iDir); + if (isTrueGaped) + { + // + iPattern = X_BAR_PATTERN_TRUE_GAPED; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + + // + // Pinned ... + bool isPinned = IsPinnedBar( + bar, + iDir, + pinBarShadowApprovedMultiplier, + pinBarRangeMultiplier, + pinBarForceDirection // + ); + bool isBullishPinned = isPinned && + IsXBullish(iDir); + bool isBearishPinned = isPinned && + IsXBearish(iDir); + if (isPinned) + { + // + iPattern = X_BAR_PATTERN_PINNED; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + + // + // Pattern Detectors ... + + // + // Star ... + bool isStar = IsStarPattern( + bar, + iDir // + ); + bool isBullishStar = isStar && + IsXBullish(iDir); + bool isBearishStar = isStar && + IsXBearish(iDir); + if (isStar) + { + // + iPattern = X_BAR_PATTERN_STAR; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + + // + // Piercing ... + bool isPiercing = IsPiercingPattern( + bar, + iDir // + ); + bool isBullishPiercing = isPiercing && + IsXBullish(iDir); + bool isBearishPiercing = isPiercing && + IsXBearish(iDir); + if (isPiercing) + { + // + iPattern = X_BAR_PATTERN_PIERCING; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + + // + // Rising ... + bool isRising = IsRisingPattern( + bar, + iDir // + ); + bool isBullishRising = isRising && + IsXBullish(iDir); + bool isBearishRising = isRising && + IsXBearish(iDir); + if (isRising) + { + // + iPattern = X_BAR_PATTERN_RISING; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + + // + // Flag ... + bool isFlag = IsFlagPattern( + bar, + iDir, + iSwing, + flagPatternPullbackLength // + ); + bool isBullishFlag = isFlag && + IsXBullish(iDir); + bool isBearishFlag = isFlag && + IsXBearish(iDir); + if (isFlag) + { + // + iPattern = X_BAR_PATTERN_FLAG; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + + // + analysis.flagSwing = iSwing; + } + + // + // SignalKey ... + bool isSignalKey = IsSignalKeyBarPattern( + bar, + iDir, + pinBarShadowApprovedMultiplier, + pinBarRangeMultiplier, + pinBarForceDirection // + ); + bool isBullishSignalKey = isSignalKey && + IsXBullish(iDir); + bool isBearishSignalKey = isSignalKey && + IsXBearish(iDir); + if (isSignalKey) + { + // + iPattern = X_BAR_PATTERN_SIGNALKEY; + + // + analysis.AddPattern( + iPattern, + iDir // + ); + } + + // + // Zone Detectors ... + + // + // OB ... + bool isOB = barAnalyser.IsOB( + bar, + iZone, + fvgForceType, + obForceTwoBar // + ); + bool isBullishOB = isOB && + iZone.IsBullish(); + bool isBearishOB = isOB && + iZone.IsBearish(); + if (isOB) + { + // + iPattern = X_BAR_PATTERN_OB; + + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.ob = iZone; + } + + // + // FVG ... + bool isFVG = barAnalyser.IsFVG( + bar, + iZone, + fvgForceType // + ); + bool isBullishFVG = isFVG && + iZone.IsBullish(); + bool isBearishFVG = isFVG && + iZone.IsBearish(); + if (isFVG) + { + // + iPattern = X_BAR_PATTERN_FVG; + + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.fvg = iZone; + } + + // + // Support ... + bool isSupport = HasSupport( + bar, + iSwing, + supportAndResistanceValidationLength, + supportAndResistanceLoopbackLength // + ); + if (isSupport) + { + // + iPattern = X_BAR_PATTERN_SUPPORT; + + // + bool has = ToSupportBox( + iSwing, + iZone, + bar.time // + ); + if (has) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.support = iZone; + } + } + + // + // Resistance ... + bool isResistance = HasResistance( + bar, + iSwing, + supportAndResistanceValidationLength, + supportAndResistanceLoopbackLength // + ); + if (isMomentum) + { + // + iPattern = X_BAR_PATTERN_RESISTANCE; + + // + bool has = ToResistanceBox( + iSwing, + iZone, + bar.time // + ); + if (has) + { + // + analysis.AddPattern( + iPattern, + iZone.dir // + ); + + // + analysis.resistance = iZone; + } + } + + // + // Validate Analysis ... + result = analysis.IsValid(); + + // + // Cleanup Resources ... + iZone.Clean(); + iSwing.Clean(); + CleanDirection(iDir); + + // + return result; + } + // // Protected ... protected: diff --git a/Documents/BKP/signaller.xfima.drawing.tmp.mq5 b/Documents/BKP/signaller.xfima.drawing.tmp.mq5 new file mode 100644 index 00000000..d63e9a02 --- /dev/null +++ b/Documents/BKP/signaller.xfima.drawing.tmp.mq5 @@ -0,0 +1,208 @@ + +// +// Draw Market Analysis ... +// has = iStructure.pvAnalysis.IsValid(); +// if (has) +// { +// // +// XBoxZone iBox; +// XCBoxObject *iBoxObj; + +// +// poiDrawer.RemoveDraws(); + +// // +// has = iStructure.pvAnalysis.HasSupportBox(iBox); +// if (has) +// { +// // +// iBox.to = iBar.time; +// poiDrawer.DrawBox( +// iBox, +// iBoxObj, +// true, +// iBox.type // +// ); +// } + +// // +// ZeroMemory(iBoxObj); +// has = iStructure.pvAnalysis.HasResistanceBox(iBox); +// if (has) +// { +// // +// iBox.to = iBar.time; +// poiDrawer.DrawBox( +// iBox, +// iBoxObj, +// true, +// iBox.type // +// ); +// } +// } + +// // +// // Draw Zones ... +// has = HasChild(iStructure.supports); +// if (has) { +// // +// CArrayObj *iSupportObjs; +// poiDrawer.DrawBoxes( +// iStructure.supports, +// iSupportObjs, +// true // +// ); +// } + +// // +// has = HasChild(iStructure.resistances); +// if (has) { +// // +// CArrayObj *iResistanceObjs; +// poiDrawer.DrawBoxes( +// iStructure.resistances, +// iResistanceObjs, +// true // +// ); +// } + +// +// Detecte Fibo Section Changes ... + +// // +// has = fimaHelper.IsFiboSectionChanged(iDir, iBar.Index()); +// has = has && +// IsXBullish(iDir) && +// fimaHelper.IsValeOverLast(iBar.Index()); + +// // +// has = fimaHelper.IsFiboSectionChanged(iDir, iBar.Index()); +// has = has && +// IsXBearish(iDir) && +// fimaHelper.IsPeakUnderLast(iBar.Index()); + +// // +// has = fimaHelper.HasFiboPush(iDir, iBar.Index(), 5); + +// // +// XBoxZone fimaZones[]; +// int fimaZonesCount = fimaHelper.DetectXFIMAZones( +// fimaZones, +// iBar.Index(), +// true, // Only Valid Zones ... +// 50, // Number of Zones ... +// 4, // Shadow Multiplier ... +// 1, // Strength ... +// 7, // Validation Length ... +// 500 // Loopback .. +// ); + +// +// XPivot fimaPivots[]; +// int fimaPivotsCount = fimaHelper.DetecteXFIMAPivots( +// fimaPivots, +// iBar.Index(), +// 50, // Number of Pivots ... +// 7, // Validation Length ... +// 500 // Loopback ... +// ); + +// // +// has = IsValidSize(fimaZonesCount); +// if (has) +// { +// // +// // Draw Detected Zones ... +// for (int i = 0; i < fimaZonesCount; i++) +// { +// // +// XCBoxObject *iObj; +// has = poiDrawer.DrawBox( +// fimaZones[i], +// iObj, +// true, // Ignore At ... +// fimaZones[i].type // Specified Name ... +// ); +// if (has) +// { +// zoneObjects.Add(iObj); +// } +// } +// } + +// // +// has = IsValidSize(fimaPivotsCount); +// if (has) +// { +// // +// // Draw Detected Pivots ... +// for (int i = 0; i < fimaPivotsCount; i++) +// { +// // +// XCBarArrowObject *iObj; +// has = poiDrawer.DrawPivot( +// fimaPivots[i], +// iObj); +// if (has) +// { +// pivotObjects.Add(iObj); +// } +// } +// } + +// +// Detect DecisionBars ... +// XOHCL decisionBars[]; +// int decisionBarsCount = 0; +// ENUM_X_DIRECTION decisionBarDirs[]; +// decisionBarsCount = fimaHelper.DetectXFIMAPOIBars( +// decisionBars, +// decisionBarDirs, +// iBar.Index(), +// X_DIRECTION_ALL, // For Dir ... +// 300 // Required Number of Bars ... +// ); +// decisionBarsCount = fimaHelper.DetectXFIMAReversalPOIBars( +// decisionBars, +// decisionBarDirs, +// iBar.Index(), +// true, // Force Touch Boundary ... +// X_DIRECTION_ALL, // For Dir ... +// 300 // Required Number of Bars ... +// ); +// decisionBarsCount = fimaHelper.DetectXFIMAContinuationalPOIBars( +// decisionBars, +// decisionBarDirs, +// iBar.Index(), +// true, +// X_DIRECTION_ALL, // For Dir ... +// 300 // Required Number of Bars ... +// ); + +// // +// has = IsValidSize(decisionBarsCount); +// if (has) +// { +// // +// for (int i = 0; i < decisionBarsCount; i++) +// { +// // +// XCBarArrowObject *iObj; +// has = poiDrawer.DrawBarArrow( +// decisionBars[i], +// iObj, +// IsXBullish(decisionBarDirs[i]) ? X_PRICE_LOW : X_PRICE_HIGH, +// 159, +// IsXBullish(decisionBarDirs[i]) ? clrAqua : clrMagenta, +// 5, +// IsXBullish(decisionBarDirs[i]) ? ANCHOR_TOP : ANCHOR_BOTTOM, +// "XOHCL_" + ToXString(TimeToSeconds(decisionBars[i].time)), +// true, // Ignore Bar Tag ... +// 5 // Threshold ... +// ); +// if (has) +// { +// barObjects.Add(iObj); +// } +// } +// } diff --git a/Helpers/x-saherelm.xfima.helper.mq5 b/Helpers/x-saherelm.xfima.helper.mq5 index 6f9bf09e..102a4976 100644 --- a/Helpers/x-saherelm.xfima.helper.mq5 +++ b/Helpers/x-saherelm.xfima.helper.mq5 @@ -3632,7 +3632,7 @@ class XCXFIMAHelper : public XCBaseHelper // // Star Pattern ... - bool isStarPattern = patternDetector.IsStartPattern( + bool isStarPattern = patternDetector.IsStarPattern( iBar, iDir // ); @@ -4317,12 +4317,6 @@ class XCXFIMAHelper : public XCBaseHelper return result; } - int DetectXFIMAPOIBarPatterns( - XOHCL &bars[], - XOHCL &dirs[], - int barIndex = 0, - ) - // // Values Retrievers ... diff --git a/Libraries/x-saherelm.x-ohcl.lib.mq5 b/Libraries/x-saherelm.x-ohcl.lib.mq5 index a3477d42..88730407 100644 --- a/Libraries/x-saherelm.x-ohcl.lib.mq5 +++ b/Libraries/x-saherelm.x-ohcl.lib.mq5 @@ -2441,4 +2441,609 @@ int GetBars( ); } +/** + * Remove Specified Item from a Collection ... + * + * @param item: Specified Item ... + * @param source: Specified Collection for Remove item from it ... + * + * @return ( bool ) + */ +bool Remove( + XOHCL &item, + XOHCL &source[] // +) +{ + // + bool result = false; + + // + result = + item.IsValid() && + HasChild(source); + if (!result) + { + return result; + } + + // + int idx = -1; + result = FindIndex( + idx, + item, + source // + ); + if (!result) + { + return result; + } + + // + result = ArrayRemove( + source, + idx, + 1 // + ); + + // + return result; +} + +/** + * Remove Specified items from a Collection ... + * + * @param items: Specified Items to Remove ... + * @param sources: Sepcified Collection for Removing items from it ... + * + * @return ( int ) + */ +int Removes( + XOHCL &items[], + XOHCL &sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items) && + HasChild(sources); + if (!has) + { + return result; + } + + // + int idx = -1; + has = false; + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + // Detect Item Index in Collection ... + has = FindIndex( + idx, + items[i], + sources // + ); + if (has) + { + // + // Remove Detected Index from Collection ... + has = ArrayRemove( + sources, + idx, + 1 // + ); + + // + if (has) + { + // + // Count Removed Items ... + result++; + } + } + } + + // + return result; +} + +/** + * Find Specified Item index in a Collection ... + * + * @param index: int, reference to Hold Index if Exists ... + * @param item: Specified item to Detect ... + * @param source: Collection to Search for item ... + * + * @return ( bool ) + */ +bool FindIndex( + int &index, + XOHCL &item, + XOHCL &source[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + int count = ArraySize(source); + result = item.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isSame = item.IsSameAs(source[i]); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Add Specified Item to Specified Collection, if not Exists ... + * + * @param item: Item to Add ... + * @param sources: Collection to Add item ... + * @param maxAllowed: int, Max Allowed Collection Size ... + * + * @return ( bool ) + */ +bool AddIfNotExists( + XOHCL &item, + XOHCL &sources[], + int maxAllowed = 0 // +) +{ + // + bool result = false; + + // + // Validate Args ... + result = item.IsValid(); + if (!result) + { + return result; + } + + // + // Check Item Exists or not ... + int idx = -1; + bool isExists = FindIndex( + idx, + item, + sources // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + AddRef( + item, + sources // + ); + + // + // Handle Cleanup Collection + // if Max Reached ... + if (result && + maxAllowed > 0) + { + // + CleanupArray( + sources, + maxAllowed // + ); + } + + // + return result; +} + +/** + * Get Oldest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetOldest( + XOHCL &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL selected; + for (int i = 0; i < count; i++) + { + // + bool canSet = + !selected.IsValid() + ? true + : selected.time > source[i].time; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetYoungest( + XOHCL &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL selected; + for (int i = 0; i < count; i++) + { + // + bool canSet = + !selected.IsValid() + ? true + : selected.time < source[i].time; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetLowest( + XOHCL &source[], + ENUM_X_PRICE _priceType = X_PRICE_LOW // +) +{ + // + int result = -1; + + // + if (!IsXValid(_priceType)) + { + _priceType = X_PRICE_LOW; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL selected; + double iPrice = EMPTY_VALUE; + double selectedPrice = EMPTY_VALUE; + for (int i = 0; i < count; i++) + { + // + iPrice = source[i].GetPrice(_priceType); + selectedPrice = selected.GetPrice(_priceType); + + // + bool canSet = + !selected.IsValid() + ? true + : selectedPrice > iPrice; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * @param _priceType: Specified Price type ... + * + * @return ( int ) + */ +int GetHighest( + XOHCL &source[], + ENUM_X_PRICE _priceType = X_PRICE_HIGH // +) +{ + // + int result = -1; + + // + if (!IsXValid(_priceType)) + { + _priceType = X_PRICE_HIGH; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL selected; + double iPrice = EMPTY_VALUE; + double selectedPrice = EMPTY_VALUE; + for (int i = 0; i < count; i++) + { + // + iPrice = source[i].GetPrice(_priceType); + selectedPrice = selected.GetPrice(_priceType); + + // + bool canSet = + !selected.IsValid() + ? true + : selectedPrice < iPrice; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Nearest Directional Bar ... + * + * @param bar: XOHCL, reference to Specified Start Bar ... + * @param directionalBar: XOHCL, reference to hold Detected Bar ... + * @param forDir: ENUM_X_DIRECTION, Specified Which Directional Bar looking for ... + * @param loopback: int, Loopback Length ... + * + * @return ( bool ) + */ +bool GetDirectionalBar( + XOHCL &bar, + XOHCL &directionalBar, + ENUM_X_DIRECTION forDir, + int loopback = 1500 // +) +{ + // + bool result = false; + + // + // Prepare ... + directionalBar.Clean(); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + + // + // Validate ... + result = bar.IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + int start = bar.Index() + 1; + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + directionalBar.Clean(); + result = bar.BarAt(i, directionalBar); + result = result && + directionalBar.GetDirection() == forDir; + if (result) + { + break; + } + + // + directionalBar.Clean(); + } + + // + result = directionalBar.IsValid() && + forDir == directionalBar.GetDirection(); + + // + // Cleanup Resources ... + if (!result) + { + directionalBar.Clean(); + } + + // + return result; +} + +/** + * Get Nearest Breaker Bar of Specified Bar's Price ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param breaker: XOHCL, reference to hold Detected Breaker Bar ... + * @param priceType: ENUM_X_PRICE, which price type of Bar to Check to Break ... + * @param breakType: ENUM_X_PRICE, which price of Breaker Bar must Breke price ... + * @param breakDir: ENUM_X_DIRECTION, Specified Break Direction ... + * @param loopback: int, Max Allowed Loopback to Detect Breaker Bar ... + * + * @return ( bool ) + */ +bool GetBreakerBar( + XOHCL &bar, + XOHCL &breaker, + ENUM_X_PRICE priceType, + ENUM_X_PRICE breakType, + ENUM_X_DIRECTION breakDir, + int loopback = 1500 // +) +{ + // + // PriceType: which Applied Price of Specified Bar must to Check for Break ... + + // + // BreakType: which Applied Price of breakerBar must Break price ... + + // + // BreakDir: + // ----------- + // Bullish: Price Must Break Applied Price from Down to Top ... + // Bearish: Price must Break Applied Price from Top to Down ... + + // + bool result = false; + + // + // Prepare ... + breaker.Clean(); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 1); + + // + // Validate ... + result = bar.IsValid() && + IsXValid(priceType) && + IsXValid(breakType) && + HasDirection(breakDir); + if (!result) + { + return result; + } + + // + double iPrice = EMPTY_VALUE; + bool isBullish = IsXBullish(breakDir); + double price = bar.GetPrice(priceType); + + // + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + breaker.Clean(); + iPrice = EMPTY_VALUE; + + // + // Initialize Indexed Bar ... + result = bar.BarAt(i, breaker); + if (!result) + { + breaker.Clean(); + break; + } + + // + // Check Breake ... + iPrice = breaker.GetPrice(breakType); + result = + isBullish + ? iPrice > price + : iPrice < price; + if (result) + { + break; + } + } + + // + result = breaker.IsValid(); + + // + // Cleanup Resources ... + if (!result) + { + breaker.Clean(); + } + + // + return result; +} + // \ No newline at end of file diff --git a/Libraries/x-saherelm.x-pivot.analysis.lib.mq5 b/Libraries/x-saherelm.x-pivot.analysis.lib.mq5 index 59a24cd7..f3724b0b 100644 --- a/Libraries/x-saherelm.x-pivot.analysis.lib.mq5 +++ b/Libraries/x-saherelm.x-pivot.analysis.lib.mq5 @@ -1283,4 +1283,1002 @@ struct XPivotAnalysis // }; +/** + * a Model to Describe Specified Bar Pattern's Analysis ... + **/ +struct XPatternAnalysis +{ + // + // Props ... + XOHCL bar; // Specified Bar ... + XBoxZone ob; // OrderBlock if Exists ... + XBoxZone fvg; // Fair Value Gap if Exists ... + datetime time; // Analysis Time ... + XOHCL flagSwing; // Flag Patterns Swing Bar if Exists ... + XBoxZone support; // Bar's Support if Exists ... + XBoxZone resistance; // Bar's Resistance if Exists ... + ENUM_X_BAR_PATTERN patterns[]; // All Bars Exists Patterns ... + ENUM_X_DIRECTION patternsDir[]; // Each Exists Patterns Directions ... + + // + // Constructor ... + XPatternAnalysis() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + ob.Clean(); + bar.Clean(); + fvg.Clean(); + time = NULL; + support.Clean(); + XClean(patterns); + flagSwing.Clean(); + resistance.Clean(); + XClean(patternsDir); + + // + ZeroMemory(this); + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = bar.IsValid() && + IsXValid(time); + + // + return result; + } + + // + int Count( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + int result = 0; + + // + // Validate ... + bool has = IsValid() && + HasChild(patternsDir); + if (!has) + { + return result; + } + + // + int count = ArraySize(patternsDir); + if (!HasDirection(forDir)) + { + // + result = count; + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + has = forDir = patternsDir[i]; + if (has) + { + result++; + } + } + + // + return result; + } + + // + // Detectors ... + + bool IsHigh() + { + // + bool result = false; + + // + result = HasPattern(X_BAR_PATTERN_HIGH); + + // + return result; + } + + bool IsLow() + { + // + bool result = false; + + // + result = HasPattern(X_BAR_PATTERN_HIGH); + + // + return result; + } + + bool IsSupport() + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_SUPPORT // + ); + + // + return result; + } + + bool IsResistance() + { + // + bool result = false; + + // + result = HasPattern(X_BAR_PATTERN_RESISTANCE); + + // + return result; + } + + bool IsMomentum( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_MOMENTUM, + forDir // + ); + + // + return result; + } + + bool IsEngulfed( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_ENGULFED, + forDir // + ); + + // + return result; + } + + bool IsTrueGaped( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_TRUE_GAPED, + forDir // + ); + + // + return result; + } + + bool IsPinned( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_PINNED, + forDir // + ); + + // + return result; + } + + bool IsStar( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_STAR, + forDir // + ); + + // + return result; + } + + bool IsPiercing( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_PIERCING, + forDir // + ); + + // + return result; + } + + bool IsRising( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_RISING, + forDir // + ); + + // + return result; + } + + bool IsFlag( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_FLAG, + forDir // + ); + + // + return result; + } + + bool IsSignalKey( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_SIGNALKEY, + forDir // + ); + + // + return result; + } + + bool IsOB( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_OB, + forDir // + ); + + // + return result; + } + + bool IsFVG( + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = HasPattern( + X_BAR_PATTERN_FVG, + forDir // + ); + + // + return result; + } + + // + // Getters ... + + bool GetLow( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_LOW; + ENUM_X_DIRECTION _patternDir = X_DIRECTION_BULLISH; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetHigh( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_HIGH; + ENUM_X_DIRECTION _patternDir = X_DIRECTION_BEARISH; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetSupport( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_SUPPORT; + ENUM_X_DIRECTION _patternDir = X_DIRECTION_BULLISH; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetResistance( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_RESISTANCE; + ENUM_X_DIRECTION _patternDir = X_DIRECTION_BEARISH; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetOB( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_OB; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetFVG( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_FVG; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetMomentum( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_MOMENTUM; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetEngulfed( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_ENGULFED; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetPinned( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_PINNED; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetTrueGaped( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_TRUE_GAPED; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetStar( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_STAR; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetFlag( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_FLAG; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetRising( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_RISING; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetPiercing( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_PIERCING; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + bool GetSignalKey( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + ENUM_X_BAR_PATTERN _pattern = X_BAR_PATTERN_SIGNALKEY; + + // + return GetPattern( + _bar, + _pivot, + _zone, + _pattern, + _patternDir // + ); + } + + // + // Common Tools ... + + /** + * Add Specified Patterns to Model ... + * + * @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern ... + * @param patternDir: ENUM_X_DIRECTION, Specified Pattern Direction ... + */ + void AddPattern( + ENUM_X_BAR_PATTERN pattern, + ENUM_X_DIRECTION patternDir // + ) + { + // + bool has = IsXValid(pattern) && + HasDirection(patternDir); + if (!has) + { + return; + } + + // + Add( + pattern, + patterns // + ); + + // + Add( + patternDir, + patternsDir // + ); + } + + /** + * Check Model Has Specified Pattern or not ... + * + * @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern ... + * @param patternDir: ENUM_X_DIRECTION, Specified Pattern Direction ... + * + * @return ( bool ) + */ + bool HasPattern( + ENUM_X_BAR_PATTERN pattern, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = Contains( + pattern, + patterns // + ); + if (!result) + { + return result; + } + + // + if (HasDirection(forDir)) + { + // + int idx = FindIndex( + pattern, + patterns // + ); + result = + IsValidIndex(idx) && + forDir == patternsDir[idx]; + } + + // + return result; + } + + /** + * Get Specified Pattern if Exists ... + * + * @param _bar: XOHCL, Patterns Bar ... + * @param _pivot: XPivot, Patterns Pivot ... + * @param _zone: XBoxZone, Patterns Box ... + * @param _pattern: ENUM_X_BAR_PATTERN, Specified Pattern ... + * @param _patternDir: ENUM_X_DIRECTION, Specified Pattern Direction ... + * @param _peakPriceType: ENUM_X_PRICE, Specified Peak Price Type ... + * @param _valePriceType: ENUM_X_PRICE, Specified Vale Price Type ... + * + * @return ( bool ) + */ + bool GetPattern( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_BAR_PATTERN _pattern, + ENUM_X_DIRECTION _patternDir = X_DIRECTION_NONE, + ENUM_X_PRICE _peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE _valePriceType = X_PRICE_LOW // + ) + { + // + bool result = false; + + // + // Prepare ... + _bar.Clean(); + _zone.Clean(); + _pivot.Clean(); + + // + // Normalize ... + if (!IsXValid(_peakPriceType)) + { + _peakPriceType = X_PRICE_HIGH; + } + if (!IsXValid(_valePriceType)) + { + _valePriceType = X_PRICE_LOW; + } + + // + // Validate ... + result = IsValid() && + HasChild(patterns) && + IsXValid(_peakPriceType) && + IsXValid(_valePriceType) && + HasPattern(_pattern, _patternDir); + if (!result) + { + return result; + } + + // + // Find Pattern Index ... + int index = FindIndex(_pattern, patterns); + result = IsValidIndex(index); + if (!result) + { + return result; + } + + // + // Fill Common Patterns Data ... + _bar = bar; + result = ToPivot( + _bar, + _pivot, + _patternDir, + _pattern, + _peakPriceType, + _valePriceType // + ); + result = result && + ToBox( + _bar, + _zone, + _patternDir, + _pattern, + _peakPriceType, + _valePriceType // + ); + + // + // Use Custom Data if Pattern Staisfied ... + if (result) + { + // + // OB ... + if (_pattern == X_BAR_PATTERN_OB) + { + // + _bar.Clean(); + _zone.Clean(); + _pivot.Clean(); + + // + // Result Preparation ... + result = ob.IsValid() && + ob.dir == _patternDir; + if (result) + { + // + _zone = ob; + result = _zone.FromBar(_bar); + if (result) + { + // + result = ToPivot( + _bar, + _pivot, + _patternDir, + _pattern, + _peakPriceType, + _valePriceType // + ); + } + } + } + // + // FVG ... + else if (_pattern == X_BAR_PATTERN_FVG) + { + // + _bar.Clean(); + _zone.Clean(); + _pivot.Clean(); + + // + // Result Preparation ... + result = fvg.IsValid() && + fvg.dir == _patternDir; + if (result) + { + // + _zone = fvg; + result = _zone.FromBar(_bar); + if (result) + { + // + result = ToPivot( + _bar, + _pivot, + _patternDir, + _pattern, + _peakPriceType, + _valePriceType // + ); + } + } + } + // + // Support ... + else if (_pattern == X_BAR_PATTERN_SUPPORT) + { + // + _bar.Clean(); + _zone.Clean(); + _pivot.Clean(); + + // + // Result Preparation ... + result = support.IsValid(); + if (result) + { + // + _zone = support; + result = _zone.AtBar(_bar); + if (result) + { + // + result = ToPivot( + _bar, + _pivot, + _patternDir, + _pattern, + _peakPriceType, + _valePriceType // + ); + } + } + } + // + // Resistance ... + else if (_pattern == X_BAR_PATTERN_RESISTANCE) + { + // + _bar.Clean(); + _zone.Clean(); + _pivot.Clean(); + + // + // Result Preparation ... + result = resistance.IsValid(); + if (result) + { + // + _zone = resistance; + result = _zone.AtBar(_bar); + if (result) + { + // + result = ToPivot( + _bar, + _pivot, + _patternDir, + _pattern, + _peakPriceType, + _valePriceType // + ); + } + } + } + } + + // + // Cleanup Resources ... + if (!result) + { + // + _bar.Clean(); + _zone.Clean(); + _pivot.Clean(); + } + + // + 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 7052b50b..a20148f0 100644 --- a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -29,51 +29,6 @@ //+------------------------------------------------------------------+ //| Oldest Detection | //+------------------------------------------------------------------+ -/** - * Get Oldest Index of Specified Collection ... - * - * @param source: Specified Collection ... - * - * @return ( int ) - */ -int GetOldestBar( - XOHCL &source[] // -) -{ - // - int result = -1; - - // - int count = ArraySize(source); - if (!IsValidSize(count)) - { - return result; - } - - // - XOHCL selected; - for (int i = 0; i < count; i++) - { - // - bool canSet = - !selected.IsValid() - ? true - : selected.time > source[i].time; - if (canSet) - { - // - result = i; - selected = source[i]; - } - } - - // - selected.Clean(); - - // - return result; -} - /** * Get Oldest Index of Specified Collection ... * @@ -253,51 +208,6 @@ int GetOldest( //+------------------------------------------------------------------+ //| Youngest Detection | //+------------------------------------------------------------------+ -/** - * Get Youngest Index of Specified Collection ... - * - * @param source: Specified Collection ... - * - * @return ( int ) - */ -int GetYoungestBar( - XOHCL &source[] // -) -{ - // - int result = -1; - - // - int count = ArraySize(source); - if (!IsValidSize(count)) - { - return result; - } - - // - XOHCL selected; - for (int i = 0; i < count; i++) - { - // - bool canSet = - !selected.IsValid() - ? true - : selected.time < source[i].time; - if (canSet) - { - // - result = i; - selected = source[i]; - } - } - - // - selected.Clean(); - - // - return result; -} - /** * Get Youngest Index of Specified Collection ... * @@ -477,65 +387,6 @@ int GetYoungest( //+------------------------------------------------------------------+ //| Highest Detection | //+------------------------------------------------------------------+ -/** - * Get Highest Index of Specified Collection ... - * - * @param source: Specified Collection ... - * @param _priceType: Specified Price type ... - * - * @return ( int ) - */ -int GetHighestBar( - XOHCL &source[], - ENUM_X_PRICE _priceType = X_PRICE_HIGH // -) -{ - // - int result = -1; - - // - if (!IsXValid(_priceType)) - { - _priceType = X_PRICE_HIGH; - } - - // - int count = ArraySize(source); - if (!IsValidSize(count)) - { - return result; - } - - // - XOHCL selected; - double iPrice = EMPTY_VALUE; - double selectedPrice = EMPTY_VALUE; - for (int i = 0; i < count; i++) - { - // - iPrice = source[i].GetPrice(_priceType); - selectedPrice = selected.GetPrice(_priceType); - - // - bool canSet = - !selected.IsValid() - ? true - : selectedPrice < iPrice; - if (canSet) - { - // - result = i; - selected = source[i]; - } - } - - // - selected.Clean(); - - // - return result; -} - /** * Get Highest Index of Specified Collection ... * @@ -725,64 +576,6 @@ int GetHighest( //+------------------------------------------------------------------+ //| Loest Detection | //+------------------------------------------------------------------+ -/** - * Get Lowest Index of Specified Collection ... - * - * @param source: Specified Collection ... - * - * @return ( int ) - */ -int GetLowestBar( - XOHCL &source[], - ENUM_X_PRICE _priceType = X_PRICE_LOW // -) -{ - // - int result = -1; - - // - if (!IsXValid(_priceType)) - { - _priceType = X_PRICE_LOW; - } - - // - int count = ArraySize(source); - if (!IsValidSize(count)) - { - return result; - } - - // - XOHCL selected; - double iPrice = EMPTY_VALUE; - double selectedPrice = EMPTY_VALUE; - for (int i = 0; i < count; i++) - { - // - iPrice = source[i].GetPrice(_priceType); - selectedPrice = selected.GetPrice(_priceType); - - // - bool canSet = - !selected.IsValid() - ? true - : selectedPrice > iPrice; - if (canSet) - { - // - result = i; - selected = source[i]; - } - } - - // - selected.Clean(); - - // - return result; -} - /** * Get Lowest Index of Specified Collection ... * @@ -2027,13 +1820,13 @@ int SelectBarForSorting( // form Oldest to Youngest ... if (sortDir == X_DIRECTION_BULLISH) { - result = GetOldestBar(source); + result = GetOldest(source); } // // form Youngest to Oldest ... else if (sortDir == X_DIRECTION_BEARISH) { - result = GetYoungestBar(source); + result = GetYoungest(source); } // // Not Valid ... @@ -2050,13 +1843,13 @@ int SelectBarForSorting( // form Lowst to Highest ... if (sortDir == X_DIRECTION_BULLISH) { - result = GetLowestBar(source, priceType); + result = GetLowest(source, priceType); } // // form Highest to Lowest ... else if (sortDir == X_DIRECTION_BEARISH) { - result = GetHighestBar(source, priceType); + result = GetHighest(source, priceType); } // // Not Valid ... @@ -2596,56 +2389,6 @@ bool ExtractResistances( //+------------------------------------------------------------------+ //| Find Index | //+------------------------------------------------------------------+ -/** - * Find Specified Item index in a Collection ... - * - * @param index: int, reference to Hold Index if Exists ... - * @param item: Specified item to Detect ... - * @param source: Collection to Search for item ... - * - * @return ( bool ) - */ -bool FindIndex( - int &index, - XOHCL &item, - XOHCL &source[] // -) -{ - // - bool result = false; - - // - index = -1; - - // - int count = ArraySize(source); - result = item.IsValid() && - IsValidSize(count); - if (!result) - { - return result; - } - - // - for (int i = 0; i < count; i++) - { - // - bool isSame = item.IsSameAs(source[i]); - if (isSame) - { - // - index = i; - break; - } - } - - // - result = IsValidIndex(index); - - // - return result; -} - /** * Find Specified Item index in a Collection ... * @@ -2800,54 +2543,6 @@ bool FindIndex( //+------------------------------------------------------------------+ //| Remove | //+------------------------------------------------------------------+ -/** - * Remove Specified Item from a Collection ... - * - * @param item: Specified Item ... - * @param source: Specified Collection for Remove item from it ... - * - * @return ( bool ) - */ -bool Remove( - XOHCL &item, - XOHCL &source[] // -) -{ - // - bool result = false; - - // - result = - item.IsValid() && - HasChild(source); - if (!result) - { - return result; - } - - // - int idx = -1; - result = FindIndex( - idx, - item, - source // - ); - if (!result) - { - return result; - } - - // - result = ArrayRemove( - source, - idx, - 1 // - ); - - // - return result; -} - /** * Remove Specified Item from a Collection ... * @@ -2992,67 +2687,6 @@ bool Remove( return result; } -/** - * Remove Specified items from a Collection ... - * - * @param items: Specified Items to Remove ... - * @param sources: Sepcified Collection for Removing items from it ... - * - * @return ( int ) - */ -int Removes( - XOHCL &items[], - XOHCL &sources[] // -) -{ - // - int result = 0; - - // - bool has = HasChild(items) && - HasChild(sources); - if (!has) - { - return result; - } - - // - int idx = -1; - has = false; - int count = ArraySize(items); - for (int i = 0; i < count; i++) - { - // - // Detect Item Index in Collection ... - has = FindIndex( - idx, - items[i], - sources // - ); - if (has) - { - // - // Remove Detected Index from Collection ... - has = ArrayRemove( - sources, - idx, - 1 // - ); - - // - if (has) - { - // - // Count Removed Items ... - result++; - } - } - } - - // - return result; -} - /** * Remove Specified items from a Collection ... * @@ -3240,69 +2874,6 @@ int Removes( //+------------------------------------------------------------------+ //| Add If Not Exists | //+------------------------------------------------------------------+ -/** - * Add Specified Item to Specified Collection, if not Exists ... - * - * @param item: Item to Add ... - * @param sources: Collection to Add item ... - * @param maxAllowed: int, Max Allowed Collection Size ... - * - * @return ( bool ) - */ -bool AddIfNotExists( - XOHCL &item, - XOHCL &sources[], - int maxAllowed = 0 // -) -{ - // - bool result = false; - - // - // Validate Args ... - result = item.IsValid(); - if (!result) - { - return result; - } - - // - // Check Item Exists or not ... - int idx = -1; - bool isExists = FindIndex( - idx, - item, - sources // - ); - result = !isExists; - if (!result) - { - return result; - } - - // - AddRef( - item, - sources // - ); - - // - // Handle Cleanup Collection - // if Max Reached ... - if (result && - maxAllowed > 0) - { - // - CleanupArray( - sources, - maxAllowed // - ); - } - - // - return result; -} - /** * Add Specified Item to Specified Collection, if not Exists ... * @@ -3852,8 +3423,9 @@ void ValidateBoxes( void UpdateToTime( XBoxZone &zones[], - datetime toTime = NULL// -) { + datetime toTime = NULL // +) +{ // // Normalize ... toTime = NormalizeTime(toTime); @@ -3861,13 +3433,15 @@ void UpdateToTime( // // Validate ... bool has = HasChild(zones); - if (!has) { + if (!has) + { return; } // int count = ArraySize(zones); - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { zones[i].to = toTime; } } @@ -3879,6 +3453,8 @@ void UpdateToTime( * @param pivot: XPivot, reference to holds result ... * @param forDir: ENUM_X_DIRECTION, specified Pivot Direction ... * @param prefix: string, Specified Pivot Prefix (used for Object Type) ... + * @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ... + * @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ... * * @return ( bool ) */ @@ -3886,7 +3462,9 @@ bool ToPivot( XOHCL &bar, XPivot &pivot, ENUM_X_DIRECTION forDir, - string prefix = NULL // + string prefix = NULL, + ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE valePriceType = X_PRICE_LOW // ) { // @@ -3896,10 +3474,23 @@ bool ToPivot( // Prepare ... pivot.Clean(); + // + // Normalize ... + if (!IsXValid(peakPriceType)) + { + peakPriceType = X_PRICE_HIGH; + } + if (!IsXValid(valePriceType)) + { + valePriceType = X_PRICE_LOW; + } + // // Validate ... result = bar.IsValid() && - HasDirection(forDir); + HasDirection(forDir) && + IsXValid(peakPriceType) && + IsXValid(valePriceType); if (!result) { return result; @@ -3913,8 +3504,8 @@ bool ToPivot( // Prepare Value of Pivot ... double iValue = isBullish - ? bar.low - : bar.high; + ? bar.GetPrice(valePriceType) + : bar.GetPrice(peakPriceType); // // Prepare Pivot Type ... @@ -3953,12 +3544,106 @@ bool ToPivot( } /** - * Converts POI Patterns to Box ... + * Converts a Bar to Pattern Pivot ... + * + * @param bar: XOHCL, reference to Specified Bar ... + * @param pivot: XPivot, reference to holds result ... + * @param patternDir: ENUM_X_DIRECTION, specified Pivot Direction ... + * @param pattern: ENUM_X_BAR_PATTERN, Specified Pattern Type ... + * @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ... + * @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ... + * + * @return ( bool ) + */ +bool ToPivot( + XOHCL &bar, + XPivot &pivot, + ENUM_X_DIRECTION patternDir, + ENUM_X_BAR_PATTERN pattern, + ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE valePriceType = X_PRICE_LOW // +) +{ + // + bool result = false; + + // + // Prepare ... + pivot.Clean(); + + // + // Normalize ... + if (!IsXValid(peakPriceType)) + { + peakPriceType = X_PRICE_HIGH; + } + if (!IsXValid(valePriceType)) + { + valePriceType = X_PRICE_LOW; + } + + // + // Validate ... + result = bar.IsValid() && + IsXValid(pattern) && + IsXValid(peakPriceType) && + IsXValid(valePriceType) && + HasDirection(patternDir); + if (!result) + { + return result; + } + + // + datetime iTime = bar.time; + string iSymbol = bar.symbol; + string iPrefix = ToXString(pattern); + ENUM_TIMEFRAMES iPeriod = bar.period; + double iValue = IsXBullish(patternDir) + ? bar.GetPrice(X_PRICE_LOW) + : IsXBearish(patternDir) + ? bar.GetPrice(X_PRICE_HIGH) + : EMPTY_VALUE; + ENUM_X_PIVOT_TYPE iType = IsXBullish(patternDir) + ? X_PIVOT_TYPE_VALE + : IsXBearish(patternDir) + ? X_PIVOT_TYPE_PEAK + : X_PIVOT_TYPE_NONE; + + // + result = pivot.Init( + iValue, + iTime, + iSymbol, + patternDir, + iPeriod, + iType // + ); + if (result) + { + pivot.prefix = iPrefix; + } + + // + // Cleanup Resources ... + if (!result) + { + pivot.Clean(); + } + + // + return result; +} + +/** + * Converts POI Bar to Box ... * * @param bar: XOHCL, reference to Specified Pattern ... * @param box: XBoxZone, reference to holds result ... * @param forDir: ENUM_X_DIRECTION, Specified Pattern Direction ... * @param prefix: string, Specified Pattern Type ... + * @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ... + * @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ... * * @return ( bool ) */ @@ -3966,7 +3651,9 @@ bool ToBox( XOHCL &bar, XBoxZone &box, ENUM_X_DIRECTION forDir, - string prefix = NULL // + string prefix = NULL, + ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE valePriceType = X_PRICE_LOW // ) { // @@ -3976,127 +3663,76 @@ bool ToBox( // Prepare ... box.Clean(); + // + // Normalize ... + if (!IsXValid(peakPriceType)) + { + peakPriceType = X_PRICE_HIGH; + } + if (!IsXValid(valePriceType)) + { + valePriceType = X_PRICE_LOW; + } + // // Validate ... result = bar.IsValid() && - HasDirection(forDir); - if (!result) - { - return result; - } - - - // - // Flags for Patterns ... - - // - bool isStar = - IsSpecifiedValid(prefix) && - prefix == "Star"; - - // - bool isPiercing = - IsSpecifiedValid(prefix) && - prefix == "Piercing"; - - // - bool isRising = - IsSpecifiedValid(prefix) && - prefix == "Rising"; - - // - bool isFlag = - IsSpecifiedValid(prefix) && - prefix == "Flag"; - - // - bool isSignalKeyBar = - IsSpecifiedValid(prefix) && - prefix == "SignalKeyBar"; - - // - // Validate Pattern ... - result = isStar || - isFlag || - isRising || - isPiercing || - isSignalKeyBar; + HasDirection(forDir) && + IsXValid(peakPriceType) && + IsXValid(valePriceType); if (!result) { return result; } // - // Now Try to Initialized Box ... - - // - // Common Configs ... - box.dir = forDir; - box.type = prefix; - box.at = bar.time; - box.to = bar.time; - box.from = bar.time; - box.symbol = bar.symbol; - box.period = bar.period; - - // - double upper = 0; - double lower = 0; - datetime from = NULL; - bool isBullish = IsSpecifiedBullish(forDir); - - // - int loopback = 0; - ENUM_SERIESMODE uMode = MODE_HIGH; - ENUM_SERIESMODE lMode = MODE_LOW; - - // - // Specified Configs ... - if (isStar) - { - loopback = 2; - } - else if (isPiercing) - { - loopback = 1; - } - else if (isRising) - { - loopback = 5; - } - else if (isFlag) - { - loopback = 1; - } - else if (isSignalKeyBar) - { - loopback = 1; - } - - // - result = IsValidSize(loopback); + // Check if is Valid Pattern ... + ENUM_X_BAR_PATTERN iPattern = ToBarPattern(prefix); + result = IsXValid(iPattern); if (result) { // - from = GetBarTime( - bar.symbol, - bar.period, - bar.Index() + loopback // - ); - upper = bar.FindHighest( - loopback, - uMode // - ); - lower = bar.FindLowest( - loopback, - lMode // + // Conver to Box as Pattern ... + result = ToBox( + bar, + box, + forDir, + iPattern, + peakPriceType, + valePriceType // ); } - // - box.from = from; - box.upper = upper; - box.lower = lower; + // There is not any Valid Pattern Provided ... + else + { + // + bool isBullish = IsXBullish(forDir); + double peakPrice = bar.GetPrice(peakPriceType); + double valePrice = bar.GetPrice(valePriceType); + + // + string iType = prefix; + datetime iAt = bar.time; + datetime iTo = bar.time; + double iUpper = peakPrice; + double iLower = valePrice; + string iSymbol = bar.symbol; + datetime iFrom = bar.BeforeOn(); + ENUM_TIMEFRAMES iPeriod = bar.period; + + // + // Assign Values to Box ... + box.at = iAt; + box.to = iTo; + box.from = iFrom; + box.type = iType; + box.dir = forDir; + box.upper = iUpper; + box.lower = iLower; + box.symbol = iSymbol; + box.period = iPeriod; + } // // Validate result ... @@ -4112,6 +3748,679 @@ bool ToBox( return result; } +/** + * Converts Pattern Bar to Box ... + * + * @param bar: XOHCL, reference to Specified Pattern ... + * @param box: XBoxZone, reference to holds result ... + * @param forDir: ENUM_X_DIRECTION, Specified Pattern Direction ... + * @param prefix: string, Specified Pattern Type ... + * @param peakPriceType: ENUM_X_PRICE, Specified Peak Pivot's Applied Price ... + * @param valePriceType: ENUM_X_PRICE, Specified Vale Pivot's Applied Price ... + * + * @return ( bool ) + */ +bool ToBox( + XOHCL &bar, + XBoxZone &box, + ENUM_X_DIRECTION patternDir, + ENUM_X_BAR_PATTERN pattern, + ENUM_X_PRICE peakPriceType = X_PRICE_HIGH, + ENUM_X_PRICE valePriceType = X_PRICE_LOW // +) +{ + // + bool result = false; + + // + // Prepare ... + box.Clean(); + + // + // Normalize ... + if (!IsXValid(peakPriceType)) + { + peakPriceType = X_PRICE_HIGH; + } + if (!IsXValid(valePriceType)) + { + valePriceType = X_PRICE_LOW; + } + + // + // Validate ... + result = bar.IsValid() && + IsXValid(pattern) && + IsXValid(peakPriceType) && + IsXValid(valePriceType) && + HasDirection(patternDir); + if (!result) + { + return result; + } + + // + // Define Requirements ... + XOHCL tmpBar; + XBoxZone tmpBox; + bool has = false; + datetime iAt = bar.time; + datetime iTo = bar.time; + double iUpper = EMPTY_VALUE; + double iLower = EMPTY_VALUE; + string iSymbol = bar.symbol; + datetime iFrom = bar.BeforeOn(); + string iType = ToXString(pattern); + ENUM_TIMEFRAMES iPeriod = bar.period; + + // + bool isBullish = IsXBullish(patternDir); + double peakPrice = bar.GetPrice(peakPriceType); + double valePrice = bar.GetPrice(valePriceType); + + // + // Calculate Requirements Based on Pattern Type and Direction ... + switch (pattern) + { + // + case X_BAR_PATTERN_HIGH: { + // + tmpBar.Clean(); + has = GetBreakerBar( + bar, + tmpBar, + peakPriceType, + peakPriceType, + X_DIRECTION_BULLISH // + ); + if (has) + { + iFrom = tmpBar.time; + } + + // + iUpper = peakPrice; + iLower = bar.GetUp(); + } + break; + + // + case X_BAR_PATTERN_LOW: { + // + tmpBar.Clean(); + has = GetBreakerBar( + bar, + tmpBar, + valePriceType, + valePriceType, + X_DIRECTION_BEARISH // + ); + if (has) + { + iFrom = tmpBar.time; + } + + // + iUpper = bar.GetDown(); + iLower = valePrice; + } + break; + + // + case X_BAR_PATTERN_MOMENTUM: { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + + // + iUpper = peakPrice; + iLower = valePrice; + } + break; + + // + case X_BAR_PATTERN_ENGULFED: { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + + // + iUpper = peakPrice; + iLower = valePrice; + } + break; + + // + case X_BAR_PATTERN_TRUE_GAPED: { + // + tmpBar.Clean(); + has = bar.GetPreviousBar(tmpBar); + if (has) + { + // + iFrom = tmpBar.time; + + // + iUpper = + isBullish + ? valePrice + : peakPrice; + iLower = + isBullish + ? tmpBar.GetPrice(peakPriceType) + : tmpBar.GetPrice(valePriceType); + } + } + break; + + // + case X_BAR_PATTERN_PINNED: { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + + // + iUpper = + isBullish + ? bar.GetDown() + : peakPrice; + iLower = + isBullish + ? valePrice + : bar.GetUp(); + } + break; + + // + case X_BAR_PATTERN_STAR: { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + + // + iUpper = + isBullish + ? peakPrice + : valePrice; + iLower = + isBullish + ? peakPrice + : valePrice; + } + break; + + // + case X_BAR_PATTERN_PIERCING: { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + + // + iUpper = + isBullish + ? peakPrice + : valePrice; + iLower = + isBullish + ? peakPrice + : valePrice; + } + break; + + // + case X_BAR_PATTERN_RISING: { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + + // + iUpper = + isBullish + ? peakPrice + : valePrice; + iLower = + isBullish + ? peakPrice + : valePrice; + } + break; + + // + case X_BAR_PATTERN_FLAG: { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + + // + iUpper = + isBullish + ? peakPrice + : valePrice; + iLower = + isBullish + ? peakPrice + : valePrice; + } + break; + + // + case X_BAR_PATTERN_SIGNALKEY: { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + + // + iUpper = + isBullish + ? peakPrice + : valePrice; + iLower = + isBullish + ? peakPrice + : valePrice; + } + break; + + // + case X_BAR_PATTERN_OB: { + // + tmpBox.Clean(); + has = ToOBBox( + bar, + tmpBox, + patternDir // + ); + if (has) + { + // + iFrom = tmpBox.from; + iUpper = tmpBox.upper; + iLower = tmpBox.lower; + } + } + break; + + // + case X_BAR_PATTERN_FVG: { + // + tmpBox.Clean(); + has = ToFVGBox( + bar, + tmpBox, + patternDir // + ); + if (has) + { + // + iFrom = tmpBox.from; + iUpper = tmpBox.upper; + iLower = tmpBox.lower; + } + } + break; + + // + case X_BAR_PATTERN_SUPPORT: { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + + // + iUpper = + isBullish + ? peakPrice + : valePrice; + iLower = + isBullish + ? peakPrice + : valePrice; + } + break; + + // + case X_BAR_PATTERN_RESISTANCE: { + // + tmpBar.Clean(); + ENUM_X_PRICE iPType = isBullish + ? valePriceType + : peakPriceType; + has = GetBreakerBar( + bar, + tmpBar, + iPType, + iPType, + patternDir // + ); + if (has) + { + iFrom = tmpBar.time; + } + + // + iUpper = + isBullish + ? peakPrice + : valePrice; + iLower = + isBullish + ? peakPrice + : valePrice; + } + break; + } + + // + // Assign Values to Box ... + box.at = iAt; + box.to = iTo; + box.from = iFrom; + box.type = iType; + box.upper = iUpper; + box.lower = iLower; + box.symbol = iSymbol; + box.period = iPeriod; + box.dir = patternDir; + + // + result = box.IsValid(); + + // + // Cleanup Resources ... + if (!result) + { + box.Clean(); + } + tmpBar.Clean(); + tmpBox.Clean(); + + // + return result; +} + +/** + * Converts a Bar to OB Box ... + * + * @param bar: XOHCL, Specified Bar ... + * @param box: XBoxZone, destination Box ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + * + * @return ( bool ) + */ +bool ToOBBox( + XOHCL &bar, + XBoxZone &box, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + bool result = false; + + // + // Prepare ... + box.Clean(); + + // + // Normalize ... + if (!HasDirection(forDir)) + { + forDir = bar.GetDirection(); + } + + // + // Validate ... + result = bar.IsValid() && + HasDirection(forDir) && + bar.GetDirection() == forDir; + if (!result) + { + return result; + } + + // + // Detect OB Start Bar ... + XOHCL obStartBar; + result = GetDirectionalBar( + bar, + obStartBar, + Opposit(forDir) // + ); + if (!result) + { + // + obStartBar.Clean(); + return result; + } + + // + box.dir = forDir; + box.to = bar.time; + box.at = bar.time; + box.symbol = bar.symbol; + box.period = bar.period; + box.from = obStartBar.time; + box.type = ToXString(X_BAR_PATTERN_OB); + box.lower = MathMin(obStartBar.low, bar.low); + box.upper = MathMax(obStartBar.high, bar.high); + + // + result = box.IsValid(); + + // + // Cleanup Resources ... + if (!result) + { + box.Clean(); + } + obStartBar.Clean(); + + // + return result; +} + +/** + * Converts a Bar to FVG Box ... + * + * @param bar: XOHCL, Specified Bar ... + * @param box: XBoxZone, destination Box ... + * @param forDir: ENUM_X_DIRECTION, Specified Direction ... + * + * @return ( bool ) + */ +bool ToFVGBox( + XOHCL &bar, + XBoxZone &box, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // +) +{ + // + bool result = false; + + // + // Prepare ... + box.Clean(); + + // + // Normalize ... + if (!HasDirection(forDir)) + { + forDir = bar.GetDirection(); + } + + // + // Validate ... + result = bar.IsValid() && + HasDirection(forDir) && + bar.GetDirection() == forDir; + if (!result) + { + return result; + } + + // + // Detect FVG Start Bar ... + XOHCL fvgStartBar; + result = bar.BarAt( + bar.Index() + 2, + fvgStartBar); + if (!result) + { + // + fvgStartBar.Clean(); + return result; + } + + // + bool isBullish = IsXBullish(forDir); + + // + box.dir = forDir; + box.to = bar.time; + box.at = bar.time; + box.upper = + isBullish + ? bar.low + : bar.high; + box.symbol = bar.symbol; + box.period = bar.period; + box.lower = + isBullish + ? fvgStartBar.high + : fvgStartBar.low; + box.from = fvgStartBar.time; + box.type = ToXString(X_BAR_PATTERN_FVG); + + // + result = box.IsValid(); + + // + // Cleanup Resources ... + if (!result) + { + box.Clean(); + } + fvgStartBar.Clean(); + + // + return result; +} + /** * Converts a Bar to Support Box ... * @@ -4529,7 +4838,7 @@ bool IsFakeBreaked( // // Get Youngest Breaker Bars ... - int idx = GetYoungestBar(breakerBars); + int idx = GetYoungest(breakerBars); result = IsValidIndex(idx); if (!result) { diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index 30d89115..140f49cf 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -38,7 +38,7 @@ enum ENUM_X_BAR_PATTERN X_BAR_PATTERN_LOW = 2, X_BAR_PATTERN_MOMENTUM = 3, X_BAR_PATTERN_ENGULFED = 4, - X_BAR_PATTERN_TRUE_GAPPED = 5, + X_BAR_PATTERN_TRUE_GAPED = 5, X_BAR_PATTERN_PINNED = 6, X_BAR_PATTERN_STAR = 7, X_BAR_PATTERN_PIERCING = 8, @@ -53,9 +53,9 @@ enum ENUM_X_BAR_PATTERN /** * Validate an ENUM member ... - * + * * @param value: ENUM_X_BAR_PATTERN ... - * + * * @return ( bool ) */ bool IsXValid(ENUM_X_BAR_PATTERN value) @@ -65,9 +65,9 @@ bool IsXValid(ENUM_X_BAR_PATTERN value) /** * Converts a Pattern ENUM to String Representation ... - * + * * @param value: ENUM_X_BAR_PATTERN, member ... - * + * * @return ( string ) */ string ToXString(ENUM_X_BAR_PATTERN value) @@ -104,8 +104,8 @@ string ToXString(ENUM_X_BAR_PATTERN value) break; // - case X_BAR_PATTERN_TRUE_GAPPED: - result = "XGAPPED"; + case X_BAR_PATTERN_TRUE_GAPED: + result = "XGAPED"; break; // @@ -165,9 +165,9 @@ string ToXString(ENUM_X_BAR_PATTERN value) /** * Parse an String Representation to it's Corresponding Bar Pattern ENUM ... - * + * * @param value: string, provided pattern's string ... - * + * * @return ( ENUM_X_BAR_PATTERN ) */ ENUM_X_BAR_PATTERN ToBarPattern(string value) @@ -203,9 +203,9 @@ ENUM_X_BAR_PATTERN ToBarPattern(string value) { result = X_BAR_PATTERN_ENGULFED; } - else if (value == ToXString(X_BAR_PATTERN_TRUE_GAPPED)) + else if (value == ToXString(X_BAR_PATTERN_TRUE_GAPED)) { - result = X_BAR_PATTERN_TRUE_GAPPED; + result = X_BAR_PATTERN_TRUE_GAPED; } else if (value == ToXString(X_BAR_PATTERN_PINNED)) { diff --git a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 index bfa61f9e..c5f834fb 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -450,9 +450,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller public: // // Props ... - CArrayObj barObjects; - CArrayObj zoneObjects; - CArrayObj pivotObjects; + CArrayObj drawnObjects; XFIMAPatternDetectorConfig analyserConfig; // @@ -529,6 +527,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller string iName = NULL; bool isBullish = false; bool isBearish = false; + XPatternAnalysis iBarAnalysis; XFIMAConditions iFIMAConditions; XFIMAMarketStructure iStructure; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; @@ -573,211 +572,519 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller ); // - // Draw Market Analysis ... - // has = iStructure.pvAnalysis.IsValid(); - // if (has) - // { - // // - // XBoxZone iBox; - // XCBoxObject *iBoxObj; - - // - // poiDrawer.RemoveDraws(); - - // // - // has = iStructure.pvAnalysis.HasSupportBox(iBox); - // if (has) - // { - // // - // iBox.to = iBar.time; - // poiDrawer.DrawBox( - // iBox, - // iBoxObj, - // true, - // iBox.type // - // ); - // } - - // // - // ZeroMemory(iBoxObj); - // has = iStructure.pvAnalysis.HasResistanceBox(iBox); - // if (has) - // { - // // - // iBox.to = iBar.time; - // poiDrawer.DrawBox( - // iBox, - // iBoxObj, - // true, - // iBox.type // - // ); - // } - // } - - // // - // // Draw Zones ... - // has = HasChild(iStructure.supports); - // if (has) { - // // - // CArrayObj *iSupportObjs; - // poiDrawer.DrawBoxes( - // iStructure.supports, - // iSupportObjs, - // true // - // ); - // } - - // // - // has = HasChild(iStructure.resistances); - // if (has) { - // // - // CArrayObj *iResistanceObjs; - // poiDrawer.DrawBoxes( - // iStructure.resistances, - // iResistanceObjs, - // true // - // ); - // } - - // - // Detecte Fibo Section Changes ... - - // // - // has = fimaHelper.IsFiboSectionChanged(iDir, iBar.Index()); - // has = has && - // IsXBullish(iDir) && - // fimaHelper.IsValeOverLast(iBar.Index()); - - // // - // has = fimaHelper.IsFiboSectionChanged(iDir, iBar.Index()); - // has = has && - // IsXBearish(iDir) && - // fimaHelper.IsPeakUnderLast(iBar.Index()); - - // // - // has = fimaHelper.HasFiboPush(iDir, iBar.Index(), 5); - - // // - // XBoxZone fimaZones[]; - // int fimaZonesCount = fimaHelper.DetectXFIMAZones( - // fimaZones, - // iBar.Index(), - // true, // Only Valid Zones ... - // 50, // Number of Zones ... - // 4, // Shadow Multiplier ... - // 1, // Strength ... - // 7, // Validation Length ... - // 500 // Loopback .. - // ); - - // - // XPivot fimaPivots[]; - // int fimaPivotsCount = fimaHelper.DetecteXFIMAPivots( - // fimaPivots, - // iBar.Index(), - // 50, // Number of Pivots ... - // 7, // Validation Length ... - // 500 // Loopback ... - // ); - - // // - // has = IsValidSize(fimaZonesCount); - // if (has) - // { - // // - // // Draw Detected Zones ... - // for (int i = 0; i < fimaZonesCount; i++) - // { - // // - // XCBoxObject *iObj; - // has = poiDrawer.DrawBox( - // fimaZones[i], - // iObj, - // true, // Ignore At ... - // fimaZones[i].type // Specified Name ... - // ); - // if (has) - // { - // zoneObjects.Add(iObj); - // } - // } - // } - - // // - // has = IsValidSize(fimaPivotsCount); - // if (has) - // { - // // - // // Draw Detected Pivots ... - // for (int i = 0; i < fimaPivotsCount; i++) - // { - // // - // XCBarArrowObject *iObj; - // has = poiDrawer.DrawPivot( - // fimaPivots[i], - // iObj); - // if (has) - // { - // pivotObjects.Add(iObj); - // } - // } - // } - - // - // Detect DecisionBars ... - XOHCL decisionBars[]; - int decisionBarsCount = 0; - ENUM_X_DIRECTION decisionBarDirs[]; - // decisionBarsCount = fimaHelper.DetectXFIMAPOIBars( - // decisionBars, - // decisionBarDirs, - // iBar.Index(), - // X_DIRECTION_ALL, // For Dir ... - // 300 // Required Number of Bars ... - // ); - // decisionBarsCount = fimaHelper.DetectXFIMAReversalPOIBars( - // decisionBars, - // decisionBarDirs, - // iBar.Index(), - // true, // Force Touch Boundary ... - // X_DIRECTION_ALL, // For Dir ... - // 300 // Required Number of Bars ... - // ); - decisionBarsCount = fimaHelper.DetectXFIMAContinuationalPOIBars( - decisionBars, - decisionBarDirs, - iBar.Index(), - true, - X_DIRECTION_ALL, // For Dir ... - 300 // Required Number of Bars ... + // Bar Pattern Analysis Detection Test ... + has = poiDetector.AnalyseBarPatterns( + iBar, + iBarAnalysis + // + // Use Default Config ... ); - - // - has = IsValidSize(decisionBarsCount); if (has) { // - for (int i = 0; i < decisionBarsCount; i++) + // Draw Bar Patterns Analysis ... + + // + XOHCL patternBar; + XPivot patternPivot; + XBoxZone patternBox; + ENUM_X_BAR_PATTERN pattern; + ENUM_X_DIRECTION patternDir; + + // + // Support and Resistance ... + + // + // Support ... + isBearish = false; + isBullish = iBarAnalysis.IsSupport(); + has = isBullish; + if (has) { // - XCBarArrowObject *iObj; - has = poiDrawer.DrawBarArrow( - decisionBars[i], - iObj, - IsXBullish(decisionBarDirs[i]) ? X_PRICE_LOW : X_PRICE_HIGH, - 159, - IsXBullish(decisionBarDirs[i]) ? clrAqua : clrMagenta, - 5, - IsXBullish(decisionBarDirs[i]) ? ANCHOR_TOP : ANCHOR_BOTTOM, - "XOHCL_" + ToXString(TimeToSeconds(decisionBars[i].time)), - true, // Ignore Bar Tag ... - 5 // Threshold ... + pattern = X_BAR_PATTERN_SUPPORT; + patternDir = X_DIRECTION_BULLISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // ); if (has) { - barObjects.Add(iObj); + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); } } + + // + // Resistance ... + isBullish = false; + isBearish = iBarAnalysis.IsResistance(); + has = isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_SUPPORT; + patternDir = X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // PV: High and Low ... + + // + // Low ... + isBearish = false; + isBullish = iBarAnalysis.IsLow(); + has = isBullish; + if (has) + { + // + pattern = X_BAR_PATTERN_LOW; + patternDir = X_DIRECTION_BULLISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // High ... + isBullish = false; + isBearish = iBarAnalysis.IsHigh(); + has = isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_HIGH; + patternDir = X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // OB ... + isBullish = iBarAnalysis.IsOB(X_DIRECTION_BULLISH); + isBearish = iBarAnalysis.IsOB(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_OB; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // FVG ... + isBullish = iBarAnalysis.IsFVG(X_DIRECTION_BULLISH); + isBearish = iBarAnalysis.IsFVG(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_FVG; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // Momentum ... + isBullish = iBarAnalysis.IsMomentum(X_DIRECTION_BULLISH); + isBearish = iBarAnalysis.IsMomentum(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_MOMENTUM; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // Engulfed ... + isBullish = iBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH); + isBearish = iBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_ENGULFED; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // Pinned ... + isBullish = iBarAnalysis.IsPinned(X_DIRECTION_BULLISH); + isBearish = iBarAnalysis.IsPinned(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_PINNED; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // TrueGaped ... + isBullish = iBarAnalysis.IsTrueGaped(X_DIRECTION_BULLISH); + isBearish = iBarAnalysis.IsTrueGaped(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_TRUE_GAPED; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // Star ... + isBullish = iBarAnalysis.IsStar(X_DIRECTION_BULLISH); + isBearish = iBarAnalysis.IsStar(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_STAR; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // Piercing ... + isBullish = iBarAnalysis.IsPiercing(X_DIRECTION_BULLISH); + isBearish = iBarAnalysis.IsPiercing(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_PIERCING; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // Rising ... + isBullish = iBarAnalysis.IsRising(X_DIRECTION_BULLISH); + isBearish = iBarAnalysis.IsRising(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_RISING; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // Flag ... + isBullish = iBarAnalysis.IsFlag(X_DIRECTION_BULLISH); + isBearish = iBarAnalysis.IsFlag(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_FLAG; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // SignalKey ... + isBullish = iBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH); + isBearish = iBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH); + has = isBullish || isBearish; + if (has) + { + // + pattern = X_BAR_PATTERN_SIGNALKEY; + patternDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + has = iBarAnalysis.GetPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + if (has) + { + // + DrawPattern( + patternBar, + patternPivot, + patternBox, + pattern, + patternDir // + ); + } + } + + // + // Cleanup Resources ... + patternBar.Clean(); + patternBox.Clean(); + patternPivot.Clean(); } // @@ -860,6 +1167,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller iZone.Clean(); iSignal.Clean(); iStructure.Clean(); + iBarAnalysis.Clean(); iFIMAConditions.Clean(); SpecifiedClean(iTargets); } @@ -1360,6 +1668,133 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller return result; } + // + // Drawer Functions ... + + // + void DrawPattern( + XOHCL &_bar, + XPivot &_pivot, + XBoxZone &_zone, + ENUM_X_BAR_PATTERN _pattern, + ENUM_X_DIRECTION _patternDir // + ) + { + // + // Validate ... + bool has = + poiDrawer != NULL && + _bar.IsValid() && + IsXValid(_pattern) && + HasDirection(_patternDir); + if (!has) + { + return; + } + + // + // Defien Draw Requirements ... + + // + int width = 3; + bool ignoreBoxAt = true; + int arrowThreshold = 5; + + // + int bullishArrow = 159; + int bearishArrow = 159; + + // + ENUM_X_PRICE arrowValePriceType = X_PRICE_LOW; + ENUM_X_PRICE arrowPeakPriceType = X_PRICE_HIGH; + + // + color bullishColor = clrAqua; + color bearishColor = clrMagenta; + + // + // Draw Bar ... + + // + // Draw Pivot ... + if (_pivot.IsValid()) + { + // + XCBarArrowObject *iObj; + has = poiDrawer.DrawBarArrow( + _bar, + iObj, + _pivot.IsPeak() + ? arrowPeakPriceType + : arrowValePriceType, + IsXBullish(_patternDir) + ? bullishArrow + : bearishArrow, + IsXBullish(_patternDir) + ? bullishColor + : bearishColor, + width, + IsXBullish(_patternDir) + ? ANCHOR_TOP + : ANCHOR_BOTTOM, + _pivot.prefix + "_" + ToXString(TimeToSeconds(_pivot.time)), + true, // Ignore Bar Tag ... + arrowThreshold // Threshold ... + ); + if (has) + { + drawnObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + // Draw Box ... + if (_zone.IsValid()) + { + // + XCBoxObject *iObj; + has = poiDrawer.DrawBox( + _zone, + iObj, + ignoreBoxAt, + _zone.type + "_" + ToXString(TimeToSeconds(_zone.from)) // + ); + if (has) + { + // + XPOIStyle iStyle; + poiDrawer.GetBoxStyle( + iStyle, + _zone.dir // + ); + + // + iStyle.clr = + IsXBullish(_patternDir) + ? bullishColor + : bearishColor; + + // + poiDrawer.ApplyBoxStyle( + iObj, + iStyle // + ); + + // + drawnObjects.Add(iObj); + + // + iStyle.Clean(); + } + + // + ZeroMemory(iObj); + } + } + // }; 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 db3977a9..b73b35b1 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 @@ -622,7 +622,7 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector if (config.detectStarPattern) { // - bool isStarPattern = IsStartPattern( + bool isStarPattern = IsStarPattern( forBar, iDir // ); @@ -1129,7 +1129,7 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector { // iPrefix = "Star"; - has = IsStartPattern( + has = IsStarPattern( iBar, iDir // );