From b921b45eb2cd54d036d115665c999e433c13d2c3 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Thu, 14 Nov 2024 20:57:29 +0330 Subject: [PATCH] Complete Ticks Zones ... --- Classes/x-saherelm.x-cobject.class.mq5 | 326 ++++++++++++++++ Classes/x-saherelm.x-poi.class.mq5 | 165 +++++++- Classes/x-saherelm.x-poi.drawer.class.mq5 | 53 +++ Libraries/x-saherelm.x-poi.lib.mq5 | 456 +++++++++++++++++++++- 4 files changed, 995 insertions(+), 5 deletions(-) diff --git a/Classes/x-saherelm.x-cobject.class.mq5 b/Classes/x-saherelm.x-cobject.class.mq5 index d4fa632f..947bc521 100644 --- a/Classes/x-saherelm.x-cobject.class.mq5 +++ b/Classes/x-saherelm.x-cobject.class.mq5 @@ -28,6 +28,7 @@ #include #include #include +#include // // Definitions ... @@ -60,6 +61,8 @@ enum ENUM_XCHARTOBJECTS X_BEARISH_ORDERBLOCK_OBJ = 9873, X_BULLISH_FVG_OBJ = 9874, X_BEARISH_FVG_OBJ = 9875, + X_TICK_ZONE_OBJ = 9876, + X_TICKS_ZONE_OBJ = 9877, }; enum ENUM_X_CHART_IDS @@ -1532,4 +1535,327 @@ class XCBearishFairValueGapObject : public XCZoneObject } }; +// +// Zone Ticks ... + +class XCTickZoneObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param name: String, Specify Chart Object Identifier ... + * @param from: Datetime ... + * @param to: Datetime ... + * @param zone: XCTickZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + string name, + datetime from, + datetime to, + XCTickZone *zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + IsValid(name) && + zone.IsValid() && + IsValid(to) && + IsValid(from); + if (!result) + { + return result; + } + + // + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + string rectName = "TKZ_" + name; + result = mRect.Create( + chart_id, + rectName, + window, + from, + zone.high, + to, + zone.low // + ); + if (!result) + { + return result; + } + + // + string lblName = "LBL_" + name; + result = mLabel.Create( + chart_id, + lblName, + window, + from, + zone.high // + ); + if (!result) + { + return result; + } + + // + mLabel.Description(ToString(zone.percent) + "%"); + + // + ObjName(name); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_TICK_ZONE_OBJ; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Zone Width ... + * + * @param value: Integer ... + */ + void ZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Zone Color ... + * + * @param value: Color ... + */ + void ZoneColor(color value) + { + mRect.Color(value); + } + + /** + * Set Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ZoneStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Zone Fill ... + * + * @param value: Boolean ... + */ + void ZoneFill(bool value) + { + mRect.Fill(value); + } + + /** + * Set Label Color ... + * + * @param value: Color ... + */ + void LabelColor(color value) + { + mLabel.Color(value); + } + + /** + * Set Label Size ... + * + * @param value: Integer ... + */ + void LabelSize(int value) + { + mLabel.FontSize(value); + } + + /** + * Set Label Font ... + * + * @param value: String ... + */ + void LabelFont(string value) + { + mLabel.Font(value); + } + + /** + * Set Label Angle ... + * + * @param value: double ... + */ + void LabelAngle(double value) + { + mLabel.Angle(value); + } + + // + private: + // + // Props ... + CChartObjectRectangle mRect; + CChartObjectLabel mLabel; + + // +}; +class XCTicksZoneObject : public XCBaseObject +{ + // + public: + // + + // + void ~XCTicksZoneObject() + { + mZones.Clear(); + } + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCTicksZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCTicksZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + int levels = zone.Levels(); + result = levels > 0; + if (!result) + { + return result; + } + + // + for (int i = 0; i < levels; i++) + { + // + XCTickZone *iZone = zone.GetZone(i); + XCTickZoneObject *iObj; + iObj = new XCTickZoneObject(); + result = iObj.Create( + chart_id, + window, + ToString(i) + "_" + name, + zone.From(), + zone.To(), + iZone, + prefix // + ); + if (!result) + { + break; + } + + // + mZones.Add(iObj); + } + + // + if (result) + { + ObjName(name); + } + else + { + mZones.Clear(); + } + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_TICKS_ZONE_OBJ; + } + + // + // Getter(s) / Setter(s) ... + + // + // Actions ... + + void Destroy() { + mZones.Clear(); + } + + // + private: + // + // Props ... + CArrayObj mZones; + + // +}; + // \ 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 f509f87e..663bfc25 100644 --- a/Classes/x-saherelm.x-poi.class.mq5 +++ b/Classes/x-saherelm.x-poi.class.mq5 @@ -437,6 +437,63 @@ class XCPOIDetector : public XCBaseAlert mFairValueGapsSameBars = value; } + // + // Ticks Zone ... + + /** + * Get Ticks Range Levels ... + * + * @return ( int ) + */ + int TicksRangeZoneLevel() + { + return mTicksRangeZoneLevel; + } + + /** + * Set Ticks Range Levels ... + * + * @param value: Integer ... + */ + void TicksRangeZoneLevel(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mTicksRangeZoneLevel = value; + } + + /** + * Get Ticks Range Zone Loopback Period ... + * + * @return ( int ) + */ + int TicksRangeZoneRange() + { + return mTicksRangeZoneRange; + } + + /** + * Set Ticks Range Zone Loopback Period ... + * + * @param value: Integer ... + */ + void TicksRangeZoneRange(int value) + { + // + if (value < 7) + { + value = 7; + } + + // + mTicksRangeZoneRange = value; + } + // // Actions ... @@ -952,6 +1009,20 @@ class XCPOIDetector : public XCBaseAlert } } + // + // Ticks Range Zone ... + int ticksLevels = TicksRangeZoneLevel(); + int ticksRange = TicksRangeZoneRange(); + if (ticksLevels > 0 && + ticksRange > 0) + { + // + isDetected = DetectTicksZoneRange(cBar); + if (isDetected) + { + } + } + // ValidatePOIs(cBar); @@ -1109,6 +1180,10 @@ class XCPOIDetector : public XCBaseAlert // FairValueGapsSameBars(3); + + // + TicksRangeZoneLevel(10); + TicksRangeZoneRange(144); } // @@ -3283,7 +3358,8 @@ class XCPOIDetector : public XCBaseAlert // int sameBars = OrderBlocksSameBars(); - if (sameBars < 0) + result = sameBars > 0; + if (!result) { return result; } @@ -3440,7 +3516,8 @@ class XCPOIDetector : public XCBaseAlert // int sameBars = OrderBlocksSameBars(); - if (sameBars < 0) + result = sameBars > 0; + if (!result) { return result; } @@ -3601,7 +3678,8 @@ class XCPOIDetector : public XCBaseAlert // int sameBars = FairValueGapsSameBars(); - if (sameBars < 0) + result = sameBars > 0; + if (!result) { return result; } @@ -3761,7 +3839,8 @@ class XCPOIDetector : public XCBaseAlert // int sameBars = FairValueGapsSameBars(); - if (sameBars < 0) + result = sameBars > 0; + if (!result) { return result; } @@ -3896,6 +3975,84 @@ class XCPOIDetector : public XCBaseAlert return result; } + // + // Ticks Range Zones ... + int mTicksRangeZoneLevel; // Ticks Range Levels ... + int mTicksRangeZoneRange; // Ticks Range Zone Loopback Period ... + + // + XCTicksZone *mTicksZone; // Ticks Zone ... + // XCTicksZoneObject *mTicksZoneObject; // Ticks Zone Object ... + + /** + * Detect Ticks Zone Range ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectTicksZoneRange(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int ticksLevels = TicksRangeZoneLevel(); + int ticksRange = TicksRangeZoneRange(); + result = ticksLevels > 0 && + ticksRange > 0; + if (!result) + { + return result; + } + + // + int startBarIndex = bar.Index() + ticksRange; + XOHCL startBar; + result = startBar.Init( + bar.symbol, + bar.period, + startBarIndex // + ); + if (!result) + { + return result; + } + + // + mTicksZone = new XCTicksZone(); + result = mTicksZone.Init( + startBar, + bar // + ); + if (!result) + { + // + mTicksZone = NULL; + return result; + } + + // // + // if (mTicksZoneObject != NULL) + // { + // mTicksZoneObject.Destroy(); + // } + // mDrawer.CreateTicksZone( + // mTicksZone, + // mTicksZoneObject // + // ); + + // + return result; + } + // // Liquidity Zones ... diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index 6dc591ab..6710ae74 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -2268,6 +2268,59 @@ class XCPOIDrawer : public XCBase return result; } + // + // Ticks Zone ... + + bool CreateTicksZone( + XCTicksZone &zone, + XCTicksZoneObject *&object + ) { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + // bool fill = BearishFVGFill(); + // int width = BearishFVGWidth(); + // color crl = BearishFVGColor(); + // ENUM_LINE_STYLE style = BearishFVGStyle(); + + // + object = new XCTicksZoneObject(); + 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: // diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index 0d5ae318..1d8057dd 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -22,6 +22,7 @@ // // Imports ... #include "../Classes/x-saherelm.base.class.mq5" +#include // // Definitions ... @@ -36,6 +37,8 @@ enum ENUM_XPOIS // X_POI_NONE, // + X_POI_TICKS_ZONES, // Ticks Zone ... + // // Trading Day ... X_POI_TRADING_DAY, // Trading Day ... // @@ -900,7 +903,7 @@ class XCTwoBarZone : public XCZone From(startBar.time); To(endBar.time); } - + // return result; } @@ -2363,6 +2366,452 @@ class XCFVG : public XCTwoBarZone // }; +// +// Ticks Zones ... + +// +class XCTickZone : public CObject +{ + // + // Public ... + public: + // + // Props ... + double high; + double low; + int ticks; + double percent; + + // + // Compare Two Zone With Each Other ... + virtual int Compare( + const CObject *node, + const int mode = 0 // + ) const + { + // + const XCTickZone *other = (XCTickZone *)node; + + // + return other.ticks - ticks; + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = high > 0 && + low > 0 && + high > low && + ticks > 0 && + percent > 0; + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // +}; + +// +class XCTicksZone : public XCTwoBarZone +{ + // + public: + // + + // + // Constructor ... + void XCTicksZone() + { + Default(); + } + + // + // Deconstructor ... + void ~XCTicksZone() + { + } + + // + // Getter(s) / Setter(s) ... + + /** + * Get Number of Ticks Levels ... + * + * @return ( int ) + */ + int Levels() + { + return mLevels; + } + + /** + * Set Number of Ticks Levels ... + * + * @return ( int ) + */ + void Levels(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mLevels = value; + } + + /** + * Apply Default Config ... + */ + virtual void Default() + { + // + Levels(10); + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param startBar: XOHCL instance ... + * @param endBar: XOHCL instance ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &startBar, + XOHCL &endBar // + ) + { + // + bool result = false; + + // + result = endBar.IsValid() && + startBar.IsValid(); + if (!result) + { + return result; + } + + // + // Calculate Start and End Time ... + datetime from = startBar.time; + datetime to = endBar.time; + ulong fromM = ((ulong)startBar.time * 1000); + ulong toM = ((ulong)endBar.time * 1000); + + // + // Symbol and Period ... + string symbol = startBar.symbol; + ENUM_TIMEFRAMES period = startBar.period; + + // + // Prepare Zones Array ... + mZones.Clear(); + + // + // Retrieve Ticks between Times ... + SpecificClean(mTicks); + CopyTicksRange( + symbol, + mTicks, + COPY_TICKS_ALL, + fromM, + toM // + ); + + // + // Retrieve Highs ... + SpecificClean(mHighs); + CopyHigh( + symbol, + period, + from, + to, + mHighs // + ); + + // + // Retrieve Lows ... + SpecificClean(mLows); + CopyLow( + symbol, + period, + from, + to, + mLows // + ); + + // + // Find Highest Value in Range ... + int highIDX = ArrayMaximum(mHighs); + mRangeHigh = mHighs[highIDX]; + + // + // Find Lowest Value in Range ... + int lowIDX = ArrayMinimum(mLows); + mRangeLow = mLows[lowIDX]; + + // + datetime mTimes[]; + CopyTime( + symbol, + period, + from, + to, + mTimes // + ); + mRangeHighTime = mTimes[highIDX]; + mRangeLowTime = mTimes[lowIDX]; + + // + double mRangeSize = mRangeHigh - mRangeLow; + + // + // Create Zones ... + for (int i = 0; i < Levels(); i++) + { + // + // Instance a New Zone ... + XCTickZone *iZone = new XCTickZone(); + + // + // Calculate Each Zones High / Low based on Range ... + double iH = mRangeHigh - mRangeSize * i / Levels(); + double iL = mRangeHigh - mRangeSize * (i + 1) / Levels(); + + // + // Set Zone High Low Properties ... + iZone.low = iL; + iZone.high = iH; + + // + // Add Zone to Zone Array Objects ... + mZones.Add(iZone); + } + + // + // Calculate Each Zone Ticks ... + int ticksCount = ArraySize(mTicks); + for (int i = 0; i < ticksCount; i++) + { + // + // Retrieve Tick ... + MqlTick iTick = mTicks[i]; + + // + // Loop through Zones ... + for (int j = 0; j < Levels(); j++) + { + // + // Rejrieve j indexed Zone Object ... + XCTickZone *jZone = mZones.At(j); + + // + bool isInRange = IsTickInZoneRange( + iTick, + jZone // + ); + if (isInRange) + { + // + jZone.ticks++; + break; + } + } + } + + // + // Calculating Zone Percents ... + for (int i = 0; i < Levels(); i++) + { + // + XCTickZone *iZone = mZones.At(i); + + // + double percent = CalculateZoneTickPercent(iZone); + iZone.percent = percent; + } + + // + // Sort Zones Based on Percents ... + mZones.Sort(); + + // + mUpper = mRangeHigh; + mLower = mRangeLow; + mType = X_POI_TICKS_ZONES; + mEndBar = endBar; + mStartBar = startBar; + From(startBar.time); + To(endBar.time); + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Retrieve Zones Count ... + * + * @return ( int ) + */ + int Count() + { + return mZones.Total(); + } + + /** + * Retrieve Specified Sorted Zones ... + * + * @param index: Integer ... + * + * @return ( XCTickZone * ) + */ + XCTickZone *GetZone(int index) + { + // + if (!IsValidIndex(index)) + { + return NULL; + } + + // + return mZones.At(index); + } + + // + // Overrides ... + bool IsValid() override + { + // + bool result = false; + + // + result = + IsValidFrom() && + IsValidTwoBarZone() && + Levels() > 0 && + mZones.Total() == Levels() && + mRangeHigh > 0 && + mRangeLow > 0; + + // + return result; + } + + // + protected: + // + + // + private: + // + // Props ... + + // + MqlTick mTicks[]; + double mHighs[]; + double mLows[]; + double mRangeHigh; + datetime mRangeHighTime; + double mRangeLow; + datetime mRangeLowTime; + + // + int mLevels; // Number of Ticks Levels ... + + // + CArrayObj mZones; + + /** + * Check a Tick is in a Zone rage or not ... + * + * @param tick: MqlTick instance ... + * @param zone: XCTickZone instance ... + * + * @return ( bool ) + */ + bool IsTickInZoneRange( + MqlTick &tick, + XCTickZone *zone // + ) + { + // + bool result = false; + + // + result = + // + tick.bid >= zone.low && + tick.bid <= zone.high + // + ; + + // + return result; + } + + /** + * Calculate Zone Tick Percent ... + * + * @param zone: XCTickZone instance ... + * @param normalizationDigits: Integer ... + * + * @return ( double ) + */ + double CalculateZoneTickPercent( + XCTickZone *zone, + int normalizationDigits = 2 // + ) + { + // + double result = 0; + + // + if (normalizationDigits < 2 || normalizationDigits > 5) + { + normalizationDigits = 2; + } + + // + int ticksCount = ArraySize(mTicks); + if (ticksCount <= 0) + { + return result; + } + + // + result = (double)zone.ticks / ticksCount * 100; + result = NormalizeDouble(result, normalizationDigits); + + // + return result; + } + + // +}; + // // Trading Day ... class XCDay : public XCFromToZone @@ -2600,6 +3049,11 @@ string ToString(ENUM_XPOIS value) case X_POI_BEARISH_FVG: result = "XBEARFVG"; break; + + // + case X_POI_TICKS_ZONES: + result = "XTKSZ"; + break; } //