From 40f97468fd2037223851685dd42b4f5f4e740092 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Tue, 12 Nov 2024 09:08:40 +0330 Subject: [PATCH] Complete Detection of Swings ... --- Classes/x-saherelm.x-bar.analyser.class.mq5 | 968 ++---------- Classes/x-saherelm.x-poi.class.mq5 | 511 ++++--- Classes/x-saherelm.x-poi.drawer.class.mq5 | 8 +- .../BKP/x-saherelm.x-bar.analyser.class.mq5 | 1360 +++++++++++++++++ Libraries/x-saherelm.x-poi.lib.mq5 | 5 + 5 files changed, 1764 insertions(+), 1088 deletions(-) create mode 100644 Documents/BKP/x-saherelm.x-bar.analyser.class.mq5 diff --git a/Classes/x-saherelm.x-bar.analyser.class.mq5 b/Classes/x-saherelm.x-bar.analyser.class.mq5 index b11cb8ee..c0bb02ad 100644 --- a/Classes/x-saherelm.x-bar.analyser.class.mq5 +++ b/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -28,7 +28,7 @@ // // Implementations ... -class XCBarAnalyser : public XSCBase +class XCBarAnalyser : public XCBase { // public: @@ -399,583 +399,25 @@ class XCBarAnalyser : public XSCBase } /** - * Converts an Specified Bar to Zone ... + * Check Specified Bar is Swing High or not ... * - * @param bar: XOHCL instance, Specified Bar ... - * @param zone: XZone instance, Converted Zone Reference ... - * @param dir: ENUM_X_DIRECTION member, Specified Bar Type to Convertion ... + * @param bar: XOHCL instnce ... + * @param range: Integer, Specified Range ... * * @return ( bool ) */ - bool ToZone( + bool IsSwingHigh( XOHCL &bar, - XZone &zone, - ENUM_X_DIRECTION dir = X_DIRECTION_BULLISH // + int range = 2 // ) { // bool result = false; // - zone.Clean(); - - // - result = bar.IsValid() && - (dir == X_DIRECTION_BULLISH || - dir == X_DIRECTION_BEARISH); - if (!result) + if (range < 1) { - return result; - } - - // - bool isBullish = dir == X_DIRECTION_BULLISH; - - // - zone.from = bar.time; - zone.to = TimeCurrent(); - zone.prefix = "XBarZone"; - - // - zone.upper = isBullish - ? bar.high - : bar.GetDown(); - - // - zone.lower = isBullish - ? bar.GetUp() - : bar.low; - - // - result = zone.IsValid(); - - // - return result; - } - - // - // Regular ... - - /** - * Check a Zone is Rejected in Specified Direction or not ... - * - * @param bar: XOHCL instance, Specified Bar ... - * @param zone: XZone instance, Specified Zone ... - * @param dir: ENUM_X_DIRECTION member, Specified Rejection Direction ... - * - * @return ( bool ) - */ - bool IsRejected( - XOHCL &bar, - XZone &zone, - ENUM_X_DIRECTION dir // - ) - { - // - bool result = false; - - // - result = bar.IsValid() && - zone.IsValid() && - (dir == X_DIRECTION_BULLISH || - dir == X_DIRECTION_BEARISH); - if (!result) - { - return result; - } - - // - bool isBullish = dir == X_DIRECTION_BULLISH; - - // - ENUM_X_DIRECTION rejectionDir; - bool isRejection = IsRejectionBar( - rejectionDir, - bar, - 40 // - ); - bool isBullishRejection = isRejection && - rejectionDir == X_DIRECTION_BULLISH; - bool isBearishRejection = isRejection && - rejectionDir == X_DIRECTION_BEARISH; - - // - result = isRejection && - rejectionDir == dir && - (isBullishRejection - ? bar.low < zone.upper && - bar.low > zone.lower - : bar.high > zone.lower && - bar.high < zone.upper); - - // - return result; - } - - /** - * Check a Zone is Breaked in Specified Direction or not ... - * - * @param bar: XOHCL instance, Specified Bar ... - * @param zone: XZone instance, Specified Zone ... - * @param dir: ENUM_X_DIRECTION member, Specified Rejection Direction ... - * - * @return ( bool ) - */ - bool IsBreaked( - XOHCL &bar, - XZone &zone, - ENUM_X_DIRECTION dir, - bool forceBody = true // - ) - { - // - bool result = false; - - // - result = bar.IsValid() && - zone.IsValid() && - (dir == X_DIRECTION_BULLISH || - dir == X_DIRECTION_BEARISH); - if (!result) - { - return result; - } - - // - bool isBullish = dir == X_DIRECTION_BULLISH; - - // - ENUM_X_DIRECTION momentumDir; - bool isMomentum = IsMomentumBar( - momentumDir, - bar, - 50 // - ); - bool isBullishBreaked = isMomentum && - momentumDir == X_DIRECTION_BULLISH; - bool isBearishBreaked = isMomentum && - momentumDir == X_DIRECTION_BEARISH; - - // - result = isMomentum && - momentumDir == dir && - (isBullishBreaked - ? bar.IsBullish() && - bar.low < zone.lower && - bar.high > zone.upper - : bar.IsBearish() && - bar.high > zone.lower && - bar.low < zone.lower); - if (result && - forceBody) - { - // - result = isBullishBreaked - ? bar.IsBullish() && - bar.GetUp() > zone.upper && - bar.GetDown() < zone.lower - : bar.IsBearish() && - bar.GetUp() > zone.upper && - bar.GetDown() < zone.lower; - } - - // - return result; - } - - // - // Rejection Bar ... - - /** - * Check Specific Bar is Rejection Bar or not ... - * - * @param dir: ENUM_X_DIRECTION member, Specified Direction ... - * @param bar: XOHCL instance, Specified Bar ... - * @param strength: Double, Specified Shadow Percent Range ... - * - * @return ( bool ) - */ - bool IsRejectionBar( - ENUM_X_DIRECTION &dir, - XOHCL &bar, - double strength // - ) - { - // - bool result = false; - - // - if (strength < 20) - { - strength = 20; - } - - // - dir = X_DIRECTION_NONE; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - double barLowShadow = bar.GetLowShadow(); - double barHighShadow = bar.GetHighShadow(); - double barRange = bar.GetRange(); - double barRangePercent = barRange / 100; - - // - bool isBullishRejectionBar = - barLowShadow > barHighShadow && - barLowShadow > barRangePercent * strength; - - // - bool isBearishRejectionBar = - barHighShadow > barLowShadow && - barHighShadow > barRangePercent * strength; - - // - result = isBullishRejectionBar || - isBearishRejectionBar; - if (result) - { - // - dir = isBullishRejectionBar - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - } - - // - return result; - } - - /** - * Check Specific Bar is Bullish Rejection Bar or not ... - * - * @param bar: XOHCL instance, Specified Bar ... - * @param strength: Double, Specified Shadow Percent Range ... - * - * @return ( bool ) - */ - bool IsBullishRejectionBar( - XOHCL &bar, - double strength = 40 // - ) - { - // - bool result = false; - - // - ENUM_X_DIRECTION dir; - result = IsRejectionBar( - dir, - bar, - strength // - ); - result = - result && - dir == X_DIRECTION_BULLISH; - - // - return result; - } - - /** - * Check Specific Bar is Bearish Rejection Bar or not ... - * - * @param bar: XOHCL instance, Specified Bar ... - * @param strength: Double, Specified Shadow Percent Range ... - * - * @return ( bool ) - */ - bool IsBearishRejectionBar( - XOHCL &bar, - double strength = 40 // - ) - { - // - bool result = false; - - // - ENUM_X_DIRECTION dir; - result = IsRejectionBar( - dir, - bar, - strength // - ); - result = - result && - dir == X_DIRECTION_BEARISH; - - // - return result; - } - - // - // Momentum Bar ... - - /** - * Check Specific Bar is Momentum Bar or not ... - * - * @param dir: ENUM_X_DIRECTION member, Specified Direction ... - * @param bar: XOHCL instance, Specified Bar ... - * @param strength: Double, Specified Shadow Percent Range ... - * - * @return ( bool ) - */ - bool IsMomentumBar( - ENUM_X_DIRECTION &dir, - XOHCL &bar, - double strength // - ) - { - // - bool result = false; - - // - if (strength < 50) - { - strength = 50; - } - - // - dir = X_DIRECTION_NONE; - - // - double rangePercent = GetBarRangePercent(bar); - bool isStrong = bar.GetBody() > rangePercent * strength; - - // - result = isStrong; - if (result) - { - // - dir = bar.IsBullish() - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - } - - // - return result; - } - - /** - * Check Specific Bar is Bullish Momentum Bar or not ... - * - * @param bar: XOHCL instance, Specified Bar ... - * @param strength: Double, Specified Shadow Percent Range ... - * - * @return ( bool ) - */ - bool IsBullishMomentumBar( - XOHCL &bar, - double strength = 40 // - ) - { - // - bool result = false; - - // - ENUM_X_DIRECTION dir; - result = IsMomentumBar( - dir, - bar, - strength // - ); - result = - result && - dir == X_DIRECTION_BULLISH; - - // - return result; - } - - /** - * Check Specific Bar is Bearish Momentum Bar or not ... - * - * @param bar: XOHCL instance, Specified Bar ... - * @param strength: Double, Specified Shadow Percent Range ... - * - * @return ( bool ) - */ - bool IsBearishMomentumBar( - XOHCL &bar, - double strength = 40 // - ) - { - // - bool result = false; - - // - ENUM_X_DIRECTION dir; - result = IsMomentumBar( - dir, - bar, - strength // - ); - result = - result && - dir == X_DIRECTION_BEARISH; - - // - return result; - } - - // - // Engulfing ... - - /** - * Check Bar is Engulfed or not ... - * - * @param dir: ENUM_X_DIRECTION member, Specified Direction ... - * @param bar: XOHCL instance, Speciied Bar ... - * @param loopback: Integer, loopback Length ... - * - * @return ( bool ) - */ - bool IsEngulfed( - ENUM_X_DIRECTION &dir, - XOHCL &bar, - int loopback // - ) - { - // - bool result = false; - - // - dir = X_DIRECTION_NONE; - - // - int hhIDX = 0; - double hh = 0; - - // - int llIDX = 0; - double ll = 0; - - // - result = CalculateLoopbackHLData( - hhIDX, - hh, - llIDX, - ll, - bar, - loopback // - ); - if (!result) - { - return result; - } - - // - result = bar.GetDown() < ll && - bar.GetUp() > hh; - if (result) - { - // - dir = bar.IsBullish() - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - } - - // - return result; - } - - /** - * Check Bar is Bullish Engulfed or not ... - * - * @param bar: XOHCL instance, Speciied Bar ... - * @param loopback: Integer, loopback Length ... - * - * @return ( bool ) - */ - bool IsBullishEngulfed( - XOHCL &bar, - int loopback = 2 // - ) - { - // - bool result = false; - - // - ENUM_X_DIRECTION dir; - result = IsEngulfed( - dir, - bar, - loopback // - ); - result = - result && - dir == X_DIRECTION_BULLISH; - - // - return result; - } - - /** - * Check Bar is Bearish Engulfed or not ... - * - * @param bar: XOHCL instance, Speciied Bar ... - * @param loopback: Integer, loopback Length ... - * - * @return ( bool ) - */ - bool IsBearishEngulfed( - XOHCL &bar, - int loopback = 2 // - ) - { - // - bool result = false; - - // - ENUM_X_DIRECTION dir; - result = IsEngulfed( - dir, - bar, - loopback // - ); - result = - result && - dir == X_DIRECTION_BEARISH; - - // - return result; - } - - // - // Bar CHOCH ... - - /** - * Check Specified Bar Has CHOCH or not ... - * - * @param dir: ENUM_X_DIRECTION member, Specified Direction ... - * @param bar: XOHCL instance, Speciied Bar ... - * @param loopback: Integer, loopback Length ... - * @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ... - * - * @return ( bool ) - */ - bool HasCHOCH( - ENUM_X_DIRECTION &dir, - XOHCL &bar, - int loopback = 2, - bool forceBody = false // - ) - { - // - bool result = false; - - // - dir = X_DIRECTION_NONE; - - // - if (loopback < 1) - { - loopback = 1; + range = 1; } // @@ -985,214 +427,82 @@ class XCBarAnalyser : public XSCBase return result; } + // + int index = bar.Index(); + result = range > 0 && + index >= range; + if (!result) + { + return result; + } + // string symbol = bar.symbol; ENUM_TIMEFRAMES period = bar.period; // - // Calculate Loopback Data ... - int index = -1; - int start = -1; - int end = -1; - int count = -1; - result = CalculateLoopBackData( - index, - start, - end, - count, - bar, - loopback // - ); - if (!result) - { - return result; - } - - // - // Calculate Loopback HH and LL Data ... - int hhIDX = -1; - double hh = -1; - int llIDX = -1; - double ll = -1; - result = CalculateLoopbackHLData( - hhIDX, - hh, - llIDX, - ll, - bar, - loopback // - ); - if (!result) - { - return result; - } - - // - bool isBullishDirection = - bar.high > hh && - bar.low > ll; - bool isBearishDirection = - bar.high < hh && - bar.low < ll; - result = isBullishDirection || - isBearishDirection; - if (!result) - { - return result; - } - - // - if (forceBody) + for (int i = 1; i <= range; i++) { // - isBullishDirection = - bar.GetUp() > hh && - bar.GetDown() > ll; - isBearishDirection = - bar.GetUp() < hh && - bar.GetDown() < ll; - result = isBullishDirection || - isBearishDirection; + // Prev Bar ... + XOHCL iPrevBar; + result = iPrevBar.Init( + symbol, + period, + index + i // + ); if (!result) { - return result; + break; + } + + // + // Next Bar ... + XOHCL iNextBar; + result = iNextBar.Init( + symbol, + period, + index - i // + ); + if (!result) + { + break; + } + + // + result = bar.high >= iPrevBar.high && + bar.high >= iNextBar.high; + if (!result) + { + break; } } - // - // Check Bar's Direction in related to CHOCH Direction ... - result = - isBullishDirection - ? bar.IsBullish() - : bar.IsBearish(); - if (!result) - { - return result; - } - - // - // Set Direction ... - dir = - isBullishDirection - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - - // - // Check Loopback End Bar ... - XOHCL endBar; - result = endBar.Init( - symbol, - period, - end - 1 // - ); - if (!result) - { - return result; - } - - // - // End Bar Must be InDirect by Specified Bar ... - result = - isBullishDirection - ? endBar.IsBearish() - : endBar.IsBullish(); - - // - // Check Loopback for Directional Bars ... - // return result; } /** - * Check Specified Bar Has Bullish CHOCH or not ... + * Check Specified Bar is Swing Low or not ... * - * @param bar: XOHCL instance, Speciied Bar ... - * @param loopback: Integer, loopback Length ... - * @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ... + * @param bar: XOHCL instnce ... + * @param range: Integer, Specified Range ... * * @return ( bool ) */ - bool HasBullishCHOCH( + bool IsSwingLow( XOHCL &bar, - int loopback = 2, - bool forceBody = false // + int range = 2 // ) { // bool result = false; // - ENUM_X_DIRECTION dir; - result = HasCHOCH( - dir, - bar, - loopback, - forceBody // - ); - result = - result && - dir == X_DIRECTION_BULLISH; - - // - return result; - } - - /** - * Check Specified Bar Has Bearish CHOCH or not ... - * - * @param bar: XOHCL instance, Speciied Bar ... - * @param loopback: Integer, loopback Length ... - * @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ... - * - * @return ( bool ) - */ - bool HasBearishCHOCH( - XOHCL &bar, - int loopback = 2, - bool forceBody = false // - ) - { - // - bool result = false; - - // - ENUM_X_DIRECTION dir; - result = HasCHOCH( - dir, - bar, - loopback, - forceBody // - ); - result = - result && - dir == X_DIRECTION_BEARISH; - - // - return result; - } - - // - // Directions ... - - /** - * Check Specified Bar Possible Direction Pressure ... - * - * @param dir: ENUM_X_DIRECTION member ... - * @param bar: XOHCL instance, Specified Bar ... - * - * @return ( bool ) - */ - bool HasDirection( - ENUM_X_DIRECTION &dir, - XOHCL &bar // - ) - { - // - bool result = false; - - // - dir = X_DIRECTION_NONE; + if (range < 1) + { + range = 1; + } // result = bar.IsValid(); @@ -1202,139 +512,55 @@ class XCBarAnalyser : public XSCBase } // - // Check Bar isExtended or not ... - bool isExtended = IsExtended( - bar, - 3 // - ); - - // - // Check Rejection ... - ENUM_X_DIRECTION rejectionDir; - bool isRejection = IsRejectionBar(rejectionDir, bar, 40); - bool isBullishRejection = isRejection && - rejectionDir == X_DIRECTION_BULLISH; - bool isBearishRejection = isRejection && - rejectionDir == X_DIRECTION_BEARISH; - - // - // Check Momentum ... - ENUM_X_DIRECTION momentumDir; - bool isMomentum = IsMomentumBar(momentumDir, bar, 40); - bool isBullisMomentumn = isMomentum && - momentumDir == X_DIRECTION_BULLISH; - bool isBearishMomentum = isMomentum && - momentumDir == X_DIRECTION_BEARISH; - - // - // Check Engulfing ... - ENUM_X_DIRECTION engulfDir; - bool isEngulfed = IsEngulfed( - engulfDir, - bar, - 2 // - ); - bool isBullishEngulfed = isEngulfed && - engulfDir == X_DIRECTION_BULLISH; - bool isBearishEngulfed = isEngulfed && - engulfDir == X_DIRECTION_BEARISH; - - // - // Check CHOCH ... - ENUM_X_DIRECTION chochDir; - bool hasCHOCH = HasCHOCH( - chochDir, - bar, - 2, - false // - ); - bool hasBullishCHOCH = hasCHOCH && - chochDir == X_DIRECTION_BULLISH; - bool hasBearishCHOCH = hasCHOCH && - chochDir == X_DIRECTION_BEARISH; - - // - bool hasBullishDirection = - // - isExtended && - (hasBullishCHOCH || - isBullishEngulfed) && - (isBullisMomentumn || - isBullishRejection) - // - ; - - // - bool hasBearishDirection = - // - isExtended && - (hasBearishCHOCH || - isBearishEngulfed) && - (isBearishMomentum || - isBearishRejection) - // - ; - - // - result = hasBullishDirection || - hasBearishDirection; - if (result) + int index = bar.Index(); + result = range > 0 && + index >= range; + if (!result) { - // - dir = hasBullishDirection - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; + return result; } // - return result; - } - - /** - * Check Specified Bar has Possibly Bullish Direction ... - * - * @param bar: XOHCL instance, Specified Bar ... - * - * @return ( virtual bool ) - */ - virtual bool HasBullishDirection( - XOHCL &bar // - ) - { - // - bool result = false; + string symbol = bar.symbol; + ENUM_TIMEFRAMES period = bar.period; // - ENUM_X_DIRECTION dir; - result = HasDirection(dir, bar); - result = - result && - dir == X_DIRECTION_BULLISH; + for (int i = 1; i <= range; i++) + { + // + // Prev Bar ... + XOHCL iPrevBar; + result = iPrevBar.Init( + symbol, + period, + index + i // + ); + if (!result) + { + break; + } - // - return result; - } + // + // Next Bar ... + XOHCL iNextBar; + result = iNextBar.Init( + symbol, + period, + index - i // + ); + if (!result) + { + break; + } - /** - * Check Specified Bar has Possibly Bearish Direction ... - * - * @param bar: XOHCL instance, Specified Bar ... - * - * @return ( virtual bool ) - */ - virtual bool HasBearishhDirection( - XOHCL &bar // - ) - { - // - bool result = false; - - // - ENUM_X_DIRECTION dir; - result = HasDirection(dir, bar); - result = - result && - dir == X_DIRECTION_BEARISH; + // + result = bar.low <= iPrevBar.low && + bar.low <= iNextBar.low; + if (!result) + { + break; + } + } // return result; diff --git a/Classes/x-saherelm.x-poi.class.mq5 b/Classes/x-saherelm.x-poi.class.mq5 index 0442e2c2..0d67e83e 100644 --- a/Classes/x-saherelm.x-poi.class.mq5 +++ b/Classes/x-saherelm.x-poi.class.mq5 @@ -25,6 +25,7 @@ // #include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" #include "../Classes/x-saherelm.x-poi.drawer.class.mq5" #include "../Libraries/x-saherelm.x-poi.lib.mq5" @@ -239,7 +240,10 @@ class XCPOIDetector : public XCBaseAlert int zIndex = 0; int cIndex = zIndex + 1; int pIndex = cIndex + 1; - int ppIndex = pIndex + 1; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); // datetime cTime = TimeCurrent(); @@ -247,8 +251,8 @@ class XCPOIDetector : public XCBaseAlert // XOHCL zBar; bool isInited = zBar.Init( - mSymbol, - mPeriod, + symbol, + period, zIndex // ); if (!isInited) @@ -259,8 +263,8 @@ class XCPOIDetector : public XCBaseAlert // XOHCL cBar; isInited = cBar.Init( - mSymbol, - mPeriod, + symbol, + period, cIndex // ); if (!isInited) @@ -269,39 +273,79 @@ class XCPOIDetector : public XCBaseAlert } // - XOHCL pBar; - isInited = pBar.Init( - mSymbol, - mPeriod, - pIndex // - ); - if (!isInited) - { - return result; - } + // POI Detecting ... + bool isDetect = false; // - XOHCL ppBar; - isInited = ppBar.Init( - mSymbol, - mPeriod, - ppIndex // - ); - if (!isInited) + // Swings ... + int swingRange = SwingRange(); + if (swingRange > 0) { - return result; - } + // + XOHCL swingBar; + isInited = swingBar.Init( + symbol, + period, + zIndex + swingRange // + ); + if (isInited) + { + // + // Swing High ... + isDetect = DetectSwingHigh(swingBar); + if (isDetect) + { + // + ENUM_XPOI_EVENTS event = X_SWING_HIGH_DETECTED; + XCSwing *param; + bool hasItem = GetLastItem( + param, + mSwingHighs // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } - // - XOHCL zDayBar; - isInited = zDayBar.Init( - mSymbol, - PERIOD_D1, - zIndex // - ); - if (!isInited) - { - return result; + // + Add( + event, + state // + ); + } + + // + // Swing Low ... + isDetect = DetectSwingLow(swingBar); + if (isDetect) + { + // + ENUM_XPOI_EVENTS event = X_SWING_LOW_DETECTED; + XCSwing *param; + bool hasItem = GetLastItem( + param, + mSwingLows // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + } } // @@ -355,6 +399,20 @@ class XCPOIDetector : public XCBaseAlert // // Event Listeners ... + /** + * Add Event Listener ... + * + * @param listener: TOnPOIEvent instance ... + */ + void AddEventListener(TOnPOIEvent listener) + { + // + Add( + listener, + mEventListeners // + ); + } + // // Destroy ... @@ -363,6 +421,9 @@ class XCPOIDetector : public XCBaseAlert */ void DestroyPOIs() { + // + Clean(mSwingHighs); + Clean(mSwingLows); } /** @@ -377,6 +438,7 @@ class XCPOIDetector : public XCBaseAlert */ void DestroyEventListeners() { + Clean(mEventListeners); } // @@ -463,10 +525,18 @@ class XCPOIDetector : public XCBaseAlert // // Swing Highs ... swingHighsCount = DetectRequiredSwingHighs(barIndex); + if (swingHighsCount == requiredPOIs) + { + ArrayReverse(mSwingHighs); + } // // Swing Lows ... swingLowsCount = DetectRequiredSwingLows(barIndex); + if (swingHighsCount == requiredPOIs) + { + ArrayReverse(mSwingLows); + } // canContinue = @@ -486,10 +556,6 @@ class XCPOIDetector : public XCBaseAlert } } - // - swingHighsCount = ArraySize(mSwingHighs); - swingLowsCount = ArraySize(mSwingLows); - // // Unlocking Detector ... Unlock(); @@ -507,11 +573,11 @@ class XCPOIDetector : public XCBaseAlert return; } - // // + // + int swingHighsCount = ArraySize(mSwingHighs); + int swingLowsCount = ArraySize(mSwingLows); // int tradingDaysCount = ArraySize(mTradingDays); // int marketSessionsCount = ArraySize(mMarketSessions); - // int swingHighsCount = ArraySize(mSwingHighs); - // int swingLowsCount = ArraySize(mSwingLows); // int momentumBarsCount = ArraySize(mMomentumBars); // int rejectionBarsCount = ArraySize(mRejectionBars); // int supportZonesCount = ArraySize(mSupportZones); @@ -523,11 +589,38 @@ class XCPOIDetector : public XCBaseAlert // int bullishFVGsCount = ArraySize(mBullishFVGs); // int bearishFVGsCount = ArraySize(mBearishFVGs); - // // - // int from = 0; - // int requiredPOIs = MaxNumberOfRequiredPOIs(); - // int count = maxAllowed - requiredPOIs; - // int to = count - 1; + // + int from = 0; + int requiredPOIs = MaxNumberOfRequiredPOIs(); + int count = maxAllowed - requiredPOIs; + int to = count - 1; + + // + // Swings ... + + // + // Swing Highs ... + if (swingHighsCount >= maxAllowed) + { + // + ArrayRemove( + mSwingHighs, + from, + count // + ); + } + + // + // Swing Lows ... + if (swingLowsCount >= maxAllowed) + { + // + ArrayRemove( + mSwingLows, + from, + count // + ); + } // // // // Trading Days ... @@ -601,45 +694,6 @@ class XCPOIDetector : public XCBaseAlert // ); // } - // // - // // Swing High and Low (s) ... - - // // - // // Swing Highs ... - // if (swingHighsCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mSwingHighs, - // from, - // count // - // ); - - // // - // mSwingHighObjects.DeleteRange( - // from, - // to // - // ); - // } - - // // - // // Swing Lows ... - // if (swingLowsCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mSwingLows, - // from, - // count // - // ); - - // // - // mSwingLowObjects.DeleteRange( - // from, - // to // - // ); - // } - // // // // Support and Resistance Zones ... @@ -799,6 +853,35 @@ class XCPOIDetector : public XCBaseAlert // } + /** + * Notify Event Listeners ... + * + * @param event: ENUM_XPOI_EVENTS member, Specified Occured Event ... + * @param param: XCBasePOI implementation, Specified Event Object ... + */ + void NotifyEventListeners( + ENUM_XPOI_EVENTS event, + XCBasePOI *param // + ) + { + // + int count = ArraySize(mEventListeners); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + mEventListeners[i]( + event, + param // + ); + } + } + void AddObjectIfNotExists(XCBaseObject *object) { // @@ -847,8 +930,12 @@ class XCPOIDetector : public XCBaseAlert int mMaxNumberOfRequiredPOIs; // Max Allowed Number of POI(s) which Must Find at Initializion Time ... // - CArrayObj mDrawnObjects; // Drawn Objects ... - XBarTracker mBarTracker; // Market Bar Tracker ... + CArrayObj mDrawnObjects; // Drawn Objects ... + XBarTracker mBarTracker; // Market Bar Tracker ... + XCBarAnalyser mBarAnalyser; // Bar Analyser ... + + // + TOnPOIEvent mEventListeners[]; // Event Listeners ... // // POI Props ... @@ -865,8 +952,80 @@ class XCPOIDetector : public XCBaseAlert // // Swing High ... + + // XCSwing *mSwingHighs[]; // Holds Founded Swing Highs ... + /** + * Detect Swing High ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectSwingHigh(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SwingRange(); + int barIndex = bar.Index(); + result = range > 0 && + barIndex >= range; + if (!result) + { + return result; + } + + // + result = mBarAnalyser.IsSwingHigh( + bar, + range // + ); + if (result) + { + // + XCSwing *swing; + swing = new XCSwing(); + result = swing.Init( + bar, + X_POI_SWING_HIGH // + ); + + // + if (result) + { + // + Add( + swing, + mSwingHighs // + ); + + // + XCSwingHighObject *iObj; + bool isCreated = mDrawer.CreateSwingHigh( + swing, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + + // + return result; + } + /** * Detect Required Swing Highs ... * @@ -926,61 +1085,67 @@ class XCPOIDetector : public XCBaseAlert } // - bool isSwing = true; - for (int i = 1; i <= range; i++) + DetectSwingHigh(bar); + + // + result = ArraySize(mSwingHighs); + + // + return result; + } + + // + // Swing Low ... + + // + XCSwing *mSwingLows[]; // Holds Founded Swing Lows ... + + /** + * Detect Swing Low ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectSwingLow(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) { - // - // Prev Bar ... - XOHCL iPrevBar; - isInited = iPrevBar.Init( - symbol, - period, - barIndex + i // - ); - if (!isInited) - { - // - isSwing = false; - break; - } - - // - // Next Bar ... - XOHCL iNextBar; - isInited = iNextBar.Init( - symbol, - period, - barIndex - i // - ); - if (!isInited) - { - // - isSwing = false; - break; - } - - // - isSwing = bar.high >= iPrevBar.high && - bar.high >= iNextBar.high; - if (!isSwing) - { - break; - } + return result; } // - if (isSwing) + int range = SwingRange(); + int barIndex = bar.Index(); + result = range > 0 && + barIndex >= range; + if (!result) + { + return result; + } + + // + result = mBarAnalyser.IsSwingLow( + bar, + range // + ); + if (result) { // XCSwing *swing; swing = new XCSwing(); - isInited = swing.Init( + result = swing.Init( bar, - X_POI_SWING_HIGH // + X_POI_SWING_LOW // ); // - if (isInited) + if (result) { // Add( @@ -989,8 +1154,8 @@ class XCPOIDetector : public XCBaseAlert ); // - XCSwingHighObject *iObj; - bool isCreated = mDrawer.CreateSwingHigh( + XCSwingLowObject *iObj; + bool isCreated = mDrawer.CreateSwingLow( swing, iObj // ); @@ -1001,17 +1166,10 @@ class XCPOIDetector : public XCBaseAlert } } - // - result = ArraySize(mSwingHighs); - // return result; } - // - // Swing Low ... - XCSwing *mSwingLows[]; // Holds Founded Swing Lows ... - /** * Detect Required Swing Lows ... * @@ -1071,80 +1229,7 @@ class XCPOIDetector : public XCBaseAlert } // - bool isSwing = true; - for (int i = 1; i <= range; i++) - { - // - // Prev Bar ... - XOHCL iPrevBar; - isInited = iPrevBar.Init( - symbol, - period, - barIndex + i // - ); - if (!isInited) - { - // - isSwing = false; - break; - } - - // - // Next Bar ... - XOHCL iNextBar; - isInited = iNextBar.Init( - symbol, - period, - barIndex - i // - ); - if (!isInited) - { - // - isSwing = false; - break; - } - - // - isSwing = bar.low <= iPrevBar.low && - bar.low <= iNextBar.low; - if (!isSwing) - { - break; - } - } - - // - if (isSwing) - { - // - XCSwing *swing; - swing = new XCSwing(); - isInited = swing.Init( - bar, - X_POI_SWING_LOW // - ); - - // - if (isInited) - { - // - Add( - swing, - mSwingLows // - ); - - // - XCSwingLowObject *iObj; - bool isCreated = mDrawer.CreateSwingLow( - swing, - iObj // - ); - if (isCreated) - { - AddObjectIfNotExists(iObj); - } - } - } + DetectSwingLow(bar); // result = ArraySize(mSwingHighs); diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index 46c720b6..c7d7a961 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -1411,14 +1411,14 @@ class XCPOIDrawer : public XCBase SubWindowIdentification(0); // - SwingLowWidth(1); + SwingLowWidth(2); SwingLowArrow(108); - SwingLowColor(clrLime); + SwingLowColor(clrAqua); // - SwingHighWidth(1); + SwingHighWidth(2); SwingHighArrow(108); - SwingHighColor(clrRed); + SwingHighColor(clrMagenta); // BullishMomentumBarWidth(1); diff --git a/Documents/BKP/x-saherelm.x-bar.analyser.class.mq5 b/Documents/BKP/x-saherelm.x-bar.analyser.class.mq5 new file mode 100644 index 00000000..b11cb8ee --- /dev/null +++ b/Documents/BKP/x-saherelm.x-bar.analyser.class.mq5 @@ -0,0 +1,1360 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XPOI +// Description: Bar Analysing ... +// +// 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 "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Implementations ... +class XCBarAnalyser : public XSCBase +{ + // + public: + // + + // + // Constructor(s) ... + void XCBarAnalyser() + { + } + + // + // Deconstructor ... + void ~XCBarAnalyser() + { + } + + // + // Getter(s) / Setter(s) ... + + // + // Providers ... + + // + // Actions ... + + /** + * Calculate Loopback Data for Specific Bar ... + * + * @param index: Integer, Bar Current Index ... + * @param start: Integer, Start of Loopback ... + * @param end: Integer, End of Loopback ... + * @param count: Integer, Number of Calculating Bars ... + * @param bar: XOHCL instance, Specified Bar ... + * @param loopback: Integer, Loopback Length ... + * @return ( bool ) + */ + bool CalculateLoopBackData( + int &index, + int &start, + int &end, + int &count, + XOHCL &bar, + int loopback = 1 // + ) + { + // + bool result = false; + + // + if (loopback < 1) + { + loopback = 1; + } + + // + index = -1; + start = -1; + end = -1; + count = -1; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + index = bar.Index(); + start = index + 1; + end = start + loopback; + count = end - start; + result = count >= 1; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Retrieve Loopback HH & LL Data ... + * + * @param hhIDX: Integer, HH Index ... + * @param hh: Double, HH Value ... + * @param llIDX: Integer, LL Index ... + * @param ll: Double, LL Value ... + * @param bar: XOHCL instance ... + * @param loopback: Integer, Loopback Length ... + * + * @return ( bool ) + */ + bool CalculateLoopbackHLData( + int &hhIDX, + double &hh, + int &llIDX, + double &ll, + XOHCL &bar, + int loopback // + ) + { + // + bool result = false; + + // + if (loopback < 1) + { + loopback = 1; + } + + // + int index = -1; + int start = -1; + int end = -1; + int count = -1; + result = CalculateLoopBackData( + index, + start, + end, + count, + bar, + loopback // + ); + if (!result) + { + return result; + } + + // + hhIDX = iHighest( + bar.symbol, + bar.period, + MODE_HIGH, + count, + start // + ); + result = IsValidIndex(hhIDX); + if (!result) + { + return result; + } + + // + llIDX = iLowest( + bar.symbol, + bar.period, + MODE_LOW, + count, + start // + ); + result = IsValidIndex(llIDX); + if (!result) + { + return result; + } + + // + hh = iHigh( + bar.symbol, + bar.period, + hhIDX // + ); + ll = iLow( + bar.symbol, + bar.period, + llIDX // + ); + + // + return result; + } + + /** + * Calculate Bar Range ... + * + * @param bar: XOHCL instance ... + * + * @return ( double ) + */ + double GetBarRangePercent(XOHCL &bar) + { + // + double result = 0; + + // + result = bar.GetRange() / 100; + + // + return result; + } + + // + // Commons ... + + /** + * Check Specified Bar's Range is Extended or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param loopback: Integer, Loopback Length ... + * + * @return ( bool ) + */ + bool HasExtendedRange( + XOHCL &bar, + int loopback = 3 // + ) + { + // + bool result = false; + + // + if (loopback < 3) + { + loopback = 3; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = bar.Index(); + int start = index + 1; + int end = start + loopback; + int count = end - start; + result = count >= 1; + if (!result) + { + return result; + } + + // + double sum = 0; + XOHCL iBar = bar; + for (int i = start; i < end; i++) + { + // + bool isRetrieved = iBar.GetPreviousBar(iBar); + if (!isRetrieved) + { + continue; + } + + // + sum += iBar.GetRange(); + } + + // + result = sum > 0; + if (!result) + { + return result; + } + + // + double avg = sum / count; + + // + result = bar.GetRange() >= avg; + + // + return result; + } + + /** + * Check Specified Bar's Body is Extended or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param loopback: Integer, Loopback Length ... + * + * @return ( bool ) + */ + bool HasExtendedBody( + XOHCL &bar, + int loopback = 3 // + ) + { + // + bool result = false; + + // + if (loopback < 3) + { + loopback = 3; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = bar.Index(); + int start = index + 1; + int end = start + loopback; + int count = end - start; + result = count >= 1; + if (!result) + { + return result; + } + + // + double sum = 0; + XOHCL iBar = bar; + for (int i = start; i < end; i++) + { + // + bool isRetrieved = iBar.GetPreviousBar(iBar); + if (!isRetrieved) + { + continue; + } + + // + sum += iBar.GetBody(); + } + + // + result = sum > 0; + if (!result) + { + return result; + } + + // + double avg = sum / count; + + // + result = bar.GetBody() >= avg; + + // + return result; + } + + /** + * Check Specified Bar's Body and Range is Extended or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param loopback: Integer, Loopback Length ... + * + * @return ( bool ) + */ + bool IsExtended( + XOHCL &bar, + int loopback = 3 // + ) + { + // + bool result = false; + + // + bool hasExtendedBody = HasExtendedBody(bar, loopback); + bool hasExtendedRange = HasExtendedRange(bar, loopback); + result = hasExtendedBody && + hasExtendedRange; + + // + return result; + } + + /** + * Converts an Specified Bar to Zone ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param zone: XZone instance, Converted Zone Reference ... + * @param dir: ENUM_X_DIRECTION member, Specified Bar Type to Convertion ... + * + * @return ( bool ) + */ + bool ToZone( + XOHCL &bar, + XZone &zone, + ENUM_X_DIRECTION dir = X_DIRECTION_BULLISH // + ) + { + // + bool result = false; + + // + zone.Clean(); + + // + result = bar.IsValid() && + (dir == X_DIRECTION_BULLISH || + dir == X_DIRECTION_BEARISH); + if (!result) + { + return result; + } + + // + bool isBullish = dir == X_DIRECTION_BULLISH; + + // + zone.from = bar.time; + zone.to = TimeCurrent(); + zone.prefix = "XBarZone"; + + // + zone.upper = isBullish + ? bar.high + : bar.GetDown(); + + // + zone.lower = isBullish + ? bar.GetUp() + : bar.low; + + // + result = zone.IsValid(); + + // + return result; + } + + // + // Regular ... + + /** + * Check a Zone is Rejected in Specified Direction or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param zone: XZone instance, Specified Zone ... + * @param dir: ENUM_X_DIRECTION member, Specified Rejection Direction ... + * + * @return ( bool ) + */ + bool IsRejected( + XOHCL &bar, + XZone &zone, + ENUM_X_DIRECTION dir // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + zone.IsValid() && + (dir == X_DIRECTION_BULLISH || + dir == X_DIRECTION_BEARISH); + if (!result) + { + return result; + } + + // + bool isBullish = dir == X_DIRECTION_BULLISH; + + // + ENUM_X_DIRECTION rejectionDir; + bool isRejection = IsRejectionBar( + rejectionDir, + bar, + 40 // + ); + bool isBullishRejection = isRejection && + rejectionDir == X_DIRECTION_BULLISH; + bool isBearishRejection = isRejection && + rejectionDir == X_DIRECTION_BEARISH; + + // + result = isRejection && + rejectionDir == dir && + (isBullishRejection + ? bar.low < zone.upper && + bar.low > zone.lower + : bar.high > zone.lower && + bar.high < zone.upper); + + // + return result; + } + + /** + * Check a Zone is Breaked in Specified Direction or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param zone: XZone instance, Specified Zone ... + * @param dir: ENUM_X_DIRECTION member, Specified Rejection Direction ... + * + * @return ( bool ) + */ + bool IsBreaked( + XOHCL &bar, + XZone &zone, + ENUM_X_DIRECTION dir, + bool forceBody = true // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + zone.IsValid() && + (dir == X_DIRECTION_BULLISH || + dir == X_DIRECTION_BEARISH); + if (!result) + { + return result; + } + + // + bool isBullish = dir == X_DIRECTION_BULLISH; + + // + ENUM_X_DIRECTION momentumDir; + bool isMomentum = IsMomentumBar( + momentumDir, + bar, + 50 // + ); + bool isBullishBreaked = isMomentum && + momentumDir == X_DIRECTION_BULLISH; + bool isBearishBreaked = isMomentum && + momentumDir == X_DIRECTION_BEARISH; + + // + result = isMomentum && + momentumDir == dir && + (isBullishBreaked + ? bar.IsBullish() && + bar.low < zone.lower && + bar.high > zone.upper + : bar.IsBearish() && + bar.high > zone.lower && + bar.low < zone.lower); + if (result && + forceBody) + { + // + result = isBullishBreaked + ? bar.IsBullish() && + bar.GetUp() > zone.upper && + bar.GetDown() < zone.lower + : bar.IsBearish() && + bar.GetUp() > zone.upper && + bar.GetDown() < zone.lower; + } + + // + return result; + } + + // + // Rejection Bar ... + + /** + * Check Specific Bar is Rejection Bar or not ... + * + * @param dir: ENUM_X_DIRECTION member, Specified Direction ... + * @param bar: XOHCL instance, Specified Bar ... + * @param strength: Double, Specified Shadow Percent Range ... + * + * @return ( bool ) + */ + bool IsRejectionBar( + ENUM_X_DIRECTION &dir, + XOHCL &bar, + double strength // + ) + { + // + bool result = false; + + // + if (strength < 20) + { + strength = 20; + } + + // + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double barLowShadow = bar.GetLowShadow(); + double barHighShadow = bar.GetHighShadow(); + double barRange = bar.GetRange(); + double barRangePercent = barRange / 100; + + // + bool isBullishRejectionBar = + barLowShadow > barHighShadow && + barLowShadow > barRangePercent * strength; + + // + bool isBearishRejectionBar = + barHighShadow > barLowShadow && + barHighShadow > barRangePercent * strength; + + // + result = isBullishRejectionBar || + isBearishRejectionBar; + if (result) + { + // + dir = isBullishRejectionBar + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + /** + * Check Specific Bar is Bullish Rejection Bar or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param strength: Double, Specified Shadow Percent Range ... + * + * @return ( bool ) + */ + bool IsBullishRejectionBar( + XOHCL &bar, + double strength = 40 // + ) + { + // + bool result = false; + + // + ENUM_X_DIRECTION dir; + result = IsRejectionBar( + dir, + bar, + strength // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + + // + return result; + } + + /** + * Check Specific Bar is Bearish Rejection Bar or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param strength: Double, Specified Shadow Percent Range ... + * + * @return ( bool ) + */ + bool IsBearishRejectionBar( + XOHCL &bar, + double strength = 40 // + ) + { + // + bool result = false; + + // + ENUM_X_DIRECTION dir; + result = IsRejectionBar( + dir, + bar, + strength // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Momentum Bar ... + + /** + * Check Specific Bar is Momentum Bar or not ... + * + * @param dir: ENUM_X_DIRECTION member, Specified Direction ... + * @param bar: XOHCL instance, Specified Bar ... + * @param strength: Double, Specified Shadow Percent Range ... + * + * @return ( bool ) + */ + bool IsMomentumBar( + ENUM_X_DIRECTION &dir, + XOHCL &bar, + double strength // + ) + { + // + bool result = false; + + // + if (strength < 50) + { + strength = 50; + } + + // + dir = X_DIRECTION_NONE; + + // + double rangePercent = GetBarRangePercent(bar); + bool isStrong = bar.GetBody() > rangePercent * strength; + + // + result = isStrong; + if (result) + { + // + dir = bar.IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + /** + * Check Specific Bar is Bullish Momentum Bar or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param strength: Double, Specified Shadow Percent Range ... + * + * @return ( bool ) + */ + bool IsBullishMomentumBar( + XOHCL &bar, + double strength = 40 // + ) + { + // + bool result = false; + + // + ENUM_X_DIRECTION dir; + result = IsMomentumBar( + dir, + bar, + strength // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + + // + return result; + } + + /** + * Check Specific Bar is Bearish Momentum Bar or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param strength: Double, Specified Shadow Percent Range ... + * + * @return ( bool ) + */ + bool IsBearishMomentumBar( + XOHCL &bar, + double strength = 40 // + ) + { + // + bool result = false; + + // + ENUM_X_DIRECTION dir; + result = IsMomentumBar( + dir, + bar, + strength // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Engulfing ... + + /** + * Check Bar is Engulfed or not ... + * + * @param dir: ENUM_X_DIRECTION member, Specified Direction ... + * @param bar: XOHCL instance, Speciied Bar ... + * @param loopback: Integer, loopback Length ... + * + * @return ( bool ) + */ + bool IsEngulfed( + ENUM_X_DIRECTION &dir, + XOHCL &bar, + int loopback // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + int hhIDX = 0; + double hh = 0; + + // + int llIDX = 0; + double ll = 0; + + // + result = CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + loopback // + ); + if (!result) + { + return result; + } + + // + result = bar.GetDown() < ll && + bar.GetUp() > hh; + if (result) + { + // + dir = bar.IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + /** + * Check Bar is Bullish Engulfed or not ... + * + * @param bar: XOHCL instance, Speciied Bar ... + * @param loopback: Integer, loopback Length ... + * + * @return ( bool ) + */ + bool IsBullishEngulfed( + XOHCL &bar, + int loopback = 2 // + ) + { + // + bool result = false; + + // + ENUM_X_DIRECTION dir; + result = IsEngulfed( + dir, + bar, + loopback // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + + // + return result; + } + + /** + * Check Bar is Bearish Engulfed or not ... + * + * @param bar: XOHCL instance, Speciied Bar ... + * @param loopback: Integer, loopback Length ... + * + * @return ( bool ) + */ + bool IsBearishEngulfed( + XOHCL &bar, + int loopback = 2 // + ) + { + // + bool result = false; + + // + ENUM_X_DIRECTION dir; + result = IsEngulfed( + dir, + bar, + loopback // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Bar CHOCH ... + + /** + * Check Specified Bar Has CHOCH or not ... + * + * @param dir: ENUM_X_DIRECTION member, Specified Direction ... + * @param bar: XOHCL instance, Speciied Bar ... + * @param loopback: Integer, loopback Length ... + * @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ... + * + * @return ( bool ) + */ + bool HasCHOCH( + ENUM_X_DIRECTION &dir, + XOHCL &bar, + int loopback = 2, + bool forceBody = false // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + if (loopback < 1) + { + loopback = 1; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + string symbol = bar.symbol; + ENUM_TIMEFRAMES period = bar.period; + + // + // Calculate Loopback Data ... + int index = -1; + int start = -1; + int end = -1; + int count = -1; + result = CalculateLoopBackData( + index, + start, + end, + count, + bar, + loopback // + ); + if (!result) + { + return result; + } + + // + // Calculate Loopback HH and LL Data ... + int hhIDX = -1; + double hh = -1; + int llIDX = -1; + double ll = -1; + result = CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + loopback // + ); + if (!result) + { + return result; + } + + // + bool isBullishDirection = + bar.high > hh && + bar.low > ll; + bool isBearishDirection = + bar.high < hh && + bar.low < ll; + result = isBullishDirection || + isBearishDirection; + if (!result) + { + return result; + } + + // + if (forceBody) + { + // + isBullishDirection = + bar.GetUp() > hh && + bar.GetDown() > ll; + isBearishDirection = + bar.GetUp() < hh && + bar.GetDown() < ll; + result = isBullishDirection || + isBearishDirection; + if (!result) + { + return result; + } + } + + // + // Check Bar's Direction in related to CHOCH Direction ... + result = + isBullishDirection + ? bar.IsBullish() + : bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Set Direction ... + dir = + isBullishDirection + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Check Loopback End Bar ... + XOHCL endBar; + result = endBar.Init( + symbol, + period, + end - 1 // + ); + if (!result) + { + return result; + } + + // + // End Bar Must be InDirect by Specified Bar ... + result = + isBullishDirection + ? endBar.IsBearish() + : endBar.IsBullish(); + + // + // Check Loopback for Directional Bars ... + + // + return result; + } + + /** + * Check Specified Bar Has Bullish CHOCH or not ... + * + * @param bar: XOHCL instance, Speciied Bar ... + * @param loopback: Integer, loopback Length ... + * @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ... + * + * @return ( bool ) + */ + bool HasBullishCHOCH( + XOHCL &bar, + int loopback = 2, + bool forceBody = false // + ) + { + // + bool result = false; + + // + ENUM_X_DIRECTION dir; + result = HasCHOCH( + dir, + bar, + loopback, + forceBody // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + + // + return result; + } + + /** + * Check Specified Bar Has Bearish CHOCH or not ... + * + * @param bar: XOHCL instance, Speciied Bar ... + * @param loopback: Integer, loopback Length ... + * @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ... + * + * @return ( bool ) + */ + bool HasBearishCHOCH( + XOHCL &bar, + int loopback = 2, + bool forceBody = false // + ) + { + // + bool result = false; + + // + ENUM_X_DIRECTION dir; + result = HasCHOCH( + dir, + bar, + loopback, + forceBody // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Directions ... + + /** + * Check Specified Bar Possible Direction Pressure ... + * + * @param dir: ENUM_X_DIRECTION member ... + * @param bar: XOHCL instance, Specified Bar ... + * + * @return ( bool ) + */ + bool HasDirection( + ENUM_X_DIRECTION &dir, + XOHCL &bar // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Bar isExtended or not ... + bool isExtended = IsExtended( + bar, + 3 // + ); + + // + // Check Rejection ... + ENUM_X_DIRECTION rejectionDir; + bool isRejection = IsRejectionBar(rejectionDir, bar, 40); + bool isBullishRejection = isRejection && + rejectionDir == X_DIRECTION_BULLISH; + bool isBearishRejection = isRejection && + rejectionDir == X_DIRECTION_BEARISH; + + // + // Check Momentum ... + ENUM_X_DIRECTION momentumDir; + bool isMomentum = IsMomentumBar(momentumDir, bar, 40); + bool isBullisMomentumn = isMomentum && + momentumDir == X_DIRECTION_BULLISH; + bool isBearishMomentum = isMomentum && + momentumDir == X_DIRECTION_BEARISH; + + // + // Check Engulfing ... + ENUM_X_DIRECTION engulfDir; + bool isEngulfed = IsEngulfed( + engulfDir, + bar, + 2 // + ); + bool isBullishEngulfed = isEngulfed && + engulfDir == X_DIRECTION_BULLISH; + bool isBearishEngulfed = isEngulfed && + engulfDir == X_DIRECTION_BEARISH; + + // + // Check CHOCH ... + ENUM_X_DIRECTION chochDir; + bool hasCHOCH = HasCHOCH( + chochDir, + bar, + 2, + false // + ); + bool hasBullishCHOCH = hasCHOCH && + chochDir == X_DIRECTION_BULLISH; + bool hasBearishCHOCH = hasCHOCH && + chochDir == X_DIRECTION_BEARISH; + + // + bool hasBullishDirection = + // + isExtended && + (hasBullishCHOCH || + isBullishEngulfed) && + (isBullisMomentumn || + isBullishRejection) + // + ; + + // + bool hasBearishDirection = + // + isExtended && + (hasBearishCHOCH || + isBearishEngulfed) && + (isBearishMomentum || + isBearishRejection) + // + ; + + // + result = hasBullishDirection || + hasBearishDirection; + if (result) + { + // + dir = hasBullishDirection + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + /** + * Check Specified Bar has Possibly Bullish Direction ... + * + * @param bar: XOHCL instance, Specified Bar ... + * + * @return ( virtual bool ) + */ + virtual bool HasBullishDirection( + XOHCL &bar // + ) + { + // + bool result = false; + + // + ENUM_X_DIRECTION dir; + result = HasDirection(dir, bar); + result = + result && + dir == X_DIRECTION_BULLISH; + + // + return result; + } + + /** + * Check Specified Bar has Possibly Bearish Direction ... + * + * @param bar: XOHCL instance, Specified Bar ... + * + * @return ( virtual bool ) + */ + virtual bool HasBearishhDirection( + XOHCL &bar // + ) + { + // + bool result = false; + + // + ENUM_X_DIRECTION dir; + result = HasDirection(dir, bar); + result = + result && + dir == X_DIRECTION_BEARISH; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // + // Props ... + + // + // Actions ... + + // +}; + +// \ No newline at end of file diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index 258b30eb..700ffd3d 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -2555,4 +2555,9 @@ string ToString(ENUM_XPOI_EVENTS value) return result; } +// +typedef void (*TOnPOIEvent)(ENUM_XPOI_EVENTS event, + XCBasePOI *param // +); + // \ No newline at end of file