From 19064114d83912b1a8278c677110c51dabaa7ae5 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Sat, 9 Nov 2024 09:20:01 +0330 Subject: [PATCH] last works ... --- Classes/z-saherelm.x-bar.analyser.class.mq5 | 186 +++ .../z-saherelm.x-bar.analyser.class_@!!@.mq5 | 1363 +++++++++++++++++ .../x-121.smc.test.strategy.class copy 4.mq5 | Bin 0 -> 153034 bytes .../x-121.smc.test.strategy.class.mq5 | Bin 153034 -> 158886 bytes 4 files changed, 1549 insertions(+) create mode 100644 Classes/z-saherelm.x-bar.analyser.class_@!!@.mq5 create mode 100644 Documents/BKP/x-121.smc.test.strategy.class copy 4.mq5 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 0000000000000000000000000000000000000000..53342c181bed7df3ecd6d191547837029e554f6f GIT binary patch literal 153034 zcmeHw{c{vYlJ@+35%2#n<|2HueWx|{Ixb>;ABzDS;;`XG*vs0nL4Xh-uY`1x0Augo zpMLL~Pv<@ps-D)&2s#u{Gdvkd_|`eh+6?XP?Qx9l`Fp;Jha|oyoVe1|wkpJi_WmQ)5?t z-Jcyxt^L`N^bpXF<=N5fwLE#+)R{|52l6+U-l4C1@_atql_%PBv^1YRlXp&}eAU#L z&$gRC;+vMB;bUn5G}RI`|3d-Q2x&gMC2u|z81vbG3C|wSewBZF@;9Gd6C8l=R`VQn z9?kw5)p;a!QRk0B6L9=U{KIHSmUj{b0EEsrP8Z~o*xS>APvuj9%u6A6_KO%)6Zs~iky8u`)8?9qAgb% zYI(umOjH8|3>;FtW1EIw=3K=@0bcRiim*9lZJ7;{RKM+kwCV_fF;M zFJc$k{rg4mcp=*NMtXiMZ^9b!t!=^Mzs2sbFQDJ@?Hx;N!`itnm<1c4JyI(K&K(MF z+vhd|PhwjHedGIa&n#6T4bb&Kg)M>fQI-o@|6$AW!G^Ona`Zr;!iK69q77`r4|vwt z+WEqoz7iTh)^`Qxwx#~6q2OK%U(n#UMi%Gt9{$iXJhk6p6D<5-3sCFW{HC_mz6)3> zy!1P$22E1ly^=nhHG0sd5h1^p-{CpDzUI8rR)hy3rTw+f=QGmHY9ni~q-MVqn>H68 za4Ht=P`Gg<{DA#R|5SD!h<>VP(f4-DTb4e2`{wMs+4thl9*NhzE#=MG*R%WLgYapm zX;*a~HVJg`TX`TRa*ytI|{FU61jMoa{| zfrttk_B!f&+-v_GYu~M1i{CA!*j>Q@9t9qZ@!GXUPt^yu{S~oFd#D_^-gund#xJYx zBYvW71hlV(KZx{pq6!`CP2YLog(@5A2-|?SK}2lnY-QQkkQ}r?mlJ__DmMB+=sTbNyZn3BP!ln>N`q~M*yP|^ zT5UJpZcm`SbhMF>RMTQA_;1$Wp;5hhpVLN~5btRJJ{{1nr$T%6anLx8>_IESVsBW+ z^$}IZZL=QBxIXmgw2}VuHZ+33sIRW2y(Y>#X}m&tYbO$aL;vu`effO9gTry(U@sA! z!n^4EKbR+Nt4#_84|i{NS9BC(;@k4+yT<4JSz?fz0`E-v4^O9%^EDrd@BV)F=fp#_ z+j=O_?@I4(2=x2%`CIvh&+w^-f;X(4ww0@icdp61|0Qod7$A8;Q!&0gl@UHX6JiO_ zKGjwBfMxpjj_87pA^i7ibS%Jzv|bagVx0IU!La>2&*L1#6zc#p{E~;-ws1Lo|2F%Z z&@}!vv=IA7Qg~l@fKmPjq7T86#@?NEeH+bR@&1`;#)IOA8QHb_l|s$&9@-DS>(V&iH~lH-?$^Se{JSRPBIc|y`@r=^|u>+#CXpi zp|P!)1OCV?)U{Oat{YpBoVU!`+4aQ(Lp}bTCa#2yz-$eo`XDW&A4|*M-Aewl{<`@a zTfujqzgV$>ML@iRm9bhrA6N33_1Dek*#ExEe2&LWI}#;;1k~f~`^C0#>?DWiA7&(;D4j4#(?@Uo*5=6M@A2RsVED+Sj>ntORK$ z03;jF@f}aK=CC$HG-X#{bYudVKrDRmZ+FL0*3Wj=Oh+N@bw=7EMqM>Bl-e)vUBcgW z_<>d9S7K9-WiI6H?8m0Yo>&2B@DCyl&}*GXn9Kap-`o{~Zul6b9SS7KQ5Srl@8j9l zoR1{-R>P1xb0YQ;I_Jqo&^^ALmf%axeAm$U_CYged$(B$|6aKGw9#P9+j@A<&p7~F z|3J7MMz_}Xds396Uuwm$+G4$d2aD9o!Q}5@26!1L^<&PoPu9D@D=dRew^d@#`zT}U zDX$NkIeW~m`kc>OZNg$%+cq+2bk^ppMQnzgqoZc-m>O@Ti|yn}w68PO0iJro4`&~C z(w-3Odcct(@)F?vkwZ{UEj#i%72j-S1$JUCIG15vCK{*hQ7%>O+< zpYK*Y`s_C$vy5TKJ%hE}ZDKy1Hy^)+n@ta3O`a`!GkzOt=dt#ABr`g%nmN6GKS%no z40O`yP}j(HCF_>pj(k6G1`!w5kkAi*4TTU{*2r;}O(MMRR{L73x1;pl7#pPHgs>hJ zOO}u0Z=HJIhj}``|5~EcyG@L9I{Rt%m&~}1RI`!6J&B6=ZkfI!gN1Lv>-OQ=6$KKb zJ{XX-bTzfj13%(o8ww+=5b9`1p;#N&4F&Tvx)!k|S(R5>c}r}qKK@A~-+7~9w%6tM zF72z|Cra}Njh|p%$q;$hwW=E9R!dOR2-k_}hr_iuJ`=SOS@(a5l?nr*c9r^R+l6ZwRW8`b( z;q6Fkzew~SvPnvCU5;Me7(J4{A=~AfPAkuTvec~1uAV*;zk5p{-7^Ed+mT(`77Iwky)^_IUby1qFFGmN= zu){OO9QYUMiRM&%Uahr0L}U>V;_}+69^}46c{`Gy1`lYn0sH-l&NpKuy9!yewgr?0 zcS|@+4nwX~BJg&A)-6Nu;@AfhG9*KTUuFI zpqPcVyzIr9!qimdP&YN>H%VLMejfLD|Mbn^-9zSRP1|t>D8JP}ur$URM)+O>rJYl2 zpVUCIK2}FFah635EbRQjdKa=sFseiU;%9Zx?2b_89;=^tAo}^dnKP(?h#8=eg^aa0 ze9L7pQ8UsqmMNQMLi&9nt7c&Zaa(8*vJVyCF3s$VT%eU4XK9PN-hbTKEbQqDyBFX| z!?!VFp4eJx`(Z}9n;ZIWI(qJVyMA;B3YDxgv>~UoSAPi!K_)9!Lic4(Ovj7yzCx_C zV^s%nFUEt&$?`L607=LH$mveydB~oRxWDP%l<#HKgA8_+N$fJinkn{WW32=0IWH3{ zT1pql9p+U-6qJsVk(UtH7`h`++rnPmv<>K|%~C?-y)Ti%TN<TFeB;a_QH`SW@SW z)7oLaKEOr<{8auB1M>H_Zu|1|P&o2KrXTnPE6=c-y6+crW%fym-Huo=g=p7+k)P}D z6SKA_ho4=s_UUbFSnM$S9(EGjUwphRoD_cx$^KSKXUNRHP){X3?FVEt{OZdkZNJ(9 zUj}1(ek^piPc%;&bO`$vHSYdz;V|}<>naXvAg3T?8$i-+uT%ULw~u8e%eIF&0FnuN zWZSfmbg!g+>$eDo?X|7N=dlHAM-Xb$c0>cY?-jHAG5-lG%+L5a{nmG?w^8W#gl^#9 z@Qi-tsr5$r@lU`~=WMVy2z!xkG&_W_&j&LqH-ze^!ohC^w=>ZK-Fb^B$b0KrvxE1V zSe-k~z9jC^y(RCxk$2#4u*fKikI9_Xp|IQfR)-O`q04Ys*P$Jxiha_9%T?1Fel)YFSF5 z`MR1ut%26YE!8@OwyZ27zIoGV^W!FK`dVYbG(S@FrV;t{jqW|URLFNEF2LICK{MuC z4wkOxo(jgAyNMBj=IC&qYB-*V(2y&0RpPkuFecQ`E(Gf57XtP77XtN*0;sjJY)3;H z2fq~FA?n6yAl`U7*zn+o^iw*@F5LxV$4%Xk3kifj6`7T45^2B@|NwNO)U zs!-FXL!er$0#y677HaBU6>9o)2vmzzfNGyA)NwQgYc24>b`Ar667$Qi#Aej?fbilG z`4|wx_;L(rVYJkSHk7jc9w9eVnfDA_gMp<9N)-Zn>^Av0Fe-wX#6?&XTi<+3dz>NQ0d4^ROtUqG)|10?gF`s4- z=HTbyT^C440t>kreGok?!kC9^?0TmDZyg_Q3um*6S})_dkm2AD-9m+uLPh5WnpJtE}yV5!(*1%G!Rh zXnPr+_>p>!ljX946>H2%!S*bJUyaOMt&|z9KaR}Qv<*Iw)pmeYE;DF*8J_qu(9*6bH~~YoJtaFuE!;7%INS&<4mJV{?9rsmkR$7o*^9Gf zV@ORbyU^|R%kH|ch-G(OSj4icSgcld+hg%QKirP}g8udInQy-xM~?L#quqm2Eo|cw zdJ}q2Ro3?U zFV2>YFS{Du^+!n7 z8;yZQEW7K%B9`5CVG+x&VzFA;ZAYtpc30y|tEJXv_xY*z+i~PruYK(vlxkrcm(Y^{ zW7!@NQhmJ5Gg7?O#(4dY{`j}0ymi`Mye8?lSk^LY_1Rw5BPM-gnSSdRcXFS#G&>Y4c`=o(M#mJXr!w1` z%Z)E>EsLSAo6a|zn}^1ub2k@A{VpqCCR1bU(z^MuIr6@4N~}gAeL3xt&u+QwlSf(` zdb3URF6~&N-uBVr+4F1La3?SG!p&~$i?)JiNk5V9){kv2-B+XIq*0evvre~mvsRy$ zvmUj*9c{IFvTl33PS3M>)L4yVs`v4tpqzvub{={{NlC6P_cQX0)m-LljI)g^f!VBrk(VX!(^OQ|`PL_NVJwFw?D9$$bQctf-A^Wrd1Z34Jwe3DS zg_EyMohTdzjAFwV@8$NO8vfp-lKdS13 z2ces*xpvF>)?G8z_O=HlH_7E1YXymk&(Fc>_I|XY?K~42`IeW&f*Z)CvwqMWtmn{mXlzqq>y5sUUJ$6sV(Vz=9^CbHR= z*hVGIqdwc}>xFUyJ0bP7fG$1|W}6>BFECer;9HI#KMOZ<{2=^pooB7Sp0Qp`?Vl^C z4V$P``DylZ5w+Q7DQ>ieDOQkeD;K`}vNe`vbYpERx8R9ywOE^_Kcg4_y1YES_Qhmn#V^HwtBDPKshzBBx0QvwPF8lc z^2+sSyEcq-=D;be@c0>c-K*1OtJ0+_=GP?G=Beb1Jd+baaf97WxtCa1op5_r*UEED z$#{LeJ0B)}(`IVsb7RuCm@AV$=Xc*0=~J&?If~gVD9tCiCcM*}VBA58dlI*zELmb! z(@Mxxd)mOpjT6Y@;k^w!SJuxeVD8Kt!RM)P@rB42WDK+Q9v0y|PwZC2S+KY*{ej%i zbw@rU^9K-d$0lwX$GO4^FVw-wvUlYTAO5b$(t-R#mJwDaPMRB-+v~l+QGdt&LaYNn zm$ph_rmJ%S+5>@t>|cfCQ6R@{YHXVeeY;%1E6uY24}xS^`T6KVGN;;Wj($Fu#iTEn zi(2%XD?j{|WsaKson@RmWHWM9zN{tqNo24jBa5)hanQ2?!|AyEbaf%+Tf)D%&PSr* zTa8Yf2?v>Tx-Htl6LxWr^w#V%`5!w1kpIQ=aChW0^Z{9ou&Lo~n)-l8e}N3)xQ} zEoxm6dzXKM)VwMj$w6hE&x*MgV-7sO6&w16(44=J{})HSeX;d8OP=<84EhoKysaI| z`Rfv~0y=Up?#ga}pBqg&6CT5o={<5E3xD-D-)p38v$pC9Z^P+tDS!Jx+CuQ;h@-G$ z7QV=4ofC)c=-0YvE8cri7jFeAsCy4NAMu`yy7#FwS9{K?PAO_Ncvy>{Ez#n55h?q{ z7^5v8-H|`vFZ0Q)U211pKS(Eb-)JM3Y+*o23yZ;g(oGwprh| zXJXM~pTKj!^-k>VCLYCI7<*#bYjCOK3VRT!gMAAcGb2XG#muA<-|s8^QBdwJ?m5P2 z&ZCr`LbrL8ibn#&XjH@NTDdzEPml4<8}VA!lbuRNp^m^Illn_3_T8NIe;qdZy~rKB zVU+9TR;D{z!>!-(o>mQ;`%r1CRqx9|O(XCNjUOJ54ZlF>QDSl2Pe*uN zT5R`*|GH@3pBae9>5%7mZ#dsx=Pib@jmX6dj4`OEEE&U(zc<{cXnl04{JkSm0zIhZ zFK1GHY%scRbCvI`ldGG$Z5TC-W!h73g)sC8`_6Uu6xs+a^yzVKg(DnVBgScT5sRgYhwoHu#vf^uASU=X%lRO_OQ=V;v^-uLU}&TuDLPdnJguF z?w6&O(x?7pDV3^0JL~LO&JK9gu7mupTS|{Yn{O$>GJ{EH;@dI2RG=el7XF-$)x%Y`c!wmeikY>qXgCt7l5>$(qL2v`wMQU_Y%7zQDCbqU>jz+LQf^?Pr@pn{Pkk3~+DVew0}XY1B*J#7!)$DmPJenQ&%AEfoo;Bl#Jlh+p~0i~Ff%g5M~dGRzD zq6K63(xWeS)d$=x9hTu5pq9R`ZC*Z&ueC8{`9;jH*^GQC^?!^_HP^hXAATkjt)>6# z&^)R8P4*~OqU=odC-R zZgoYhB@#Hrud36V5x;sI+w>^*TbUQZxl!1={7OD?uin^e`G-k6+(9};uAWyapGzu> zTyxa7F{_V9cpBzRF$(!A%0iB%T;ssF2BIb%!qQqPWhkXXAij1w(j4FgvM;*SE^RsboYs!DM zH8EA{dhO2~5G$7XnFQ8gS;}q7w_Uj#TfTJ{d8|WaysYD4X`e}>8VTnNqCc-+$Lmd% za4Q4rm2h$>EqyJ?Yeh~XRO;_bRKk-XHH*C+n|QvYb|)gDwz!=sHc2@ff6wtPt~H;P z#U^?Bj~ShKl9J-f?_mZ;$9i{~wL{#@`B?UMVU04ZBBph3E!Gm#+G>MJuqdUjYDsLj z=gt1{SemIdQ}pwGL_cl2`L4x3?H(>C<5L7g%ctdKh=AHMuv#gPDHgts8w2e$=kw}) zdGst}&&-^jw-H+4SUvPBmWUBlA;ezq`-wGo<-|qY%MU9j+WzIgjR6cv*rL}F$9O>fK! zc~^cPmAcxZy)kGm=WTy0(6FL_^9c2<>s_Iwg=70jKIM9aXkx5WW|u!7m)Npg_qnyW z^A7aES;N$;Ls{d*i5NOl67K2a8ffsf9v|8?!V{I$9ccqve74x-@Iao28+rE6PZ#da z)3zrCckf@iCpWs?mpuY^MK^J4Ti@*~IJ-M1M|uCRXIkfbiIZ4y<`K_}=6o3DzYqbQ z_2i|O_t)O4)lHc^wt*+Ll<4C8&4va#{tPYrdt|Ms6D<2~@+#>APUE)rCB2cXEg{(Z zfSi-Aw=A9WcbD-j*np>{!e&c_#We7%RwCLIxFdQ1-}j=iHaNQz9vQbbUX#;za7SFA zR%$IQ#lWFZ(_$NHQDZ$TmFo$f2TzByZ($XK=gZ%@(C#blp;w6yI5FNLL~UU#duQdc zTmQdpY$EQyye0PW8~MMxexSAGVCg$Pf9h>*z#`BVH;EzUKpfJJ-e^n0*dCDu_z|CY z?n7q1)$_;0$4XI7ekt?pH%rbm=sYg_wI@0hM~tlRM~?gzku7h=@n<^PQ8VAoVXm5| zQ6=?`F=ma{;hyK5)>-JQ=V{QnJEDDmx?~y`=vt<6eR^i$Q65*%lb~k-pZ7t}Zk)&D zxsjV4Z&7zy#&_9b^uY0~_2}^Izx2em*56y3j>s5Mg2rNjOSVp&W&BZ(KG~K6ueZhb z!Is5)U*qV));?%Py&>kSi7jHP9ZCbL6pf!T;Biy02R#XwK8 zh16S|^yb{HW?W6pi0Ma7Vj0VZN?8szq_YNgpCz`GAvH_y2nkf^js-)Hy6agg5*N$a z?ze+Hr(*|>VY=V9w;ko;l*=1oaSk--L_BjCM{?~5u58}Z&al?Z)0WM8TIjj?TdUK4 z9Gm0qzW6bW_u{*UpxvJ?>;?6eCEtkewZR)P40|gW-(^V{@jYUI5koD5(S{N~u~00f zh)o}DpvlwyWZ;ha$sKcVS$_Pv?s;D1f=u_5;cmHZ4^TdX66<$PYc8+1K##D>Gu==2 z4?>6d@3M21Ym;eCpyv+a29`9L~{0 zEx5pYq+>70OsY2~r;=K;!Tmg)TIAZr8bk85<+U@oTHU{gi z*^Z2Il%@Ts;YK`zjXCclnaSQ0O5%Rd)8_M2nOA(>Q0Z$K2R{+Mb8RcO;{zOh1zBnx@m)~Wy1iSezUQ5bbSw>6BTUka+%3E1R zOUheWy_P_G=Hi|IB(eRmeDXYL?rDA{?xDcB)j+)_zTbzrD>M49C6^xUdNuqAz`iw3 zBw!(Wcy#;uO^FD?oWjEz-KU+$7{&hz~wzhZbGH)JphIuqN{a5W+`g>p0 zNe;D3jAP5<>t!R9uSB}+U0u*fv>y5t|9&xjO5>qrdIf#KIpGJ*JUaW6@&;O?J&h^g z+kfV+SlC0dR&sJi35eI=_QevumVdaN9b=ilWL5z9wzZ@f`|`~#;i!d_({dklItFhH5!-C2N~?C5bKQH;Y4lT?v^5IPH2z;sy94 zNW#99c!EsgvqswHGX6!j@{arhjF4gIXD@hJ`+pSJ(80&e$xd_OH6i1~Xv|}P2cbR4 zEp7|6Cz^UuQP+Bw_A9{La@+aP;1bLGZ?4bD@h!GNuq@9h4dpn;Hsr4KM579Or|YmD#5SlL@|gYM%`;>4pbOTRIQu88 z43(pp3pKFE?9+Xb=J;#~%_SVCS9Q>r>sQz#$z0>1eF%{5h^2iaR>_mnWwBL@g!u6+ z(*kV<%eE~7eNV+cTkE_$wp^dzmEOM+JBJJbSjt>Z0J2cvna%_g-Q8mIO7JGLQLYQT z6ZwP3!Y&ZT1~s&V1%>Ym7Tvo6#)Fvl=URiyWAO=Lx4Kdiz1bG3hBktwC(h&wOGa&o zp7b6>s)k zJMM^Mn-m7W`!NrHP0LaY`5tDktPYV6cV#Vu{$MVjJ9 zp;g#92`(Hi;!Ngf=}MQa>0#Hs-j!m(??Dc_=ebxvElGp?{*Ckve$Uwo{+^bUpElLX zWQOqSWQT7Z%1oF>>Ms{u*EuoV6n;%O_f#x4X;Is=cud3=)3Upk|7&}EMW{KQP!D3` zc+Z23bB7pW_V#EYM?La?@*(7*Up_Q`BWSl;7VATN>R&D&V&#-p8h6ln5l%|2Iy;cl zmlP_$!-sg-ZH^D|u$z1c`PW_6$qr$?Up^$BqnV4>DI(ep43;pktXDabbcJwlroMh~lM}D5Jnjq^9dkv8@d9foWt{YEdC109z5k^|O z+#^}ellqs<2YG$i9Iw;HZj<~>8@tJ~q}t?vpF9iblCwzum}j+~#l}#yZIfs5r8&pP zw05~?@u)v}mXx0Qy_EWV8|ysrct+)WlRQhC|C47S|GLY`vw%K1ouFs2kqb_c8*-Z{ zVOd!n3M*uj>8f{ME*nm`=6Tk*)0bJElZW!PBPS1OZF^b-&$({rA>^oE7)t|5kDD^fD2E#kH;9LGMcFRA)m=sY)uVcP_zqll*fD zzLSS0kGsk`=^~_QG(bw^N`Ex4*|tFAk$5(KJWESTwZ{WFs%(Dp1kWS>!gN|HYL6!K52Pz);^pHGv=n~zyS@BG9uE&qwr1~mx_r6mz!i;}BKihvAdVn0@;zV2v$LCef zHgX>M1Icsb4dnLz_&7%hZT06*SXlPX^kre??%=j(=K{l+9^|A?7yb%seO()r`gRiped^YMA<~+YIPziaaaxdM?5nUR?$)2ps}fIJSmu8{T9)PY^X%EO z+Ton%{3w7l&PCz;os!h1n9p&(*KMa*Ys{6DaaTR8-uZS(M@n_t=R+#j!ET@CbEKOS zB|7L~P01e?ACIAlU0BuXW1wr9hE4kTv&1KUghAcDIDL$L`Vc*gA(ZQ%eUBQTdk(|B z2Sa1G5=~^A!?cc4t8vgvi4}3<61=Pj7yVEUdp3?-?!y{qQtLfZ&!w$>xvLPjFX5ac zoP{4eqEFdxnt1ksyz|`LnZdTxvfrwZ0^5=I|H|BrRAxD@%jvVYN$O1Qi^56UxYGlk z5;s;MMhtf;mf922rK~>U?k92^9_}l_U1o1a!lRoXWw?De`+kO4v8*;n3!5IP^vOA8 zF-RD73S4?BGVwwr`0BY%v3{;>!?`YeK9GMW0tdHepUnO&l84if!GG#%4j!Mk;qC}- zZw1Ppz}=DiYW^&|yV=|_dQHCHl5@`Q%2UGcvIT6Tlvb;X{)kt5?At#J@@=E%e{Jkg z%}u%evmh2ScneM5KervHjlHwf_T#u5t%EH*6MK7ne!qp<-DlFP0~rJDby)a*$Q)gA z7Qo&y$Fa6;+m9ClriAC6U7v?%X+%yhhdXAr;GJU1ErWd*#O3ghcOKmps{ns=B0G{` z7jOpqGJT1&?dzalbicZ2N;zQJma+bxb-^FAZ+fE8cwFj(H$LuNlp+UM_Hlyehvn%p zCjS0j?|j?r1>tRe|EgE%2_n8H^XMsg0!{QM^ra1 z^0vns`j*YcaCTtRXJb}9b3p4-vWu~XD^nI6DVvtL5qw&&>zv#=PS{+yw3YOGxOs89 zUpJ+VUA4Csewc+#p|98Crq~2ID6_Ba_mwLB_BMT!^Remk+;@8Pwx9A>jdO7PS;$;% zJ|ELw6DCW4osqw??5^ei+MX{aw48Oq^LcbLX!-rRle4YRN*zt?MVQ*5S~E2W74{r!r$;&srWw|=HESPa!){~Q{TJ&DeY^kA}dBcreGKi;V~S`EuFf!TuhVt)bPeot1Kl zT*kU{4Axk z{b5#P94pbrX4&Yj4RMO+a<;;s$@8C%H^0YSAh|3TYT#`dD}|lcJ2H0qRYp)4e$>>Qmw-}_A9pGc<1mb8dgu(Mh7JwKHlb^7h!qzriI(@$of2u5CpG3j3xBlO`% zXhT+N;~712;Qlh(j-y$(Po*Fw6v#?dO#+s2+ zXseCH+Pzt4B-X}e*+{Gnaf-xpw!)9O{HG!A(5U2^L@OsUyZly8bYP5BHV;kzKSg3b zUoJKhYwO49Y>LE|;{@Ms&zEgpB-ZACnZ;!vSx%7{DbZcNZ;_ZCCCz8)etz6*j1@_q zH0s~%$FVr~EyOtqDNI5fXLihozS!mp^mB)B@<-D}(a()_S0BPxPlGHNV6GwbqbBDyg6yG71dsAo8#(wj^~Km?8srf z$j(CbWq7RFHXr(GBfI|It~0Xh$F9ttWxB-Lr4(lU_N<)m35Ho-w!(6p z$gZEZWtNy&v7911QlhII(`u*f_*T5GmJefiWM@b6xS1yj17;y-T}Uhvjl{UJ0M3NRPBm z%hEVxNTgTB8M|&<5@(fS%rTL_{*tq5n>vq|!*`e!PNiVeta6Iq6!E1L@xH%r5uY7j zj2ZD+xH-LBF5)X`VYLxo2}Z+g%{aED1ixh?zLGYkh|jY;c(%HTuY^xi#Fyh!Y5X)K z;w$6K>LR`}e7bj@kdCXK-^+QPVOE&EV7X~lnRv0BB0f^0t9-vAzHmFpT=GfwOvZ|Y6xtLAc{-10tB-?}BU2QV~I3ZPa61{!va}dMSBt!!&;! zP51CwHUhFR>*AlX+Pkv{GLLsClnXfaQUFO;K z@T`7aF6F@LVkN7&n>1Hs@mkJm2EOR0bz9LCpK+q5GCP{KU1L|%cXL)Et;g@Q9@8#L zQpA>BV`DGpGBDOD`VJ^ zF07V|$vk?O*$D1=EUR5(LHaDlPzzC(_c7+Ut4mw0R^#(Bx$_{8c5}i0t<2Ry@(vcg_@=>R$2<@1P|{f5oP9U@ zUQYCTBpBY7@}}H)abM=M@M%Zj9Sbb9btF=!G*amI%<}-frWfF+j-9kOd$ZR9)8Ca` z5BJ9gzoT<_%!>3N*$Cy=g&pwu+}3K=$LQ*%&u)=TraJh#4&SiUV4@Ciffcdr@g$`10#=buHd1Pw-=W?nfk7yWWS2fE#kz| zn-(7Spu=_xrXdemDDWQ&I{Ax~>9Uq3*z;#8)5Rs9aySMVn1me6f%wS^21|7W&x6|3C}r1kD#O zVYIh`GelvQ_~%GP0Ve2ahA3v>t{`g2=oB(4Vt*&1rk22-X;&>-mE;6Jj iV^sS~ys~XWR6I`&n`K`|dRVyY%))3KOQUhql=2(gfKS>0 delta 688 zcmZ2>lk?PS&JAV`)8~aUifmrx5cPC&KpNZjBkGJv%##}qb4=go%*ZwUzzIgaZMuvz z1g9@3WE7ZQ6~m}9y@{JqVe$kuAlBmIO=iep$Y&^KNM%r9u$%mGvMg^JLncEKgE3Gn zn!#Z5!$ei_0tP3BM1~>;JqBdeHXzlUaMhFVCTikSiDIr1A#+hw8t#(R7D;Age5fv1WRZ6Qj)Jwm(*r15UC`uZU%gnmj>(Yw`ykq4tP4 L#_bVtOn!U-L|V1o