diff --git a/Classes/x-saherelm.x-bar.analyser.class.mq5 b/Classes/x-saherelm.x-bar.analyser.class.mq5 index a6596c5d..6eaacbff 100644 --- a/Classes/x-saherelm.x-bar.analyser.class.mq5 +++ b/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -1763,6 +1763,90 @@ class XCBarAnalyser : public XCBase return result; } + /** + * Check a Bar Has Support or not ... + * + * @param bar: XOHCL instance ... + * @param supportBar: XOHCL instance Specified Support Bar ... + * @param rage: int, + * @return ( bool ) + */ + bool HasSupport( + XOHCL &bar, + XOHCL &supportBar, + int range = 21 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + range; + result = IsValidIndex(barIndex); + if (!result) + { + // + supportBar.Clean(); + return result; + } + result = supportBar.Init( + bar.symbol, + bar.period, + barIndex // + ); + + // + result = supportBar.low < supportBar.GetDown(); + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + double selectedValue = supportBar.GetDown(); + + // + int llIDX = bar.FindLowestIndex(range - 1, MODE_LOW); + result = IsValidIndex(llIDX); + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + double llValue = iLow( + bar.symbol, + bar.period, + llIDX // + ); + + // + result = llValue >= selectedValue; + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + result = supportBar.IsValid(); + + // + return result; + } + /** * Check a Bar is Resistance Bar or not ... * diff --git a/Indicators/x-saherelm.x121.xwz.mq5 b/Indicators/x-saherelm.x121.xwz.mq5 index f1d21441..780dac6d 100644 --- a/Indicators/x-saherelm.x121.xwz.mq5 +++ b/Indicators/x-saherelm.x121.xwz.mq5 @@ -88,6 +88,18 @@ input bool showDownTrend = true; // Show Down Trend input bool showLongReject = true; // Show Long Reject input bool showShortReject = true; // Show Short Reject +// +input bool showPOIs = false; // Draw POI(s) ... +input bool showActivatedPOIs = false; // Draw Activated POI(s) ... +input bool showBullishOrderBlocks = true; // Draw Bullish Order Blocks ... +input bool showBearishOrderBlocks = true; // Draw Bearish Order Blocks ... +input bool showBullishFairValueGaps = true; // Draw Bullish Fair Value Gaps ... +input bool showBearishFairValueGaps = true; // Draw Bearish Fair Value Gaps ... +input bool showSupplyZones = true; // Draw Supply Zones ... +input bool showDemandZones = true; // Draw Demand Zones ... +input bool showSupportZones = true; // Draw Support Zones ... +input bool showResistanceZones = true; // Draw Resistance Zones ... + // #property indicator_chart_window @@ -246,6 +258,9 @@ XCResistanceZone *mXWZActivatedResistanceZones[]; */ int OnInit() { + // + mXWZDrawnObjects.Clear(); + // // Validate Inputs ... if (!ValidateInputs()) @@ -487,20 +502,6 @@ int OnCalculate( // Main Loop ... for (int i = limit - 1; i >= 0 && !IsStopped(); i--) { - // - CalculatedPOIs( - // - i, - prev_calculated, - rates_total, - // - open, - high, - close, - low, - tick_volume // - ); - // CalculateBuffers( // @@ -756,6 +757,20 @@ void CalculateBuffers( bar_index <= barsLimit; if (canCalculate) { + // + CalculatedPOIs( + // + bar_index, + prevCalculated, + ratesTotal, + // + open, + high, + close, + low, + tickVolume // + ); + // CalculateValues( bar_index, @@ -1264,6 +1279,10 @@ void CalculatedPOIs( DetectPOIs(iBar); UpdatePOIs(iBar); DrawPOIs(); + + // + iBar.Clean(); + pBar.Clean(); } // @@ -1272,37 +1291,8 @@ void DetectPOIs( ) { // - // Detect PullBack ... - - // - ENUM_X_DIRECTION pullbackDir; - bool hasPullBack = mXWZBarAnalyser.HasPullBack( - pullbackDir, - bar // - ); - bool hasBullishPullBack = - hasPullBack && - IsBullish(pullbackDir); - bool hasBearishPullBack = - hasPullBack && - IsBearish(pullbackDir); - - // - // Detect PinBar ... - - // - ENUM_X_DIRECTION pinBarDir; - bool hasPinBar = mXWZBarAnalyser.IsPinBar( - bar, - pinBarDir, - 0 // - ); - bool hasBullishPinBar = - hasPinBar && - IsBullish(pinBarDir); - bool hasBearishPinBar = - hasPinBar && - IsBearish(pinBarDir); + int idx = -1; + int range = 21; // // Detect Order Block ... @@ -1348,17 +1338,233 @@ void DetectPOIs( if (!isActivated) { // - Add( + idx = FindIndex( ob, mXWZUnActivatedOBs // ); + if (!IsValidIndex(idx)) + { + // + Add( + ob, + mXWZUnActivatedOBs // + ); + } + } + else + { + // + idx = FindIndex( + ob, + mXWZActivatedOBs // + ); + if (!IsValidIndex(idx)) + { + // + ob.To(activationBar.time); + + // + Add( + ob, + mXWZActivatedOBs // + ); + } } // - obBar.Clean(); activationBar.Clean(); } } + + // + obBar.Clean(); + + // + // Detect Fair Value Gap ... + + // + XOHCL fvgStartBar; + XOHCL fvgEndBar; + XCFVG *fvg; + ENUM_X_DIRECTION fvgDir; + bool hasFVG = mXWZBarAnalyser.HasFairValueGap( + bar, + fvgStartBar, + fvgEndBar, + fvgDir // + ); + bool hasBullishFVG = + hasFVG && + IsBullish(fvgDir); + bool hasBearishFVG = + hasFVG && + IsBearish(fvgDir); + if (hasFVG) + { + // + fvg = new XCFVG(); + bool isInited = fvg.Init( + fvgStartBar, + fvgEndBar, + fvgDir // + ); + if (isInited) + { + // + ENUM_X_DIRECTION forDir = fvg.GetDirection(); + + // + // Check OB Not Activated ... + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = fvg.IsActivated( + forDir, + activationBar, + isActivationBarBodyIn, + false, + _Period // + ); + + // + if (!isActivated) + { + // + idx = FindIndex( + fvg, + mXWZUnActivatedFVGs // + ); + if (!IsValidIndex(idx)) + { + // + Add( + fvg, + mXWZUnActivatedFVGs // + ); + } + } + else + { + // + idx = FindIndex( + fvg, + mXWZActivatedFVGs // + ); + if (!IsValidIndex(idx)) + { + // + fvg.To(activationBar.time); + + // + Add( + fvg, + mXWZActivatedFVGs // + ); + } + } + + // + activationBar.Clean(); + } + } + + // + fvgEndBar.Clean(); + fvgStartBar.Clean(); + + // + // Detect Supply Zone ... + + // + // Detect Deman Zone ... + + // + // Detect Support Zone ... + + // + XOHCL supportBar; + XCSupportZone *supportZone; + bool hasSupport = mXWZBarAnalyser + .HasSupport( + bar, + supportBar, + range // + ); + if (hasSupport) + { + // + supportZone = new XCSupportZone(); + hasSupport = supportZone.Init( + supportBar, + range, + true // Use Range As Start ... + ); + + // + if (hasSupport) + { + // + // Check OB Not Activated ... + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = supportZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + _Period // + ); + + // + if (!isActivated) + { + // + idx = FindIndex( + supportZone, + mXWZUnActivatedSupportZones // + ); + hasSupport = !IsValidIndex(idx); + if (hasSupport) + { + // + Add( + supportZone, + mXWZUnActivatedSupportZones // + ); + } + } + else + { + // + idx = FindIndex( + supportZone, + mXWZActivatedSupportZones // + ); + hasSupport = !IsValidIndex(idx); + if (hasSupport) + { + // + supportZone.To(activationBar.time); + + // + Add( + supportZone, + mXWZActivatedSupportZones // + ); + } + } + + // + activationBar.Clean(); + } + } + + // + supportBar.Clean(); + + // + // Detect Resistance Zone ... + + // } // @@ -1459,7 +1665,7 @@ void UpdatePOIs( // Check OB Not Activated ... XOHCL activationBar; bool isActivationBarBodyIn = false; - bool isActivated = mXWZUnActivatedOBs[i] + bool isActivated = mXWZUnActivatedFVGs[i] .IsActivated( mXWZUnActivatedFVGs[i].GetDirection(), activationBar, @@ -1480,6 +1686,14 @@ void UpdatePOIs( tmps // ); } + else + { + // + Add( + mXWZUnActivatedFVGs[i], + mXWZActivatedFVGs // + ); + } } // @@ -1489,6 +1703,68 @@ void UpdatePOIs( ); } + // + // Support Zones ... + count = ArraySize(mXWZUnActivatedSupportZones); + has = IsValidSize(count); + if (has) + { + // + XCSupportZone *tmps[]; + for (int i = 0; i < count; i++) + { + // + // Update To ... + mXWZUnActivatedSupportZones[i].To(to); + + // + // Check Activation ... + + // + // Check OB Not Activated ... + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = mXWZUnActivatedSupportZones[i] + .IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + _Period // + ); + + // + if (!isActivated) + { + // + Add( + mXWZUnActivatedSupportZones[i], + tmps // + ); + } + else + { + // + mXWZUnActivatedSupportZones[i].To(activationBar.time); + + // + Add( + mXWZUnActivatedSupportZones[i], + mXWZActivatedSupportZones // + ); + } + + // + activationBar.Clean(); + } + + // + Copy( + tmps, + mXWZUnActivatedSupportZones // + ); + } + // } @@ -1501,96 +1777,244 @@ void DrawPOIs() bool isCreated = false; // - mXWZDrawnObjects.Clear(); - - // - // Order Blocks ... - - // - // UnActivated ... - count = ArraySize(mXWZUnActivatedOBs); - has = IsValidSize(count); - if (has) + if (!showPOIs) { - // - for (int i = 0; i < count; i++) - { - // - XCBaseObject *iObj; - isCreated = mXWZPOIDrawer - .CreateOrderBlock( - mXWZUnActivatedOBs[i], - iObj // - ); - if (isCreated) - { - mXWZDrawnObjects.Add(iObj); - } - } + return; } // - // Activated ... - count = ArraySize(mXWZActivatedOBs); - has = IsValidSize(count); - if (has) + // Order Blocks ... + bool showOrderBlocks = + showBullishOrderBlocks || + showBearishOrderBlocks; + if (showOrderBlocks) { // - for (int i = 0; i < count; i++) + // UnActivated ... + count = ArraySize(mXWZUnActivatedOBs); + has = IsValidSize(count); + if (has) { // - XCOrderBlock *iOB = mXWZActivatedOBs[i]; - - // - bool isBullish = iOB.IsBullish(); - - // - XCBaseObject *iObj; - isCreated = mXWZPOIDrawer - .CreateOrderBlock( - iOB, - iObj // - ); - if (isCreated) + for (int i = 0; i < count; i++) { // - if (isBullish) - { - ((XCBullishOrderBlockObject *)iObj).ZoneFill(true); - } - else - { - ((XCBearishOrderBlockObject *)iObj).ZoneFill(true); - } + bool isBullish = mXWZUnActivatedOBs[i].IsBullish(); // - mXWZDrawnObjects.Add(iObj); + if ((isBullish && + showBullishOrderBlocks) || + (!isBullish && + showBearishOrderBlocks)) + { + // + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateOrderBlock( + mXWZUnActivatedOBs[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + + // + // Activated ... + count = ArraySize(mXWZActivatedOBs); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iOB = mXWZActivatedOBs[i]; + + // + bool isBullish = iOB.IsBullish(); + + // + if (showActivatedPOIs && + ((isBullish && + showBullishOrderBlocks) || + (!isBullish && + showBearishOrderBlocks))) + { + // + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateOrderBlock( + iOB, + iObj // + ); + if (isCreated) + { + // + // if (isBullish) + // { + // ((XCBullishOrderBlockObject *)iObj).ZoneFill(true); + // } + // else + // { + // ((XCBearishOrderBlockObject *)iObj).ZoneFill(true); + // } + + // + mXWZDrawnObjects.Add(iObj); + } + } } } } // // Fair Value Gaps ... - count = ArraySize(mXWZUnActivatedFVGs); - has = IsValidSize(count); - if (has) + bool showOrderFairValueGaps = + showBullishFairValueGaps || + showBearishFairValueGaps; + if (showOrderFairValueGaps) { // - for (int i = 0; i < count; i++) + // UnActivated ... + count = ArraySize(mXWZUnActivatedFVGs); + has = IsValidSize(count); + if (has) { // - XCBaseObject *iObj; - isCreated = mXWZPOIDrawer - .CreateFairValueGap( - mXWZUnActivatedFVGs[i], - iObj // - ); - if (isCreated) + for (int i = 0; i < count; i++) { - mXWZDrawnObjects.Add(iObj); + // + bool isBullish = mXWZUnActivatedFVGs[i].IsBullish(); + + // + if ((isBullish && + showBullishFairValueGaps) || + (!isBullish && + showBearishFairValueGaps)) + { + // + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateFairValueGap( + mXWZUnActivatedFVGs[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + + // + // Activated ... + count = ArraySize(mXWZActivatedFVGs); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iFVG = mXWZActivatedFVGs[i]; + + // + bool isBullish = iFVG.IsBullish(); + + // + if (showActivatedPOIs && + ((isBullish && + showBullishFairValueGaps) || + (!isBullish && + showBearishFairValueGaps))) + { + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateFairValueGap( + iFVG, + iObj // + ); + if (isCreated) + { + // + // if (isBullish) + // { + // ((XCBullishOrderBlockObject *)iObj).ZoneFill(true); + // } + // else + // { + // ((XCBearishOrderBlockObject *)iObj).ZoneFill(true); + // } + + // + mXWZDrawnObjects.Add(iObj); + } + } } } } + + // + // Support Zones ... + if (showSupportZones) + { + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedSupportZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZoneObject *iObj; + isCreated = mXWZPOIDrawer + .CreateSupportZone( + mXWZUnActivatedSupportZones[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + + // + // Activated ... + if (showActivatedPOIs) + { + // + count = ArraySize(mXWZActivatedSupportZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZoneObject *iObj; + isCreated = mXWZPOIDrawer + .CreateSupportZone( + mXWZActivatedSupportZones[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + } + + // } // \ No newline at end of file diff --git a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 index 6b971a7d..cc8b9cee 100644 --- a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -22,6 +22,7 @@ // // Imports ... #include "../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../Libraries/x-saherelm.xobfvg.lib.mq5" // // Extensions ... @@ -2435,1292 +2436,6 @@ int FilterZones( // // -/** - * 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); -} - -// -// -// - /** * Check Trading Conditions based on Specified Box ... * diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index bda99aab..89b3e285 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -3612,7 +3612,8 @@ class XCSupportZone : public XCBarZone */ bool Init( XOHCL &bar, - int range = 0 // + int range = 0, + bool useRangeAsStart = false // ) { // @@ -3647,7 +3648,10 @@ class XCSupportZone : 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)); // @@ -6323,588 +6327,3 @@ struct XBoxZone }; // -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); - } - } - } -}; - -// \ No newline at end of file diff --git a/Libraries/x-saherelm.xobfvg.lib.mq5 b/Libraries/x-saherelm.xobfvg.lib.mq5 new file mode 100644 index 00000000..a0fca88a --- /dev/null +++ b/Libraries/x-saherelm.xobfvg.lib.mq5 @@ -0,0 +1,1898 @@ +/////////////////////////////////////////////////////// +// +// 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); +} + +//