diff --git a/Classes/x-saherelm.x-chart-objects.class.mq5 b/Classes/x-saherelm.x-chart-objects.class.mq5 index dfc64384..93114c8a 100644 --- a/Classes/x-saherelm.x-chart-objects.class.mq5 +++ b/Classes/x-saherelm.x-chart-objects.class.mq5 @@ -511,10 +511,10 @@ class XCZoneObject : public XCBaseObject } // - NormalizeTime(time2); + datetime time_2 = NormalizeTime(time2); // - result = time1 < time2; + result = time1 < time_2; if (!result) { return result; @@ -544,7 +544,7 @@ class XCZoneObject : public XCBaseObject window, time1, upperPrice1, - time2, + time_2, lowerPrice1 // ); } 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..aeb831a1 --- /dev/null +++ b/Classes/z-saherelm.x-bar.analyser.class.mq5 @@ -0,0 +1,713 @@ +/////////////////////////////////////////////////////// +// +// 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" + +// +// 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; + } + + // + // Rejection Bar ... + + /** + * 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 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; + } + + /** + * 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; + } + + // + protected: + // + + // + private: + // + + // + // Props ... + + // + // Actions ... + + /** + * Calculate Bar Range ... + * + * @param bar: XOHCL instance ... + * + * @return ( double ) + */ + double GetBarRangePercent(XOHCL &bar) + { + // + double result = 0; + + // + result = bar.GetRange() / 100; + + // + return result; + } + + /** + * 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 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; + } + + /** + * 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 GetLoopbackData( + int &hhIDX, + double &hh, + int &llIDX, + double &ll, + XOHCL &bar, + int loopback // + ) + { + // + bool result = false; + + // + if (loopback < 1) + { + loopback = 1; + } + + // + int index = bar.Index(); + int start = index + 1; + int end = start + loopback; + int count = end - start; + result = count >= 1; + if (!result) + { + return result; + } + + // + hhIDX = iHighest( + bar.symbol, + bar.period, + MODE_HIGH, + start, + count // + ); + result = IsValidIndex(hhIDX); + if (!result) + { + return result; + } + + // + llIDX = iLowest( + bar.symbol, + bar.period, + MODE_LOW, + start, + count // + ); + result = IsValidIndex(llIDX); + if (!result) + { + return result; + } + + // + hh = iHigh( + bar.symbol, + bar.period, + hhIDX // + ); + ll = iLow( + bar.symbol, + bar.period, + llIDX // + ); + + // + return result; + } + + /** + * 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 = GetLoopbackData( + 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; + } + + // +}; + +// \ No newline at end of file diff --git a/X121SMCEA/Classes/x-121.smc.base.strategy.class.mq5 b/X121SMCEA/Classes/x-121.smc.base.strategy.class.mq5 index de857359..f239f4ce 100644 --- a/X121SMCEA/Classes/x-121.smc.base.strategy.class.mq5 +++ b/X121SMCEA/Classes/x-121.smc.base.strategy.class.mq5 @@ -26,6 +26,7 @@ #include "../../Classes/x-saherelm.x-poi.class.mq5" #include "../../Classes/x-saherelm.xalert.class.mq5" #include "../../Classes/x-saherelm.xtrade.class.mq5" +#include "../../Classes/z-saherelm.x-bar.analyser.class.mq5" #include "../Classes/x-121.smc.chart.objects.class.mq5" #include "../Libraries/x-121.smc.lib.mq5" @@ -533,6 +534,7 @@ class XCX121SMCBaseStrategy : public XSCBaseAlert // XBarTracker mBarTracker; // Strategy Time Tracker ... + XCBarAnalyser mBarAnalyser; // Bar Analyser Instance X121SMCStrategyConditions mConditions; // Market Conditions ... // diff --git a/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 b/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 index 73a14df3..41a4d515 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