diff --git a/Classes/x-saherelm.x-cobject.class.mq5 b/Classes/x-saherelm.x-cobject.class.mq5 index e1752eed..1ab0f7d0 100644 --- a/Classes/x-saherelm.x-cobject.class.mq5 +++ b/Classes/x-saherelm.x-cobject.class.mq5 @@ -233,7 +233,7 @@ class XCBarArrowObject : public XCBaseObject // result = - // + // bar.IsValid() && IsValid(name) // @@ -1845,25 +1845,36 @@ class XCSignalObject : public XCBaseObject // // TARGET ... - if (signal.target > 0) + bool hasTargets = HasChild(signal.targets); + if (hasTargets) { // - string targetName = ToString(X_TARGET) + "_" + nameMD5; - result = mTargetTrend.Create( - chart_id, - targetName, - window, - time1, - signal.target, - time2, - signal.target // - ); - if (!result) + int targetsCount = ArraySize(signal.targets); + for (int i = 0; i < targetsCount; i++) { // - mTPTrend.Delete(); - mSLTrend.Delete(); - return result; + string targetName = ToString(X_TARGET) + "_" + ToString(i) + "_" + nameMD5; + CChartObjectTrend *mTargetTrend; + mTargetTrend = new CChartObjectTrend(); + result = mTargetTrend.Create( + chart_id, + targetName, + window, + time1, + signal.targets[i], + time2, + signal.targets[i] // + ); + if (!result) + { + // + mTPTrend.Delete(); + mSLTrend.Delete(); + break; + } + + // + mTargetTrends.Add(mTargetTrend); } } @@ -1884,7 +1895,7 @@ class XCSignalObject : public XCBaseObject // mTPTrend.Delete(); mSLTrend.Delete(); - mTargetTrend.Delete(); + mTargetTrends.Clear(); return result; } @@ -1996,7 +2007,12 @@ class XCSignalObject : public XCBaseObject } // - mTargetTrend.Width(value); + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Width(value); + } } /** @@ -2006,7 +2022,13 @@ class XCSignalObject : public XCBaseObject */ void TargetColor(color value) { - mTargetTrend.Color(value); + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Color(value); + } } /** @@ -2016,7 +2038,13 @@ class XCSignalObject : public XCBaseObject */ void TargetStyle(ENUM_LINE_STYLE value) { - mTargetTrend.Style(value); + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Style(value); + } } // @@ -2077,7 +2105,7 @@ class XCSignalObject : public XCBaseObject CChartObjectTrend mTPTrend; CChartObjectTrend mSLTrend; CChartObjectTrend mEntryTrend; - CChartObjectTrend mTargetTrend; + CArrayObj mTargetTrends; }; class XCOHCLObject : public XCBaseObject @@ -2985,19 +3013,19 @@ class XCTrendObject : public XCBaseObject ? first <= second : first >= second) && IsSpecifiedValid(firstTime) && - IsSpecifiedValid(secondTime) + IsSpecifiedValid(secondTime) // ; if (!result) { return result; } - + // - ENUM_X_DIRECTION dir = - useMinAsStart - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; + ENUM_X_DIRECTION dir = + useMinAsStart + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; // string name = "XTRND" + ToString(dir) + "_" + ToString(first) + "_" + ToString(second); diff --git a/Classes/x-saherelm.x-poi.class.mq5 b/Classes/x-saherelm.x-poi.class.mq5 index be134d9f..8ae90491 100644 --- a/Classes/x-saherelm.x-poi.class.mq5 +++ b/Classes/x-saherelm.x-poi.class.mq5 @@ -26,8 +26,7 @@ // #include "../Classes/x-saherelm.x-alert.class.mq5" #include "../Classes/x-saherelm.x-bar.analyser.class.mq5" -#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" -#include "../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.state.lib.mq5" // #include @@ -42,7 +41,6 @@ class XCPOIDetector : public XCBaseAlert // public: // - XCPOIDrawer *mDrawer; // // Constructors ... @@ -54,8 +52,7 @@ class XCPOIDetector : public XCBaseAlert */ void XCPOIDetector( string symbol, - ENUM_TIMEFRAMES period // - ) + ENUM_TIMEFRAMES period) { // // Attach Required Properties ... @@ -70,8 +67,7 @@ class XCPOIDetector : public XCBaseAlert ); // - // Create Default Drawer Instance ... - mDrawer = new XCPOIDrawer(); + mBarAnalyser = new XCBarAnalyser(); // // Apply Default Configurations ... @@ -109,79 +105,61 @@ class XCPOIDetector : public XCBaseAlert } /** - * Get Max Number of POIs which holds ... + * Get Max Required POI(s) allowed to Holds ... * * @return ( int ) */ - int MaxNumberOfPOIs() + int MaxRequiredPOIs() { - return mMaxNumberOfPOIs; + return mMaxRequiredPOIs; } /** - * Set Max Number of POIs which holds ... - * 0 => Infinity ... + * Set Max Required POI(s) allowed to Holds ... * - * @param value: Integer ... + * @param value: int ... */ - void MaxNumberOfPOIs(int value) + void MaxRequiredPOIs(int value) { // if (value < 0) { - value = 0; + value = 5; } // - mMaxNumberOfPOIs = value; + mMaxRequiredPOIs = value; } /** - * Get Number of POI(s) which must Find at Initializations ... + * Get Max Allowed Loopback for POI(s) Detection on Initialization Process ... * * @return ( int ) */ - int MaxNumberOfRequiredPOIs() + int MaxAllowedLoopbackForInit() { - return mMaxNumberOfRequiredPOIs; + return maxAllowedLoopbackForInit; } /** - * Set Number of POI(s) which must Find at Initializations ... - * 2 is Default ... + * Set Max Allowed Loopback for POI(s) Detection on Initialization Process ... * - * @param value: Integer ... + * @param value: int ... */ - void MaxNumberOfRequiredPOIs(int value) + void MaxAllowedLoopbackForInit(int value) { // - if (value < 2) + if (value < 0) { - value = 2; + value = 578; } // - mMaxNumberOfRequiredPOIs = value; + maxAllowedLoopbackForInit = value; } /** - * Check Is Locked or not ... - * - * @return ( bool ) - */ - bool IsLocked() - { - return mLock; - } - - // - // POI(s) Configs ... - - // - // Swings ... - - /** - * Get Swing Verification Range Length ... + * Get Swing Range Validation ... * * @return ( int ) */ @@ -191,41 +169,38 @@ class XCPOIDetector : public XCBaseAlert } /** - * Set Swing Verification Range Length ... + * Set Swing Range Validation ... * - * @param value: Integer ... + * @param value: int ... */ void SwingRange(int value) { // - if (value < 0) + if (value < 1) { - value = 0; + value = 1; } // mSwingRange = value; } - // - // Momentum Bars ... - /** - * Get Momentum Bars must Extends Range ... + * Get Momentum Bar Detection Extends Range ... * * @return ( int ) */ - int MomentumBarExtendRange() + int MomentumExtend() { - return mMomentumBarExtendRange; + return mMomentumExtend; } /** - * Set Momentum Bars must Extends Range ... + * Set Momentum Bar Detection Extends Range ... * - * @param value: Integer ... + * @param value: int ... */ - void MomentumBarExtendRange(int value) + void MomentumExtend(int value) { // if (value < 0) @@ -234,25 +209,25 @@ class XCPOIDetector : public XCBaseAlert } // - mMomentumBarExtendRange = value; + mMomentumExtend = value; } /** - * Get Momentum Bars Body Percent ... + * Get Momentum Bar Detection Body Percent ... * * @return ( double ) */ - double MomentumBarBodyPercent() + double MomentumBodyPercent() { - return mMomentumBarBodyPercent; + return mMomentumBodyPercent; } /** - * Set Momentum Bars Body Percent ... + * Set Momentum Bar Detection Body Percent ... * - * @param value: Double ... + * @param value: double ... */ - void MomentumBarBodyPercent(double value) + void MomentumBodyPercent(double value) { // if (value < 50) @@ -261,28 +236,31 @@ class XCPOIDetector : public XCBaseAlert } // - mMomentumBarBodyPercent = value; + if (value > 100) + { + value = 100; + } + + // + mMomentumBodyPercent = value; } - // - // Rejection Bars ... - /** - * Get Rejection Bars must Extends Range ... + * Get Rejection Bar Detection Extends Range ... * * @return ( int ) */ - int RejectionBarExtendRange() + int RejectionExtend() { - return mRejectionBarExtendRange; + return mRejectionExtend; } /** - * Set Rejection Bars must Extends Range ... + * Set Rejection Bar Detection Extends Range ... * - * @param value: Integer ... + * @param value: int ... */ - void RejectionBarExtendRange(int value) + void RejectionExtend(int value) { // if (value < 0) @@ -291,25 +269,25 @@ class XCPOIDetector : public XCBaseAlert } // - mRejectionBarExtendRange = value; + mRejectionExtend = value; } /** - * Get Rejection Bars Shadow Percent ... + * Get Rejection Bar Detection Shadow Percent ... * * @return ( double ) */ - double RejectionBarShadowPercent() + double RejectionShadowPercent() { - return mRejectionBarShadowPercent; + return mRejectionShadowPercent; } /** - * Set Rejection Bars Shadow Percent ... + * Set Rejection Bar Detection Shadow Percent ... * - * @param value: Double ... + * @param value: double ... */ - void RejectionBarShadowPercent(double value) + void RejectionShadowPercent(double value) { // if (value < 50) @@ -318,88 +296,31 @@ 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) + if (value > 100) { - value = 2; + value = 100; } // - mSupportAndResistanceRange = value; + mRejectionShadowPercent = value; } - // - // Supply and Demand Zone(s) ... - /** - * Get Supply and Demand Range Verifications ... + * Get Support and Resistance Detection Range ... * * @return ( int ) */ - int SupplyAndDemandRange() + int SupResRange() { - return mSupplyAndDemandRange; + return mSupResRange; } /** - * Set Supply and Demand Range Verifications ... + * Set Support and Resistance Detection Range ... * - * @param value: Integer ... + * @param value: int ... */ - void SupplyAndDemandRange(int value) - { - // - if (value < 2) - { - value = 2; - } - - // - mSupplyAndDemandRange = value; - } - - // - // Order Blocks ... - - /** - * Get Order Blocks Detection Bars ... - * - * @return ( int ) - */ - int OrderBlocksSameBars() - { - return mOrderBlocksSameBars; - } - - /** - * Set Order Blocks Detection Bars ... - * - * @param value: Argument 1 - */ - void OrderBlocksSameBars(int value) + void SupResRange(int value) { // if (value < 0) @@ -408,58 +329,44 @@ class XCPOIDetector : public XCBaseAlert } // - mOrderBlocksSameBars = value; + mSupResRange = value; } - // - // Fair Value Gaps ... + /** + * Get use Support and Resistance Range as Start ... + * + * @return ( bool ) + */ + bool SupResRangeAsStart() + { + return mSupResRangeAsStart; + } /** - * Get Fair Value Gaps Detection Same Bars ... + * Set use Support and Resistance Range as Start ... + * @param value: bool ... + */ + void SupResRangeAsStart(bool value) + { + mSupResRangeAsStart = value; + } + + /** + * Get OrderBlock Detection Same Bars ... * * @return ( int ) */ - int FairValueGapsSameBars() + int OrderBlockSameBars() { - return mFairValueGapsSameBars; + return mOrderBlockSameBars; } /** - * Set Fair Value Gaps Detection Same Bars ... + * Set OrderBlock Detection Same Bars ... * - * @param value: Integer ... + * @param value: int ... */ - void FairValueGapsSameBars(int value) - { - // - if (value < 0) - { - value = 0; - } - - // - 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) + void OrderBlockSameBars(int value) { // if (value < 2) @@ -468,603 +375,733 @@ class XCPOIDetector : public XCBaseAlert } // - mTicksRangeZoneLevel = value; + mOrderBlockSameBars = value; } /** - * Get Ticks Range Zone Loopback Period ... + * Get FairValueGap Detection Same Bars ... * * @return ( int ) */ - int TicksRangeZoneRange() + int FairValueGapSameBars() { - return mTicksRangeZoneRange; + return mFairValueGapSameBars; } /** - * Set Ticks Range Zone Loopback Period ... + * Set FairValueGap Detection Same Bars ... * - * @param value: Integer ... + * @param value: int ... */ - void TicksRangeZoneRange(int value) + void FairValueGapSameBars(int value) { // - if (value < 7) + if (value < 2) { - value = 7; + value = 2; } // - mTicksRangeZoneRange = value; + mFairValueGapSameBars = value; } // // Actions ... /** - * Initialize POI Detector ... + * Apply Default Configurations ... */ - void Init() + virtual void Default() { - DetectRequiredPOIs(); + // + // Default Props ... + SwingRange(3); + SupResRange(21); + MomentumExtend(1); + RejectionExtend(1); + MaxRequiredPOIs(100); + OrderBlockSameBars(3); + FairValueGapSameBars(3); + MomentumBodyPercent(70); + SupResRangeAsStart(true); + RejectionShadowPercent(70); + MaxAllowedLoopbackForInit(578); + } + + /** + * Add Event Listener ... + * + * @param listener: TOnPOIEvent instance ... + */ + void AddEventListener(TOnPOIEvent listener) + { + // + Add( + listener, + mEventListeners // + ); + } + + /** + * Initialize Instance ... + */ + void Init( + int barIndex = 0 // + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (maxAllowedLoopbackForInit <= 0) + { + return; + } + + // + mLock = true; + bool canContinue = true; + int index = barIndex + maxAllowedLoopbackForInit; + if (!IsValidIndex(index)) + { + // + mLock = false; + return; + } + + // + while (canContinue) + { + // + XOHCL iBar; + bool has = iBar.Init( + mSymbol, + mPeriod, + index // + ); + index--; + + // + int count = 0; + ENUM_XPOI_EVENTS iEvent = X_POI_EVENT_NONE; + + // + // Swings ... + bool lookupSwings = ArraySize(mSwingLows) < mMaxRequiredPOIs || + ArraySize(mSwingHighs) < mMaxRequiredPOIs; + if (has && + lookupSwings) + { + // + DetectSwing( + iBar, + iEvent, + false // + ); + } + + // + // Momentum Bar ... + bool lookupMomentums = ArraySize(mBullishMomentumBars) < mMaxRequiredPOIs || + ArraySize(mBearishMomentumBars) < mMaxRequiredPOIs; + if (has && + lookupMomentums) + { + // + DetectMomentumBar( + iBar, + iEvent, + false // + ); + } + + // + // Rejection Bar ... + bool lookupRejections = ArraySize(mBullishRejectionBars) < mMaxRequiredPOIs || + ArraySize(mBearishRejectionBars) < mMaxRequiredPOIs; + if (has && + lookupRejections) + { + // + DetectRejectionBar( + iBar, + iEvent, + false // + ); + } + + // + // Support ... + bool lookupSupports = ArraySize(mSupportZones) < mMaxRequiredPOIs; + if (has && + lookupSupports) + { + // + DetectSupportZone( + iBar, + iEvent, + false // + ); + } + + // + // Demand ... + bool lookupDemands = ArraySize(mDemandZones) < mMaxRequiredPOIs; + if (has && + lookupDemands) + { + // + DetectDemandZone( + iBar, + iEvent, + false // + ); + } + + // + // Resistance ... + bool lookupResistance = ArraySize(mResistanceZones) < mMaxRequiredPOIs; + if (has && + lookupResistance) + { + // + DetectResistanceZone( + iBar, + iEvent, + false // + ); + } + + // + // Supply ... + bool lookupSupplies = ArraySize(mSupplyZones) < mMaxRequiredPOIs; + if (has && + lookupSupplies) + { + // + DetectSupplyZone( + iBar, + iEvent, + false // + ); + } + + // + // OrderBlock ... + bool lookupOrderBlocks = ArraySize(mBullishOrderBlocks) < mMaxRequiredPOIs || + ArraySize(mBearishOrderBlocks) < mMaxRequiredPOIs; + if (has && + lookupOrderBlocks) + { + // + DetectOrderBlock( + iBar, + iEvent, + false // + ); + } + + // + // FairValueGap ... + bool lookupFairValeGaps = ArraySize(mBullishFairValueGaps) < mMaxRequiredPOIs || + ArraySize(mBearishFairValueGaps) < mMaxRequiredPOIs; + if (has && + lookupFairValeGaps) + { + // + DetectFairValueGap( + iBar, + iEvent, + false // + ); + } + + // + canContinue = + has && + (lookupSwings || + lookupMomentums || + lookupRejections || + lookupSupports || + lookupDemands || + lookupResistance || + lookupSupplies || + lookupOrderBlocks || + lookupFairValeGaps); + + // + iBar.Clean(); + } + + // + mLock = false; } /** * Update POI(s) ... - * - * @param state: an Array Refrence of ENUM_XPOI_EVENTS members ... + * @param events: ENUM_XPOI_EVENTS member Collection ... */ - int Update( - ENUM_XPOI_EVENTS &state[] // + void Update( + ENUM_XPOI_EVENTS &events[], + int barIndex = 0 // ) { // - int result = 0; - - // - Clean(state); - - // - // Check Bar Tracker if Waits ... - if (!mBarTracker.IsNewBar()) + if (barIndex < 0) { - return result; + barIndex = 0; } // - int zIndex = 0; - int cIndex = zIndex + 1; - int pIndex = cIndex + 1; + Clean(events); // - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); + if (mLock) + { + return; + } // - datetime cTime = TimeCurrent(); + mLock = true; // - XOHCL zBar; - bool isInited = zBar.Init( - symbol, - period, - zIndex // + XOHCL iBar; + bool has = iBar.Init( + mSymbol, + mPeriod, + barIndex // ); - if (!isInited) + + // + if (!has) { - return result; + // + iBar.Clean(); + + // + return; } // - XOHCL cBar; - isInited = cBar.Init( - symbol, - period, - cIndex // - ); - if (!isInited) - { - return result; - } - - // - // POI Detecting ... - bool isDetected = false; + int count = 0; + ENUM_XPOI_EVENTS iEvent = X_POI_EVENT_NONE; // // Swings ... - int iSwingRange = SwingRange(); - if (iSwingRange > 0) + has = DetectSwing( + iBar, + iEvent // + ); + if (has) { // - XOHCL swingBar; - isInited = swingBar.Init( - symbol, - period, - zIndex + iSwingRange // + Add( + iEvent, + events // ); - if (isInited) + + // + XCBasePOI *item = NULL; + XCSwing *iSwing = NULL; + if (iEvent == X_SWING_LOW_DETECTED) { // - // Swing High ... - isDetected = DetectSwingHigh(swingBar); - if (isDetected) - { - // - ENUM_XPOI_EVENTS event = X_SWING_HIGH_DETECTED; - XCSwing *param; - bool hasItem = GetLastItem( - param, - mSwingHighs // - ); - if (hasItem) - { - // - NotifyEventListeners( - event, - param // - ); - } - - // - Add( - event, - state // - ); - } - + has = GetLastItem( + iSwing, + mSwingLows // + ); + } + else if (iEvent == X_SWING_HIGH_DETECTED) + { // - // Swing Low ... - isDetected = DetectSwingLow(swingBar); - if (isDetected) - { - // - ENUM_XPOI_EVENTS event = X_SWING_LOW_DETECTED; - XCSwing *param; - bool hasItem = GetLastItem( - param, - mSwingLows // - ); - if (hasItem) - { - // - NotifyEventListeners( - event, - param // - ); - } - - // - Add( - event, - state // - ); - } + has = GetLastItem( + iSwing, + mSwingHighs // + ); + } + if (has) + { + item = (XCBasePOI *)iSwing; } - } - // - // Bullish Momentum Bars ... - isDetected = DetectBullishMomentumBar(cBar); - if (isDetected) - { // - ENUM_XPOI_EVENTS event = X_BULLISH_MOMENTUM_BAR_DETECTED; - XCMomentumBar *param; - bool hasItem = GetLastItem( - param, - mBullishMomentumBars // - ); - if (hasItem) + has = item != NULL; + if (has) { // NotifyEventListeners( - event, - param // + iEvent, + item // ); } - - // - Add( - event, - state // - ); } // - // Bearish Momentum Bars ... - isDetected = DetectBearishMomentumBar(cBar); - if (isDetected) + // Momentum Bar ... + has = DetectMomentumBar( + iBar, + iEvent // + ); + if (has) { // - ENUM_XPOI_EVENTS event = X_BEARISH_MOMENTUM_BAR_DETECTED; - XCMomentumBar *param; - bool hasItem = GetLastItem( - param, - mBearishMomentumBars // + Add( + iEvent, + events // ); - if (hasItem) + + // + XCBasePOI *item = NULL; + XCMomentumBar *iMomentum = NULL; + if (iEvent == X_BULLISH_MOMENTUM_BAR_DETECTED) + { + // + has = GetLastItem( + iMomentum, + mBullishMomentumBars // + ); + } + else if (iEvent == X_BEARISH_MOMENTUM_BAR_DETECTED) + { + // + has = GetLastItem( + iMomentum, + mBearishMomentumBars // + ); + } + if (has) + { + item = (XCBasePOI *)iMomentum; + } + + // + has = item != NULL; + if (has) { // NotifyEventListeners( - event, - param // + iEvent, + item // ); } - - // - Add( - event, - state // - ); } // - // Bullish Rejection Bars ... - isDetected = DetectBullishRejectionBar(cBar); - if (isDetected) + // Rejection Bar ... + has = DetectRejectionBar( + iBar, + iEvent // + ); + if (has) { // - ENUM_XPOI_EVENTS event = X_BULLISH_REJECTION_BAR_DETECTED; - XCRejectionBar *param; - bool hasItem = GetLastItem( - param, - mBullishRejectionBars // + Add( + iEvent, + events // ); - if (hasItem) + + // + XCBasePOI *item = NULL; + XCRejectionBar *iRejection = NULL; + if (iEvent == X_BULLISH_REJECTION_BAR_DETECTED) + { + // + has = GetLastItem( + iRejection, + mBullishRejectionBars // + ); + } + else if (iEvent == X_BEARISH_REJECTION_BAR_DETECTED) + { + // + has = GetLastItem( + iRejection, + mBearishRejectionBars // + ); + } + if (has) + { + item = (XCBasePOI *)iRejection; + } + + // + has = item != NULL; + if (has) { // NotifyEventListeners( - event, - param // + iEvent, + item // ); } - - // - Add( - event, - state // - ); } // - // Bearish Rejection Bars ... - isDetected = DetectBearishRejectionBar(cBar); - if (isDetected) + // Support ... + has = DetectSupportZone( + iBar, + iEvent // + ); + if (has) { // - ENUM_XPOI_EVENTS event = X_BEARISH_REJECTION_BAR_DETECTED; - XCRejectionBar *param; - bool hasItem = GetLastItem( - param, - mBearishRejectionBars // + Add( + iEvent, + events // ); - if (hasItem) + + // + XCBasePOI *item = NULL; + XCSupportZone *iZone = NULL; + has = GetLastItem( + iZone, + mSupportZones // + ); + if (has) + { + item = (XCBasePOI *)iZone; + } + + // + has = item != NULL; + if (has) { // NotifyEventListeners( - event, - param // + iEvent, + item // ); } + } + // + // Demand ... + has = DetectDemandZone( + iBar, + iEvent // + ); + if (has) + { // Add( - event, - state // + iEvent, + events // ); - } - // - // Support and Resistance Zones ... - int supResRange = SupportAndResistanceRange(); - if (supResRange > 0) - { // - XOHCL supResBar; - isInited = supResBar.Init( - symbol, - period, - zIndex + supResRange // + XCBasePOI *item = NULL; + XCDemandZone *iZone = NULL; + has = GetLastItem( + iZone, + mDemandZones // ); - if (isInited) + if (has) { - // - // 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 // - ); - } - } - } - - // - // Supply And Demand Zones ... - int supDemRange = SupplyAndDemandRange(); - if (supDemRange > 0) - { - // - // Supply Zone ... - isDetected = DetectSupplyZone(cBar); - if (isDetected) - { - // - ENUM_XPOI_EVENTS event = X_SUPPLY_ZONE_DETECTED; - XCSupplyZone *param; - bool hasItem = GetLastItem( - param, - mSupplyZones // - ); - if (hasItem) - { - // - NotifyEventListeners( - event, - param // - ); - } - - // - Add( - event, - state // - ); + item = (XCBasePOI *)iZone; } // - // Demand Zone ... - isDetected = DetectDemandZone(cBar); - if (isDetected) + has = item != NULL; + if (has) { // - ENUM_XPOI_EVENTS event = X_DEMAND_ZONE_DETECTED; - XCDemandZone *param; - bool hasItem = GetLastItem( - param, - mDemandZones // - ); - if (hasItem) - { - // - NotifyEventListeners( - event, - param // - ); - } - - // - Add( - event, - state // + NotifyEventListeners( + iEvent, + item // ); } } // - // Order Blocks ... - int obSameBars = OrderBlocksSameBars(); - if (obSameBars > 0) + // Resistance ... + has = DetectResistanceZone( + iBar, + iEvent // + ); + if (has) { // - // Bullish Order Block ... - isDetected = DetectBullishOrderBlock(cBar); - if (isDetected) + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCResistanceZone *iZone = NULL; + has = GetLastItem( + iZone, + mResistanceZones // + ); + if (has) + { + item = (XCBasePOI *)iZone; + } + + // + has = item != NULL; + if (has) { // - ENUM_XPOI_EVENTS event = X_BULLISH_ORDERBLOCK_DETECTED; - XCOrderBlock *param; - bool hasItem = GetLastItem( - param, + NotifyEventListeners( + iEvent, + item // + ); + } + } + + // + // Supply ... + has = DetectSupplyZone( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCSupplyZone *iZone = NULL; + has = GetLastItem( + iZone, + mSupplyZones // + ); + if (has) + { + item = (XCBasePOI *)iZone; + } + + // + has = item != NULL; + if (has) + { + // + NotifyEventListeners( + iEvent, + item // + ); + } + } + + // + // OrderBlock ... + has = DetectOrderBlock( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCOrderBlock *iZone = NULL; + if (iEvent == X_BULLISH_ORDERBLOCK_DETECTED) + { + // + has = GetLastItem( + iZone, mBullishOrderBlocks // ); - if (hasItem) - { - // - NotifyEventListeners( - event, - param // - ); - } - - // - Add( - event, - state // - ); } - - // - // Bearish Order Block ... - isDetected = DetectBearishOrderBlock(cBar); - if (isDetected) + else if (iEvent == X_BEARISH_ORDERBLOCK_DETECTED) { // - ENUM_XPOI_EVENTS event = X_BEARISH_ORDERBLOCK_DETECTED; - XCOrderBlock *param; - bool hasItem = GetLastItem( - param, + has = GetLastItem( + iZone, mBearishOrderBlocks // ); - if (hasItem) - { - // - NotifyEventListeners( - event, - param // - ); - } + } + if (has) + { + item = (XCBasePOI *)iZone; + } + // + has = item != NULL; + if (has) + { // - Add( - event, - state // + NotifyEventListeners( + iEvent, + item // ); } } // - // Fair Value Gaps ... - int fvgSameBars = FairValueGapsSameBars(); - if (fvgSameBars > 0) + // FairValueGap ... + has = DetectFairValueGap( + iBar, + iEvent // + ); + if (has) { // - // Bullish Fair Value Gap ... - isDetected = DetectBullishFairValueGap(cBar); - if (isDetected) + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCFVG *iZone = NULL; + if (iEvent == X_BULLISH_FVG_DETECTED) { // - ENUM_XPOI_EVENTS event = X_BULLISH_FVG_DETECTED; - XCFVG *param; - bool hasItem = GetLastItem( - param, + has = GetLastItem( + iZone, mBullishFairValueGaps // ); - if (hasItem) - { - // - NotifyEventListeners( - event, - param // - ); - } - - // - Add( - event, - state // - ); } - - // - // Bearish Fair Value Gap ... - isDetected = DetectBearishFairValueGap(cBar); - if (isDetected) + else if (iEvent == X_BEARISH_FVG_DETECTED) { // - ENUM_XPOI_EVENTS event = X_BEARISH_FVG_DETECTED; - XCFVG *param; - bool hasItem = GetLastItem( - param, + has = GetLastItem( + iZone, mBearishFairValueGaps // ); - if (hasItem) - { - // - NotifyEventListeners( - event, - param // - ); - } + } + if (has) + { + item = (XCBasePOI *)iZone; + } + // + has = item != NULL; + if (has) + { // - Add( - event, - state // + NotifyEventListeners( + iEvent, + item // ); } } // - // Ticks Range Zone ... - int ticksLevels = TicksRangeZoneLevel(); - int ticksRange = TicksRangeZoneRange(); - if (ticksLevels > 0 && - ticksRange > 0) + iBar.Clean(); + mLock = false; + + // + if (HasChild(events)) { - // - isDetected = DetectTicksZoneRange(cBar); - if (isDetected) - { - } + CleanupUnusedCollections(); } - - // - ValidatePOIs(cBar); - - // - CleanupUnusedPOIs(); - - // - mBarTracker.Waits(); - - // - result = ArraySize(state); - - // - return result; } - /** - * Destroy Class ... - */ - void Destroy() - { - // - DestroyPOIs(); - DestroySessions(); - DestroyEventListeners(); - - // - delete mDrawer; - delete mTicksZone; - - // - ZeroMemory(mDrawer); - ZeroMemory(mTicksZone); - } - - // - // Retrievers ... - /** * Get Current State of POIs ... * @@ -1082,6 +1119,12 @@ class XCPOIDetector : public XCBaseAlert state.period = mPeriod; state.time = TimeCurrent(); + // + Copy( + mSwings, + state.swings // + ); + // Copy( mSwingHighs, @@ -1094,6 +1137,12 @@ class XCPOIDetector : public XCBaseAlert state.swingLows // ); + // + Copy( + mMomentumBars, + state.momentumBars // + ); + // Copy( mBullishMomentumBars, @@ -1106,6 +1155,12 @@ class XCPOIDetector : public XCBaseAlert state.bearishMomentumBars // ); + // + Copy( + mRejectionBars, + state.rejectionBars // + ); + // Copy( mBullishRejectionBars, @@ -1142,6 +1197,12 @@ class XCPOIDetector : public XCBaseAlert state.demandZones // ); + // + Copy( + mOrderBlocks, + state.orderBlocks // + ); + // Copy( mBullishOrderBlocks, @@ -1154,6 +1215,12 @@ class XCPOIDetector : public XCBaseAlert state.bearishOrderBlocks // ); + // + Copy( + mFairValueGaps, + state.fairValueGaps // + ); + // Copy( mBullishFairValueGaps, @@ -1167,1204 +1234,19 @@ class XCPOIDetector : public XCBaseAlert ); // - state.ticksZone = mTicksZone; - - // - } - - // - // Event Listeners ... - - /** - * Add Event Listener ... - * - * @param listener: TOnPOIEvent instance ... - */ - void AddEventListener(TOnPOIEvent listener) - { - // - Add( - listener, - mEventListeners // - ); - } - - // - // Destroy ... - - /** - * Destroy Detected POI(s) ... - */ - void DestroyPOIs() - { - // - Clean(mSwingHighs); - Clean(mSwingLows); - - // - Clean(mBullishMomentumBars); - Clean(mBearishMomentumBars); - - // - Clean(mBullishRejectionBars); - Clean(mBearishRejectionBars); - - // - Clean(mSupportZones); - Clean(mResistanceZones); - - // - Clean(mSupplyZones); - Clean(mDemandZones); - - // - Clean(mBullishOrderBlocks); - Clean(mBearishOrderBlocks); - - // - Clean(mBullishFairValueGaps); - Clean(mBearishFairValueGaps); } /** - * Destroy Added Sessions ... + * Destroy Instance ... */ - void DestroySessions() - { - } - - /** - * Destroy Rejistered Event Handlers ... - */ - void DestroyEventListeners() - { - Clean(mEventListeners); - } - - // - // Virtual Actions ... - - /** - * Apply Default Configurations ... - */ - virtual void Default() + void Destroy() { // - // Common ... + mBarTracker.Clean(); + ZeroMemory(mBarAnalyser); // - MaxNumberOfPOIs(10); - MaxNumberOfRequiredPOIs(2); - - // - SwingRange(2); - - // - MomentumBarExtendRange(2); - MomentumBarBodyPercent(70); - - // - RejectionBarExtendRange(0); - RejectionBarShadowPercent(55); - - // - SupportAndResistanceRange(7); - - // - SupplyAndDemandRange(144); - - // - OrderBlocksSameBars(3); - - // - FairValueGapsSameBars(3); - - // - TicksRangeZoneLevel(10); - TicksRangeZoneRange(144); - } - - // - // Detector Functions ... - - /** - * Detect Swing High ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectSwingHigh(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int range = SwingRange(); - int barIndex = bar.Index(); - result = range > 0 && - barIndex >= range; - if (!result) - { - return result; - } - - // - result = mBarAnalyser.IsSwingHigh( - bar, - range // - ); - if (result) - { - // - XCSwing *swing; - swing = new XCSwing(); - result = swing.Init( - bar, - X_POI_SWING_HIGH // - ); - - // - if (result) - { - // - Add( - swing, - mSwingHighs // - ); - } - } - - // - return result; - } - - /** - * Detect Swing Low ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectSwingLow(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int range = SwingRange(); - int barIndex = bar.Index(); - result = range > 0 && - barIndex >= range; - if (!result) - { - return result; - } - - // - result = mBarAnalyser.IsSwingLow( - bar, - range // - ); - if (result) - { - // - XCSwing *swing; - swing = new XCSwing(); - result = swing.Init( - bar, - X_POI_SWING_LOW // - ); - - // - if (result) - { - // - Add( - swing, - mSwingLows // - ); - } - } - - // - return result; - } - - /** - * Detect Bullish Momentum Bar ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectBullishMomentumBar(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid() && - bar.Index() > 0; - if (!result) - { - return result; - } - - // - int extendRange = MomentumBarExtendRange(); - double bodyPercent = MomentumBarBodyPercent(); - ENUM_X_DIRECTION dir; - result = mBarAnalyser.IsMomentumBar( - bar, - dir, - extendRange, - bodyPercent // - ); - result = - result && - dir == X_DIRECTION_BULLISH; - if (result) - { - // - XCMomentumBar *momentumBar; - momentumBar = new XCMomentumBar(); - result = momentumBar.Init(bar); - - // - if (result) - { - // - Add( - momentumBar, - mBullishMomentumBars // - ); - } - } - - // - return result; - } - - /** - * Detect Bearish Momentum Bar ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectBearishMomentumBar(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid() && - bar.Index() > 0; - if (!result) - { - return result; - } - - // - int extendRange = MomentumBarExtendRange(); - double bodyPercent = MomentumBarBodyPercent(); - ENUM_X_DIRECTION dir; - result = mBarAnalyser.IsMomentumBar( - bar, - dir, - extendRange, - bodyPercent // - ); - result = - result && - dir == X_DIRECTION_BEARISH; - if (result) - { - // - XCMomentumBar *momentumBar; - momentumBar = new XCMomentumBar(); - result = momentumBar.Init(bar); - - // - if (result) - { - // - Add( - momentumBar, - mBearishMomentumBars // - ); - } - } - - // - return result; - } - - /** - * Detect Bullish Rejection Bar ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectBullishRejectionBar(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid() && - bar.Index() > 0; - if (!result) - { - return result; - } - - // - int extendRange = RejectionBarExtendRange(); - double shadowPercent = RejectionBarShadowPercent(); - ENUM_X_DIRECTION dir; - result = mBarAnalyser.IsRejectionBar( - bar, - dir, - extendRange, - shadowPercent // - ); - result = - result && - dir == X_DIRECTION_BULLISH; - if (result) - { - // - XCRejectionBar *rejectionBar; - rejectionBar = new XCRejectionBar(); - result = rejectionBar.Init(bar); - - // - if (result) - { - // - Add( - rejectionBar, - mBullishRejectionBars // - ); - } - } - - // - return result; - } - - /** - * Detect Bearish Rejection Bar ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectBearishRejectionBar(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid() && - bar.Index() > 0; - if (!result) - { - return result; - } - - // - int extendRange = RejectionBarExtendRange(); - double shadowPercent = RejectionBarShadowPercent(); - ENUM_X_DIRECTION dir; - result = mBarAnalyser.IsRejectionBar( - bar, - dir, - extendRange, - shadowPercent // - ); - result = - result && - dir == X_DIRECTION_BEARISH; - if (result) - { - // - XCRejectionBar *rejectionBar; - rejectionBar = new XCRejectionBar(); - result = rejectionBar.Init(bar); - - // - if (result) - { - // - Add( - rejectionBar, - mBearishRejectionBars // - ); - } - } - - // - return result; - } - - /** - * 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 // - ); - } - } - - // - return result; - } - - /** - * 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 // - ); - } - } - - // - return result; - } - - /** - * Detect Supply Zone ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectSupplyZone(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int range = SupplyAndDemandRange(); - result = range > 0; - if (!result) - { - return result; - } - - // - int hhIDX = -1; - double hh = -1; - - // - int llIDX = -1; - double ll = -1; - - // - result = mBarAnalyser - .CalculateLoopbackHLData( - hhIDX, - hh, - llIDX, - ll, - bar, - range // - ); - if (!result) - { - return result; - } - - // - XOHCL supplyBar; - result = supplyBar.Init( - bar.symbol, - bar.period, - hhIDX // - ); - if (result) - { - // - XCSupplyZone *supply; - supply = new XCSupplyZone(); - result = supply.Init( - supplyBar, - range // - ); - - // - if (result) - { - // - datetime cTime = TimeCurrent(); - supply.To(cTime); - - // - Add( - supply, - mSupplyZones // - ); - } - } - - // - return result; - } - - /** - * Detect Demand Zone ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectDemandZone(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int range = SupplyAndDemandRange(); - result = range > 0; - if (!result) - { - return result; - } - - // - int hhIDX = -1; - double hh = -1; - - // - int llIDX = -1; - double ll = -1; - - // - result = mBarAnalyser - .CalculateLoopbackHLData( - hhIDX, - hh, - llIDX, - ll, - bar, - range // - ); - if (!result) - { - return result; - } - - // - XOHCL demandBar; - result = demandBar.Init( - bar.symbol, - bar.period, - llIDX // - ); - if (result) - { - // - XCDemandZone *demand; - demand = new XCDemandZone(); - result = demand.Init( - demandBar, - range // - ); - - // - if (result) - { - // - datetime cTime = TimeCurrent(); - demand.To(cTime); - - // - Add( - demand, - mDemandZones // - ); - } - } - - // - return result; - } - - /** - * Detect Bullish Order Block ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectBullishOrderBlock(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int sameBars = OrderBlocksSameBars(); - result = sameBars > 0; - if (!result) - { - return result; - } - - // - XOHCL obBar; - ENUM_X_DIRECTION dir; - result = mBarAnalyser - .HasOrderBlock( - bar, - obBar, - dir, - sameBars // - ); - result = - result && - dir == X_DIRECTION_BULLISH; - if (!result) - { - return result; - } - - // - if (result) - { - // - XCOrderBlock *ob; - ob = new XCOrderBlock(); - result = ob.Init( - obBar, - dir // - ); - - // - if (result) - { - // - datetime cTime = TimeCurrent(); - ob.To(cTime); - - // - Add( - ob, - mBullishOrderBlocks // - ); - } - } - - // - return result; - } - - /** - * Detect Bullish Order Block ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectBullishOrderBlock( - XOHCL &bar, - XCOrderBlock *&ob // - ) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int sameBars = OrderBlocksSameBars(); - result = sameBars > 0; - if (!result) - { - return result; - } - - // - XOHCL obBar; - ENUM_X_DIRECTION dir; - result = mBarAnalyser - .HasOrderBlock( - bar, - obBar, - dir, - sameBars // - ); - result = - result && - dir == X_DIRECTION_BULLISH; - if (!result) - { - return result; - } - - // - if (result) - { - // - ob = new XCOrderBlock(); - result = ob.Init( - obBar, - dir // - ); - - // - if (result) - { - // - datetime cTime = TimeCurrent(); - ob.To(cTime); - } - } - - // - return result; - } - - /** - * Detect Bearish Order Block ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectBearishOrderBlock(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int sameBars = OrderBlocksSameBars(); - result = sameBars > 0; - if (!result) - { - return result; - } - - // - XOHCL obBar; - ENUM_X_DIRECTION dir; - result = mBarAnalyser - .HasOrderBlock( - bar, - obBar, - dir, - sameBars // - ); - result = - result && - dir == X_DIRECTION_BEARISH; - if (!result) - { - return result; - } - - // - if (result) - { - // - XCOrderBlock *ob; - ob = new XCOrderBlock(); - result = ob.Init( - obBar, - dir // - ); - - // - if (result) - { - // - datetime cTime = TimeCurrent(); - ob.To(cTime); - - // - Add( - ob, - mBearishOrderBlocks // - ); - } - } - - // - return result; - } - - /** - * Detect Bearish Order Block ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectBearishOrderBlock( - XOHCL &bar, - XCOrderBlock *&ob // - ) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int sameBars = OrderBlocksSameBars(); - result = sameBars > 0; - if (!result) - { - return result; - } - - // - XOHCL obBar; - ENUM_X_DIRECTION dir; - result = mBarAnalyser - .HasOrderBlock( - bar, - obBar, - dir, - sameBars // - ); - result = - result && - dir == X_DIRECTION_BEARISH; - if (!result) - { - return result; - } - - // - if (result) - { - // - ob = new XCOrderBlock(); - result = ob.Init( - obBar, - dir // - ); - - // - if (result) - { - // - datetime cTime = TimeCurrent(); - ob.To(cTime); - } - } - - // - return result; - } - - /** - * Detect Bullish Fair Value Gap ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectBullishFairValueGap(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int sameBars = FairValueGapsSameBars(); - result = sameBars > 0; - if (!result) - { - return result; - } - - // - XOHCL prevBar; - XOHCL nextBar; - ENUM_X_DIRECTION dir; - result = mBarAnalyser - .HasFairValueGap( - bar, - prevBar, - nextBar, - dir, - sameBars // - ); - result = - result && - dir == X_DIRECTION_BULLISH; - if (!result) - { - return result; - } - - // - if (result) - { - // - XCFVG *fvg; - fvg = new XCFVG(); - result = fvg.Init( - prevBar, - nextBar, - dir // - ); - - // - if (result) - { - // - datetime cTime = TimeCurrent(); - fvg.To(cTime); - - // - Add( - fvg, - mBullishFairValueGaps // - ); - } - } - - // - return result; - } - - /** - * Detect Bearish Fair Value Gap ... - * - * @param bar: XOHCL instance ... - * - * @return ( bool ) - */ - bool DetectBearishFairValueGap(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int sameBars = FairValueGapsSameBars(); - result = sameBars > 0; - if (!result) - { - return result; - } - - // - XOHCL prevBar; - XOHCL nextBar; - ENUM_X_DIRECTION dir; - result = mBarAnalyser - .HasFairValueGap( - bar, - prevBar, - nextBar, - dir, - sameBars // - ); - result = - result && - dir == X_DIRECTION_BEARISH; - if (!result) - { - return result; - } - - // - if (result) - { - // - XCFVG *fvg; - fvg = new XCFVG(); - result = fvg.Init( - prevBar, - nextBar, - dir // - ); - - // - if (result) - { - // - datetime cTime = TimeCurrent(); - fvg.To(cTime); - - // - Add( - fvg, - mBearishFairValueGaps // - ); - } - } - - // - return result; + CleanCollections(); } // @@ -2372,658 +1254,164 @@ class XCPOIDetector : public XCBaseAlert // // - // Actions ... - - /** - * Lock ... - */ - void Lock() - { - mLock = true; - } - - /** - * Unlock ... - */ - void Unlock() - { - mLock = false; - } - - /** - * Detect Required POI(s) ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - */ - void DetectRequiredPOIs(int barIndex = 0) + void CleanCollections() { // - // Validate Reuired POI(s) ... - int requiredPOIs = MaxNumberOfRequiredPOIs(); - if (requiredPOIs <= 0) + Clean(mEventListeners); + Clean(mSwings); + Clean(mSwingLows); + Clean(mSwingHighs); + Clean(mMomentumBars); + Clean(mBullishMomentumBars); + Clean(mBearishMomentumBars); + Clean(mRejectionBars); + Clean(mBullishRejectionBars); + Clean(mBearishRejectionBars); + Clean(mSupplyZones); + Clean(mDemandZones); + Clean(mSupplyZones); + Clean(mResistanceZones); + Clean(mFairValueGaps); + Clean(mBullishFairValueGaps); + Clean(mBearishFairValueGaps); + Clean(mOrderBlocks); + Clean(mBullishOrderBlocks); + Clean(mBearishOrderBlocks); + } + + // + void CleanupUnusedCollections( + int maxAllowed = 0 // + ) + { + // + maxAllowed = MaxRequiredPOIs(); + + // + if (maxAllowed <= 0) { return; } // - // Locking Detector ... - Lock(); + CleanupArray( + mEventListeners, + maxAllowed // + ); // - // Normalize Bar Index ... - if (barIndex < 0) - { - barIndex = 0; - } + CleanupArray( + mSwings, + maxAllowed // + ); // - int swingLowsCount = 0; - int swingHighsCount = 0; + CleanupArray( + mSwingLows, + maxAllowed // + ); // - int bullishMomentumBarsCount = 0; - int bearishMomentumBarsCount = 0; + CleanupArray( + mSwingHighs, + maxAllowed // + ); // - int bullishRejectionBarsCount = 0; - int bearishRejectionBarsCount = 0; + CleanupArray( + mMomentumBars, + maxAllowed // + ); // - int supportZonesCount = 0; - int resistanceZonesCount = 0; + CleanupArray( + mBullishMomentumBars, + maxAllowed // + ); // - int supplyZonesCount = 0; - int demandZonesCount = 0; + CleanupArray( + mBearishMomentumBars, + maxAllowed // + ); // - int bullishOrderBlocksCount = 0; - int bearishOrderBlocksCount = 0; + CleanupArray( + mRejectionBars, + maxAllowed // + ); // - int bullishFairValueGapsCount = 0; - int bearishFairValueGapsCount = 0; + CleanupArray( + mBullishRejectionBars, + maxAllowed // + ); // - bool canContinue = true; + CleanupArray( + mBearishRejectionBars, + maxAllowed // + ); // - while (canContinue) - { - // - // Swings ... - int iSwingRange = SwingRange(); - if (iSwingRange > 0) - { - // - // Swing Highs ... - swingHighsCount = DetectRequiredSwingHighs(barIndex); - if (swingHighsCount == requiredPOIs) - { - ArrayReverse(mSwingHighs); - } - - // - // Swing Lows ... - swingLowsCount = DetectRequiredSwingLows(barIndex); - if (swingLowsCount == requiredPOIs) - { - ArrayReverse(mSwingLows); - } - } - - // - bool canLookupMomentumBars = - MomentumBarExtendRange() >= 0 && - MomentumBarBodyPercent() > 0; - if (canLookupMomentumBars) - { - // - // - // Bullish Momentum Bars ... - bullishMomentumBarsCount = DetectRequiredBullishMomentumBars(barIndex); - if (bullishMomentumBarsCount == requiredPOIs) - { - ArrayReverse(mBullishMomentumBars); - } - - // - // Bearish Momentum Bars ... - bearishMomentumBarsCount = DetectRequiredBearishMomentumBars(barIndex); - if (bearishMomentumBarsCount == requiredPOIs) - { - ArrayReverse(mBearishMomentumBars); - } - } - - // - bool canLookupRejectionBars = - RejectionBarExtendRange() >= 0 && - RejectionBarShadowPercent() > 0; - if (canLookupRejectionBars) - { - // - // - // Bullish Rejection Bars ... - bullishRejectionBarsCount = DetectRequiredBullishRejectionBars(barIndex); - if (bullishRejectionBarsCount == requiredPOIs) - { - ArrayReverse(mBullishRejectionBars); - } - - // - // Bearish Rejection Bars ... - bearishRejectionBarsCount = DetectRequiredBearishRejectionBars(barIndex); - if (bearishRejectionBarsCount == requiredPOIs) - { - ArrayReverse(mBearishRejectionBars); - } - } - - // - // Support and Resistance Zones ... - int supResRange = SupportAndResistanceRange(); - if (supResRange > 0) - { - // - // Support Zone(s) ... - supportZonesCount = DetectRequiredSupportZones(barIndex); - if (supportZonesCount == requiredPOIs) - { - ArrayReverse(mSupportZones); - } - - // - // Resistance Zone(s) ... - resistanceZonesCount = DetectRequiredResistanceZones(barIndex); - if (resistanceZonesCount == requiredPOIs) - { - ArrayReverse(mResistanceZones); - } - } - - // - // Supply and Demand Zones ... - int supDemRange = SupplyAndDemandRange(); - if (supDemRange > 0) - { - // - supplyZonesCount = DetectRequiredSupplyZones(barIndex); - if (supplyZonesCount == requiredPOIs) - { - ArrayReverse(mSupplyZones); - } - - // - demandZonesCount = DetectRequiredDemandZones(barIndex); - if (demandZonesCount == requiredPOIs) - { - ArrayReverse(mDemandZones); - } - } - - // - // Oder Blocks ... - int obSameBars = OrderBlocksSameBars(); - if (obSameBars > 0) - { - // - // Bullish Order Blocks ... - bullishOrderBlocksCount = DetectRequiredBullishOrderBlocks(barIndex); - if (bullishOrderBlocksCount == requiredPOIs) - { - ArrayReverse(mBullishOrderBlocks); - } - - // - // Bearish Order Blocks ... - bearishOrderBlocksCount = DetectRequiredBearishOrderBlocks(barIndex); - if (bearishOrderBlocksCount == requiredPOIs) - { - ArrayReverse(mBearishOrderBlocks); - } - } - - // - // Fair Value Gaps ... - int fvgSameBars = FairValueGapsSameBars(); - if (fvgSameBars > 0) - { - // - // Bullish Fair Value Gaps ... - bullishFairValueGapsCount = DetectRequiredBullishFairValueGaps(barIndex); - if (bullishFairValueGapsCount == requiredPOIs) - { - ArrayReverse(mBullishFairValueGaps); - } - - // - // Bearish Fair Value Gaps ... - bearishFairValueGapsCount = DetectRequiredBearishFairValueGaps(barIndex); - if (bearishFairValueGapsCount == requiredPOIs) - { - ArrayReverse(mBearishFairValueGaps); - } - } - - // - // Swings ... - bool canContinueSwingHighs = - iSwingRange > 0 - ? swingHighsCount < requiredPOIs - : false; - bool canContinueSwingLows = - iSwingRange > 0 - ? swingLowsCount < requiredPOIs - : false; - - // - // Support and Resistance Zones ... - bool canContinueSupportZones = - supResRange > 0 - ? supportZonesCount < requiredPOIs - : false; - bool canContinueResistanceZones = - supResRange > 0 - ? resistanceZonesCount < requiredPOIs - : false; - - // - // Supply and Demand Zones ... - bool canContinueSupplyZones = - supDemRange > 0 - ? supplyZonesCount < requiredPOIs - : false; - bool canContinueDemandZones = - supDemRange > 0 - ? demandZonesCount < requiredPOIs - : false; - - // - // Order Blocks ... - bool canContinueBullishOrderBlocks = - obSameBars > 0 - ? bullishOrderBlocksCount < requiredPOIs - : false; - bool canContinueBearishOrderBlocks = - obSameBars > 0 - ? bearishOrderBlocksCount < requiredPOIs - : false; - - // - // Fair Value Gaps ... - bool canContinueBullishFairValueGaps = - fvgSameBars > 0 - ? bullishFairValueGapsCount < requiredPOIs - : false; - bool canContinueBearishFairValueGaps = - fvgSameBars > 0 - ? bearishFairValueGapsCount < requiredPOIs - : false; - - // - // Rejection Bars ... - bool canContinueBullishRejectionBars = - canLookupRejectionBars - ? bullishRejectionBarsCount < requiredPOIs - : false; - bool canContinueBearishRejectionBars = - canLookupRejectionBars - ? bearishRejectionBarsCount < requiredPOIs - : false; - - // - // Momentum Bars ... - bool canContinueBullishMomentumBars = - canLookupMomentumBars - ? bullishMomentumBarsCount < requiredPOIs - : false; - bool canContinueBearishMomentumBars = - canLookupMomentumBars - ? bearishMomentumBarsCount < requiredPOIs - : false; - - // - canContinue = - // - // Swings ... - canContinueSwingHighs || - canContinueSwingLows || - // - // Support and Resistance Zones ... - canContinueSupportZones || - canContinueResistanceZones || - // - // Supply and Demand Zones ... - canContinueSupplyZones || - canContinueDemandZones || - // - // Order Blocks ... - canContinueBullishOrderBlocks || - canContinueBearishOrderBlocks || - // - // Fair Value Gaps ... - canContinueBullishFairValueGaps || - canContinueBearishFairValueGaps || - // - // Rejection Bars ... - canContinueBullishRejectionBars || - canContinueBearishRejectionBars || - // - // Momentum Bars ... - canContinueBullishMomentumBars || - canContinueBearishMomentumBars - // - ; - if (canContinue) - { - barIndex++; - } - } + CleanupArray( + mSupplyZones, + maxAllowed // + ); // - // Unlocking Detector ... - Unlock(); - } - - /** - * Validate Founded POI(s) ... - * - * @param bar: XOHCL instance ... - */ - void ValidatePOIs(XOHCL &bar) - { - } - - /** - * Cleanup Unused Objects ... - */ - void CleanupUnusedPOIs() - { - // - int maxAllowed = MaxNumberOfPOIs(); - if (!IsValidSize(maxAllowed)) - { - return; - } + CleanupArray( + mDemandZones, + maxAllowed // + ); // - int swingHighsCount = ArraySize(mSwingHighs); - int swingLowsCount = ArraySize(mSwingLows); - // int tradingDaysCount = ArraySize(mTradingDays); - // int marketSessionsCount = ArraySize(mMarketSessions); - // int momentumBarsCount = ArraySize(mMomentumBars); - // int rejectionBarsCount = ArraySize(mRejectionBars); - // int supportZonesCount = ArraySize(mSupportZones); - // int resistanceZonesCount = ArraySize(mResistanceZones); - // int supplyZonesCount = ArraySize(mSupplyZones); - // int demandZonesCount = ArraySize(mDemandZones); - // int bullishOBsCount = ArraySize(mBullishOrderBlocks); - // int bearishOBsCount = ArraySize(mBearishOrderBlocks); - // int bullishFVGsCount = ArraySize(mBullishFVGs); - // int bearishFVGsCount = ArraySize(mBearishFVGs); + CleanupArray( + mSupplyZones, + maxAllowed // + ); // - int from = 0; - int requiredPOIs = MaxNumberOfRequiredPOIs(); - int count = maxAllowed - requiredPOIs; - int to = count - 1; + CleanupArray( + mResistanceZones, + maxAllowed // + ); // - // Swings ... + CleanupArray( + mFairValueGaps, + maxAllowed // + ); - // // - // // Swing Highs ... - // if (swingHighsCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mSwingHighs, - // from, - // count // - // ); - // } + // + CleanupArray( + mBullishFairValueGaps, + maxAllowed // + ); - // // - // // Swing Lows ... - // if (swingLowsCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mSwingLows, - // from, - // count // - // ); - // } + // + CleanupArray( + mBearishFairValueGaps, + maxAllowed // + ); - // // - // // Trading Days ... - // if (tradingDaysCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mTradingDays, - // from, - // count // - // ); + // + CleanupArray( + mOrderBlocks, + maxAllowed // + ); - // // - // mTradingDayObjects.DeleteRange( - // from, - // to // - // ); - // } + // + CleanupArray( + mBullishOrderBlocks, + maxAllowed // + ); - // // - // // Market Sessions ... - // if (marketSessionsCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mMarketSessions, - // from, - // count // - // ); - - // // - // mMarketSessionObjects.DeleteRange( - // from, - // to // - // ); - // } - - // // - // // Momentum Bars ... - // if (momentumBarsCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mMomentumBars, - // from, - // count // - // ); - - // // - // mMomentumBarObjects.DeleteRange( - // from, - // to // - // ); - // } - - // // - // // Rejection Bars ... - // if (rejectionBarsCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mRejectionBars, - // from, - // count // - // ); - - // // - // mRejectionBarObjects.DeleteRange( - // from, - // to // - // ); - // } - - // // - // // Support and Resistance Zones ... - - // // - // // Support Zones ... - // if (supportZonesCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mSupportZones, - // from, - // count // - // ); - - // // - // mSupportZoneObjects.DeleteRange( - // from, - // to // - // ); - // } - - // // - // // Resistance Zones ... - // if (resistanceZonesCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mResistanceZones, - // from, - // count // - // ); - - // // - // mResistanceZoneObjects.DeleteRange( - // from, - // to // - // ); - // } - - // // - // // Supply and Demand Zones ... - - // // - // // Supply Zones ... - // if (supplyZonesCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mSupplyZones, - // from, - // count // - // ); - - // // - // mSupplyZoneObjects.DeleteRange( - // from, - // to // - // ); - // } - - // // - // // Demand Zones ... - // if (demandZonesCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mDemandZones, - // from, - // count // - // ); - - // // - // mDemandZoneObjects.DeleteRange( - // from, - // to // - // ); - // } - - // // - // // Order Blocks ... - - // // - // // Bullish Order Blocks ... - // if (bullishOBsCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mBullishOrderBlocks, - // from, - // count // - // ); - - // // - // mBullishOrderBlockObjects.DeleteRange( - // from, - // to // - // ); - // } - - // // - // // Bearish Order Blocks ... - // if (bearishOBsCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mBearishOrderBlocks, - // from, - // count // - // ); - - // // - // mBearishOrderBlockObjects.DeleteRange( - // from, - // to // - // ); - // } - - // // - // // Fair Vakue Gaps ... - - // // - // // Bullish FVGs ... - // if (bullishFVGsCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mBullishFVGs, - // from, - // count // - // ); - - // // - // mBullishFVGObjects.DeleteRange( - // from, - // to // - // ); - // } - - // // - // // Bearish FVGs ... - // if (bearishFVGsCount >= maxAllowed) - // { - // // - // ArrayRemove( - // mBearishFVGs, - // from, - // count // - // ); - - // // - // mBearishFVGObjects.DeleteRange( - // from, - // to // - // ); - // } + // + CleanupArray( + mBearishOrderBlocks, + maxAllowed // + ); // } @@ -3057,1105 +1445,30 @@ class XCPOIDetector : public XCBaseAlert } } - void AddObjectIfNotExists(XCBaseObject *object) - { - // - string name = object.ObjName(); - - // - bool canAdd = true; - int count = mDrawnObjects.Total(); - if (IsValidSize(count)) - { - // - for (int i = 0; i < count; i++) - { - // - string iName = ((XCBaseObject *)mDrawnObjects.At(i)).ObjName(); - - // - if (name == iName) - { - // - canAdd = false; - break; - } - } - } - - // - if (canAdd) - { - mDrawnObjects.Add(object); - } - } - // - private: // - // - // Props ... - - // - bool mLock; // Lock State ... - string mSymbol; // Market Symbol ... - ENUM_TIMEFRAMES mPeriod; // Market Period ... - int mMaxNumberOfPOIs; // Max Allowed Number of POI(s) which Can Holds ... - int mMaxNumberOfRequiredPOIs; // Max Allowed Number of POI(s) which Must Find at Initializion Time ... - - // - CArrayObj mDrawnObjects; // Drawn Objects ... - XBarTracker mBarTracker; // Market Bar Tracker ... - XCBarAnalyser mBarAnalyser; // Bar Analyser ... - - // - TOnPOIEvent mEventListeners[]; // Event Listeners ... - - // - // POI Props ... - - // - // XDay ... - - // - // XSession ... - - // - // XSwing ... - int mSwingRange; // Swing Verification Range Length ... - - // - // Swing High ... - - // - XCSwing *mSwingHighs[]; // Holds Founded Swing Highs ... /** - * Detect Required Swing Highs ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - * - * @return ( int ) - */ - int DetectRequiredSwingHighs(int barIndex = 0) - { - // - int result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int required = MaxNumberOfRequiredPOIs(); - if (required <= 0) - { - return result; - } - - // - int count = ArraySize(mSwingHighs); - if (count >= required) - { - // - result = count; - return result; - } - - // - int range = SwingRange(); - 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; - } - - // - DetectSwingHigh(bar); - - // - result = ArraySize(mSwingHighs); - - // - return result; - } - - // - // Swing Low ... - - // - XCSwing *mSwingLows[]; // Holds Founded Swing Lows ... - - /** - * Detect Required Swing Lows ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - * - * @return ( int ) - */ - int DetectRequiredSwingLows(int barIndex = 0) - { - // - int result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int required = MaxNumberOfRequiredPOIs(); - if (required <= 0) - { - return result; - } - - // - int count = ArraySize(mSwingLows); - if (count >= required) - { - // - result = count; - return result; - } - - // - int range = SwingRange(); - 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; - } - - // - DetectSwingLow(bar); - - // - result = ArraySize(mSwingLows); - - // - return result; - } - - // - // Momentum Bars ... - int mMomentumBarExtendRange; // Momentum Bars must Extends Range ... - double mMomentumBarBodyPercent; // Momentum Bars Body Percent ... - - // - // Bullish ... - XCMomentumBar *mBullishMomentumBars[]; // Holds Founded Bullish Momentum Bars ... - - /** - * Detect Required Bullish Momentum Bars ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - * - * @return ( int ) - */ - int DetectRequiredBullishMomentumBars(int barIndex = 0) - { - // - int result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int required = MaxNumberOfRequiredPOIs(); - if (required <= 0) - { - return result; - } - - // - int count = ArraySize(mBullishMomentumBars); - if (count >= required) - { - // - result = count; - return result; - } - - // - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); - - // - XOHCL bar; - bool isInited = bar.Init( - symbol, - period, - barIndex // - ); - if (!isInited) - { - return result; - } - - // - DetectBullishMomentumBar(bar); - - // - result = ArraySize(mBullishMomentumBars); - - // - return result; - } - - // - // Bearish ... - XCMomentumBar *mBearishMomentumBars[]; // Holds Founded Bearish Momentum Bars ... - - /** - * Detect Required Bearish Momentum Bars ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - * - * @return ( int ) - */ - int DetectRequiredBearishMomentumBars(int barIndex = 0) - { - // - int result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int required = MaxNumberOfRequiredPOIs(); - if (required <= 0) - { - return result; - } - - // - int count = ArraySize(mBearishMomentumBars); - if (count >= required) - { - // - result = count; - return result; - } - - // - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); - - // - XOHCL bar; - bool isInited = bar.Init( - symbol, - period, - barIndex // - ); - if (!isInited) - { - return result; - } - - // - DetectBearishMomentumBar(bar); - - // - result = ArraySize(mBearishMomentumBars); - - // - return result; - } - - // - // Rejection Bars ... - int mRejectionBarExtendRange; // Rejection Bars must Extends Range ... - double mRejectionBarShadowPercent; // Rejection Bars Shadow Percent ... - - // - // Bullish ... - XCRejectionBar *mBullishRejectionBars[]; // Holds Founded Bullish Rejection Bars ... - - /** - * Detect Required Bullish Rejection Bars ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - * - * @return ( int ) - */ - int DetectRequiredBullishRejectionBars(int barIndex = 0) - { - // - int result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int required = MaxNumberOfRequiredPOIs(); - if (required <= 0) - { - return result; - } - - // - int count = ArraySize(mBullishRejectionBars); - if (count >= required) - { - // - result = count; - return result; - } - - // - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); - - // - XOHCL bar; - bool isInited = bar.Init( - symbol, - period, - barIndex // - ); - if (!isInited) - { - return result; - } - - // - DetectBullishRejectionBar(bar); - - // - result = ArraySize(mBullishRejectionBars); - - // - return result; - } - - // - // Bearish ... - XCRejectionBar *mBearishRejectionBars[]; // Holds Founded Bearish Rejection Bars ... - - /** - * Detect Required Bearish Rejection Bars ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - * - * @return ( int ) - */ - int DetectRequiredBearishRejectionBars(int barIndex = 0) - { - // - int result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int required = MaxNumberOfRequiredPOIs(); - if (required <= 0) - { - return result; - } - - // - int count = ArraySize(mBearishRejectionBars); - if (count >= required) - { - // - result = count; - return result; - } - - // - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); - - // - XOHCL bar; - bool isInited = bar.Init( - symbol, - period, - barIndex // - ); - if (!isInited) - { - return result; - } - - // - DetectBearishRejectionBar(bar); - - // - result = ArraySize(mBearishRejectionBars); - - // - return result; - } - - // - // Support and Resistance Zone ... - int mSupportAndResistanceRange; // Support and Resistance Range for Verification ... - - // - // Support Zone(s) ... - XCSupportZone *mSupportZones[]; // Holds Founded Support Zones ... - - /** - * 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 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 and Demand Zones ... - int mSupplyAndDemandRange; // Supply and Demand Range Verifications ... - - // - // Supply Zone(s) ... - XCSupplyZone *mSupplyZones[]; // Holds Founded Supply Zones ... - - /** - * Detect Required Supply Zones ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - * - * @return ( int ) - */ - int DetectRequiredSupplyZones(int barIndex) - { - // - int result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int required = MaxNumberOfRequiredPOIs(); - if (required <= 0) - { - return result; - } - - // - int count = ArraySize(mSupplyZones); - if (count >= required) - { - // - result = count; - return result; - } - - // - int range = SupplyAndDemandRange(); - if (range < 0) - { - return result; - } - - // - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); - - // - XOHCL bar; - bool isInited = bar.Init( - symbol, - period, - barIndex // - ); - if (!isInited) - { - return result; - } - - // - DetectSupplyZone(bar); - - // - result = ArraySize(mSupplyZones); - - // - return result; - } - - // - // Demand Zone(s) ... - XCDemandZone *mDemandZones[]; // Holds Founded Demand Zones ... - - /** - * Detect Required Demand Zones ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - * - * @return ( int ) - */ - int DetectRequiredDemandZones(int barIndex) - { - // - int result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int required = MaxNumberOfRequiredPOIs(); - if (required <= 0) - { - return result; - } - - // - int count = ArraySize(mDemandZones); - if (count >= required) - { - // - result = count; - return result; - } - - // - int range = SupplyAndDemandRange(); - if (range < 0) - { - return result; - } - - // - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); - - // - XOHCL bar; - bool isInited = bar.Init( - symbol, - period, - barIndex // - ); - if (!isInited) - { - return result; - } - - // - DetectDemandZone(bar); - - // - result = ArraySize(mDemandZones); - - // - return result; - } - - // - // Order Blocks ... - int mOrderBlocksSameBars; // Order Blocks Detection Bars ... - - // - // Bullish OB ... - XCOrderBlock *mBullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ... - - /** - * Detect Required Bullish Order Blocks ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - * - * @return ( int ) - */ - int DetectRequiredBullishOrderBlocks(int barIndex) - { - // - int result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int required = MaxNumberOfRequiredPOIs(); - if (required <= 0) - { - return result; - } - - // - int count = ArraySize(mBullishOrderBlocks); - if (count >= required) - { - // - result = count; - return result; - } - - // - int sameBars = OrderBlocksSameBars(); - if (sameBars < 0) - { - return result; - } - - // - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); - - // - XOHCL bar; - bool isInited = bar.Init( - symbol, - period, - barIndex // - ); - if (!isInited) - { - return result; - } - - // - DetectBullishOrderBlock(bar); - - // - result = ArraySize(mBullishOrderBlocks); - - // - return result; - } - - // - // Bearish OB ... - XCOrderBlock *mBearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ... - - /** - * Detect Required Bearish Order Blocks ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - * - * @return ( int ) - */ - int DetectRequiredBearishOrderBlocks(int barIndex) - { - // - int result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int required = MaxNumberOfRequiredPOIs(); - if (required <= 0) - { - return result; - } - - // - int count = ArraySize(mBearishOrderBlocks); - if (count >= required) - { - // - result = count; - return result; - } - - // - int sameBars = OrderBlocksSameBars(); - if (sameBars < 0) - { - return result; - } - - // - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); - - // - XOHCL bar; - bool isInited = bar.Init( - symbol, - period, - barIndex // - ); - if (!isInited) - { - return result; - } - - // - DetectBearishOrderBlock(bar); - - // - result = ArraySize(mBearishOrderBlocks); - - // - return result; - } - - // - // Fair Value Gaps ... - int mFairValueGapsSameBars; // Fair Value Gaps Detection Same Bars ... - - // - // Bullish FVG ... - XCFVG *mBullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ... - - /** - * Detect Required Bullish Fair Value Gaps ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - * - * @return ( int ) - */ - int DetectRequiredBullishFairValueGaps(int barIndex) - { - // - int result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int required = MaxNumberOfRequiredPOIs(); - if (required <= 0) - { - return result; - } - - // - int count = ArraySize(mBullishFairValueGaps); - if (count >= required) - { - // - result = count; - return result; - } - - // - int sameBars = FairValueGapsSameBars(); - if (sameBars < 0) - { - return result; - } - - // - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); - - // - XOHCL bar; - bool isInited = bar.Init( - symbol, - period, - barIndex // - ); - if (!isInited) - { - return result; - } - - // - DetectBullishFairValueGap(bar); - - // - result = ArraySize(mBullishFairValueGaps); - - // - return result; - } - - // - // Bearish FVG ... - XCFVG *mBearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ... - - /** - * Detect Required Bearish Fair Value Gaps ... - * - * @param barIndex: Integer Start bar index ... - * 0 is Default ... - * - * @return ( int ) - */ - int DetectRequiredBearishFairValueGaps(int barIndex) - { - // - int result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int required = MaxNumberOfRequiredPOIs(); - if (required <= 0) - { - return result; - } - - // - int count = ArraySize(mBearishFairValueGaps); - if (count >= required) - { - // - result = count; - return result; - } - - // - int sameBars = FairValueGapsSameBars(); - if (sameBars < 0) - { - return result; - } - - // - string symbol = GetSymbol(); - ENUM_TIMEFRAMES period = GetPeriod(); - - // - XOHCL bar; - bool isInited = bar.Init( - symbol, - period, - barIndex // - ); - if (!isInited) - { - return result; - } - - // - DetectBearishFairValueGap(bar); - - // - result = ArraySize(mBearishFairValueGaps); - - // - 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 ... + * Detect Swing Bars ... * * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... * * @return ( bool ) */ - bool DetectTicksZoneRange(XOHCL &bar) + bool DetectSwing( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false // + ) { // bool result = false; + // + state = X_POI_EVENT_NONE; + // result = bar.IsValid(); if (!result) @@ -4164,22 +1477,38 @@ class XCPOIDetector : public XCBaseAlert } // - int ticksLevels = TicksRangeZoneLevel(); - int ticksRange = TicksRangeZoneRange(); - result = ticksLevels > 0 && - ticksRange > 0; + ENUM_X_DIRECTION iDir; + result = mBarAnalyser.IsSwing( + bar, + iDir, + mSwingRange // + ); + + // + result = result && + HasDirection(iDir); if (!result) { return result; } // - int startBarIndex = bar.Index() + ticksRange; - XOHCL startBar; - result = startBar.Init( - bar.symbol, - bar.period, - startBarIndex // + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + + // + ENUM_XPOIS type = + isBullish + ? X_POI_SWING_LOW + : X_POI_SWING_HIGH; + + // + // Swing Object ... + XCSwing *swing; + swing = new XCSwing(); + result = swing.Init( + bar, + type // ); if (!result) { @@ -4187,30 +1516,1513 @@ class XCPOIDetector : public XCBaseAlert } // - mTicksZone = new XCTicksZone(); - result = mTicksZone.Init( - startBar, + // Add ... + + // + int idx = FindIndex( + swing, + mSwings // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + + // + if (reversal) + { + // + ArrayReverse(mSwings); + + // + Add( + swing, + mSwings // + ); + + // + ArrayReverse(mSwings); + } + else + { + // + Add( + swing, + mSwings // + ); + } + + // + if (isBullish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mSwings); + + // + Add( + swing, + mSwings // + ); + + // + ArrayReverse(mSwings); + } + else + { + // + Add( + swing, + mSwingLows // + ); + } + } + else if (isBearish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mSwingHighs); + + // + Add( + swing, + mSwingHighs // + ); + + // + ArrayReverse(mSwingHighs); + } + else + { + // + Add( + swing, + mSwingHighs // + ); + } + } + + // + state = + isBullish + ? X_SWING_LOW_DETECTED + : X_SWING_HIGH_DETECTED; + + // + return result; + } + + /** + * Detect Momentum Bars ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectMomentumBar( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION iDir; + result = mBarAnalyser.IsMomentumBar( + bar, + iDir, + mMomentumExtend, // Extends ... + mMomentumBodyPercent // Body Percent ... + ); + + // + result = result && + HasDirection(iDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + + // + ENUM_XPOIS type = + isBullish + ? X_POI_MOMENTUM_BAR + : X_POI_MOMENTUM_BAR; + + // + // Swing Object ... + XCMomentumBar *momentum; + momentum = new XCMomentumBar(); + result = momentum.Init( bar // ); if (!result) { - // - mTicksZone = NULL; return result; } + // + int idx = FindIndex( + momentum, + mMomentumBars // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + + // + // Add ... + if (reversal) + { + // + ArrayReverse(mMomentumBars); + + // + Add( + momentum, + mMomentumBars // + ); + + // + ArrayReverse(mMomentumBars); + } + else + { + // + Add( + momentum, + mMomentumBars // + ); + } + + // + if (isBullish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBullishMomentumBars); + + // + Add( + momentum, + mBullishMomentumBars // + ); + + // + ArrayReverse(mBullishMomentumBars); + } + else + { + // + Add( + momentum, + mBullishMomentumBars // + ); + } + } + else if (isBearish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBearishMomentumBars); + + // + Add( + momentum, + mBearishMomentumBars // + ); + + // + ArrayReverse(mBearishMomentumBars); + } + else + { + // + Add( + momentum, + mBearishMomentumBars // + ); + } + } + + // + state = + isBullish + ? X_BULLISH_MOMENTUM_BAR_DETECTED + : X_BEARISH_MOMENTUM_BAR_DETECTED; + + // + return result; + } + + /** + * Detect Rejection Bars ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectRejectionBar( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION iDir; + result = mBarAnalyser.IsRejectionBar( + bar, + iDir, + mRejectionExtend, // Extends ... + mRejectionShadowPercent // Shadow Percent ... + ); + + // + result = result && + HasDirection(iDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + + // + ENUM_XPOIS type = + isBullish + ? X_POI_MOMENTUM_BAR + : X_POI_MOMENTUM_BAR; + + // + // Swing Object ... + XCRejectionBar *rejection; + rejection = new XCRejectionBar(); + result = rejection.Init( + bar // + ); + if (!result) + { + return result; + } + + // + int idx = FindIndex( + rejection, + mRejectionBars // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + + // + // Add ... + if (reversal) + { + // + ArrayReverse(mRejectionBars); + + // + Add( + rejection, + mRejectionBars // + ); + + // + ArrayReverse(mRejectionBars); + } + else + { + // + Add( + rejection, + mRejectionBars // + ); + } + + // + if (isBullish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBullishRejectionBars); + + // + Add( + rejection, + mBullishRejectionBars // + ); + + // + ArrayReverse(mBullishRejectionBars); + } + else + { + // + Add( + rejection, + mBullishRejectionBars // + ); + } + } + else if (isBearish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBearishRejectionBars); + + // + Add( + rejection, + mBearishRejectionBars // + ); + + // + ArrayReverse(mBearishRejectionBars); + } + else + { + // + Add( + rejection, + mBearishRejectionBars // + ); + } + } + + // + state = + isBullish + ? X_BULLISH_REJECTION_BAR_DETECTED + : X_BEARISH_REJECTION_BAR_DETECTED; + + // + return result; + } + + /** + * Detect Support Zone ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectSupportZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false, + bool forceActivation = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL supportBar; + result = mBarAnalyser + .HasSupport( + bar, + supportBar, + mSupResRange // + ); + if (!result) + { + // + supportBar.Clean(); + + // + return result; + } + + // + XCSupportZone *supportZone; + supportZone = new XCSupportZone(); + result = supportZone.Init( + supportBar, + mSupResRange, + mSupResRangeAsStart // Use Range As Start ... + ); + if (!result) + { + // + supportBar.Clean(); + ZeroMemory(supportZone); + + // + return result; + } + + // + // Check Zone Not Activated ... + if (forceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = supportZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + supportBar.Clean(); + activationBar.Clean(); + ZeroMemory(supportZone); + + // + return result; + } + } + + // + // Add ... + + // + int idx = FindIndex( + supportZone, + mSupportZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + supportBar.Clean(); + activationBar.Clean(); + ZeroMemory(supportZone); + + // + return result; + } + + // + if (reversal) + { + // + ArrayReverse(mSupportZones); + + // + Add( + supportZone, + mSupportZones // + ); + + // + ArrayReverse(mSupportZones); + } + else + { + // + Add( + supportZone, + mSupportZones // + ); + } + + // + state = X_SUPPORT_ZONE_DETECTED; + + // + supportBar.Clean(); + activationBar.Clean(); + + // + return result; + } + + /** + * Detect Resistance Zone ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectResistanceZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false, + bool forceActivation = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL resistanceBar; + result = mBarAnalyser + .HasResistance( + bar, + resistanceBar, + mSupResRange // + ); + if (!result) + { + // + resistanceBar.Clean(); + + // + return result; + } + + // + XCResistanceZone *resistanceZone; + resistanceZone = new XCResistanceZone(); + result = resistanceZone.Init( + resistanceBar, + mSupResRange, + mSupResRangeAsStart // Use Range As Start ... + ); + if (!result) + { + // + resistanceBar.Clean(); + ZeroMemory(resistanceZone); + + // + return result; + } + + // + // Check Zone Not Activated ... + if (forceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = resistanceZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + resistanceBar.Clean(); + activationBar.Clean(); + ZeroMemory(resistanceZone); + + // + return result; + } + } + + // + // Add ... + + // + int idx = FindIndex( + resistanceZone, + mResistanceZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + resistanceBar.Clean(); + activationBar.Clean(); + ZeroMemory(resistanceZone); + + // + return result; + } + + // + if (reversal) + { + // + ArrayReverse(mResistanceZones); + + // + Add( + resistanceZone, + mResistanceZones // + ); + + // + ArrayReverse(mResistanceZones); + } + else + { + // + Add( + resistanceZone, + mResistanceZones // + ); + } + + // + state = X_RESISTANCE_ZONE_DETECTED; + + // + resistanceBar.Clean(); + activationBar.Clean(); + + // + return result; + } + + /** + * Detect Supply Zone ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectSupplyZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false, + bool forceActivation = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int mSupDemRange = mSupResRange * 2; + + // + XOHCL supplyBar; + result = mBarAnalyser + .HasResistance( + bar, + supplyBar, + mSupDemRange // + ); + if (!result) + { + // + supplyBar.Clean(); + + // + return result; + } + + // + XCSupplyZone *supplyZone; + supplyZone = new XCSupplyZone(); + result = supplyZone.Init( + supplyBar, + mSupDemRange, + mSupResRangeAsStart // Use Range As Start ... + ); + if (!result) + { + // + supplyBar.Clean(); + ZeroMemory(supplyZone); + + // + return result; + } + + // + // Check Zone Not Activated ... + if (forceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = supplyZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + supplyBar.Clean(); + activationBar.Clean(); + ZeroMemory(supplyZone); + + // + return result; + } + } + + // + // Add ... + + // + int idx = FindIndex( + supplyZone, + mSupplyZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + supplyBar.Clean(); + activationBar.Clean(); + ZeroMemory(supplyZone); + + // + return result; + } + + // + if (reversal) + { + // + ArrayReverse(mSupplyZones); + + // + Add( + supplyZone, + mSupplyZones // + ); + + // + ArrayReverse(mSupplyZones); + } + else + { + // + Add( + supplyZone, + mSupplyZones // + ); + } + + // + state = X_SUPPLY_ZONE_DETECTED; + + // + supplyBar.Clean(); + activationBar.Clean(); + + // + return result; + } + + /** + * Detect Demand Zone ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectDemandZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false, + bool forceActivation = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int mSupDemRange = mSupResRange * 2; + + // + XOHCL demandBar; + result = mBarAnalyser + .HasSupport( + bar, + demandBar, + mSupDemRange // + ); + if (!result) + { + // + demandBar.Clean(); + + // + return result; + } + + // + XCDemandZone *demandZone; + demandZone = new XCDemandZone(); + result = demandZone.Init( + demandBar, + mSupDemRange, + mSupResRangeAsStart // Use Range As Start ... + ); + if (!result) + { + // + demandBar.Clean(); + ZeroMemory(demandZone); + + // + return result; + } + + // + // Check Zone Not Activated ... + if (forceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = demandZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + demandBar.Clean(); + activationBar.Clean(); + ZeroMemory(demandZone); + + // + return result; + } + } + + // + // Add ... + + // + int idx = FindIndex( + demandZone, + mDemandZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + demandBar.Clean(); + activationBar.Clean(); + ZeroMemory(demandZone); + + // + return result; + } + + // + if (reversal) + { + // + ArrayReverse(mDemandZones); + + // + Add( + demandZone, + mDemandZones // + ); + + // + ArrayReverse(mDemandZones); + } + else + { + // + Add( + demandZone, + mDemandZones // + ); + } + + // + state = X_DEMAND_ZONE_DETECTED; + + // + demandBar.Clean(); + activationBar.Clean(); + + // + return result; + } + + /** + * Detect Order Blocks ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectOrderBlock( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false, + bool forceActivation = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL obBar; + ENUM_X_DIRECTION obDir; + result = mBarAnalyser.HasOrderBlock( + bar, + obBar, + obDir, + mOrderBlockSameBars // + ); + if (!result) + { + // + obBar.Clean(); + + // + return result; + } + + // + XCOrderBlock *ob; + ob = new XCOrderBlock(); + result = ob.Init( + obBar, + obDir // + ); + if (!result) + { + // + obBar.Clean(); + ZeroMemory(ob); + + // + return result; + } + + // + bool isBullish = IsBullish(obDir); + bool isBearish = IsBearish(obDir); + + // + // Check Zone Not Activated ... + if (forceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = ob.IsActivated( + obDir, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + obBar.Clean(); + activationBar.Clean(); + ZeroMemory(ob); + + // + return result; + } + } + + // + int idx = FindIndex( + ob, + mOrderBlocks // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + obBar.Clean(); + activationBar.Clean(); + ZeroMemory(ob); + + // + return result; + } + + // + // Add ... + if (reversal) + { + // + ArrayReverse(mOrderBlocks); + + // + Add( + ob, + mOrderBlocks // + ); + + // + ArrayReverse(mOrderBlocks); + } + else + { + // + Add( + ob, + mOrderBlocks // + ); + } + + // + if (isBullish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBullishOrderBlocks); + + // + Add( + ob, + mBullishOrderBlocks // + ); + + // + ArrayReverse(mBullishOrderBlocks); + } + else + { + // + Add( + ob, + mBullishOrderBlocks // + ); + } + } + else if (isBearish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBearishOrderBlocks); + + // + Add( + ob, + mBearishOrderBlocks // + ); + + // + ArrayReverse(mBearishOrderBlocks); + } + else + { + // + Add( + ob, + mBearishOrderBlocks // + ); + } + } + + // + state = + isBullish + ? X_BULLISH_ORDERBLOCK_DETECTED + : X_BEARISH_ORDERBLOCK_DETECTED; + + // + obBar.Clean(); + activationBar.Clean(); + + // + return result; + } + + /** + * Detect Fair Value Gaps ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectFairValueGap( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false, + bool forceActivation = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL fvgStartBar; + XOHCL fvgEndBar; + ENUM_X_DIRECTION fvgDir; + result = mBarAnalyser.HasFairValueGap( + bar, + fvgStartBar, + fvgEndBar, + fvgDir, + mFairValueGapSameBars // + ); + if (!result) + { + // + fvgEndBar.Clean(); + fvgStartBar.Clean(); + + // + return result; + } + + // + XCFVG *fvg; + fvg = new XCFVG(); + result = fvg.Init( + fvgStartBar, + fvgEndBar, + fvgDir // + ); + if (!result) + { + // + ZeroMemory(fvg); + fvgEndBar.Clean(); + fvgStartBar.Clean(); + + // + return result; + } + + // + bool isBullish = IsBullish(fvgDir); + bool isBearish = IsBearish(fvgDir); + + // + // Check Zone Not Activated ... + if (forceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = fvg.IsActivated( + fvgDir, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + ZeroMemory(fvg); + fvgEndBar.Clean(); + fvgStartBar.Clean(); + activationBar.Clean(); + + // + return result; + } + } + + // + int idx = FindIndex( + fvg, + mFairValueGaps // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + ZeroMemory(fvg); + fvgEndBar.Clean(); + fvgStartBar.Clean(); + activationBar.Clean(); + + // + return result; + } + + // + // Add ... + if (reversal) + { + // + ArrayReverse(mFairValueGaps); + + // + Add( + fvg, + mFairValueGaps // + ); + + // + ArrayReverse(mFairValueGaps); + } + else + { + // + Add( + fvg, + mFairValueGaps // + ); + } + + // + if (isBullish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBullishFairValueGaps); + + // + Add( + fvg, + mBullishFairValueGaps // + ); + + // + ArrayReverse(mBullishFairValueGaps); + } + else + { + // + Add( + fvg, + mBullishFairValueGaps // + ); + } + } + else if (isBearish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBearishFairValueGaps); + + // + Add( + fvg, + mBearishFairValueGaps // + ); + + // + ArrayReverse(mBearishFairValueGaps); + } + else + { + // + Add( + fvg, + mBearishFairValueGaps // + ); + } + } + + // + state = + isBullish + ? X_BULLISH_FVG_DETECTED + : X_BEARISH_FVG_DETECTED; + + // + fvgEndBar.Clean(); + fvgStartBar.Clean(); + activationBar.Clean(); + // return result; } // - // Liquidity Zones ... + private: + // // - // Sell Side ... + // Props ... + string mSymbol; // Market Symbol ... + ENUM_TIMEFRAMES mPeriod; // Market Period ... + XBarTracker mBarTracker; // Market Bar Tracker ... + XCBarAnalyser *mBarAnalyser; // Bar Analyser ... // - // Buy Side ... + bool mLock; + + // + int mMaxRequiredPOIs; // Max Allowed Holds POI(s) ... + int maxAllowedLoopbackForInit; // Max Allowed Loopback for POI(s) Detection on Initialization Process ... + + // + TOnPOIEvent mEventListeners[]; // Event Listeners ... + + // + XCSwing *mSwings[]; // Holds Founded Swing ... + XCSwing *mSwingLows[]; // Holds Founded Swing Lows ... + XCSwing *mSwingHighs[]; // Holds Founded Swing Highs ... + int mSwingRange; // Swing Detection Range ... + + // + XCMomentumBar *mMomentumBars[]; // Holds Founded Momentum Bars ... + XCMomentumBar *mBullishMomentumBars[]; // Holds Founded Bullish Momentum Bars ... + XCMomentumBar *mBearishMomentumBars[]; // Holds Founded Bearish Momentum Bars ... + int mMomentumExtend; // Momentum Bar Detection Extends Range ... + double mMomentumBodyPercent; // Momentum Bar Detection Body Percent ... + + // + XCRejectionBar *mRejectionBars[]; // Holds Founded Rejection Bars ... + XCRejectionBar *mBullishRejectionBars[]; // Holds Founded Bullish Rejection Bars ... + XCRejectionBar *mBearishRejectionBars[]; // Holds Founded Bearish Rejection Bars ... + int mRejectionExtend; // Rejection Bar Detection Extends Range ... + double mRejectionShadowPercent; // Rejection Bar Detection Body Percent ... + + // + XCSupplyZone *mSupplyZones[]; // Holds Detected Supply Zones ... + XCDemandZone *mDemandZones[]; // Holds Detected Demand Zones ... + + // + int mSupResRange; // Support and Resistance Detection Range ... + bool mSupResRangeAsStart; // use Support and Resistance Range as Start ... + XCSupportZone *mSupportZones[]; // Holds Detected Support Zones ... + XCResistanceZone *mResistanceZones[]; // Holds Detected Resistance Zones ... + + // + XCFVG *mFairValueGaps[]; // Holds Founded FairValueGaps ... + XCFVG *mBullishFairValueGaps[]; // Holds Founded Bullish FairValueGaps ... + XCFVG *mBearishFairValueGaps[]; // Holds Founded Bearish FairValueGaps ... + int mFairValueGapSameBars; // FairValueGap Detection Same Bars ... + + // + XCOrderBlock *mOrderBlocks[]; // Holds Founded OrderBlocks ... + XCOrderBlock *mBullishOrderBlocks[]; // Holds Founded Bullish OrderBlocks ... + XCOrderBlock *mBearishOrderBlocks[]; // Holds Founded Bearish OrderBlocks ... + int mOrderBlockSameBars; // OrderBlock Detection Same Bars ... // }; diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index 898fa363..dad0249b 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -3093,7 +3093,7 @@ class XCPOIDrawer : public XCBase /** * Create Bar Arrow Object ... - * + * * @param bar: XOHCL instance Reference ... * @param priceType: ENUM_X_PRICE member ... * @param arrow: int, Arrow Code ... @@ -3101,7 +3101,7 @@ class XCPOIDrawer : public XCBase * @param width: int, Arrow Width ... * @param anchor: ENUM_ARROW_ANCHOR, anchor of Arrow ... * @param name: string, name of Arrow ... - * + * * @return ( bool ) */ bool CreateBarArrow( @@ -3141,10 +3141,10 @@ class XCPOIDrawer : public XCBase color mBearishColor = BarBearishColor(); // - prefix = + prefix = (IsValid(prefix) - ? prefix + "_" - : prefix) + + ? prefix + "_" + : prefix) + barTag; // @@ -3924,24 +3924,6 @@ class XCPOIDrawer : public XCBase } } - // - if (drawTicksZone && state.ticksZone != NULL) - { - // - XCTicksZoneObject *iObj; - bool isCreated = CreateTicksZone( - state.ticksZone, - iObj // - ); - if (isCreated) - { - Add( - (XCBaseObject *)iObj, - drawnObjects // - ); - } - } - // result = ArraySize(drawnObjects); @@ -4629,170 +4611,6 @@ class XCPOIDrawer : public XCBase } } - // - // Supply Zones ... - has = item.HasSupplyZones(); - if (has && - drawSupplyZones) - { - // - Clean(tmpObjects); - count = item.CountSupplyZones(); - for (int i = 0; i < count; i++) - { - // - XCSupplyZoneObject *iZoneObj; - has = CreateSupplyZone( - item.supplyZones[i], - iZoneObj // - ); - if (has) - { - // - Add( - (XCBaseObject *)iZoneObj, - tmpObjects // - ); - } - } - - // - count = ArraySize(tmpObjects); - has = IsValidSize(count); - if (has) - { - // - Copy( - tmpObjects, - objects, - false // - ); - } - } - - // - // Demand Zones ... - has = item.HasDemandZones(); - if (has && - drawDemandZones) - { - // - Clean(tmpObjects); - count = item.CountDemandZones(); - for (int i = 0; i < count; i++) - { - // - XCDemandZoneObject *iZoneObj; - has = CreateDemandZone( - item.demandZones[i], - iZoneObj // - ); - if (has) - { - // - Add( - (XCBaseObject *)iZoneObj, - tmpObjects // - ); - } - } - - // - count = ArraySize(tmpObjects); - has = IsValidSize(count); - if (has) - { - // - Copy( - tmpObjects, - objects, - false // - ); - } - } - - // - // Support Zones ... - has = item.HasSupportZones(); - if (has && - drawSupportZones) - { - // - Clean(tmpObjects); - count = item.CountSupportZones(); - for (int i = 0; i < count; i++) - { - // - XCSupportZoneObject *iZoneObj; - has = CreateSupportZone( - item.supportZones[i], - iZoneObj // - ); - if (has) - { - // - Add( - (XCBaseObject *)iZoneObj, - tmpObjects // - ); - } - } - - // - count = ArraySize(tmpObjects); - has = IsValidSize(count); - if (has) - { - // - Copy( - tmpObjects, - objects, - false // - ); - } - } - - // - // Resistance Zones ... - has = item.HasResistanceZones(); - if (has && - drawResistanceZones) - { - // - Clean(tmpObjects); - count = item.CountResistanceZones(); - for (int i = 0; i < count; i++) - { - // - XCResistanceZoneObject *iZoneObj; - has = CreateResistanceZone( - item.resistanceZones[i], - iZoneObj // - ); - if (has) - { - // - Add( - (XCBaseObject *)iZoneObj, - tmpObjects // - ); - } - } - - // - count = ArraySize(tmpObjects); - has = IsValidSize(count); - if (has) - { - // - Copy( - tmpObjects, - objects, - false // - ); - } - } - // Clean(tmpObjects); diff --git a/Documents/BKP/1.mq5 b/Documents/BKP/1.mq5 new file mode 100644 index 00000000..6bd53c04 --- /dev/null +++ b/Documents/BKP/1.mq5 @@ -0,0 +1,97 @@ + +// +// Fix Signal TP Based On Working Zone ... +// double maxAllowedTP = +// hasLong +// ? mXWZConditions.workingZone.upper +// : mXWZConditions.workingZone.lower; +// bool canApplyMaxAlowedTP = (hasLong && +// signal.tp > maxAllowedTP) || +// (!hasLong && signal.tp < maxAllowedTP); +// if (canApplyMaxAlowedTP) +// { +// signal.tp = maxAllowedTP; +// } + +// +// Configuring Global Protector ... +// signal.trailSL = true; +// signal.trailSLStartOnReachTPLevel = 3; +// signal.fullTPLevel = signal.GetRiskRewardRatio(); + +// // +// mXSupDemOBSSignalDetector.RemoveDraws(); +// mXSupDemOBSSignalDetector.DrawConditions( +// mXSupDemOBSConditions, +// mVisionCycleHelper.mPOIDrawer // +// ); + +// // +// mXSupDemOBSSignalDetector.RemoveWorkingZoneDraws(); +// mXSupDemOBSSignalDetector.DrawWorkingZone( +// mXSupDemOBSConditions, +// mVisionCycleHelper.mPOIDrawer // +// ); + +// +// bool canReplaceTarget = +// signal.target > 0 && +// (hasLong +// ? signal.target > signal.tp +// : signal.target < signal.tp); +// if (canReplaceTarget) +// { +// // +// signal.tp = conditions.target; +// signal.target = tp; +// } + + + // + // consolidationState.UpdateTo(cTime); + // XPOIState filtered; + // consolidationState.Filter( + // filtered, + // NULL, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // XCBaseObject *objects[]; + // int objectsCount = drawer.DrawState( + // filtered, + // objects // + // ); + // if (IsValidSize(objectsCount)) + // { + // // + // Print(""); + // } + + // // + // XOBFVG activeObfvgs[]; + // int activeObfvgsCount = ExtractOBFVGs( + // activeObfvgs, + // consolidationState, + // analyseState // + // ); + // bool hasActiveOBFVGs = IsValidSize(activeObfvgsCount); + // if (hasActiveOBFVGs) + // { + // // + // SpecifiedUpdateTo(activeObfvgs); + // for (int i = 0; i < activeObfvgsCount; i++) + // { + // // + // XCBaseObject *objects[]; + // int objectsCount = drawer.DrawOBFVG( + // activeObfvgs[i], + // objects // + // ); + // } + // } diff --git a/Documents/BKP/x-121.smc.xwz.signal.class.mq5 b/Documents/BKP/x-121.smc.xwz.signal.class.mq5 new file mode 100644 index 00000000..c80b6cc3 --- /dev/null +++ b/Documents/BKP/x-121.smc.xwz.signal.class.mq5 @@ -0,0 +1,3960 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: XWZ +// Description: provide all Signalling functions ... +// +// +// 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-121.smc.market.cycle.helper.class.mq5" +#include "../Libraries/x-121.smc.guard.lib.mq5" +#include "../Libraries/x-121.smc.lib.mq5" +#include "./x-121.smc.xwz.signal.lib.mq5" + +// +// Definition ... +class XCX121SMCXWZSignalDetector : public XCBase +{ + // + public: + // + // Props ... + XOBFVG chochZone; + XOBFVG targetZone; + XOBFVG signalZone; + XOBFVG waitingZone; + X121SMCStrategyXWZWorkingZone workingZone; + X121SMCStrategyXWZSignalConditions mConditions; + X121SMCStrategyXWZSignalConditions mConditionsCollection[]; + + // + // Constructor(s) ... + XCX121SMCXWZSignalDetector( + string _symbol, + ENUM_TIMEFRAMES _period // + ) + { + // + symbol = _symbol; + period = _period; + Init(); + } + + // + // Deconstructor ... + ~XCX121SMCXWZSignalDetector() + { + DeInit(); + } + + // + // + // + + // + // Detect Setup Conditions ... + bool DetectSignalSetup( + // + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper + // + ) + { + // + bool result = false; + + // + // Validate Cycle Helpers ... + result = + // + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL + // + ; + if (!result) + { + // + mConditions.Clean(); + + // + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + mConditions.symbol = symbol; + mConditions.period = period; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + double pivot = 0; + double point = 0; + double target = 0; + double reward = 0; + double amountPercent = 0; + ENUM_X121SMC_XWZ_PRIORITY priority = X121SMC_XWZ_PRIORITY_NONE; + + // + // Cycles Conditions ... + + // + XOHCL consolidationZBar; + result = consolidationCycleHelper.GetBar( + consolidationZBar, + zIndex // + ); + if (!result) + { + // + consolidationZBar.Clean(); + return result; + } + + // + bool drawBar = true; + if (drawBar) + { + // + DrawBar( + consolidationZBar, + decisionCycleHelper.mPOIDrawer // + ); + } + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(visionCycleEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + visionConditions.Clean(); + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Cycles POI States ... + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + X121Conditions consolidationXConditions = consolidationConditions.x121Conditions; + X121Conditions visionXConditions = visionConditions.x121Conditions; + + // + // Setup Conditions ... + + // + // Choch Trading Senario ... + bool hasChochBullishConditions = false; + bool hasChochBearishConditions = false; + + // + // Order Flow Side Trading Senario ... + bool hasOrderFlowhBullishConditions = false; + bool hasOrderFlowhBearishConditions = false; + + // + // Trend Line Trading Senario ... + bool hasTrendLineBullishConditions = false; + bool hasTrendLineBearishConditions = false; + + // + // Quarter Line Trading Senario ... + bool hasBQuarterLineBullishConditions = false; + bool hasBQuarterLineBearishConditions = false; + + // + // Supply and Demand Trading Senario ... + bool hasSupDemBullishConditions = false; + bool hasSupDemBearishConditions = false; + + // + // Support and Resistance Trading Senario ... + bool hasSupResBullishConditions = false; + bool hasSupResBearishConditions = false; + + // + ENUM_X121SMC_XWZ_PROVIDERS provider = X121SMC_XWZ_PROVIDER_NONE; + + // + // Detect Working Zone ... + bool hasWorkingZone = workingZone.IsValid(); + if (!hasWorkingZone) + { + hasWorkingZone = DetectWorkingZone(visionState); + } + + // + // result = hasWorkingZone; + // if (!result) + // { + // // + // Clean(visionPoiEvents); + // Clean(analysePoiEvents); + // Clean(decisionPoiEvents); + // Clean(consolidationPoiEvents); + + // // + // Clean(visionCycleEvents); + // Clean(analyseCycleEvents); + // Clean(decisionCycleEvents); + // Clean(consolidationCycleEvents); + + // // + // visionState.Clean(); + // analyseState.Clean(); + // decisionState.Clean(); + // consolidationState.Clean(); + + // // + // visionConditions.Clean(); + // analyseConditions.Clean(); + // decisionConditions.Clean(); + // consolidationConditions.Clean(); + + // // + // visionXConditions.Clean(); + // analyseXConditions.Clean(); + // decisionXConditions.Clean(); + // consolidationXConditions.Clean(); + + // // + // mConditions.Clean(); + // consolidationZBar.Clean(); + + // // + // return result; + // } + + // + // Supply Zones ... + bool hasSupplyZones = workingZone.HasSupplyZones(); + int supplyZonesCount = workingZone.CountSupplyZones(); + if (hasWorkingZone) + { + // + supplyZonesCount = workingZone + .DetectSupplyZones(consolidationState); + hasSupplyZones = IsValidSize(supplyZonesCount); + } + + // + // Demand Zones ... + bool hasDemandZones = workingZone.HasDemandZones(); + int demandZonesCount = workingZone.CountDemandZones(); + if (hasWorkingZone) + { + // + demandZonesCount = workingZone + .DetectDemandZones(consolidationState); + hasDemandZones = IsValidSize(demandZonesCount); + } + + // + // TODO: Remove this ... + UpdateTo(cTime); + + // + // Detect Working Zone Destroy ... + bool isWorkingZoneDetroyed = + hasWorkingZone && + workingZone.IsDestroyed(); + if (isWorkingZoneDetroyed) + { + mWorkingZoneObjects.Clear(); + } + + // + // result = !isWorkingZoneDetroyed; + // if (!result) + // { + // // + // workingZone.Clean(); + // mWorkingZoneObjects.Clear(); + + // // + // Clean(visionPoiEvents); + // Clean(analysePoiEvents); + // Clean(decisionPoiEvents); + // Clean(consolidationPoiEvents); + + // // + // Clean(visionCycleEvents); + // Clean(analyseCycleEvents); + // Clean(decisionCycleEvents); + // Clean(consolidationCycleEvents); + + // // + // visionState.Clean(); + // analyseState.Clean(); + // decisionState.Clean(); + // consolidationState.Clean(); + + // // + // visionConditions.Clean(); + // analyseConditions.Clean(); + // decisionConditions.Clean(); + // consolidationConditions.Clean(); + + // // + // visionXConditions.Clean(); + // analyseXConditions.Clean(); + // decisionXConditions.Clean(); + // consolidationXConditions.Clean(); + + // // + // mConditions.Clean(); + // consolidationZBar.Clean(); + + // // + // return result; + // } + + // + // Checking Target Zone Breaked ... + bool hasTargetZone = targetZone.IsValid(); + if (hasTargetZone) + { + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + zIndex // + ); + + XOHCL cBar; + isInited = + isInited && + bar.GetPreviousBar(cBar); + + // + bool isBullish = targetZone.IsBullish(); + + // + bool isLowerBreaked = + // + bar.high < targetZone.ob.Lower() && + cBar.high < targetZone.ob.Lower() + // + ; + + // + bool isUpperBreaked = + // + bar.low > targetZone.ob.Upper() && + cBar.low > targetZone.ob.Upper() + // + ; + + // + bool isBreaked = isBullish + ? isLowerBreaked + : isUpperBreaked; + if (isBreaked) + { + // + mWorkingZoneObjects.Clear(); + targetZone.Clean(); + } + } + + // + // Detect Order Flow ... + ENUM_X_DIRECTION trend = X_DIRECTION_NONE; + bool hasOrderFlow = + hasWorkingZone && + workingZone.HasOrderFlow(trend); + if (!hasOrderFlow) + { + // + int orderFlowCount = workingZone.DetectOrderFlow( + symbol, + period, + trend, + visionState, + consolidationState, + analyseState, + decisionState // + ); + hasOrderFlow = IsValidSize(orderFlowCount); + } + + // + bool hasTrend = HasDirection(trend); + bool hasBllishTrend = + hasTrend && + IsBullish(trend); + bool hasBearishTrend = + hasTrend && + IsBearish(trend); + + // + UpdateTo(cTime); + + // + isBullish = IsBullish(trend); + isBearish = IsBearish(trend); + + // + bool hasPriority = workingZone + .DetectPriority( + priority, + trend, + zIndex, + period // + ); + + // + bool hasRewardAmount = CalculateRiskReward( + priority, + reward, + amountPercent // + ); + + // + // Checking Order Flow Break ... + int breakedIDX = -1; + bool isOrderFlowBreaked = + hasOrderFlow && + hasWorkingZone && + workingZone.IsOrderFlowBreaked( + breakedIDX, + true, // Force OB Breaked + false, // Force FVG Breaked + zIndex, + period // + ); + + // + // Order Flow Breaked Senario ... + if (isOrderFlowBreaked) + { + // + AddRef( + workingZone.orderFlow[breakedIDX], + workingZone.brokenOrderFlow // + ); + + // + signalZone = workingZone.orderFlow[breakedIDX]; + provider = X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH; + + // + ArrayRemove( + workingZone.orderFlow, + breakedIDX, + 1 // + ); + Clean(workingZone.orderFlow); + + // + CleanupArray( + workingZone.brokenOrderFlow, + 10 // + ); + } + + // + // First Check Last Order Flow FVG ... + XOBFVG youngestOrderFlow; + int youngestOBFVGIDX = GetYoungest(workingZone.orderFlow); + bool hasYoungestOBFVG = IsValidIndex(youngestOBFVGIDX); + if (hasYoungestOBFVG) + { + // + youngestOrderFlow = workingZone.orderFlow[youngestOBFVGIDX]; + + // + XOHCL obWorkerBar; + XOHCL obActivationBar; + + // + XOHCL fvgWorkerBar; + XOHCL fvgActivationBar; + + // + bool isOBBodyOut = false; + bool isOBWorked = youngestOrderFlow + .ob + .IsWorked( + trend, + obWorkerBar, + isOBBodyOut, + false // + ); + + // + bool isOBBodyIn = false; + bool isOBActivated = youngestOrderFlow + .ob + .IsActivated( + trend, + obActivationBar, + isOBBodyIn, + false // + ); + + // + bool isFVGBodyOut = false; + bool isFVGWorked = youngestOrderFlow + .fvg + .IsWorked( + trend, + fvgWorkerBar, + isFVGBodyOut, + false // + ); + + // + bool isFVGBodyIn = false; + bool isFVGActivated = youngestOrderFlow + .fvg + .IsActivated( + trend, + fvgActivationBar, + isFVGBodyIn, + false // + ); + + // + if (!isFVGWorked && + isFVGActivated) + { + // + youngestOrderFlow + .UpdateZones(decisionState); + + // + signalZone = youngestOrderFlow; + youngestOrderFlow.Clean(); + ArrayRemove( + workingZone.orderFlow, + youngestOBFVGIDX, + 1 // + ); + + // + provider = X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE; + } + else + { + // + bool isPriceInsideFVG = + // + IsInside( + consolidationZBar.high, + youngestOrderFlow.fvg // + ) + // + && + // + IsInside( + consolidationZBar.low, + youngestOrderFlow.fvg // + ) + // + ; + + // + if (isPriceInsideFVG) + { + // + youngestOrderFlow + .UpdateZones(decisionState); + + // + signalZone = youngestOrderFlow; + youngestOrderFlow.Clean(); + ArrayRemove( + workingZone.orderFlow, + youngestOBFVGIDX, + 1 // + ); + + // + provider = X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE; + } + } + + // + fvgWorkerBar.Clean(); + fvgActivationBar.Clean(); + } + + // + // Check New Order Blocks ... + bool hasNewConsolidationBullishOB = Contains( + X_BULLISH_ORDERBLOCK_DETECTED, + consolidationPoiEvents // + ); + bool hasNewConsolidationBearishOB = Contains( + X_BEARISH_ORDERBLOCK_DETECTED, + consolidationPoiEvents // + ); + bool hasNewOB = hasNewConsolidationBullishOB || + hasNewConsolidationBearishOB; + + // + // Check New Fair Value Gaps ... + bool hasNewConsolidationBullishFVG = Contains( + X_BULLISH_FVG_DETECTED, + consolidationPoiEvents // + ); + bool hasNewConsolidationBearishFVG = Contains( + X_BEARISH_FVG_DETECTED, + consolidationPoiEvents // + ); + bool hasNewFVG = hasNewConsolidationBullishFVG || + hasNewConsolidationBearishFVG; + + // + // Check New Order Blocks ... + bool hasNewAnalyseBullishOrderBlock = Contains( + X_BULLISH_ORDERBLOCK_DETECTED, + analysePoiEvents // + ); + bool hasNewAnalyseBearishOrderBlock = Contains( + X_BEARISH_ORDERBLOCK_DETECTED, + analysePoiEvents // + ); + bool hasNewAnalyseOB = hasNewAnalyseBullishOrderBlock || + hasNewAnalyseBearishOrderBlock; + + // + // Check New Fair Value Gaps ... + bool hasNewAnalyseBullishFVG = Contains( + X_BULLISH_FVG_DETECTED, + analysePoiEvents // + ); + bool hasNewAnalyseBearishFVG = Contains( + X_BEARISH_FVG_DETECTED, + analysePoiEvents // + ); + bool hasNewAnalyseFVG = hasNewAnalyseBullishFVG || + hasNewAnalyseBearishFVG; + + // + // Do Order Flow Actions when new Order Blocks + // or FVGs Formed ... + if (hasNewOB || + hasNewFVG || + hasNewAnalyseOB || + hasNewAnalyseFVG) + { + // + XCFVG *newFVG = NULL; + XCOrderBlock *newOB = NULL; + XCFVG *newAnalyseFVG = NULL; + XCOrderBlock *newAnalyseOB = NULL; + + // + bool isValid = false; + bool hasWaitingZone = waitingZone.IsValid(); + + // + int idx = -1; + if (hasNewOB) + { + // + if (hasNewConsolidationBullishOB) + { + // + idx = consolidationState.CountBullishOrderBlocks() - 1; + newOB = consolidationState.bullishOrderBlocks[idx]; + } + else + { + // + idx = consolidationState.CountBearishOrderBlocks() - 1; + newOB = consolidationState.bearishOrderBlocks[idx]; + } + + // + if (hasWaitingZone) + { + } + else + { + // + isValid = + !waitingZone.HasOB() + ? true + : !IsSame( + newOB, + waitingZone.ob // + ); + if (isValid) + { + // + bool isAbove = IsAbove( + newOB, + youngestOrderFlow.ob, + true // Ignore Inside ... + ); + bool isBelow = IsBelow( + newOB, + youngestOrderFlow.ob, + true // Ignore Inside ... + ); + + // + isValid = + isBullish + ? isAbove + : isBelow; + + // + if (isValid) + { + waitingZone.ob = newOB; + } + } + } + } + + // + if (hasNewFVG) + { + // + if (hasNewConsolidationBullishFVG) + { + // + idx = consolidationState.CountBullishFairValueGaps() - 1; + newFVG = consolidationState.bullishFairValueGaps[idx]; + } + else + { + // + idx = consolidationState.CountBearishFairValueGaps() - 1; + newFVG = consolidationState.bearishFairValueGaps[idx]; + } + } + + // + if (hasNewAnalyseOB) + { + // + if (hasNewAnalyseBullishOrderBlock) + { + // + idx = analyseState.CountBullishOrderBlocks() - 1; + newAnalyseOB = analyseState.bullishOrderBlocks[idx]; + } + else + { + // + idx = analyseState.CountBearishOrderBlocks() - 1; + newAnalyseOB = analyseState.bearishOrderBlocks[idx]; + } + } + + // + if (hasNewAnalyseFVG) + { + // + if (hasNewAnalyseBullishFVG) + { + // + idx = analyseState.CountBullishFairValueGaps() - 1; + newAnalyseFVG = analyseState.bullishFairValueGaps[idx]; + } + else + { + // + idx = analyseState.CountBearishFairValueGaps() - 1; + newAnalyseFVG = analyseState.bearishFairValueGaps[idx]; + } + + // + if (hasWaitingZone) + { + } + else + { + // + if (waitingZone.HasOB()) + { + // + XCFVG *tmpFVGs[]; + XCFVG *tmpWorkingFVGs[]; + bool isOBBullish = waitingZone.ob.IsBullish(); + if (isOBBullish) + { + Copy( + analyseState.bullishFairValueGaps, + tmpFVGs // + ); + } + else + { + Copy( + analyseState.bearishFairValueGaps, + tmpFVGs // + ); + } + + // + for (int j = 0; j < ArraySize(tmpFVGs); j++) + { + // + XCFVG *jFVG = tmpFVGs[j]; + + // + // Check Start Date ... + bool isFromPassed = jFVG.From() > waitingZone.ob.From(); + if (!isFromPassed) + { + // + ZeroMemory(jFVG); + continue; + } + + // + // Check Place ... + + // + bool isAbove = IsAboveDiff( + jFVG, + waitingZone.ob, + true // + ); + + // + bool isBelow = IsBelowDiff( + jFVG, + waitingZone.ob, + true // + ); + + // + bool isInside = IsInsideDiff( + jFVG, + waitingZone.ob, + false // + ); + + // + bool isPlacePassed = + isInside || + (isBullish + ? isAbove + : isBelow); + if (!isPlacePassed) + { + // + ZeroMemory(jFVG); + continue; + } + + // + Add( + jFVG, + tmpWorkingFVGs // + ); + } + + // + int fvgsCount = ArraySize(tmpWorkingFVGs); + isValid = IsValidSize(fvgsCount); + if (isValid) + { + // + idx = + isBullish + ? GetLowest(tmpWorkingFVGs) + : GetHighest(tmpWorkingFVGs); + + // + if (IsValidIndex(idx)) + { + // + XCFVG *selectedFVG = tmpWorkingFVGs[idx]; + + // + waitingZone.fvg = selectedFVG; + + // + bool isExists = FindIndex( + idx, + selectedFVG, + tmpFVGs // + ); + if (isExists) + { + // + ArrayRemove( + tmpFVGs, + idx, + 1 // + ); + } + } + } + + // + Clean(tmpFVGs); + Clean(tmpWorkingFVGs); + } + } + } + + // + hasWaitingZone = waitingZone.IsValid(); + if (hasWaitingZone) + { + // + bool isSameDir = waitingZone.GetDirection() == trend; + if (!isSameDir) + { + targetZone = waitingZone; + } + else + { + workingZone.AddOrderFlowItem(waitingZone); + } + + // + waitingZone.Clean(); + } + + // + if (signalZone.IsValid() && + provider == X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH) + { + // + ENUM_X_DIRECTION iForDir = Opposit(signalZone.GetDirection()); + if (hasNewAnalyseOB && + hasNewAnalyseFVG) + { + // + bool isSameDir = + newAnalyseOB.GetDirection() == iForDir && + newAnalyseFVG.GetDirection() == iForDir; + bool isOneInsideAnoter = + // + (newAnalyseFVG.Upper() < newAnalyseOB.Upper() && + newAnalyseFVG.Upper() > newAnalyseOB.Lower()) + // + || + // + (newAnalyseOB.Upper() < newAnalyseFVG.Upper() && + newAnalyseOB.Upper() > newAnalyseFVG.Lower()) + // + ; + + // + bool isZoneDetected = + isSameDir && + isOneInsideAnoter; + if (isZoneDetected) + { + // + XOBFVG iSignalZone; + iSignalZone.ob = newAnalyseOB; + iSignalZone.fvg = newAnalyseFVG; + + // + chochZone = iSignalZone; + } + } + } + + // + ZeroMemory(newOB); + ZeroMemory(newFVG); + ZeroMemory(newAnalyseOB); + ZeroMemory(newAnalyseFVG); + } + + // + bool isPriceInsideCHOCHZone = false; + bool hasCHOCHZone = chochZone.IsValid(); + if (hasCHOCHZone) + { + // + XOHCL cBar; + bool isInited = cBar.Init( + symbol, + period, + cIndex // + ); + + // + isPriceInsideCHOCHZone = + isInited && + cBar.low >= chochZone.fvg.Lower() && + cBar.high <= chochZone.fvg.Upper(); + if (isPriceInsideCHOCHZone) + { + // + // Reverse Trend and ReCalculate Requirements + // For CHOCH Tradng ... + + // + trend = chochZone.GetDirection(); + + // + isBullish = IsBullish(trend); + isBearish = IsBearish(trend); + + // + bool hasPriority = workingZone + .DetectPriority( + priority, + trend, + zIndex, + period // + ); + + // + bool hasRewardAmount = CalculateRiskReward( + priority, + reward, + amountPercent // + ); + + // + provider = X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH; + } + + // + cBar.Clean(); + } + + // + // + // + + // + if (hasSupplyZones || + hasDemandZones) + { + // + UpdateTo(cTime); + DrawWorkingZone( + visionCycleHelper.mPOIDrawer // + ); + Print("CHECK ..."); + } + + // + // Reading Trand Line Value ... + double zValue = workingZone.GetOrderFlowTrendLinePrice( + zIndex, + period // + ); + double cValue = workingZone.GetOrderFlowTrendLinePrice( + cIndex, + period // + ); + double pValue = workingZone.GetOrderFlowTrendLinePrice( + pIndex, + period // + ); + double ppValue = workingZone.GetOrderFlowTrendLinePrice( + ppIndex, + period // + ); + + // + // Implementing Signals ... + // + + // + // TODO: Implement Order Flow Side Trading Senario ... + bool hasOrderFlowConditions = + hasTrend && + hasPriority && + hasRewardAmount && + signalZone.IsValid() && + provider == X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE; + + // + hasOrderFlowhBullishConditions = + isBullish && + hasOrderFlowConditions && + signalZone.IsBullish(); + + // + hasOrderFlowhBearishConditions = + isBearish && + hasOrderFlowConditions && + signalZone.IsBearish(); + + // + if (hasOrderFlowConditions) + { + // + mConditions.signalZone = signalZone; + + // + point = hasOrderFlowhBullishConditions + ? signalZone.ob.Upper() + : signalZone.ob.Lower(); + + // + pivot = hasOrderFlowhBullishConditions + ? signalZone.ob.Lower() + : signalZone.ob.Upper(); + + // + signalZone.Clean(); + } + + // + // TODO: Implement Inside Zone Trading Senario ... + bool hasInsideZoneConditions = + hasTrend && + hasPriority && + hasRewardAmount && + signalZone.IsValid() && + provider == X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE; + + // + bool hasInsideZoneBullishConditions = + isBullish && + signalZone.IsBullish() && + hasInsideZoneConditions; + + // + bool hasInsideZoneBearishConditions = + isBearish && + signalZone.IsBearish() && + hasInsideZoneConditions; + + // + if (hasInsideZoneConditions) + { + // + mConditions.signalZone = signalZone; + + // + point = hasOrderFlowhBullishConditions + ? signalZone.ob.Upper() + : signalZone.ob.Lower(); + + // + pivot = hasOrderFlowhBullishConditions + ? signalZone.ob.Lower() + : signalZone.ob.Upper(); + + // + signalZone.Clean(); + } + + // + // TODO: Implement CHOCH Trading Senario ... + bool hasCHOCHConditions = + hasCHOCHZone && + chochZone.IsValid() && + isPriceInsideCHOCHZone && + provider == X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH; + + // + hasChochBullishConditions = + hasCHOCHConditions && + chochZone.IsBullish(); + hasChochBearishConditions = + hasCHOCHConditions && + chochZone.IsBearish(); + + // + if (hasCHOCHConditions) + { + // + mConditions.signalZone = chochZone; + + // + point = hasChochBullishConditions + ? chochZone.ob.Upper() + : chochZone.ob.Lower(); + + // + pivot = hasChochBearishConditions + ? chochZone.ob.Lower() + : chochZone.ob.Upper(); + + // + chochZone.Clean(); + signalZone.Clean(); + } + + // + // TODO: Implement Trend Line Trading Senario ... + + // + // TODO: Implement Quarter Line Trading Senario ... + + // + // TODO: Implement Supply and Demand Trading Senario ... + + // + // TODO: Implement Support and Resistance Trading Senario ... + + // + // TODO: Implement Mitigation Blocks Trading Senario ... + + // + // Summarize ... + + // + bool hasBullishConditions = + // + hasChochBullishConditions || + hasSupDemBullishConditions || + hasSupResBullishConditions || + hasTrendLineBullishConditions || + hasOrderFlowhBullishConditions || + hasInsideZoneBullishConditions || + hasBQuarterLineBullishConditions + // + ; + + // + bool hasBearishConditions = + // + hasChochBearishConditions || + hasSupDemBearishConditions || + hasSupResBearishConditions || + hasTrendLineBearishConditions || + hasOrderFlowhBearishConditions || + hasInsideZoneBearishConditions || + hasBQuarterLineBearishConditions + // + ; + + // + result = + hasBullishConditions || + hasBearishConditions; + + // + if (result) + { + // + mConditions.dir = trend; + mConditions.pivot = pivot; + mConditions.point = point; + mConditions.reward = reward; + mConditions.setupTime = cTime; + mConditions.priority = priority; + mConditions.provider = provider; + mConditions.amountPercent = amountPercent; + } + + // + // Cleanups ... + + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(visionCycleEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + visionState.Clean(); + analyseState.Clean(); + decisionState.Clean(); + consolidationState.Clean(); + + // + visionConditions.Clean(); + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + visionXConditions.Clean(); + analyseXConditions.Clean(); + decisionXConditions.Clean(); + consolidationXConditions.Clean(); + + // + // mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Detect Trigger Conditions ... + bool DetectSignalTrigger( + // + X121SMCStrategyXWZSignalConditions &conditions, + // + string _symbol, + ENUM_TIMEFRAMES _period, + // + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper, + // + int maxAllowedSetupAge = 60 + // + ) + { + // + bool result = false; + + // + result = + // + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL + // + ; + if (!result) + { + return result; + } + + // + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + datetime setupTime = conditions.setupTime; + ENUM_X_DIRECTION setupDir = conditions.dir; + + // + bool isBullish = IsBullish(setupDir); + bool isBearish = IsBearish(setupDir); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + double sls[]; + + // + // Cycles Conditions ... + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + // Cleanup ... + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + + // + return result; + } + + // + // Cycles POI States ... + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + + // + // Check Signal Validation ... + + // + XOHCL cBar; + bool isInited = cBar.Init( + conditions.symbol, + conditions.period, + cIndex // + ); + XOHCL pBar; + isInited = + isInited && + cBar.GetPreviousBar(pBar); + bool isLowerBreaked = + // + isInited && + cBar.high < conditions.point && + pBar.high >= conditions.point + // + ; + bool isUpperBreaked = + // + isInited && + cBar.low > conditions.point && + pBar.low <= conditions.point + // + ; + bool isZoneBreaked = + (isBullish && + isLowerBreaked) || + (isBearish && + isUpperBreaked); + result = !isZoneBreaked; + if (!result) + { + // + cBar.Clean(); + pBar.Clean(); + conditions.Clean(); + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionState.Clean(); + decisionConditions.Clean(); + decisionXConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseState.Clean(); + analyseConditions.Clean(); + analyseXConditions.Clean(); + } + + // + cBar.Clean(); + pBar.Clean(); + + // + double bullishScore = 0; + double bearishScore = 0; + decisionXConditions.GenerateScore( + bullishScore, + bearishScore // + ); + bool isBullishScorePassed = + isBullish && + bullishScore > (bearishScore * 1.5); + bool isBearishScorePassed = + isBearish && + bearishScore > (bullishScore * 1.5); + bool isScorePassed = isBullishScorePassed || + isBearishScorePassed; + + // + // Base SL Used Pivot of Conditions ... + // Add( + // conditions.pivot, + // sls // + // ); + + // + int lowestSupportIDX = -1; + int highestResistanceIDX = -1; + bool isSupportRejected = false; + bool isResistanceRejected = false; + bool hasSignalZone = conditions.signalZone.IsValid(); + if (hasSignalZone) + { + // + conditions + .signalZone + .UpdateZones(decisionState); + conditions + .signalZone + .UpdateTo(cTime); + + // + XOHCL cBar; + bool isBarInited = cBar.Init( + conditions.symbol, + conditions.period, + cIndex // + ); + + // + lowestSupportIDX = GetLowest(conditions.signalZone.supportZones); + if (IsValidIndex(lowestSupportIDX)) + { + // + isSupportRejected = + // + isBarInited && + ( + // + (cBar.low < conditions.signalZone.supportZones[lowestSupportIDX].Upper() && + cBar.GetDown() > conditions.signalZone.supportZones[lowestSupportIDX].Upper()) + // + || + // + (cBar.low < conditions.signalZone.supportZones[lowestSupportIDX].Lower() && + cBar.GetDown() > conditions.signalZone.supportZones[lowestSupportIDX].Lower()) + // + ) + // + ; + + // + isSupportRejected = + isBullish && + isSupportRejected; + if (isSupportRejected) + { + // + double vPivot = conditions.signalZone.supportZones[lowestSupportIDX].Lower(); + bool canSetPivot = vPivot > conditions.pivot && + vPivot < conditions.point; + if (canSetPivot) + { + // + Add( + vPivot, + sls // + ); + } + } + } + + // + highestResistanceIDX = GetHighest(conditions.signalZone.resistanceZones); + if (IsValidIndex(highestResistanceIDX)) + { + // + isResistanceRejected = + // + isBarInited && + ( + // + (cBar.high > conditions.signalZone.resistanceZones[highestResistanceIDX].Upper() && + cBar.GetUp() < conditions.signalZone.resistanceZones[highestResistanceIDX].Upper()) + // + || + // + (cBar.high > conditions.signalZone.resistanceZones[highestResistanceIDX].Lower() && + cBar.GetUp() < conditions.signalZone.resistanceZones[highestResistanceIDX].Lower()) + // + ) + // + ; + + // + isResistanceRejected = + isBearish && + isResistanceRejected; + if (isResistanceRejected) + { + // + double vPivot = conditions.signalZone.resistanceZones[highestResistanceIDX].Upper(); + bool canSetPivot = vPivot < conditions.pivot && + vPivot > conditions.point; + if (canSetPivot) + { + // + Add( + vPivot, + sls // + ); + } + } + } + + // + cBar.Clean(); + } + + // + // Consolidation Zone Detection ... + + // + // Detect Consolidation Zones ... + + // + // Bullish Consolidation Zone ... + XConsolidationZone bullishCZones[]; + bool hasBullishConsolidationZone = false; + XConsolidationZone bullishConsolidationZone; + int bullishCZonesCount = decisionCycleHelper.FillConsolidationZones( + X_DIRECTION_BULLISH, + bullishCZones // + ); + bool hasBullishConsolidationZones = IsValidSize(bullishCZonesCount); + if (hasBullishConsolidationZones) + { + // + int idx = -1; + while (HasChild(bullishCZones)) + { + // + idx = GetYoungest(bullishCZones); + hasBullishConsolidationZone = IsValidIndex(idx); + if (hasBullishConsolidationZone) + { + // + bullishConsolidationZone = bullishCZones[idx]; + + // + ArrayRemove( + bullishCZones, + idx, + 1 // + ); + + // + // Check Zone Based On pivot, since this is the SL ... + hasBullishConsolidationZone = + isBullish && + hasBullishConsolidationZone && + bullishConsolidationZone.lower > conditions.pivot && + bullishConsolidationZone.upper <= conditions.point; + if (hasBullishConsolidationZone) + { + // + Add( + bullishConsolidationZone.lower, + sls // + ); + } + } + } + } + Clean(bullishCZones); + bullishConsolidationZone.Clean(); + + // + // Bearish Consolidation Zone ... + XConsolidationZone bearishCZones[]; + bool hasBearishConsolidationZone = false; + XConsolidationZone bearishConsolidationZone; + int bearishCZonesCount = decisionCycleHelper.FillConsolidationZones( + X_DIRECTION_BEARISH, + bearishCZones // + ); + bool hasBearishConsolidationZones = IsValidSize(bearishCZones); + if (hasBearishConsolidationZones) + { + // + int idx = -1; + while (HasChild(bearishCZones)) + { + // + idx = GetYoungest(bearishCZones); + hasBearishConsolidationZone = IsValidIndex(idx); + if (hasBearishConsolidationZone) + { + // + bearishConsolidationZone = bearishCZones[idx]; + + // + ArrayRemove( + bearishCZones, + idx, + 1 // + ); + + // + hasBearishConsolidationZone = + isBearish && + hasBearishConsolidationZone && + bearishConsolidationZone.upper < conditions.pivot && + bearishConsolidationZone.lower >= conditions.point; + if (hasBearishConsolidationZone) + { + // + Add( + bearishConsolidationZone.upper, + sls // + ); + } + } + } + } + Clean(bearishCZones); + bearishConsolidationZone.Clean(); + + // + // Check VWap Crossing ... + + // + bool isVWapSwitchedToBullish = + // + (decisionXConditions.isVWapBullishOrdered && + decisionXConditions.isVWapSwitchedToBullishState) + // + || + // + (decisionXConditions.isVWapBullishState && + decisionXConditions.isVWapSwitchedToBullishOrdered) + // + ; + + // + isVWapSwitchedToBullish = + isBullish && + isVWapSwitchedToBullish; + if (isVWapSwitchedToBullish) + { + // + double vPivot = decisionXConditions.vwapMin; + bool canSetPivot = vPivot > conditions.pivot && + vPivot < conditions.point; + if (canSetPivot) + { + // + Add( + vPivot, + sls // + ); + } + } + + // + bool isVWapSwitchedToBearish = + // + (decisionXConditions.isVWapBearishOrdered && + decisionXConditions.isVWapSwitchedToBearishState) + // + || + // + (decisionXConditions.isVWapBearishState && + decisionXConditions.isVWapSwitchedToBearishOrdered) + // + ; + + // + isVWapSwitchedToBearish = + isBearish && + isVWapSwitchedToBearish; + if (isVWapSwitchedToBearish) + { + // + double vPivot = decisionXConditions.vwapMax; + bool canSetPivot = vPivot < conditions.pivot && + vPivot > conditions.point; + if (canSetPivot) + { + // + Add( + vPivot, + sls // + ); + } + } + + // + // Point Break ... + isInited = cBar.Init( + conditions.symbol, + conditions.period, + cIndex // + ); + double point = conditions.point; + bool isPointBreaked = + isInited && + IsBarBreak( + point, + setupDir, + cBar // + ); + cBar.Clean(); + + // + bool isCommonsPassed = + // + (isSupportRejected || + isResistanceRejected || + isVWapSwitchedToBullish || + isVWapSwitchedToBearish || + hasBullishConsolidationZone || + hasBearishConsolidationZone) + // + ; + + // + // Trigger Conditions ... + + // + bool canTriggerCHOCHZone = + // + isScorePassed && + isCommonsPassed && + conditions.provider == X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH + // + ; + + // + bool canTriggerActivatedZone = + // + // isPointBreaked && + isScorePassed && + isCommonsPassed && + conditions.provider == X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE + // + ; + + // + bool canTriggerPriceInsideZone = + // + isScorePassed && + isCommonsPassed && + conditions.provider == X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE + // + ; + + // + bool canTrigger = (canTriggerCHOCHZone || + canTriggerActivatedZone || + canTriggerPriceInsideZone); + + // + // Summary ... + + // + isBullish = + // + isBullish && + canTrigger + // + ; + + // + isBearish = + // + isBearish && + canTrigger + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + // + // Cleanup Setup Conditions ... + int setupAge = conditions.GetSetupAge(); + if (IsValidSize(setupAge) && + IsValidSize(maxAllowedSetupAge) && + setupAge >= maxAllowedSetupAge) + { + conditions.Clean(); + } + + // + // Cleanup ... + + // + cBar.Clean(); + pBar.Clean(); + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionState.Clean(); + decisionConditions.Clean(); + decisionXConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseState.Clean(); + analyseConditions.Clean(); + analyseXConditions.Clean(); + + // + return result; + } + + // + double entry = GetEntry( + conditions.symbol, + setupDir // + ); + + // + // Manipulate SL Based on Consolidation Zones ... + + // + double iAtr = decisionXConditions.atrBuffer[1]; + iAtr *= 1.5; + + // + // Since Pivot Value almost used + // as Default SL, if there isn't any Refind SL + // we use Default ... + if (!HasChild(sls)) + { + // + Add( + conditions.pivot, + sls // + ); + } + + // + double slsMin = GetMin(sls); + double slsMax = GetMax(sls); + + // + double sl = isBullish + ? slsMin - iAtr + : slsMax + iAtr; + double risk = MathAbs(entry - sl); + + // + // Filling Conditions Props ... + conditions.sl = sl; + conditions.triggerTime = cTime; + conditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + // Checking Targets ... + + // + ENUM_X121SMC_XWZ_PRIORITY priority = X121SMC_XWZ_PRIORITY_NONE; + bool hasPriority = workingZone + .DetectPriority( + priority, + setupDir, + zIndex, + decisionState.period // + ); + + // + // Order Block Targets ... + + // + XCOrderBlock *bullishOBs[]; + Copy( + analyseState.bullishOrderBlocks, + bullishOBs // + ); + + // + // Extract Available Order Blocks ... + int bullishOBsCont = FilterZones( + // + bullishOBs, + // + X_DIRECTION_BULLISH, + analyseState.period, + NULL, + // + // Start ... + XZONE_STATE_IGNORED, + false, + // + // Activation ... + XZONE_STATE_IGNORED, + false, + // + // Breake ... + XZONE_STATE_FAILED, + false, + // + // Work ... + XZONE_STATE_IGNORED, + false, + // + true, // Apply Sore ... + true // Ignore Inside ... + ); + bool hasBullishOBs = HasChild(bullishOBs); + + // + XCOrderBlock *bearishOBs[]; + Copy( + analyseState.bearishOrderBlocks, + bearishOBs // + ); + + // + // Extract Available Order Blocks ... + int bearishOBsCont = FilterZones( + // + bearishOBs, + // + X_DIRECTION_BEARISH, + analyseState.period, + NULL, + // + // Start ... + XZONE_STATE_IGNORED, + false, + // + // Activation ... + XZONE_STATE_IGNORED, + false, + // + // Breake ... + XZONE_STATE_FAILED, + false, + // + // Work ... + XZONE_STATE_IGNORED, + false, + // + true, // Apply Sore ... + true // Ignore Inside ... + ); + bool hasBearishOBs = HasChild(bearishOBs); + + // + if (isBullish && + hasBearishOBs) + { + // + int count = ArraySize(bearishOBs); + for (int i = 0; i < count; i++) + { + // + XCBaseObject *iObj; + bool isCreated = visionCycleHelper + .mPOIDrawer + .CreateOrderBlock( + bearishOBs[i], + iObj // + ); + if (isCreated) + { + mObjects.Add(iObj); + } + + // + double value = bearishOBs[i].Lower(); + bool canSet = value > entry; + if (canSet) + { + // + Add( + value, + conditions.targets // + ); + } + } + } + + // + if (isBearish && + hasBullishOBs) + { + // + int count = ArraySize(bullishOBs); + for (int i = 0; i < count; i++) + { + // + XCBaseObject *iObj; + bool isCreated = visionCycleHelper + .mPOIDrawer + .CreateOrderBlock( + bullishOBs[i], + iObj // + ); + if (isCreated) + { + mObjects.Add(iObj); + } + + // + double value = bullishOBs[i].Upper(); + bool canSet = value < entry; + if (canSet) + { + // + Add( + value, + conditions.targets // + ); + } + } + } + + // + Clean(bullishOBs); + Clean(bearishOBs); + + // + // Detect Quarter Targets ... + + // + double quarterTarget = 0; + if (hasPriority) + { + // + switch (priority) + { + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + quarterTarget = + isBullish + ? workingZone.supplyZone.Lower() + : workingZone.demandZone.Upper(); + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + quarterTarget = + isBullish + ? workingZone.quarter1 + : workingZone.quarter3; + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + quarterTarget = + isBullish + ? workingZone.quarter2 + : workingZone.quarter2; + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + quarterTarget = + isBullish + ? workingZone.quarter3 + : workingZone.quarter1; + break; + + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + quarterTarget = + isBullish + ? workingZone.demandZone.Upper() + : workingZone.supplyZone.Lower(); + break; + } + } + + // + if (quarterTarget > 0) + { + // + Add( + quarterTarget, + conditions.targets // + ); + } + + // + // Cleanup ... + + // + cBar.Clean(); + pBar.Clean(); + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionState.Clean(); + decisionConditions.Clean(); + decisionXConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseState.Clean(); + analyseConditions.Clean(); + analyseXConditions.Clean(); + + // + return result; + } + + // + // Detect Guards ... + bool DetectGuards( + // + X121SMCGuard &guards[], + const XPosition &positions[], + // + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper + // + ) + { + // + bool result = false; + + // + Clean(guards); + + // + bool isCycleHelpersValid = + // + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL + // + ; + + // + return false; + + // + result = isCycleHelpersValid; + if (!result) + { + return result; + } + + // + int count = ArraySize(positions); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + string provider = ToString(X_121_SMC_PROVIDER_XWZ); + + // + XPosition ownPositions[]; + XPosition ownLongPositions[]; + XPosition ownShortPositions[]; + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + bool isOwn = iPosition + .IsFiltersPassed( + symbol, + provider, + NULL, + X_POSITION_TYPE_ALL, + iPosition.magic // + ); + if (isOwn) + { + // + AddRef( + iPosition, + ownPositions // + ); + + // + bool isLong = IsLong(positions[i].type); + if (isLong) + { + // + AddRef( + iPosition, + ownLongPositions // + ); + } + else + { + // + AddRef( + iPosition, + ownShortPositions // + ); + } + } + } + + // + count = ArraySize(ownPositions); + + // + int longsCount = ArraySize(ownLongPositions); + bool hasLongs = IsValidSize(longsCount); + + // + int shortsCount = ArraySize(ownShortPositions); + bool hasShorts = IsValidSize(shortsCount); + + // + result = IsValidSize(count); + if (!result) + { + // + Clean(ownPositions); + Clean(ownLongPositions); + Clean(ownShortPositions); + + // + return result; + } + + // + // + // + + // + // Get Global and Common Guards ... + + // + ENUM_X_121_SMC_GUARD_ACTIONS ignoreGuards[1] = { + X_121_SMC_GUARD_ACTION_TRAIL_STOP // + }; + result = DetectX121SMCGuards( + provider, + guards, + positions, + decisionCycleHelper, + analyseCycleHelper, + consolidationCycleHelper, + visionCycleHelper, + // + ignoreGuards + // + ); + + // + // + // + + // + // Get Custom Implemented Guards ... + + // + // Here we Are Sure there is Positions to Guard ... + // based on Current Provider ... + + // + // Detect Required Data for Analyse Market to Guard Positions ... + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + // + result = HasChild(guards); + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + // + zBar.Clean(); + result = HasChild(guards); + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + symbol, + period, + pIndex // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + result = HasChild(guards); + return result; + } + + // + XOHCL ppBar; + result = ppBar.Init( + symbol, + period, + ppIndex // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + result = HasChild(guards); + return result; + } + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + + // + // Cycles Conditions ... + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + ppBar.Clean(); + result = HasChild(guards); + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + ppBar.Clean(); + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + ppBar.Clean(); + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + ppBar.Clean(); + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseConditions.Clean(); + + // + Clean(consolidationPoiEvents); + Clean(consolidationCycleEvents); + + // + consolidationConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Cycles POI States ... + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + X121Conditions consolidationXConditions = consolidationConditions.x121Conditions; + X121Conditions visionXConditions = visionConditions.x121Conditions; + + // + // + // + + // + // Detect Consolidation Zone ... + + // + // Bullish ... + XConsolidationZone bullishConsolidationZone; + bool hasBullishConsolidationZone = decisionCycleHelper + .GetLastDirectionalConsolidationZone( + X_DIRECTION_BULLISH, + bullishConsolidationZone // + ); + + // + // Bearish ... + XConsolidationZone bearishConsolidationZone; + bool hasBearishConsolidationZone = decisionCycleHelper + .GetLastDirectionalConsolidationZone( + X_DIRECTION_BEARISH, + bearishConsolidationZone // + ); + + // + // Detect High Probability Swings ... + bool isSwingLow = + // + cBar.low > pBar.low && + ppBar.low > pBar.low && + // + zBar.low > pBar.low + // + ; + bool isSwingHigh = + // + cBar.high < pBar.high && + ppBar.high < pBar.high && + // + zBar.high < pBar.high + // + ; + bool isStrongSwingLow = + pBar.IsBullish() && + pBar.GetLowShadow() >= pBar.GetBody() * 2; + bool isStrongSwingHigh = + pBar.IsBearish() && + pBar.GetHighShadow() >= pBar.GetBody() * 2; + + // + // Here We Have all Requirements for Guarding Positions ... + + // + // Available Guards: + // X_121_SMC_GUARD_ACTION_NONE + // X_121_SMC_GUARD_ACTION_CLOSE + // X_121_SMC_GUARD_ACTION_CLOSE_ALL + // X_121_SMC_GUARD_ACTION_CLOSE_LONGS + // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS + // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE + // X_121_SMC_GUARD_ACTION_TRAIL_STOP + // X_121_SMC_GUARD_ACTION_TRAIL_TARGET + // X_121_SMC_GUARD_ACTION_HEDGE + + // + // X_121_SMC_GUARD_ACTION_CLOSE: + // Close Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_ALL: + // Close All Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_LONGS: + // Close All Long Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS: + // Close All Short Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE: + // Partial Close Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_TRAIL_STOP: + // Trail Stop Specified Position on Specified Conditions ... + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = ownPositions[i]; + + // + bool isLong = IsLong(iPosition.type); + bool isInProfit = iPosition.profit > 0; + + // + double sl = iPosition.sl; + double tp = iPosition.tp; + + // + // Trail Stops Using Consolidation Zones ... + bool canTraiLonglUsingCZone = + // + (isLong && + isInProfit && + hasBullishConsolidationZone && + bullishConsolidationZone.lower > iPosition.sl && + bullishConsolidationZone.lower > iPosition.entry) + // + ; + if (canTraiLonglUsingCZone) + { + sl = bullishConsolidationZone.lower; + } + + // + bool canTraiShortlUsingCZone = + // + (!isLong && + isInProfit && + hasBearishConsolidationZone && + bearishConsolidationZone.upper < iPosition.sl && + bearishConsolidationZone.upper < iPosition.entry) + // + ; + if (canTraiShortlUsingCZone) + { + sl = bearishConsolidationZone.upper; + } + + // + bool canTrailUsingCZone = + canTraiLonglUsingCZone || + canTraiShortlUsingCZone; + + // + // Trail Stops Using Swings ... + + // + bool canTrailLongUsingSwings = + // + isLong && + isInProfit && + (isSwingLow || + isStrongSwingLow) && + pBar.low > iPosition.sl && + pBar.low > iPosition.entry + // + ; + if (canTrailLongUsingSwings) + { + sl = pBar.low; + } + + // + bool canTraiShortlUsingSwings = + // + !isLong && + isInProfit && + (isSwingHigh || + isStrongSwingHigh) && + pBar.high < iPosition.sl && + pBar.high < iPosition.entry + // + ; + if (canTraiShortlUsingSwings) + { + sl = pBar.high; + } + + // + bool canTrailUsingSwings = + canTrailLongUsingSwings || + canTraiShortlUsingSwings; + + // + // + // + + // + bool canTrail = + sl != iPosition.sl && + (canTrailUsingCZone || + canTrailUsingSwings); + if (canTrail) + { + // + X121SMCGuard iGuard; + + // + iGuard.time = cTime; + iGuard.symbol = symbol; + iGuard.provider = provider; + iGuard.action = X_121_SMC_GUARD_ACTION_TRAIL_STOP; + + // + iGuard.ticket = iPosition.ticket; + + // + iGuard.sl = sl; + + // + AddGuard( + iGuard, + guards // + ); + } + } + + // + // X_121_SMC_GUARD_ACTION_TRAIL_TARGET: + // Trail Target Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_HEDGE: + // Hedge all Positions on Specified Conditions ... + + // + // Cleanup Collections ... + + // + Clean(ownPositions); + Clean(ownLongPositions); + Clean(ownShortPositions); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + ppBar.Clean(); + + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(visionCycleEvents); + Clean(decisionPoiEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationPoiEvents); + Clean(consolidationCycleEvents); + + // + visionState.Clean(); + analyseState.Clean(); + decisionState.Clean(); + visionConditions.Clean(); + analyseConditions.Clean(); + visionXConditions.Clean(); + decisionConditions.Clean(); + consolidationState.Clean(); + analyseXConditions.Clean(); + decisionXConditions.Clean(); + consolidationConditions.Clean(); + consolidationXConditions.Clean(); + + // + count = ArraySize(guards); + result = IsValidSize(count); + + // + return result; + } + + // + // Add Conditions to Conditions Collection ... + int AddConditionsIfNotExists( + int maxAllowed = 10 // + ) + { + // + int result = 0; + + // + bool isSetuped = IsValid(mConditions.setupTime) && + HasDirection(mConditions.dir); + if (!isSetuped) + { + return result; + } + + // + int count = ArraySize(mConditionsCollection); + if (IsValidSize(count)) + { + // + // Copy Original Items ... + X121SMCStrategyXWZSignalConditions tmpItems[]; + Copy( + mConditionsCollection, + tmpItems // + ); + + // + // Prese Item Data ... + bool isBullish = IsBullish(mConditions.dir); + + // + for (int i = 0; i < count; i++) + { + // + X121SMCStrategyXWZSignalConditions iItem = tmpItems[i]; + + // + bool canRemove = mConditions.dir == iItem.dir && + mConditions.pivot == iItem.pivot; + if (canRemove) + { + // + ArrayRemove( + mConditionsCollection, + i, + 1 // + ); + } + } + + // + Clean(tmpItems); + } + + // + AddRef( + mConditions, + mConditionsCollection // + ); + + // + // Remove Olds ... + CleanupArray( + mConditionsCollection, + maxAllowed // + ); + + // + result = ArraySize(mConditionsCollection); + + // + return result; + } + + // + bool DetectWorkingZone( + XPOIState <fState // + ) + { + // + bool result = false; + + // + result = IsValid(symbol) && + IsValid(period); + if (!result) + { + return result; + } + + // + result = !workingZone.IsValid(); + if (!result) + { + return result; + } + + // + workingZone.symbol = symbol; + workingZone.period = period; + + // + int idx = -1; + bool has = false; + + // + has = ltfState.HasSupplyZones(); + if (has) + { + // + idx = GetHighest(ltfState.supplyZones); + if (IsValidIndex(idx)) + { + workingZone.supplyZone = ltfState.supplyZones[idx]; + } + } + + // + has = ltfState.HasDemandZones(); + if (has) + { + // + idx = GetLowest(ltfState.demandZones); + if (IsValidIndex(idx)) + { + workingZone.demandZone = ltfState.demandZones[idx]; + } + } + + // + bool hasWorkingZone = workingZone.HasSupplyZone() && + workingZone.HasDemandZone(); + if (hasWorkingZone) + { + // + double upper = workingZone.supplyZone.Lower(); + double lower = workingZone.demandZone.Upper(); + + // + double delta = ((upper - lower) / 100) * 25; + + // + workingZone.quarter1 = upper - (1 * delta); + workingZone.quarter2 = upper - (2 * delta); + workingZone.quarter3 = upper - (3 * delta); + + // + hasWorkingZone = workingZone.IsValid(); + } + + // + result = hasWorkingZone; + + // + return result; + } + + // + // Draw Functions ... + // + + // + void RemoveDraws() + { + mObjects.Clear(); + } + + // + void DrawBar( + XOHCL &bar, + XCPOIDrawer *drawer, + bool forceClean = true // + ) + { + // + if (forceClean) + { + mBarObjects.Clear(); + } + + // + if (drawer == NULL || + !bar.IsValid()) + { + return; + } + + // + bool isBullish = bar.IsBullish(); + + // + int widthBar = 2; + bool fillShadowsBar = true; + ENUM_LINE_STYLE styleBar = STYLE_SOLID; + color clrBar = + isBullish + ? clrAqua + : clrMagenta; + + // + datetime to = bar.NextAt(); + + // + XCOHCLObject *iObj; + bool isCreated = drawer + .CreateBar( + bar, + iObj, + to // + ); + if (isCreated) + { + // + iObj.BarSpes( + widthBar, + clrBar, + styleBar // + ); + + // + iObj.LowShadowFill(fillShadowsBar); + iObj.HighShadowFill(fillShadowsBar); + + // + mBarObjects.Add(iObj); + } + } + + // + void DrawWorkingZone( + XCPOIDrawer *drawer, + bool drawTrendLine = true, + bool forceClean = false // + ) + { + // + if (drawer == NULL) + { + return; + } + + // + if (forceClean) + { + mWorkingZoneObjects.Clear(); + } + + // + int count = 0; + bool has = false; + bool isCreated = false; + + // + ulong chartID = drawer.ChartIdentification(); + int subWindow = drawer.SubWindowIdentification(); + color bullishColor = drawer.BarBullishColor(); + color bearishColor = drawer.BarBearishColor(); + + // + // Supply Zone ... + has = workingZone.HasSupplyZone(); + if (has) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + workingZone.supplyZone, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + + // + has = workingZone.HasSupplyZones(); + if (has) + { + // + count = workingZone.CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + workingZone.supplyZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + + // + // Demand Zone ... + has = workingZone.HasDemandZone(); + if (has) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + workingZone.demandZone, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + + // + has = workingZone.HasDemandZones(); + if (has) + { + // + count = workingZone.CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + workingZone.demandZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + + // + // Quarters ... + has = workingZone.IsValid(); + if (has) + { + // + double zoneUpper = workingZone.supplyZone.Upper(); + double upper = workingZone.supplyZone.Lower(); + + // + double lower = workingZone.demandZone.Upper(); + double zoneLower = workingZone.demandZone.Lower(); + + // + string prefix = "X121WZone_" + workingZone.symbol + "_" + ToString(workingZone.period); + + // + // Zone Upper ... + CChartObjectHLine *zoneUpperLine; + zoneUpperLine = new CChartObjectHLine(); + isCreated = zoneUpperLine.Create( + chartID, + prefix + "_ZoneTop", + subWindow, + zoneUpper // + ); + if (isCreated) + { + // + zoneUpperLine.Color(clrRed); + + // + mWorkingZoneObjects.Add(zoneUpperLine); + } + + // + // Zone Lower ... + CChartObjectHLine *zoneLowerLine; + zoneLowerLine = new CChartObjectHLine(); + isCreated = zoneLowerLine.Create( + chartID, + prefix + "_ZoneDown", + subWindow, + zoneLower // + ); + if (isCreated) + { + // + zoneLowerLine.Color(clrRed); + + // + mWorkingZoneObjects.Add(zoneLowerLine); + } + + // + // Upper ... + CChartObjectHLine *upperLine; + upperLine = new CChartObjectHLine(); + isCreated = upperLine.Create( + chartID, + prefix + "_Upper", + subWindow, + upper // + ); + if (isCreated) + { + // + upperLine.Color(clrLime); + + // + mWorkingZoneObjects.Add(upperLine); + } + + // + // Lower ... + CChartObjectHLine *lowerLine; + lowerLine = new CChartObjectHLine(); + isCreated = lowerLine.Create( + chartID, + prefix + "_Lower", + subWindow, + lower // + ); + if (isCreated) + { + // + lowerLine.Color(clrLime); + + // + mWorkingZoneObjects.Add(lowerLine); + } + + // + // Quarters ... + + // + // Quarter 1 ... + CChartObjectHLine *q1Line; + q1Line = new CChartObjectHLine(); + isCreated = q1Line.Create( + chartID, + prefix + "_Q1", + subWindow, + workingZone.quarter1 // + ); + if (isCreated) + { + // + q1Line.Color(clrYellow); + + // + mWorkingZoneObjects.Add(q1Line); + } + + // + // Quarter 2 ... + CChartObjectHLine *q2Line; + q2Line = new CChartObjectHLine(); + isCreated = q2Line.Create( + chartID, + prefix + "_Q2", + subWindow, + workingZone.quarter2 // + ); + if (isCreated) + { + // + q2Line.Color(clrYellow); + + // + mWorkingZoneObjects.Add(q2Line); + } + + // + // Quarter 3 ... + CChartObjectHLine *q3Line; + q3Line = new CChartObjectHLine(); + isCreated = q3Line.Create( + chartID, + prefix + "_Q3", + subWindow, + workingZone.quarter3 // + ); + if (isCreated) + { + // + q3Line.Color(clrYellow); + + // + mWorkingZoneObjects.Add(q3Line); + } + } + + // + // Draw Order Flow ... + ENUM_X_DIRECTION trend; + has = workingZone.HasOrderFlow(trend); + if (has) + { + // + bool isBullish = IsBullish(trend); + + // + count = workingZone.CountOrderFlow(); + for (int i = 0; i < count; i++) + { + // + XOBFVG iOBFVG = workingZone.orderFlow[i]; + + // + XCBaseObject *drawnObjects[]; + int drawnObjectsCount = drawer + .DrawOBFVG( + // + iOBFVG, + drawnObjects, + // + true, // Draw Order Block ... + true, // Draw Fair Value Gap ... + false, // Draw Supply Zones ... + false, // Draw Demand Zones ... + false, // Draw Support Zones ... + false // Draw Resistance Zones ... + ); + if (IsValidSize(drawnObjectsCount)) + { + AddDrawnWorkingZoneObjects(drawnObjects); + } + } + + // + // Draw Trend Line ... + if (drawTrendLine) + { + // + XOBFVGPivot pivots[]; + count = workingZone.GetSwings(pivots); + has = count >= 2; + if (has) + { + // + // Get Max / Min ... + double max = 0; + double min = 0; + datetime maxAt = NULL; + datetime minAt = NULL; + for (int i = 0; i < count; i++) + { + // + XOBFVGPivot iPivot = pivots[i]; + + // + if (!iPivot.IsValid()) + { + // + iPivot.Clean(); + continue; + } + + // + // Min ... + bool canSetMin = + min == 0 + ? true + : min > iPivot.value; + if (canSetMin) + { + // + minAt = iPivot.at; + min = iPivot.value; + } + + // + // Max ... + bool canSetMax = + max == 0 + ? true + : max < iPivot.value; + if (canSetMax) + { + // + maxAt = iPivot.at; + max = iPivot.value; + } + + // + iPivot.Clean(); + } + + // + double price1 = + isBullish + ? min + : max; + double price2 = + isBullish + ? max + : min; + datetime time1 = + isBullish + ? minAt + : maxAt; + datetime time2 = + isBullish + ? maxAt + : minAt; + + // + color clrTrend = + isBullish + ? bullishColor + : bearishColor; + + // + string trendName = + ToString(trend) + "_" + "XTRNDL_" + + ToString(period) + "_" + + ToString(price1) + "_" + + ToString(price2) + "_"; + // + ToMD5(ToString(time1)); + + // + CChartObjectTrend *mTrend; + mTrend = new CChartObjectTrend(); + isCreated = mTrend.Create( + chartID, + trendName, + subWindow, + time1, + price1, + time2, + price2 // + ); + + // + if (isCreated) + { + // + mTrend.Width(2); + mTrend.Color(clrTrend); + mTrend.RayRight(true); + + // + mWorkingZoneObjects.Add(mTrend); + } + } + } + + // + // Draw Target Zone ... + has = targetZone.IsValid(); + if (has) + { + // + XCBaseObject *drawnObjects[]; + int drawnObjectsCount = drawer + .DrawOBFVG( + // + targetZone, + drawnObjects, + // + true, // Draw Order Block ... + true, // Draw Fair Value Gap ... + false, // Draw Supply Zones ... + false, // Draw Demand Zones ... + false, // Draw Support Zones ... + false // Draw Resistance Zones ... + ); + if (IsValidSize(drawnObjectsCount)) + { + AddDrawnWorkingZoneObjects(drawnObjects); + } + } + } + + // + } + + // + void DrawConditions( + X121SMCStrategyXWZSignalConditions &conditions, + XCPOIDrawer *drawer, + bool forceClean = false // + ) + { + // + if (drawer == NULL) + { + return; + } + + // + if (forceClean) + { + mObjects.Clear(); + } + + // + bool hasSignalZone = conditions.signalZone.IsValid(); + if (hasSignalZone) + { + // + XCBaseObject *iObjects[]; + int iObjectsCount = drawer.DrawOBFVG( + conditions.signalZone, + iObjects // + ); + AddDrawnObjects(iObjects); + } + } + + // + protected: + // + + // + private: + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + CArrayObj mObjects; + CArrayObj mBarObjects; + CArrayObj mWorkingZoneObjects; + + /** + * Initialize ... + */ + void Init() + { + } + + /** + * DeInitialize ... + */ + void DeInit() + { + // + chochZone.Clean(); + signalZone.Clean(); + targetZone.Clean(); + mConditions.Clean(); + workingZone.Clean(); + Clean(mConditionsCollection); + + // + mObjects.Clear(); + mBarObjects.Clear(); + mWorkingZoneObjects.Clear(); + } + + /** + * Update To Time of Exists Components ... + * + * @param value: updated time ... + */ + void UpdateTo( + datetime value = NULL // + ) + { + // + value = NormalizeTime(value); + + // + chochZone.UpdateTo(value); + targetZone.UpdateTo(value); + signalZone.UpdateTo(value); + workingZone.UpdateTo(value); + mConditions.UpdateTo(value); + waitingZone.UpdateTo(value); + } + + // + // Helpers ... + + // + bool CalculateRiskReward( + ENUM_X121SMC_XWZ_PRIORITY priority, + double &reward, + double &amountPercent // + ) + { + // + bool result = false; + + // + reward = 0; + amountPercent = 0; + + // + result = priority != X121SMC_XWZ_PRIORITY_NONE; + if (!result) + { + return result; + } + + // + switch (priority) + { + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + reward = 6; + amountPercent = 2; + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + reward = 4; + amountPercent = 2; + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + reward = 3; + amountPercent = 1.5; + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + reward = 2; + amountPercent = 1; + break; + + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + reward = 1; + amountPercent = 0.5; + break; + } + + // + result = + // + reward > 0 && + amountPercent > 0 + // + ; + + // + return result; + } + + // + void AddDrawnObjects(XCBaseObject *&objects[]) + { + // + int count = ArraySize(objects); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + mObjects.Add(objects[i]); + } + } + + // + void AddDrawnWorkingZoneObjects(XCBaseObject *&objects[]) + { + // + int count = ArraySize(objects); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + mWorkingZoneObjects.Add(objects[i]); + } + } + + // +}; + +// \ No newline at end of file diff --git a/Documents/BKP/x-121.smc.xwz.signal.lib.mq5 b/Documents/BKP/x-121.smc.xwz.signal.lib.mq5 new file mode 100644 index 00000000..dd8835d8 --- /dev/null +++ b/Documents/BKP/x-121.smc.xwz.signal.lib.mq5 @@ -0,0 +1,1582 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: XWZ +// Description: provide all Signalling functions ... +// +// +// 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 "../../Libraries/x-trade.lib" +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" +#include "../Libraries/x-121.smc.guard.lib.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +enum ENUM_X121SMC_XWZ_PROVIDERS +{ + X121SMC_XWZ_PROVIDER_NONE, + X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE, + X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH, + X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE, +}; + +// +enum ENUM_X121SMC_XWZ_PRIORITY +{ + X121SMC_XWZ_PRIORITY_NONE, + X121SMC_XWZ_PRIORITY_WEAK, + X121SMC_XWZ_PRIORITY_LOW, + X121SMC_XWZ_PRIORITY_REGULAR, + X121SMC_XWZ_PRIORITY_HIGH, + X121SMC_XWZ_PRIORITY_STRONG_HIGH, +}; + +// +struct X121SMCStrategyXWZWorkingZone +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + XCSupplyZone *supplyZone; + XCDemandZone *demandZone; + + // + double quarter1; + double quarter2; + double quarter3; + + // + XOBFVG orderFlow[]; + XOBFVGPivot swings[]; + XOBFVG brokenOrderFlow[]; + CChartObjectTrend *orderFlowTrend; + + // + XCSupplyZone *supplyZones[]; + XCDemandZone *demandZones[]; + + // + // Constructor ... + X121SMCStrategyXWZWorkingZone() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + quarter1 = 0; + quarter2 = 0; + quarter3 = 0; + + // + symbol = NULL; + period = NULL; + + // + Clean(orderFlow); + Clean(brokenOrderFlow); + + // + Clean(swings); + ZeroMemory(supplyZone); + ZeroMemory(demandZone); + + // + if (orderFlowTrend != NULL) + { + orderFlowTrend.Delete(); + } + ZeroMemory(orderFlowTrend); + + // + ZeroMemory(this); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + // + quarter1 > 0 && + quarter2 > 0 && + quarter3 > 0 && + HasSupplyZone() && + HasDemandZone() && + quarter1 > quarter2 && + quarter2 > quarter3 + // + ; + + // + return result; + } + + // + bool HasSupplyZone() + { + return supplyZone != NULL && + supplyZone.IsValid(); + } + + // + bool HasDemandZone() + { + return demandZone != NULL && + demandZone.IsValid(); + } + + // + // + // + + // + bool HasOrderFlow() + { + // + bool result = false; + + // + result = IsValid() && + HasChild(orderFlow); + + // + return result; + } + + // + bool HasOrderFlow( + ENUM_X_DIRECTION &orderFlowDir // + ) + { + // + bool result = false; + + // + result = IsValid() && + HasChild(orderFlow); + if (result) + { + orderFlowDir = orderFlow[0].GetDirection(); + } + + // + return result; + } + + // + int CountOrderFlow() + { + return ArraySize(orderFlow); + } + + // + int GetSwings( + XOBFVGPivot &pivots[] // + ) + { + // + int result = 0; + + // + Clean(pivots); + + // + int count = 0; + bool has = false; + + // + has = HasOrderFlow(); + if (!has) + { + return result; + } + + // + count = CountOrderFlow(); + for (int i = 0; i < count; i++) + { + // + XOBFVGPivot iPivots[]; + int iPivotsCount = orderFlow[i] + .GetSwings(iPivots); + bool hasPivots = IsValidSize(iPivotsCount); + if (hasPivots) + { + // + Copy( + iPivots, + pivots, + false // + ); + } + + // + Clean(iPivots); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + double GetOrderFlowTrendLinePrice( + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + double result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + if (!IsValid() || + !HasOrderFlow() || + orderFlowTrend == NULL) + { + return result; + } + + // + datetime time = iTime( + symbol, + forPeriod, + barIndex // + ); + + // + result = ObjectGetValueByTime( + orderFlowTrend.ChartId(), + orderFlowTrend.Name(), + time // + ); + + // + return result; + } + + // + int DetectOrderFlow( + string forSymbol, + ENUM_TIMEFRAMES forPeriod, + ENUM_X_DIRECTION &orderFlowDir, + XPOIState <fState, + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &stfState // + ) + { + // + int result = 0; + + // + Clean(orderFlow); + orderFlowDir = X_DIRECTION_NONE; + + // + bool isValid = + // + IsValid(forSymbol) && + IsValid(forPeriod) && + ltfState.HasChild() && + htfState.HasChild() && + mtfState.HasChild() && + stfState.HasChild() + // + ; + if (!isValid) + { + return result; + } + + // + // Find Working Zone ... + bool hasWorkingZone = IsValid(); + if (!hasWorkingZone) + { + // + symbol = forSymbol; + period = forPeriod; + + // + int idx = -1; + bool has = false; + + // + has = ltfState.HasSupplyZones(); + if (has) + { + // + idx = GetHighest(ltfState.supplyZones); + if (IsValidIndex(idx)) + { + supplyZone = ltfState.supplyZones[idx]; + } + } + + // + has = ltfState.HasDemandZones(); + if (has) + { + // + idx = GetLowest(ltfState.demandZones); + if (IsValidIndex(idx)) + { + demandZone = ltfState.demandZones[idx]; + } + } + + // + hasWorkingZone = HasSupplyZone() && + HasDemandZone(); + if (hasWorkingZone) + { + // + double upper = supplyZone.Lower(); + double lower = demandZone.Upper(); + + // + double delta = ((upper - lower) / 100) * 25; + + // + quarter1 = upper - (1 * delta); + quarter2 = upper - (2 * delta); + quarter3 = upper - (3 * delta); + + // + hasWorkingZone = IsValid(); + } + } + + // + if (!hasWorkingZone) + { + return result; + } + + // + // Bullish OBFVGs ... + XOBFVG bullOBFVGs[]; + int bullOBFVGsCount = ExtractOBFVGZones( + htfState, + mtfState, + stfState, + bullOBFVGs, + X_DIRECTION_BULLISH, + NULL, // For Period ... + // + // Start ... + XZONE_STATE_PASSED, + true, // Force Body Out ... + // + // Activation ... + XZONE_STATE_PASSED, + true, // Force Body In ... + // + // Breaktion ... + XZONE_STATE_FAILED, + false, // Force Body In ... + // + // Works ... + XZONE_STATE_PASSED, + true, // Force Body Out ... + // + true, // Apply Sort ... + true, // From Filter ... + true, // Place Filter ... + // + true, // Ignore Inside in Place Filter ... + // + true, // Detect Inside OB POI(s) ... + true, // Detect Inside FVG POI(s) ... + true // Apply From Filter to Selected POI(s) ... + ); + bool hasBullOBFVGs = IsValidSize(bullOBFVGsCount); + + // + // Bearish OBFVGs ... + XOBFVG bearOBFVGs[]; + int bearOBFVGsCount = ExtractOBFVGZones( + htfState, + mtfState, + stfState, + bearOBFVGs, + X_DIRECTION_BEARISH, + NULL, // For Period ... + // + // Start ... + XZONE_STATE_PASSED, + true, // Force Body Out ... + // + // Activation ... + XZONE_STATE_PASSED, + true, // Force Body In ... + // + // Breaktion ... + XZONE_STATE_FAILED, + false, // Force Body In ... + // + // Works ... + XZONE_STATE_PASSED, + true, // Force Body Out ... + // + true, // Apply Sort ... + true, // From Filter ... + true, // Place Filter ... + // + true, // Ignore Inside in Place Filter ... + // + true, // Detect Inside OB POI(s) ... + true, // Detect Inside FVG POI(s) ... + true // Apply From Filter to Selected POI(s) ... + ); + bool hasBearOBFVGs = IsValidSize(bearOBFVGsCount); + + // + XOBFVG lastBroken; + bool hasBroken = false; + int idx = GetYoungest(brokenOrderFlow); + if (IsValidIndex(idx)) + { + // + lastBroken = brokenOrderFlow[idx]; + hasBroken = lastBroken.IsValid(); + } + + // + bool hasOrderFlow = hasBearOBFVGs || + hasBullOBFVGs; + if (hasOrderFlow) + { + // + // Vlidate ... + isValid = + // + (hasBullOBFVGs && + !hasBearOBFVGs && + bullOBFVGsCount >= 1) + // + || + // + (hasBearOBFVGs && + !hasBullOBFVGs && + bearOBFVGsCount >= 1) + // + ; + + // + if (isValid) + { + // + if (hasBullOBFVGs) + { + // + Copy( + bullOBFVGs, + orderFlow // + ); + } + else if (hasBearOBFVGs) + { + // + Copy( + bearOBFVGs, + orderFlow // + ); + } + + // + orderFlowDir = + hasBullOBFVGs + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + bool isPlacePassed = true; + if (hasBroken) + { + // + bool isBullish = IsBullish(orderFlowDir); + + // + idx = GetYoungest(orderFlow); + bool hasYounget = IsValidIndex(idx); + + // + isPlacePassed = + ArraySize(orderFlow) > 1 + ? true + : isBullish + ? (IsAbove( + orderFlow[idx].ob, + lastBroken.ob, + true // Ignore Inside ... + )) + : (IsBelow( + orderFlow[idx].ob, + lastBroken.ob, + true // Ignore Inside + )); + + // + Clean(brokenOrderFlow); + AddRef( + orderFlow[idx], + brokenOrderFlow // + ); + } + + // + if (!isPlacePassed) + { + // + Clean(orderFlow); + orderFlowDir = X_DIRECTION_NONE; + } + + // + result = ArraySize(orderFlow); + } + } + + // + Clean(bullOBFVGs); + Clean(bearOBFVGs); + + // + lastBroken.Clean(); + + // + if (IsValidSize(result)) + { + // + int count = GetSwings(swings); + bool has = count >= 2; + bool isBullish = IsBullish(orderFlowDir); + if (has) + { + // + // Get Max / Min ... + double max = 0; + double min = 0; + datetime maxAt = NULL; + datetime minAt = NULL; + for (int i = 0; i < count; i++) + { + // + XOBFVGPivot iPivot = swings[i]; + + // + if (!iPivot.IsValid()) + { + // + iPivot.Clean(); + continue; + } + + // + // Min ... + bool canSetMin = + min == 0 + ? true + : min > iPivot.value; + if (canSetMin) + { + // + minAt = iPivot.at; + min = iPivot.value; + } + + // + // Max ... + bool canSetMax = + max == 0 + ? true + : max < iPivot.value; + if (canSetMax) + { + // + maxAt = iPivot.at; + max = iPivot.value; + } + + // + iPivot.Clean(); + } + + // + double price1 = + isBullish + ? min + : max; + double price2 = + isBullish + ? max + : min; + datetime time1 = + isBullish + ? minAt + : maxAt; + datetime time2 = + isBullish + ? maxAt + : minAt; + + // + color clrTrend = clrNONE; + + // + string trendName = + "XORDFLW" + ToString(orderFlowDir) + "_" + "XTRNDL_" + + ToString(period) + "_" + + ToString(price1) + "_" + + ToString(price2) + "_"; + + // + orderFlowTrend = new CChartObjectTrend(); + has = orderFlowTrend.Create( + 0, + trendName, + 0, + time1, + price1, + time2, + price2 // + ); + + // + if (has) + { + // + orderFlowTrend.Width(1); + orderFlowTrend.Color(clrTrend); + orderFlowTrend.RayRight(true); + } + } + } + + // + return result; + } + + // + void AddOrderFlowItem( + XOBFVG &orderItem // + ) + { + // + ENUM_X_DIRECTION trend; + if (!HasOrderFlow(trend)) + { + return; + } + + // + bool isSameDir = orderItem + .GetDirection() == trend; + if (!isSameDir) + { + return; + } + + // + bool isBullish = IsBullish(trend); + + // + AddRef( + orderItem, + orderFlow // + ); + + // + Sort( + orderFlow, + trend, + true // Ignore Inside ... + ); + } + + // + bool IsDestroyed( + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init( + symbol, + period, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + XOHCL cBar; + result = bar.GetPreviousBar(cBar); + if (!result) + { + // + bar.Clean(); + cBar.Clean(); + + // + return result; + } + + // + bool isSupplyZoneBreaked = + // + bar.low > supplyZone.Upper() && + cBar.low > supplyZone.Upper() + // + ; + + // + bool isDemandZoneBreaked = + // + bar.high < demandZone.Lower() && + cBar.high < demandZone.Lower() + // + ; + + // + bar.Clean(); + cBar.Clean(); + + // + result = isSupplyZoneBreaked || + isDemandZoneBreaked; + + // + return result; + } + + // + bool IsOrderFlowBreaked( + int &breakedIndex, + bool forceOBBreake = false, + bool forceFVGBreake = false, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + breakedIndex = -1; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + ENUM_X_DIRECTION orderFlowDir; + result = HasOrderFlow(orderFlowDir); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init( + symbol, + forPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + bool isBullish = IsBullish(orderFlowDir); + + // + int idx = + isBullish + ? GetHighest(orderFlow) + : GetLowest(orderFlow); + result = IsValidIndex(idx); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + XOHCL obBreakerBar; + bool isOBBodyOut = false; + bool isOBBreaked = orderFlow[idx].ob.IsBreaked( + orderFlowDir, + obBreakerBar, + isOBBodyOut, + false, // Ignore Start ... + false, // Started Bar Body Out ... + forPeriod // + ); + + // + if (!isOBBreaked) + { + obBreakerBar.Clean(); + } + + // + XOHCL fvgBreakerBar; + bool isFVGBodyOut = false; + bool isFVGBreaked = orderFlow[idx].fvg.IsBreaked( + orderFlowDir, + fvgBreakerBar, + isFVGBodyOut, + false, // Ignore Start ... + true, // Started Bar Body Out ... + forPeriod // + ); + + // + if (!isFVGBreaked) + { + fvgBreakerBar.Clean(); + } + + // + isOBBreaked = + obBreakerBar.IsValid(); + + // + isFVGBreaked = + fvgBreakerBar.IsValid(); + + // + if ((forceOBBreake && forceFVGBreake) || + (!forceOBBreake && !forceFVGBreake)) + { + // + result = isOBBreaked || + isFVGBreaked; + } + else if (forceOBBreake) + { + result = isOBBreaked; + } + else if (forceFVGBreake) + { + result = isFVGBreaked; + } + + // + if (result) + { + breakedIndex = idx; + } + + // + bar.Clean(); + obBreakerBar.Clean(); + fvgBreakerBar.Clean(); + + // + return result; + } + + // + bool DetectPriority( + ENUM_X121SMC_XWZ_PRIORITY &priority, + ENUM_X_DIRECTION forDir, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + priority = X121SMC_XWZ_PRIORITY_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + XOHCL bar; + result = bar.Init( + symbol, + forPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + if (bar.high < supplyZone.Upper() && + bar.low > supplyZone.Lower()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_NONE + : X121SMC_XWZ_PRIORITY_STRONG_HIGH; + } + else if (bar.high < supplyZone.Lower() && + bar.low > quarter1) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_WEAK + : X121SMC_XWZ_PRIORITY_HIGH; + } + else if (bar.high < quarter1 && + bar.low > quarter2) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_LOW + : X121SMC_XWZ_PRIORITY_REGULAR; + } + else if (bar.high < quarter2 && + bar.low > quarter3) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_REGULAR + : X121SMC_XWZ_PRIORITY_LOW; + } + else if (bar.high < quarter3 && + bar.low > demandZone.Upper()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_HIGH + : X121SMC_XWZ_PRIORITY_WEAK; + } + else if (bar.high < demandZone.Upper() && + bar.low > demandZone.Lower()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_STRONG_HIGH + : X121SMC_XWZ_PRIORITY_NONE; + } + + // + result = priority != X121SMC_XWZ_PRIORITY_NONE && + priority != X121SMC_XWZ_PRIORITY_WEAK; + + // + bar.Clean(); + + // + return result; + } + + // + // + // + + // + bool HasSupplyZones() + { + return HasChild(supplyZones); + } + + // + int CountSupplyZones() + { + return ArraySize(supplyZones); + } + + // + bool HasDemandZones() + { + return HasChild(demandZones); + } + + // + int CountDemandZones() + { + return ArraySize(demandZones); + } + + // + int DetectSupplyZones( + XPOIState &state // + ) + { + // + int result = CountSupplyZones(); + + bool isValid = state.IsValid() && + state.HasSupplyZones(); + if (!isValid) + { + return result; + } + + // + XCSupplyZone *tmpZones[]; + Copy( + state.supplyZones, + tmpZones // + ); + int count = FilterZones( + // + tmpZones, + // + X_DIRECTION_BULLISH, + state.period, + NULL, + // + // Start ... + XZONE_STATE_IGNORED, + false, + // + // Activation ... + XZONE_STATE_IGNORED, + false, + // + // Breake ... + XZONE_STATE_FAILED, + false, + // + // Work ... + XZONE_STATE_IGNORED, + false, + // + true, // Apply Sore ... + true // Ignore Inside ... + ); + bool has = IsValidSize(count); + if (!has) + { + return result; + } + + // + int idx = -1; + while (HasChild(tmpZones)) + { + // + XCSupplyZone *iZone; + idx = GetHighest(tmpZones); + has = IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(iZone); + continue; + } + + // + iZone = tmpZones[idx]; + + // + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + idx = FindIndex( + iZone, + supplyZones // + ); + has = IsValidIndex(idx); + if (has) + { + // + ZeroMemory(iZone); + continue; + } + + // + Add( + iZone, + supplyZones // + ); + } + + // + int after = CountSupplyZones(); + result = after; + + // + return result; + } + + // + int DetectDemandZones( + XPOIState &state // + ) + { + // + int result = CountDemandZones(); + + bool isValid = state.IsValid() && + state.HasDemandZones(); + if (!isValid) + { + return result; + } + + // + XCDemandZone *tmpZones[]; + Copy( + state.demandZones, + tmpZones // + ); + int count = FilterZones( + // + tmpZones, + // + X_DIRECTION_BEARISH, + state.period, + NULL, + // + // Start ... + XZONE_STATE_IGNORED, + false, + // + // Activation ... + XZONE_STATE_IGNORED, + false, + // + // Breake ... + XZONE_STATE_FAILED, + false, + // + // Work ... + XZONE_STATE_IGNORED, + false, + // + true, // Apply Sore ... + true // Ignore Inside ... + ); + bool has = IsValidSize(count); + if (!has) + { + return result; + } + + // + int idx = -1; + while (HasChild(tmpZones)) + { + // + XCDemandZone *iZone; + idx = GetLowest(tmpZones); + has = IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(iZone); + continue; + } + + // + iZone = tmpZones[idx]; + + // + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + idx = FindIndex( + iZone, + demandZones // + ); + has = IsValidIndex(idx); + if (has) + { + // + ZeroMemory(iZone); + continue; + } + + // + Add( + iZone, + demandZones // + ); + } + + // + int after = CountDemandZones(); + result = after; + + // + return result; + } + + // + // + // + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + + // + has = HasSupplyZone(); + if (has) + { + supplyZone.To(value); + } + + // + has = HasDemandZone(); + if (has) + { + demandZone.To(value); + } + + // + // Order Flow ... + ENUM_X_DIRECTION orderFlowDir; + has = HasOrderFlow(orderFlowDir); + if (has) + { + // + count = CountOrderFlow(); + for (int i = 0; i < count; i++) + { + orderFlow[i].UpdateTo(value); + } + } + + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + supplyZones[i].To(value); + } + } + + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + demandZones[i].To(value); + } + } + + // + } +}; + +// +// Definitions ... +struct X121SMCStrategyXWZSignalConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + double reward; + double amountPercent; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + + // + double pivot; + double point; + double targets[]; + + // + XOBFVG signalZone; + + // + ENUM_X121SMC_XWZ_PRIORITY priority; + ENUM_X121SMC_XWZ_PROVIDERS provider; + + // + // Constructor ... + X121SMCStrategyXWZSignalConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + + // + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + + // + symbol = NULL; + period = NULL; + setupTime = NULL; + triggerTime = NULL; + + // + ExtensionClean(); + + // + ZeroMemory(this); + } + + /** + * Check Condition is Setting Up ... + * + * @param dir: ENUM_X_DIRECTION member, Setting Up Direction ... + * + * @return ( bool ) + */ + bool IsSetuped() + { + // + bool result = false; + + // + result = IsValid(setupTime) && + HasDirection(dir); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Calculate Setup Age ... + * + * @return ( int ) + */ + int GetSetupAge() + { + // + int result = 0; + + // + if (!IsSetuped()) + { + return result; + } + + // + result = (int)(TimeCurrent() - setupTime) / PeriodSeconds(period); + + // + return result; + } + + /** + * Detect How we Can Trigger Signal ... + * + * @return ( bool ) + */ + bool CanTrigger() + { + // + bool result = false; + + // + result = + // + sl > 0 && + IsValid(symbol) && + IsValid(period) && + IsValid(triggerTime) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE + // + ; + + // + return result; + } + + // + // Extensions ... + + /** + * Clean Additional Properties ... + */ + void ExtensionClean() + { + // + pivot = 0; + point = 0; + + // + reward = 0; + amountPercent = 0; + + // + Clean(targets); + signalZone.Clean(); + + // + provider = X121SMC_XWZ_PROVIDER_NONE; + } + + // + // + // + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + } + + // +}; + +// \ No newline at end of file diff --git a/Documents/BKP/x-saherelm.x-poi.class.mq5 b/Documents/BKP/x-saherelm.x-poi.class.mq5 new file mode 100644 index 00000000..be134d9f --- /dev/null +++ b/Documents/BKP/x-saherelm.x-poi.class.mq5 @@ -0,0 +1,4218 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XPOI +// Description: Provides Point of Interests ... +// - Swing Highs; +// - Swing Lows; +// +// 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.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +#include + +// +// Implementation ... + +// +// POI Detector Class ... +class XCPOIDetector : public XCBaseAlert +{ + // + public: + // + XCPOIDrawer *mDrawer; + + // + // Constructors ... + /** + * Create an Instance ... + * + * @param symbol: String ... + * @param period: ENUM_TIMEFRAMES member ... + */ + void XCPOIDetector( + string symbol, + ENUM_TIMEFRAMES period // + ) + { + // + // Attach Required Properties ... + mSymbol = symbol; + mPeriod = period; + + // + // Initialize Bar Tracker ... + mBarTracker.Init( + mSymbol, + mPeriod // + ); + + // + // Create Default Drawer Instance ... + mDrawer = new XCPOIDrawer(); + + // + // Apply Default Configurations ... + Default(); + } + + // + // Deconstructor ... + void ~XCPOIDetector() + { + Destroy(); + } + + // + // Getter(s) / Setter(s) ... + + /** + * Retrieve Detector Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + return mSymbol; + } + + /** + * Retrieve Detector Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + /** + * Get Max Number of POIs which holds ... + * + * @return ( int ) + */ + int MaxNumberOfPOIs() + { + return mMaxNumberOfPOIs; + } + + /** + * Set Max Number of POIs which holds ... + * 0 => Infinity ... + * + * @param value: Integer ... + */ + void MaxNumberOfPOIs(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxNumberOfPOIs = value; + } + + /** + * Get Number of POI(s) which must Find at Initializations ... + * + * @return ( int ) + */ + int MaxNumberOfRequiredPOIs() + { + return mMaxNumberOfRequiredPOIs; + } + + /** + * Set Number of POI(s) which must Find at Initializations ... + * 2 is Default ... + * + * @param value: Integer ... + */ + void MaxNumberOfRequiredPOIs(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mMaxNumberOfRequiredPOIs = value; + } + + /** + * Check Is Locked or not ... + * + * @return ( bool ) + */ + bool IsLocked() + { + return mLock; + } + + // + // POI(s) Configs ... + + // + // Swings ... + + /** + * Get Swing Verification Range Length ... + * + * @return ( int ) + */ + int SwingRange() + { + return mSwingRange; + } + + /** + * Set Swing Verification Range Length ... + * + * @param value: Integer ... + */ + void SwingRange(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mSwingRange = value; + } + + // + // Momentum Bars ... + + /** + * Get Momentum Bars must Extends Range ... + * + * @return ( int ) + */ + int MomentumBarExtendRange() + { + return mMomentumBarExtendRange; + } + + /** + * Set Momentum Bars must Extends Range ... + * + * @param value: Integer ... + */ + void MomentumBarExtendRange(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMomentumBarExtendRange = value; + } + + /** + * Get Momentum Bars Body Percent ... + * + * @return ( double ) + */ + double MomentumBarBodyPercent() + { + return mMomentumBarBodyPercent; + } + + /** + * Set Momentum Bars Body Percent ... + * + * @param value: Double ... + */ + void MomentumBarBodyPercent(double value) + { + // + if (value < 50) + { + value = 50; + } + + // + mMomentumBarBodyPercent = value; + } + + // + // Rejection Bars ... + + /** + * Get Rejection Bars must Extends Range ... + * + * @return ( int ) + */ + int RejectionBarExtendRange() + { + return mRejectionBarExtendRange; + } + + /** + * Set Rejection Bars must Extends Range ... + * + * @param value: Integer ... + */ + void RejectionBarExtendRange(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mRejectionBarExtendRange = value; + } + + /** + * Get Rejection Bars Shadow Percent ... + * + * @return ( double ) + */ + double RejectionBarShadowPercent() + { + return mRejectionBarShadowPercent; + } + + /** + * Set Rejection Bars Shadow Percent ... + * + * @param value: Double ... + */ + void RejectionBarShadowPercent(double value) + { + // + if (value < 50) + { + value = 50; + } + + // + 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; + } + + // + // Supply and Demand Zone(s) ... + + /** + * Get Supply and Demand Range Verifications ... + * + * @return ( int ) + */ + int SupplyAndDemandRange() + { + return mSupplyAndDemandRange; + } + + /** + * Set Supply and Demand Range Verifications ... + * + * @param value: Integer ... + */ + void SupplyAndDemandRange(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mSupplyAndDemandRange = value; + } + + // + // Order Blocks ... + + /** + * Get Order Blocks Detection Bars ... + * + * @return ( int ) + */ + int OrderBlocksSameBars() + { + return mOrderBlocksSameBars; + } + + /** + * Set Order Blocks Detection Bars ... + * + * @param value: Argument 1 + */ + void OrderBlocksSameBars(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mOrderBlocksSameBars = value; + } + + // + // Fair Value Gaps ... + + /** + * Get Fair Value Gaps Detection Same Bars ... + * + * @return ( int ) + */ + int FairValueGapsSameBars() + { + return mFairValueGapsSameBars; + } + + /** + * Set Fair Value Gaps Detection Same Bars ... + * + * @param value: Integer ... + */ + void FairValueGapsSameBars(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + 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 ... + + /** + * Initialize POI Detector ... + */ + void Init() + { + DetectRequiredPOIs(); + } + + /** + * Update POI(s) ... + * + * @param state: an Array Refrence of ENUM_XPOI_EVENTS members ... + */ + int Update( + ENUM_XPOI_EVENTS &state[] // + ) + { + // + int result = 0; + + // + Clean(state); + + // + // Check Bar Tracker if Waits ... + if (!mBarTracker.IsNewBar()) + { + return result; + } + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + datetime cTime = TimeCurrent(); + + // + XOHCL zBar; + bool isInited = zBar.Init( + symbol, + period, + zIndex // + ); + if (!isInited) + { + return result; + } + + // + XOHCL cBar; + isInited = cBar.Init( + symbol, + period, + cIndex // + ); + if (!isInited) + { + return result; + } + + // + // POI Detecting ... + bool isDetected = false; + + // + // Swings ... + int iSwingRange = SwingRange(); + if (iSwingRange > 0) + { + // + XOHCL swingBar; + isInited = swingBar.Init( + symbol, + period, + zIndex + iSwingRange // + ); + if (isInited) + { + // + // Swing High ... + isDetected = DetectSwingHigh(swingBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_SWING_HIGH_DETECTED; + XCSwing *param; + bool hasItem = GetLastItem( + param, + mSwingHighs // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Swing Low ... + isDetected = DetectSwingLow(swingBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_SWING_LOW_DETECTED; + XCSwing *param; + bool hasItem = GetLastItem( + param, + mSwingLows // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + } + } + + // + // Bullish Momentum Bars ... + isDetected = DetectBullishMomentumBar(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BULLISH_MOMENTUM_BAR_DETECTED; + XCMomentumBar *param; + bool hasItem = GetLastItem( + param, + mBullishMomentumBars // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Bearish Momentum Bars ... + isDetected = DetectBearishMomentumBar(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BEARISH_MOMENTUM_BAR_DETECTED; + XCMomentumBar *param; + bool hasItem = GetLastItem( + param, + mBearishMomentumBars // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Bullish Rejection Bars ... + isDetected = DetectBullishRejectionBar(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BULLISH_REJECTION_BAR_DETECTED; + XCRejectionBar *param; + bool hasItem = GetLastItem( + param, + mBullishRejectionBars // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Bearish Rejection Bars ... + isDetected = DetectBearishRejectionBar(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BEARISH_REJECTION_BAR_DETECTED; + XCRejectionBar *param; + bool hasItem = GetLastItem( + param, + mBearishRejectionBars // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // 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 // + ); + } + } + } + + // + // Supply And Demand Zones ... + int supDemRange = SupplyAndDemandRange(); + if (supDemRange > 0) + { + // + // Supply Zone ... + isDetected = DetectSupplyZone(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_SUPPLY_ZONE_DETECTED; + XCSupplyZone *param; + bool hasItem = GetLastItem( + param, + mSupplyZones // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Demand Zone ... + isDetected = DetectDemandZone(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_DEMAND_ZONE_DETECTED; + XCDemandZone *param; + bool hasItem = GetLastItem( + param, + mDemandZones // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + } + + // + // Order Blocks ... + int obSameBars = OrderBlocksSameBars(); + if (obSameBars > 0) + { + // + // Bullish Order Block ... + isDetected = DetectBullishOrderBlock(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BULLISH_ORDERBLOCK_DETECTED; + XCOrderBlock *param; + bool hasItem = GetLastItem( + param, + mBullishOrderBlocks // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Bearish Order Block ... + isDetected = DetectBearishOrderBlock(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BEARISH_ORDERBLOCK_DETECTED; + XCOrderBlock *param; + bool hasItem = GetLastItem( + param, + mBearishOrderBlocks // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + } + + // + // Fair Value Gaps ... + int fvgSameBars = FairValueGapsSameBars(); + if (fvgSameBars > 0) + { + // + // Bullish Fair Value Gap ... + isDetected = DetectBullishFairValueGap(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BULLISH_FVG_DETECTED; + XCFVG *param; + bool hasItem = GetLastItem( + param, + mBullishFairValueGaps // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Bearish Fair Value Gap ... + isDetected = DetectBearishFairValueGap(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BEARISH_FVG_DETECTED; + XCFVG *param; + bool hasItem = GetLastItem( + param, + mBearishFairValueGaps // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + } + + // + // Ticks Range Zone ... + int ticksLevels = TicksRangeZoneLevel(); + int ticksRange = TicksRangeZoneRange(); + if (ticksLevels > 0 && + ticksRange > 0) + { + // + isDetected = DetectTicksZoneRange(cBar); + if (isDetected) + { + } + } + + // + ValidatePOIs(cBar); + + // + CleanupUnusedPOIs(); + + // + mBarTracker.Waits(); + + // + result = ArraySize(state); + + // + return result; + } + + /** + * Destroy Class ... + */ + void Destroy() + { + // + DestroyPOIs(); + DestroySessions(); + DestroyEventListeners(); + + // + delete mDrawer; + delete mTicksZone; + + // + ZeroMemory(mDrawer); + ZeroMemory(mTicksZone); + } + + // + // Retrievers ... + + /** + * Get Current State of POIs ... + * + * @param state: XPOIState instance ... + */ + void GetState( + XPOIState &state // + ) + { + // + state.Clean(); + + // + state.symbol = mSymbol; + state.period = mPeriod; + state.time = TimeCurrent(); + + // + Copy( + mSwingHighs, + state.swingHighs // + ); + + // + Copy( + mSwingLows, + state.swingLows // + ); + + // + Copy( + mBullishMomentumBars, + state.bullishMomentumBars // + ); + + // + Copy( + mBearishMomentumBars, + state.bearishMomentumBars // + ); + + // + Copy( + mBullishRejectionBars, + state.bullishRejectionBars // + ); + + // + Copy( + mBearishRejectionBars, + state.bearishRejectionBars // + ); + + // + Copy( + mSupportZones, + state.supportZones // + ); + + // + Copy( + mResistanceZones, + state.resistanceZones // + ); + + // + Copy( + mSupplyZones, + state.supplyZones // + ); + + // + Copy( + mDemandZones, + state.demandZones // + ); + + // + Copy( + mBullishOrderBlocks, + state.bullishOrderBlocks // + ); + + // + Copy( + mBearishOrderBlocks, + state.bearishOrderBlocks // + ); + + // + Copy( + mBullishFairValueGaps, + state.bullishFairValueGaps // + ); + + // + Copy( + mBearishFairValueGaps, + state.bearishFairValueGaps // + ); + + // + state.ticksZone = mTicksZone; + + // + } + + // + // Event Listeners ... + + /** + * Add Event Listener ... + * + * @param listener: TOnPOIEvent instance ... + */ + void AddEventListener(TOnPOIEvent listener) + { + // + Add( + listener, + mEventListeners // + ); + } + + // + // Destroy ... + + /** + * Destroy Detected POI(s) ... + */ + void DestroyPOIs() + { + // + Clean(mSwingHighs); + Clean(mSwingLows); + + // + Clean(mBullishMomentumBars); + Clean(mBearishMomentumBars); + + // + Clean(mBullishRejectionBars); + Clean(mBearishRejectionBars); + + // + Clean(mSupportZones); + Clean(mResistanceZones); + + // + Clean(mSupplyZones); + Clean(mDemandZones); + + // + Clean(mBullishOrderBlocks); + Clean(mBearishOrderBlocks); + + // + Clean(mBullishFairValueGaps); + Clean(mBearishFairValueGaps); + } + + /** + * Destroy Added Sessions ... + */ + void DestroySessions() + { + } + + /** + * Destroy Rejistered Event Handlers ... + */ + void DestroyEventListeners() + { + Clean(mEventListeners); + } + + // + // Virtual Actions ... + + /** + * Apply Default Configurations ... + */ + virtual void Default() + { + // + // Common ... + + // + MaxNumberOfPOIs(10); + MaxNumberOfRequiredPOIs(2); + + // + SwingRange(2); + + // + MomentumBarExtendRange(2); + MomentumBarBodyPercent(70); + + // + RejectionBarExtendRange(0); + RejectionBarShadowPercent(55); + + // + SupportAndResistanceRange(7); + + // + SupplyAndDemandRange(144); + + // + OrderBlocksSameBars(3); + + // + FairValueGapsSameBars(3); + + // + TicksRangeZoneLevel(10); + TicksRangeZoneRange(144); + } + + // + // Detector Functions ... + + /** + * Detect Swing High ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectSwingHigh(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SwingRange(); + int barIndex = bar.Index(); + result = range > 0 && + barIndex >= range; + if (!result) + { + return result; + } + + // + result = mBarAnalyser.IsSwingHigh( + bar, + range // + ); + if (result) + { + // + XCSwing *swing; + swing = new XCSwing(); + result = swing.Init( + bar, + X_POI_SWING_HIGH // + ); + + // + if (result) + { + // + Add( + swing, + mSwingHighs // + ); + } + } + + // + return result; + } + + /** + * Detect Swing Low ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectSwingLow(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SwingRange(); + int barIndex = bar.Index(); + result = range > 0 && + barIndex >= range; + if (!result) + { + return result; + } + + // + result = mBarAnalyser.IsSwingLow( + bar, + range // + ); + if (result) + { + // + XCSwing *swing; + swing = new XCSwing(); + result = swing.Init( + bar, + X_POI_SWING_LOW // + ); + + // + if (result) + { + // + Add( + swing, + mSwingLows // + ); + } + } + + // + return result; + } + + /** + * Detect Bullish Momentum Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBullishMomentumBar(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + int extendRange = MomentumBarExtendRange(); + double bodyPercent = MomentumBarBodyPercent(); + ENUM_X_DIRECTION dir; + result = mBarAnalyser.IsMomentumBar( + bar, + dir, + extendRange, + bodyPercent // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + if (result) + { + // + XCMomentumBar *momentumBar; + momentumBar = new XCMomentumBar(); + result = momentumBar.Init(bar); + + // + if (result) + { + // + Add( + momentumBar, + mBullishMomentumBars // + ); + } + } + + // + return result; + } + + /** + * Detect Bearish Momentum Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBearishMomentumBar(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + int extendRange = MomentumBarExtendRange(); + double bodyPercent = MomentumBarBodyPercent(); + ENUM_X_DIRECTION dir; + result = mBarAnalyser.IsMomentumBar( + bar, + dir, + extendRange, + bodyPercent // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + if (result) + { + // + XCMomentumBar *momentumBar; + momentumBar = new XCMomentumBar(); + result = momentumBar.Init(bar); + + // + if (result) + { + // + Add( + momentumBar, + mBearishMomentumBars // + ); + } + } + + // + return result; + } + + /** + * Detect Bullish Rejection Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBullishRejectionBar(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + int extendRange = RejectionBarExtendRange(); + double shadowPercent = RejectionBarShadowPercent(); + ENUM_X_DIRECTION dir; + result = mBarAnalyser.IsRejectionBar( + bar, + dir, + extendRange, + shadowPercent // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + if (result) + { + // + XCRejectionBar *rejectionBar; + rejectionBar = new XCRejectionBar(); + result = rejectionBar.Init(bar); + + // + if (result) + { + // + Add( + rejectionBar, + mBullishRejectionBars // + ); + } + } + + // + return result; + } + + /** + * Detect Bearish Rejection Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBearishRejectionBar(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + int extendRange = RejectionBarExtendRange(); + double shadowPercent = RejectionBarShadowPercent(); + ENUM_X_DIRECTION dir; + result = mBarAnalyser.IsRejectionBar( + bar, + dir, + extendRange, + shadowPercent // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + if (result) + { + // + XCRejectionBar *rejectionBar; + rejectionBar = new XCRejectionBar(); + result = rejectionBar.Init(bar); + + // + if (result) + { + // + Add( + rejectionBar, + mBearishRejectionBars // + ); + } + } + + // + return result; + } + + /** + * 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 // + ); + } + } + + // + return result; + } + + /** + * 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 // + ); + } + } + + // + return result; + } + + /** + * Detect Supply Zone ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectSupplyZone(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SupplyAndDemandRange(); + result = range > 0; + if (!result) + { + return result; + } + + // + int hhIDX = -1; + double hh = -1; + + // + int llIDX = -1; + double ll = -1; + + // + result = mBarAnalyser + .CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + range // + ); + if (!result) + { + return result; + } + + // + XOHCL supplyBar; + result = supplyBar.Init( + bar.symbol, + bar.period, + hhIDX // + ); + if (result) + { + // + XCSupplyZone *supply; + supply = new XCSupplyZone(); + result = supply.Init( + supplyBar, + range // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + supply.To(cTime); + + // + Add( + supply, + mSupplyZones // + ); + } + } + + // + return result; + } + + /** + * Detect Demand Zone ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectDemandZone(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SupplyAndDemandRange(); + result = range > 0; + if (!result) + { + return result; + } + + // + int hhIDX = -1; + double hh = -1; + + // + int llIDX = -1; + double ll = -1; + + // + result = mBarAnalyser + .CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + range // + ); + if (!result) + { + return result; + } + + // + XOHCL demandBar; + result = demandBar.Init( + bar.symbol, + bar.period, + llIDX // + ); + if (result) + { + // + XCDemandZone *demand; + demand = new XCDemandZone(); + result = demand.Init( + demandBar, + range // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + demand.To(cTime); + + // + Add( + demand, + mDemandZones // + ); + } + } + + // + return result; + } + + /** + * Detect Bullish Order Block ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBullishOrderBlock(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sameBars = OrderBlocksSameBars(); + result = sameBars > 0; + if (!result) + { + return result; + } + + // + XOHCL obBar; + ENUM_X_DIRECTION dir; + result = mBarAnalyser + .HasOrderBlock( + bar, + obBar, + dir, + sameBars // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + if (!result) + { + return result; + } + + // + if (result) + { + // + XCOrderBlock *ob; + ob = new XCOrderBlock(); + result = ob.Init( + obBar, + dir // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + ob.To(cTime); + + // + Add( + ob, + mBullishOrderBlocks // + ); + } + } + + // + return result; + } + + /** + * Detect Bullish Order Block ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBullishOrderBlock( + XOHCL &bar, + XCOrderBlock *&ob // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sameBars = OrderBlocksSameBars(); + result = sameBars > 0; + if (!result) + { + return result; + } + + // + XOHCL obBar; + ENUM_X_DIRECTION dir; + result = mBarAnalyser + .HasOrderBlock( + bar, + obBar, + dir, + sameBars // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + if (!result) + { + return result; + } + + // + if (result) + { + // + ob = new XCOrderBlock(); + result = ob.Init( + obBar, + dir // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + ob.To(cTime); + } + } + + // + return result; + } + + /** + * Detect Bearish Order Block ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBearishOrderBlock(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sameBars = OrderBlocksSameBars(); + result = sameBars > 0; + if (!result) + { + return result; + } + + // + XOHCL obBar; + ENUM_X_DIRECTION dir; + result = mBarAnalyser + .HasOrderBlock( + bar, + obBar, + dir, + sameBars // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + if (!result) + { + return result; + } + + // + if (result) + { + // + XCOrderBlock *ob; + ob = new XCOrderBlock(); + result = ob.Init( + obBar, + dir // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + ob.To(cTime); + + // + Add( + ob, + mBearishOrderBlocks // + ); + } + } + + // + return result; + } + + /** + * Detect Bearish Order Block ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBearishOrderBlock( + XOHCL &bar, + XCOrderBlock *&ob // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sameBars = OrderBlocksSameBars(); + result = sameBars > 0; + if (!result) + { + return result; + } + + // + XOHCL obBar; + ENUM_X_DIRECTION dir; + result = mBarAnalyser + .HasOrderBlock( + bar, + obBar, + dir, + sameBars // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + if (!result) + { + return result; + } + + // + if (result) + { + // + ob = new XCOrderBlock(); + result = ob.Init( + obBar, + dir // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + ob.To(cTime); + } + } + + // + return result; + } + + /** + * Detect Bullish Fair Value Gap ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBullishFairValueGap(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sameBars = FairValueGapsSameBars(); + result = sameBars > 0; + if (!result) + { + return result; + } + + // + XOHCL prevBar; + XOHCL nextBar; + ENUM_X_DIRECTION dir; + result = mBarAnalyser + .HasFairValueGap( + bar, + prevBar, + nextBar, + dir, + sameBars // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + if (!result) + { + return result; + } + + // + if (result) + { + // + XCFVG *fvg; + fvg = new XCFVG(); + result = fvg.Init( + prevBar, + nextBar, + dir // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + fvg.To(cTime); + + // + Add( + fvg, + mBullishFairValueGaps // + ); + } + } + + // + return result; + } + + /** + * Detect Bearish Fair Value Gap ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBearishFairValueGap(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sameBars = FairValueGapsSameBars(); + result = sameBars > 0; + if (!result) + { + return result; + } + + // + XOHCL prevBar; + XOHCL nextBar; + ENUM_X_DIRECTION dir; + result = mBarAnalyser + .HasFairValueGap( + bar, + prevBar, + nextBar, + dir, + sameBars // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + if (!result) + { + return result; + } + + // + if (result) + { + // + XCFVG *fvg; + fvg = new XCFVG(); + result = fvg.Init( + prevBar, + nextBar, + dir // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + fvg.To(cTime); + + // + Add( + fvg, + mBearishFairValueGaps // + ); + } + } + + // + return result; + } + + // + protected: + // + + // + // Actions ... + + /** + * Lock ... + */ + void Lock() + { + mLock = true; + } + + /** + * Unlock ... + */ + void Unlock() + { + mLock = false; + } + + /** + * Detect Required POI(s) ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + */ + void DetectRequiredPOIs(int barIndex = 0) + { + // + // Validate Reuired POI(s) ... + int requiredPOIs = MaxNumberOfRequiredPOIs(); + if (requiredPOIs <= 0) + { + return; + } + + // + // Locking Detector ... + Lock(); + + // + // Normalize Bar Index ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + int swingLowsCount = 0; + int swingHighsCount = 0; + + // + int bullishMomentumBarsCount = 0; + int bearishMomentumBarsCount = 0; + + // + int bullishRejectionBarsCount = 0; + int bearishRejectionBarsCount = 0; + + // + int supportZonesCount = 0; + int resistanceZonesCount = 0; + + // + int supplyZonesCount = 0; + int demandZonesCount = 0; + + // + int bullishOrderBlocksCount = 0; + int bearishOrderBlocksCount = 0; + + // + int bullishFairValueGapsCount = 0; + int bearishFairValueGapsCount = 0; + + // + bool canContinue = true; + + // + while (canContinue) + { + // + // Swings ... + int iSwingRange = SwingRange(); + if (iSwingRange > 0) + { + // + // Swing Highs ... + swingHighsCount = DetectRequiredSwingHighs(barIndex); + if (swingHighsCount == requiredPOIs) + { + ArrayReverse(mSwingHighs); + } + + // + // Swing Lows ... + swingLowsCount = DetectRequiredSwingLows(barIndex); + if (swingLowsCount == requiredPOIs) + { + ArrayReverse(mSwingLows); + } + } + + // + bool canLookupMomentumBars = + MomentumBarExtendRange() >= 0 && + MomentumBarBodyPercent() > 0; + if (canLookupMomentumBars) + { + // + // + // Bullish Momentum Bars ... + bullishMomentumBarsCount = DetectRequiredBullishMomentumBars(barIndex); + if (bullishMomentumBarsCount == requiredPOIs) + { + ArrayReverse(mBullishMomentumBars); + } + + // + // Bearish Momentum Bars ... + bearishMomentumBarsCount = DetectRequiredBearishMomentumBars(barIndex); + if (bearishMomentumBarsCount == requiredPOIs) + { + ArrayReverse(mBearishMomentumBars); + } + } + + // + bool canLookupRejectionBars = + RejectionBarExtendRange() >= 0 && + RejectionBarShadowPercent() > 0; + if (canLookupRejectionBars) + { + // + // + // Bullish Rejection Bars ... + bullishRejectionBarsCount = DetectRequiredBullishRejectionBars(barIndex); + if (bullishRejectionBarsCount == requiredPOIs) + { + ArrayReverse(mBullishRejectionBars); + } + + // + // Bearish Rejection Bars ... + bearishRejectionBarsCount = DetectRequiredBearishRejectionBars(barIndex); + if (bearishRejectionBarsCount == requiredPOIs) + { + ArrayReverse(mBearishRejectionBars); + } + } + + // + // Support and Resistance Zones ... + int supResRange = SupportAndResistanceRange(); + if (supResRange > 0) + { + // + // Support Zone(s) ... + supportZonesCount = DetectRequiredSupportZones(barIndex); + if (supportZonesCount == requiredPOIs) + { + ArrayReverse(mSupportZones); + } + + // + // Resistance Zone(s) ... + resistanceZonesCount = DetectRequiredResistanceZones(barIndex); + if (resistanceZonesCount == requiredPOIs) + { + ArrayReverse(mResistanceZones); + } + } + + // + // Supply and Demand Zones ... + int supDemRange = SupplyAndDemandRange(); + if (supDemRange > 0) + { + // + supplyZonesCount = DetectRequiredSupplyZones(barIndex); + if (supplyZonesCount == requiredPOIs) + { + ArrayReverse(mSupplyZones); + } + + // + demandZonesCount = DetectRequiredDemandZones(barIndex); + if (demandZonesCount == requiredPOIs) + { + ArrayReverse(mDemandZones); + } + } + + // + // Oder Blocks ... + int obSameBars = OrderBlocksSameBars(); + if (obSameBars > 0) + { + // + // Bullish Order Blocks ... + bullishOrderBlocksCount = DetectRequiredBullishOrderBlocks(barIndex); + if (bullishOrderBlocksCount == requiredPOIs) + { + ArrayReverse(mBullishOrderBlocks); + } + + // + // Bearish Order Blocks ... + bearishOrderBlocksCount = DetectRequiredBearishOrderBlocks(barIndex); + if (bearishOrderBlocksCount == requiredPOIs) + { + ArrayReverse(mBearishOrderBlocks); + } + } + + // + // Fair Value Gaps ... + int fvgSameBars = FairValueGapsSameBars(); + if (fvgSameBars > 0) + { + // + // Bullish Fair Value Gaps ... + bullishFairValueGapsCount = DetectRequiredBullishFairValueGaps(barIndex); + if (bullishFairValueGapsCount == requiredPOIs) + { + ArrayReverse(mBullishFairValueGaps); + } + + // + // Bearish Fair Value Gaps ... + bearishFairValueGapsCount = DetectRequiredBearishFairValueGaps(barIndex); + if (bearishFairValueGapsCount == requiredPOIs) + { + ArrayReverse(mBearishFairValueGaps); + } + } + + // + // Swings ... + bool canContinueSwingHighs = + iSwingRange > 0 + ? swingHighsCount < requiredPOIs + : false; + bool canContinueSwingLows = + iSwingRange > 0 + ? swingLowsCount < requiredPOIs + : false; + + // + // Support and Resistance Zones ... + bool canContinueSupportZones = + supResRange > 0 + ? supportZonesCount < requiredPOIs + : false; + bool canContinueResistanceZones = + supResRange > 0 + ? resistanceZonesCount < requiredPOIs + : false; + + // + // Supply and Demand Zones ... + bool canContinueSupplyZones = + supDemRange > 0 + ? supplyZonesCount < requiredPOIs + : false; + bool canContinueDemandZones = + supDemRange > 0 + ? demandZonesCount < requiredPOIs + : false; + + // + // Order Blocks ... + bool canContinueBullishOrderBlocks = + obSameBars > 0 + ? bullishOrderBlocksCount < requiredPOIs + : false; + bool canContinueBearishOrderBlocks = + obSameBars > 0 + ? bearishOrderBlocksCount < requiredPOIs + : false; + + // + // Fair Value Gaps ... + bool canContinueBullishFairValueGaps = + fvgSameBars > 0 + ? bullishFairValueGapsCount < requiredPOIs + : false; + bool canContinueBearishFairValueGaps = + fvgSameBars > 0 + ? bearishFairValueGapsCount < requiredPOIs + : false; + + // + // Rejection Bars ... + bool canContinueBullishRejectionBars = + canLookupRejectionBars + ? bullishRejectionBarsCount < requiredPOIs + : false; + bool canContinueBearishRejectionBars = + canLookupRejectionBars + ? bearishRejectionBarsCount < requiredPOIs + : false; + + // + // Momentum Bars ... + bool canContinueBullishMomentumBars = + canLookupMomentumBars + ? bullishMomentumBarsCount < requiredPOIs + : false; + bool canContinueBearishMomentumBars = + canLookupMomentumBars + ? bearishMomentumBarsCount < requiredPOIs + : false; + + // + canContinue = + // + // Swings ... + canContinueSwingHighs || + canContinueSwingLows || + // + // Support and Resistance Zones ... + canContinueSupportZones || + canContinueResistanceZones || + // + // Supply and Demand Zones ... + canContinueSupplyZones || + canContinueDemandZones || + // + // Order Blocks ... + canContinueBullishOrderBlocks || + canContinueBearishOrderBlocks || + // + // Fair Value Gaps ... + canContinueBullishFairValueGaps || + canContinueBearishFairValueGaps || + // + // Rejection Bars ... + canContinueBullishRejectionBars || + canContinueBearishRejectionBars || + // + // Momentum Bars ... + canContinueBullishMomentumBars || + canContinueBearishMomentumBars + // + ; + if (canContinue) + { + barIndex++; + } + } + + // + // Unlocking Detector ... + Unlock(); + } + + /** + * Validate Founded POI(s) ... + * + * @param bar: XOHCL instance ... + */ + void ValidatePOIs(XOHCL &bar) + { + } + + /** + * Cleanup Unused Objects ... + */ + void CleanupUnusedPOIs() + { + // + int maxAllowed = MaxNumberOfPOIs(); + if (!IsValidSize(maxAllowed)) + { + return; + } + + // + int swingHighsCount = ArraySize(mSwingHighs); + int swingLowsCount = ArraySize(mSwingLows); + // int tradingDaysCount = ArraySize(mTradingDays); + // int marketSessionsCount = ArraySize(mMarketSessions); + // int momentumBarsCount = ArraySize(mMomentumBars); + // int rejectionBarsCount = ArraySize(mRejectionBars); + // int supportZonesCount = ArraySize(mSupportZones); + // int resistanceZonesCount = ArraySize(mResistanceZones); + // int supplyZonesCount = ArraySize(mSupplyZones); + // int demandZonesCount = ArraySize(mDemandZones); + // int bullishOBsCount = ArraySize(mBullishOrderBlocks); + // int bearishOBsCount = ArraySize(mBearishOrderBlocks); + // int bullishFVGsCount = ArraySize(mBullishFVGs); + // int bearishFVGsCount = ArraySize(mBearishFVGs); + + // + int from = 0; + int requiredPOIs = MaxNumberOfRequiredPOIs(); + int count = maxAllowed - requiredPOIs; + int to = count - 1; + + // + // Swings ... + + // // + // // Swing Highs ... + // if (swingHighsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mSwingHighs, + // from, + // count // + // ); + // } + + // // + // // Swing Lows ... + // if (swingLowsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mSwingLows, + // from, + // count // + // ); + // } + + // // + // // Trading Days ... + // if (tradingDaysCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mTradingDays, + // from, + // count // + // ); + + // // + // mTradingDayObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Market Sessions ... + // if (marketSessionsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mMarketSessions, + // from, + // count // + // ); + + // // + // mMarketSessionObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Momentum Bars ... + // if (momentumBarsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mMomentumBars, + // from, + // count // + // ); + + // // + // mMomentumBarObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Rejection Bars ... + // if (rejectionBarsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mRejectionBars, + // from, + // count // + // ); + + // // + // mRejectionBarObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Support and Resistance Zones ... + + // // + // // Support Zones ... + // if (supportZonesCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mSupportZones, + // from, + // count // + // ); + + // // + // mSupportZoneObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Resistance Zones ... + // if (resistanceZonesCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mResistanceZones, + // from, + // count // + // ); + + // // + // mResistanceZoneObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Supply and Demand Zones ... + + // // + // // Supply Zones ... + // if (supplyZonesCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mSupplyZones, + // from, + // count // + // ); + + // // + // mSupplyZoneObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Demand Zones ... + // if (demandZonesCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mDemandZones, + // from, + // count // + // ); + + // // + // mDemandZoneObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Order Blocks ... + + // // + // // Bullish Order Blocks ... + // if (bullishOBsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mBullishOrderBlocks, + // from, + // count // + // ); + + // // + // mBullishOrderBlockObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Bearish Order Blocks ... + // if (bearishOBsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mBearishOrderBlocks, + // from, + // count // + // ); + + // // + // mBearishOrderBlockObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Fair Vakue Gaps ... + + // // + // // Bullish FVGs ... + // if (bullishFVGsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mBullishFVGs, + // from, + // count // + // ); + + // // + // mBullishFVGObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Bearish FVGs ... + // if (bearishFVGsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mBearishFVGs, + // from, + // count // + // ); + + // // + // mBearishFVGObjects.DeleteRange( + // from, + // to // + // ); + // } + + // + } + + /** + * Notify Event Listeners ... + * + * @param event: ENUM_XPOI_EVENTS member, Specified Occured Event ... + * @param param: XCBasePOI implementation, Specified Event Object ... + */ + void NotifyEventListeners( + ENUM_XPOI_EVENTS event, + XCBasePOI *param // + ) + { + // + int count = ArraySize(mEventListeners); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + mEventListeners[i]( + event, + param // + ); + } + } + + void AddObjectIfNotExists(XCBaseObject *object) + { + // + string name = object.ObjName(); + + // + bool canAdd = true; + int count = mDrawnObjects.Total(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + string iName = ((XCBaseObject *)mDrawnObjects.At(i)).ObjName(); + + // + if (name == iName) + { + // + canAdd = false; + break; + } + } + } + + // + if (canAdd) + { + mDrawnObjects.Add(object); + } + } + + // + private: + // + + // + // Props ... + + // + bool mLock; // Lock State ... + string mSymbol; // Market Symbol ... + ENUM_TIMEFRAMES mPeriod; // Market Period ... + int mMaxNumberOfPOIs; // Max Allowed Number of POI(s) which Can Holds ... + int mMaxNumberOfRequiredPOIs; // Max Allowed Number of POI(s) which Must Find at Initializion Time ... + + // + CArrayObj mDrawnObjects; // Drawn Objects ... + XBarTracker mBarTracker; // Market Bar Tracker ... + XCBarAnalyser mBarAnalyser; // Bar Analyser ... + + // + TOnPOIEvent mEventListeners[]; // Event Listeners ... + + // + // POI Props ... + + // + // XDay ... + + // + // XSession ... + + // + // XSwing ... + int mSwingRange; // Swing Verification Range Length ... + + // + // Swing High ... + + // + XCSwing *mSwingHighs[]; // Holds Founded Swing Highs ... + + /** + * Detect Required Swing Highs ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredSwingHighs(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mSwingHighs); + if (count >= required) + { + // + result = count; + return result; + } + + // + int range = SwingRange(); + 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; + } + + // + DetectSwingHigh(bar); + + // + result = ArraySize(mSwingHighs); + + // + return result; + } + + // + // Swing Low ... + + // + XCSwing *mSwingLows[]; // Holds Founded Swing Lows ... + + /** + * Detect Required Swing Lows ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredSwingLows(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mSwingLows); + if (count >= required) + { + // + result = count; + return result; + } + + // + int range = SwingRange(); + 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; + } + + // + DetectSwingLow(bar); + + // + result = ArraySize(mSwingLows); + + // + return result; + } + + // + // Momentum Bars ... + int mMomentumBarExtendRange; // Momentum Bars must Extends Range ... + double mMomentumBarBodyPercent; // Momentum Bars Body Percent ... + + // + // Bullish ... + XCMomentumBar *mBullishMomentumBars[]; // Holds Founded Bullish Momentum Bars ... + + /** + * Detect Required Bullish Momentum Bars ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBullishMomentumBars(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBullishMomentumBars); + if (count >= required) + { + // + result = count; + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBullishMomentumBar(bar); + + // + result = ArraySize(mBullishMomentumBars); + + // + return result; + } + + // + // Bearish ... + XCMomentumBar *mBearishMomentumBars[]; // Holds Founded Bearish Momentum Bars ... + + /** + * Detect Required Bearish Momentum Bars ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBearishMomentumBars(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBearishMomentumBars); + if (count >= required) + { + // + result = count; + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBearishMomentumBar(bar); + + // + result = ArraySize(mBearishMomentumBars); + + // + return result; + } + + // + // Rejection Bars ... + int mRejectionBarExtendRange; // Rejection Bars must Extends Range ... + double mRejectionBarShadowPercent; // Rejection Bars Shadow Percent ... + + // + // Bullish ... + XCRejectionBar *mBullishRejectionBars[]; // Holds Founded Bullish Rejection Bars ... + + /** + * Detect Required Bullish Rejection Bars ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBullishRejectionBars(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBullishRejectionBars); + if (count >= required) + { + // + result = count; + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBullishRejectionBar(bar); + + // + result = ArraySize(mBullishRejectionBars); + + // + return result; + } + + // + // Bearish ... + XCRejectionBar *mBearishRejectionBars[]; // Holds Founded Bearish Rejection Bars ... + + /** + * Detect Required Bearish Rejection Bars ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBearishRejectionBars(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBearishRejectionBars); + if (count >= required) + { + // + result = count; + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBearishRejectionBar(bar); + + // + result = ArraySize(mBearishRejectionBars); + + // + return result; + } + + // + // Support and Resistance Zone ... + int mSupportAndResistanceRange; // Support and Resistance Range for Verification ... + + // + // Support Zone(s) ... + XCSupportZone *mSupportZones[]; // Holds Founded Support Zones ... + + /** + * 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 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 and Demand Zones ... + int mSupplyAndDemandRange; // Supply and Demand Range Verifications ... + + // + // Supply Zone(s) ... + XCSupplyZone *mSupplyZones[]; // Holds Founded Supply Zones ... + + /** + * Detect Required Supply Zones ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredSupplyZones(int barIndex) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mSupplyZones); + if (count >= required) + { + // + result = count; + return result; + } + + // + int range = SupplyAndDemandRange(); + if (range < 0) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectSupplyZone(bar); + + // + result = ArraySize(mSupplyZones); + + // + return result; + } + + // + // Demand Zone(s) ... + XCDemandZone *mDemandZones[]; // Holds Founded Demand Zones ... + + /** + * Detect Required Demand Zones ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredDemandZones(int barIndex) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mDemandZones); + if (count >= required) + { + // + result = count; + return result; + } + + // + int range = SupplyAndDemandRange(); + if (range < 0) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectDemandZone(bar); + + // + result = ArraySize(mDemandZones); + + // + return result; + } + + // + // Order Blocks ... + int mOrderBlocksSameBars; // Order Blocks Detection Bars ... + + // + // Bullish OB ... + XCOrderBlock *mBullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ... + + /** + * Detect Required Bullish Order Blocks ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBullishOrderBlocks(int barIndex) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBullishOrderBlocks); + if (count >= required) + { + // + result = count; + return result; + } + + // + int sameBars = OrderBlocksSameBars(); + if (sameBars < 0) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBullishOrderBlock(bar); + + // + result = ArraySize(mBullishOrderBlocks); + + // + return result; + } + + // + // Bearish OB ... + XCOrderBlock *mBearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ... + + /** + * Detect Required Bearish Order Blocks ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBearishOrderBlocks(int barIndex) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBearishOrderBlocks); + if (count >= required) + { + // + result = count; + return result; + } + + // + int sameBars = OrderBlocksSameBars(); + if (sameBars < 0) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBearishOrderBlock(bar); + + // + result = ArraySize(mBearishOrderBlocks); + + // + return result; + } + + // + // Fair Value Gaps ... + int mFairValueGapsSameBars; // Fair Value Gaps Detection Same Bars ... + + // + // Bullish FVG ... + XCFVG *mBullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ... + + /** + * Detect Required Bullish Fair Value Gaps ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBullishFairValueGaps(int barIndex) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBullishFairValueGaps); + if (count >= required) + { + // + result = count; + return result; + } + + // + int sameBars = FairValueGapsSameBars(); + if (sameBars < 0) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBullishFairValueGap(bar); + + // + result = ArraySize(mBullishFairValueGaps); + + // + return result; + } + + // + // Bearish FVG ... + XCFVG *mBearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ... + + /** + * Detect Required Bearish Fair Value Gaps ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBearishFairValueGaps(int barIndex) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBearishFairValueGaps); + if (count >= required) + { + // + result = count; + return result; + } + + // + int sameBars = FairValueGapsSameBars(); + if (sameBars < 0) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBearishFairValueGap(bar); + + // + result = ArraySize(mBearishFairValueGaps); + + // + 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; + } + + // + return result; + } + + // + // Liquidity Zones ... + + // + // Sell Side ... + + // + // Buy Side ... + + // +}; + +// \ No newline at end of file diff --git a/Documents/BKP/x-saherelm.xobfvg.lib.mq5 b/Documents/BKP/x-saherelm.xobfvg.lib.mq5 new file mode 100644 index 00000000..39396031 --- /dev/null +++ b/Documents/BKP/x-saherelm.xobfvg.lib.mq5 @@ -0,0 +1,1897 @@ +// /////////////////////////////////////////////////////// +// // +// // SaherElm IT Center MQL5 Seriallize Library +// // --------------------------------------- +// // Name: XOBFVGLib +// // Description: All models related to POIs ... +// // +// // +// // Maintainer: +// // ------------ +// // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// // +// ////////////////////////////////////////////////////// +// // +// // Global Properties ... +// #property library +// #property copyright "Copyright `023, SaherElm IT Center" +// #property link "https://www.saherelm.ir" +// #property version "1.00" +// #property strict + +// // +// // Imports ... +// #include "../Libraries/x-saherelm.x-poi.state.lib.mq5" + +// // +// struct XOBFVGPivot +// { +// // +// // Props ... +// double value; +// datetime at; + +// // +// // Constructor ... +// XOBFVGPivot() +// { +// Clean(); +// } + +// // +// // Tools ... + +// // +// void Clean() +// { +// // +// value = 0; +// at = NULL; + +// // +// ZeroMemory(this); +// } + +// // +// bool IsValid() +// { +// // +// bool result = false; + +// // +// result = +// value > 0 && +// IsValid(at); + +// // +// return result; +// } +// }; + +// // +// struct XOBFVG +// { +// // +// // Props ... +// XCFVG *fvg; +// XCOrderBlock *ob; + +// // +// XCSupplyZone *supplyZones[]; +// XCDemandZone *demandZones[]; + +// // +// XCSupportZone *supportZones[]; +// XCResistanceZone *resistanceZones[]; + +// // +// // Constructor ... +// XOBFVG() +// { +// Clean(); +// } + +// // +// // Tools ... + +// // +// void Clean() +// { +// // +// ZeroMemory(ob); +// ZeroMemory(fvg); + +// // +// Clean(supplyZones); +// Clean(demandZones); +// Clean(supportZones); +// Clean(resistanceZones); + +// // +// ZeroMemory(this); +// } + +// // +// bool IsValid() +// { +// return HasOB() && +// HasFVG(); +// } + +// // +// bool HasOB() +// { +// return ob != NULL && +// ob.IsValid(); +// } + +// // +// bool HasFVG() +// { +// return fvg != NULL && +// fvg.IsValid(); +// } + +// // +// bool HasSupplyZones() +// { +// return HasChild(supplyZones); +// } + +// // +// int CountSupplyZones() +// { +// return ArraySize(supplyZones); +// } + +// // +// bool HasDemandZones() +// { +// return HasChild(demandZones); +// } + +// // +// int CountDemandZones() +// { +// return ArraySize(demandZones); +// } + +// // +// bool HasSupportZones() +// { +// return HasChild(supportZones); +// } + +// // +// int CountSupportZones() +// { +// return ArraySize(supportZones); +// } + +// // +// bool HasResistanceZones() +// { +// return HasChild(resistanceZones); +// } + +// // +// int CountResistanceZones() +// { +// return ArraySize(resistanceZones); +// } + +// // +// ENUM_X_DIRECTION GetDirection() +// { +// // +// ENUM_X_DIRECTION result = X_DIRECTION_NONE; + +// // +// bool isValid = IsValid(); +// if (!isValid) +// { +// return result; +// } + +// // +// result = ob.GetDirection(); + +// // +// return result; +// } + +// // +// bool IsBullish() +// { +// return IsBullish(GetDirection()); +// } + +// // +// bool IsBearish() +// { +// return IsBearish(GetDirection()); +// } + +// // +// int GetSwings( +// XOBFVGPivot &pivots[] // +// ) +// { +// // +// int result = 0; + +// // +// Clean(pivots); + +// // +// if (!IsValid()) +// { +// return result; +// } + +// // +// ENUM_X_DIRECTION forDir = GetDirection(); +// bool isBullish = IsBullish(forDir); + +// // +// XOHCL passedBar; +// XOBFVGPivot iPivot; +// bool isPassed = false; +// double appliedPrice = 0; +// bool isBodyState = false; + +// // +// // Start ... +// isPassed = ob.IsStarted( +// forDir, +// passedBar, +// isBodyState // +// ); +// if (isPassed) +// { +// // +// appliedPrice = +// isBullish +// ? passedBar.low +// : passedBar.high; + +// // +// iPivot.Clean(); +// iPivot.value = appliedPrice; +// iPivot.at = passedBar.time; + +// // +// AddRef( +// iPivot, +// pivots // +// ); + +// // +// iPivot.Clean(); +// } + +// // +// // Activation ... +// isPassed = ob.IsActivated( +// forDir, +// passedBar, +// isBodyState // +// ); +// if (isPassed) +// { +// // +// appliedPrice = +// isBullish +// ? passedBar.low +// : passedBar.high; + +// // +// iPivot.Clean(); +// iPivot.value = appliedPrice; +// iPivot.at = passedBar.time; + +// // +// AddRef( +// iPivot, +// pivots // +// ); + +// // +// iPivot.Clean(); +// } + +// // +// // Worked ... +// isPassed = ob.IsWorked( +// forDir, +// passedBar, +// isBodyState // +// ); +// if (isPassed) +// { +// // +// appliedPrice = +// isBullish +// ? passedBar.low +// : passedBar.high; + +// // +// iPivot.Clean(); +// iPivot.value = appliedPrice; +// iPivot.at = passedBar.time; + +// // +// AddRef( +// iPivot, +// pivots // +// ); + +// // +// iPivot.Clean(); +// } + +// // +// passedBar.Clean(); + +// // +// result = ArraySize(pivots); + +// // +// return result; +// } + +// // +// void UpdateZones( +// XPOIState &state // +// ) +// { +// // +// Clean(supplyZones); +// Clean(demandZones); +// Clean(supportZones); +// Clean(resistanceZones); + +// // +// bool isValid = +// IsValid() && +// state.HasChild(); +// if (!isValid) +// { +// return; +// } + +// // +// int count = 0; +// bool has = false; +// bool isPassed = false; + +// // +// // Supply Zones ... +// has = state.HasSupplyZones(); +// if (has) +// { +// // +// count = state.CountSupplyZones(); +// for (int i = 0; i < count; i++) +// { +// // +// XCSupplyZone *iZone = state.supplyZones[i]; + +// // +// isPassed = iZone.From() > ob.From(); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// isPassed = IsInsideDiff( +// iZone, +// ob // +// ); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// Add( +// iZone, +// supplyZones // +// ); +// } +// } + +// // +// // Demand Zones ... +// has = state.HasDemandZones(); +// if (has) +// { +// // +// count = state.CountDemandZones(); +// for (int i = 0; i < count; i++) +// { +// // +// XCDemandZone *iZone = state.demandZones[i]; + +// // +// isPassed = iZone.From() > ob.From(); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// isPassed = IsInsideDiff( +// iZone, +// ob // +// ); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// Add( +// iZone, +// demandZones // +// ); +// } +// } + +// // +// // Support Zones ... +// has = state.HasSupportZones(); +// if (has) +// { +// // +// count = state.CountSupportZones(); +// for (int i = 0; i < count; i++) +// { +// // +// XCSupportZone *iZone = state.supportZones[i]; + +// // +// isPassed = iZone.From() > ob.From(); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// isPassed = IsInsideDiff( +// iZone, +// ob // +// ); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// Add( +// iZone, +// supportZones // +// ); +// } +// } + +// // +// // Resistance Zones ... +// has = state.HasResistanceZones(); +// if (has) +// { +// // +// count = state.CountResistanceZones(); +// for (int i = 0; i < count; i++) +// { +// // +// XCResistanceZone *iZone = state.resistanceZones[i]; + +// // +// isPassed = iZone.From() > ob.From(); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// isPassed = IsInsideDiff( +// iZone, +// ob // +// ); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// Add( +// iZone, +// resistanceZones // +// ); +// } +// } +// } + +// // +// void UpdateTo(datetime value = NULL) +// { +// // +// value = NormalizeTime(value); + +// // +// int count = 0; +// bool has = false; + +// // +// has = HasOB(); +// if (has) +// { +// ob.To(value); +// } + +// // +// has = HasFVG(); +// if (has) +// { +// fvg.To(value); +// } + +// // +// // Supply Zones ... +// has = HasSupplyZones(); +// if (has) +// { +// // +// count = CountSupplyZones(); +// for (int i = 0; i < count; i++) +// { +// supplyZones[i].To(value); +// } +// } + +// // +// // Demand Zones ... +// has = HasDemandZones(); +// if (has) +// { +// // +// count = CountDemandZones(); +// for (int i = 0; i < count; i++) +// { +// demandZones[i].To(value); +// } +// } + +// // +// // Support Zones ... +// has = HasSupportZones(); +// if (has) +// { +// // +// count = CountSupportZones(); +// for (int i = 0; i < count; i++) +// { +// supportZones[i].To(value); +// } +// } + +// // +// // Resistance Zones ... +// has = HasResistanceZones(); +// if (has) +// { +// // +// count = CountResistanceZones(); +// for (int i = 0; i < count; i++) +// { +// resistanceZones[i].To(value); +// } +// } +// } +// }; + +// // +// // +// // + +// /** +// * Extract XOBFVG Collection of Market ... +// * +// * @param htfState: Higher Time Frame POI State (Used For Detecting Order Blocks) ... +// * @param mtfState: Medium Time Frame POI State (Used For Detecting Fair Value Gaps) ... +// * @param stfState: Short Time Frame POI State (Used For Detecting Other POI(s)) ... +// * @param dest: Result Collection ... +// * @param forDir: Market Direction for Detecting POI(s) ... +// * @param forPeriod: Time Frame which Used for Zones actions (NULL for Default) ... +// * @param startState: Zones Start State ... +// * @param forceStartedBodyOut: Zones Started Bar's Body State ... +// * @param activeState: Zones Activation State ... +// * @param forceActivatedBodyIn: Zones Activated Bar's Body State ... +// * @param breakState: Zones Breaked State ... +// * @param forceBreakedBodyOut: Zone Breaker Bar's Body State ... +// * @param workState: Zones Worked State ... +// * @param forceWorkedBodyOut: Zones Worked Bar's Body State ... +// * @param applySort: Specify Applying Sorting on Collections ... +// * @param applyFromFilter: Filter Sorted Zones based on Occured Date ... +// * @param applyPlaceFilter: Filter Sorted Zones based on Occured Place ... +// * @param ignoreInside: Ignore Inside Sides of POI(s) Zones in Related to Order Block ... +// * @param applyFromFilterForPOIs: Apply From Filter for Other POI(s) ... +// * +// * @return ( int ) +// */ +// int ExtractOBFVGZones( +// XPOIState &htfState, +// XPOIState &mtfState, +// XPOIState &stfState, +// XOBFVG &dest[], +// // +// ENUM_X_DIRECTION forDir, +// ENUM_TIMEFRAMES forPeriod = NULL, +// // +// // Start ... +// ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, +// bool forceStartedBodyOut = false, +// // +// // Activation ... +// ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, +// bool forceActivatedBodyIn = false, +// // +// // Breaktion ... +// ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, +// bool forceBreakedBodyOut = false, +// // +// // Works ... +// ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, +// bool forceWorkedBodyOut = false, +// // +// bool applySort = true, +// bool applyFromFilter = true, +// bool applyPlaceFilter = true, +// // +// bool ignoreInside = true, +// // +// bool detectInsideOBPOIs = true, +// bool detectInsideFVGPOIs = true, +// bool applyFromFilterForPOIs = true +// // +// ) +// { +// // +// int result = 0; + +// // +// Clean(dest); + +// // +// bool isValid = +// // +// htfState.HasChild() && +// mtfState.HasChild() && +// stfState.HasChild() && +// HasDirection(forDir) +// // +// ; +// if (!isValid) +// { +// return result; +// } + +// // +// // Implement Logic ... + +// // +// int idx = -1; +// int count = 0; +// bool has = false; +// XCFVG *tmpFVGs[]; +// XOBFVG tmpOBFVGs[]; +// XCOrderBlock *tmpOBs[]; +// XCOrderBlock *tmpWorkingOBs[]; +// datetime cTime = TimeCurrent(); +// bool isBullish = IsBullish(forDir); + +// // +// if (isBullish) +// { +// // +// has = htfState.HasBullishOrderBlocks(); +// if (has) +// { +// // +// Copy( +// htfState.bullishOrderBlocks, +// tmpOBs // +// ); + +// // +// has = mtfState.HasBullishFairValueGaps(); +// if (has) +// { +// // +// Copy( +// mtfState.bullishFairValueGaps, +// tmpFVGs // +// ); +// } +// } +// } +// else +// { +// // +// has = htfState.HasBearishOrderBlocks(); +// if (has) +// { +// // +// Copy( +// htfState.bearishOrderBlocks, +// tmpOBs // +// ); + +// // +// has = mtfState.HasBearishFairValueGaps(); +// if (has) +// { +// // +// Copy( +// mtfState.bearishFairValueGaps, +// tmpFVGs // +// ); +// } +// } +// } + +// // +// count = ArraySize(tmpOBs); +// has = IsValidSize(count); +// if (has) +// { +// // +// for (int i = 0; i < count; i++) +// { +// // +// XCOrderBlock *iOB = tmpOBs[i]; + +// // +// // Check Started State ... +// if (startState == XZONE_STATE_PASSED || +// startState == XZONE_STATE_FAILED) +// { +// // +// XOHCL passedBar; +// bool isBodyOut = false; +// bool isStarted = iOB.IsStarted( +// forDir, +// passedBar, +// isBodyOut, +// forPeriod // +// ); + +// // +// bool isPassed = +// startState == XZONE_STATE_FAILED +// ? !isStarted +// : !forceStartedBodyOut +// ? isStarted +// : isStarted && +// isBodyOut; + +// // +// passedBar.Clean(); +// if (!isPassed) +// { +// continue; +// } +// } + +// // +// // Check Activation State ... +// if (activeState == XZONE_STATE_PASSED || +// activeState == XZONE_STATE_FAILED) +// { +// // +// XOHCL passedBar; +// bool isBodyIn = false; +// bool isActivated = iOB.IsActivated( +// forDir, +// passedBar, +// isBodyIn, +// forceStartedBodyOut, +// forPeriod // +// ); + +// // +// bool isPassed = +// activeState == XZONE_STATE_FAILED +// ? !isActivated +// : !forceActivatedBodyIn +// ? isActivated +// : isActivated && +// isBodyIn; + +// // +// passedBar.Clean(); +// if (!isPassed) +// { +// continue; +// } +// } + +// // +// // Check Break State ... +// if (breakState == XZONE_STATE_PASSED || +// breakState == XZONE_STATE_FAILED) +// { +// // +// XOHCL passedBar; +// bool isBodyOut = false; +// bool isBreaked = iOB.IsBreaked( +// forDir, +// passedBar, +// isBodyOut, +// forceStartedBodyOut, +// forPeriod // +// ); + +// // +// bool isPassed = +// breakState == XZONE_STATE_FAILED +// ? !isBreaked +// : !forceBreakedBodyOut +// ? isBreaked +// : isBreaked && +// isBodyOut; + +// // +// passedBar.Clean(); +// if (!isPassed) +// { +// continue; +// } +// } + +// // +// // Check Work State ... +// if (workState == XZONE_STATE_PASSED || +// workState == XZONE_STATE_FAILED) +// { +// // +// bool ignoreActivation = activeState != XZONE_STATE_PASSED; + +// // +// XOHCL passedBar; +// bool isBodyOut = false; +// bool isWorked = iOB.IsWorked( +// forDir, +// passedBar, +// isBodyOut, +// ignoreActivation, +// forceStartedBodyOut, +// forceActivatedBodyIn, +// forPeriod // +// ); + +// // +// bool isPassed = +// workState == XZONE_STATE_FAILED +// ? !isWorked +// : !forceWorkedBodyOut +// ? isWorked +// : isWorked && +// isBodyOut; + +// // +// passedBar.Clean(); +// if (!isPassed) +// { +// continue; +// } +// } + +// // +// has = FindIndex( +// idx, +// iOB, +// tmpWorkingOBs // +// ); +// if (has) +// { +// // +// ZeroMemory(iOB); +// continue; +// } + +// // +// Add( +// iOB, +// tmpWorkingOBs // +// ); +// } +// } + +// // +// // Clean ... +// Clean(tmpOBs); +// has = HasChild(tmpWorkingOBs); +// if (has) +// { +// // +// Clean(tmpOBs); +// Copy( +// tmpWorkingOBs, +// tmpOBs // +// ); + +// // +// Clean(tmpWorkingOBs); +// } + +// // +// // Sorting ... +// if (applySort) +// { +// // +// Clean(tmpWorkingOBs); +// has = HasChild(tmpOBs); +// count = ArraySize(tmpOBs); + +// // +// // Sorting Applied Only when there is more than one item ... +// if (has && count > 1) +// { +// // +// bool hasLast = false; +// XCOrderBlock *last = NULL; +// while (HasChild(tmpOBs)) +// { +// // +// // Extract First Last Item ... +// if (!hasLast) +// { +// // +// idx = +// isBullish +// ? GetLowest(tmpOBs) +// : GetHighest(tmpOBs); +// hasLast = IsValidIndex(idx); +// if (hasLast) +// { +// // +// last = tmpOBs[idx]; +// ArrayRemove( +// tmpOBs, +// idx, +// 1 // +// ); + +// // +// Add( +// last, +// tmpWorkingOBs // +// ); +// } +// } + +// // +// has = false; +// XCOrderBlock *iOB = NULL; +// idx = +// isBullish +// ? GetLowest(tmpOBs) +// : GetHighest(tmpOBs); +// has = IsValidIndex(idx); +// if (has) +// { +// // +// iOB = tmpOBs[idx]; +// ArrayRemove( +// tmpOBs, +// idx, +// 1 // +// ); +// } + +// // +// if (!has) +// { +// break; +// } + +// // +// // Apply From Filter ... +// if (applyFromFilter) +// { +// // +// bool isFromPassed = +// hasLast && +// last.From() < iOB.From(); +// if (!isFromPassed) +// { +// continue; +// } +// } + +// // +// // Apply Place Filter ... +// if (applyPlaceFilter) +// { +// // +// bool isAbove = +// hasLast && +// IsAbove( +// iOB, +// last, +// ignoreInside // +// ); + +// // +// bool isBelow = +// hasLast && +// IsBelow( +// iOB, +// last, +// ignoreInside // +// ); + +// // +// bool isPlacePassed = +// isBullish +// ? isAbove +// : isBelow; +// if (!isPlacePassed) +// { +// continue; +// } +// } + +// // +// last = iOB; +// Add( +// iOB, +// tmpWorkingOBs // +// ); +// } + +// // +// if (hasLast && +// !HasChild(tmpWorkingOBs)) +// { +// // +// Add( +// last, +// tmpWorkingOBs // +// ); +// } +// } +// else +// { +// // +// Copy( +// tmpOBs, +// tmpWorkingOBs // +// ); +// } + +// // +// if (HasChild(tmpWorkingOBs)) +// { +// // +// Copy( +// tmpWorkingOBs, +// tmpOBs // +// ); +// } +// // +// } + +// // +// count = ArraySize(tmpOBs); +// has = IsValidSize(count); + +// // +// // Converts to XOBFVG ... +// if (has) +// { +// // +// for (int i = 0; i < count; i++) +// { +// // +// XOBFVG iOBFVG; + +// // +// iOBFVG.ob = tmpOBs[i]; + +// // +// AddRef( +// iOBFVG, +// tmpOBFVGs // +// ); + +// // +// iOBFVG.Clean(); +// } +// } + +// // +// Clean(dest); +// Clean(tmpOBs); +// Clean(tmpWorkingOBs); + +// // +// // Here we Going to Complete XOBFVGs ... +// has = HasChild(tmpOBFVGs); +// if (has && HasChild(tmpFVGs)) +// { +// // +// count = ArraySize(tmpOBFVGs); +// for (int i = 0; i < count; i++) +// { +// // +// XOBFVG iOBFVG = tmpOBFVGs[i]; + +// // +// // Detecting FVG ... +// XCFVG *tmpWorkingFVGs[]; +// for (int j = 0; j < ArraySize(tmpFVGs); j++) +// { +// // +// XCFVG *jFVG = tmpFVGs[j]; + +// // +// // Check Start Date ... +// bool isFromPassed = jFVG.From() > iOBFVG.ob.From(); +// if (!isFromPassed) +// { +// // +// ZeroMemory(jFVG); +// continue; +// } + +// // +// // Check Place ... + +// // +// bool isAbove = IsAboveDiff( +// jFVG, +// iOBFVG.ob, +// ignoreInside // +// ); + +// // +// bool isBelow = IsBelowDiff( +// jFVG, +// iOBFVG.ob, +// ignoreInside // +// ); + +// // +// bool isInside = IsInsideDiff( +// jFVG, +// iOBFVG.ob, +// false // +// ); + +// // +// bool isPlacePassed = +// isInside || +// (isBullish +// ? isAbove +// : isBelow); +// if (!isPlacePassed) +// { +// // +// ZeroMemory(jFVG); +// continue; +// } + +// // +// Add( +// jFVG, +// tmpWorkingFVGs // +// ); +// } + +// // +// int fvgsCount = ArraySize(tmpWorkingFVGs); +// has = IsValidSize(fvgsCount); +// if (has) +// { +// // +// idx = +// isBullish +// ? GetLowest(tmpWorkingFVGs) +// : GetHighest(tmpWorkingFVGs); + +// // +// if (IsValidIndex(idx)) +// { +// // +// XCFVG *selectedFVG = tmpWorkingFVGs[idx]; + +// // +// iOBFVG.fvg = selectedFVG; + +// // +// bool isExists = FindIndex( +// idx, +// selectedFVG, +// tmpFVGs // +// ); +// if (isExists) +// { +// // +// ArrayRemove( +// tmpFVGs, +// idx, +// 1 // +// ); +// } +// } +// } +// Clean(tmpWorkingFVGs); + +// // +// bool isFVGPassed = iOBFVG.HasFVG(); +// if (!isFVGPassed) +// { +// // +// iOBFVG.Clean(); +// continue; +// } + +// // +// // Validate Model ... +// bool isValid = iOBFVG.IsValid(); +// if (!isValid) +// { +// // +// iOBFVG.Clean(); +// continue; +// } + +// // +// iOBFVG.UpdateTo(cTime); + +// // +// AddRef( +// iOBFVG, +// dest // +// ); + +// // +// iOBFVG.Clean(); +// } + +// // +// Clean(tmpOBFVGs); +// } + +// // +// // Detecting Other POI(s) ... +// has = HasChild(dest); +// bool canDetectPOIs = +// detectInsideOBPOIs || +// detectInsideFVGPOIs; +// if (has && +// canDetectPOIs) +// { +// // +// count = ArraySize(dest); +// for (int i = 0; i < count; i++) +// { +// // +// // Supply Zones ... +// has = stfState.HasSupplyZones(); +// if (has) +// { +// // +// for (int j = 0; j < stfState.CountSupplyZones(); j++) +// { +// // +// bool isInsideOB = IsInsideDiff( +// stfState.supplyZones[j], +// dest[i].ob // +// ); + +// // +// bool isInsideFVG = IsInsideDiff( +// stfState.supplyZones[j], +// dest[i].fvg // +// ); + +// // +// bool isInside = isInsideOB || +// isInsideFVG; +// if (isInside) +// { +// // +// bool isPassed = +// detectInsideOBPOIs +// ? isInsideOB +// : detectInsideFVGPOIs +// ? isInsideFVG +// : false; +// if (isPassed) +// { +// // +// isPassed = +// !applyFromFilterForPOIs +// ? isPassed +// : isInsideOB +// ? stfState.supplyZones[j].From() > dest[i].ob.From() +// : isInsideFVG +// ? stfState.supplyZones[j].From() > dest[i].fvg.From() +// : false; +// } + +// // +// if (isPassed) +// { +// // +// Add( +// stfState.supplyZones[j], +// dest[i].supplyZones // +// ); +// } +// } +// } +// } + +// // +// // Demand Zones ... +// has = stfState.HasDemandZones(); +// if (has) +// { +// // +// for (int j = 0; j < stfState.CountDemandZones(); j++) +// { +// // +// bool isInsideOB = IsInsideDiff( +// stfState.demandZones[j], +// dest[i].ob // +// ); + +// // +// bool isInsideFVG = IsInsideDiff( +// stfState.demandZones[j], +// dest[i].fvg // +// ); + +// // +// bool isInside = isInsideOB || +// isInsideFVG; +// if (isInside) +// { +// // +// bool isPassed = +// detectInsideOBPOIs +// ? isInsideOB +// : detectInsideFVGPOIs +// ? isInsideFVG +// : false; +// if (isPassed) +// { +// // +// isPassed = +// !applyFromFilterForPOIs +// ? isPassed +// : isInsideOB +// ? stfState.demandZones[j].From() > dest[i].ob.From() +// : isInsideFVG +// ? stfState.demandZones[j].From() > dest[i].fvg.From() +// : false; +// } + +// // +// if (isPassed) +// { +// // +// Add( +// stfState.demandZones[j], +// dest[i].demandZones // +// ); +// } +// } +// } +// } + +// // +// // Support Zones ... +// has = stfState.HasSupportZones(); +// if (has) +// { +// // +// for (int j = 0; j < stfState.CountSupportZones(); j++) +// { +// // +// bool isInsideOB = IsInsideDiff( +// stfState.supportZones[j], +// dest[i].ob // +// ); + +// // +// bool isInsideFVG = IsInsideDiff( +// stfState.supportZones[j], +// dest[i].fvg // +// ); + +// // +// bool isInside = isInsideOB || +// isInsideFVG; +// if (isInside) +// { +// // +// bool isPassed = +// detectInsideOBPOIs +// ? isInsideOB +// : detectInsideFVGPOIs +// ? isInsideFVG +// : false; +// if (isPassed) +// { +// // +// isPassed = +// !applyFromFilterForPOIs +// ? isPassed +// : isInsideOB +// ? stfState.supportZones[j].From() > dest[i].ob.From() +// : isInsideFVG +// ? stfState.supportZones[j].From() > dest[i].fvg.From() +// : false; +// } + +// // +// if (isPassed) +// { +// // +// Add( +// stfState.supportZones[j], +// dest[i].supportZones // +// ); +// } +// } +// } +// } + +// // +// // Resistance Zones ... +// has = stfState.HasResistanceZones(); +// if (has) +// { +// // +// for (int j = 0; j < stfState.CountResistanceZones(); j++) +// { +// // +// bool isInsideOB = IsInsideDiff( +// stfState.resistanceZones[j], +// dest[i].ob // +// ); + +// // +// bool isInsideFVG = IsInsideDiff( +// stfState.resistanceZones[j], +// dest[i].fvg // +// ); + +// // +// bool isInside = isInsideOB || +// isInsideFVG; +// if (isInside) +// { +// // +// bool isPassed = +// detectInsideOBPOIs +// ? isInsideOB +// : detectInsideFVGPOIs +// ? isInsideFVG +// : false; +// if (isPassed) +// { +// // +// isPassed = +// !applyFromFilterForPOIs +// ? isPassed +// : isInsideOB +// ? stfState.resistanceZones[j].From() > dest[i].ob.From() +// : isInsideFVG +// ? stfState.resistanceZones[j].From() > dest[i].fvg.From() +// : false; +// } + +// // +// if (isPassed) +// { +// // +// Add( +// stfState.resistanceZones[j], +// dest[i].resistanceZones // +// ); +// } +// } +// } +// } +// } +// } + +// // +// Clean(tmpOBs); +// Clean(tmpFVGs); +// Clean(tmpOBFVGs); + +// // +// result = ArraySize(dest); + +// // +// return result; +// } + +// /** +// * Find Highest Order Block of XOBFVG Collection ... +// * +// * @param source: XOBFVG Collection ... +// * +// * @return ( int ) +// */ +// int GetHighest( +// XOBFVG &source[] // +// ) +// { +// // +// int result = -1; + +// // +// int count = ArraySize(source); +// bool has = IsValidSize(count); +// if (!has) +// { +// return result; +// } + +// // +// XOBFVG item; +// for (int i = 0; i < count; i++) +// { +// // +// XOBFVG iOBFVG = source[i]; + +// // +// bool canSet = +// !item.IsValid() +// ? true +// : item.ob.Upper() < iOBFVG.ob.Upper(); +// if (canSet) +// { +// // +// item = iOBFVG; +// result = i; +// } + +// // +// iOBFVG.Clean(); +// } + +// // +// item.Clean(); + +// // +// return result; +// } + +// /** +// * Find Lowest Order Block of XOBFVG Collection ... +// * +// * @param source: XOBFVG Collection ... +// * +// * @return ( int ) +// */ +// int GetLowest( +// XOBFVG &source[] // +// ) +// { +// // +// int result = -1; + +// // +// int count = ArraySize(source); +// bool has = IsValidSize(count); +// if (!has) +// { +// return result; +// } + +// // +// XOBFVG item; +// for (int i = 0; i < count; i++) +// { +// // +// XOBFVG iOBFVG = source[i]; + +// // +// bool canSet = +// !item.IsValid() +// ? true +// : item.ob.Lower() > iOBFVG.ob.Lower(); +// if (canSet) +// { +// // +// item = iOBFVG; +// result = i; +// } + +// // +// iOBFVG.Clean(); +// } + +// // +// item.Clean(); + +// // +// return result; +// } + +// /** +// * Find Youngest Order Block of XOBFVG Collection ... +// * +// * @param source: XOBFVG Collection ... +// * +// * @return ( int ) +// */ +// int GetYoungest( +// XOBFVG &source[] // +// ) +// { +// // +// int result = -1; + +// // +// int count = ArraySize(source); +// bool has = IsValidSize(count); +// if (!has) +// { +// return result; +// } + +// // +// XOBFVG item; +// for (int i = 0; i < count; i++) +// { +// // +// XOBFVG iOBFVG = source[i]; + +// // +// bool canSet = +// !item.IsValid() +// ? true +// : item.ob.From() < iOBFVG.ob.From(); +// if (canSet) +// { +// // +// item = iOBFVG; +// result = i; +// } + +// // +// iOBFVG.Clean(); +// } + +// // +// item.Clean(); + +// // +// return result; +// } + +// /** +// * Find Oldest Order Block of XOBFVG Collection ... +// * +// * @param source: XOBFVG Collection ... +// * +// * @return ( int ) +// */ +// int GetOldest( +// XOBFVG &source[] // +// ) +// { +// // +// int result = -1; + +// // +// int count = ArraySize(source); +// bool has = IsValidSize(count); +// if (!has) +// { +// return result; +// } + +// // +// XOBFVG item; +// for (int i = 0; i < count; i++) +// { +// // +// XOBFVG iOBFVG = source[i]; + +// // +// bool canSet = +// !item.IsValid() +// ? true +// : item.ob.From() > iOBFVG.ob.From(); +// if (canSet) +// { +// // +// item = iOBFVG; +// result = i; +// } + +// // +// iOBFVG.Clean(); +// } + +// // +// item.Clean(); + +// // +// return result; +// } + +// /** +// * Sort XOBFVG Collection based on OB Place ... +// * +// * @param source: XOBFVG instance Collection ... +// * @param forDir: ENUM_X_DIRECTION member ... +// * @param ignoreInside: Specified Ignoring price inside in Sorting ... +// */ +// void Sort( +// XOBFVG &source[], +// ENUM_X_DIRECTION forDir, +// bool ignoreInside = true // +// ) +// { +// // +// int idx = -1; +// int count = 0; +// bool has = false; + +// // +// has = HasDirection(forDir); +// if (!has) +// { +// return; +// } + +// // +// bool isBullish = IsBullish(forDir); + +// // +// count = ArraySize(source); +// has = IsValidSize(count); +// if (!has) +// { +// return; +// } + +// // +// XOBFVG last; +// XOBFVG tmpItems[]; +// bool hasLast = false; +// while (HasChild(source)) +// { +// // +// if (!hasLast) +// { +// // +// idx = GetOldest(source); +// hasLast = IsValidIndex(idx); +// if (hasLast) +// { +// // +// last = source[idx]; +// ArrayRemove( +// source, +// idx, +// 1 // +// ); + +// // +// AddRef( +// last, +// tmpItems // +// ); +// } + +// // +// count = ArraySize(source); +// has = IsValidSize(count); +// if (!has) +// { +// // +// last.Clean(); +// break; +// } +// } +// if (!hasLast) +// { +// // +// last.Clean(); +// break; +// } + +// // +// XOBFVG item; +// idx = GetOldest(source); +// has = IsValidIndex(idx); +// if (!has) +// { +// // +// item.Clean(); +// last.Clean(); +// break; +// } +// item = source[idx]; +// ArrayRemove( +// source, +// idx, +// 1 // +// ); + +// // +// bool isAbove = IsAbove( +// item.ob, +// last.ob, +// ignoreInside // +// ); + +// // +// bool isBelow = IsBelow( +// item.ob, +// last.ob, +// ignoreInside // +// ); + +// // +// has = +// isBullish +// ? isAbove +// : isBelow; +// if (has) +// { +// // +// AddRef( +// item, +// tmpItems // +// ); + +// // +// last = item; +// hasLast = item.IsValid(); +// } +// } + +// // +// Clean(source); +// Copy( +// tmpItems, +// source // +// ); + +// // +// Clean(tmpItems); +// } + +// // diff --git a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 index 96d16b72..c91b5f6e 100644 --- a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -22,146 +22,11 @@ // // Imports ... #include "../Libraries/x-saherelm.x-poi.lib.mq5" -#include "../Libraries/x-saherelm.xobfvg.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.state.lib.mq5" // // Extensions ... -/** - * Combine a Collection of States into dest ... - * - * @param dest: XPOIState instance ... - * @param source: XPOIState Collection ... - */ -void CombineStates( - XPOIState &dest, - XPOIState &source[] // -) -{ - // - dest.Clean(); - - // - int count = ArraySize(source); - if (!IsValidSize(count)) - { - return; - } - - // - for (int i = 0; i < count; i++) - { - // - XPOIState iState = source[i]; - - // - if (dest.ticksZone == NULL) - { - dest.ticksZone = iState.ticksZone; - } - - // - Copy( - iState.swingHighs, - dest.swingHighs, - false // - ); - - // - Copy( - iState.swingLows, - dest.swingLows, - false // - ); - - // - Copy( - iState.bullishMomentumBars, - dest.bullishMomentumBars, - false // - ); - - // - Copy( - iState.bearishMomentumBars, - dest.bearishMomentumBars, - false // - ); - - // - Copy( - iState.bullishRejectionBars, - dest.bullishRejectionBars, - false // - ); - - // - Copy( - iState.bearishRejectionBars, - dest.bearishRejectionBars, - false // - ); - - // - Copy( - iState.supportZones, - dest.supportZones, - false // - ); - - // - Copy( - iState.resistanceZones, - dest.resistanceZones, - false // - ); - - // - Copy( - iState.supplyZones, - dest.supplyZones, - false // - ); - - // - Copy( - iState.demandZones, - dest.demandZones, - false // - ); - - // - Copy( - iState.bullishOrderBlocks, - dest.bullishOrderBlocks, - false // - ); - - // - Copy( - iState.bearishOrderBlocks, - dest.bearishOrderBlocks, - false // - ); - - // - Copy( - iState.bullishFairValueGaps, - dest.bullishFairValueGaps, - false // - ); - - // - Copy( - iState.bearishFairValueGaps, - dest.bearishFairValueGaps, - false // - ); - - // - } -} - template bool ToZone( T *&source[], @@ -265,7 +130,7 @@ bool ToBox( template int GetOldest( - T *&sourec[] // + T *&source[] // ) { // @@ -732,6 +597,47 @@ bool IsInside( return result; } +template +bool IsInsideOr( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInsideOr( + sourceBox, + destBox // + ); + + // + return result; +} + template bool IsInsideDiff( T *source, @@ -775,6 +681,48 @@ bool IsInsideDiff( return result; } +template +bool IsInsideOrDiff( + T *source, + F *dest, + bool forceSideOut = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInsideOr( + sourceBox, + destBox // + ); + + // + return result; +} + template bool FindIndex( int &index, @@ -1117,6 +1065,50 @@ bool IsBoxInside( return result; } +/** + * Detect source BoX is Inside Dest Box or Have a Side Out on it ... + * + * @param source: XBoxZone instance, source box which checks by dest ... + * @param dest: XBoxZone instance, dest Box which compares source with it ... + * + * @return ( bool ) + */ +bool IsBoxInsideOr( + XBoxZone &source, + XBoxZone &dest // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSame(dest); + if (!result) + { + return result; + } + + // + bool isLowerInside = + source.lower > dest.lower && + source.lower < dest.upper && + (source.upper < dest.upper || + source.upper > dest.upper); + bool isUpperInside = + source.upper < dest.upper && + source.upper > dest.lower && + (source.lower > dest.lower || + source.lower < dest.lower); + result = + isLowerInside || + isUpperInside; + + // + return result; +} + /** * Check Value is Inside Specified Box ... * diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index c9d0680f..cd7f29a4 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -27,9 +27,6 @@ // // Definitions ... -// -// Definitions ... - // // All Available POI(s) ... enum ENUM_XPOIS @@ -76,6 +73,8 @@ enum ENUM_XPOIS // Event Types ... enum ENUM_XPOI_EVENTS { + // + X_POI_EVENT_NONE, // // Trading Days ... X_TRADE_DAY_FIRST_BAR, // Trading Day First Bar ... @@ -3392,7 +3391,8 @@ class XCSupplyZone : public XCBarZone */ bool Init( XOHCL &bar, - int range = 0 // + int range = 0, + bool useRangeAsStart = false // ) { // @@ -3427,7 +3427,10 @@ class XCSupplyZone : public XCBarZone int periodSeconds = PeriodSeconds(bar.period); // - datetime from = (datetime)((int)time - (range * periodSeconds)); + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; datetime to = (datetime)((int)time + (range * periodSeconds)); // @@ -3502,7 +3505,8 @@ class XCDemandZone : public XCBarZone */ bool Init( XOHCL &bar, - int range = 0 // + int range = 0, + bool useRangeAsStart = false // ) { // @@ -3537,7 +3541,10 @@ class XCDemandZone : public XCBarZone int periodSeconds = PeriodSeconds(bar.period); // - datetime from = (datetime)((int)time - (range * periodSeconds)); + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; datetime to = (datetime)((int)time + (range * periodSeconds)); // @@ -5168,633 +5175,6 @@ class XCSession : public XCFromToZone // }; -// -// -// Model Exists Founded POIs ... -struct XPOIState -{ - // - string symbol; - ENUM_TIMEFRAMES period; - datetime time; - - // - XCTicksZone *ticksZone; // Ticks Zone ... - - // - XCSwing *swingHighs[]; // Holds Founded Swing Highs ... - XCSwing *swingLows[]; // Holds Founded Swing Lows ... - XCMomentumBar *bullishMomentumBars[]; // Holds Founded Bullish Momentum Bars ... - XCMomentumBar *bearishMomentumBars[]; // Holds Founded Bearish Momentum Bars ... - XCRejectionBar *bullishRejectionBars[]; // Holds Founded Bullish Rejection Bars ... - XCRejectionBar *bearishRejectionBars[]; // Holds Founded Bearish Rejection Bars ... - XCSupportZone *supportZones[]; // Holds Founded Support Zones ... - XCResistanceZone *resistanceZones[]; // Holds Founded Resistance Zones ... - XCSupplyZone *supplyZones[]; // Holds Founded Supply Zones ... - XCDemandZone *demandZones[]; // Holds Founded Demand Zones ... - XCOrderBlock *bullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ... - XCOrderBlock *bearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ... - XCFVG *bullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ... - XCFVG *bearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ... - - // - // Constructor ... - void XPOIState() - { - Clean(); - } - - // - // Actions ... - - /** - * Cleanup all props ... - */ - void Clean() - { - // - symbol = NULL; - period = NULL; - time = NULL; - - // - ticksZone = NULL; - - // - Clean(swingHighs); - Clean(swingLows); - Clean(bullishMomentumBars); - Clean(bearishMomentumBars); - Clean(bullishRejectionBars); - Clean(bearishRejectionBars); - Clean(supportZones); - Clean(resistanceZones); - Clean(supplyZones); - Clean(demandZones); - Clean(bullishOrderBlocks); - Clean(bearishOrderBlocks); - Clean(bullishFairValueGaps); - Clean(bearishFairValueGaps); - - // - ZeroMemory(this); - } - - /** - * Validate ... - * - * @return ( bool ) - */ - bool IsValid() - { - // - bool result = false; - - // - result = - IsSpecifiedValid(symbol) && - IsSpecifiedValid(period) && - IsSpecifiedValid(time); - - // - return result; - } - - /** - * Check State has Childs or not ... - * - * @return ( bool ) - */ - bool HasChild() - { - // - bool result = false; - - // - result = - // - IsValidSize(CountSwingHighs()) || - IsValidSize(CountSwingLows()) || - IsValidSize(CountBullishMomentumBars()) || - IsValidSize(CountBearishMomentumBars()) || - IsValidSize(CountBullishRejectionBars()) || - IsValidSize(CountBearishRejectionBars()) || - IsValidSize(CountSupportZones()) || - IsValidSize(CountResistanceZones()) || - IsValidSize(CountSupplyZones()) || - IsValidSize(CountDemandZones()) || - IsValidSize(CountBullishOrderBlocks()) || - IsValidSize(CountBearishOrderBlocks()) || - IsValidSize(CountBullishFairValueGaps()) || - IsValidSize(CountBearishFairValueGaps()) - // - ; - - // - return result; - } - - /** - * Fill Dest State by Current State's Data ... - * - * @param dest: XPOIState instance, reference to specified dest ... - * - */ - void Fill(XPOIState &dest) - { - // - if (!IsValid() || - !HasChild()) - { - return; - } - - // - dest.symbol = symbol; - dest.period = period; - dest.time = time; - - // - Copy( - swingHighs, - dest.swingHighs, - false // - ); - Copy( - swingLows, - dest.swingLows, - false // - ); - Copy( - bullishMomentumBars, - dest.bullishMomentumBars, - false // - ); - Copy( - bearishMomentumBars, - dest.bearishMomentumBars, - false // - ); - Copy( - bullishRejectionBars, - dest.bullishRejectionBars, - false // - ); - Copy( - bearishRejectionBars, - dest.bearishRejectionBars, - false // - ); - Copy( - supportZones, - dest.supportZones, - false // - ); - Copy( - resistanceZones, - dest.resistanceZones, - false // - ); - Copy( - supplyZones, - dest.supplyZones, - false // - ); - Copy( - demandZones, - dest.demandZones, - false // - ); - Copy( - bullishOrderBlocks, - dest.bullishOrderBlocks, - false // - ); - Copy( - bearishOrderBlocks, - dest.bearishOrderBlocks, - false // - ); - Copy( - bullishFairValueGaps, - dest.bullishFairValueGaps, - false // - ); - Copy( - bearishFairValueGaps, - dest.bearishFairValueGaps, - false // - ); - - // - } - - /** - * Calculate Liquidity Percent for Specified Direction ... - * - * @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ... - * @param price: Double, Specified Price ... - * - * @return ( double ) - */ - double CalculateLiquidityPercent( - ENUM_X_DIRECTION forDirection, - double price = 0 // - ) - { - // - double result = 0; - - // - if (!IsValid() || - ticksZone == NULL) - { - return result; - } - - // - // Normalize Price for Actions ... - if (price <= 0) - { - // - MqlTick mTick; - bool isTickRetrieved = GetTick( - symbol, - mTick // - ); - if (isTickRetrieved) - { - price = mTick.bid; - } - } - - // - result = ticksZone - .CalculateLiquidityPercent( - forDirection, - price // - ); - - // - return result; - } - - // - // Counters ... - - // - int CountSwingHighs() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(swingHighs); - - // - return result; - } - - // - bool HasSwingHighs() - { - return IsValidSize(CountSwingHighs()); - } - - // - int CountSwingLows() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(swingLows); - - // - return result; - } - - // - bool HasSwingLows() - { - return IsValidSize(CountSwingLows()); - } - - // - int CountBullishMomentumBars() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(bullishMomentumBars); - - // - return result; - } - - // - bool HasBullishMomentumBars() - { - return IsValidSize(CountBullishMomentumBars()); - } - - // - int CountBearishMomentumBars() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(bearishMomentumBars); - - // - return result; - } - - // - bool HasBearishMomentumBars() - { - return IsValidSize(CountBearishMomentumBars()); - } - - // - int CountBullishRejectionBars() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(bullishRejectionBars); - - // - return result; - } - - // - bool HasBullishRejectionBars() - { - return IsValidSize(CountBullishRejectionBars()); - } - - // - int CountBearishRejectionBars() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(bearishRejectionBars); - - // - return result; - } - - // - bool HasBearishRejectionBars() - { - return IsValidSize(CountBearishRejectionBars()); - } - - // - int CountSupportZones() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(supportZones); - - // - return result; - } - - // - bool HasSupportZones() - { - return IsValidSize(CountSupportZones()); - } - - // - int CountResistanceZones() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(resistanceZones); - - // - return result; - } - - // - bool HasResistanceZones() - { - return IsValidSize(CountResistanceZones()); - } - - // - int CountSupplyZones() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(supplyZones); - - // - return result; - } - - // - bool HasSupplyZones() - { - return IsValidSize(CountSupplyZones()); - } - - // - int CountDemandZones() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(demandZones); - - // - return result; - } - - // - bool HasDemandZones() - { - return IsValidSize(CountDemandZones()); - } - - // - int CountBullishOrderBlocks() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(bullishOrderBlocks); - - // - return result; - } - - // - bool HasBullishOrderBlocks() - { - return IsValidSize(CountBullishOrderBlocks()); - } - - // - int CountBearishOrderBlocks() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(bearishOrderBlocks); - - // - return result; - } - - // - bool HasBearishOrderBlocks() - { - return IsValidSize(CountBearishOrderBlocks()); - } - - // - int CountBullishFairValueGaps() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(bullishFairValueGaps); - - // - return result; - } - - // - bool HasBullishFairValueGaps() - { - return IsValidSize(CountBullishFairValueGaps()); - } - - // - int CountBearishFairValueGaps() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = ArraySize(bearishFairValueGaps); - - // - return result; - } - - // - bool HasBearishFairValueGaps() - { - return IsValidSize(CountBearishFairValueGaps()); - } - - // -}; - // // Consolidation Zone ... struct XConsolidationZone diff --git a/Libraries/x-saherelm.x-poi.state.lib.mq5 b/Libraries/x-saherelm.x-poi.state.lib.mq5 new file mode 100644 index 00000000..f44ca40e --- /dev/null +++ b/Libraries/x-saherelm.x-poi.state.lib.mq5 @@ -0,0 +1,3915 @@ + +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XPOILib +// Description: All models related to POIs ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright `023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +enum ENUM_X_OBFVG_FVG_FILTERS +{ + X_OBFVG_FVG_FILTER_NONE, + X_OBFVG_FVG_FILTER_INSIDE_OR, + X_OBFVG_FVG_FILTER_ABOVE_BELOW, +}; + +// +enum ENUM_X_OBFVG_FVG_SELECTION +{ + X_OBFVG_FVG_SELECT_NONE, + X_OBFVG_FVG_SELECT_OLDEST, + X_OBFVG_FVG_SELECT_LOWEST, + X_OBFVG_FVG_SELECT_HIGHEST, + X_OBFVG_FVG_SELECT_YOUNGEST, + X_OBFVG_FVG_SELECT_HIGHEST_LOWEST, + X_OBFVG_FVG_SELECT_LOWEST_HIGHEST, +}; + +// +struct XOBFVGPivot +{ + // + // Props ... + double value; + datetime at; + + // + // Constructor ... + XOBFVGPivot() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + value = 0; + at = NULL; + + // + ZeroMemory(this); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + value > 0 && + IsValid(at); + + // + return result; + } +}; + +// +struct XOBFVG +{ + // + // Props ... + XCFVG *fvg; + XCOrderBlock *ob; + + // + // Constructor ... + XOBFVG() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + ZeroMemory(ob); + ZeroMemory(fvg); + + // + ZeroMemory(this); + } + + // + bool IsValid() + { + return HasOB() && + HasFVG(); + } + + // + bool HasOB() + { + return ob != NULL && + ob.IsValid(); + } + + // + bool HasFVG() + { + return fvg != NULL && + fvg.IsValid(); + } + + // + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + bool isValid = IsValid(); + if (!isValid) + { + return result; + } + + // + result = ob.GetDirection(); + + // + return result; + } + + // + bool IsBullish() + { + return IsBullish(GetDirection()); + } + + // + bool IsBearish() + { + return IsBearish(GetDirection()); + } + + // + int GetSwings( + XOBFVGPivot &pivots[] // + ) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!IsValid()) + { + return result; + } + + // + ENUM_X_DIRECTION forDir = GetDirection(); + bool isBullish = IsBullish(forDir); + + // + XOHCL passedBar; + XOBFVGPivot iPivot; + bool isPassed = false; + double appliedPrice = 0; + bool isBodyState = false; + + // + // Start ... + isPassed = ob.IsStarted( + forDir, + passedBar, + isBodyState // + ); + if (isPassed) + { + // + appliedPrice = + isBullish + ? passedBar.low + : passedBar.high; + + // + iPivot.Clean(); + iPivot.value = appliedPrice; + iPivot.at = passedBar.time; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + // Activation ... + isPassed = ob.IsActivated( + forDir, + passedBar, + isBodyState // + ); + if (isPassed) + { + // + appliedPrice = + isBullish + ? passedBar.low + : passedBar.high; + + // + iPivot.Clean(); + iPivot.value = appliedPrice; + iPivot.at = passedBar.time; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + // Worked ... + isPassed = ob.IsWorked( + forDir, + passedBar, + isBodyState // + ); + if (isPassed) + { + // + appliedPrice = + isBullish + ? passedBar.low + : passedBar.high; + + // + iPivot.Clean(); + iPivot.value = appliedPrice; + iPivot.at = passedBar.time; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + passedBar.Clean(); + + // + result = ArraySize(pivots); + + // + return result; + } + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + + // + has = HasOB(); + if (has) + { + ob.To(value); + } + + // + has = HasFVG(); + if (has) + { + fvg.To(value); + } + } +}; + +// +// +// Model Exists Founded POIs ... +struct XPOIState +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + XCSwing *swings[]; // Holds Founded Swing ... + XCSwing *swingLows[]; // Holds Founded Swing Lows ... + XCSwing *swingHighs[]; // Holds Founded Swing Highs ... + + // + XCMomentumBar *momentumBars[]; // Holds Founded Momentum Bars ... + XCMomentumBar *bullishMomentumBars[]; // Holds Founded Bullish Momentum Bars ... + XCMomentumBar *bearishMomentumBars[]; // Holds Founded Bearish Momentum Bars ... + + // + XCRejectionBar *rejectionBars[]; // Holds Founded Rejection Bars ... + XCRejectionBar *bullishRejectionBars[]; // Holds Founded Bullish Rejection Bars ... + XCRejectionBar *bearishRejectionBars[]; // Holds Founded Bearish Rejection Bars ... + + // + XCSupportZone *supportZones[]; // Holds Founded Support Zones ... + XCResistanceZone *resistanceZones[]; // Holds Founded Resistance Zones ... + + // + XCSupplyZone *supplyZones[]; // Holds Founded Supply Zones ... + XCDemandZone *demandZones[]; // Holds Founded Demand Zones ... + + // + XCOrderBlock *orderBlocks[]; // Holds Founded Order Blocks ... + XCOrderBlock *bullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ... + XCOrderBlock *bearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ... + + // + XCFVG *fairValueGaps[]; // Holds Founded Fair Value Gaps ... + XCFVG *bullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ... + XCFVG *bearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ... + + // + // Constructor ... + void XPOIState() + { + Clean(); + } + + // + // Actions ... + + /** + * Cleanup all props ... + */ + void Clean() + { + // + time = NULL; + symbol = NULL; + period = NULL; + + // + Clean(swings); + Clean(swingLows); + Clean(swingHighs); + + // + Clean(momentumBars); + Clean(bullishMomentumBars); + Clean(bearishMomentumBars); + + // + Clean(rejectionBars); + Clean(bullishRejectionBars); + Clean(bearishRejectionBars); + + // + Clean(supportZones); + Clean(resistanceZones); + + // + Clean(supplyZones); + Clean(demandZones); + + // + Clean(orderBlocks); + Clean(bullishOrderBlocks); + Clean(bearishOrderBlocks); + + // + Clean(fairValueGaps); + Clean(bullishFairValueGaps); + Clean(bearishFairValueGaps); + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + + // + return result; + } + + /** + * Check State has Childs or not ... + * + * @return ( bool ) + */ + bool HasChild() + { + // + bool result = false; + + // + result = + // + IsValidSize(CountSwingHighs()) || + IsValidSize(CountSwingLows()) || + IsValidSize(CountBullishMomentumBars()) || + IsValidSize(CountBearishMomentumBars()) || + IsValidSize(CountBullishRejectionBars()) || + IsValidSize(CountBearishRejectionBars()) || + IsValidSize(CountSupportZones()) || + IsValidSize(CountResistanceZones()) || + IsValidSize(CountSupplyZones()) || + IsValidSize(CountDemandZones()) || + IsValidSize(CountBullishOrderBlocks()) || + IsValidSize(CountBearishOrderBlocks()) || + IsValidSize(CountBullishFairValueGaps()) || + IsValidSize(CountBearishFairValueGaps()) + // + ; + + // + return result; + } + + /** + * Fill Dest State by Current State's Data ... + * + * @param dest: XPOIState instance, reference to specified dest ... + * + */ + void Fill(XPOIState &dest) + { + // + if (!IsValid() || + !HasChild()) + { + return; + } + + // + dest.symbol = symbol; + dest.period = period; + dest.time = time; + + // + Copy( + swingHighs, + dest.swingHighs, + false // + ); + Copy( + swingLows, + dest.swingLows, + false // + ); + Copy( + bullishMomentumBars, + dest.bullishMomentumBars, + false // + ); + Copy( + bearishMomentumBars, + dest.bearishMomentumBars, + false // + ); + Copy( + bullishRejectionBars, + dest.bullishRejectionBars, + false // + ); + Copy( + bearishRejectionBars, + dest.bearishRejectionBars, + false // + ); + Copy( + supportZones, + dest.supportZones, + false // + ); + Copy( + resistanceZones, + dest.resistanceZones, + false // + ); + Copy( + supplyZones, + dest.supplyZones, + false // + ); + Copy( + demandZones, + dest.demandZones, + false // + ); + Copy( + bullishOrderBlocks, + dest.bullishOrderBlocks, + false // + ); + Copy( + bearishOrderBlocks, + dest.bearishOrderBlocks, + false // + ); + Copy( + bullishFairValueGaps, + dest.bullishFairValueGaps, + false // + ); + Copy( + bearishFairValueGaps, + dest.bearishFairValueGaps, + false // + ); + + // + } + + // + // Counters ... + + // + int CountSwings() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(swings); + + // + return result; + } + + // + bool HasSwings() + { + return IsValidSize(CountSwings()); + } + + // + int CountSwingHighs() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(swingHighs); + + // + return result; + } + + // + bool HasSwingHighs() + { + return IsValidSize(CountSwingHighs()); + } + + // + int CountSwingLows() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(swingLows); + + // + return result; + } + + // + bool HasSwingLows() + { + return IsValidSize(CountSwingLows()); + } + + // + int CountMomentumBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(momentumBars); + + // + return result; + } + + // + bool HasMomentumBars() + { + return IsValidSize(CountMomentumBars()); + } + + // + int CountBullishMomentumBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bullishMomentumBars); + + // + return result; + } + + // + bool HasBullishMomentumBars() + { + return IsValidSize(CountBullishMomentumBars()); + } + + // + int CountBearishMomentumBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bearishMomentumBars); + + // + return result; + } + + // + bool HasBearishMomentumBars() + { + return IsValidSize(CountBearishMomentumBars()); + } + + // + int CountRejectionBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(rejectionBars); + + // + return result; + } + + // + bool HasRejectionBars() + { + return IsValidSize(CountRejectionBars()); + } + + // + int CountBullishRejectionBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bullishRejectionBars); + + // + return result; + } + + // + bool HasBullishRejectionBars() + { + return IsValidSize(CountBullishRejectionBars()); + } + + // + int CountBearishRejectionBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bearishRejectionBars); + + // + return result; + } + + // + bool HasBearishRejectionBars() + { + return IsValidSize(CountBearishRejectionBars()); + } + + // + int CountSupportZones() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(supportZones); + + // + return result; + } + + // + bool HasSupportZones() + { + return IsValidSize(CountSupportZones()); + } + + // + int CountResistanceZones() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(resistanceZones); + + // + return result; + } + + // + bool HasResistanceZones() + { + return IsValidSize(CountResistanceZones()); + } + + // + int CountSupplyZones() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(supplyZones); + + // + return result; + } + + // + bool HasSupplyZones() + { + return IsValidSize(CountSupplyZones()); + } + + // + int CountDemandZones() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(demandZones); + + // + return result; + } + + // + bool HasDemandZones() + { + return IsValidSize(CountDemandZones()); + } + + // + int CountOrderBlocks() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(orderBlocks); + + // + return result; + } + + // + bool HasOrderBlocks() + { + return IsValidSize(CountOrderBlocks()); + } + + // + int CountBullishOrderBlocks() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bullishOrderBlocks); + + // + return result; + } + + // + bool HasBullishOrderBlocks() + { + return IsValidSize(CountBullishOrderBlocks()); + } + + // + int CountBearishOrderBlocks() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bearishOrderBlocks); + + // + return result; + } + + // + bool HasBearishOrderBlocks() + { + return IsValidSize(CountBearishOrderBlocks()); + } + + // + int CountFairValueGaps() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(fairValueGaps); + + // + return result; + } + + // + bool HasFairValueGaps() + { + return IsValidSize(CountFairValueGaps()); + } + + // + int CountBullishFairValueGaps() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bullishFairValueGaps); + + // + return result; + } + + // + bool HasBullishFairValueGaps() + { + return IsValidSize(CountBullishFairValueGaps()); + } + + // + int CountBearishFairValueGaps() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bearishFairValueGaps); + + // + return result; + } + + // + bool HasBearishFairValueGaps() + { + return IsValidSize(CountBearishFairValueGaps()); + } + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + + // + has = HasMomentumBars(); + if (has) + { + // + count = CountMomentumBars(); + for (int i = 0; i < count; i++) + { + momentumBars[i].To(value); + } + } + + // + has = HasBullishMomentumBars(); + if (has) + { + // + count = CountBullishMomentumBars(); + for (int i = 0; i < count; i++) + { + bullishMomentumBars[i].To(value); + } + } + + // + has = HasBearishMomentumBars(); + if (has) + { + // + count = CountBearishMomentumBars(); + for (int i = 0; i < count; i++) + { + bearishMomentumBars[i].To(value); + } + } + + // + has = HasRejectionBars(); + if (has) + { + // + count = CountRejectionBars(); + for (int i = 0; i < count; i++) + { + rejectionBars[i].To(value); + } + } + + // + has = HasBullishRejectionBars(); + if (has) + { + // + count = CountBullishRejectionBars(); + for (int i = 0; i < count; i++) + { + bullishRejectionBars[i].To(value); + } + } + + // + has = HasBearishRejectionBars(); + if (has) + { + // + count = CountBearishRejectionBars(); + for (int i = 0; i < count; i++) + { + bearishRejectionBars[i].To(value); + } + } + + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + supportZones[i].To(value); + } + } + + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + resistanceZones[i].To(value); + } + } + + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + supplyZones[i].To(value); + } + } + + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + demandZones[i].To(value); + } + } + + // + has = HasOrderBlocks(); + if (has) + { + // + count = CountOrderBlocks(); + for (int i = 0; i < count; i++) + { + orderBlocks[i].To(value); + } + } + + // + has = HasBullishOrderBlocks(); + if (has) + { + // + count = CountBullishOrderBlocks(); + for (int i = 0; i < count; i++) + { + bullishOrderBlocks[i].To(value); + } + } + + // + has = HasBearishOrderBlocks(); + if (has) + { + // + count = CountBearishOrderBlocks(); + for (int i = 0; i < count; i++) + { + bearishOrderBlocks[i].To(value); + } + } + + // + has = HasFairValueGaps(); + if (has) + { + // + count = CountFairValueGaps(); + for (int i = 0; i < count; i++) + { + fairValueGaps[i].To(value); + } + } + + // + has = HasBullishFairValueGaps(); + if (has) + { + // + count = CountBullishFairValueGaps(); + for (int i = 0; i < count; i++) + { + bullishFairValueGaps[i].To(value); + } + } + + // + has = HasBearishFairValueGaps(); + if (has) + { + // + count = CountBearishFairValueGaps(); + for (int i = 0; i < count; i++) + { + bearishFairValueGaps[i].To(value); + } + } + } + + // + // Filter Zones ... + + // + // Support ... + int FilterSupportZones( + XCSupportZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasSupportZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = supportZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Resistance ... + int FilterResistanceZones( + XCResistanceZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasResistanceZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = resistanceZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Supply ... + int FilterSupplyZones( + XCSupplyZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasSupplyZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = supplyZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Demand ... + int FilterDemandZones( + XCDemandZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasDemandZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = demandZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // OrderBlock ... + int FilterOrderBlocks( + XCOrderBlock *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasOrderBlocks(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + count = CountOrderBlocks(); + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = orderBlocks[i]; + passedDir = iZone.GetDirection(); + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bullish OrderBlock ... + int FilterBullishOrderBlocks( + XCOrderBlock *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBullishOrderBlocks(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountBullishOrderBlocks(); + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = bullishOrderBlocks[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bearish OrderBlock ... + int FilterBearishOrderBlocks( + XCOrderBlock *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBearishOrderBlocks(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountBearishOrderBlocks(); + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = bearishOrderBlocks[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // FairValueGap ... + int FilterFairValueGaps( + XCFVG *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasFairValueGaps(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + count = CountFairValueGaps(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = fairValueGaps[i]; + passedDir = iZone.GetDirection(); + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bullish FairValueGap ... + int FilterBullishFairValueGaps( + XCFVG *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBullishFairValueGaps(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountBullishFairValueGaps(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = bullishFairValueGaps[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bearish FairValueGap ... + int FilterBearishFairValueGaps( + XCFVG *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBearishFairValueGaps(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountBearishFairValueGaps(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = bearishFairValueGaps[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + void Filter( + XPOIState &dest, + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int count = 0; + bool has = false; + + // + dest.Clean(); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasChild(); + if (!has) + { + return; + } + + // + dest = this; + + // + // Support Zones ... + FilterSupportZones( + dest.supportZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Resistance Zones ... + FilterResistanceZones( + dest.resistanceZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Supply Zones ... + FilterSupplyZones( + dest.supplyZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Demand Zones ... + FilterDemandZones( + dest.demandZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // OrderBlocks ... + FilterOrderBlocks( + dest.orderBlocks, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bullish OrderBlocks ... + FilterBullishOrderBlocks( + dest.bullishOrderBlocks, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bearish OrderBlocks ... + FilterBearishOrderBlocks( + dest.bearishOrderBlocks, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // FairValueGaps ... + FilterFairValueGaps( + dest.fairValueGaps, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bullish FairValueGaps ... + FilterBullishFairValueGaps( + dest.bullishFairValueGaps, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bearish FairValueGaps ... + FilterBearishFairValueGaps( + dest.bearishFairValueGaps, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + } + + // +}; + +// +int ExtractOBFVGs( + XOBFVG &dest[], + XPOIState &obState, + XPOIState &fvgState, + // + ENUM_X_OBFVG_FVG_FILTERS filterFVGs = X_OBFVG_FVG_FILTER_INSIDE_OR, + ENUM_X_OBFVG_FVG_SELECTION selectFVG = X_OBFVG_FVG_SELECT_HIGHEST_LOWEST, + // + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_IGNORED, + bool forceWorkedBodyOut = false // +) +{ + // + int result = 0; + + // + bool has = false; + + // + Clean(dest); + + // + has = obState.IsValid() && + fvgState.IsValid() && + obState.HasChild() && + fvgState.HasChild() && + selectFVG != X_OBFVG_FVG_SELECT_NONE && + filterFVGs != X_OBFVG_FVG_FILTER_NONE; + if (!has) + { + return result; + } + + // + XCOrderBlock *obs[]; + int obsCount = obState.FilterOrderBlocks( + obs, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + has = IsValidSize(obsCount); + if (!has) + { + return result; + } + + // + XCFVG *fvgs[]; + int fvgsCount = fvgState.FilterFairValueGaps( + fvgs, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + has = IsValidSize(fvgsCount); + if (!has) + { + return result; + } + + // + for (int i = 0; i < obsCount; i++) + { + // + XCOrderBlock *iOB = obs[i]; + XCFVG *iFVG = NULL; + + // + ENUM_X_DIRECTION iOBDir = iOB.GetDirection(); + bool isIOBBullish = IsBullish(iOBDir); + + // + XCFVG *iFVGs[]; + for (int j = 0; j < fvgsCount; j++) + { + // + XCFVG *jFVG = fvgs[j]; + ENUM_X_DIRECTION jFVGDir = jFVG.GetDirection(); + + // + bool isSameDir = iOBDir == jFVGDir; + bool isFromPassed = jFVG.From() >= iOB.From(); + bool isInsideOr = IsInsideOrDiff( + jFVG, + iOB // + ); + bool isAbove = IsAboveDiff( + jFVG, + iOB, + true // + ); + bool isBelow = IsBelowDiff( + jFVG, + iOB, + true // + ); + + // + bool isFilterPassed = + filterFVGs == X_OBFVG_FVG_FILTER_ABOVE_BELOW + ? isIOBBullish + ? isAbove + : isBelow + : filterFVGs == X_OBFVG_FVG_FILTER_INSIDE_OR + ? isInsideOr + : false; + + // + has = + isSameDir && + isFromPassed && + isFilterPassed; + if (has) + { + // + Add( + jFVG, + iFVGs // + ); + } + } + has = HasChild(iFVGs); + if (!has) + { + continue; + } + + // + int idx = -1; + idx = selectFVG == X_OBFVG_FVG_SELECT_OLDEST + ? GetOldest(iFVGs) + : selectFVG == X_OBFVG_FVG_SELECT_YOUNGEST + ? GetYoungest(iFVGs) + : selectFVG == X_OBFVG_FVG_SELECT_HIGHEST_LOWEST + ? isIOBBullish + ? GetHighest(iFVGs) + : GetLowest(iFVGs) + : selectFVG == X_OBFVG_FVG_SELECT_LOWEST_HIGHEST + ? isIOBBullish + ? GetLowest(iFVGs) + : GetHighest(iFVGs) + : selectFVG == X_OBFVG_FVG_SELECT_LOWEST + ? GetLowest(iFVGs) + : selectFVG == X_OBFVG_FVG_SELECT_HIGHEST + ? GetHighest(iFVGs) + : -1; + + // + has = IsValidIndex(idx); + if (!has) + { + continue; + } + + // + iFVG = iFVGs[idx]; + Clean(iFVGs); + + // + XOBFVG iOBFVG; + iOBFVG.ob = iOB; + iOBFVG.fvg = iFVG; + + // + has = iOBFVG.IsValid(); + if (!has) + { + // + iOBFVG.Clean(); + continue; + } + + // + AddRef( + iOBFVG, + dest // + ); + + // + iOBFVG.Clean(); + } + + // + result = ArraySize(dest); + + // + return result; +} + +void SpecifiedUpdateTo( + XOBFVG &items[], + datetime value = NULL // +) +{ + // + value = NormalizeTime(value); + + // + int count = ArraySize(items); + bool has = HasChild(items); + if (!has) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + items[i].UpdateTo(value); + } +} + +// diff --git a/Libraries/x-saherelm.x-trade.lib.mq5 b/Libraries/x-saherelm.x-trade.lib.mq5 index 666d803a..076d446c 100644 --- a/Libraries/x-saherelm.x-trade.lib.mq5 +++ b/Libraries/x-saherelm.x-trade.lib.mq5 @@ -1118,7 +1118,7 @@ struct XSignal // // Traget ... - double target; // Force Risk Free On Target ... + double targets[]; // Force Risk Free On Targets ... bool ignoreEAVolume; // Ignore EA Volume ... // @@ -1679,7 +1679,7 @@ struct XSignal conditions = NULL; // - target = 0; + Clean(targets); ignoreEAVolume = false; // diff --git a/Libraries/x-saherelm.xobfvg.lib.mq5 b/Libraries/x-saherelm.xobfvg.lib.mq5 deleted file mode 100644 index a0fca88a..00000000 --- a/Libraries/x-saherelm.xobfvg.lib.mq5 +++ /dev/null @@ -1,1898 +0,0 @@ -/////////////////////////////////////////////////////// -// -// SaherElm IT Center MQL5 Seriallize Library -// --------------------------------------- -// Name: XOBFVGLib -// Description: All models related to POIs ... -// -// -// Maintainer: -// ------------ -// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) -// -////////////////////////////////////////////////////// -// -// Global Properties ... -#property library -#property copyright "Copyright `023, SaherElm IT Center" -#property link "https://www.saherelm.ir" -#property version "1.00" -#property strict - -// -// Imports ... -#include "../Libraries/x-saherelm.x-poi.lib.mq5" -#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" - -// -struct XOBFVGPivot -{ - // - // Props ... - double value; - datetime at; - - // - // Constructor ... - XOBFVGPivot() - { - Clean(); - } - - // - // Tools ... - - // - void Clean() - { - // - value = 0; - at = NULL; - - // - ZeroMemory(this); - } - - // - bool IsValid() - { - // - bool result = false; - - // - result = - value > 0 && - IsValid(at); - - // - return result; - } -}; - -// -struct XOBFVG -{ - // - // Props ... - XCFVG *fvg; - XCOrderBlock *ob; - - // - XCSupplyZone *supplyZones[]; - XCDemandZone *demandZones[]; - - // - XCSupportZone *supportZones[]; - XCResistanceZone *resistanceZones[]; - - // - // Constructor ... - XOBFVG() - { - Clean(); - } - - // - // Tools ... - - // - void Clean() - { - // - ZeroMemory(ob); - ZeroMemory(fvg); - - // - Clean(supplyZones); - Clean(demandZones); - Clean(supportZones); - Clean(resistanceZones); - - // - ZeroMemory(this); - } - - // - bool IsValid() - { - return HasOB() && - HasFVG(); - } - - // - bool HasOB() - { - return ob != NULL && - ob.IsValid(); - } - - // - bool HasFVG() - { - return fvg != NULL && - fvg.IsValid(); - } - - // - bool HasSupplyZones() - { - return HasChild(supplyZones); - } - - // - int CountSupplyZones() - { - return ArraySize(supplyZones); - } - - // - bool HasDemandZones() - { - return HasChild(demandZones); - } - - // - int CountDemandZones() - { - return ArraySize(demandZones); - } - - // - bool HasSupportZones() - { - return HasChild(supportZones); - } - - // - int CountSupportZones() - { - return ArraySize(supportZones); - } - - // - bool HasResistanceZones() - { - return HasChild(resistanceZones); - } - - // - int CountResistanceZones() - { - return ArraySize(resistanceZones); - } - - // - ENUM_X_DIRECTION GetDirection() - { - // - ENUM_X_DIRECTION result = X_DIRECTION_NONE; - - // - bool isValid = IsValid(); - if (!isValid) - { - return result; - } - - // - result = ob.GetDirection(); - - // - return result; - } - - // - bool IsBullish() - { - return IsBullish(GetDirection()); - } - - // - bool IsBearish() - { - return IsBearish(GetDirection()); - } - - // - int GetSwings( - XOBFVGPivot &pivots[] // - ) - { - // - int result = 0; - - // - Clean(pivots); - - // - if (!IsValid()) - { - return result; - } - - // - ENUM_X_DIRECTION forDir = GetDirection(); - bool isBullish = IsBullish(forDir); - - // - XOHCL passedBar; - XOBFVGPivot iPivot; - bool isPassed = false; - double appliedPrice = 0; - bool isBodyState = false; - - // - // Start ... - isPassed = ob.IsStarted( - forDir, - passedBar, - isBodyState // - ); - if (isPassed) - { - // - appliedPrice = - isBullish - ? passedBar.low - : passedBar.high; - - // - iPivot.Clean(); - iPivot.value = appliedPrice; - iPivot.at = passedBar.time; - - // - AddRef( - iPivot, - pivots // - ); - - // - iPivot.Clean(); - } - - // - // Activation ... - isPassed = ob.IsActivated( - forDir, - passedBar, - isBodyState // - ); - if (isPassed) - { - // - appliedPrice = - isBullish - ? passedBar.low - : passedBar.high; - - // - iPivot.Clean(); - iPivot.value = appliedPrice; - iPivot.at = passedBar.time; - - // - AddRef( - iPivot, - pivots // - ); - - // - iPivot.Clean(); - } - - // - // Worked ... - isPassed = ob.IsWorked( - forDir, - passedBar, - isBodyState // - ); - if (isPassed) - { - // - appliedPrice = - isBullish - ? passedBar.low - : passedBar.high; - - // - iPivot.Clean(); - iPivot.value = appliedPrice; - iPivot.at = passedBar.time; - - // - AddRef( - iPivot, - pivots // - ); - - // - iPivot.Clean(); - } - - // - passedBar.Clean(); - - // - result = ArraySize(pivots); - - // - return result; - } - - // - void UpdateZones( - XPOIState &state // - ) - { - // - Clean(supplyZones); - Clean(demandZones); - Clean(supportZones); - Clean(resistanceZones); - - // - bool isValid = - IsValid() && - state.HasChild(); - if (!isValid) - { - return; - } - - // - int count = 0; - bool has = false; - bool isPassed = false; - - // - // Supply Zones ... - has = state.HasSupplyZones(); - if (has) - { - // - count = state.CountSupplyZones(); - for (int i = 0; i < count; i++) - { - // - XCSupplyZone *iZone = state.supplyZones[i]; - - // - isPassed = iZone.From() > ob.From(); - if (!isPassed) - { - // - ZeroMemory(iZone); - continue; - } - - // - isPassed = IsInsideDiff( - iZone, - ob // - ); - if (!isPassed) - { - // - ZeroMemory(iZone); - continue; - } - - // - Add( - iZone, - supplyZones // - ); - } - } - - // - // Demand Zones ... - has = state.HasDemandZones(); - if (has) - { - // - count = state.CountDemandZones(); - for (int i = 0; i < count; i++) - { - // - XCDemandZone *iZone = state.demandZones[i]; - - // - isPassed = iZone.From() > ob.From(); - if (!isPassed) - { - // - ZeroMemory(iZone); - continue; - } - - // - isPassed = IsInsideDiff( - iZone, - ob // - ); - if (!isPassed) - { - // - ZeroMemory(iZone); - continue; - } - - // - Add( - iZone, - demandZones // - ); - } - } - - // - // Support Zones ... - has = state.HasSupportZones(); - if (has) - { - // - count = state.CountSupportZones(); - for (int i = 0; i < count; i++) - { - // - XCSupportZone *iZone = state.supportZones[i]; - - // - isPassed = iZone.From() > ob.From(); - if (!isPassed) - { - // - ZeroMemory(iZone); - continue; - } - - // - isPassed = IsInsideDiff( - iZone, - ob // - ); - if (!isPassed) - { - // - ZeroMemory(iZone); - continue; - } - - // - Add( - iZone, - supportZones // - ); - } - } - - // - // Resistance Zones ... - has = state.HasResistanceZones(); - if (has) - { - // - count = state.CountResistanceZones(); - for (int i = 0; i < count; i++) - { - // - XCResistanceZone *iZone = state.resistanceZones[i]; - - // - isPassed = iZone.From() > ob.From(); - if (!isPassed) - { - // - ZeroMemory(iZone); - continue; - } - - // - isPassed = IsInsideDiff( - iZone, - ob // - ); - if (!isPassed) - { - // - ZeroMemory(iZone); - continue; - } - - // - Add( - iZone, - resistanceZones // - ); - } - } - } - - // - void UpdateTo(datetime value = NULL) - { - // - value = NormalizeTime(value); - - // - int count = 0; - bool has = false; - - // - has = HasOB(); - if (has) - { - ob.To(value); - } - - // - has = HasFVG(); - if (has) - { - fvg.To(value); - } - - // - // Supply Zones ... - has = HasSupplyZones(); - if (has) - { - // - count = CountSupplyZones(); - for (int i = 0; i < count; i++) - { - supplyZones[i].To(value); - } - } - - // - // Demand Zones ... - has = HasDemandZones(); - if (has) - { - // - count = CountDemandZones(); - for (int i = 0; i < count; i++) - { - demandZones[i].To(value); - } - } - - // - // Support Zones ... - has = HasSupportZones(); - if (has) - { - // - count = CountSupportZones(); - for (int i = 0; i < count; i++) - { - supportZones[i].To(value); - } - } - - // - // Resistance Zones ... - has = HasResistanceZones(); - if (has) - { - // - count = CountResistanceZones(); - for (int i = 0; i < count; i++) - { - resistanceZones[i].To(value); - } - } - } -}; - -// -// -// - -/** - * Extract XOBFVG Collection of Market ... - * - * @param htfState: Higher Time Frame POI State (Used For Detecting Order Blocks) ... - * @param mtfState: Medium Time Frame POI State (Used For Detecting Fair Value Gaps) ... - * @param stfState: Short Time Frame POI State (Used For Detecting Other POI(s)) ... - * @param dest: Result Collection ... - * @param forDir: Market Direction for Detecting POI(s) ... - * @param forPeriod: Time Frame which Used for Zones actions (NULL for Default) ... - * @param startState: Zones Start State ... - * @param forceStartedBodyOut: Zones Started Bar's Body State ... - * @param activeState: Zones Activation State ... - * @param forceActivatedBodyIn: Zones Activated Bar's Body State ... - * @param breakState: Zones Breaked State ... - * @param forceBreakedBodyOut: Zone Breaker Bar's Body State ... - * @param workState: Zones Worked State ... - * @param forceWorkedBodyOut: Zones Worked Bar's Body State ... - * @param applySort: Specify Applying Sorting on Collections ... - * @param applyFromFilter: Filter Sorted Zones based on Occured Date ... - * @param applyPlaceFilter: Filter Sorted Zones based on Occured Place ... - * @param ignoreInside: Ignore Inside Sides of POI(s) Zones in Related to Order Block ... - * @param applyFromFilterForPOIs: Apply From Filter for Other POI(s) ... - * - * @return ( int ) - */ -int ExtractOBFVGZones( - XPOIState &htfState, - XPOIState &mtfState, - XPOIState &stfState, - XOBFVG &dest[], - // - ENUM_X_DIRECTION forDir, - ENUM_TIMEFRAMES forPeriod = NULL, - // - // Start ... - ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, - bool forceStartedBodyOut = false, - // - // Activation ... - ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, - bool forceActivatedBodyIn = false, - // - // Breaktion ... - ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, - bool forceBreakedBodyOut = false, - // - // Works ... - ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, - bool forceWorkedBodyOut = false, - // - bool applySort = true, - bool applyFromFilter = true, - bool applyPlaceFilter = true, - // - bool ignoreInside = true, - // - bool detectInsideOBPOIs = true, - bool detectInsideFVGPOIs = true, - bool applyFromFilterForPOIs = true - // -) -{ - // - int result = 0; - - // - Clean(dest); - - // - bool isValid = - // - htfState.HasChild() && - mtfState.HasChild() && - stfState.HasChild() && - HasDirection(forDir) - // - ; - if (!isValid) - { - return result; - } - - // - // Implement Logic ... - - // - int idx = -1; - int count = 0; - bool has = false; - XCFVG *tmpFVGs[]; - XOBFVG tmpOBFVGs[]; - XCOrderBlock *tmpOBs[]; - XCOrderBlock *tmpWorkingOBs[]; - datetime cTime = TimeCurrent(); - bool isBullish = IsBullish(forDir); - - // - if (isBullish) - { - // - has = htfState.HasBullishOrderBlocks(); - if (has) - { - // - Copy( - htfState.bullishOrderBlocks, - tmpOBs // - ); - - // - has = mtfState.HasBullishFairValueGaps(); - if (has) - { - // - Copy( - mtfState.bullishFairValueGaps, - tmpFVGs // - ); - } - } - } - else - { - // - has = htfState.HasBearishOrderBlocks(); - if (has) - { - // - Copy( - htfState.bearishOrderBlocks, - tmpOBs // - ); - - // - has = mtfState.HasBearishFairValueGaps(); - if (has) - { - // - Copy( - mtfState.bearishFairValueGaps, - tmpFVGs // - ); - } - } - } - - // - count = ArraySize(tmpOBs); - has = IsValidSize(count); - if (has) - { - // - for (int i = 0; i < count; i++) - { - // - XCOrderBlock *iOB = tmpOBs[i]; - - // - // Check Started State ... - if (startState == XZONE_STATE_PASSED || - startState == XZONE_STATE_FAILED) - { - // - XOHCL passedBar; - bool isBodyOut = false; - bool isStarted = iOB.IsStarted( - forDir, - passedBar, - isBodyOut, - forPeriod // - ); - - // - bool isPassed = - startState == XZONE_STATE_FAILED - ? !isStarted - : !forceStartedBodyOut - ? isStarted - : isStarted && - isBodyOut; - - // - passedBar.Clean(); - if (!isPassed) - { - continue; - } - } - - // - // Check Activation State ... - if (activeState == XZONE_STATE_PASSED || - activeState == XZONE_STATE_FAILED) - { - // - XOHCL passedBar; - bool isBodyIn = false; - bool isActivated = iOB.IsActivated( - forDir, - passedBar, - isBodyIn, - forceStartedBodyOut, - forPeriod // - ); - - // - bool isPassed = - activeState == XZONE_STATE_FAILED - ? !isActivated - : !forceActivatedBodyIn - ? isActivated - : isActivated && - isBodyIn; - - // - passedBar.Clean(); - if (!isPassed) - { - continue; - } - } - - // - // Check Break State ... - if (breakState == XZONE_STATE_PASSED || - breakState == XZONE_STATE_FAILED) - { - // - XOHCL passedBar; - bool isBodyOut = false; - bool isBreaked = iOB.IsBreaked( - forDir, - passedBar, - isBodyOut, - forceStartedBodyOut, - forPeriod // - ); - - // - bool isPassed = - breakState == XZONE_STATE_FAILED - ? !isBreaked - : !forceBreakedBodyOut - ? isBreaked - : isBreaked && - isBodyOut; - - // - passedBar.Clean(); - if (!isPassed) - { - continue; - } - } - - // - // Check Work State ... - if (workState == XZONE_STATE_PASSED || - workState == XZONE_STATE_FAILED) - { - // - bool ignoreActivation = activeState != XZONE_STATE_PASSED; - - // - XOHCL passedBar; - bool isBodyOut = false; - bool isWorked = iOB.IsWorked( - forDir, - passedBar, - isBodyOut, - ignoreActivation, - forceStartedBodyOut, - forceActivatedBodyIn, - forPeriod // - ); - - // - bool isPassed = - workState == XZONE_STATE_FAILED - ? !isWorked - : !forceWorkedBodyOut - ? isWorked - : isWorked && - isBodyOut; - - // - passedBar.Clean(); - if (!isPassed) - { - continue; - } - } - - // - has = FindIndex( - idx, - iOB, - tmpWorkingOBs // - ); - if (has) - { - // - ZeroMemory(iOB); - continue; - } - - // - Add( - iOB, - tmpWorkingOBs // - ); - } - } - - // - // Clean ... - Clean(tmpOBs); - has = HasChild(tmpWorkingOBs); - if (has) - { - // - Clean(tmpOBs); - Copy( - tmpWorkingOBs, - tmpOBs // - ); - - // - Clean(tmpWorkingOBs); - } - - // - // Sorting ... - if (applySort) - { - // - Clean(tmpWorkingOBs); - has = HasChild(tmpOBs); - count = ArraySize(tmpOBs); - - // - // Sorting Applied Only when there is more than one item ... - if (has && count > 1) - { - // - bool hasLast = false; - XCOrderBlock *last = NULL; - while (HasChild(tmpOBs)) - { - // - // Extract First Last Item ... - if (!hasLast) - { - // - idx = - isBullish - ? GetLowest(tmpOBs) - : GetHighest(tmpOBs); - hasLast = IsValidIndex(idx); - if (hasLast) - { - // - last = tmpOBs[idx]; - ArrayRemove( - tmpOBs, - idx, - 1 // - ); - - // - Add( - last, - tmpWorkingOBs // - ); - } - } - - // - has = false; - XCOrderBlock *iOB = NULL; - idx = - isBullish - ? GetLowest(tmpOBs) - : GetHighest(tmpOBs); - has = IsValidIndex(idx); - if (has) - { - // - iOB = tmpOBs[idx]; - ArrayRemove( - tmpOBs, - idx, - 1 // - ); - } - - // - if (!has) - { - break; - } - - // - // Apply From Filter ... - if (applyFromFilter) - { - // - bool isFromPassed = - hasLast && - last.From() < iOB.From(); - if (!isFromPassed) - { - continue; - } - } - - // - // Apply Place Filter ... - if (applyPlaceFilter) - { - // - bool isAbove = - hasLast && - IsAbove( - iOB, - last, - ignoreInside // - ); - - // - bool isBelow = - hasLast && - IsBelow( - iOB, - last, - ignoreInside // - ); - - // - bool isPlacePassed = - isBullish - ? isAbove - : isBelow; - if (!isPlacePassed) - { - continue; - } - } - - // - last = iOB; - Add( - iOB, - tmpWorkingOBs // - ); - } - - // - if (hasLast && - !HasChild(tmpWorkingOBs)) - { - // - Add( - last, - tmpWorkingOBs // - ); - } - } - else - { - // - Copy( - tmpOBs, - tmpWorkingOBs // - ); - } - - // - if (HasChild(tmpWorkingOBs)) - { - // - Copy( - tmpWorkingOBs, - tmpOBs // - ); - } - // - } - - // - count = ArraySize(tmpOBs); - has = IsValidSize(count); - - // - // Converts to XOBFVG ... - if (has) - { - // - for (int i = 0; i < count; i++) - { - // - XOBFVG iOBFVG; - - // - iOBFVG.ob = tmpOBs[i]; - - // - AddRef( - iOBFVG, - tmpOBFVGs // - ); - - // - iOBFVG.Clean(); - } - } - - // - Clean(dest); - Clean(tmpOBs); - Clean(tmpWorkingOBs); - - // - // Here we Going to Complete XOBFVGs ... - has = HasChild(tmpOBFVGs); - if (has && HasChild(tmpFVGs)) - { - // - count = ArraySize(tmpOBFVGs); - for (int i = 0; i < count; i++) - { - // - XOBFVG iOBFVG = tmpOBFVGs[i]; - - // - // Detecting FVG ... - XCFVG *tmpWorkingFVGs[]; - for (int j = 0; j < ArraySize(tmpFVGs); j++) - { - // - XCFVG *jFVG = tmpFVGs[j]; - - // - // Check Start Date ... - bool isFromPassed = jFVG.From() > iOBFVG.ob.From(); - if (!isFromPassed) - { - // - ZeroMemory(jFVG); - continue; - } - - // - // Check Place ... - - // - bool isAbove = IsAboveDiff( - jFVG, - iOBFVG.ob, - ignoreInside // - ); - - // - bool isBelow = IsBelowDiff( - jFVG, - iOBFVG.ob, - ignoreInside // - ); - - // - bool isInside = IsInsideDiff( - jFVG, - iOBFVG.ob, - false // - ); - - // - bool isPlacePassed = - isInside || - (isBullish - ? isAbove - : isBelow); - if (!isPlacePassed) - { - // - ZeroMemory(jFVG); - continue; - } - - // - Add( - jFVG, - tmpWorkingFVGs // - ); - } - - // - int fvgsCount = ArraySize(tmpWorkingFVGs); - has = IsValidSize(fvgsCount); - if (has) - { - // - idx = - isBullish - ? GetLowest(tmpWorkingFVGs) - : GetHighest(tmpWorkingFVGs); - - // - if (IsValidIndex(idx)) - { - // - XCFVG *selectedFVG = tmpWorkingFVGs[idx]; - - // - iOBFVG.fvg = selectedFVG; - - // - bool isExists = FindIndex( - idx, - selectedFVG, - tmpFVGs // - ); - if (isExists) - { - // - ArrayRemove( - tmpFVGs, - idx, - 1 // - ); - } - } - } - Clean(tmpWorkingFVGs); - - // - bool isFVGPassed = iOBFVG.HasFVG(); - if (!isFVGPassed) - { - // - iOBFVG.Clean(); - continue; - } - - // - // Validate Model ... - bool isValid = iOBFVG.IsValid(); - if (!isValid) - { - // - iOBFVG.Clean(); - continue; - } - - // - iOBFVG.UpdateTo(cTime); - - // - AddRef( - iOBFVG, - dest // - ); - - // - iOBFVG.Clean(); - } - - // - Clean(tmpOBFVGs); - } - - // - // Detecting Other POI(s) ... - has = HasChild(dest); - bool canDetectPOIs = - detectInsideOBPOIs || - detectInsideFVGPOIs; - if (has && - canDetectPOIs) - { - // - count = ArraySize(dest); - for (int i = 0; i < count; i++) - { - // - // Supply Zones ... - has = stfState.HasSupplyZones(); - if (has) - { - // - for (int j = 0; j < stfState.CountSupplyZones(); j++) - { - // - bool isInsideOB = IsInsideDiff( - stfState.supplyZones[j], - dest[i].ob // - ); - - // - bool isInsideFVG = IsInsideDiff( - stfState.supplyZones[j], - dest[i].fvg // - ); - - // - bool isInside = isInsideOB || - isInsideFVG; - if (isInside) - { - // - bool isPassed = - detectInsideOBPOIs - ? isInsideOB - : detectInsideFVGPOIs - ? isInsideFVG - : false; - if (isPassed) - { - // - isPassed = - !applyFromFilterForPOIs - ? isPassed - : isInsideOB - ? stfState.supplyZones[j].From() > dest[i].ob.From() - : isInsideFVG - ? stfState.supplyZones[j].From() > dest[i].fvg.From() - : false; - } - - // - if (isPassed) - { - // - Add( - stfState.supplyZones[j], - dest[i].supplyZones // - ); - } - } - } - } - - // - // Demand Zones ... - has = stfState.HasDemandZones(); - if (has) - { - // - for (int j = 0; j < stfState.CountDemandZones(); j++) - { - // - bool isInsideOB = IsInsideDiff( - stfState.demandZones[j], - dest[i].ob // - ); - - // - bool isInsideFVG = IsInsideDiff( - stfState.demandZones[j], - dest[i].fvg // - ); - - // - bool isInside = isInsideOB || - isInsideFVG; - if (isInside) - { - // - bool isPassed = - detectInsideOBPOIs - ? isInsideOB - : detectInsideFVGPOIs - ? isInsideFVG - : false; - if (isPassed) - { - // - isPassed = - !applyFromFilterForPOIs - ? isPassed - : isInsideOB - ? stfState.demandZones[j].From() > dest[i].ob.From() - : isInsideFVG - ? stfState.demandZones[j].From() > dest[i].fvg.From() - : false; - } - - // - if (isPassed) - { - // - Add( - stfState.demandZones[j], - dest[i].demandZones // - ); - } - } - } - } - - // - // Support Zones ... - has = stfState.HasSupportZones(); - if (has) - { - // - for (int j = 0; j < stfState.CountSupportZones(); j++) - { - // - bool isInsideOB = IsInsideDiff( - stfState.supportZones[j], - dest[i].ob // - ); - - // - bool isInsideFVG = IsInsideDiff( - stfState.supportZones[j], - dest[i].fvg // - ); - - // - bool isInside = isInsideOB || - isInsideFVG; - if (isInside) - { - // - bool isPassed = - detectInsideOBPOIs - ? isInsideOB - : detectInsideFVGPOIs - ? isInsideFVG - : false; - if (isPassed) - { - // - isPassed = - !applyFromFilterForPOIs - ? isPassed - : isInsideOB - ? stfState.supportZones[j].From() > dest[i].ob.From() - : isInsideFVG - ? stfState.supportZones[j].From() > dest[i].fvg.From() - : false; - } - - // - if (isPassed) - { - // - Add( - stfState.supportZones[j], - dest[i].supportZones // - ); - } - } - } - } - - // - // Resistance Zones ... - has = stfState.HasResistanceZones(); - if (has) - { - // - for (int j = 0; j < stfState.CountResistanceZones(); j++) - { - // - bool isInsideOB = IsInsideDiff( - stfState.resistanceZones[j], - dest[i].ob // - ); - - // - bool isInsideFVG = IsInsideDiff( - stfState.resistanceZones[j], - dest[i].fvg // - ); - - // - bool isInside = isInsideOB || - isInsideFVG; - if (isInside) - { - // - bool isPassed = - detectInsideOBPOIs - ? isInsideOB - : detectInsideFVGPOIs - ? isInsideFVG - : false; - if (isPassed) - { - // - isPassed = - !applyFromFilterForPOIs - ? isPassed - : isInsideOB - ? stfState.resistanceZones[j].From() > dest[i].ob.From() - : isInsideFVG - ? stfState.resistanceZones[j].From() > dest[i].fvg.From() - : false; - } - - // - if (isPassed) - { - // - Add( - stfState.resistanceZones[j], - dest[i].resistanceZones // - ); - } - } - } - } - } - } - - // - Clean(tmpOBs); - Clean(tmpFVGs); - Clean(tmpOBFVGs); - - // - result = ArraySize(dest); - - // - return result; -} - -/** - * Find Highest Order Block of XOBFVG Collection ... - * - * @param source: XOBFVG Collection ... - * - * @return ( int ) - */ -int GetHighest( - XOBFVG &source[] // -) -{ - // - int result = -1; - - // - int count = ArraySize(source); - bool has = IsValidSize(count); - if (!has) - { - return result; - } - - // - XOBFVG item; - for (int i = 0; i < count; i++) - { - // - XOBFVG iOBFVG = source[i]; - - // - bool canSet = - !item.IsValid() - ? true - : item.ob.Upper() < iOBFVG.ob.Upper(); - if (canSet) - { - // - item = iOBFVG; - result = i; - } - - // - iOBFVG.Clean(); - } - - // - item.Clean(); - - // - return result; -} - -/** - * Find Lowest Order Block of XOBFVG Collection ... - * - * @param source: XOBFVG Collection ... - * - * @return ( int ) - */ -int GetLowest( - XOBFVG &source[] // -) -{ - // - int result = -1; - - // - int count = ArraySize(source); - bool has = IsValidSize(count); - if (!has) - { - return result; - } - - // - XOBFVG item; - for (int i = 0; i < count; i++) - { - // - XOBFVG iOBFVG = source[i]; - - // - bool canSet = - !item.IsValid() - ? true - : item.ob.Lower() > iOBFVG.ob.Lower(); - if (canSet) - { - // - item = iOBFVG; - result = i; - } - - // - iOBFVG.Clean(); - } - - // - item.Clean(); - - // - return result; -} - -/** - * Find Youngest Order Block of XOBFVG Collection ... - * - * @param source: XOBFVG Collection ... - * - * @return ( int ) - */ -int GetYoungest( - XOBFVG &source[] // -) -{ - // - int result = -1; - - // - int count = ArraySize(source); - bool has = IsValidSize(count); - if (!has) - { - return result; - } - - // - XOBFVG item; - for (int i = 0; i < count; i++) - { - // - XOBFVG iOBFVG = source[i]; - - // - bool canSet = - !item.IsValid() - ? true - : item.ob.From() < iOBFVG.ob.From(); - if (canSet) - { - // - item = iOBFVG; - result = i; - } - - // - iOBFVG.Clean(); - } - - // - item.Clean(); - - // - return result; -} - -/** - * Find Oldest Order Block of XOBFVG Collection ... - * - * @param source: XOBFVG Collection ... - * - * @return ( int ) - */ -int GetOldest( - XOBFVG &source[] // -) -{ - // - int result = -1; - - // - int count = ArraySize(source); - bool has = IsValidSize(count); - if (!has) - { - return result; - } - - // - XOBFVG item; - for (int i = 0; i < count; i++) - { - // - XOBFVG iOBFVG = source[i]; - - // - bool canSet = - !item.IsValid() - ? true - : item.ob.From() > iOBFVG.ob.From(); - if (canSet) - { - // - item = iOBFVG; - result = i; - } - - // - iOBFVG.Clean(); - } - - // - item.Clean(); - - // - return result; -} - -/** - * Sort XOBFVG Collection based on OB Place ... - * - * @param source: XOBFVG instance Collection ... - * @param forDir: ENUM_X_DIRECTION member ... - * @param ignoreInside: Specified Ignoring price inside in Sorting ... - */ -void Sort( - XOBFVG &source[], - ENUM_X_DIRECTION forDir, - bool ignoreInside = true // -) -{ - // - int idx = -1; - int count = 0; - bool has = false; - - // - has = HasDirection(forDir); - if (!has) - { - return; - } - - // - bool isBullish = IsBullish(forDir); - - // - count = ArraySize(source); - has = IsValidSize(count); - if (!has) - { - return; - } - - // - XOBFVG last; - XOBFVG tmpItems[]; - bool hasLast = false; - while (HasChild(source)) - { - // - if (!hasLast) - { - // - idx = GetOldest(source); - hasLast = IsValidIndex(idx); - if (hasLast) - { - // - last = source[idx]; - ArrayRemove( - source, - idx, - 1 // - ); - - // - AddRef( - last, - tmpItems // - ); - } - - // - count = ArraySize(source); - has = IsValidSize(count); - if (!has) - { - // - last.Clean(); - break; - } - } - if (!hasLast) - { - // - last.Clean(); - break; - } - - // - XOBFVG item; - idx = GetOldest(source); - has = IsValidIndex(idx); - if (!has) - { - // - item.Clean(); - last.Clean(); - break; - } - item = source[idx]; - ArrayRemove( - source, - idx, - 1 // - ); - - // - bool isAbove = IsAbove( - item.ob, - last.ob, - ignoreInside // - ); - - // - bool isBelow = IsBelow( - item.ob, - last.ob, - ignoreInside // - ); - - // - has = - isBullish - ? isAbove - : isBelow; - if (has) - { - // - AddRef( - item, - tmpItems // - ); - - // - last = item; - hasLast = item.IsValid(); - } - } - - // - Clean(source); - Copy( - tmpItems, - source // - ); - - // - Clean(tmpItems); -} - -// diff --git a/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 b/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 index a0a7f9b2..e109cb15 100644 --- a/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 +++ b/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 @@ -299,16 +299,16 @@ class XC121SMCCycleHelper : public XCBase string symbol, ENUM_TIMEFRAMES period, X121Inputs &x121Inputs, - int requiredPOIS = 50 // + int requiredPOIs = 50 // ) { // bool result = false; // - if (requiredPOIS < 10) + if (requiredPOIs < 10) { - requiredPOIS = 10; + requiredPOIs = 10; } // @@ -341,8 +341,21 @@ class XC121SMCCycleHelper : public XCBase symbol, period // ); - mPOIDetector.MaxNumberOfPOIs(requiredPOIS); - mPOIDetector.MaxNumberOfRequiredPOIs(requiredPOIS); + mPOIDetector.MaxRequiredPOIs(requiredPOIs); + + // + int maxLoopbackBars = mPOIDetector.MaxAllowedLoopbackForInit(); + int periodSeconds = PeriodSeconds(period); + if (periodSeconds > PeriodSeconds(PERIOD_M15)) { + // + int multiplier = periodSeconds / PeriodSeconds(PERIOD_M15); + + // + if (multiplier >= 1) { + maxLoopbackBars *= 2; + } + } + mPOIDetector.MaxAllowedLoopbackForInit(maxLoopbackBars); mPOIDetector.Init(); // diff --git a/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 b/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 index 346a7a0d..cae1bce8 100644 --- a/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 +++ b/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 @@ -48,7 +48,7 @@ struct X121SMCTradeData double commission; // Commission string conditions; // Signal Conditions double maxDrawdown; // Max Position Drawdown - bool isTargeted; // Check Targetted Before Or Not + double lastTarget; // Check Last Targetted double lastTrailedTPLevel; // Hold Last Trailed TP Level // @@ -115,7 +115,7 @@ struct X121SMCTradeData conditions = NULL; // - isTargeted = false; + lastTarget = 0; // signal.Clean(); @@ -644,9 +644,22 @@ struct X121SMCTradeData * * @return ( double ) */ - double Target() + int Targets(double &targets[]) { - return signal.target; + // + int result = 0; + + // + Copy( + signal.targets, + targets // + ); + + // + result = ArraySize(targets); + + // + return result; } /** @@ -3722,50 +3735,72 @@ class XC121SMCTradeHandler : public XCBaseAlert // // Handle RF On Target ... - double target = iData.Target(); - double targetDelta = isLong - ? target + (15 * points) - : target - (15 * points); - bool canRF = - target > 0 && - !iData.isTargeted && - (isLong ? target > entry - : target < entry) && - (isLong - ? iPosition.sl < target - : iPosition.sl > target) && - (isLong - ? iPosition.price > targetDelta - : iPosition.price < targetDelta); - if (canRF) + double targets[]; + int targetsCount = iData.Targets(targets); + bool hasTargets = IsValidSize(targetsCount); + if (hasTargets) { // - double sl = target; - double tp = iPosition.tp; - string comment = "RF On Target ..."; - bool isModified = mTrader.Modify( - iData.ticket, - sl, - tp, - comment // - ); - if (isModified) + for (int k = 0; k < targetsCount; k++) { // - isProtected = true; + double target = targets[k]; + bool isValidTarget = + iData.lastTarget == 0 + ? true + : isLong + ? target > iData.lastTarget + : target < iData.lastTarget; + if (!isValidTarget) + { + continue; + } // - // Update mData ... - mData[i].isTargeted = true; + double targetDelta = isLong + ? target + (15 * points) + : target - (15 * points); + bool canRF = + target > 0 && + (isLong ? target > entry + : target < entry) && + (isLong + ? iPosition.sl < target + : iPosition.sl > target) && + (isLong + ? iPosition.price > targetDelta + : iPosition.price < targetDelta); + if (canRF) + { + // + double sl = target; + double tp = iPosition.tp; + string comment = "RF On Target ..."; + bool isModified = mTrader.Modify( + iData.ticket, + sl, + tp, + comment // + ); + if (isModified) + { + // + isProtected = true; - // - string message = prefix + - ToString(iData.Type()) + - " Position: " + - ToString(iData.ticket) + - " RF On Traget: " + ToString(target) + - " Successfully ..."; - Alert(message); + // + // Update mData ... + mData[i].lastTarget = target; + + // + string message = prefix + + ToString(iData.Type()) + + " Position: " + + ToString(iData.ticket) + + " RF On Traget: " + ToString(target) + + " Successfully ..."; + Alert(message); + } + } } } } diff --git a/X121SMCEA/Libraries/x-121.smc.lib.mq5 b/X121SMCEA/Libraries/x-121.smc.lib.mq5 index 80c31a8e..b411b86f 100644 --- a/X121SMCEA/Libraries/x-121.smc.lib.mq5 +++ b/X121SMCEA/Libraries/x-121.smc.lib.mq5 @@ -267,8 +267,8 @@ struct X121SMCStrategyConditions // double sl; double tp; - double target; string provider; + double targets[]; ENUM_X_DIRECTION signalDir; // @@ -286,9 +286,9 @@ struct X121SMCStrategyConditions void Clean() { // + time = NULL; symbol = NULL; period = NULL; - time = NULL; // sl = 0; @@ -296,6 +296,9 @@ struct X121SMCStrategyConditions provider = NULL; signalDir = X_DIRECTION_NONE; + // + Clean(targets); + // ZeroMemory(this); } diff --git a/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 b/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 index beea66dc..5f7bd885 100644 --- a/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 +++ b/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 @@ -34,10 +34,6 @@ class XCX121SMCXWZSignalDetector : public XCBase public: // // Props ... - XOBFVG chochZone; - XOBFVG targetZone; - XOBFVG signalZone; - XOBFVG waitingZone; X121SMCStrategyXWZWorkingZone workingZone; X121SMCStrategyXWZSignalConditions mConditions; X121SMCStrategyXWZSignalConditions mConditionsCollection[]; @@ -311,1137 +307,56 @@ class XCX121SMCXWZSignalDetector : public XCBase X121Conditions consolidationXConditions = consolidationConditions.x121Conditions; X121Conditions visionXConditions = visionConditions.x121Conditions; + // + XCPOIDrawer *drawer = visionCycleHelper.mPOIDrawer; + // // Setup Conditions ... // - // Choch Trading Senario ... - bool hasChochBullishConditions = false; - bool hasChochBearishConditions = false; - - // - // Order Flow Side Trading Senario ... - bool hasOrderFlowhBullishConditions = false; - bool hasOrderFlowhBearishConditions = false; - - // - // Trend Line Trading Senario ... - bool hasTrendLineBullishConditions = false; - bool hasTrendLineBearishConditions = false; - - // - // Quarter Line Trading Senario ... - bool hasBQuarterLineBullishConditions = false; - bool hasBQuarterLineBearishConditions = false; - - // - // Supply and Demand Trading Senario ... - bool hasSupDemBullishConditions = false; - bool hasSupDemBearishConditions = false; - - // - // Support and Resistance Trading Senario ... - bool hasSupResBullishConditions = false; - bool hasSupResBearishConditions = false; - - // - ENUM_X121SMC_XWZ_PROVIDERS provider = X121SMC_XWZ_PROVIDER_NONE; - - // - // Detect Working Zone ... + // First We Have to Has Working Zone ... bool hasWorkingZone = workingZone.IsValid(); if (!hasWorkingZone) - { - hasWorkingZone = DetectWorkingZone(visionState); - } - result = hasWorkingZone; - if (!result) { // - Clean(visionPoiEvents); - Clean(analysePoiEvents); - Clean(decisionPoiEvents); - Clean(consolidationPoiEvents); - - // - Clean(visionCycleEvents); - Clean(analyseCycleEvents); - Clean(decisionCycleEvents); - Clean(consolidationCycleEvents); - - // - visionState.Clean(); - analyseState.Clean(); - decisionState.Clean(); - consolidationState.Clean(); - - // - visionConditions.Clean(); - analyseConditions.Clean(); - decisionConditions.Clean(); - consolidationConditions.Clean(); - - // - visionXConditions.Clean(); - analyseXConditions.Clean(); - decisionXConditions.Clean(); - consolidationXConditions.Clean(); - - // - mConditions.Clean(); - consolidationZBar.Clean(); - - // - return result; - } - - // - // TODO: Remove this ... - UpdateTo(cTime); - DrawWorkingZone( - visionCycleHelper.mPOIDrawer // - ); - - // - // Detect Working Zone Destroy ... - bool isWorkingZoneDetroyed = workingZone.IsDestroyed(); - result = !isWorkingZoneDetroyed; - if (!result) - { - // - workingZone.Clean(); - mWorkingZoneObjects.Clear(); - - // - Clean(visionPoiEvents); - Clean(analysePoiEvents); - Clean(decisionPoiEvents); - Clean(consolidationPoiEvents); - - // - Clean(visionCycleEvents); - Clean(analyseCycleEvents); - Clean(decisionCycleEvents); - Clean(consolidationCycleEvents); - - // - visionState.Clean(); - analyseState.Clean(); - decisionState.Clean(); - consolidationState.Clean(); - - // - visionConditions.Clean(); - analyseConditions.Clean(); - decisionConditions.Clean(); - consolidationConditions.Clean(); - - // - visionXConditions.Clean(); - analyseXConditions.Clean(); - decisionXConditions.Clean(); - consolidationXConditions.Clean(); - - // - mConditions.Clean(); - consolidationZBar.Clean(); - - // - return result; - } - - // - // Checking Target Zone Breaked ... - bool hasTargetZone = targetZone.IsValid(); - if (hasTargetZone) - { - // - XOHCL bar; - bool isInited = bar.Init( + hasWorkingZone = workingZone.Init( symbol, period, - zIndex // - ); - - XOHCL cBar; - isInited = - isInited && - bar.GetPreviousBar(cBar); - - // - bool isBullish = targetZone.IsBullish(); - - // - bool isLowerBreaked = - // - bar.high < targetZone.ob.Lower() && - cBar.high < targetZone.ob.Lower() - // - ; - - // - bool isUpperBreaked = - // - bar.low > targetZone.ob.Upper() && - cBar.low > targetZone.ob.Upper() - // - ; - - // - bool isBreaked = isBullish - ? isLowerBreaked - : isUpperBreaked; - if (isBreaked) - { - // - mWorkingZoneObjects.Clear(); - targetZone.Clean(); - - // - // TODO: Remove this ... - DrawWorkingZone( - visionCycleHelper.mPOIDrawer // - ); - } - } - - // - // Detect Order Flow ... - ENUM_X_DIRECTION trend = X_DIRECTION_NONE; - bool hasOrderFlow = workingZone.HasOrderFlow(trend); - if (!hasOrderFlow) - { - // - int orderFlowCount = workingZone.DetectOrderFlow( - symbol, - period, - trend, visionState, consolidationState, - analyseState, - decisionState // + analyseState // ); - hasOrderFlow = IsValidSize(orderFlowCount); } // - bool hasTrend = HasDirection(trend); - bool hasBllishTrend = - hasTrend && - IsBullish(trend); - bool hasBearishTrend = - hasTrend && - IsBearish(trend); - - // result = hasOrderFlow; - // if (!result) - // { - - // // - // Clean(visionPoiEvents); - // Clean(analysePoiEvents); - // Clean(decisionPoiEvents); - // Clean(consolidationPoiEvents); - - // // - // Clean(visionCycleEvents); - // Clean(analyseCycleEvents); - // Clean(decisionCycleEvents); - // Clean(consolidationCycleEvents); - - // // - // visionState.Clean(); - // analyseState.Clean(); - // decisionState.Clean(); - // consolidationState.Clean(); - - // // - // visionConditions.Clean(); - // analyseConditions.Clean(); - // decisionConditions.Clean(); - // consolidationConditions.Clean(); - - // // - // visionXConditions.Clean(); - // analyseXConditions.Clean(); - // decisionXConditions.Clean(); - // consolidationXConditions.Clean(); - - // // - // mConditions.Clean(); - // consolidationZBar.Clean(); - - // // - // return result; - // } + if (hasWorkingZone) + { + // + workingZone.Update( + visionState, + consolidationState, + analyseState // + ); + } // - // TODO: Remove this ... UpdateTo(cTime); - DrawWorkingZone( - visionCycleHelper.mPOIDrawer // - ); // - isBullish = IsBullish(trend); - isBearish = IsBearish(trend); - - // - bool hasPriority = workingZone - .DetectPriority( - priority, - trend, - zIndex, - period // - ); - - // - bool hasRewardAmount = CalculateRiskReward( - priority, - reward, - amountPercent // - ); - - // - // Checking Order Flow Break ... - int breakedIDX = -1; - bool isOrderFlowBreaked = - hasOrderFlow && - workingZone.IsOrderFlowBreaked( - breakedIDX, - true, // Force OB Breaked - false, // Force FVG Breaked - zIndex, - period // - ); - - // - // Order Flow Breaked Senario ... - if (isOrderFlowBreaked) + if (hasWorkingZone) { // - AddRef( - workingZone.orderFlow[breakedIDX], - workingZone.brokenOrderFlow // - ); - - // - signalZone = workingZone.orderFlow[breakedIDX]; - provider = X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH; - - // - ArrayRemove( - workingZone.orderFlow, - breakedIDX, - 1 // - ); - - // - CleanupArray( - workingZone.brokenOrderFlow, - 10 // + workingZone.Draw( + drawer, + true // Force Clean ... ); } // - // First Check Last Order Flow FVG ... - XOBFVG youngestOrderFlow; - int youngestOBFVGIDX = GetYoungest(workingZone.orderFlow); - bool hasYoungestOBFVG = IsValidIndex(youngestOBFVGIDX); - if (hasYoungestOBFVG) - { - // - youngestOrderFlow = workingZone.orderFlow[youngestOBFVGIDX]; - - // - XOHCL obWorkerBar; - XOHCL obActivationBar; - - // - XOHCL fvgWorkerBar; - XOHCL fvgActivationBar; - - // - bool isOBBodyOut = false; - bool isOBWorked = youngestOrderFlow - .ob - .IsWorked( - trend, - obWorkerBar, - isOBBodyOut, - false // - ); - - // - bool isOBBodyIn = false; - bool isOBActivated = youngestOrderFlow - .ob - .IsActivated( - trend, - obActivationBar, - isOBBodyIn, - false // - ); - - // - bool isFVGBodyOut = false; - bool isFVGWorked = youngestOrderFlow - .fvg - .IsWorked( - trend, - fvgWorkerBar, - isFVGBodyOut, - false // - ); - - // - bool isFVGBodyIn = false; - bool isFVGActivated = youngestOrderFlow - .fvg - .IsActivated( - trend, - fvgActivationBar, - isFVGBodyIn, - false // - ); - - // - if (!isFVGWorked && - isFVGActivated) - { - // - youngestOrderFlow - .UpdateZones(decisionState); - - // - signalZone = youngestOrderFlow; - youngestOrderFlow.Clean(); - ArrayRemove( - workingZone.orderFlow, - youngestOBFVGIDX, - 1 // - ); - - // - provider = X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE; - } - else - { - // - bool isPriceInsideFVG = - // - IsInside( - consolidationZBar.high, - youngestOrderFlow.fvg // - ) - // - && - // - IsInside( - consolidationZBar.low, - youngestOrderFlow.fvg // - ) - // - ; - - // - if (isPriceInsideFVG) - { - // - youngestOrderFlow - .UpdateZones(decisionState); - - // - signalZone = youngestOrderFlow; - youngestOrderFlow.Clean(); - ArrayRemove( - workingZone.orderFlow, - youngestOBFVGIDX, - 1 // - ); - - // - provider = X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE; - } - } - - // - fvgWorkerBar.Clean(); - fvgActivationBar.Clean(); - } + return false; // - // Check New Order Blocks ... - bool hasNewConsolidationBullishOB = Contains( - X_BULLISH_ORDERBLOCK_DETECTED, - consolidationPoiEvents // - ); - bool hasNewConsolidationBearishOB = Contains( - X_BEARISH_ORDERBLOCK_DETECTED, - consolidationPoiEvents // - ); - bool hasNewOB = hasNewConsolidationBullishOB || - hasNewConsolidationBearishOB; - - // - // Check New Fair Value Gaps ... - bool hasNewConsolidationBullishFVG = Contains( - X_BULLISH_FVG_DETECTED, - consolidationPoiEvents // - ); - bool hasNewConsolidationBearishFVG = Contains( - X_BEARISH_FVG_DETECTED, - consolidationPoiEvents // - ); - bool hasNewFVG = hasNewConsolidationBullishFVG || - hasNewConsolidationBearishFVG; - - // - // Check New Order Blocks ... - bool hasNewAnalyseBullishOrderBlock = Contains( - X_BULLISH_ORDERBLOCK_DETECTED, - analysePoiEvents // - ); - bool hasNewAnalyseBearishOrderBlock = Contains( - X_BEARISH_ORDERBLOCK_DETECTED, - analysePoiEvents // - ); - bool hasNewAnalyseOB = hasNewAnalyseBullishOrderBlock || - hasNewAnalyseBearishOrderBlock; - - // - // Check New Fair Value Gaps ... - bool hasNewAnalyseBullishFVG = Contains( - X_BULLISH_FVG_DETECTED, - analysePoiEvents // - ); - bool hasNewAnalyseBearishFVG = Contains( - X_BEARISH_FVG_DETECTED, - analysePoiEvents // - ); - bool hasNewAnalyseFVG = hasNewAnalyseBullishFVG || - hasNewAnalyseBearishFVG; - - // - // Do Order Flow Actions when new Order Blocks - // or FVGs Formed ... - if (hasNewOB || - hasNewFVG || - hasNewAnalyseOB || - hasNewAnalyseFVG) - { - // - XCFVG *newFVG = NULL; - XCOrderBlock *newOB = NULL; - XCFVG *newAnalyseFVG = NULL; - XCOrderBlock *newAnalyseOB = NULL; - - // - bool isValid = false; - bool hasWaitingZone = waitingZone.IsValid(); - - // - int idx = -1; - if (hasNewOB) - { - // - if (hasNewConsolidationBullishOB) - { - // - idx = consolidationState.CountBullishOrderBlocks() - 1; - newOB = consolidationState.bullishOrderBlocks[idx]; - } - else - { - // - idx = consolidationState.CountBearishOrderBlocks() - 1; - newOB = consolidationState.bearishOrderBlocks[idx]; - } - - // - if (hasWaitingZone) - { - } - else - { - // - isValid = - !waitingZone.HasOB() - ? true - : !IsSame( - newOB, - waitingZone.ob // - ); - if (isValid) - { - // - bool isAbove = IsAbove( - newOB, - youngestOrderFlow.ob, - true // Ignore Inside ... - ); - bool isBelow = IsBelow( - newOB, - youngestOrderFlow.ob, - true // Ignore Inside ... - ); - - // - isValid = - isBullish - ? isAbove - : isBelow; - - // - if (isValid) - { - waitingZone.ob = newOB; - } - } - } - } - - // - if (hasNewFVG) - { - // - if (hasNewConsolidationBullishFVG) - { - // - idx = consolidationState.CountBullishFairValueGaps() - 1; - newFVG = consolidationState.bullishFairValueGaps[idx]; - } - else - { - // - idx = consolidationState.CountBearishFairValueGaps() - 1; - newFVG = consolidationState.bearishFairValueGaps[idx]; - } - } - - // - if (hasNewAnalyseOB) - { - // - if (hasNewAnalyseBullishOrderBlock) - { - // - idx = analyseState.CountBullishOrderBlocks() - 1; - newAnalyseOB = analyseState.bullishOrderBlocks[idx]; - } - else - { - // - idx = analyseState.CountBearishOrderBlocks() - 1; - newAnalyseOB = analyseState.bearishOrderBlocks[idx]; - } - } - - // - if (hasNewAnalyseFVG) - { - // - if (hasNewAnalyseBullishFVG) - { - // - idx = analyseState.CountBullishFairValueGaps() - 1; - newAnalyseFVG = analyseState.bullishFairValueGaps[idx]; - } - else - { - // - idx = analyseState.CountBearishFairValueGaps() - 1; - newAnalyseFVG = analyseState.bearishFairValueGaps[idx]; - } - - // - if (hasWaitingZone) - { - } - else - { - // - if (waitingZone.HasOB()) - { - // - XCFVG *tmpFVGs[]; - XCFVG *tmpWorkingFVGs[]; - bool isOBBullish = waitingZone.ob.IsBullish(); - if (isOBBullish) - { - Copy( - analyseState.bullishFairValueGaps, - tmpFVGs // - ); - } - else - { - Copy( - analyseState.bearishFairValueGaps, - tmpFVGs // - ); - } - - // - for (int j = 0; j < ArraySize(tmpFVGs); j++) - { - // - XCFVG *jFVG = tmpFVGs[j]; - - // - // Check Start Date ... - bool isFromPassed = jFVG.From() > waitingZone.ob.From(); - if (!isFromPassed) - { - // - ZeroMemory(jFVG); - continue; - } - - // - // Check Place ... - - // - bool isAbove = IsAboveDiff( - jFVG, - waitingZone.ob, - true // - ); - - // - bool isBelow = IsBelowDiff( - jFVG, - waitingZone.ob, - true // - ); - - // - bool isInside = IsInsideDiff( - jFVG, - waitingZone.ob, - false // - ); - - // - bool isPlacePassed = - isInside || - (isBullish - ? isAbove - : isBelow); - if (!isPlacePassed) - { - // - ZeroMemory(jFVG); - continue; - } - - // - Add( - jFVG, - tmpWorkingFVGs // - ); - } - - // - int fvgsCount = ArraySize(tmpWorkingFVGs); - isValid = IsValidSize(fvgsCount); - if (isValid) - { - // - idx = - isBullish - ? GetLowest(tmpWorkingFVGs) - : GetHighest(tmpWorkingFVGs); - - // - if (IsValidIndex(idx)) - { - // - XCFVG *selectedFVG = tmpWorkingFVGs[idx]; - - // - waitingZone.fvg = selectedFVG; - - // - bool isExists = FindIndex( - idx, - selectedFVG, - tmpFVGs // - ); - if (isExists) - { - // - ArrayRemove( - tmpFVGs, - idx, - 1 // - ); - } - } - } - - // - Clean(tmpFVGs); - Clean(tmpWorkingFVGs); - } - } - } - - // - hasWaitingZone = waitingZone.IsValid(); - if (hasWaitingZone) - { - // - bool isSameDir = waitingZone.GetDirection() == trend; - if (!isSameDir) - { - targetZone = waitingZone; - } - else - { - // - workingZone.AddOrderFlowItem(waitingZone); - - // - // TODO: Remove this ... - mWorkingZoneObjects.Clear(); - DrawWorkingZone( - visionCycleHelper.mPOIDrawer // - ); - } - - // - waitingZone.Clean(); - } - - // - if (signalZone.IsValid() && - provider == X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH) - { - // - ENUM_X_DIRECTION iForDir = Opposit(signalZone.GetDirection()); - if (hasNewAnalyseOB && - hasNewAnalyseFVG) - { - // - bool isSameDir = - newAnalyseOB.GetDirection() == iForDir && - newAnalyseFVG.GetDirection() == iForDir; - bool isOneInsideAnoter = - // - (newAnalyseFVG.Upper() < newAnalyseOB.Upper() && - newAnalyseFVG.Upper() > newAnalyseOB.Lower()) - // - || - // - (newAnalyseOB.Upper() < newAnalyseFVG.Upper() && - newAnalyseOB.Upper() > newAnalyseFVG.Lower()) - // - ; - - // - bool isZoneDetected = - isSameDir && - isOneInsideAnoter; - if (isZoneDetected) - { - // - XOBFVG iSignalZone; - iSignalZone.ob = newAnalyseOB; - iSignalZone.fvg = newAnalyseFVG; - - // - chochZone = iSignalZone; - } - } - } - - // - ZeroMemory(newOB); - ZeroMemory(newFVG); - ZeroMemory(newAnalyseOB); - ZeroMemory(newAnalyseFVG); - } - - // - bool isPriceInsideCHOCHZone = false; - bool hasCHOCHZone = chochZone.IsValid(); - if (hasCHOCHZone) - { - // - XCBaseObject *objects[]; - bool isCreated = visionCycleHelper - .mPOIDrawer - .DrawOBFVG( - chochZone, - objects // - ); - if (isCreated) - { - AddDrawnObjects(objects); - } - - // - XOHCL cBar; - bool isInited = cBar.Init( - symbol, - period, - cIndex // - ); - - // - isPriceInsideCHOCHZone = - isInited && - cBar.low >= chochZone.fvg.Lower() && - cBar.high <= chochZone.fvg.Upper(); - if (isPriceInsideCHOCHZone) - { - // - // Reverse Trend and ReCalculate Requirements - // For CHOCH Tradng ... - - // - trend = chochZone.GetDirection(); - - // - isBullish = IsBullish(trend); - isBearish = IsBearish(trend); - - // - bool hasPriority = workingZone - .DetectPriority( - priority, - trend, - zIndex, - period // - ); - - // - bool hasRewardAmount = CalculateRiskReward( - priority, - reward, - amountPercent // - ); - - // - provider = X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH; - } - - // - cBar.Clean(); - } - - // - // Reading Trand Line Value ... - double zValue = workingZone.GetOrderFlowTrendLinePrice( - zIndex, - period // - ); - double cValue = workingZone.GetOrderFlowTrendLinePrice( - cIndex, - period // - ); - double pValue = workingZone.GetOrderFlowTrendLinePrice( - pIndex, - period // - ); - double ppValue = workingZone.GetOrderFlowTrendLinePrice( - ppIndex, - period // - ); - - // - // Implementing Signals ... - // - - // - // TODO: Implement Order Flow Side Trading Senario ... - bool hasOrderFlowConditions = - hasTrend && - hasPriority && - hasRewardAmount && - signalZone.IsValid() && - provider == X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE; - - // - hasOrderFlowhBullishConditions = - isBullish && - hasOrderFlowConditions && - signalZone.IsBullish(); - - // - hasOrderFlowhBearishConditions = - isBearish && - hasOrderFlowConditions && - signalZone.IsBearish(); - - // - if (hasOrderFlowConditions) - { - // - mConditions.signalZone = signalZone; - mConditions.targetZone = targetZone; - - // - point = hasOrderFlowhBullishConditions - ? signalZone.ob.Upper() - : signalZone.ob.Lower(); - - // - pivot = hasOrderFlowhBullishConditions - ? signalZone.ob.Lower() - : signalZone.ob.Upper(); - - // - signalZone.Clean(); - } - - // - // TODO: Implement Inside Zone Trading Senario ... - bool hasInsideZoneConditions = - hasTrend && - hasPriority && - hasRewardAmount && - signalZone.IsValid() && - provider == X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE; - - // - bool hasInsideZoneBullishConditions = - isBullish && - signalZone.IsBullish() && - hasInsideZoneConditions; - - // - bool hasInsideZoneBearishConditions = - isBearish && - signalZone.IsBearish() && - hasInsideZoneConditions; - - // - if (hasInsideZoneConditions) - { - // - mConditions.signalZone = signalZone; - mConditions.targetZone = targetZone; - - // - point = hasOrderFlowhBullishConditions - ? signalZone.ob.Upper() - : signalZone.ob.Lower(); - - // - pivot = hasOrderFlowhBullishConditions - ? signalZone.ob.Lower() - : signalZone.ob.Upper(); - - // - signalZone.Clean(); - } - - // - // TODO: Implement CHOCH Trading Senario ... - bool hasCHOCHConditions = - hasCHOCHZone && - chochZone.IsValid() && - isPriceInsideCHOCHZone && - provider == X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH; - - // - hasChochBullishConditions = - hasCHOCHConditions && - chochZone.IsBullish(); - hasChochBearishConditions = - hasCHOCHConditions && - chochZone.IsBearish(); - - // - if (hasCHOCHConditions) - { - // - mConditions.signalZone = chochZone; - mConditions.targetZone = targetZone; - - // - point = hasChochBullishConditions - ? chochZone.ob.Upper() - : chochZone.ob.Lower(); - - // - pivot = hasChochBearishConditions - ? chochZone.ob.Lower() - : chochZone.ob.Upper(); - - // - chochZone.Clean(); - signalZone.Clean(); - } - - // - // TODO: Implement Trend Line Trading Senario ... - - // - // TODO: Implement Quarter Line Trading Senario ... - - // - // TODO: Implement Supply and Demand Trading Senario ... - - // - // TODO: Implement Support and Resistance Trading Senario ... - - // - // TODO: Implement Mitigation Blocks Trading Senario ... - - // - // Summarize ... - - // - bool hasBullishConditions = - // - hasChochBullishConditions || - hasSupDemBullishConditions || - hasSupResBullishConditions || - hasTrendLineBullishConditions || - hasOrderFlowhBullishConditions || - hasInsideZoneBullishConditions || - hasBQuarterLineBullishConditions - // - ; - - // - bool hasBearishConditions = - // - hasChochBearishConditions || - hasSupDemBearishConditions || - hasSupResBearishConditions || - hasTrendLineBearishConditions || - hasOrderFlowhBearishConditions || - hasInsideZoneBearishConditions || - hasBQuarterLineBearishConditions - // - ; - - // - result = - hasBullishConditions || - hasBearishConditions; - - // - if (result) - { - // - mConditions.dir = trend; - mConditions.pivot = pivot; - mConditions.point = point; - mConditions.reward = reward; - mConditions.target = target; - mConditions.setupTime = cTime; - mConditions.priority = priority; - mConditions.provider = provider; - mConditions.amountPercent = amountPercent; - } - - // - // Cleanups ... + // Cleanup Resources ... // Clean(visionPoiEvents); @@ -1580,13 +495,45 @@ class XCX121SMCXWZSignalDetector : public XCBase return result; } + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + + // + return result; + } + // // Cycles POI States ... XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; // // Cycle X121Conditions ... X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; // // Check Signal Validation ... @@ -1637,6 +584,15 @@ class XCX121SMCXWZSignalDetector : public XCBase decisionState.Clean(); decisionConditions.Clean(); decisionXConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseState.Clean(); + analyseConditions.Clean(); + analyseXConditions.Clean(); } // @@ -1661,479 +617,14 @@ class XCX121SMCXWZSignalDetector : public XCBase // // Base SL Used Pivot of Conditions ... - // Add( - // conditions.pivot, - // sls // - // ); - - // - int lowestSupportIDX = -1; - int highestResistanceIDX = -1; - bool isSupportRejected = false; - bool isResistanceRejected = false; - bool hasSignalZone = conditions.signalZone.IsValid(); - if (hasSignalZone) - { - // - conditions - .signalZone - .UpdateZones(decisionState); - conditions - .signalZone - .UpdateTo(cTime); - - // - XOHCL cBar; - bool isBarInited = cBar.Init( - conditions.symbol, - conditions.period, - cIndex // - ); - - // - lowestSupportIDX = GetLowest(conditions.signalZone.supportZones); - if (IsValidIndex(lowestSupportIDX)) - { - // - isSupportRejected = - // - isBarInited && - ( - // - (cBar.low < conditions.signalZone.supportZones[lowestSupportIDX].Upper() && - cBar.GetDown() > conditions.signalZone.supportZones[lowestSupportIDX].Upper()) - // - || - // - (cBar.low < conditions.signalZone.supportZones[lowestSupportIDX].Lower() && - cBar.GetDown() > conditions.signalZone.supportZones[lowestSupportIDX].Lower()) - // - ) - // - ; - - // - isSupportRejected = - isBullish && - isSupportRejected; - if (isSupportRejected) - { - // - double vPivot = conditions.signalZone.supportZones[lowestSupportIDX].Lower(); - bool canSetPivot = vPivot > conditions.pivot && - vPivot < conditions.point; - if (canSetPivot) - { - // - Add( - vPivot, - sls // - ); - } - } - } - - // - highestResistanceIDX = GetHighest(conditions.signalZone.resistanceZones); - if (IsValidIndex(highestResistanceIDX)) - { - // - isResistanceRejected = - // - isBarInited && - ( - // - (cBar.high > conditions.signalZone.resistanceZones[highestResistanceIDX].Upper() && - cBar.GetUp() < conditions.signalZone.resistanceZones[highestResistanceIDX].Upper()) - // - || - // - (cBar.high > conditions.signalZone.resistanceZones[highestResistanceIDX].Lower() && - cBar.GetUp() < conditions.signalZone.resistanceZones[highestResistanceIDX].Lower()) - // - ) - // - ; - - // - isResistanceRejected = - isBearish && - isResistanceRejected; - if (isResistanceRejected) - { - // - double vPivot = conditions.signalZone.resistanceZones[highestResistanceIDX].Upper(); - bool canSetPivot = vPivot < conditions.pivot && - vPivot > conditions.point; - if (canSetPivot) - { - // - Add( - vPivot, - sls // - ); - } - } - } - - // - cBar.Clean(); - } - - // - // Consolidation Zone Detection ... - - // - // Detect Consolidation Zones ... - - // - // Bullish Consolidation Zone ... - XConsolidationZone bullishCZones[]; - bool hasBullishConsolidationZone = false; - XConsolidationZone bullishConsolidationZone; - int bullishCZonesCount = decisionCycleHelper.FillConsolidationZones( - X_DIRECTION_BULLISH, - bullishCZones // - ); - bool hasBullishConsolidationZones = IsValidSize(bullishCZonesCount); - if (hasBullishConsolidationZones) - { - // - int idx = -1; - while (HasChild(bullishCZones)) - { - // - idx = GetYoungest(bullishCZones); - hasBullishConsolidationZone = IsValidIndex(idx); - if (hasBullishConsolidationZone) - { - // - bullishConsolidationZone = bullishCZones[idx]; - - // - ArrayRemove( - bullishCZones, - idx, - 1 // - ); - - // - // Check Zone Based On pivot, since this is the SL ... - hasBullishConsolidationZone = - isBullish && - hasBullishConsolidationZone && - bullishConsolidationZone.lower > conditions.pivot && - bullishConsolidationZone.upper <= conditions.point; - if (hasBullishConsolidationZone) - { - // - XCConsolidationZoneObject *iObj; - bool isCreated = decisionCycleHelper.mPOIDrawer.CreateConsolidationZone( - bullishConsolidationZone, - iObj // - ); - if (isCreated) - { - mObjects.Add(iObj); - } - - // - Add( - bullishConsolidationZone.lower, - sls // - ); - } - } - } - } - Clean(bullishCZones); - bullishConsolidationZone.Clean(); - - // - // Bearish Consolidation Zone ... - XConsolidationZone bearishCZones[]; - bool hasBearishConsolidationZone = false; - XConsolidationZone bearishConsolidationZone; - int bearishCZonesCount = decisionCycleHelper.FillConsolidationZones( - X_DIRECTION_BEARISH, - bearishCZones // - ); - bool hasBearishConsolidationZones = IsValidSize(bearishCZones); - if (hasBearishConsolidationZones) - { - // - int idx = -1; - while (HasChild(bearishCZones)) - { - // - idx = GetYoungest(bearishCZones); - hasBearishConsolidationZone = IsValidIndex(idx); - if (hasBearishConsolidationZone) - { - // - bearishConsolidationZone = bearishCZones[idx]; - - // - ArrayRemove( - bearishCZones, - idx, - 1 // - ); - - // - hasBearishConsolidationZone = - isBearish && - hasBearishConsolidationZone && - bearishConsolidationZone.upper < conditions.pivot && - bearishConsolidationZone.lower >= conditions.point; - if (hasBearishConsolidationZone) - { - // - Add( - bearishConsolidationZone.upper, - sls // - ); - } - } - } - } - Clean(bearishCZones); - bearishConsolidationZone.Clean(); - - // - // Check VWap Crossing ... - - // - bool isVWapSwitchedToBullish = - // - (decisionXConditions.isVWapBullishOrdered && - decisionXConditions.isVWapSwitchedToBullishState) - // - || - // - (decisionXConditions.isVWapBullishState && - decisionXConditions.isVWapSwitchedToBullishOrdered) - // - ; - - // - isVWapSwitchedToBullish = - isBullish && - isVWapSwitchedToBullish; - if (isVWapSwitchedToBullish) - { - // - double vPivot = decisionXConditions.vwapMin; - bool canSetPivot = vPivot > conditions.pivot && - vPivot < conditions.point; - if (canSetPivot) - { - // - Add( - vPivot, - sls // - ); - } - } - - // - bool isVWapSwitchedToBearish = - // - (decisionXConditions.isVWapBearishOrdered && - decisionXConditions.isVWapSwitchedToBearishState) - // - || - // - (decisionXConditions.isVWapBearishState && - decisionXConditions.isVWapSwitchedToBearishOrdered) - // - ; - - // - isVWapSwitchedToBearish = - isBearish && - isVWapSwitchedToBearish; - if (isVWapSwitchedToBearish) - { - // - double vPivot = decisionXConditions.vwapMax; - bool canSetPivot = vPivot < conditions.pivot && - vPivot > conditions.point; - if (canSetPivot) - { - // - Add( - vPivot, - sls // - ); - } - } - - // - // Point Break ... - isInited = cBar.Init( - conditions.symbol, - conditions.period, - cIndex // - ); - double point = conditions.point; - bool isPointBreaked = - isInited && - IsBarBreak( - point, - setupDir, - cBar // - ); - cBar.Clean(); - - // - bool isCommonsPassed = - // - (isSupportRejected || - isResistanceRejected || - isVWapSwitchedToBullish || - isVWapSwitchedToBearish || - hasBullishConsolidationZone || - hasBearishConsolidationZone) - // - ; - - // - // Trigger Conditions ... - - // - bool canTriggerCHOCHZone = - // - isScorePassed && - isCommonsPassed && - conditions.provider == X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH - // - ; - - // - bool canTriggerActivatedZone = - // - // isPointBreaked && - isScorePassed && - isCommonsPassed && - conditions.provider == X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE - // - ; - - // - bool canTriggerPriceInsideZone = - // - isScorePassed && - isCommonsPassed && - conditions.provider == X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE - // - ; - - // - bool canTrigger = (canTriggerCHOCHZone || - canTriggerActivatedZone || - canTriggerPriceInsideZone); - - // - // Summary ... - - // - isBullish = - // - isBullish && - canTrigger - // - ; - - // - isBearish = - // - isBearish && - canTrigger - // - ; - - // - result = isBullish || - isBearish; - if (!result) - { - // - // Cleanup Setup Conditions ... - int setupAge = conditions.GetSetupAge(); - if (IsValidSize(setupAge) && - IsValidSize(maxAllowedSetupAge) && - setupAge >= maxAllowedSetupAge) - { - conditions.Clean(); - } - - // - // Cleanup ... - - // - Clean(decisionPoiEvents); - Clean(decisionCycleEvents); - - // - decisionState.Clean(); - decisionConditions.Clean(); - decisionXConditions.Clean(); - - // - return result; - } - - // - double entry = GetEntry( - conditions.symbol, - setupDir // - ); - - // - // Manipulate SL Based on Consolidation Zones ... - - // - // TODO: Add Consolidation Zone for SLs ... - - // - double iAtr = decisionXConditions.atrBuffer[1]; - iAtr *= 1.5; - - // - // Since Pivot Value almost used - // as Default SL, if there isn't any Refind SL - // we use Default ... - if (!HasChild(sls)) - { - // - Add( - conditions.pivot, - sls // - ); - } - - // - double slsMin = GetMin(sls); - double slsMax = GetMax(sls); - - // - double sl = isBullish - ? slsMin - iAtr - : slsMax + iAtr; - double risk = MathAbs(entry - sl); - - // - // Filling Conditions Props ... - conditions.sl = sl; - conditions.triggerTime = cTime; - conditions.type = isBullish - ? X_POSITION_TYPE_LONG - : X_POSITION_TYPE_SHORT; // // Cleanup ... + // + cBar.Clean(); + pBar.Clean(); + // Clean(decisionPoiEvents); Clean(decisionCycleEvents); @@ -2143,6 +634,15 @@ class XCX121SMCXWZSignalDetector : public XCBase decisionConditions.Clean(); decisionXConditions.Clean(); + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseState.Clean(); + analyseConditions.Clean(); + analyseXConditions.Clean(); + // return result; } @@ -2883,99 +1383,10 @@ class XCX121SMCXWZSignalDetector : public XCBase return result; } - // - bool DetectWorkingZone( - XPOIState <fState // - ) - { - // - bool result = false; - - // - result = IsValid(symbol) && - IsValid(period); - if (!result) - { - return result; - } - - // - result = !workingZone.IsValid(); - if (!result) - { - return result; - } - - // - workingZone.symbol = symbol; - workingZone.period = period; - - // - int idx = -1; - bool has = false; - - // - has = ltfState.HasSupplyZones(); - if (has) - { - // - idx = GetHighest(ltfState.supplyZones); - if (IsValidIndex(idx)) - { - workingZone.supplyZone = ltfState.supplyZones[idx]; - } - } - - // - has = ltfState.HasDemandZones(); - if (has) - { - // - idx = GetLowest(ltfState.demandZones); - if (IsValidIndex(idx)) - { - workingZone.demandZone = ltfState.demandZones[idx]; - } - } - - // - bool hasWorkingZone = workingZone.HasSupplyZone() && - workingZone.HasDemandZone(); - if (hasWorkingZone) - { - // - double upper = workingZone.supplyZone.Lower(); - double lower = workingZone.demandZone.Upper(); - - // - double delta = ((upper - lower) / 100) * 25; - - // - workingZone.quarter1 = upper - (1 * delta); - workingZone.quarter2 = upper - (2 * delta); - workingZone.quarter3 = upper - (3 * delta); - - // - hasWorkingZone = workingZone.IsValid(); - } - - // - result = hasWorkingZone; - - // - return result; - } - // // Draw Functions ... // - // - void RemoveDraws() - { - mObjects.Clear(); - } - // void DrawBar( XOHCL &bar, @@ -3037,433 +1448,6 @@ class XCX121SMCXWZSignalDetector : public XCBase } } - // - void DrawWorkingZone( - XCPOIDrawer *drawer, - bool drawTrendLine = true, - bool forceClean = false // - ) - { - // - if (drawer == NULL) - { - return; - } - - // - if (forceClean) - { - mWorkingZoneObjects.Clear(); - } - - // - int count = 0; - bool has = false; - bool isCreated = false; - - // - ulong chartID = drawer.ChartIdentification(); - int subWindow = drawer.SubWindowIdentification(); - color bullishColor = drawer.BarBullishColor(); - color bearishColor = drawer.BarBearishColor(); - - // - // Supply Zone ... - has = workingZone.HasSupplyZone(); - if (has) - { - // - XCSupplyZoneObject *iObj; - isCreated = drawer.CreateSupplyZone( - workingZone.supplyZone, - iObj // - ); - - // - if (isCreated) - { - mWorkingZoneObjects.Add(iObj); - } - } - - // - // Demand Zone ... - has = workingZone.HasDemandZone(); - if (has) - { - // - XCDemandZoneObject *iObj; - isCreated = drawer.CreateDemandZone( - workingZone.demandZone, - iObj // - ); - - // - if (isCreated) - { - mWorkingZoneObjects.Add(iObj); - } - } - - // - // Quarters ... - has = workingZone.IsValid(); - if (has) - { - // - double zoneUpper = workingZone.supplyZone.Upper(); - double upper = workingZone.supplyZone.Lower(); - - // - double lower = workingZone.demandZone.Upper(); - double zoneLower = workingZone.demandZone.Lower(); - - // - string prefix = "X121WZone_" + workingZone.symbol + "_" + ToString(workingZone.period); - - // - // Zone Upper ... - CChartObjectHLine *zoneUpperLine; - zoneUpperLine = new CChartObjectHLine(); - isCreated = zoneUpperLine.Create( - chartID, - prefix + "_ZoneTop", - subWindow, - zoneUpper // - ); - if (isCreated) - { - // - zoneUpperLine.Color(clrRed); - - // - mWorkingZoneObjects.Add(zoneUpperLine); - } - - // - // Zone Lower ... - CChartObjectHLine *zoneLowerLine; - zoneLowerLine = new CChartObjectHLine(); - isCreated = zoneLowerLine.Create( - chartID, - prefix + "_ZoneDown", - subWindow, - zoneLower // - ); - if (isCreated) - { - // - zoneLowerLine.Color(clrRed); - - // - mWorkingZoneObjects.Add(zoneLowerLine); - } - - // - // Upper ... - CChartObjectHLine *upperLine; - upperLine = new CChartObjectHLine(); - isCreated = upperLine.Create( - chartID, - prefix + "_Upper", - subWindow, - upper // - ); - if (isCreated) - { - // - upperLine.Color(clrLime); - - // - mWorkingZoneObjects.Add(upperLine); - } - - // - // Lower ... - CChartObjectHLine *lowerLine; - lowerLine = new CChartObjectHLine(); - isCreated = lowerLine.Create( - chartID, - prefix + "_Lower", - subWindow, - lower // - ); - if (isCreated) - { - // - lowerLine.Color(clrLime); - - // - mWorkingZoneObjects.Add(lowerLine); - } - - // - // Quarters ... - - // - // Quarter 1 ... - CChartObjectHLine *q1Line; - q1Line = new CChartObjectHLine(); - isCreated = q1Line.Create( - chartID, - prefix + "_Q1", - subWindow, - workingZone.quarter1 // - ); - if (isCreated) - { - // - q1Line.Color(clrYellow); - - // - mWorkingZoneObjects.Add(q1Line); - } - - // - // Quarter 2 ... - CChartObjectHLine *q2Line; - q2Line = new CChartObjectHLine(); - isCreated = q2Line.Create( - chartID, - prefix + "_Q2", - subWindow, - workingZone.quarter2 // - ); - if (isCreated) - { - // - q2Line.Color(clrYellow); - - // - mWorkingZoneObjects.Add(q2Line); - } - - // - // Quarter 3 ... - CChartObjectHLine *q3Line; - q3Line = new CChartObjectHLine(); - isCreated = q3Line.Create( - chartID, - prefix + "_Q3", - subWindow, - workingZone.quarter3 // - ); - if (isCreated) - { - // - q3Line.Color(clrYellow); - - // - mWorkingZoneObjects.Add(q3Line); - } - } - - // - // Draw Order Flow ... - ENUM_X_DIRECTION trend; - has = workingZone.HasOrderFlow(trend); - if (has) - { - // - bool isBullish = IsBullish(trend); - - // - count = workingZone.CountOrderFlow(); - for (int i = 0; i < count; i++) - { - // - XOBFVG iOBFVG = workingZone.orderFlow[i]; - - // - XCBaseObject *drawnObjects[]; - int drawnObjectsCount = drawer - .DrawOBFVG( - // - iOBFVG, - drawnObjects, - // - true, // Draw Order Block ... - true, // Draw Fair Value Gap ... - false, // Draw Supply Zones ... - false, // Draw Demand Zones ... - false, // Draw Support Zones ... - false // Draw Resistance Zones ... - ); - if (IsValidSize(drawnObjectsCount)) - { - AddDrawnWorkingZoneObjects(drawnObjects); - } - } - - // - // Draw Trend Line ... - if (drawTrendLine) - { - // - XOBFVGPivot pivots[]; - count = workingZone.GetSwings(pivots); - has = count >= 2; - if (has) - { - // - // Get Max / Min ... - double max = 0; - double min = 0; - datetime maxAt = NULL; - datetime minAt = NULL; - for (int i = 0; i < count; i++) - { - // - XOBFVGPivot iPivot = pivots[i]; - - // - if (!iPivot.IsValid()) - { - // - iPivot.Clean(); - continue; - } - - // - // Min ... - bool canSetMin = - min == 0 - ? true - : min > iPivot.value; - if (canSetMin) - { - // - minAt = iPivot.at; - min = iPivot.value; - } - - // - // Max ... - bool canSetMax = - max == 0 - ? true - : max < iPivot.value; - if (canSetMax) - { - // - maxAt = iPivot.at; - max = iPivot.value; - } - - // - iPivot.Clean(); - } - - // - double price1 = - isBullish - ? min - : max; - double price2 = - isBullish - ? max - : min; - datetime time1 = - isBullish - ? minAt - : maxAt; - datetime time2 = - isBullish - ? maxAt - : minAt; - - // - color clrTrend = - isBullish - ? bullishColor - : bearishColor; - - // - string trendName = - ToString(trend) + "_" + "XTRNDL_" + - ToString(period) + "_" + - ToString(price1) + "_" + - ToString(price2) + "_"; - // + ToMD5(ToString(time1)); - - // - CChartObjectTrend *mTrend; - mTrend = new CChartObjectTrend(); - isCreated = mTrend.Create( - chartID, - trendName, - subWindow, - time1, - price1, - time2, - price2 // - ); - - // - if (isCreated) - { - // - mTrend.Width(2); - mTrend.Color(clrTrend); - mTrend.RayRight(true); - - // - mWorkingZoneObjects.Add(mTrend); - } - } - } - - // - // Draw Target Zone ... - has = targetZone.IsValid(); - if (has) - { - // - XCBaseObject *drawnObjects[]; - int drawnObjectsCount = drawer - .DrawOBFVG( - // - targetZone, - drawnObjects, - // - true, // Draw Order Block ... - true, // Draw Fair Value Gap ... - false, // Draw Supply Zones ... - false, // Draw Demand Zones ... - false, // Draw Support Zones ... - false // Draw Resistance Zones ... - ); - if (IsValidSize(drawnObjectsCount)) - { - AddDrawnWorkingZoneObjects(drawnObjects); - } - } - } - - // - } - - // - void DrawConditions( - X121SMCStrategyXWZSignalConditions &conditions, - XCPOIDrawer *drawer, - bool drawTrendLine = true, - bool forceClean = false // - ) - { - // - if (drawer == NULL) - { - return; - } - - // - if (forceClean) - { - mObjects.Clear(); - } - } - // protected: // @@ -3491,17 +1475,12 @@ class XCX121SMCXWZSignalDetector : public XCBase void DeInit() { // - chochZone.Clean(); - signalZone.Clean(); - targetZone.Clean(); mConditions.Clean(); workingZone.Clean(); Clean(mConditionsCollection); // - mObjects.Clear(); mBarObjects.Clear(); - mWorkingZoneObjects.Clear(); } /** @@ -3517,12 +1496,7 @@ class XCX121SMCXWZSignalDetector : public XCBase value = NormalizeTime(value); // - chochZone.UpdateTo(value); - targetZone.UpdateTo(value); - signalZone.UpdateTo(value); workingZone.UpdateTo(value); - mConditions.UpdateTo(value); - waitingZone.UpdateTo(value); } // @@ -3600,42 +1574,6 @@ class XCX121SMCXWZSignalDetector : public XCBase return result; } - // - void AddDrawnObjects(XCBaseObject *&objects[]) - { - // - int count = ArraySize(objects); - bool has = IsValidSize(count); - if (!has) - { - return; - } - - // - for (int i = 0; i < count; i++) - { - mObjects.Add(objects[i]); - } - } - - // - void AddDrawnWorkingZoneObjects(XCBaseObject *&objects[]) - { - // - int count = ArraySize(objects); - bool has = IsValidSize(count); - if (!has) - { - return; - } - - // - for (int i = 0; i < count; i++) - { - mWorkingZoneObjects.Add(objects[i]); - } - } - // }; diff --git a/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 b/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 index d29b8d7d..b39fdd73 100644 --- a/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 +++ b/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 @@ -56,20 +56,28 @@ struct X121SMCStrategyXWZWorkingZone string symbol; ENUM_TIMEFRAMES period; - // - XCSupplyZone *supplyZone; - XCDemandZone *demandZone; - // double quarter1; double quarter2; double quarter3; // - XOBFVG orderFlow[]; - XOBFVGPivot swings[]; - XOBFVG brokenOrderFlow[]; - CChartObjectTrend *orderFlowTrend; + XCSupplyZone *supplyZone; + XCDemandZone *demandZone; + + // + XCSupplyZone *supplyZones[]; + XCDemandZone *demandZones[]; + + // + XCSupportZone *supportZones[]; + XCResistanceZone *resistanceZones[]; + + // + XOBFVG waitingZones[]; + + // + CArrayObj mObjects; // // Constructor ... @@ -94,23 +102,22 @@ struct X121SMCStrategyXWZWorkingZone period = NULL; // - Clean(orderFlow); - Clean(brokenOrderFlow); + Clean(supplyZones); + Clean(demandZones); + + // + Clean(waitingZones); + + // + Clean(supportZones); + Clean(resistanceZones); // - Clean(swings); ZeroMemory(supplyZone); ZeroMemory(demandZone); // - if (orderFlowTrend != NULL) - { - orderFlowTrend.Delete(); - } - ZeroMemory(orderFlowTrend); - - // - ZeroMemory(this); + mObjects.Clear(); } // @@ -136,6 +143,288 @@ struct X121SMCStrategyXWZWorkingZone return result; } + // + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &stfState // + ) + { + // + bool result = false; + + // + result = + // + IsValid(_symbol) && + IsValid(_period) && + // + htfState.IsValid() && + mtfState.IsValid() && + stfState.IsValid() && + // + htfState.HasChild() && + mtfState.HasChild() && + stfState.HasChild() + // + ; + if (!result) + { + return result; + } + + // + symbol = _symbol; + period = _period; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + // Supply Zone ... + has = HasSupplyZone(); + if (!has) + { + // + idx = GetHighest(htfState.supplyZones); + has = IsValidIndex(idx); + if (has) + { + supplyZone = htfState.supplyZones[idx]; + } + } + + // + // Demand Zone ... + has = HasDemandZone(); + if (!has) + { + // + idx = GetLowest(htfState.demandZones); + has = IsValidIndex(idx); + if (has) + { + demandZone = htfState.demandZones[idx]; + } + } + + // + // Supply Zones ... + has = HasSupplyZones(); + if (!has) + { + // + count = mtfState.FilterSupplyZones( + supplyZones, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + } + + // + // Demand Zones ... + has = HasDemandZones(); + if (!has) + { + // + count = mtfState.FilterDemandZones( + demandZones, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + } + + // + // Support Zones ... + has = HasSupportZones(); + if (!has) + { + // + count = stfState.FilterSupportZones( + supportZones, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + } + + // + // Resistance Zones ... + has = HasResistanceZones(); + if (!has) + { + // + count = stfState.FilterResistanceZones( + resistanceZones, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + } + + // + if (supplyZone != NULL && + demandZone != NULL && + supplyZone.IsValid() && + demandZone.IsValid()) + { + // + double upper = supplyZone.Lower(); + double lower = demandZone.Upper(); + + // + double delta = ((upper - lower) / 100) * 25; + + // + quarter1 = upper - (1 * delta); + quarter2 = upper - (2 * delta); + quarter3 = upper - (3 * delta); + } + + // + ExtractOBFVGs( + waitingZones, + mtfState, + stfState // + ); + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + return result; + } + + // + void Update( + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &stfState // + ) + { + // + int count = 0; + bool has = false; + + // + has = + // + IsValid() && + // + htfState.IsValid() && + mtfState.IsValid() && + stfState.IsValid() && + // + htfState.HasChild() && + mtfState.HasChild() && + stfState.HasChild() + // + ; + + // + + // + // Supply Zones ... + count = mtfState.FilterSupplyZones( + supplyZones, + NULL, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + + // + // Demand Zones ... + count = mtfState.FilterDemandZones( + demandZones, + NULL, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + + // + // Support Zones ... + count = stfState.FilterSupportZones( + supportZones, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + + // + // Resistance Zones ... + count = stfState.FilterResistanceZones( + resistanceZones, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + + // + ExtractOBFVGs( + waitingZones, + mtfState, + stfState // + ); + } + // bool HasSupplyZone() { @@ -151,589 +440,69 @@ struct X121SMCStrategyXWZWorkingZone } // - // - // - - // - bool HasOrderFlow() + bool HasSupplyZones() { - // - bool result = false; - - // - result = IsValid() && - HasChild(orderFlow); - - // - return result; + return HasChild(supplyZones); } // - bool HasOrderFlow( - ENUM_X_DIRECTION &orderFlowDir // - ) + int CountSupplyZones() { - // - bool result = false; - - // - result = IsValid() && - HasChild(orderFlow); - if (result) - { - orderFlowDir = orderFlow[0].GetDirection(); - } - - // - return result; + return ArraySize(supplyZones); } // - int CountOrderFlow() + bool HasDemandZones() { - return ArraySize(orderFlow); + return HasChild(demandZones); } // - int GetSwings( - XOBFVGPivot &pivots[] // - ) + int CountDemandZones() { - // - int result = 0; - - // - Clean(pivots); - - // - int count = 0; - bool has = false; - - // - has = HasOrderFlow(); - if (!has) - { - return result; - } - - // - count = CountOrderFlow(); - for (int i = 0; i < count; i++) - { - // - XOBFVGPivot iPivots[]; - int iPivotsCount = orderFlow[i] - .GetSwings(iPivots); - bool hasPivots = IsValidSize(iPivotsCount); - if (hasPivots) - { - // - Copy( - iPivots, - pivots, - false // - ); - } - - // - Clean(iPivots); - } - - // - result = ArraySize(pivots); - - // - return result; + return ArraySize(demandZones); } // - double GetOrderFlowTrendLinePrice( - int barIndex = 0, - ENUM_TIMEFRAMES forPeriod = NULL // - ) + bool HasSupportZones() { - // - double result = 0; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - if (!IsValid(forPeriod)) - { - forPeriod = period; - } - - // - if (!IsValid() || - !HasOrderFlow() || - orderFlowTrend == NULL) - { - return result; - } - - // - datetime time = iTime( - symbol, - forPeriod, - barIndex // - ); - - // - result = ObjectGetValueByTime( - orderFlowTrend.ChartId(), - orderFlowTrend.Name(), - time // - ); - - // - return result; + return HasChild(supportZones); } // - int DetectOrderFlow( - string forSymbol, - ENUM_TIMEFRAMES forPeriod, - ENUM_X_DIRECTION &orderFlowDir, - XPOIState <fState, - XPOIState &htfState, - XPOIState &mtfState, - XPOIState &stfState // - ) + int CountSupportZones() { - // - int result = 0; - - // - Clean(orderFlow); - orderFlowDir = X_DIRECTION_NONE; - - // - bool isValid = - // - IsValid(forSymbol) && - IsValid(forPeriod) && - ltfState.HasChild() && - htfState.HasChild() && - mtfState.HasChild() && - stfState.HasChild() - // - ; - if (!isValid) - { - return result; - } - - // - // Find Working Zone ... - bool hasWorkingZone = IsValid(); - if (!hasWorkingZone) - { - // - symbol = forSymbol; - period = forPeriod; - - // - int idx = -1; - bool has = false; - - // - has = ltfState.HasSupplyZones(); - if (has) - { - // - idx = GetHighest(ltfState.supplyZones); - if (IsValidIndex(idx)) - { - supplyZone = ltfState.supplyZones[idx]; - } - } - - // - has = ltfState.HasDemandZones(); - if (has) - { - // - idx = GetLowest(ltfState.demandZones); - if (IsValidIndex(idx)) - { - demandZone = ltfState.demandZones[idx]; - } - } - - // - hasWorkingZone = HasSupplyZone() && - HasDemandZone(); - if (hasWorkingZone) - { - // - double upper = supplyZone.Lower(); - double lower = demandZone.Upper(); - - // - double delta = ((upper - lower) / 100) * 25; - - // - quarter1 = upper - (1 * delta); - quarter2 = upper - (2 * delta); - quarter3 = upper - (3 * delta); - - // - hasWorkingZone = IsValid(); - } - } - - // - if (!hasWorkingZone) - { - return result; - } - - // - // Bullish OBFVGs ... - XOBFVG bullOBFVGs[]; - int bullOBFVGsCount = ExtractOBFVGZones( - htfState, - mtfState, - stfState, - bullOBFVGs, - X_DIRECTION_BULLISH, - NULL, // For Period ... - // - // Start ... - XZONE_STATE_PASSED, - true, // Force Body Out ... - // - // Activation ... - XZONE_STATE_PASSED, - true, // Force Body In ... - // - // Breaktion ... - XZONE_STATE_FAILED, - false, // Force Body In ... - // - // Works ... - XZONE_STATE_PASSED, - true, // Force Body Out ... - // - true, // Apply Sort ... - true, // From Filter ... - true, // Place Filter ... - // - true, // Ignore Inside in Place Filter ... - // - true, // Detect Inside OB POI(s) ... - true, // Detect Inside FVG POI(s) ... - true // Apply From Filter to Selected POI(s) ... - ); - bool hasBullOBFVGs = IsValidSize(bullOBFVGsCount); - - // - // Bearish OBFVGs ... - XOBFVG bearOBFVGs[]; - int bearOBFVGsCount = ExtractOBFVGZones( - htfState, - mtfState, - stfState, - bearOBFVGs, - X_DIRECTION_BEARISH, - NULL, // For Period ... - // - // Start ... - XZONE_STATE_PASSED, - true, // Force Body Out ... - // - // Activation ... - XZONE_STATE_PASSED, - true, // Force Body In ... - // - // Breaktion ... - XZONE_STATE_FAILED, - false, // Force Body In ... - // - // Works ... - XZONE_STATE_PASSED, - true, // Force Body Out ... - // - true, // Apply Sort ... - true, // From Filter ... - true, // Place Filter ... - // - true, // Ignore Inside in Place Filter ... - // - true, // Detect Inside OB POI(s) ... - true, // Detect Inside FVG POI(s) ... - true // Apply From Filter to Selected POI(s) ... - ); - bool hasBearOBFVGs = IsValidSize(bearOBFVGsCount); - - // - XOBFVG lastBroken; - bool hasBroken = false; - int idx = GetYoungest(brokenOrderFlow); - if (IsValidIndex(idx)) - { - // - lastBroken = brokenOrderFlow[idx]; - hasBroken = lastBroken.IsValid(); - } - - // - bool hasOrderFlow = hasBearOBFVGs || - hasBullOBFVGs; - if (hasOrderFlow) - { - // - // Vlidate ... - isValid = - // - (hasBullOBFVGs && - !hasBearOBFVGs && - bullOBFVGsCount >= 1) - // - || - // - (hasBearOBFVGs && - !hasBullOBFVGs && - bearOBFVGsCount >= 1) - // - ; - - // - if (isValid) - { - // - if (hasBullOBFVGs) - { - // - Copy( - bullOBFVGs, - orderFlow // - ); - } - else if (hasBearOBFVGs) - { - // - Copy( - bearOBFVGs, - orderFlow // - ); - } - - // - orderFlowDir = - hasBullOBFVGs - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - - // - bool isPlacePassed = true; - if (hasBroken) - { - // - bool isBullish = IsBullish(orderFlowDir); - - // - idx = GetYoungest(orderFlow); - bool hasYounget = IsValidIndex(idx); - - // - isPlacePassed = - ArraySize(orderFlow) > 1 - ? true - : isBullish - ? (IsAbove( - orderFlow[idx].ob, - lastBroken.ob, - true // Ignore Inside ... - )) - : (IsBelow( - orderFlow[idx].ob, - lastBroken.ob, - true // Ignore Inside - )); - - // - Clean(brokenOrderFlow); - AddRef( - orderFlow[idx], - brokenOrderFlow // - ); - } - - // - if (!isPlacePassed) - { - // - Clean(orderFlow); - orderFlowDir = X_DIRECTION_NONE; - } - - // - result = ArraySize(orderFlow); - } - } - - // - Clean(bullOBFVGs); - Clean(bearOBFVGs); - - // - lastBroken.Clean(); - - // - if (IsValidSize(result)) - { - // - int count = GetSwings(swings); - bool has = count >= 2; - bool isBullish = IsBullish(orderFlowDir); - if (has) - { - // - // Get Max / Min ... - double max = 0; - double min = 0; - datetime maxAt = NULL; - datetime minAt = NULL; - for (int i = 0; i < count; i++) - { - // - XOBFVGPivot iPivot = swings[i]; - - // - if (!iPivot.IsValid()) - { - // - iPivot.Clean(); - continue; - } - - // - // Min ... - bool canSetMin = - min == 0 - ? true - : min > iPivot.value; - if (canSetMin) - { - // - minAt = iPivot.at; - min = iPivot.value; - } - - // - // Max ... - bool canSetMax = - max == 0 - ? true - : max < iPivot.value; - if (canSetMax) - { - // - maxAt = iPivot.at; - max = iPivot.value; - } - - // - iPivot.Clean(); - } - - // - double price1 = - isBullish - ? min - : max; - double price2 = - isBullish - ? max - : min; - datetime time1 = - isBullish - ? minAt - : maxAt; - datetime time2 = - isBullish - ? maxAt - : minAt; - - // - color clrTrend = clrNONE; - - // - string trendName = - "XORDFLW" + ToString(orderFlowDir) + "_" + "XTRNDL_" + - ToString(period) + "_" + - ToString(price1) + "_" + - ToString(price2) + "_"; - - // - orderFlowTrend = new CChartObjectTrend(); - has = orderFlowTrend.Create( - 0, - trendName, - 0, - time1, - price1, - time2, - price2 // - ); - - // - if (has) - { - // - orderFlowTrend.Width(1); - orderFlowTrend.Color(clrTrend); - orderFlowTrend.RayRight(true); - } - } - } - - // - return result; + return ArraySize(supportZones); } // - void AddOrderFlowItem( - XOBFVG &orderItem // - ) + bool HasResistanceZones() { - // - ENUM_X_DIRECTION trend; - if (!HasOrderFlow(trend)) - { - return; - } - - // - bool isSameDir = orderItem - .GetDirection() == trend; - if (!isSameDir) - { - return; - } - - // - bool isBullish = IsBullish(trend); - - // - AddRef( - orderItem, - orderFlow // - ); - - // - Sort( - orderFlow, - trend, - true // Ignore Inside ... - ); + return HasChild(resistanceZones); } + // + int CountResistanceZones() + { + return ArraySize(resistanceZones); + } + + // + bool HasWaitingZones() + { + return HasChild(waitingZones); + } + + // + int CountWaitingZones() + { + return ArraySize(waitingZones); + } + + // + // + // + // bool IsDestroyed( int barIndex = 0, @@ -817,147 +586,6 @@ struct X121SMCStrategyXWZWorkingZone return result; } - // - bool IsOrderFlowBreaked( - int &breakedIndex, - bool forceOBBreake = false, - bool forceFVGBreake = false, - int barIndex = 0, - ENUM_TIMEFRAMES forPeriod = NULL // - ) - { - // - bool result = false; - - // - breakedIndex = -1; - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - if (!IsValid(forPeriod)) - { - forPeriod = period; - } - - // - ENUM_X_DIRECTION orderFlowDir; - result = HasOrderFlow(orderFlowDir); - if (!result) - { - return result; - } - - // - XOHCL bar; - result = bar.Init( - symbol, - forPeriod, - barIndex // - ); - if (!result) - { - // - bar.Clean(); - return result; - } - - // - bool isBullish = IsBullish(orderFlowDir); - - // - int idx = - isBullish - ? GetHighest(orderFlow) - : GetLowest(orderFlow); - result = IsValidIndex(idx); - if (!result) - { - // - bar.Clean(); - return result; - } - - // - XOHCL obBreakerBar; - bool isOBBodyOut = false; - bool isOBBreaked = orderFlow[idx].ob.IsBreaked( - orderFlowDir, - obBreakerBar, - isOBBodyOut, - false, // Ignore Start ... - false, // Started Bar Body Out ... - forPeriod // - ); - - // - if (!isOBBreaked) - { - obBreakerBar.Clean(); - } - - // - XOHCL fvgBreakerBar; - bool isFVGBodyOut = false; - bool isFVGBreaked = orderFlow[idx].fvg.IsBreaked( - orderFlowDir, - fvgBreakerBar, - isFVGBodyOut, - false, // Ignore Start ... - true, // Started Bar Body Out ... - forPeriod // - ); - - // - if (!isFVGBreaked) - { - fvgBreakerBar.Clean(); - } - - // - isOBBreaked = - obBreakerBar.IsValid(); - - // - isFVGBreaked = - fvgBreakerBar.IsValid(); - - // - if ((forceOBBreake && forceFVGBreake) || - (!forceOBBreake && !forceFVGBreake)) - { - // - result = isOBBreaked || - isFVGBreaked; - } - else if (forceOBBreake) - { - result = isOBBreaked; - } - else if (forceFVGBreake) - { - result = isFVGBreaked; - } - - // - if (result) - { - breakedIndex = idx; - } - - // - bar.Clean(); - obBreakerBar.Clean(); - fvgBreakerBar.Clean(); - - // - return result; - } - // bool DetectPriority( ENUM_X121SMC_XWZ_PRIORITY &priority, @@ -1105,21 +733,448 @@ struct X121SMCStrategyXWZWorkingZone } // - // Order Flow ... - ENUM_X_DIRECTION orderFlowDir; - has = HasOrderFlow(orderFlowDir); + has = HasSupplyZones(); if (has) { // - count = CountOrderFlow(); + count = CountSupplyZones(); for (int i = 0; i < count; i++) { - orderFlow[i].UpdateTo(value); + supplyZones[i].To(value); + } + } + + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + demandZones[i].To(value); + } + } + + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + supportZones[i].To(value); + } + } + + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + resistanceZones[i].To(value); + } + } + + // + has = HasWaitingZones(); + if (has) + { + // + count = CountWaitingZones(); + for (int i = 0; i < count; i++) + { + waitingZones[i].UpdateTo(value); } } // } + + // + void Draw( + XCPOIDrawer *drawer, + bool forceClean = false, + bool drawWaitingZones = true, + bool drawSupplyZone = false, + bool drawDemandZone = false, + bool drawSupplyZones = false, + bool drawDemandZones = false, + bool drawSupportZones = false, + bool drawResistanceZones = false // + ) + { + // + if (drawer == NULL) + { + return; + } + + // + if (forceClean) + { + mObjects.Clear(); + } + + // + int count = 0; + bool has = false; + bool isCreated = false; + + // + ulong chartID = drawer.ChartIdentification(); + int subWindow = drawer.SubWindowIdentification(); + color bullishColor = drawer.BarBullishColor(); + color bearishColor = drawer.BarBearishColor(); + + // + // Supply Zone ... + if (drawSupplyZone) + { + // + has = HasSupplyZone(); + if (has) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + supplyZone, + iObj // + ); + + // + if (isCreated) + { + mObjects.Add(iObj); + } + } + } + + // + // Supply Zones ... + if (drawSupplyZones) + { + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + supplyZones[i], + iObj // + ); + + // + if (isCreated) + { + mObjects.Add(iObj); + } + } + } + } + + // + // Demand Zone ... + if (drawDemandZone) + { + // + has = HasDemandZone(); + if (has) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + demandZone, + iObj // + ); + + // + if (isCreated) + { + mObjects.Add(iObj); + } + } + } + + // + // Demand Zones ... + if (drawDemandZones) + { + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + demandZones[i], + iObj // + ); + + // + if (isCreated) + { + mObjects.Add(iObj); + } + } + } + } + + // + // Support Zones ... + if (drawSupportZones) + { + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + // + XCSupportZoneObject *iObj; + isCreated = drawer.CreateSupportZone( + supportZones[i], + iObj // + ); + + // + if (isCreated) + { + mObjects.Add(iObj); + } + } + } + } + + // + // Resistance Zones ... + if (drawResistanceZones) + { + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + // + XCResistanceZoneObject *iObj; + isCreated = drawer.CreateResistanceZone( + resistanceZones[i], + iObj // + ); + + // + if (isCreated) + { + mObjects.Add(iObj); + } + } + } + } + + // + // Waiting Zones ... + if (drawWaitingZones) + { + // + has = HasWaitingZones(); + if (has) + { + // + count = CountWaitingZones(); + for (int i = 0; i < count; i++) + { + // + XCBaseObject *objects[]; + int objectsCount = drawer.DrawOBFVG( + waitingZones[i], + objects // + ); + has = IsValidSize(objectsCount); + if (has) + { + // + for (int j = 0; j < objectsCount; j++) + { + mObjects.Add(objects[j]); + } + } + } + } + } + + // + // Quarters ... + has = IsValid(); + if (has) + { + // + double zoneUpper = supplyZone.Upper(); + double upper = supplyZone.Lower(); + + // + double lower = demandZone.Upper(); + double zoneLower = demandZone.Lower(); + + // + string prefix = "X121WZone_" + symbol + "_" + ToString(period); + + // + // Zone Upper ... + CChartObjectHLine *zoneUpperLine; + zoneUpperLine = new CChartObjectHLine(); + isCreated = zoneUpperLine.Create( + chartID, + prefix + "_ZoneTop", + subWindow, + zoneUpper // + ); + if (isCreated) + { + // + zoneUpperLine.Color(clrRed); + + // + mObjects.Add(zoneUpperLine); + } + + // + // Zone Lower ... + CChartObjectHLine *zoneLowerLine; + zoneLowerLine = new CChartObjectHLine(); + isCreated = zoneLowerLine.Create( + chartID, + prefix + "_ZoneDown", + subWindow, + zoneLower // + ); + if (isCreated) + { + // + zoneLowerLine.Color(clrRed); + + // + mObjects.Add(zoneLowerLine); + } + + // + // Upper ... + CChartObjectHLine *upperLine; + upperLine = new CChartObjectHLine(); + isCreated = upperLine.Create( + chartID, + prefix + "_Upper", + subWindow, + upper // + ); + if (isCreated) + { + // + upperLine.Color(clrLime); + + // + mObjects.Add(upperLine); + } + + // + // Lower ... + CChartObjectHLine *lowerLine; + lowerLine = new CChartObjectHLine(); + isCreated = lowerLine.Create( + chartID, + prefix + "_Lower", + subWindow, + lower // + ); + if (isCreated) + { + // + lowerLine.Color(clrLime); + + // + mObjects.Add(lowerLine); + } + + // + // Quarters ... + + // + // Quarter 1 ... + CChartObjectHLine *q1Line; + q1Line = new CChartObjectHLine(); + isCreated = q1Line.Create( + chartID, + prefix + "_Q1", + subWindow, + quarter1 // + ); + if (isCreated) + { + // + q1Line.Color(clrYellow); + + // + mObjects.Add(q1Line); + } + + // + // Quarter 2 ... + CChartObjectHLine *q2Line; + q2Line = new CChartObjectHLine(); + isCreated = q2Line.Create( + chartID, + prefix + "_Q2", + subWindow, + quarter2 // + ); + if (isCreated) + { + // + q2Line.Color(clrYellow); + + // + mObjects.Add(q2Line); + } + + // + // Quarter 3 ... + CChartObjectHLine *q3Line; + q3Line = new CChartObjectHLine(); + isCreated = q3Line.Create( + chartID, + prefix + "_Q3", + subWindow, + quarter3 // + ); + if (isCreated) + { + // + q3Line.Color(clrYellow); + + // + mObjects.Add(q3Line); + } + } + } + + // }; // @@ -1135,7 +1190,6 @@ struct X121SMCStrategyXWZSignalConditions // double sl; - double target; double reward; double amountPercent; ENUM_X_DIRECTION dir; @@ -1151,9 +1205,9 @@ struct X121SMCStrategyXWZSignalConditions // double pivot; double point; + double targets[]; // - XOBFVG targetZone; XOBFVG signalZone; // @@ -1177,7 +1231,6 @@ struct X121SMCStrategyXWZSignalConditions { // sl = 0; - target = 0; // dir = X_DIRECTION_NONE; @@ -1282,12 +1335,11 @@ struct X121SMCStrategyXWZSignalConditions point = 0; // - target = 0; reward = 0; amountPercent = 0; // - targetZone.Clean(); + Clean(targets); signalZone.Clean(); // diff --git a/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 b/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 index 2de53677..606f90d4 100644 --- a/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 +++ b/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 @@ -294,20 +294,12 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy signal.pushers = pushers; signal.provider = provider; signal.time = TimeCurrent(); - signal.target = conditions.target; // - bool canReplaceTarget = - signal.target > 0 && - (hasLong - ? signal.target > signal.tp - : signal.target < signal.tp); - if (canReplaceTarget) - { - // - signal.tp = conditions.target; - signal.target = tp; - } + Copy( + conditions.targets, + signal.targets // + ); // result = PrepareSignal(signal); @@ -354,40 +346,6 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy signal.volume = cVolume; } } - - // - // Fix Signal TP Based On Working Zone ... - // double maxAllowedTP = - // hasLong - // ? mXWZConditions.workingZone.upper - // : mXWZConditions.workingZone.lower; - // bool canApplyMaxAlowedTP = (hasLong && - // signal.tp > maxAllowedTP) || - // (!hasLong && signal.tp < maxAllowedTP); - // if (canApplyMaxAlowedTP) - // { - // signal.tp = maxAllowedTP; - // } - - // - // Configuring Global Protector ... - // signal.trailSL = true; - // signal.trailSLStartOnReachTPLevel = 3; - // signal.fullTPLevel = signal.GetRiskRewardRatio(); - - // // - // mXSupDemOBSSignalDetector.RemoveDraws(); - // mXSupDemOBSSignalDetector.DrawConditions( - // mXSupDemOBSConditions, - // mVisionCycleHelper.mPOIDrawer // - // ); - - // // - // mXSupDemOBSSignalDetector.RemoveWorkingZoneDraws(); - // mXSupDemOBSSignalDetector.DrawWorkingZone( - // mXSupDemOBSConditions, - // mVisionCycleHelper.mPOIDrawer // - // ); } // @@ -595,33 +553,9 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy setupDir = mXWZSignalDetector.mConditions.dir; setupTime = mXWZSignalDetector.mConditions.setupTime; - // - if (!isSetuped) - { - // - mXWZSignalDetector.RemoveDraws(); - // mXWZSignalDetector.RemoveWorkingZoneDraws(); - - // - // mXWZSignalDetector.DrawWorkingZone( - // mXWZSignalDetector.mConditions, - // mVisionCycleHelper.mPOIDrawer // - // ); - - // - mXWZSignalDetector.DrawConditions( - mXWZSignalDetector.mConditions, - mVisionCycleHelper.mPOIDrawer // - ); - } - // if (isSetuped) { - // - mXWZSignalDetector.RemoveDraws(); - // mXWZSignalDetector.RemoveWorkingZoneDraws(); - // int items = mXWZSignalDetector .AddConditionsIfNotExists(); @@ -694,22 +628,6 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy // if (canTrigger) { - // - mXWZSignalDetector.RemoveDraws(); - // mXWZSignalDetector.RemoveWorkingZoneDraws(); - - // - // mXWZSignalDetector.DrawWorkingZone( - // mTmpConditions[i], - // mVisionCycleHelper.mPOIDrawer // - // ); - - // - mXWZSignalDetector.DrawConditions( - mTmpConditions[i], - mVisionCycleHelper.mPOIDrawer // - ); - // selectedIndex = i; mConditions = mTmpConditions[i]; @@ -749,7 +667,12 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy conditions.sl = mConditions.sl; conditions.provider = providerStr; conditions.signalDir = mConditions.dir; - conditions.target = mConditions.target; + + // + Copy( + mConditions.targets, + conditions.targets // + ); // xWZConditions = mConditions; @@ -785,7 +708,7 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy // if (mMaxAllowedRequiredPOIs <= 0) { - mMaxAllowedRequiredPOIs = 50; + mMaxAllowedRequiredPOIs = 200; } //