diff --git a/Classes/z-saherelm.x-bar.analyser.class.mq5 b/Classes/z-saherelm.x-bar.analyser.class.mq5 index 8b2f5f37..c2086a13 100644 --- a/Classes/z-saherelm.x-bar.analyser.class.mq5 +++ b/Classes/z-saherelm.x-bar.analyser.class.mq5 @@ -21,6 +21,7 @@ // // Imports ... #include "../Classes/x-saherelm.base.class.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" // // Definitions ... @@ -229,6 +230,191 @@ class XCBarAnalyser : public XSCBase 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 ... diff --git a/Classes/z-saherelm.x-bar.analyser.class_@!!@.mq5 b/Classes/z-saherelm.x-bar.analyser.class_@!!@.mq5 new file mode 100644 index 00000000..c2086a13 --- /dev/null +++ b/Classes/z-saherelm.x-bar.analyser.class_@!!@.mq5 @@ -0,0 +1,1363 @@ +/////////////////////////////////////////////////////// +// +// 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 ... + + // + // 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 * 40; + + // + bool isBearishRejectionBar = + barHighShadow > barLowShadow && + barHighShadow > barRangePercent * 40; + + // + 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: + // + + // + // 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; + } + + // + private: + // + + // + // Props ... + + // + // Actions ... + + // +}; + +// \ No newline at end of file diff --git a/Documents/BKP/x-121.smc.test.strategy.class copy 4.mq5 b/Documents/BKP/x-121.smc.test.strategy.class copy 4.mq5 new file mode 100644 index 00000000..53342c18 Binary files /dev/null and b/Documents/BKP/x-121.smc.test.strategy.class copy 4.mq5 differ diff --git a/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 b/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 index 53342c18..e6d3e785 100644 Binary files a/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 and b/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 differ