From 797917e30ad0c7fab7f7dbbd82665f57e695a1dc Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Tue, 12 Nov 2024 21:51:07 +0330 Subject: [PATCH] Complete Support and Resistance POI ... --- Classes/x-saherelm.x-bar.analyser.class.mq5 | 179 ++++++++ Classes/x-saherelm.x-cobject.class.mq5 | 161 ++++++- Classes/x-saherelm.x-poi.class.mq5 | 463 +++++++++++++++++++- Classes/x-saherelm.x-poi.drawer.class.mq5 | 133 +++++- Libraries/x-saherelm.x-poi.lib.mq5 | 118 +++-- 5 files changed, 998 insertions(+), 56 deletions(-) diff --git a/Classes/x-saherelm.x-bar.analyser.class.mq5 b/Classes/x-saherelm.x-bar.analyser.class.mq5 index 1ce16bf2..06856b74 100644 --- a/Classes/x-saherelm.x-bar.analyser.class.mq5 +++ b/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -730,6 +730,185 @@ class XCBarAnalyser : public XCBase return result; } + // + // Support and Resistance Zones ... + + /** + * Check a Bar is Support Bar or not ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Specified Verifiation Range ... + * + * @return ( bool ) + */ + bool IsSupport( + XOHCL &bar, + int range = 21 // + ) + { + // + bool result = false; + + // + if (range < 2) + { + range = 2; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = bar.Index(); + result = range > 0 && + index >= range; + if (!result) + { + return result; + } + + // + string symbol = bar.symbol; + ENUM_TIMEFRAMES period = bar.period; + + // + for (int i = 1; i <= range; i++) + { + // + int prevIDX = index + i; + int nextIDX = index - 1; + + // + // Prev Bar ... + XOHCL iPrevBar; + result = iPrevBar.Init( + symbol, + period, + prevIDX // + ); + if (!result) + { + break; + } + + // + // Next Bar ... + XOHCL iNextBar; + result = iNextBar.Init( + symbol, + period, + nextIDX // + ); + if (!result) + { + break; + } + + // + result = bar.low <= iPrevBar.low && + bar.low <= iNextBar.low; + if (!result) + { + break; + } + } + + // + return result; + } + + /** + * Check a Bar is Resistance Bar or not ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Specified Verifiation Range ... + * + * @return ( bool ) + */ + bool IsResistance( + XOHCL &bar, + int range = 21 // + ) + { + // + bool result = false; + + // + if (range < 2) + { + range = 2; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = bar.Index(); + result = range > 0 && + index >= range; + if (!result) + { + return result; + } + + // + string symbol = bar.symbol; + ENUM_TIMEFRAMES period = bar.period; + + // + for (int i = 1; i <= range; i++) + { + // + int prevIDX = index + i; + int nextIDX = index - 1; + + // + // Prev Bar ... + XOHCL iPrevBar; + result = iPrevBar.Init( + symbol, + period, + prevIDX // + ); + if (!result) + { + break; + } + + // + // Next Bar ... + XOHCL iNextBar; + result = iNextBar.Init( + symbol, + period, + nextIDX // + ); + if (!result) + { + break; + } + + // + result = bar.high >= iPrevBar.high && + bar.high >= iNextBar.high; + if (!result) + { + break; + } + } + + // + return result; + } + // protected: // diff --git a/Classes/x-saherelm.x-cobject.class.mq5 b/Classes/x-saherelm.x-cobject.class.mq5 index 381a742f..16d05700 100644 --- a/Classes/x-saherelm.x-cobject.class.mq5 +++ b/Classes/x-saherelm.x-cobject.class.mq5 @@ -870,6 +870,7 @@ class XCZoneObject : public XCBaseObject * @param name: String, Specified Object Identifier on Chart ... * @param window: Integer, Specified Chart Window ID ... * @param zone: XCZone instance ... + * @param prefix: String ... * * @return ( bool ) */ @@ -877,7 +878,8 @@ class XCZoneObject : public XCBaseObject long chart_id, string name, int window, - XCZone &zone // + XCZone &zone, + string prefix = NULL // ) { // @@ -897,17 +899,28 @@ class XCZoneObject : public XCBaseObject } // + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + datetime from = zone.From(); datetime to = NormalizeTime(zone.To()); + // + double upper = zone.Upper(); + double lower = zone.Lower(); + // result = mRect.Create( chart_id, name, window, - zone.From(), - zone.Upper(), + from, + upper, to, - zone.Lower() // + lower // ); // @@ -973,6 +986,16 @@ class XCZoneObject : public XCBaseObject mRect.Style(value); } + /** + * Set Zone Fill ... + * + * @param value: Boolean ... + */ + void ZoneFill(bool value) + { + mRect.Fill(value); + } + // private: // @@ -981,4 +1004,134 @@ class XCZoneObject : public XCBaseObject // }; +// +// Support Zone ... +class XCSupportZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCSupportZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCSupportZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SUPPORT_ZONE_OBJ; + } +}; + +// +// Resistance Zone ... +class XCResistanceZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCResistanceZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCResistanceZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_RESISTANCE_ZONE_OBJ; + } +}; + // \ No newline at end of file diff --git a/Classes/x-saherelm.x-poi.class.mq5 b/Classes/x-saherelm.x-poi.class.mq5 index c85ae70f..63fc90e9 100644 --- a/Classes/x-saherelm.x-poi.class.mq5 +++ b/Classes/x-saherelm.x-poi.class.mq5 @@ -317,6 +317,36 @@ class XCPOIDetector : public XCBaseAlert mRejectionBarShadowPercent = value; } + // + // Support and Resistance Zone(s) ... + + /** + * Get Support and Resistance Range for Verification ... + * + * @return ( int ) + */ + int SupportAndResistanceRange() + { + return mSupportAndResistanceRange; + } + + /** + * Set Support and Resistance Range for Verification ... + * + * @param value: Integer ... + */ + void SupportAndResistanceRange(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mSupportAndResistanceRange = value; + } + // // Actions ... @@ -574,6 +604,78 @@ class XCPOIDetector : public XCBaseAlert ); } + // + // Support and Resistance Zones ... + int supResRange = SupportAndResistanceRange(); + if (supResRange > 0) + { + // + XOHCL supResBar; + isInited = supResBar.Init( + symbol, + period, + zIndex + supResRange // + ); + if (isInited) + { + // + // Support Zones ... + isDetected = DetectSupportZone(supResBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_SUPPORT_ZONE_DETECTED; + XCSupportZone *param; + bool hasItem = GetLastItem( + param, + mSupportZones // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Resistance Zones ... + isDetected = DetectResistanceZone(supResBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_RESISTANCE_ZONE_DETECTED; + XCResistanceZone *param; + bool hasItem = GetLastItem( + param, + mResistanceZones // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + } + } + // CleanupUnusedPOIs(); @@ -658,6 +760,10 @@ class XCPOIDetector : public XCBaseAlert // Clean(mBullishRejectionBars); Clean(mBearishRejectionBars); + + // + Clean(mSupportZones); + Clean(mResistanceZones); } /** @@ -700,6 +806,9 @@ class XCPOIDetector : public XCBaseAlert // RejectionBarExtendRange(0); RejectionBarShadowPercent(55); + + // + SupportAndResistanceRange(7); } // @@ -764,6 +873,10 @@ class XCPOIDetector : public XCBaseAlert int bullishRejectionBarsCount = 0; int bearishRejectionBarsCount = 0; + // + int supportZonesCount = 0; + int resistanceZonesCount = 0; + // bool canContinue = true; @@ -818,6 +931,22 @@ class XCPOIDetector : public XCBaseAlert ArrayReverse(mBearishRejectionBars); } + // + // Support Zone(s) ... + supportZonesCount = DetectRequiredSupportZones(barIndex); + if (supportZonesCount == requiredPOIs) + { + ArrayReverse(mSupportZones); + } + + // + // Resistance Zone(s) ... + resistanceZonesCount = DetectRequiredResistanceZones(barIndex); + if (resistanceZonesCount == requiredPOIs) + { + ArrayReverse(mResistanceZones); + } + // canContinue = // @@ -849,6 +978,16 @@ class XCPOIDetector : public XCBaseAlert // Bearish Rejection Bars ... bearishRejectionBarsCount < requiredPOIs // + || + // + // Support Zones ... + supportZonesCount < requiredPOIs + // + || + // + // Resistance Zones ... + resistanceZonesCount < requiredPOIs + // ; if (canContinue) { @@ -1863,16 +2002,16 @@ class XCPOIDetector : public XCBaseAlert mBullishRejectionBars // ); - // - XCBullishRejectionObject *iObj; - bool isCreated = mDrawer.CreateBullishRejectionBar( - rejectionBar, - iObj // - ); - if (isCreated) - { - AddObjectIfNotExists(iObj); - } + // // + // XCBullishRejectionObject *iObj; + // bool isCreated = mDrawer.CreateBullishRejectionBar( + // rejectionBar, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } } } @@ -1995,15 +2134,15 @@ class XCPOIDetector : public XCBaseAlert ); // - XCBearishRejectionObject *iObj; - bool isCreated = mDrawer.CreateBearishRejectionBar( - rejectionBar, - iObj // - ); - if (isCreated) - { - AddObjectIfNotExists(iObj); - } + // XCBearishRejectionObject *iObj; + // bool isCreated = mDrawer.CreateBearishRejectionBar( + // rejectionBar, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } } } @@ -2072,11 +2211,297 @@ class XCPOIDetector : public XCBaseAlert return result; } + // + // Support and Resistance Zone ... + int mSupportAndResistanceRange; // Support and Resistance Range for Verification ... + // // Support Zone(s) ... + XCSupportZone *mSupportZones[]; // Holds Founded Support Zones ... + + /** + * Detect Support Zone ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectSupportZone(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SupportAndResistanceRange(); + int barIndex = bar.Index(); + result = range > 0 && + barIndex >= range; + if (!result) + { + return result; + } + + // + result = mBarAnalyser.IsSupport( + bar, + range // + ); + if (result) + { + // + XCSupportZone *support; + support = new XCSupportZone(); + result = support.Init( + bar, + range // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + support.To(cTime); + + // + Add( + support, + mSupportZones // + ); + + // // + // XCSupportZoneObject *iObj; + // bool isCreated = mDrawer.CreateSupportZone( + // support, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Required Support Zones ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredSupportZones(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mSupportZones); + if (count >= required) + { + // + result = count; + return result; + } + + // + int range = SupportAndResistanceRange(); + if (range < 0 || barIndex < range) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectSupportZone(bar); + + // + result = ArraySize(mSupportZones); + + // + return result; + } // // Resistance Zone(s) ... + XCResistanceZone *mResistanceZones[]; // Holds Founded Resistance Zones ... + + /** + * Detect Resistance Zone ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectResistanceZone(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SupportAndResistanceRange(); + int barIndex = bar.Index(); + result = range > 0 && + barIndex >= range; + if (!result) + { + return result; + } + + // + result = mBarAnalyser.IsResistance( + bar, + range // + ); + if (result) + { + // + XCResistanceZone *resistance; + resistance = new XCResistanceZone(); + result = resistance.Init( + bar, + range // + ); + + // + if (result) + { + // + Add( + resistance, + mResistanceZones // + ); + + // // + // XCResistanceZoneObject *iObj; + // bool isCreated = mDrawer.CreateResistanceZone( + // resistance, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Required Resistance Zones ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredResistanceZones(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mResistanceZones); + if (count >= required) + { + // + result = count; + return result; + } + + // + int range = SupportAndResistanceRange(); + if (range < 0 || barIndex < range) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectResistanceZone(bar); + + // + result = ArraySize(mResistanceZones); + + // + return result; + } // // Supply Zone(s) ... diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index dd4df24b..19d4ad8c 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -1659,6 +1659,135 @@ class XCPOIDrawer : public XCBase return result; } + // + // Support and Resistance ... + + /** + * Create Support Object ... + * + * @param zone: XCSupportZone instance ... + * @param object: XCSupportZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateSupportZone( + XCSupportZone &zone, + XCSupportZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = SupportZoneFill(); + int width = SupportZoneWidth(); + color crl = SupportZoneColor(); + ENUM_LINE_STYLE style = SupportZoneStyle(); + + // + object = new XCSupportZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Resistance Object ... + * + * @param zone: XCResistanceZone instance ... + * @param object: XCResistanceZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateResistanceZone( + XCResistanceZone &zone, + XCResistanceZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = ResistanceZoneFill(); + int width = ResistanceZoneWidth(); + color crl = ResistanceZoneColor(); + ENUM_LINE_STYLE style = ResistanceZoneStyle(); + + // + object = new XCResistanceZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + // protected: // @@ -1705,13 +1834,13 @@ class XCPOIDrawer : public XCBase BearishRejectionBarColor(clrMagenta); // - SupportZoneFill(true); + SupportZoneFill(false); SupportZoneWidth(1); SupportZoneStyle(STYLE_DOT); SupportZoneColor(clrLime); // - ResistanceZoneFill(true); + ResistanceZoneFill(false); ResistanceZoneWidth(1); ResistanceZoneStyle(STYLE_DOT); ResistanceZoneColor(clrRed); diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index 2a9b01e5..0692b5cf 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -319,7 +319,7 @@ class XCZone : public XCBasePOI // mUpper > 0 && mLower > 0 && - mUpper > mLower + mUpper >= mLower // ; @@ -637,6 +637,12 @@ class XCBarZone : public XCZone // result = IsValidBarZone(); + if (result) + { + // + From(bar.time); + To(TimeCurrent()); + } // return result; @@ -674,6 +680,46 @@ class XCBarZone : public XCZone return result; } + /** + * Set From Date ... + * + * @param value: DateTime ... + */ + void From(datetime value) + { + // + if (!IsValidBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mFrom = value; + } + + /** + * Set To Date ... + * + * @param value: DateTime ... + */ + void To(datetime value) + { + // + if (!IsValidBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mTo = value; + } + // // Overrides ... @@ -688,38 +734,12 @@ class XCBarZone : public XCZone datetime From() override { - // - datetime result = NULL; - - // - if (!IsValidBarZone()) - { - return result; - } - - // - result = mBar.time; - - // - return result; + return mFrom; } datetime To() override { - // - datetime result = NULL; - - // - if (!IsValidBarZone()) - { - return result; - } - - // - result = TimeCurrent(); - - // - return result; + return mTo; } string GetTag() override @@ -795,6 +815,8 @@ class XCBarZone : public XCZone private: // // Props ... + datetime mFrom; + datetime mTo; // }; @@ -1450,11 +1472,13 @@ class XCSupportZone : public XCBarZone * Initialize POI ... * * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... * * @return ( bool ) */ bool Init( - XOHCL &bar // + XOHCL &bar, + int range = 0 // ) { // @@ -1481,6 +1505,21 @@ class XCSupportZone : public XCBarZone // result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = (datetime)((int)time - (range * periodSeconds)); + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } // return result; @@ -1543,11 +1582,13 @@ class XCResistanceZone : public XCBarZone * Initialize POI ... * * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... * * @return ( bool ) */ bool Init( - XOHCL &bar // + XOHCL &bar, + int range = 0 // ) { // @@ -1574,6 +1615,21 @@ class XCResistanceZone : public XCBarZone // result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = (datetime)((int)time - (range * periodSeconds)); + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } // return result;