/////////////////////////////////////////////////////// // // 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 "../Libraries/x-saherelm.x-poi.state.lib.mq5" // #include // // Implementation ... // // POI Detector Class ... class XCPOIDetector : public XCBaseAlert { // public: // // // 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 // ); // mBarAnalyser = new XCBarAnalyser(); // // 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 Required POI(s) allowed to Holds ... * * @return ( int ) */ int MaxRequiredPOIs() { return mMaxRequiredPOIs; } /** * Set Max Required POI(s) allowed to Holds ... * * @param value: int ... */ void MaxRequiredPOIs(int value) { // if (value < 0) { value = 5; } // mMaxRequiredPOIs = value; } /** * Get Max Allowed Loopback for POI(s) Detection on Initialization Process ... * * @return ( int ) */ int MaxAllowedLoopbackForInit() { return maxAllowedLoopbackForInit; } /** * Set Max Allowed Loopback for POI(s) Detection on Initialization Process ... * * @param value: int ... */ void MaxAllowedLoopbackForInit(int value) { // if (value < 0) { value = 578; } // maxAllowedLoopbackForInit = value; } /** * Get Swing Range Validation ... * * @return ( int ) */ int SwingRange() { return mSwingRange; } /** * Set Swing Range Validation ... * * @param value: int ... */ void SwingRange(int value) { // if (value < 1) { value = 1; } // mSwingRange = value; } /** * Get Momentum Bar Detection Extends Range ... * * @return ( int ) */ int MomentumExtend() { return mMomentumExtend; } /** * Set Momentum Bar Detection Extends Range ... * * @param value: int ... */ void MomentumExtend(int value) { // if (value < 0) { value = 0; } // mMomentumExtend = value; } /** * Get Momentum Bar Detection Body Percent ... * * @return ( double ) */ double MomentumBodyPercent() { return mMomentumBodyPercent; } /** * Set Momentum Bar Detection Body Percent ... * * @param value: double ... */ void MomentumBodyPercent(double value) { // if (value < 50) { value = 50; } // if (value > 100) { value = 100; } // mMomentumBodyPercent = value; } /** * Get Rejection Bar Detection Extends Range ... * * @return ( int ) */ int RejectionExtend() { return mRejectionExtend; } /** * Set Rejection Bar Detection Extends Range ... * * @param value: int ... */ void RejectionExtend(int value) { // if (value < 0) { value = 0; } // mRejectionExtend = value; } /** * Get Rejection Bar Detection Shadow Percent ... * * @return ( double ) */ double RejectionShadowPercent() { return mRejectionShadowPercent; } /** * Set Rejection Bar Detection Shadow Percent ... * * @param value: double ... */ void RejectionShadowPercent(double value) { // if (value < 50) { value = 50; } // if (value > 100) { value = 100; } // mRejectionShadowPercent = value; } /** * Get Support and Resistance Detection Range ... * * @return ( int ) */ int SupResRange() { return mSupResRange; } /** * Set Support and Resistance Detection Range ... * * @param value: int ... */ void SupResRange(int value) { // if (value < 0) { value = 0; } // mSupResRange = value; } /** * Get use Support and Resistance Range as Start ... * * @return ( bool ) */ bool SupResRangeAsStart() { return mSupResRangeAsStart; } /** * 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 OrderBlockSameBars() { return mOrderBlockSameBars; } /** * Set OrderBlock Detection Same Bars ... * * @param value: int ... */ void OrderBlockSameBars(int value) { // if (value < 2) { value = 2; } // mOrderBlockSameBars = value; } /** * Get FairValueGap Detection Same Bars ... * * @return ( int ) */ int FairValueGapSameBars() { return mFairValueGapSameBars; } /** * Set FairValueGap Detection Same Bars ... * * @param value: int ... */ void FairValueGapSameBars(int value) { // if (value < 2) { value = 2; } // mFairValueGapSameBars = value; } /** * Get Minimum Length of Cnsolidation Zone ... * * @return ( int ) */ int ConsolidationZoneMinLoopback() { return mConsolidationZoneMinLoopback; } /** * Set Minimum Length of Cnsolidation Zone ... * * @param value: int ... */ void ConsolidationZoneMinLoopback(int value) { // if (value < 1) { value = 1; } // mConsolidationZoneMinLoopback = value; } /** * Get Consolidation Zone Range in Point ... * * @return ( double ) */ double ConsolidationZoneRangeInPoint() { return mConsolidationZoneRangeInPoint; } /** * Set Consolidation Zone Range in Point ... * * @param value: double */ void ConsolidationZoneRangeInPoint(double value) { // if (value < 50) { value = 50; } // mConsolidationZoneRangeInPoint = value; } /** * Get Consolidation Zone Upper Applied To ... * * @return ( ENUM_APPLIED_PRICE ) */ ENUM_APPLIED_PRICE ConsolidationZonesLowerAppliedTo() { return mConsolidationZonesLowerAppliedTo; } /** * Set Consolidation Zone Upper Applied To ... * * @param value: ENUM_APPLIED_PRICE */ void ConsolidationZonesLowerAppliedTo(ENUM_APPLIED_PRICE value = PRICE_LOW) { mConsolidationZonesLowerAppliedTo = value; } /** * Get Consolidation Zone Lower Applied To ... * * @return ( ENUM_APPLIED_PRICE ) */ ENUM_APPLIED_PRICE ConsolidationZonesUpperAppliedTo() { return mConsolidationZonesUpperAppliedTo; } /** * Set Consolidation Zone Lower Applied To ... * * @param value: ENUM_APPLIED_PRICE */ void ConsolidationZonesUpperAppliedTo(ENUM_APPLIED_PRICE value = PRICE_HIGH) { mConsolidationZonesUpperAppliedTo = value; } // // Actions ... /** * Apply Default Configurations ... */ virtual void Default() { // // Default Props ... SwingRange(3); SupResRange(21); MomentumExtend(1); RejectionExtend(1); MaxRequiredPOIs(100); OrderBlockSameBars(3); FairValueGapSameBars(3); MomentumBodyPercent(70); SupResRangeAsStart(true); RejectionShadowPercent(70); MaxAllowedLoopbackForInit(578); ConsolidationZoneMinLoopback(5); ConsolidationZoneRangeInPoint(50); ConsolidationZonesLowerAppliedTo(PRICE_LOW); ConsolidationZonesUpperAppliedTo(PRICE_HIGH); } /** * Add Event Listener ... * * @param listener: TOnPOIEvent instance ... */ void AddEventListener(TOnPOIEvent listener) { // Add( listener, mEventListeners // ); } /** * Initialize Instance ... */ void Init( int barIndex = 0, bool ignoreMaxAllowed = true // ) { // 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 ... DetectSwing( iBar, iEvent, false // ); // // Rejection Bar ... DetectRejectionBar( iBar, iEvent, false // ); // // Momentum Bar ... DetectMomentumBar( iBar, iEvent, false // ); // // Support ... DetectSupportZone( iBar, iEvent, false // ); // // Demand ... DetectDemandZone( iBar, iEvent, false // ); // // Resistance ... DetectResistanceZone( iBar, iEvent, false // ); // // Supply ... DetectSupplyZone( iBar, iEvent, false // ); // // OrderBlock ... DetectOrderBlock( iBar, iEvent, false // ); // // FairValueGap ... DetectFairValueGap( iBar, iEvent, false // ); // // Consolidation Zone ... DetectConsolidationZone( iBar, iEvent, false // ); // canContinue = has && index >= 0; // iBar.Clean(); } // ReverseCollections(); // mLock = false; } /** * Update POI(s) ... * @param events: ENUM_XPOI_EVENTS member Collection ... */ void Update( ENUM_XPOI_EVENTS &events[], int barIndex = 0 // ) { // if (barIndex < 0) { barIndex = 0; } // Clean(events); // if (mLock) { return; } // // Check Bar Tracker if Waits ... if (!mBarTracker.IsNewBar()) { return; } // mLock = true; // XOHCL iBar; bool has = iBar.Init( mSymbol, mPeriod, barIndex // ); // if (!has) { // iBar.Clean(); // return; } // int count = 0; ENUM_XPOI_EVENTS iEvent = X_POI_EVENT_NONE; // // Swings ... has = DetectSwing( iBar, iEvent // ); if (has) { // Add( iEvent, events // ); // XCBasePOI *item = NULL; XCSwing *iSwing = NULL; if (iEvent == X_SWING_LOW_DETECTED) { // has = GetLastItem( iSwing, mSwingLows // ); } else if (iEvent == X_SWING_HIGH_DETECTED) { // has = GetLastItem( iSwing, mSwingHighs // ); } if (has) { item = (XCBasePOI *)iSwing; } // has = item != NULL; if (has) { // NotifyEventListeners( iEvent, item // ); } } // // Momentum Bar ... has = DetectMomentumBar( iBar, iEvent // ); if (has) { // Add( iEvent, events // ); // 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( iEvent, item // ); } } // // Rejection Bar ... has = DetectRejectionBar( iBar, iEvent // ); if (has) { // Add( iEvent, events // ); // 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( iEvent, item // ); } } // // Support ... has = DetectSupportZone( iBar, iEvent // ); if (has) { // Add( iEvent, events // ); // XCBasePOI *item = NULL; XCSupportZone *iZone = NULL; has = GetLastItem( iZone, mSupportZones // ); if (has) { item = (XCBasePOI *)iZone; } // has = item != NULL; if (has) { // NotifyEventListeners( iEvent, item // ); } } // // Demand ... has = DetectDemandZone( iBar, iEvent // ); if (has) { // Add( iEvent, events // ); // XCBasePOI *item = NULL; XCDemandZone *iZone = NULL; has = GetLastItem( iZone, mDemandZones // ); if (has) { item = (XCBasePOI *)iZone; } // has = item != NULL; if (has) { // NotifyEventListeners( iEvent, item // ); } } // // Resistance ... has = DetectResistanceZone( iBar, iEvent // ); if (has) { // Add( iEvent, events // ); // XCBasePOI *item = NULL; XCResistanceZone *iZone = NULL; has = GetLastItem( iZone, mResistanceZones // ); if (has) { item = (XCBasePOI *)iZone; } // has = item != NULL; if (has) { // 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 // ); } else if (iEvent == X_BEARISH_ORDERBLOCK_DETECTED) { // has = GetLastItem( iZone, mBearishOrderBlocks // ); } if (has) { item = (XCBasePOI *)iZone; } // has = item != NULL; if (has) { // NotifyEventListeners( iEvent, item // ); } } // // FairValueGap ... has = DetectFairValueGap( iBar, iEvent // ); if (has) { // Add( iEvent, events // ); // XCBasePOI *item = NULL; XCFVG *iZone = NULL; if (iEvent == X_BULLISH_FVG_DETECTED) { // has = GetLastItem( iZone, mBullishFairValueGaps // ); } else if (iEvent == X_BEARISH_FVG_DETECTED) { // has = GetLastItem( iZone, mBearishFairValueGaps // ); } if (has) { item = (XCBasePOI *)iZone; } // has = item != NULL; if (has) { // NotifyEventListeners( iEvent, item // ); } } // has = DetectConsolidationZone( iBar, iEvent // ); if (has) { // Add( iEvent, events // ); } // iBar.Clean(); mLock = false; // mBarTracker.Waits(); // if (HasChild(events)) { CleanupUnusedCollections(); } } /** * 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( mSwings, state.swings // ); // Copy( mSwingHighs, state.swingHighs // ); // Copy( mSwingLows, state.swingLows // ); // Copy( mMomentumBars, state.momentumBars // ); // Copy( mBullishMomentumBars, state.bullishMomentumBars // ); // Copy( mBearishMomentumBars, state.bearishMomentumBars // ); // Copy( mRejectionBars, state.rejectionBars // ); // 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( mOrderBlocks, state.orderBlocks // ); // Copy( mBullishOrderBlocks, state.bullishOrderBlocks // ); // Copy( mBearishOrderBlocks, state.bearishOrderBlocks // ); // Copy( mFairValueGaps, state.fairValueGaps // ); // Copy( mBullishFairValueGaps, state.bullishFairValueGaps // ); // Copy( mBearishFairValueGaps, state.bearishFairValueGaps // ); // Copy( mConsolidationZones, state.consolidationZones // ); // Copy( mBullishConsolidationZones, state.bullishConsolidationZones // ); // Copy( mBearishConsolidationZones, state.bearishConsolidationZones // ); // } /** * Destroy Instance ... */ void Destroy() { // mBarTracker.Clean(); ZeroMemory(mBarAnalyser); // CleanCollections(); } // // // // // // /** * Detect Swing Bars ... * * @param bar: XOHCL instance ... * @param reversal: boolean reversal add to collection ... * * @return ( bool ) */ bool DetectSwing( 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.IsSwing( bar, iDir, mSwingRange // ); // result = result && HasDirection(iDir); if (!result) { return result; } // 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) { return result; } // // 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) { 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; } // activationBar.Clean(); } // // Add ... // int idx = FindIndex( supportZone, mSupportZones // ); result = !IsValidIndex(idx); if (!result) { // supportBar.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(); // 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; } // activationBar.Clean(); } // // Add ... // int idx = FindIndex( resistanceZone, mResistanceZones // ); result = !IsValidIndex(idx); if (!result) { // resistanceBar.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(); // 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; } // activationBar.Clean(); } // // Add ... // int idx = FindIndex( supplyZone, mSupplyZones // ); result = !IsValidIndex(idx); if (!result) { // supplyBar.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(); // 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; } // activationBar.Clean(); } // // Add ... // int idx = FindIndex( demandZone, mDemandZones // ); result = !IsValidIndex(idx); if (!result) { // demandBar.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(); // 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; } // activationBar.Clean(); } // int idx = FindIndex( ob, mOrderBlocks // ); result = !IsValidIndex(idx); if (!result) { // obBar.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(); // 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; } // activationBar.Clean(); } // int idx = FindIndex( fvg, mFairValueGaps // ); result = !IsValidIndex(idx); if (!result) { // ZeroMemory(fvg); fvgEndBar.Clean(); fvgStartBar.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(); // return result; } /** * Detect Consolidation Zones ... * * @param bar: XOHCL instance ... * @param reversal: boolean reversal add to collection ... * * @return ( bool ) */ bool DetectConsolidationZone( XOHCL &bar, ENUM_XPOI_EVENTS &state, bool reversal = false // ) { // bool result = false; // state = X_POI_EVENT_NONE; // XConsolidationZone cZone; result = mBarAnalyser.HasConsolidationZone( bar, cZone, mConsolidationZoneMinLoopback, mConsolidationZoneRangeInPoint, mConsolidationZonesUpperAppliedTo, mConsolidationZonesLowerAppliedTo // ); if (!result) { // cZone.Clean(); // return result; } // // Add ... // bool isBullish = IsBullish(cZone.dir); bool isBearish = IsBearish(cZone.dir); // int idx = FindIndex( cZone, mConsolidationZones // ); result = !IsValidIndex(idx); if (!result) { // cZone.Clean(); // return result; } // if (reversal) { // ArrayReverse(mConsolidationZones); // AddRef( cZone, mConsolidationZones // ); // ArrayReverse(mConsolidationZones); } else { // AddRef( cZone, mConsolidationZones // ); } // if (isBullish) { // // Add Swings ... if (reversal) { // ArrayReverse(mBullishConsolidationZones); // AddRef( cZone, mBullishConsolidationZones // ); // ArrayReverse(mBullishConsolidationZones); } else { // AddRef( cZone, mBullishConsolidationZones // ); } } else if (isBearish) { // // Add Swings ... if (reversal) { // ArrayReverse(mBearishConsolidationZones); // AddRef( cZone, mBearishConsolidationZones // ); // ArrayReverse(mBearishConsolidationZones); } else { // AddRef( cZone, mBearishConsolidationZones // ); } } // state = IsBullish(cZone.dir) ? X_BULLISH_CONSOLIDATION_ZONE_DETECTED : X_BEARISH_CONSOLIDATION_ZONE_DETECTED; // cZone.Clean(); // return result; } // protected: // // void CleanCollections() { // Clean(mSwings); Clean(mSwingLows); Clean(mSwingHighs); Clean(mDemandZones); Clean(mSupplyZones); Clean(mOrderBlocks); Clean(mMomentumBars); Clean(mSupportZones); Clean(mRejectionBars); Clean(mFairValueGaps); Clean(mEventListeners); Clean(mResistanceZones); Clean(mBullishOrderBlocks); Clean(mBearishOrderBlocks); Clean(mConsolidationZones); Clean(mBullishMomentumBars); Clean(mBearishMomentumBars); Clean(mBullishRejectionBars); Clean(mBearishRejectionBars); Clean(mBullishFairValueGaps); Clean(mBearishFairValueGaps); Clean(mBullishConsolidationZones); Clean(mBearishConsolidationZones); } // void ReverseCollections() { // ArrayReverse(mSwings); ArrayReverse(mSwingLows); ArrayReverse(mSwingHighs); ArrayReverse(mDemandZones); ArrayReverse(mSupplyZones); ArrayReverse(mOrderBlocks); ArrayReverse(mMomentumBars); ArrayReverse(mSupportZones); ArrayReverse(mRejectionBars); ArrayReverse(mFairValueGaps); ArrayReverse(mEventListeners); ArrayReverse(mResistanceZones); ArrayReverse(mBullishOrderBlocks); ArrayReverse(mBearishOrderBlocks); ArrayReverse(mConsolidationZones); ArrayReverse(mBullishMomentumBars); ArrayReverse(mBearishMomentumBars); ArrayReverse(mBullishRejectionBars); ArrayReverse(mBearishRejectionBars); ArrayReverse(mBullishFairValueGaps); ArrayReverse(mBearishFairValueGaps); ArrayReverse(mBullishConsolidationZones); ArrayReverse(mBearishConsolidationZones); } // void CleanupUnusedCollections( int maxAllowed = 0 // ) { // maxAllowed = MaxRequiredPOIs(); // if (maxAllowed <= 0) { return; } // CleanupArray( mEventListeners, maxAllowed // ); // CleanupArray( mSwings, maxAllowed // ); // CleanupArray( mSwingLows, maxAllowed // ); // CleanupArray( mSwingHighs, maxAllowed // ); // CleanupArray( mMomentumBars, maxAllowed // ); // CleanupArray( mBullishMomentumBars, maxAllowed // ); // CleanupArray( mBearishMomentumBars, maxAllowed // ); // CleanupArray( mRejectionBars, maxAllowed // ); // CleanupArray( mBullishRejectionBars, maxAllowed // ); // CleanupArray( mBearishRejectionBars, maxAllowed // ); // CleanupArray( mSupportZones, maxAllowed // ); // CleanupArray( mDemandZones, maxAllowed // ); // CleanupArray( mSupplyZones, maxAllowed // ); // CleanupArray( mResistanceZones, maxAllowed // ); // CleanupArray( mFairValueGaps, maxAllowed // ); // CleanupArray( mBullishFairValueGaps, maxAllowed // ); // CleanupArray( mBearishFairValueGaps, maxAllowed // ); // CleanupArray( mOrderBlocks, maxAllowed // ); // CleanupArray( mBullishOrderBlocks, maxAllowed // ); // CleanupArray( mBearishOrderBlocks, maxAllowed // ); // CleanupArray( mConsolidationZones, maxAllowed // ); // CleanupArray( mBullishConsolidationZones, maxAllowed // ); // CleanupArray( mBearishConsolidationZones, maxAllowed // ); // } /** * 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 // ); } } // private: // // // Props ... string mSymbol; // Market Symbol ... ENUM_TIMEFRAMES mPeriod; // Market Period ... XBarTracker mBarTracker; // Market Bar Tracker ... XCBarAnalyser *mBarAnalyser; // Bar Analyser ... // 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 ... // int mConsolidationZoneMinLoopback; // Minimum Length of Cnsolidation Zone ... double mConsolidationZoneRangeInPoint; // Consolidation Zone Range in Point ... XConsolidationZone mConsolidationZones[]; // Holds Founded Consolidation Zones ... XConsolidationZone mBullishConsolidationZones[]; // Holds Founded Bullish Consolidation Zones ... XConsolidationZone mBearishConsolidationZones[]; // Holds Founded Bearish Consolidation Zones ... ENUM_APPLIED_PRICE mConsolidationZonesLowerAppliedTo; // Consolidation Zone Upper Applied To ... ENUM_APPLIED_PRICE mConsolidationZonesUpperAppliedTo; // Consolidation Zone Lower Applied To ... // }; //