From 70876676f56445a9991c3838148c18755dff0cd4 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Tue, 20 May 2025 21:48:12 +0330 Subject: [PATCH] last ... --- Classes/x-saherelm.x-bar.analyser.class.mq5 | 841 ++-- Classes/x-saherelm.x-cobject.class.mq5 | 18 +- Classes/x-saherelm.x-poi.drawer.class.mq5 | 28 +- Documents/BKP/sample.mq5 | 780 ++++ Documents/BKP/xcaea.trigger.block.lib.mq5 | 4122 +++++++++++++++++++ Experts/test.mq5 | 173 +- XCAEA/Libraries/xcaea.trigger.block.lib.mq5 | 1359 +++--- 7 files changed, 5904 insertions(+), 1417 deletions(-) create mode 100644 Documents/BKP/sample.mq5 create mode 100644 Documents/BKP/xcaea.trigger.block.lib.mq5 diff --git a/Classes/x-saherelm.x-bar.analyser.class.mq5 b/Classes/x-saherelm.x-bar.analyser.class.mq5 index e82603b4..b241cb04 100644 --- a/Classes/x-saherelm.x-bar.analyser.class.mq5 +++ b/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -26,6 +26,44 @@ // // Definitions ... +// +// Extensions ... +void FillLiquidity( + XOHCL &lBar, + ENUM_X_DIRECTION lDir, + XBoxZone &lq, + datetime to // +) +{ + // + // Normalize Args ... + lq.Clean(); + to = NormalizeTime(to); + + // + // Validate Args ... + bool has = lBar.IsValid() && + HasDirection(lDir); + if (!has) + { + return; + } + + // + lq.to = to; + lq.dir = lDir; + lq.type = "XLQ"; + lq.from = lBar.time; + lq.symbol = lBar.symbol; + lq.period = lBar.period; + lq.upper = IsBullish(lDir) + ? lBar.GetDown() + : lBar.high; + lq.lower = IsBullish(lDir) + ? lBar.low + : lBar.GetUp(); +} + // // Implementations ... class XCBarAnalyser : public XCBase @@ -2040,20 +2078,45 @@ class XCBarAnalyser : public XCBase return result; } + /** + * Check a Bar is a Trigger Box or Not ... + * + * @param bar: XOHCL instance Referernce, Specified Start Bar to Check ... + * @param trigger: XBoxZone instance Reference, Holds Detected Trigger Bar ... + * @param ob: XBoxZone instance Reference, Holds Detected Trigger Bar's OB ... + * @param fvg: XBoxZone instance Reference, Holds Detected Trigger Bar's FVG ... + * @param rLiquidity: XBoxZone instance Reference, Holds Detected Trigger Bar's Reversal Side Liquidity ... + * @param fLiquidity: XBoxZone instance Reference, Holds Detected Trigger Bar's Following Side Liquidity ... + * @param swingBar: XOHCL instance Referernce, Holds Detected Trigger Bar's Swing ... + * @param loopback: int, Loopback Bars Count ... + * @param maxAllowedRange: double, Max Allowed Trigger's OB Range ... + * @param minAllowedBlockEdgeLength: int, Min Allowed Block Edge Validation Length ... + * @param forceOBOppositBar: bool, Force OB to Start by Opposite Bar ... + * @param forceFVGBarType: bool, Force FVG to Has Same Bar Type ... + * @param forceGapBarBreakout: bool, Force Gap Bar Breakout OB Edge ... + * @param forceHasSwingBar: bool, Force Has Swing Bar ... + * @param forceHasLiquidity: bool, Force Has Following Liquidity ... + * @param forceHasReversalLiquidity: bool, Force Has Reversal Liquidity ... + * + * @return ( bool ) + */ bool IsTrigger( XOHCL &bar, - XBoxZone &box, + XBoxZone &trigger, XBoxZone &ob, XBoxZone &fvg, - XBoxZone &liquidity, + XBoxZone &rLiquidity, + XBoxZone &fLiquidity, XOHCL &swingBar, int loopback = 10, - bool forceLiquidity = true, - bool forceLiquidityUsed = true, - bool forceEntryBar = true, - bool forceEntryBarPower = true, - bool forceFVGBarType = false, - bool forceOBTwoBar = false // + double maxAllowedRange = 0.0, + int minAllowedBlockEdgeLength = 0, + bool forceOBOppositBar = true, + bool forceFVGBarType = true, + bool forceGapBarBreakout = true, + bool forceHasSwingBar = true, + bool forceHasLiquidity = true, + bool forceHasReversalLiquidity = true // ) { // @@ -2063,9 +2126,10 @@ class XCBarAnalyser : public XCBase // Normalize Args ... ob.Clean(); fvg.Clean(); - box.Clean(); + trigger.Clean(); swingBar.Clean(); - liquidity.Clean(); + rLiquidity.Clean(); + fLiquidity.Clean(); loopback = NormalizeInt(loopback, 5); // @@ -2077,429 +2141,171 @@ class XCBarAnalyser : public XCBase } // - XOHCL pBar; // Previous of Provided Bar ... - XOHCL iBar; - XOHCL iPBar; - int barIndex; - int pBarIndex; - ENUM_X_DIRECTION iDir; + XOHCL pBar; + XOHCL tmpBar; + XOHCL tmpPBar; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; // result = bar.GetPreviousBar(pBar); - if (!result) + + // + // Detect Base Order Block ... + result = + result && + // + // Order Block Detection ... + IsOB( + pBar, + ob, + forceFVGBarType, + forceOBOppositBar // + ) && + // + // Gap Detection ... + IsFVG( + pBar, + fvg, + forceFVGBarType // + ); + if (result) { // - ob.Clean(); - fvg.Clean(); - box.Clean(); - pBar.Clean(); - iBar.Clean(); - iPBar.Clean(); - swingBar.Clean(); - liquidity.Clean(); - - // - return result; + trigger = ob; + trigger.type = "XTRG"; } // - barIndex = bar.Index(); - pBarIndex = pBar.Index(); + // Reading Requirements ... // - // Loopback to Find a Block ... - for (int i = pBarIndex; i < pBarIndex + loopback; i++) + double points = GetPoints(bar.symbol); + + // + bool isBullish = ob.IsBullish(); + bool isBearish = ob.IsBearish(); + + // + int toIDX = trigger.ToIndex(); + int fromIDX = trigger.FromIndex(); + + // + // Validate Gaps Bar Breakeout ... + if (result && + forceGapBarBreakout) { // - // Inital IBar ... - result = iBar.Init( - bar.symbol, - bar.period, - i // - ); - if (!result) - { - break; - } + // Extract Gap Bar ... + tmpBar.Clean(); + tmpPBar.Clean(); + result = + // + // Retrieve Bars ... + fvg.ToBar(tmpBar) && + tmpBar.GetPreviousBar(tmpPBar) && + // + // Validate Gap Bar is Momentum Bar ... + IsMomentum( + tmpPBar, + iDir, + 1 // + ) && + iDir == fvg.dir && + // + // Validate ... + (isBullish + ? tmpPBar.close > ob.upper + : tmpPBar.close < ob.lower); // - // Detect Block ... - result = IsOB( - iBar, - ob, - forceFVGBarType, - forceOBTwoBar // - ); + tmpBar.Clean(); + tmpPBar.Clean(); + } + + // + // Validate Range ... + if (result && + maxAllowedRange > 0) + { + // + double range = ob.GetRange(); + result = range <= (maxAllowedRange * points); + } + + // + // Validating Swing Bar ... + if (result && + forceHasSwingBar) + { + // + int swingIDX = -1; + result = ob.FromBar(tmpBar); if (result) { // - // Validate Block Last Bars ... - XOHCL fromBar; - XOHCL fromBarPrev; - result = ob.FromBar(fromBar); - result = - result && - fromBar.GetPreviousBar(fromBarPrev); - result = - result && - (ob.IsBullish() - ? fromBarPrev.IsBearish() - : fromBarPrev.IsBullish()); + // Detect Swing Bar Index ... + if (isBullish) + { + swingIDX = tmpBar.FindLowestIndex(loopback, MODE_LOW); + } + else if (isBearish) + { + swingIDX = tmpBar.FindHighestIndex(loopback, MODE_HIGH); + } + result = IsValidIndex(swingIDX); if (result) { // - // Detect FVG ... - result = IsFVG( - iBar, - fvg, - forceFVGBarType // + // Initialize Swing Bar ... + result = swingBar.Init( + bar.symbol, + bar.period, + swingIDX // ); - if (result) - { - // - box.Clone(ob); - box.type = "XTRG"; - box.from = fromBarPrev.time; - break; - } } // - fromBar.Clean(); - fromBarPrev.Clean(); - } - - // - iBar.Clean(); - } - iBar.Clean(); - - // - // Validate Block Detected ... - result = box.IsValid(); - if (!result) - { - // - ob.Clean(); - fvg.Clean(); - box.Clean(); - pBar.Clean(); - iBar.Clean(); - iPBar.Clean(); - swingBar.Clean(); - liquidity.Clean(); - - // - return result; - } - - // - int toIDX = box.ToIndex(); - int fromIDX = box.FromIndex(); - bool isBullish = box.IsBullish(); - bool isBearish = box.IsBearish(); - - // - // Detect Swing Bar ... - int swingBarIDX = -1; - int swingLoopback = fromIDX - pBarIndex; - if (isBullish) - { - // - // Looking for Swing Low ... - swingBarIDX = pBar.FindLowestIndex(swingLoopback, MODE_LOW); - } - else if (isBearish) - { - // - // Looking for Swing High ... - swingBarIDX = pBar.FindHighestIndex(swingLoopback, MODE_LOW); - } - result = IsValidIndex(swingBarIDX); - if (!result) - { - // - ob.Clean(); - fvg.Clean(); - box.Clean(); - pBar.Clean(); - iBar.Clean(); - iPBar.Clean(); - swingBar.Clean(); - liquidity.Clean(); - - // - return result; - } - - // - // Initialize Swing Bar ... - result = swingBar.Init( - bar.symbol, - bar.period, - swingBarIDX // - ); - if (!result) - { - // - ob.Clean(); - fvg.Clean(); - box.Clean(); - pBar.Clean(); - iBar.Clean(); - iPBar.Clean(); - swingBar.Clean(); - liquidity.Clean(); - - // - return result; - } - - // - // Update Trigger Box ... - if (isBullish) - { - box.lower = MathMin(box.lower, swingBar.GetDown()); - } - else if (isBearish) - { - box.upper = MathMin(box.upper, swingBar.GetUp()); - } - - // - // Now we Have to Check Spike from Swing Bar Next till Current Bar ... - // To Validate Highs and Lows ... - for (int i = pBarIndex; i < pBarIndex + (swingBarIDX - pBarIndex) - 1; i++) - { - // - // Initialize iBar ... - result = iBar.Init( - bar.symbol, - bar.period, - i // - ); - result = - result && - iBar.GetPreviousBar(iPBar); - if (!result) - { - break; - } - - // - // Since we Go Backward Bars from Current Bar ... - // for Bullish: each Bar Low Must over Prev Bar Low ... - // for Bearish: each Bar High Must Under Prev Bar High ... - if (isBullish) - { - result = iBar.low > iPBar.low; - } - else if (isBearish) - { - result = iBar.high < iPBar.high; - } - if (!result) - { - break; - } - - // - iBar.Clean(); - iPBar.Clean(); - } - iBar.Clean(); - iPBar.Clean(); - if (!result) - { - // - ob.Clean(); - fvg.Clean(); - box.Clean(); - pBar.Clean(); - iBar.Clean(); - iPBar.Clean(); - swingBar.Clean(); - liquidity.Clean(); - - // - return result; - } - - // - // We Have to Make sure Bars until Spikes Closed ... - // for Bullish: bars must Close Above box.upper ... - // for Bearish: bars must Close Below box.lower ... - for (int i = pBarIndex; i < toIDX; i++) - { - // - // Initialize iBar ... - result = iBar.Init( - bar.symbol, - bar.period, - i // - ); - result = - result && - (isBullish - ? iBar.close > box.upper - : iBar.close < box.lower); - - // - if (!result) - { - break; - } - - // - iBar.Clean(); - } - iBar.Clean(); - if (!result) - { - // - ob.Clean(); - fvg.Clean(); - box.Clean(); - pBar.Clean(); - iBar.Clean(); - iPBar.Clean(); - swingBar.Clean(); - liquidity.Clean(); - - // - return result; - } - - // - // Now we Have to Detect Spike Breake Ruls ... - // for Bullish: bar.low goes Below of pBar.low ... - // for Bearish: bar.high goes Above of pBar.high ... - if (isBullish) - { - result = bar.low < pBar.low; - } - else if (isBearish) - { - result = bar.high > pBar.high; - } - if (!result) - { - // - ob.Clean(); - fvg.Clean(); - box.Clean(); - pBar.Clean(); - iBar.Clean(); - iPBar.Clean(); - swingBar.Clean(); - liquidity.Clean(); - - // - return result; - } - - // - // Update Box ... - if (isBullish) - { - box.upper = MathMax(box.upper, bar.GetDown()); - } - else if (isBearish) - { - box.lower = MathMin(box.lower, bar.GetUp()); - } - box.to = bar.time; - - // - toIDX = box.ToIndex(); - fromIDX = box.FromIndex(); - - // - // Liquidity ... - if (forceLiquidity) - { - // - // Now we Have to Detect Liquidity Zone ... - for (int i = fromIDX; i < fromIDX + loopback; i++) - { - // - // Initialize iBar - result = iBar.Init( - bar.symbol, - bar.period, - i // - ); - result = - result && - IsRejected( - iBar, - iDir, - false, // Force Bar Type ... - true // Force Fibo Pressure ... - ) && - iDir == box.dir && - (isBullish - ? iBar.low < box.lower - : iBar.high > box.upper); + // Update Trigger Block based on Swing Bar ... + result = swingBar.IsValid(); if (result) { // - // Filling Liquidity ... - liquidity.dir = iDir; - liquidity.to = box.to; - liquidity.type = "XLQ"; - liquidity.from = iBar.time; - liquidity.symbol = iBar.symbol; - liquidity.period = iBar.period; - liquidity.upper = isBullish - ? iBar.GetDown() - : iBar.high; - liquidity.lower = isBullish - ? iBar.low - : iBar.GetUp(); + // Update From ... + trigger.from = ((datetime)MathMin((int)trigger.from, (int)swingBar.time)); // - result = liquidity.IsValid(); - if (result) + // Update Edge ... + if (isBullish) { - break; + trigger.lower = MathMin(trigger.lower, swingBar.GetDown()); + } + else if (isBearish) + { + trigger.upper = MathMax(trigger.upper, swingBar.GetUp()); } } - - // - iBar.Clean(); - } - iBar.Clean(); - result = liquidity.IsValid(); - if (!result) - { - // - ob.Clean(); - fvg.Clean(); - box.Clean(); - pBar.Clean(); - iBar.Clean(); - iPBar.Clean(); - swingBar.Clean(); - liquidity.Clean(); - - // - return result; } // - // Check Liquidity Usage ... - if (forceLiquidityUsed) + tmpBar.Clean(); + } + + // + // Validate Min Block Edge ... + if (result && + minAllowedBlockEdgeLength > 0) + { + // + fromIDX = trigger.FromIndex(); + if (result) { // - // now We have to Ensure Detected Liqudity is Used ... - toIDX = box.ToIndex(); - fromIDX = liquidity.FromIndex(); - for (int i = fromIDX - 1; i >= toIDX; i--) + // Looping Back ... + for (int i = fromIDX; i < fromIDX + minAllowedBlockEdgeLength; i++) { // - // Initialize iBar ... - result = iBar.Init( + // Initialize i Bar ... + result = tmpBar.Init( bar.symbol, bar.period, i // @@ -2507,130 +2313,173 @@ class XCBarAnalyser : public XCBase result = result && (isBullish - ? iBar.low < liquidity.upper - : iBar.high > liquidity.lower); - if (result) + ? tmpBar.low > trigger.lower + : tmpBar.high > trigger.upper); + if (!result) { break; } // - iBar.Clean(); + tmpBar.Clean(); } - if (!result) - { - // - ob.Clean(); - fvg.Clean(); - box.Clean(); - pBar.Clean(); - iBar.Clean(); - iPBar.Clean(); - swingBar.Clean(); - liquidity.Clean(); + result = tmpBar.IsValid(); - // - return result; + // + // Update Trigger Block ... + if (result) + { + trigger.from = ((datetime)(MathMin((int)trigger.from, (int)tmpBar.time))); } } + + // + tmpBar.Clean(); } // - // Entry Bar ... - if (forceEntryBar) + // Validating Liquidity ... + if (result && + (forceHasLiquidity || + forceHasReversalLiquidity)) { // - // Validate Bar is Not Opposit Powered Bar ... - - // - // Momentum ... - bool isMomentum = IsMomentum( - bar, - iDir, - 1 // - ); - bool isBullishMomentum = - isMomentum && - IsBullish(iDir); - bool isBearishMomentum = - isMomentum && - IsBearish(iDir); - - // - // Engulfed ... - bool isEngulfed = IsEngulfed( - bar, - iDir // - ); - bool isBullishEngulfed = - isEngulfed && - IsBullish(iDir); - bool isBearishEngulfed = - isEngulfed && - IsBearish(iDir); - - // - // Rejected ... - bool isRejected = IsRejected( - bar, - iDir, - false, - true // - ); - bool isBullishRejected = - isRejected && - IsBullish(iDir); - bool isBearishRejected = - isRejected && - IsBearish(iDir); - - // - bool isBullishPowered = - isBullishMomentum || - isBullishEngulfed || - isBullishRejected; - - // - bool isBearishPowered = - isBearishMomentum || - isBearishEngulfed || - isBearishRejected; - - // - // Make Sure Entry Bar is a Valid Bar ... - result = - isBullish - ? !isBearishPowered && (!forceEntryBarPower - ? true - : isBullishPowered) - : !isBullishPowered && (!forceEntryBarPower - ? true - : isBearishPowered); - if (!result) + // Try to Detect Liquidity ... + toIDX = ob.ToIndex(); + for (int i = toIDX; i < toIDX + (loopback * 10); i++) { // - ob.Clean(); - fvg.Clean(); - box.Clean(); - pBar.Clean(); - iBar.Clean(); - iPBar.Clean(); - swingBar.Clean(); - liquidity.Clean(); + // Initialize i Bar ... + result = tmpBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } // - return result; + // Detect Liquidity ... + bool isRejected = + result && + IsRejected( + tmpBar, + iDir, + false, // Force Bar Type ... + true // Force Fibo Pressure ... + ); + bool isBullishRejected = + isRejected && + IsBullish(iDir); + bool isBearishRejected = + isRejected && + IsBearish(iDir); + + // + // Validate Liquidities ... + if (isBullish) + { + // + if (isBullishRejected && + forceHasLiquidity && + !fLiquidity.IsValid() && + tmpBar.low < trigger.lower) + { + // + // Filling Following Liquidity ... + FillLiquidity( + tmpBar, + trigger.dir, + fLiquidity, + trigger.to // + ); + } + + // + if (isBearishRejected && + !rLiquidity.IsValid() && + forceHasReversalLiquidity && + tmpBar.high > trigger.upper) + { + // + // Filling Revrsal Liquidity ... + FillLiquidity( + tmpBar, + Opposit(trigger.dir), + rLiquidity, + trigger.to // + ); + } + } + else if (isBearish) + { + // + if (isBearishRejected && + forceHasLiquidity && + !fLiquidity.IsValid() && + tmpBar.high > trigger.upper) + { + // + // Filling Following Liquidity ... + FillLiquidity( + tmpBar, + trigger.dir, + fLiquidity, + trigger.to // + ); + } + + // + if (isBullishRejected && + !rLiquidity.IsValid() && + forceHasReversalLiquidity && + tmpBar.low < trigger.lower) + { + // + // Filling Reversal Liquidity ... + FillLiquidity( + tmpBar, + Opposit(trigger.dir), + rLiquidity, + trigger.to // + ); + } + } + + // + if ((!forceHasLiquidity + ? true + : fLiquidity.IsValid()) && + (!forceHasReversalLiquidity + ? true + : rLiquidity.IsValid())) + { + break; + } + + // + tmpBar.Clean(); } + tmpBar.Clean(); + + // + result = (!forceHasLiquidity + ? true + : fLiquidity.IsValid()) && + (!forceHasReversalLiquidity + ? true + : rLiquidity.IsValid()); } // // Cleanup Resources ... // - iBar.Clean(); pBar.Clean(); - iPBar.Clean(); - swingBar.Clean(); + tmpBar.Clean(); + tmpPBar.Clean(); // if (!result) @@ -2638,9 +2487,13 @@ class XCBarAnalyser : public XCBase // ob.Clean(); fvg.Clean(); - box.Clean(); + trigger.Clean(); swingBar.Clean(); - liquidity.Clean(); + rLiquidity.Clean(); + fLiquidity.Clean(); + + // + return result; } // diff --git a/Classes/x-saherelm.x-cobject.class.mq5 b/Classes/x-saherelm.x-cobject.class.mq5 index d23bcd57..46e7c45b 100644 --- a/Classes/x-saherelm.x-cobject.class.mq5 +++ b/Classes/x-saherelm.x-cobject.class.mq5 @@ -426,7 +426,8 @@ class XCBarArrowObject : public XCBaseObject int window, int arrow, XOHCL &bar, - ENUM_X_PRICE priceType // + ENUM_X_PRICE priceType, + double threshold = 5 // ) { // @@ -448,6 +449,21 @@ class XCBarArrowObject : public XCBaseObject datetime time = bar.time; double price = bar.GetPrice(priceType); + // + if (threshold > 0) + { + // + double thresholdPrice = threshold * GetPoints(bar.symbol); + if (priceType == X_PRICE_HIGH) + { + price += thresholdPrice; + } + else if (priceType == X_PRICE_LOW) + { + price -= thresholdPrice; + } + } + // result = mArrow.Create( chart_id, diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index adc86929..2fe2d02c 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -28,6 +28,32 @@ // // Definitions ... + +// +// Extensions ... + +void AddObjects( + CArrayObj *&source, + CArrayObj &dest // +) +{ + // + bool has = source != NULL && + source.Total() > 0; + if (!has) + { + return; + } + + // + for (int i = 0; i < source.Total(); i++) + { + dest.Add(source.At(i)); + } +} + +// +// Implementations ... class XCPOIDrawer : public XCBase { // @@ -3268,7 +3294,7 @@ class XCPOIDrawer : public XCBase bool DrawSignal( XSignal &signal, XCSignalObject *&object, - int length = 3 // + int length = 3 // ) { // diff --git a/Documents/BKP/sample.mq5 b/Documents/BKP/sample.mq5 new file mode 100644 index 00000000..1cf4d7a7 --- /dev/null +++ b/Documents/BKP/sample.mq5 @@ -0,0 +1,780 @@ +// // +// // Now we Have to Detect Spike Breake Ruls ... +// // for Bullish: bar.low goes Below of pBar.low ... +// // for Bearish: bar.high goes Above of pBar.high ... +// for (int i = toIDX; i > pBarIndex; i--) +// { +// // +// // Initialize iBar ... +// result = iBar.Init( +// bar.symbol, +// bar.period, +// i // +// ); +// result = +// result && +// iBar.GetPreviousBar(iPBar); +// if (result) +// { +// // +// if (isBullish) +// { +// result = iBar.low < iPBar.low; +// } +// else if (isBearish) +// { +// result = iBar.high > iPBar.high; +// } + +// // +// if (result) +// { +// break; +// } +// } + +// // +// iBar.Clean(); +// iPBar.Clean(); +// } +// if (!result) +// { +// // +// ob.Clean(); +// fvg.Clean(); +// box.Clean(); +// pBar.Clean(); +// iBar.Clean(); +// iPBar.Clean(); +// swingBar.Clean(); +// liquidity.Clean(); + +// // +// return result; +// } + +// // +// // Update Box ... +// if (isBullish) +// { +// box.upper = MathMax(box.upper, iBar.GetDown()); +// } +// else if (isBearish) +// { +// box.lower = MathMin(box.lower, iBar.GetUp()); +// } + +bool IsTrigger( + XOHCL &bar, + XBoxZone &box, + XBoxZone &ob, + XBoxZone &fvg, + XBoxZone &liquidity, + XOHCL &swingBar, + int loopback = 10, + int hlDistance = 300, + double maxAlowedRange = 0.0, + bool forceOBOppositBar = true, + bool forceFVGBarType = true, + bool forceSwingBar = true, + bool forceGapBarBreakout = true, + bool forceCheckBarsSequence = true, + bool lookingEntry = false, + bool forceLiquidity = true, + bool forceLiquidityUsed = true, + bool forceEntryBar = true, + bool forceEntryBarPower = true + // +) +{ + // + bool result = false; + + // + // Normalize Args ... + ob.Clean(); + fvg.Clean(); + box.Clean(); + swingBar.Clean(); + liquidity.Clean(); + loopback = NormalizeInt(loopback, 5); + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + XOHCL iBar; + XOHCL iPBar; + int barIndex; + int pBarIndex; + ENUM_X_DIRECTION iDir; + + // + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + + // + return result; + } + + // + barIndex = bar.Index(); + pBarIndex = pBar.Index(); + + // + // Loopback to Find a Block ... + for (int i = pBarIndex; i < pBarIndex + loopback; i++) + { + // + // Inital IBar ... + result = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } + + // + // Detect Block ... + result = IsOB( + iBar, + ob, + forceFVGBarType, + forceOBOppositBar // + ); + if (result) + { + // + // Validate Block Last Bars ... + if (forceOBOppositBar) + { + // + XOHCL fromBar; + XOHCL fromBarPrev; + result = ob.FromBar(fromBar); + result = + result && + fromBar.GetPreviousBar(fromBarPrev); + result = + result && + (ob.IsBullish() + ? fromBarPrev.IsBearish() + : fromBarPrev.IsBullish()); + if (result) + { + // + // Detect FVG ... + result = IsFVG( + iBar, + fvg, + forceFVGBarType // + ); + if (result) + { + // + box.Clone(ob); + box.type = "XTRG"; + box.from = fromBarPrev.time; + break; + } + } + + // + fromBar.Clean(); + fromBarPrev.Clean(); + } + + // + break; + } + + // + iBar.Clean(); + } + iBar.Clean(); + result = box.IsValid(); + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + + // + return result; + } + + // + // Filter Using Max Allowed Range ... + if (maxAlowedRange > 0) + { + // + result = box.GetRange() <= (maxAlowedRange * GetPoints(bar.symbol)); + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + + // + return result; + } + } + + // + // Validate Gap Bar ... + if (forceGapBarBreakout) + { + // + // We Have to Check Gap Bar's Breakout ... + result = fvg.ToBar(iBar); + result = + result && + iBar.GetPreviousBar(iPBar); + result = + result && + (box.IsBullish() + ? iPBar.close > ob.upper + : iPBar.close < ob.lower); + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + + // + return result; + } + + // + iBar.Clean(); + iPBar.Clean(); + } + + // + // Validate HH LL Distance ... + if (hlDistance > 0) + { + // + result = ob.FromBar(iBar); + if (result) + { + // + double ll = iBar.FindLowest(iBar.Index() + hlDistance, MODE_LOW); + double hh = iBar.FindHighest(iBar.Index() + hlDistance, MODE_HIGH); + + // + result = + ll > 0 && + hh > 0 && + ob.upper < hh && + ob.lower > ll; + } + + // + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + + // + return result; + } + + // + iBar.Clean(); + } + + // + int toIDX = box.ToIndex(); + int fromIDX = box.FromIndex(); + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + + // + // We Have to Make sure Bars until Spikes Closed ... + // for Bullish: bars must Close Above box.upper ... + // for Bearish: bars must Close Below box.lower ... + for (int i = pBarIndex; i < toIDX; i++) + { + // + // Initialize iBar ... + result = iBar.Init( + bar.symbol, + bar.period, + i // + ); + result = + result && + (isBullish + ? iBar.close > box.upper + : iBar.close < box.lower); + + // + if (!result) + { + break; + } + + // + iBar.Clean(); + } + iBar.Clean(); + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + + // + return result; + } + + // + // Detect Swing Bar ... + int swingBarIDX = -1; + int swingLoopback = fromIDX - pBarIndex; + if (isBullish) + { + // + // Looking for Swing Low ... + swingBarIDX = pBar.FindLowestIndex(swingLoopback, MODE_LOW); + } + else if (isBearish) + { + // + // Looking for Swing High ... + swingBarIDX = pBar.FindHighestIndex(swingLoopback, MODE_LOW); + } + result = IsValidIndex(swingBarIDX); + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + + // + return result; + } + + // + // Initialize Swing Bar ... + result = swingBar.Init( + bar.symbol, + bar.period, + swingBarIDX // + ); + if (forceSwingBar) + { + // + result = + result && + IsSimpleSwing( + swingBar, + iDir // + ) && + iDir == fvg.dir; + } + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + + // + return result; + } + + // + // Update Trigger Box ... + if (isBullish) + { + box.lower = MathMin(box.lower, swingBar.GetDown()); + } + else if (isBearish) + { + box.upper = MathMin(box.upper, swingBar.GetUp()); + } + + // + // Validating Bar Sequence ... + if (forceCheckBarsSequence) + { + // + // Now we Have to Check Spike from Swing Bar Next till Current Bar ... + // To Validate Highs and Lows ... + for (int i = pBarIndex; i < pBarIndex + (swingBarIDX - pBarIndex) - 1; i++) + { + // + // Initialize iBar ... + result = iBar.Init( + bar.symbol, + bar.period, + i // + ); + result = + result && + iBar.GetPreviousBar(iPBar); + if (!result) + { + break; + } + + // + // Since we Go Backward Bars from Current Bar ... + // for Bullish: each Bar Low Must over Prev Bar Low ... + // for Bearish: each Bar High Must Under Prev Bar High ... + if (isBullish) + { + // + result = + result && + iBar.low > iPBar.low; + } + else if (isBearish) + { + // + result = + result && + iBar.high < iPBar.high; + } + if (!result) + { + break; + } + + // + iBar.Clean(); + iPBar.Clean(); + } + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + + // + return result; + } + + // + box.to = pBar.time; + + // + iBar.Clean(); + iPBar.Clean(); + } + + // + toIDX = box.ToIndex(); + fromIDX = box.FromIndex(); + + // + // Liquidity ... + if (forceLiquidity) + { + // + // Checking Swing Bar is Liquidity ... + result = IsRejected( + swingBar, + iDir, + true, // Force Bar Type ... + true // Foce Fibo Pressure ... + ) && + iDir == fvg.dir; + if (result) + { + // + // Filling Liquidity ... + liquidity.dir = iDir; + liquidity.to = box.to; + liquidity.type = "XLQ"; + liquidity.from = swingBar.time; + liquidity.symbol = swingBar.symbol; + liquidity.period = swingBar.period; + liquidity.upper = isBullish + ? swingBar.GetDown() + : swingBar.high; + liquidity.lower = isBullish + ? swingBar.low + : swingBar.GetUp(); + + // + result = liquidity.IsValid(); + } + result = liquidity.IsValid(); + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + + // + return result; + } + + // + // Check Liquidity Usage ... + if (forceLiquidityUsed) + { + // + // now We have to Ensure Detected Liqudity is Used ... + toIDX = box.ToIndex(); + fromIDX = liquidity.FromIndex(); + for (int i = fromIDX - 1; i >= toIDX; i--) + { + // + // Initialize iBar ... + result = iBar.Init( + bar.symbol, + bar.period, + i // + ); + result = + result && + (isBullish + ? iBar.low < liquidity.upper + : iBar.high > liquidity.lower); + if (result) + { + break; + } + + // + iBar.Clean(); + } + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + + // + return result; + } + } + } + + // + // Looking for Entry ... + if (lookingEntry) + { + // + // Entry Bar ... + if (forceEntryBar) + { + // + // Validate Bar is Not Opposit Powered Bar ... + + // + // Momentum ... + bool isMomentum = IsMomentum( + bar, + iDir, + 1 // + ); + bool isBullishMomentum = + isMomentum && + IsBullish(iDir); + bool isBearishMomentum = + isMomentum && + IsBearish(iDir); + + // + // Engulfed ... + bool isEngulfed = IsEngulfed( + bar, + iDir // + ); + bool isBullishEngulfed = + isEngulfed && + IsBullish(iDir); + bool isBearishEngulfed = + isEngulfed && + IsBearish(iDir); + + // + // Rejected ... + bool isRejected = IsRejected( + bar, + iDir, + false, + true // + ); + bool isBullishRejected = + isRejected && + IsBullish(iDir); + bool isBearishRejected = + isRejected && + IsBearish(iDir); + + // + bool isBullishPowered = + isBullishMomentum || + isBullishEngulfed || + isBullishRejected; + + // + bool isBearishPowered = + isBearishMomentum || + isBearishEngulfed || + isBearishRejected; + + // + // Make Sure Entry Bar is a Valid Bar ... + result = + isBullish + ? !isBearishPowered && (!forceEntryBarPower + ? true + : isBullishPowered) + : !isBullishPowered && (!forceEntryBarPower + ? true + : isBearishPowered); + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + + // + return result; + } + } + + // + // Check Entry Bar Sequences ... + if (forceCheckBarsSequence) + { + // + // if Sequences is Important ... + // we have to detect sequence Breaker Bar ... + result = + result && + (isBullish + ? bar.low < pBar.low + : bar.high > pBar.high); + } + + // + // Validate Bar Close ... + result = + result && + (isBullish + ? bar.close > box.lower + : bar.close < box.upper); + } + + // + if (!lookingEntry) + { + result = fvg.to == pBar.time; + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + pBar.Clean(); + iPBar.Clean(); + + // + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + box.Clean(); + swingBar.Clean(); + swingBar.Clean(); + liquidity.Clean(); + } + + // + return result; +} diff --git a/Documents/BKP/xcaea.trigger.block.lib.mq5 b/Documents/BKP/xcaea.trigger.block.lib.mq5 new file mode 100644 index 00000000..c3b7877f --- /dev/null +++ b/Documents/BKP/xcaea.trigger.block.lib.mq5 @@ -0,0 +1,4122 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCAEAHelper Lib +// Description: Library for XCAEA Signaller ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Library for XCAEA Helper" +#property strict + +// +// Imports ... +#include "../../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/xcaea.x-poi.detector.class.mq5" +#include "../Helpers/xcaea.helper.mq5" + +// +// Definitions ... +enum ENUM_XCAEA_TIGGER_TYPE +{ + XCA_TRIGGER_NONE, // None + XCA_TRIGGER_BULL, // TriggerBull + XCA_TRIGGER_BEAR, // TriggerBear +}; + +// +bool IsValid(ENUM_XCAEA_TIGGER_TYPE value) +{ + return value != XCA_TRIGGER_NONE; +} + +// +string ToString(ENUM_XCAEA_TIGGER_TYPE value) +{ + return EnumToString(value); +} + +// +ENUM_XCAEA_TIGGER_TYPE GetType(string type) +{ + // + ENUM_XCAEA_TIGGER_TYPE result = XCA_TRIGGER_NONE; + + // + bool isTriggerBull = type == ToString(XCA_TRIGGER_BULL); + bool isTriggerBear = type == ToString(XCA_TRIGGER_BEAR); + + // + if (isTriggerBull) + { + result = XCA_TRIGGER_BULL; + } + else if (isTriggerBear) + { + result = XCA_TRIGGER_BEAR; + } + + // + return result; +} + +// +ENUM_X_DIRECTION GetDirection(ENUM_XCAEA_TIGGER_TYPE value) +{ + return value == XCA_TRIGGER_BULL + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; +} + +// +// Structues ... +struct XCAEATriggerBlockConfiguration +{ + // + // Props ... + + // + // Trigger Detection ... + + // + double maxAllowedRange; // Maximum Allowed Range + int minAllowedBlockEdgeLength; // Minimum Required Block Edge Length + + // + bool forceOBOppositBar; // Force OB to Start by Opposit Bars + bool forceFVGBarType; // Force FVG to Has Same Type of Bars + bool forceGapBarBreakout; // Force FVG's Gap Bar to Breakeout OB Edge Side + bool forceHasSwingBar; // Force Has Propper Swing + bool forceHasLiquidity; // Force Has Following Liquidity Zone + bool forceHasReversalLiquidity; // Force Has Reversal Liquidity Zone + + // + // Validating ... + int minZoneLength; // Minimum Length of Consolidation Zone + bool forceHasSwing; // Force Zone's Has Propper Swing + bool forceHasPinBarEntry; // Force Zone's Ends with a Pin Bar + bool forceGapBarsBreakout; // Force Zone's Gap Bar's Breakes Out + double maxZoneRangeInPoints; // Max Zone Range in Point + double maxAllowedEntryDistance; // Max Allowed Entry Distance + + // + // Filtering ... + bool filterBasedOnSar; // Filter Trigger Block Based on Sar + bool filterBasedOnRSI; // Filter Trigger Block Based on RSI + bool filterBasedOnADX; // Filter Trigger Block Based on ADX + bool filterBasedOnTrend; // Filter Trigger Block Based on Trend + bool filterBasedOnScores; // Filter Trigger Block Based on Scores + bool filterBasedOnVolumes; // Filter Trigger Block Based on Volumes + + // + // Constructor ... + XCAEATriggerBlockConfiguration() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + + // + // Validating ... + minZoneLength = 0; + forceHasSwing = false; + maxZoneRangeInPoints = 0.0; + forceHasPinBarEntry = false; + forceGapBarsBreakout = false; + maxAllowedEntryDistance = 0.0; + + // + // Filtering ... + filterBasedOnSar = false; + filterBasedOnRSI = false; + filterBasedOnADX = false; + filterBasedOnTrend = false; + + // + ZeroMemory(this); + } + + // + // Preset Configurations ... + + // + // Commons Verifications which used in all + // Preset Configurations ... + void ConfigureCommons() + { + // + minZoneLength = 7; + forceHasSwing = true; + maxZoneRangeInPoints = 70; + forceHasPinBarEntry = true; + forceGapBarsBreakout = true; + maxAllowedEntryDistance = 30; + } + + // + // Cleanup Range Verifications ... + void CleanRanges() + { + // + maxZoneRangeInPoints = 0; + maxAllowedEntryDistance = 0; + } + + // + void ConfigureFullFilter() + { + // + // Apply Common Configurations ... + ConfigureCommons(); + + // + // Apply Full Filters ... + filterBasedOnSar = true; + filterBasedOnRSI = true; + filterBasedOnADX = true; + filterBasedOnTrend = true; + } + + // + void ConfigureFullFilterNoRange() + { + // + // Apply Common Configurations ... + ConfigureCommons(); + + // + // Clean Ranges ... + CleanRanges(); + + // + // Apply Full Filters ... + filterBasedOnSar = true; + filterBasedOnRSI = true; + filterBasedOnADX = true; + filterBasedOnTrend = true; + } + + // + void ConfigureSarRsiAdxFilter() + { + // + ConfigureFullFilter(); + + // + filterBasedOnTrend = false; + } + + // + void ConfigureSarRsiTrendFilter() + { + // + ConfigureFullFilter(); + + // + filterBasedOnADX = false; + } + + // + void ConfigureSarAdxTrendFilter() + { + // + ConfigureFullFilter(); + + // + filterBasedOnRSI = false; + } + + // + void ConfigureRsiAdxTrendFilter() + { + // + ConfigureFullFilter(); + + // + filterBasedOnSar = false; + } + + // + void ConfigureSarRsiFilter() + { + // + ConfigureFullFilter(); + + // + filterBasedOnADX = false; + filterBasedOnTrend = false; + } + + // + void ConfigureSarAdxFilter() + { + // + ConfigureFullFilter(); + + // + filterBasedOnRSI = false; + filterBasedOnTrend = false; + } + + // + void ConfigureSarTrendFilter() + { + // + ConfigureFullFilter(); + + // + filterBasedOnRSI = false; + filterBasedOnADX = false; + } + + // + void ConfigureRsiAdxFilter() + { + // + ConfigureFullFilter(); + + // + filterBasedOnSar = false; + filterBasedOnTrend = false; + } + + // + void ConfigureRsiTrendFilter() + { + // + ConfigureFullFilter(); + + // + filterBasedOnSar = false; + filterBasedOnADX = false; + } + + // + void ConfigureAdxTrendFilter() + { + // + ConfigureFullFilter(); + + // + filterBasedOnSar = false; + filterBasedOnRSI = false; + } + + // +}; + +// +struct XTriggerBlock +{ + // + // Props ... + XBoxZone ob; // Order Block + XBoxZone fvg; // Fair Value Gap + XOHCL swingBar; // Swing of Trigger + XBoxZone trigger; // Trigger Block + XBoxZone rLiquidity; // Reversal Liquidity + XBoxZone fLiquidity; // Following Liquidity + XCAEAConditions conditions; // Market Conditions + XCAEATriggerBlockConfiguration configuration; // Detection Configuration + + // + // Constructor ... + XTriggerBlock() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + ob.Clean(); + fvg.Clean(); + trigger.Clean(); + swingBar.Clean(); + rLiquidity.Clean(); + fLiquidity.Clean(); + conditions.Clean(); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = ob.IsValid() && + fvg.IsValid() && + trigger.IsValid(); + + // + return result; + } + + // +}; + +// +// Extensions ... + +/** + * Detect a Trigger Block ... + * + * @param triggerBlock: XBoxZone instance reference, The Detected Trigger Block ... + * @param conditions: XCAEAConditions instance reference, The Block Verification Conditions ... + * @param helper: XCXCAEAHelper instance pointer, Specified The Helper Class Instance which used to Detect Conditions ... + * @param config: XCAEATriggerBlockConfiguration instance reference, Specified The Trigger Block Detection Configuration ... + * @param bar_index: int, Specified The Bar Index to Start Detection ... + * @param loopback: int, Specified The Loopback Length to Detect Helper Conditions ... + * + * @return ( bool ) + */ +bool DetectTriggerBlock( + XBoxZone &triggerBlock, + XCAEAConditions &conditions, + XCXCAEAHelper *helper, + XCAEATriggerBlockConfiguration &config, + int bar_index = 0, + int loopback = 6 // +) +{ + // + bool result = false; + + // + conditions.Clean(); + triggerBlock.Clean(); + + // + // Normalize Args ... + loopback = NormalizeInt(loopback, 6); + bar_index = NormalizeInt(bar_index, 0); + + // + // Validate Args ... + result = helper != NULL; + if (!result) + { + return result; + } + + // + // Provide base Requirements ... + + // + string symbol = helper.GetSymbol(); + double points = GetPoints(symbol); + ENUM_TIMEFRAMES period = helper.GetPeriod(); + + // + // Conditions Reading Indexes ... + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + double ll = 0; + double hh = 0; + bool has = false; + ENUM_X_DIRECTION iDir; + + // + // Retrieve Current Conditions ... + result = helper.GetConditions( + conditions, + bar_index, + loopback // + ); + + // + // Retrieve Required Bars ... + + // + XOHCL zBar; // Current Start Checking Bar (Usually Used for Triggering) ... + XOHCL cBar; // Current Finished Bar which Start Detecting Structures based on it ( End of Block and FVG Bar ) ... + XOHCL pBar; // Determines Block Gap Bar (all Filtering must applied and Check using this Bar and it's Next Bar) ... + XOHCL p2Bar; // Determines FVG's Start Bar in a Block ... + XOHCL p3Bar; // First Verification of Block ... + XOHCL p4Bar; // Seccond Verification of Block ... + + // + result = zBar.Init( + symbol, + period, + bar_index // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(p2Bar); + result = + result && + p2Bar.GetPreviousBar(p3Bar); + result = + result && + p3Bar.GetPreviousBar(p4Bar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + + // + // Detect Based Order Block using CBar ... + result = + helper + .barAnalyser + .IsOB( + cBar, + triggerBlock, + true, // Force FVG Bar Type ... + true // Force Block Two Bar Checking ... + ); + + // + // Ensure a Block is Detected ... + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + + // + // Reading Some Block Based Requirements ... + + // + bool isBullish = + result && + triggerBlock.IsBullish(); + + // + bool isBearish = + result && + triggerBlock.IsBearish(); + + // + int toIDX = triggerBlock.ToIndex(); + int fromIDX = triggerBlock.FromIndex(); + + // + // Start Validating ... + + // + // Validating p2Bar and p3Bar Direction ... + if (result) + { + // + iDir = Opposit(triggerBlock.dir); + + // + result = + iDir == p3Bar.GetDirection() || + iDir == p4Bar.GetDirection(); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // Validating Using Max Range ... + result = config.maxZoneRangeInPoints > 0; + if (result) + { + // + double range = triggerBlock.GetRange(); + result = range <= config.maxZoneRangeInPoints * points; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // Validate Gap Endup with PinBar ... + result = config.forceHasPinBarEntry; + if (result) + { + // + bool isBullishRejected = + isBullish && + cBar.IsBullish() && + cBar.GetLowShadow() > cBar.GetHighShadow(); + + // + bool isBearishRejected = + isBearish && + cBar.IsBearish() && + cBar.GetLowShadow() < cBar.GetHighShadow(); + + // + result = isBullishRejected || + isBearishRejected; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // Validating Gap Bar must a Momentum Bar and + // Breakes out Zone's Directional Edge ... + // for Bullish: Upper + // for Bearish: Lower + result = config.forceGapBarsBreakout; + if (result) + { + // + // Gap Bar is PBar ... + + // + // Check Gap Bar is Momentum Bar ... + result = + helper + .barAnalyser + .IsMomentum( + pBar, + iDir // + ); + bool isBullishMomentum = + result && + IsBullish(iDir); + bool isBearishMomentum = + result && + IsBearish(iDir); + + // + // Check Gap Bar's Breakout ... + + // + bool isBullishBreakedout = + isBullish && + pBar.IsBullish() && + isBullishMomentum && + pBar.GetUp() > triggerBlock.upper && + pBar.GetDown() < triggerBlock.upper; + + // + bool isBearishBreakedout = + isBearish && + pBar.IsBearish() && + isBearishMomentum && + pBar.GetUp() > triggerBlock.lower && + pBar.GetDown() < triggerBlock.lower; + + // + result = isBullishBreakedout || + isBearishBreakedout; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // Validate Zone Has Propper Swing ... + // for Bullish: p2Bar or p3Bar must be a Swing Low ... + // for Bearish: p2Bar or p3Bar must be a Swing High ... + result = config.forceHasSwing; + if (result) + { + // + // p2Bar ... + bool isP2BarSwing = + helper + .barAnalyser + .IsSimpleSwing( + p2Bar, + iDir // + ); + bool isP2BarSwingLow = + isP2BarSwing && + IsBullish(iDir); + bool isP2BarSwingHigh = + isP2BarSwing && + IsBearish(iDir); + + // + // p3Bar ... + bool isP3BarSwing = + helper + .barAnalyser + .IsSimpleSwing( + p3Bar, + iDir // + ); + bool isP3BarSwingLow = + isP3BarSwing && + IsBullish(iDir); + bool isP3BarSwingHigh = + isP3BarSwing && + IsBearish(iDir); + + // + bool hasSwingLow = + isBullish && + (isP2BarSwingLow || + isP3BarSwingLow); + + // + bool hasSwingHigh = + isBearish && + (isP2BarSwingHigh || + isP3BarSwingHigh); + + // + result = + hasSwingLow || + hasSwingHigh; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // Validating Using Swing Length ... + result = config.minZoneLength > 0; + if (result) + { + // + XOHCL fromBar; + has = triggerBlock.FromBar(fromBar); + if (result) + { + // + // Retrieve HH and LL ... + ll = fromBar.FindLowest(config.minZoneLength, MODE_LOW); + hh = fromBar.FindHighest(config.minZoneLength, MODE_HIGH); + + // + // Validate Using HH and LL ... + + // + bool isBullishValid = + isBullish && + ll >= triggerBlock.lower; + + // + bool isBearishValid = + isBearish && + hh <= triggerBlock.upper; + + // + result = isBullishValid || + isBearishValid; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + + // + // Update Zone's From Time ... + triggerBlock.from = GetBarTime( + triggerBlock.symbol, + triggerBlock.period, + fromBar.Index() + config.minZoneLength // + ); + } + + // + fromBar.Clean(); + } + + // + // Validate Max Allowed Entry Distance ... + result = config.maxAllowedEntryDistance > 0; + if (result) + { + // + double base = + isBullish + ? triggerBlock.upper + : triggerBlock.lower; + double entryDistance = MathAbs(zBar.open - base); + result = entryDistance <= config.maxAllowedEntryDistance * points; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // Here we Ensure which have a Valid Zone using Different Applied Validations ... + // from now we are Going to Filterd Validate Zones ... + + // + // Check Exists Filters or not ... + result = config.filterBasedOnSar || + config.filterBasedOnRSI || + config.filterBasedOnADX || + config.filterBasedOnTrend; + if (result) + { + // + // Do Apply Several Exists Filters ... + + // + // SAR Filter ... + if (config.filterBasedOnSar) + { + // + // Reading Conditions Values ... + + // + double zSar = conditions.sarBuffer[zIDX]; + double cSar = conditions.sarBuffer[cIDX]; + double pSar = conditions.sarBuffer[pIDX]; + double p2Sar = conditions.sarBuffer[p2IDX]; + double p3Sar = conditions.sarBuffer[p3IDX]; + double p4Sar = conditions.sarBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + bool isZSarBullish = zSar < zBar.low; + bool isZSarBearish = zSar > zBar.high; + + // + bool isCSarBullish = cSar < cBar.low; + bool isCSarBearish = cSar > cBar.high; + + // + bool isPSarBullish = pSar < pBar.low; + bool isPSarBearish = pSar > pBar.high; + + // + bool isP2SarBullish = p2Sar < p2Bar.low; + bool isP2SarBearish = p2Sar > p2Bar.high; + + // + bool isCSarSwitchedToBullish = + isZSarBullish && + isCSarBullish && + !isPSarBullish && + cBar.IsBullish() && + cBar.GetUp() > pSar; + + // + bool isCSarSwitchedToBearish = + isZSarBearish && + isCSarBearish && + !isPSarBearish && + cBar.IsBearish() && + cBar.GetDown() < pSar; + + // + bool isPSarSwitchedToBullish = + isZSarBullish && + isCSarBullish && + isPSarBullish && + !isP2SarBullish && + pBar.IsBullish() && + pBar.GetUp() > p2Sar; + + // + bool isPSarSwitchedToBearish = + isZSarBearish && + isCSarBearish && + isPSarBearish && + !isP2SarBearish && + pBar.IsBearish() && + pBar.GetDown() < p2Sar; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + (isCSarSwitchedToBullish || + isPSarSwitchedToBullish); + + // + bool isBearishFilterd = + isBearish && + (isCSarSwitchedToBearish || + isPSarSwitchedToBearish); + + // + result = + isBullishFilterd || + isBearishFilterd; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // RSI Filter ... + if (config.filterBasedOnRSI) + { + // + // Reading Conditions Values ... + + // + double rsiTrend = (conditions.rsiOBLevel + conditions.rsiOSLevel) / 2; + + // + double zRSI = conditions.rsiBuffer[zIDX]; + double cRSI = conditions.rsiBuffer[cIDX]; + double pRSI = conditions.rsiBuffer[pIDX]; + double p2RSI = conditions.rsiBuffer[p2IDX]; + double p3RSI = conditions.rsiBuffer[p3IDX]; + double p4RSI = conditions.rsiBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + bool isZRSIBullish = zRSI > rsiTrend; + bool isZRSIBearish = zRSI < rsiTrend; + + // + bool isCRSIBullish = cRSI > rsiTrend; + bool isCRSIBearish = cRSI < rsiTrend; + + // + bool isPRSIBullish = pRSI > rsiTrend; + bool isPRSIBearish = pRSI < rsiTrend; + + // + bool isP2RSIBullish = p2RSI > rsiTrend; + bool isP2RSIBearish = p2RSI < rsiTrend; + + // + bool isP3RSIBullish = p3RSI > rsiTrend; + bool isP3RSIBearish = p3RSI < rsiTrend; + + // + // Trending Conditions ... + + // + bool isCRSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + !isPRSIBullish; + + // + bool isCRSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + !isPRSIBearish; + + // + bool isPRSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + isPRSIBullish && + !isP2RSIBullish; + + // + bool isPRSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + isPRSIBearish && + !isP2RSIBearish; + + // + bool isP2RSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + isPRSIBullish && + isP2RSIBullish && + !isP3RSIBullish; + + // + bool isP2RSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + isPRSIBearish && + isP2RSIBearish && + !isP3RSIBearish; + + // + // Crosses Conditions ... + + // + bool isCBarCrossedOverOS = + zRSI > conditions.rsiOSLevel && + cRSI > conditions.rsiOSLevel && + pRSI <= conditions.rsiOSLevel; + + // + bool isCBarCrossedUnderOB = + zRSI < conditions.rsiOBLevel && + cRSI < conditions.rsiOBLevel && + pRSI >= conditions.rsiOBLevel; + + // + bool isPBarCrossedOverOS = + zRSI > conditions.rsiOSLevel && + cRSI > conditions.rsiOSLevel && + pRSI > conditions.rsiOSLevel && + p2RSI <= conditions.rsiOSLevel; + + // + bool isPBarCrossedUnderOB = + zRSI < conditions.rsiOBLevel && + cRSI < conditions.rsiOBLevel && + pRSI < conditions.rsiOBLevel && + p2RSI >= conditions.rsiOBLevel; + + // + // V Pattern Conditions ... + + // + bool isCRSIHasVBullishPattern = + zRSI >= cRSI && + cRSI > pRSI && + p2RSI > pRSI && + cRSI >= p2RSI; + + // + bool isCRSIHasVBearishPattern = + zRSI <= cRSI && + cRSI < pRSI && + p2RSI < pRSI && + cRSI <= p2RSI; + + // + // Continuation Conditions ... + + // + bool isRSIUp = + zRSI >= cRSI && + (cRSI >= pRSI || + pRSI >= p2RSI || + p2RSI >= p3RSI); + + // + bool isRSIDown = + zRSI <= cRSI && + (cRSI <= pRSI || + pRSI <= p2RSI || + p2RSI <= p3RSI); + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + ( + // + // Grows ... + isRSIUp + // + || + // + // Crosses ... + (isCBarCrossedOverOS || + isPBarCrossedOverOS) + // + || + // + // V Pattern ... + isCRSIHasVBullishPattern + // + || + // + // Trending ... + (isCRSISwitchedToBullish || + isPRSISwitchedToBullish || + isP2RSISwitchedToBullish) + // + ); + + // + bool isBearishFilterd = + isBearish && + ( + // + // Grows ... + isRSIDown + // + || + // + // Crosses ... + (isCBarCrossedUnderOB || + isPBarCrossedUnderOB) + // + || + // + // V Pattern ... + isCRSIHasVBearishPattern + // + || + // + // Trending ... + (isCRSISwitchedToBearish || + isPRSISwitchedToBearish || + isP2RSISwitchedToBearish) + // + ); + + // + result = + isBullishFilterd || + isBearishFilterd; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // ADX Filter ... + if (config.filterBasedOnADX) + { + // + // Reading Conditions Values ... + + // + // ADX ... + double zADX = conditions.adxBuffer[zIDX]; + double cADX = conditions.adxBuffer[cIDX]; + double pADX = conditions.adxBuffer[pIDX]; + double p2ADX = conditions.adxBuffer[p2IDX]; + double p3ADX = conditions.adxBuffer[p3IDX]; + double p4ADX = conditions.adxBuffer[p4IDX]; + + // + // ADX +DI ... + double zADXP = conditions.adxpBuffer[zIDX]; + double cADXP = conditions.adxpBuffer[cIDX]; + double pADXP = conditions.adxpBuffer[pIDX]; + double p2ADXP = conditions.adxpBuffer[p2IDX]; + double p3ADXP = conditions.adxpBuffer[p3IDX]; + double p4ADXP = conditions.adxpBuffer[p4IDX]; + + // + // ADX -DI ... + double zADXN = conditions.adxnBuffer[zIDX]; + double cADXN = conditions.adxnBuffer[cIDX]; + double pADXN = conditions.adxnBuffer[pIDX]; + double p2ADXN = conditions.adxnBuffer[p2IDX]; + double p3ADXN = conditions.adxnBuffer[p3IDX]; + double p4ADXN = conditions.adxnBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + // Grows ... + + // + bool isADXUp = + zADX >= cADX && + (cADX >= pADX || + pADX >= p2ADX); + + // + bool isADXDown = + zADX <= cADX && + (cADX <= pADX || + pADX <= p2ADX); + + // + // Trending ... + + // + bool isZADXBullish = zADX > conditions.adxThreshold; + bool isZADXBearish = zADX < conditions.adxThreshold; + + // + bool isCADXBullish = cADX > conditions.adxThreshold; + bool isCADXBearish = cADX < conditions.adxThreshold; + + // + bool isPADXBullish = pADX > conditions.adxThreshold; + bool isPADXBearish = pADX < conditions.adxThreshold; + + // + bool isP2ADXBullish = p2ADX > conditions.adxThreshold; + bool isP2ADXBearish = p2ADX < conditions.adxThreshold; + + // + bool isP3ADXBullish = p3ADX > conditions.adxThreshold; + bool isP3ADXBearish = p3ADX < conditions.adxThreshold; + + // + bool isP4ADXBullish = p4ADX > conditions.adxThreshold; + bool isP4ADXBearish = p4ADX < conditions.adxThreshold; + + // + bool isCADXSwitchedToBullish = + isZADXBullish && + isCADXBullish && + !isPADXBullish; + + // + bool isCADXSwitchedToBearish = + isZADXBearish && + isCADXBearish && + !isPADXBearish; + + // + bool isPADXSwitchedToBullish = + isZADXBullish && + isCADXBullish && + isPADXBullish && + !isP2ADXBullish; + + // + bool isPADXSwitchedToBearish = + isZADXBearish && + isCADXBearish && + isPADXBearish && + !isP2ADXBearish; + + // + // Powering ... + + // + bool isZADXHasBullishPower = zADXP > zADXN; + bool isZADXHasBearishPower = zADXN > zADXP; + + // + bool isCADXHasBullishPower = cADXP > cADXN; + bool isCADXHasBearishPower = cADXN > cADXP; + + // + bool isPADXHasBullishPower = pADXP > pADXN; + bool isPADXHasBearishPower = pADXN > pADXP; + + // + bool isP2ADXHasBullishPower = p2ADXP > p2ADXN; + bool isP2ADXHasBearishPower = p2ADXN > p2ADXP; + + // + bool isP3ADXHasBullishPower = p3ADXP > p3ADXN; + bool isP3ADXHasBearishPower = p3ADXN > p3ADXP; + + // + bool isP4ADXHasBullishPower = p4ADXP > p4ADXN; + bool isP4ADXHasBearishPower = p4ADXN > p4ADXP; + + // + bool isCADXSwitchedToBullishPower = + isZADXHasBullishPower && + isCADXHasBullishPower && + !isPADXHasBullishPower; + + // + bool isCADXSwitchedToBearishPower = + isZADXHasBearishPower && + isCADXHasBearishPower && + !isPADXHasBearishPower; + + // + bool isPADXSwitchedToBullishPower = + isZADXHasBullishPower && + isCADXHasBullishPower && + isPADXHasBullishPower && + !isP2ADXHasBullishPower; + + // + bool isPADXSwitchedToBearishPower = + isZADXHasBearishPower && + isCADXHasBearishPower && + isPADXHasBearishPower && + !isP2ADXHasBearishPower; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + ( + // + // Grows ... + isADXUp + // + || + // + // Trending ... + (isCADXSwitchedToBullish || + isPADXSwitchedToBullish) + // + || + // + // Powering ... + (isCADXSwitchedToBullishPower || + isPADXSwitchedToBullishPower) + // + ); + + // + bool isBearishFilterd = + isBearish && + ( + // + // Grows ... + isADXDown + // + || + // + // Trending ... + (isCADXSwitchedToBearish || + isPADXSwitchedToBearish) + // + || + // + // Powering ... + (isCADXSwitchedToBearishPower || + isPADXSwitchedToBearishPower) + // + ); + + // + result = + isBullishFilterd || + isBearishFilterd; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // TREND Filter ... + if (config.filterBasedOnTrend) + { + // + // Reading Conditions Values ... + + // + double zTrend = conditions.trendBuffer[zIDX]; + double cTrend = conditions.trendBuffer[cIDX]; + double pTrend = conditions.trendBuffer[pIDX]; + double p2Trend = conditions.trendBuffer[p2IDX]; + double p3Trend = conditions.trendBuffer[p3IDX]; + double p4Trend = conditions.trendBuffer[p4IDX]; + + // + double trends[] = { + zTrend, + cTrend, + pTrend, + p2Trend, + p3Trend, + p4Trend // + }; + double trendsMin = GetMin(trends); + double trendsMax = GetMax(trends); + double trendsAVG = GetAverage(trends); + + // + double zTrendState = conditions.trendStateBuffer[zIDX]; + double cTrendState = conditions.trendStateBuffer[cIDX]; + double pTrendState = conditions.trendStateBuffer[pIDX]; + double p2TrendState = conditions.trendStateBuffer[p2IDX]; + double p3TrendState = conditions.trendStateBuffer[p3IDX]; + double p4TrendState = conditions.trendStateBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + // Grows ... + + // + bool isTrendUp = + zTrend >= cTrend && + cTrend >= trendsAVG && + cTrend > trendsMin; + + // + bool isTrendDown = + zTrend <= cTrend && + cTrend <= trendsAVG && + cTrend < trendsMax; + + // + // Stating ... + + // + bool isCTrendBullish = + zTrendState > 0 && + cTrendState > 0; + + // + bool isCTrendBearish = + zTrendState < 0 && + cTrendState < 0; + + // + bool isPTrendBullish = + zTrendState > 0 && + cTrendState > 0 && + pTrendState > 0; + + // + bool isPTrendBearish = + zTrendState < 0 && + cTrendState < 0 && + pTrendState < 0; + + // + bool isP2TrendBullish = + zTrendState > 0 && + cTrendState > 0 && + pTrendState > 0 && + p2TrendState > 0; + + // + bool isP2TrendBearish = + zTrendState < 0 && + cTrendState < 0 && + pTrendState < 0 && + p2TrendState < 0; + + // + bool isCTrendSwitchedToBullish = + isCTrendBullish && + !isPTrendBullish; + + // + bool isCTrendSwitchedToBearish = + isCTrendBearish && + !isPTrendBearish; + + // + bool isPTrendSwitchedToBullish = + isCTrendBullish && + isPTrendBullish && + !isP2TrendBullish; + + // + bool isPTrendSwitchedToBearish = + isCTrendBearish && + isPTrendBearish && + !isP2TrendBearish; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + ( + // + // Grows ... + isTrendUp + // + || + // + // Trend Stating ... + (isCTrendBullish && + isPTrendBullish) + // + || + // + // Switching ... + (isCTrendSwitchedToBullish || + isPTrendSwitchedToBullish) + // + ); + + // + bool isBearishFilterd = + isBearish && + ( + // + // Grows ... + isTrendDown + // + || + // + // Trend Stating ... + (isCTrendBearish && + isPTrendBearish) + // + || + // + // Switching ... + (isCTrendSwitchedToBearish || + isPTrendSwitchedToBearish) + // + ); + + // + result = + isBullishFilterd || + isBearishFilterd; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // SCORE Filter ... + + // + // VOLUME Filter ... + } + + // + result = triggerBlock.IsValid(); + if (result) + { + // + triggerBlock.type = + isBullish + ? ToString(XCA_TRIGGER_BULL) + : ToString(XCA_TRIGGER_BEAR); + } + + // + // Cleanup Resources ... + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + if (!result) + { + // + conditions.Clean(); + triggerBlock.Clean(); + } + + // + return result; +}; + +bool DetectTriggerBlock1( + XBoxZone &triggerBlock, + XCAEAConditions &conditions, + XCXCAEAHelper *helper, + XCAEATriggerBlockConfiguration &config, + int bar_index = 0, + int loopback = 6 // +) +{ + // + bool result = false; + + // + conditions.Clean(); + triggerBlock.Clean(); + + // + // Normalize Args ... + loopback = NormalizeInt(loopback, 6); + bar_index = NormalizeInt(bar_index, 0); + + // + // Validate Args ... + result = helper != NULL; + if (!result) + { + return result; + } + + // + // Provide base Requirements ... + + // + string symbol = helper.GetSymbol(); + double points = GetPoints(symbol); + ENUM_TIMEFRAMES period = helper.GetPeriod(); + + // + // Conditions Reading Indexes ... + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + double ll = 0; + double hh = 0; + bool has = false; + ENUM_X_DIRECTION iDir; + + // + // Retrieve Current Conditions ... + result = helper.GetConditions( + conditions, + bar_index, + loopback // + ); + + // + // Retrieve Required Bars ... + + // + XOHCL zBar; // Current Start Checking Bar (Usually Used for Triggering) ... + XOHCL cBar; // Current Finished Bar which Start Detecting Structures based on it ( End of Block and FVG Bar ) ... + XOHCL pBar; // Determines Block Gap Bar (all Filtering must applied and Check using this Bar and it's Next Bar) ... + XOHCL p2Bar; // Determines FVG's Start Bar in a Block ... + XOHCL p3Bar; // First Verification of Block ... + XOHCL p4Bar; // Seccond Verification of Block ... + + // + result = zBar.Init( + symbol, + period, + bar_index // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(p2Bar); + result = + result && + p2Bar.GetPreviousBar(p3Bar); + result = + result && + p3Bar.GetPreviousBar(p4Bar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + + // + // Detect Based Order Block using CBar ... + result = + helper + .barAnalyser + .IsOB( + cBar, + triggerBlock, + true, // Force FVG Bar Type ... + true // Force Block Two Bar Checking ... + ); + + // + // Ensure a Block is Detected ... + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + return result; + + // + // Reading Some Block Based Requirements ... + + // + bool isBullish = + result && + triggerBlock.IsBullish(); + + // + bool isBearish = + result && + triggerBlock.IsBearish(); + + // + int toIDX = triggerBlock.ToIndex(); + int fromIDX = triggerBlock.FromIndex(); + + // + // Start Validating ... + + // + // Validating p2Bar and p3Bar Direction ... + if (result) + { + // + iDir = Opposit(triggerBlock.dir); + + // + result = + iDir == p3Bar.GetDirection() || + iDir == p4Bar.GetDirection(); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // Validating Using Max Range ... + result = config.maxZoneRangeInPoints > 0; + if (result) + { + // + double range = triggerBlock.GetRange(); + result = range <= config.maxZoneRangeInPoints * points; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // Validate Gap Endup with PinBar ... + result = config.forceHasPinBarEntry; + if (result) + { + // + bool isBullishRejected = + isBullish && + cBar.IsBullish() && + cBar.GetLowShadow() > cBar.GetHighShadow(); + + // + bool isBearishRejected = + isBearish && + cBar.IsBearish() && + cBar.GetLowShadow() < cBar.GetHighShadow(); + + // + result = isBullishRejected || + isBearishRejected; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // Validating Gap Bar must a Momentum Bar and + // Breakes out Zone's Directional Edge ... + // for Bullish: Upper + // for Bearish: Lower + result = config.forceGapBarsBreakout; + if (result) + { + // + // Gap Bar is PBar ... + + // + // Check Gap Bar is Momentum Bar ... + result = + helper + .barAnalyser + .IsMomentum( + pBar, + iDir // + ); + bool isBullishMomentum = + result && + IsBullish(iDir); + bool isBearishMomentum = + result && + IsBearish(iDir); + + // + // Check Gap Bar's Breakout ... + + // + bool isBullishBreakedout = + isBullish && + pBar.IsBullish() && + isBullishMomentum && + pBar.GetUp() > triggerBlock.upper && + pBar.GetDown() < triggerBlock.upper; + + // + bool isBearishBreakedout = + isBearish && + pBar.IsBearish() && + isBearishMomentum && + pBar.GetUp() > triggerBlock.lower && + pBar.GetDown() < triggerBlock.lower; + + // + result = isBullishBreakedout || + isBearishBreakedout; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // Validate Zone Has Propper Swing ... + // for Bullish: p2Bar or p3Bar must be a Swing Low ... + // for Bearish: p2Bar or p3Bar must be a Swing High ... + result = config.forceHasSwing; + if (result) + { + // + // p2Bar ... + bool isP2BarSwing = + helper + .barAnalyser + .IsSimpleSwing( + p2Bar, + iDir // + ); + bool isP2BarSwingLow = + isP2BarSwing && + IsBullish(iDir); + bool isP2BarSwingHigh = + isP2BarSwing && + IsBearish(iDir); + + // + // p3Bar ... + bool isP3BarSwing = + helper + .barAnalyser + .IsSimpleSwing( + p3Bar, + iDir // + ); + bool isP3BarSwingLow = + isP3BarSwing && + IsBullish(iDir); + bool isP3BarSwingHigh = + isP3BarSwing && + IsBearish(iDir); + + // + bool hasSwingLow = + isBullish && + (isP2BarSwingLow || + isP3BarSwingLow); + + // + bool hasSwingHigh = + isBearish && + (isP2BarSwingHigh || + isP3BarSwingHigh); + + // + result = + hasSwingLow || + hasSwingHigh; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // Validating Using Swing Length ... + result = config.minZoneLength > 0; + if (result) + { + // + XOHCL fromBar; + has = triggerBlock.FromBar(fromBar); + if (result) + { + // + // Retrieve HH and LL ... + ll = fromBar.FindLowest(config.minZoneLength, MODE_LOW); + hh = fromBar.FindHighest(config.minZoneLength, MODE_HIGH); + + // + // Validate Using HH and LL ... + + // + bool isBullishValid = + isBullish && + ll >= triggerBlock.lower; + + // + bool isBearishValid = + isBearish && + hh <= triggerBlock.upper; + + // + result = isBullishValid || + isBearishValid; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + + // + // Update Zone's From Time ... + triggerBlock.from = GetBarTime( + triggerBlock.symbol, + triggerBlock.period, + fromBar.Index() + config.minZoneLength // + ); + } + + // + fromBar.Clean(); + } + + // + // Validate Max Allowed Entry Distance ... + result = config.maxAllowedEntryDistance > 0; + if (result) + { + // + double base = + isBullish + ? triggerBlock.upper + : triggerBlock.lower; + double entryDistance = MathAbs(zBar.open - base); + result = entryDistance <= config.maxAllowedEntryDistance * points; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // Here we Ensure which have a Valid Zone using Different Applied Validations ... + // from now we are Going to Filterd Validate Zones ... + + // + // Check Exists Filters or not ... + result = config.filterBasedOnSar || + config.filterBasedOnRSI || + config.filterBasedOnADX || + config.filterBasedOnTrend; + if (result) + { + // + // Do Apply Several Exists Filters ... + + // + // SAR Filter ... + if (config.filterBasedOnSar) + { + // + // Reading Conditions Values ... + + // + double zSar = conditions.sarBuffer[zIDX]; + double cSar = conditions.sarBuffer[cIDX]; + double pSar = conditions.sarBuffer[pIDX]; + double p2Sar = conditions.sarBuffer[p2IDX]; + double p3Sar = conditions.sarBuffer[p3IDX]; + double p4Sar = conditions.sarBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + bool isZSarBullish = zSar < zBar.low; + bool isZSarBearish = zSar > zBar.high; + + // + bool isCSarBullish = cSar < cBar.low; + bool isCSarBearish = cSar > cBar.high; + + // + bool isPSarBullish = pSar < pBar.low; + bool isPSarBearish = pSar > pBar.high; + + // + bool isP2SarBullish = p2Sar < p2Bar.low; + bool isP2SarBearish = p2Sar > p2Bar.high; + + // + bool isCSarSwitchedToBullish = + isZSarBullish && + isCSarBullish && + !isPSarBullish && + cBar.IsBullish() && + cBar.GetUp() > pSar; + + // + bool isCSarSwitchedToBearish = + isZSarBearish && + isCSarBearish && + !isPSarBearish && + cBar.IsBearish() && + cBar.GetDown() < pSar; + + // + bool isPSarSwitchedToBullish = + isZSarBullish && + isCSarBullish && + isPSarBullish && + !isP2SarBullish && + pBar.IsBullish() && + pBar.GetUp() > p2Sar; + + // + bool isPSarSwitchedToBearish = + isZSarBearish && + isCSarBearish && + isPSarBearish && + !isP2SarBearish && + pBar.IsBearish() && + pBar.GetDown() < p2Sar; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + (isCSarSwitchedToBullish || + isPSarSwitchedToBullish); + + // + bool isBearishFilterd = + isBearish && + (isCSarSwitchedToBearish || + isPSarSwitchedToBearish); + + // + result = + isBullishFilterd || + isBearishFilterd; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // RSI Filter ... + if (config.filterBasedOnRSI) + { + // + // Reading Conditions Values ... + + // + double rsiTrend = (conditions.rsiOBLevel + conditions.rsiOSLevel) / 2; + + // + double zRSI = conditions.rsiBuffer[zIDX]; + double cRSI = conditions.rsiBuffer[cIDX]; + double pRSI = conditions.rsiBuffer[pIDX]; + double p2RSI = conditions.rsiBuffer[p2IDX]; + double p3RSI = conditions.rsiBuffer[p3IDX]; + double p4RSI = conditions.rsiBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + bool isZRSIBullish = zRSI > rsiTrend; + bool isZRSIBearish = zRSI < rsiTrend; + + // + bool isCRSIBullish = cRSI > rsiTrend; + bool isCRSIBearish = cRSI < rsiTrend; + + // + bool isPRSIBullish = pRSI > rsiTrend; + bool isPRSIBearish = pRSI < rsiTrend; + + // + bool isP2RSIBullish = p2RSI > rsiTrend; + bool isP2RSIBearish = p2RSI < rsiTrend; + + // + bool isP3RSIBullish = p3RSI > rsiTrend; + bool isP3RSIBearish = p3RSI < rsiTrend; + + // + // Trending Conditions ... + + // + bool isCRSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + !isPRSIBullish; + + // + bool isCRSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + !isPRSIBearish; + + // + bool isPRSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + isPRSIBullish && + !isP2RSIBullish; + + // + bool isPRSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + isPRSIBearish && + !isP2RSIBearish; + + // + bool isP2RSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + isPRSIBullish && + isP2RSIBullish && + !isP3RSIBullish; + + // + bool isP2RSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + isPRSIBearish && + isP2RSIBearish && + !isP3RSIBearish; + + // + // Crosses Conditions ... + + // + bool isCBarCrossedOverOS = + zRSI > conditions.rsiOSLevel && + cRSI > conditions.rsiOSLevel && + pRSI <= conditions.rsiOSLevel; + + // + bool isCBarCrossedUnderOB = + zRSI < conditions.rsiOBLevel && + cRSI < conditions.rsiOBLevel && + pRSI >= conditions.rsiOBLevel; + + // + bool isPBarCrossedOverOS = + zRSI > conditions.rsiOSLevel && + cRSI > conditions.rsiOSLevel && + pRSI > conditions.rsiOSLevel && + p2RSI <= conditions.rsiOSLevel; + + // + bool isPBarCrossedUnderOB = + zRSI < conditions.rsiOBLevel && + cRSI < conditions.rsiOBLevel && + pRSI < conditions.rsiOBLevel && + p2RSI >= conditions.rsiOBLevel; + + // + // V Pattern Conditions ... + + // + bool isCRSIHasVBullishPattern = + zRSI >= cRSI && + cRSI > pRSI && + p2RSI > pRSI && + cRSI >= p2RSI; + + // + bool isCRSIHasVBearishPattern = + zRSI <= cRSI && + cRSI < pRSI && + p2RSI < pRSI && + cRSI <= p2RSI; + + // + // Continuation Conditions ... + + // + bool isRSIUp = + zRSI >= cRSI && + (cRSI >= pRSI || + pRSI >= p2RSI || + p2RSI >= p3RSI); + + // + bool isRSIDown = + zRSI <= cRSI && + (cRSI <= pRSI || + pRSI <= p2RSI || + p2RSI <= p3RSI); + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + ( + // + // Grows ... + isRSIUp + // + || + // + // Crosses ... + (isCBarCrossedOverOS || + isPBarCrossedOverOS) + // + || + // + // V Pattern ... + isCRSIHasVBullishPattern + // + || + // + // Trending ... + (isCRSISwitchedToBullish || + isPRSISwitchedToBullish || + isP2RSISwitchedToBullish) + // + ); + + // + bool isBearishFilterd = + isBearish && + ( + // + // Grows ... + isRSIDown + // + || + // + // Crosses ... + (isCBarCrossedUnderOB || + isPBarCrossedUnderOB) + // + || + // + // V Pattern ... + isCRSIHasVBearishPattern + // + || + // + // Trending ... + (isCRSISwitchedToBearish || + isPRSISwitchedToBearish || + isP2RSISwitchedToBearish) + // + ); + + // + result = + isBullishFilterd || + isBearishFilterd; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // ADX Filter ... + if (config.filterBasedOnADX) + { + // + // Reading Conditions Values ... + + // + // ADX ... + double zADX = conditions.adxBuffer[zIDX]; + double cADX = conditions.adxBuffer[cIDX]; + double pADX = conditions.adxBuffer[pIDX]; + double p2ADX = conditions.adxBuffer[p2IDX]; + double p3ADX = conditions.adxBuffer[p3IDX]; + double p4ADX = conditions.adxBuffer[p4IDX]; + + // + // ADX +DI ... + double zADXP = conditions.adxpBuffer[zIDX]; + double cADXP = conditions.adxpBuffer[cIDX]; + double pADXP = conditions.adxpBuffer[pIDX]; + double p2ADXP = conditions.adxpBuffer[p2IDX]; + double p3ADXP = conditions.adxpBuffer[p3IDX]; + double p4ADXP = conditions.adxpBuffer[p4IDX]; + + // + // ADX -DI ... + double zADXN = conditions.adxnBuffer[zIDX]; + double cADXN = conditions.adxnBuffer[cIDX]; + double pADXN = conditions.adxnBuffer[pIDX]; + double p2ADXN = conditions.adxnBuffer[p2IDX]; + double p3ADXN = conditions.adxnBuffer[p3IDX]; + double p4ADXN = conditions.adxnBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + // Grows ... + + // + bool isADXUp = + zADX >= cADX && + (cADX >= pADX || + pADX >= p2ADX); + + // + bool isADXDown = + zADX <= cADX && + (cADX <= pADX || + pADX <= p2ADX); + + // + // Trending ... + + // + bool isZADXBullish = zADX > conditions.adxThreshold; + bool isZADXBearish = zADX < conditions.adxThreshold; + + // + bool isCADXBullish = cADX > conditions.adxThreshold; + bool isCADXBearish = cADX < conditions.adxThreshold; + + // + bool isPADXBullish = pADX > conditions.adxThreshold; + bool isPADXBearish = pADX < conditions.adxThreshold; + + // + bool isP2ADXBullish = p2ADX > conditions.adxThreshold; + bool isP2ADXBearish = p2ADX < conditions.adxThreshold; + + // + bool isP3ADXBullish = p3ADX > conditions.adxThreshold; + bool isP3ADXBearish = p3ADX < conditions.adxThreshold; + + // + bool isP4ADXBullish = p4ADX > conditions.adxThreshold; + bool isP4ADXBearish = p4ADX < conditions.adxThreshold; + + // + bool isCADXSwitchedToBullish = + isZADXBullish && + isCADXBullish && + !isPADXBullish; + + // + bool isCADXSwitchedToBearish = + isZADXBearish && + isCADXBearish && + !isPADXBearish; + + // + bool isPADXSwitchedToBullish = + isZADXBullish && + isCADXBullish && + isPADXBullish && + !isP2ADXBullish; + + // + bool isPADXSwitchedToBearish = + isZADXBearish && + isCADXBearish && + isPADXBearish && + !isP2ADXBearish; + + // + // Powering ... + + // + bool isZADXHasBullishPower = zADXP > zADXN; + bool isZADXHasBearishPower = zADXN > zADXP; + + // + bool isCADXHasBullishPower = cADXP > cADXN; + bool isCADXHasBearishPower = cADXN > cADXP; + + // + bool isPADXHasBullishPower = pADXP > pADXN; + bool isPADXHasBearishPower = pADXN > pADXP; + + // + bool isP2ADXHasBullishPower = p2ADXP > p2ADXN; + bool isP2ADXHasBearishPower = p2ADXN > p2ADXP; + + // + bool isP3ADXHasBullishPower = p3ADXP > p3ADXN; + bool isP3ADXHasBearishPower = p3ADXN > p3ADXP; + + // + bool isP4ADXHasBullishPower = p4ADXP > p4ADXN; + bool isP4ADXHasBearishPower = p4ADXN > p4ADXP; + + // + bool isCADXSwitchedToBullishPower = + isZADXHasBullishPower && + isCADXHasBullishPower && + !isPADXHasBullishPower; + + // + bool isCADXSwitchedToBearishPower = + isZADXHasBearishPower && + isCADXHasBearishPower && + !isPADXHasBearishPower; + + // + bool isPADXSwitchedToBullishPower = + isZADXHasBullishPower && + isCADXHasBullishPower && + isPADXHasBullishPower && + !isP2ADXHasBullishPower; + + // + bool isPADXSwitchedToBearishPower = + isZADXHasBearishPower && + isCADXHasBearishPower && + isPADXHasBearishPower && + !isP2ADXHasBearishPower; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + ( + // + // Grows ... + isADXUp + // + || + // + // Trending ... + (isCADXSwitchedToBullish || + isPADXSwitchedToBullish) + // + || + // + // Powering ... + (isCADXSwitchedToBullishPower || + isPADXSwitchedToBullishPower) + // + ); + + // + bool isBearishFilterd = + isBearish && + ( + // + // Grows ... + isADXDown + // + || + // + // Trending ... + (isCADXSwitchedToBearish || + isPADXSwitchedToBearish) + // + || + // + // Powering ... + (isCADXSwitchedToBearishPower || + isPADXSwitchedToBearishPower) + // + ); + + // + result = + isBullishFilterd || + isBearishFilterd; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // TREND Filter ... + if (config.filterBasedOnTrend) + { + // + // Reading Conditions Values ... + + // + double zTrend = conditions.trendBuffer[zIDX]; + double cTrend = conditions.trendBuffer[cIDX]; + double pTrend = conditions.trendBuffer[pIDX]; + double p2Trend = conditions.trendBuffer[p2IDX]; + double p3Trend = conditions.trendBuffer[p3IDX]; + double p4Trend = conditions.trendBuffer[p4IDX]; + + // + double trends[] = { + zTrend, + cTrend, + pTrend, + p2Trend, + p3Trend, + p4Trend // + }; + double trendsMin = GetMin(trends); + double trendsMax = GetMax(trends); + double trendsAVG = GetAverage(trends); + + // + double zTrendState = conditions.trendStateBuffer[zIDX]; + double cTrendState = conditions.trendStateBuffer[cIDX]; + double pTrendState = conditions.trendStateBuffer[pIDX]; + double p2TrendState = conditions.trendStateBuffer[p2IDX]; + double p3TrendState = conditions.trendStateBuffer[p3IDX]; + double p4TrendState = conditions.trendStateBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + // Grows ... + + // + bool isTrendUp = + zTrend >= cTrend && + cTrend >= trendsAVG && + cTrend > trendsMin; + + // + bool isTrendDown = + zTrend <= cTrend && + cTrend <= trendsAVG && + cTrend < trendsMax; + + // + // Stating ... + + // + bool isCTrendBullish = + zTrendState > 0 && + cTrendState > 0; + + // + bool isCTrendBearish = + zTrendState < 0 && + cTrendState < 0; + + // + bool isPTrendBullish = + zTrendState > 0 && + cTrendState > 0 && + pTrendState > 0; + + // + bool isPTrendBearish = + zTrendState < 0 && + cTrendState < 0 && + pTrendState < 0; + + // + bool isP2TrendBullish = + zTrendState > 0 && + cTrendState > 0 && + pTrendState > 0 && + p2TrendState > 0; + + // + bool isP2TrendBearish = + zTrendState < 0 && + cTrendState < 0 && + pTrendState < 0 && + p2TrendState < 0; + + // + bool isCTrendSwitchedToBullish = + isCTrendBullish && + !isPTrendBullish; + + // + bool isCTrendSwitchedToBearish = + isCTrendBearish && + !isPTrendBearish; + + // + bool isPTrendSwitchedToBullish = + isCTrendBullish && + isPTrendBullish && + !isP2TrendBullish; + + // + bool isPTrendSwitchedToBearish = + isCTrendBearish && + isPTrendBearish && + !isP2TrendBearish; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + ( + // + // Grows ... + isTrendUp + // + || + // + // Trend Stating ... + (isCTrendBullish && + isPTrendBullish) + // + || + // + // Switching ... + (isCTrendSwitchedToBullish || + isPTrendSwitchedToBullish) + // + ); + + // + bool isBearishFilterd = + isBearish && + ( + // + // Grows ... + isTrendDown + // + || + // + // Trend Stating ... + (isCTrendBearish && + isPTrendBearish) + // + || + // + // Switching ... + (isCTrendSwitchedToBearish || + isPTrendSwitchedToBearish) + // + ); + + // + result = + isBullishFilterd || + isBearishFilterd; + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + return result; + } + } + + // + // SCORE Filter ... + + // + // VOLUME Filter ... + } + + // + result = triggerBlock.IsValid(); + if (result) + { + // + triggerBlock.type = + isBullish + ? ToString(XCA_TRIGGER_BULL) + : ToString(XCA_TRIGGER_BEAR); + } + + // + // Cleanup Resources ... + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + if (!result) + { + // + conditions.Clean(); + triggerBlock.Clean(); + } + + // + return result; +} + +/** + * Detect Trigger Block ... + * + * @param trigger: XTriggerBlock instance Reference, hold founded Trigger Block + * @param helper: XCXCAEAHelper instance Reference Pointer, XCAEA Market nalyser Helper for acc Drawer + * @param config: XCAEATriggerBlockConfiguration instance Reference, Trigger Block Detecting Configuration + * @param bar_index: int, Bar Index to Start Detecting + * @param loopback: int, Loopback Bars Count + * + * @return ( bool ) + */ +bool DetectTriggerBlock( + XTriggerBlock &trigger, + XCXCAEAHelper *helper, + XCAEATriggerBlockConfiguration &config, + int bar_index = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Normalize Args ... + trigger.Clean(); + loopback = NormalizeInt(loopback, 10); + bar_index = NormalizeInt(bar_index, 0); + + // + // Validate Args ... + result = helper != NULL; + if (!result) + { + return result; + } + + // + // Extract Required Informations ... + + // + string symbol = helper.GetSymbol(); + ENUM_TIMEFRAMES period = helper.GetPeriod(); + + // + double points = GetPoints(symbol); + + // + // Retrieve Indexed Bar ... + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + result = zBar.Init( + symbol, + period, + bar_index // + ); + result = result && + zBar.GetPreviousBar(cBar); + result = result && + cBar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + // Check Trigger Block Exists ... + result = + result && + helper + .barAnalyser + .IsTrigger( + cBar, + trigger.trigger, + trigger.ob, + trigger.fvg, + trigger.rLiquidity, + trigger.fLiquidity, + trigger.swingBar, + loopback, + config.maxAllowedRange, + config.minAllowedBlockEdgeLength, + config.forceOBOppositBar, + config.forceFVGBarType, + config.forceGapBarBreakout, + config.forceHasSwingBar, + config.forceHasLiquidity, + config.forceHasReversalLiquidity // + ); + + // + // Now we Have to Implement Required Validations ... + + // + bool isBullish = trigger.trigger.IsBullish(); + bool isBearish = trigger.trigger.IsBearish(); + + // + // First Reading Market Conditions ... + result = + result && + helper.GetConditions( + trigger.conditions, + bar_index, + loopback // + ); + + // + // All Custom andAdditional Validations and Filters + // Applied here ... + + // + // SAR Filter ... + if (config.filterBasedOnSar) + { + // + if (result) + { + // + // Reading Values ... + + // + double zSar = trigger.conditions.sarBuffer[zIDX]; + double cSar = trigger.conditions.sarBuffer[cIDX]; + double pSar = trigger.conditions.sarBuffer[pIDX]; + double p2Sar = trigger.conditions.sarBuffer[p2IDX]; + double p3Sar = trigger.conditions.sarBuffer[p3IDX]; + double p4Sar = trigger.conditions.sarBuffer[p4IDX]; + + // + // Preparing Conditions ... + + // + bool isZSarBullish = zSar < zBar.low; + bool isZSarBearish = zSar > zBar.high; + + // + bool isCSarBullish = cSar < cBar.low; + bool isCSarBearish = cSar > cBar.high; + + // + bool isPSarBullish = pSar < pBar.low; + bool isPSarBearish = pSar > pBar.high; + + // + bool isP2SarBullish = p2Sar < p2Bar.low; + bool isP2SarBearish = p2Sar > p2Bar.high; + + // + bool isCSarSwitchedToBullish = + isZSarBullish && + isCSarBullish && + !isPSarBullish && + cBar.IsBullish() && + cBar.GetUp() > pSar; + + // + bool isCSarSwitchedToBearish = + isZSarBearish && + isCSarBearish && + !isPSarBearish && + cBar.IsBearish() && + cBar.GetDown() < pSar; + + // + bool isPSarSwitchedToBullish = + isZSarBullish && + isCSarBullish && + isPSarBullish && + !isP2SarBullish && + pBar.IsBullish() && + pBar.GetUp() > p2Sar; + + // + bool isPSarSwitchedToBearish = + isZSarBearish && + isCSarBearish && + isPSarBearish && + !isP2SarBearish && + pBar.IsBearish() && + pBar.GetDown() < p2Sar; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + (isCSarSwitchedToBullish || + isPSarSwitchedToBullish); + + // + bool isBearishFilterd = + isBearish && + (isCSarSwitchedToBearish || + isPSarSwitchedToBearish); + + // + // Apply Result .... + + // + result = + result && + (isBullishFilterd || + isBearishFilterd); + } + } + + // + // RSI Filter ... + if (config.filterBasedOnRSI) + { + // + if (result) + { + // + // Reading Values ... + + // + double rsiTrend = (trigger.conditions.rsiOBLevel + trigger.conditions.rsiOSLevel) / 2; + + // + double zRSI = trigger.conditions.rsiBuffer[zIDX]; + double cRSI = trigger.conditions.rsiBuffer[cIDX]; + double pRSI = trigger.conditions.rsiBuffer[pIDX]; + double p2RSI = trigger.conditions.rsiBuffer[p2IDX]; + double p3RSI = trigger.conditions.rsiBuffer[p3IDX]; + double p4RSI = trigger.conditions.rsiBuffer[p4IDX]; + + // + // Preparing Conditions ... + + // + bool isZRSIBullish = zRSI > rsiTrend; + bool isZRSIBearish = zRSI < rsiTrend; + + // + bool isCRSIBullish = cRSI > rsiTrend; + bool isCRSIBearish = cRSI < rsiTrend; + + // + bool isPRSIBullish = pRSI > rsiTrend; + bool isPRSIBearish = pRSI < rsiTrend; + + // + bool isP2RSIBullish = p2RSI > rsiTrend; + bool isP2RSIBearish = p2RSI < rsiTrend; + + // + bool isP3RSIBullish = p3RSI > rsiTrend; + bool isP3RSIBearish = p3RSI < rsiTrend; + + // + // Trending Conditions ... + + // + bool isCRSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + !isPRSIBullish; + + // + bool isCRSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + !isPRSIBearish; + + // + bool isPRSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + isPRSIBullish && + !isP2RSIBullish; + + // + bool isPRSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + isPRSIBearish && + !isP2RSIBearish; + + // + bool isP2RSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + isPRSIBullish && + isP2RSIBullish && + !isP3RSIBullish; + + // + bool isP2RSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + isPRSIBearish && + isP2RSIBearish && + !isP3RSIBearish; + + // + // Crosses Conditions ... + + // + bool isCBarCrossedOverOS = + zRSI > trigger.conditions.rsiOSLevel && + cRSI > trigger.conditions.rsiOSLevel && + pRSI <= trigger.conditions.rsiOSLevel; + + // + bool isCBarCrossedUnderOB = + zRSI < trigger.conditions.rsiOBLevel && + cRSI < trigger.conditions.rsiOBLevel && + pRSI >= trigger.conditions.rsiOBLevel; + + // + bool isPBarCrossedOverOS = + zRSI > trigger.conditions.rsiOSLevel && + cRSI > trigger.conditions.rsiOSLevel && + pRSI > trigger.conditions.rsiOSLevel && + p2RSI <= trigger.conditions.rsiOSLevel; + + // + bool isPBarCrossedUnderOB = + zRSI < trigger.conditions.rsiOBLevel && + cRSI < trigger.conditions.rsiOBLevel && + pRSI < trigger.conditions.rsiOBLevel && + p2RSI >= trigger.conditions.rsiOBLevel; + + // + // V Pattern Conditions ... + + // + bool isCRSIHasVBullishPattern = + zRSI >= cRSI && + cRSI > pRSI && + p2RSI > pRSI && + cRSI >= p2RSI; + + // + bool isCRSIHasVBearishPattern = + zRSI <= cRSI && + cRSI < pRSI && + p2RSI < pRSI && + cRSI <= p2RSI; + + // + // Continuation Conditions ... + + // + bool isRSIUp = + zRSI >= cRSI && + (cRSI >= pRSI || + pRSI >= p2RSI || + p2RSI >= p3RSI); + + // + bool isRSIDown = + zRSI <= cRSI && + (cRSI <= pRSI || + pRSI <= p2RSI || + p2RSI <= p3RSI); + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + ( + // + // Grows ... + isRSIUp + // + || + // + // Crosses ... + (isCBarCrossedOverOS || + isPBarCrossedOverOS) + // + || + // + // V Pattern ... + isCRSIHasVBullishPattern + // + || + // + // Trending ... + (isCRSISwitchedToBullish || + isPRSISwitchedToBullish || + isP2RSISwitchedToBullish) + // + ); + + // + bool isBearishFilterd = + isBearish && + ( + // + // Grows ... + isRSIDown + // + || + // + // Crosses ... + (isCBarCrossedUnderOB || + isPBarCrossedUnderOB) + // + || + // + // V Pattern ... + isCRSIHasVBearishPattern + // + || + // + // Trending ... + (isCRSISwitchedToBearish || + isPRSISwitchedToBearish || + isP2RSISwitchedToBearish) + // + ); + + // + // Apply Result .... + + // + result = + result && + (isBullishFilterd || + isBearishFilterd); + } + } + + // + // ADX Filter ... + if (config.filterBasedOnADX) + { + // + if (result) + { + // + // Reading Values ... + + // + // ADX ... + double zADX = trigger.conditions.adxBuffer[zIDX]; + double cADX = trigger.conditions.adxBuffer[cIDX]; + double pADX = trigger.conditions.adxBuffer[pIDX]; + double p2ADX = trigger.conditions.adxBuffer[p2IDX]; + double p3ADX = trigger.conditions.adxBuffer[p3IDX]; + double p4ADX = trigger.conditions.adxBuffer[p4IDX]; + + // + // ADX +DI ... + double zADXP = trigger.conditions.adxpBuffer[zIDX]; + double cADXP = trigger.conditions.adxpBuffer[cIDX]; + double pADXP = trigger.conditions.adxpBuffer[pIDX]; + double p2ADXP = trigger.conditions.adxpBuffer[p2IDX]; + double p3ADXP = trigger.conditions.adxpBuffer[p3IDX]; + double p4ADXP = trigger.conditions.adxpBuffer[p4IDX]; + + // + // ADX -DI ... + double zADXN = trigger.conditions.adxnBuffer[zIDX]; + double cADXN = trigger.conditions.adxnBuffer[cIDX]; + double pADXN = trigger.conditions.adxnBuffer[pIDX]; + double p2ADXN = trigger.conditions.adxnBuffer[p2IDX]; + double p3ADXN = trigger.conditions.adxnBuffer[p3IDX]; + double p4ADXN = trigger.conditions.adxnBuffer[p4IDX]; + + // + // Preparing Conditions ... + + // + // Grows ... + + // + bool isADXUp = + zADX >= cADX && + (cADX >= pADX || + pADX >= p2ADX); + + // + bool isADXDown = + zADX <= cADX && + (cADX <= pADX || + pADX <= p2ADX); + + // + // Trending ... + + // + bool isZADXBullish = zADX > trigger.conditions.adxThreshold; + bool isZADXBearish = zADX < trigger.conditions.adxThreshold; + + // + bool isCADXBullish = cADX > trigger.conditions.adxThreshold; + bool isCADXBearish = cADX < trigger.conditions.adxThreshold; + + // + bool isPADXBullish = pADX > trigger.conditions.adxThreshold; + bool isPADXBearish = pADX < trigger.conditions.adxThreshold; + + // + bool isP2ADXBullish = p2ADX > trigger.conditions.adxThreshold; + bool isP2ADXBearish = p2ADX < trigger.conditions.adxThreshold; + + // + bool isP3ADXBullish = p3ADX > trigger.conditions.adxThreshold; + bool isP3ADXBearish = p3ADX < trigger.conditions.adxThreshold; + + // + bool isP4ADXBullish = p4ADX > trigger.conditions.adxThreshold; + bool isP4ADXBearish = p4ADX < trigger.conditions.adxThreshold; + + // + bool isCADXSwitchedToBullish = + isZADXBullish && + isCADXBullish && + !isPADXBullish; + + // + bool isCADXSwitchedToBearish = + isZADXBearish && + isCADXBearish && + !isPADXBearish; + + // + bool isPADXSwitchedToBullish = + isZADXBullish && + isCADXBullish && + isPADXBullish && + !isP2ADXBullish; + + // + bool isPADXSwitchedToBearish = + isZADXBearish && + isCADXBearish && + isPADXBearish && + !isP2ADXBearish; + + // + // Powering ... + + // + bool isZADXHasBullishPower = zADXP > zADXN; + bool isZADXHasBearishPower = zADXN > zADXP; + + // + bool isCADXHasBullishPower = cADXP > cADXN; + bool isCADXHasBearishPower = cADXN > cADXP; + + // + bool isPADXHasBullishPower = pADXP > pADXN; + bool isPADXHasBearishPower = pADXN > pADXP; + + // + bool isP2ADXHasBullishPower = p2ADXP > p2ADXN; + bool isP2ADXHasBearishPower = p2ADXN > p2ADXP; + + // + bool isP3ADXHasBullishPower = p3ADXP > p3ADXN; + bool isP3ADXHasBearishPower = p3ADXN > p3ADXP; + + // + bool isP4ADXHasBullishPower = p4ADXP > p4ADXN; + bool isP4ADXHasBearishPower = p4ADXN > p4ADXP; + + // + bool isCADXSwitchedToBullishPower = + isZADXHasBullishPower && + isCADXHasBullishPower && + !isPADXHasBullishPower; + + // + bool isCADXSwitchedToBearishPower = + isZADXHasBearishPower && + isCADXHasBearishPower && + !isPADXHasBearishPower; + + // + bool isPADXSwitchedToBullishPower = + isZADXHasBullishPower && + isCADXHasBullishPower && + isPADXHasBullishPower && + !isP2ADXHasBullishPower; + + // + bool isPADXSwitchedToBearishPower = + isZADXHasBearishPower && + isCADXHasBearishPower && + isPADXHasBearishPower && + !isP2ADXHasBearishPower; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + ( + // + // Grows ... + isADXUp + // + || + // + // Trending ... + (isCADXSwitchedToBullish || + isPADXSwitchedToBullish) + // + || + // + // Powering ... + (isCADXSwitchedToBullishPower || + isPADXSwitchedToBullishPower) + // + ); + + // + bool isBearishFilterd = + isBearish && + ( + // + // Grows ... + isADXDown + // + || + // + // Trending ... + (isCADXSwitchedToBearish || + isPADXSwitchedToBearish) + // + || + // + // Powering ... + (isCADXSwitchedToBearishPower || + isPADXSwitchedToBearishPower) + // + ); + + // + // Apply Result .... + + // + result = + result && + (isBullishFilterd || + isBearishFilterd); + } + } + + // + // TREND Filter ... + if (config.filterBasedOnTrend) + { + // + if (result) + { + // + // Reading Values ... + + // + double zTrend = trigger.conditions.trendBuffer[zIDX]; + double cTrend = trigger.conditions.trendBuffer[cIDX]; + double pTrend = trigger.conditions.trendBuffer[pIDX]; + double p2Trend = trigger.conditions.trendBuffer[p2IDX]; + double p3Trend = trigger.conditions.trendBuffer[p3IDX]; + double p4Trend = trigger.conditions.trendBuffer[p4IDX]; + + // + double trends[] = { + zTrend, + cTrend, + pTrend, + p2Trend, + p3Trend, + p4Trend // + }; + double trendsMin = GetMin(trends); + double trendsMax = GetMax(trends); + double trendsAVG = GetAverage(trends); + + // + double zTrendState = trigger.conditions.trendStateBuffer[zIDX]; + double cTrendState = trigger.conditions.trendStateBuffer[cIDX]; + double pTrendState = trigger.conditions.trendStateBuffer[pIDX]; + double p2TrendState = trigger.conditions.trendStateBuffer[p2IDX]; + double p3TrendState = trigger.conditions.trendStateBuffer[p3IDX]; + double p4TrendState = trigger.conditions.trendStateBuffer[p4IDX]; + + // + // Preparing Conditions ... + + // + // Grows ... + + // + bool isTrendUp = + zTrend >= cTrend && + cTrend >= trendsAVG && + cTrend > trendsMin; + + // + bool isTrendDown = + zTrend <= cTrend && + cTrend <= trendsAVG && + cTrend < trendsMax; + + // + // Stating ... + + // + bool isCTrendBullish = + zTrendState > 0 && + cTrendState > 0; + + // + bool isCTrendBearish = + zTrendState < 0 && + cTrendState < 0; + + // + bool isPTrendBullish = + zTrendState > 0 && + cTrendState > 0 && + pTrendState > 0; + + // + bool isPTrendBearish = + zTrendState < 0 && + cTrendState < 0 && + pTrendState < 0; + + // + bool isP2TrendBullish = + zTrendState > 0 && + cTrendState > 0 && + pTrendState > 0 && + p2TrendState > 0; + + // + bool isP2TrendBearish = + zTrendState < 0 && + cTrendState < 0 && + pTrendState < 0 && + p2TrendState < 0; + + // + bool isCTrendSwitchedToBullish = + isCTrendBullish && + !isPTrendBullish; + + // + bool isCTrendSwitchedToBearish = + isCTrendBearish && + !isPTrendBearish; + + // + bool isPTrendSwitchedToBullish = + isCTrendBullish && + isPTrendBullish && + !isP2TrendBullish; + + // + bool isPTrendSwitchedToBearish = + isCTrendBearish && + isPTrendBearish && + !isP2TrendBearish; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + ( + // + // Grows ... + isTrendUp + // + || + // + // Trend Stating ... + (isCTrendBullish && + isPTrendBullish) + // + || + // + // Switching ... + (isCTrendSwitchedToBullish || + isPTrendSwitchedToBullish) + // + ); + + // + bool isBearishFilterd = + isBearish && + ( + // + // Grows ... + isTrendDown + // + || + // + // Trend Stating ... + (isCTrendBearish && + isPTrendBearish) + // + || + // + // Switching ... + (isCTrendSwitchedToBearish || + isPTrendSwitchedToBearish) + // + ); + + // + // Apply Result .... + + // + result = + result && + (isBullishFilterd || + isBearishFilterd); + } + } + + // + // SCORE Filter ... + if (config.filterBasedOnScores) + { + // + if (result) + { + // + // Reading Values ... + + // + double bullishScore = 0; + double bearishScore = 0; + + // + trigger.conditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // + // Preparing Conditions ... + + // + bool isScoreBullish = bullishScore > bearishScore; + bool isScoreBearish = bearishScore > bullishScore; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + isScoreBullish; + + // + bool isBearishFilterd = + isBearish && + isScoreBearish; + + // + // Apply Result .... + + // + result = + result && + (isBullishFilterd || + isBearishFilterd); + } + } + + // + // VOLUME Filter ... + if (config.filterBasedOnVolumes) + { + // + if (result) + { + // + // Reading Values ... + + // + double bullishVolume = 0; + double bearishVolume = 0; + + // + helper + .barAnalyser + .CalculateRangeVolume( + zBar, + bullishVolume, + bearishVolume, + loopback // + ); + + // + // Preparing Conditions ... + + // + bool isVolumeBullish = bullishVolume > bearishVolume; + bool isVolumeBearish = bearishVolume > bullishVolume; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + isVolumeBullish; + + // + bool isBearishFilterd = + isBearish && + isVolumeBearish; + + // + // Apply Result .... + + // + result = + result && + (isBullishFilterd || + isBearishFilterd); + } + } + + // + // Cleanup Resources ... + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + if (!result) + { + trigger.Clean(); + } + + // + // Attach Configuration if Trigger Block Founded ... + if (result) + { + trigger.configuration = config; + } + + // + return result; +} + +/** + * Draw Specified Trigger Block ... + * + * @param trigger: XTriggerBlock instance Reference, specified Trigger Block to Draw + * @param objects: CArrayObj instance Reference Pointer, Objects Array for Providing Drawn Objects + * @param helper: XCXCAEAHelper instance Reference Pointer, XCAEA Market nalyser Helper for acc Drawer + * @param to: datetime, specified Time for update Trigger parts + * + * @return ( bool ) + */ +bool DrawTriggerBlock( + XTriggerBlock &trigger, + CArrayObj *&objects, + XCXCAEAHelper *helper, + datetime to = NULL // +) +{ + // + bool result = false; + + // + // Validate Args ... + result = helper != NULL && + trigger.IsValid(); + if (!result) + { + return result; + } + + // + // Update To ... + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + // + trigger.trigger.to = to; + trigger.rLiquidity.to = to; + trigger.fLiquidity.to = to; + } + + // + // Draw OB ... + if (trigger.ob.IsValid()) + { + // + XCBoxObject *iOBObj; + result = helper.poiDrawer.DrawBox( + trigger.ob, + iOBObj // + ); + if (result) + { + objects.Add(iOBObj); + } + ZeroMemory(iOBObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw FVG ... + if (trigger.fvg.IsValid()) + { + // + XCBoxObject *iFVGObj; + result = helper.poiDrawer.DrawBox( + trigger.fvg, + iFVGObj // + ); + if (result) + { + // + // Style Object ... + color clr = + trigger.fvg.IsBullish() + ? clrAqua + : clrMagenta; + iFVGObj.BoxWidth(2); + iFVGObj.BoxColor(clr); + iFVGObj.BoxStyle(STYLE_SOLID); + + // + // Store Object ... + objects.Add(iFVGObj); + } + ZeroMemory(iFVGObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Trigger ... + if (trigger.trigger.IsValid()) + { + // + XCBoxObject *iTriggerObj; + result = helper.poiDrawer.DrawBox( + trigger.trigger, + iTriggerObj // + ); + if (result) + { + objects.Add(iTriggerObj); + } + ZeroMemory(iTriggerObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Liquidities ... + + // + // Reversla Liquidity ... + if (trigger.rLiquidity.IsValid()) + { + // + XCBoxObject *iLiqObj; + result = helper.poiDrawer.DrawBox( + trigger.rLiquidity, + iLiqObj // + ); + if (result) + { + objects.Add(iLiqObj); + } + ZeroMemory(iLiqObj); + + // + if (!result) + { + return result; + } + } + + // + // Following Liquidity ... + if (trigger.fLiquidity.IsValid()) + { + // + XCBoxObject *iLiqObj; + result = helper.poiDrawer.DrawBox( + trigger.fLiquidity, + iLiqObj // + ); + if (result) + { + objects.Add(iLiqObj); + } + ZeroMemory(iLiqObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Swing Bar ... + if (trigger.swingBar.IsValid()) + { + // + color swingColor = + trigger.fvg.IsBullish() + ? clrAqua + : clrMagenta; + ENUM_X_PRICE swingPType = + trigger.fvg.IsBullish() + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + XCBarArrowObject *swingObj; + result = helper.poiDrawer.CreateBarArrow( + trigger.swingBar, + swingObj, + swingPType, + 159, + swingColor // + ); + if (result) + { + objects.Add(swingObj); + } + ZeroMemory(swingObj); + + // + if (!result) + { + return result; + } + } + + // + return result; +} + +// \ No newline at end of file diff --git a/Experts/test.mq5 b/Experts/test.mq5 index e2c050ca..c0f9ebae 100644 --- a/Experts/test.mq5 +++ b/Experts/test.mq5 @@ -13,6 +13,7 @@ // Include Common Library ... #include "../Libraries/x-saherelm.common.lib.mq5" #include "../XCAEA/Helpers/xcaea.helper.mq5" +#include "../XCAEA/Libraries/xcaea.trigger.block.lib.mq5" // // Variables ... @@ -20,6 +21,7 @@ XCAEAInputs eaInputs; XCXCAEAHelper *eaHelper; XBarTracker eaBarTraker; +// CArrayObj eaObjects; //+------------------------------------------------------------------+ @@ -44,6 +46,7 @@ int OnInit() // // we Can make Show all requirements here ... + eaInputs.caInputs.showSar = true; // eaHelper = new XCXCAEAHelper(); @@ -67,14 +70,14 @@ int OnInit() void OnDeinit(const int reason) { // - eaObjects.Clear(); + // eaObjects.Clear(); // eaBarTraker.Clean(); // - // delete eaHelper; - // ZeroMemory(eaHelper); + delete eaHelper; + ZeroMemory(eaHelper); } //+------------------------------------------------------------------+ @@ -120,126 +123,67 @@ void OnTick() } // - // Here Do What we Want ... - XOHCL swingBar; - XBoxZone ob; - XBoxZone fvg; - XBoxZone trigger; - XBoxZone liquidity; - has = eaHelper - .barAnalyser - .IsTrigger( - cBar, - trigger, - ob, - fvg, - liquidity, - swingBar, - 10 // - ); + // Define Trigger Block ... + XTriggerBlock tb; + XCAEATriggerBlockConfiguration tbConfig; + + // + // Configure Detector ... + + // + // Validation ... + tbConfig.maxAllowedRange = 0.0; + tbConfig.minAllowedBlockEdgeLength = 7; + + // + // Validation ... + tbConfig.forceFVGBarType = true; + tbConfig.forceHasSwingBar = true; + tbConfig.forceOBOppositBar = true; + tbConfig.forceHasLiquidity = false; + tbConfig.forceGapBarBreakout = true; + tbConfig.forceHasReversalLiquidity = true; + + // + // Filters ... + tbConfig.filterBasedOnSar = true; + tbConfig.filterBasedOnADX = true; + tbConfig.filterBasedOnRSI = true; + tbConfig.filterBasedOnTrend = true; + tbConfig.filterBasedOnScores = true; + tbConfig.filterBasedOnVolumes = true; + + // + // Do Detection ... + has = DetectTriggerBlock( + tb, + eaHelper, + tbConfig, + zBar.Index(), + 10 // + ); if (has) { // - bool isBullish = trigger.IsBullish(); + CArrayObj *tObjects; + tObjects = new CArrayObj(); // - // ob.to = zBar.time; - // fvg.to = zBar.time; - trigger.to = zBar.time; - liquidity.to = zBar.time; - - // - // Draw OB ... - XCBoxObject *iOBObj; - has = eaHelper.poiDrawer.DrawBox( - ob, - iOBObj // + has = DrawTriggerBlock( + tb, + tObjects, + eaHelper, + zBar.time // ); if (has) { - eaObjects.Add(iOBObj); - } - ZeroMemory(iOBObj); - - // - // Draw FVG ... - XCBoxObject *iFVGObj; - has = eaHelper.poiDrawer.DrawBox( - fvg, - iFVGObj // - ); - if (has) - { - // - // Style Object ... - color clr = - isBullish - ? clrAqua - : clrMagenta; - iFVGObj.BoxWidth(2); - iFVGObj.BoxColor(clr); - iFVGObj.BoxStyle(STYLE_SOLID); - - // - // Store Object ... - eaObjects.Add(iFVGObj); - } - ZeroMemory(iFVGObj); - - // - // Draw Trigger ... - XCBoxObject *iTriggerObj; - has = eaHelper.poiDrawer.DrawBox( - trigger, - iTriggerObj // - ); - if (has) - { - eaObjects.Add(iTriggerObj); - } - ZeroMemory(iTriggerObj); - - // - // Draw Liquidity ... - XCBoxObject *iLiqObj; - has = eaHelper.poiDrawer.DrawBox( - liquidity, - iLiqObj // - ); - if (has) - { - eaObjects.Add(iLiqObj); - } - ZeroMemory(iLiqObj); - - // - // Draw Swing Bar ... - color swingColor = - isBullish - ? clrAqua - : clrMagenta; - ENUM_X_PRICE swingPType = - isBullish - ? X_PRICE_LOW - : X_PRICE_HIGH; - - // - XCBarArrowObject *swingObj; - has = eaHelper.poiDrawer.CreateBarArrow( - swingBar, - swingObj, - swingPType, - 159, - swingColor // - ); - if (has) - { - eaObjects.Add(swingObj); + AddObjects(tObjects, eaObjects); } // - Print("Trigger Box Detected ..."); + Print("Trigger Block Detected ..."); } + tb.Clean(); // // Do What we Want ... @@ -250,11 +194,8 @@ void OnTick() // Cleanup Resources ... // - ob.Clean(); - fvg.Clean(); + tb.Clean(); zBar.Clean(); cBar.Clean(); - trigger.Clean(); - swingBar.Clean(); - liquidity.Clean(); + tbConfig.Clean(); } diff --git a/XCAEA/Libraries/xcaea.trigger.block.lib.mq5 b/XCAEA/Libraries/xcaea.trigger.block.lib.mq5 index 1517b562..d8240f9d 100644 --- a/XCAEA/Libraries/xcaea.trigger.block.lib.mq5 +++ b/XCAEA/Libraries/xcaea.trigger.block.lib.mq5 @@ -87,20 +87,29 @@ struct XCAEATriggerBlockConfiguration // Props ... // - // Validating ... - int minZoneLength; // Minimum Length of Consolidation Zone - bool forceHasSwing; // Force Zone's Has Propper Swing - bool forceHasPinBarEntry; // Force Zone's Ends with a Pin Bar - bool forceGapBarsBreakout; // Force Zone's Gap Bar's Breakes Out - double maxZoneRangeInPoints; // Max Zone Range in Point - double maxAllowedEntryDistance; // Max Allowed Entry Distance + // Trigger Detection ... + + // + double maxAllowedRange; // Maximum Allowed Range + int minAllowedBlockEdgeLength; // Minimum Required Block Edge Length + + // + // Validation ... + bool forceOBOppositBar; // Force OB to Start by Opposit Bars + bool forceFVGBarType; // Force FVG to Has Same Type of Bars + bool forceGapBarBreakout; // Force FVG's Gap Bar to Breakeout OB Edge Side + bool forceHasSwingBar; // Force Has Propper Swing + bool forceHasLiquidity; // Force Has Following Liquidity Zone + bool forceHasReversalLiquidity; // Force Has Reversal Liquidity Zone // // Filtering ... - bool filterBasedOnSar; // Filter Pivots Based on Sar - bool filterBasedOnRSI; // Filter Pivots Based on RSI - bool filterBasedOnADX; // Filter Pivots Based on ADX - bool filterBasedOnTrend; // Filter Pivots Based on Trend + bool filterBasedOnSar; // Filter Trigger Block Based on Sar + bool filterBasedOnRSI; // Filter Trigger Block Based on RSI + bool filterBasedOnADX; // Filter Trigger Block Based on ADX + bool filterBasedOnTrend; // Filter Trigger Block Based on Trend + bool filterBasedOnScores; // Filter Trigger Block Based on Scores + bool filterBasedOnVolumes; // Filter Trigger Block Based on Volumes // // Constructor ... @@ -117,15 +126,17 @@ struct XCAEATriggerBlockConfiguration void Clean() { // + // Validating ... + maxAllowedRange = false; + minAllowedBlockEdgeLength = false; // - // Validating ... - minZoneLength = 0; - forceHasSwing = false; - maxZoneRangeInPoints = 0.0; - forceHasPinBarEntry = false; - forceGapBarsBreakout = false; - maxAllowedEntryDistance = 0.0; + forceOBOppositBar = false; + forceFVGBarType = false; + forceGapBarBreakout = false; + forceHasSwingBar = false; + forceHasLiquidity = false; + forceHasReversalLiquidity = false; // // Filtering ... @@ -133,6 +144,8 @@ struct XCAEATriggerBlockConfiguration filterBasedOnRSI = false; filterBasedOnADX = false; filterBasedOnTrend = false; + filterBasedOnScores = false; + filterBasedOnVolumes = false; // ZeroMemory(this); @@ -142,166 +155,63 @@ struct XCAEATriggerBlockConfiguration // Preset Configurations ... // - // Commons Verifications which used in all - // Preset Configurations ... - void ConfigureCommons() +}; + +// +struct XTriggerBlock +{ + // + // Props ... + XBoxZone ob; // Order Block + XBoxZone fvg; // Fair Value Gap + XOHCL swingBar; // Swing of Trigger + XBoxZone trigger; // Trigger Block + XBoxZone rLiquidity; // Reversal Liquidity + XBoxZone fLiquidity; // Following Liquidity + XCAEAConditions conditions; // Market Conditions + XCAEATriggerBlockConfiguration configuration; // Detection Configuration + + // + // Constructor ... + XTriggerBlock() { - // - minZoneLength = 7; - forceHasSwing = true; - maxZoneRangeInPoints = 70; - forceHasPinBarEntry = true; - forceGapBarsBreakout = true; - maxAllowedEntryDistance = 30; + Clean(); } // - // Cleanup Range Verifications ... - void CleanRanges() + // Tools ... + + // + // Cleanup ... + void Clean() { // - maxZoneRangeInPoints = 0; - maxAllowedEntryDistance = 0; + ob.Clean(); + fvg.Clean(); + trigger.Clean(); + swingBar.Clean(); + rLiquidity.Clean(); + fLiquidity.Clean(); + conditions.Clean(); + + // + ZeroMemory(this); } // - void ConfigureFullFilter() + // Validate ... + bool IsValid() { // - // Apply Common Configurations ... - ConfigureCommons(); + bool result = false; // - // Apply Full Filters ... - filterBasedOnSar = true; - filterBasedOnRSI = true; - filterBasedOnADX = true; - filterBasedOnTrend = true; - } - - // - void ConfigureFullFilterNoRange() - { - // - // Apply Common Configurations ... - ConfigureCommons(); + result = ob.IsValid() && + fvg.IsValid() && + trigger.IsValid(); // - // Clean Ranges ... - CleanRanges(); - - // - // Apply Full Filters ... - filterBasedOnSar = true; - filterBasedOnRSI = true; - filterBasedOnADX = true; - filterBasedOnTrend = true; - } - - // - void ConfigureSarRsiAdxFilter() - { - // - ConfigureFullFilter(); - - // - filterBasedOnTrend = false; - } - - // - void ConfigureSarRsiTrendFilter() - { - // - ConfigureFullFilter(); - - // - filterBasedOnADX = false; - } - - // - void ConfigureSarAdxTrendFilter() - { - // - ConfigureFullFilter(); - - // - filterBasedOnRSI = false; - } - - // - void ConfigureRsiAdxTrendFilter() - { - // - ConfigureFullFilter(); - - // - filterBasedOnSar = false; - } - - // - void ConfigureSarRsiFilter() - { - // - ConfigureFullFilter(); - - // - filterBasedOnADX = false; - filterBasedOnTrend = false; - } - - // - void ConfigureSarAdxFilter() - { - // - ConfigureFullFilter(); - - // - filterBasedOnRSI = false; - filterBasedOnTrend = false; - } - - // - void ConfigureSarTrendFilter() - { - // - ConfigureFullFilter(); - - // - filterBasedOnRSI = false; - filterBasedOnADX = false; - } - - // - void ConfigureRsiAdxFilter() - { - // - ConfigureFullFilter(); - - // - filterBasedOnSar = false; - filterBasedOnTrend = false; - } - - // - void ConfigureRsiTrendFilter() - { - // - ConfigureFullFilter(); - - // - filterBasedOnSar = false; - filterBasedOnADX = false; - } - - // - void ConfigureAdxTrendFilter() - { - // - ConfigureFullFilter(); - - // - filterBasedOnSar = false; - filterBasedOnRSI = false; + return result; } // @@ -311,36 +221,31 @@ struct XCAEATriggerBlockConfiguration // Extensions ... /** - * Detect a Trigger Block ... + * Detect Trigger Block ... * - * @param triggerBlock: XBoxZone instance reference, The Detected Trigger Block ... - * @param conditions: XCAEAConditions instance reference, The Block Verification Conditions ... - * @param helper: XCXCAEAHelper instance pointer, Specified The Helper Class Instance which used to Detect Conditions ... - * @param config: XCAEATriggerBlockConfiguration instance reference, Specified The Trigger Block Detection Configuration ... - * @param bar_index: int, Specified The Bar Index to Start Detection ... - * @param loopback: int, Specified The Loopback Length to Detect Helper Conditions ... + * @param trigger: XTriggerBlock instance Reference, hold founded Trigger Block + * @param helper: XCXCAEAHelper instance Reference Pointer, XCAEA Market nalyser Helper for acc Drawer + * @param config: XCAEATriggerBlockConfiguration instance Reference, Trigger Block Detecting Configuration + * @param bar_index: int, Bar Index to Start Detecting + * @param loopback: int, Loopback Bars Count * * @return ( bool ) */ bool DetectTriggerBlock( - XBoxZone &triggerBlock, - XCAEAConditions &conditions, + XTriggerBlock &trigger, XCXCAEAHelper *helper, XCAEATriggerBlockConfiguration &config, int bar_index = 0, - int loopback = 6 // + int loopback = 10 // ) { // bool result = false; - // - conditions.Clean(); - triggerBlock.Clean(); - // // Normalize Args ... - loopback = NormalizeInt(loopback, 6); + trigger.Clean(); + loopback = NormalizeInt(loopback, 10); bar_index = NormalizeInt(bar_index, 0); // @@ -352,15 +257,34 @@ bool DetectTriggerBlock( } // - // Provide base Requirements ... + // Extract Required Informations ... // string symbol = helper.GetSymbol(); - double points = GetPoints(symbol); ENUM_TIMEFRAMES period = helper.GetPeriod(); // - // Conditions Reading Indexes ... + double points = GetPoints(symbol); + + // + // Retrieve Indexed Bar ... + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + result = zBar.Init( + symbol, + period, + bar_index // + ); + result = result && + zBar.GetPreviousBar(cBar); + result = result && + cBar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + + // int zIDX = 0; int cIDX = zIDX + 1; int pIDX = cIDX + 1; @@ -369,466 +293,71 @@ bool DetectTriggerBlock( int p4IDX = p3IDX + 1; // - double ll = 0; - double hh = 0; - bool has = false; - ENUM_X_DIRECTION iDir; - - // - // Retrieve Current Conditions ... - result = helper.GetConditions( - conditions, - bar_index, - loopback // - ); - - // - // Retrieve Required Bars ... - - // - XOHCL zBar; // Current Start Checking Bar (Usually Used for Triggering) ... - XOHCL cBar; // Current Finished Bar which Start Detecting Structures based on it ( End of Block and FVG Bar ) ... - XOHCL pBar; // Determines Block Gap Bar (all Filtering must applied and Check using this Bar and it's Next Bar) ... - XOHCL p2Bar; // Determines FVG's Start Bar in a Block ... - XOHCL p3Bar; // First Verification of Block ... - XOHCL p4Bar; // Seccond Verification of Block ... - - // - result = zBar.Init( - symbol, - period, - bar_index // - ); + // Check Trigger Block Exists ... result = result && - zBar.GetPreviousBar(cBar); - result = - result && - cBar.GetPreviousBar(pBar); - result = - result && - pBar.GetPreviousBar(p2Bar); - result = - result && - p2Bar.GetPreviousBar(p3Bar); - result = - result && - p3Bar.GetPreviousBar(p4Bar); - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } - - // - // Detect Based Order Block using CBar ... - result = helper .barAnalyser - .IsOB( + .IsTrigger( cBar, - triggerBlock, - true, // Force FVG Bar Type ... - true // Force Block Two Bar Checking ... + trigger.trigger, + trigger.ob, + trigger.fvg, + trigger.rLiquidity, + trigger.fLiquidity, + trigger.swingBar, + loopback, + config.maxAllowedRange, + config.minAllowedBlockEdgeLength, + config.forceOBOppositBar, + config.forceFVGBarType, + config.forceGapBarBreakout, + config.forceHasSwingBar, + config.forceHasLiquidity, + config.forceHasReversalLiquidity // ); // - // Ensure a Block is Detected ... - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } + // Now we Have to Implement Required Validations ... // - // Reading Some Block Based Requirements ... + bool isBullish = trigger.trigger.IsBullish(); + bool isBearish = trigger.trigger.IsBearish(); // - bool isBullish = + // First Reading Market Conditions ... + result = result && - triggerBlock.IsBullish(); + helper.GetConditions( + trigger.conditions, + bar_index, + loopback // + ); // - bool isBearish = - result && - triggerBlock.IsBearish(); + // All Custom andAdditional Validations and Filters + // Applied here ... // - int toIDX = triggerBlock.ToIndex(); - int fromIDX = triggerBlock.FromIndex(); - - // - // Start Validating ... - - // - // Validating p2Bar and p3Bar Direction ... - if (result) + // SAR Filter ... + if (config.filterBasedOnSar) { // - iDir = Opposit(triggerBlock.dir); - - // - result = - iDir == p3Bar.GetDirection() || - iDir == p4Bar.GetDirection(); - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } - } - - // - // Validating Using Max Range ... - result = config.maxZoneRangeInPoints > 0; - if (result) - { - // - double range = triggerBlock.GetRange(); - result = range <= config.maxZoneRangeInPoints * points; - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } - } - - // - // Validate Gap Endup with PinBar ... - result = config.forceHasPinBarEntry; - if (result) - { - // - bool isBullishRejected = - isBullish && - cBar.IsBullish() && - cBar.GetLowShadow() > cBar.GetHighShadow(); - - // - bool isBearishRejected = - isBearish && - cBar.IsBearish() && - cBar.GetLowShadow() < cBar.GetHighShadow(); - - // - result = isBullishRejected || - isBearishRejected; - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } - } - - // - // Validating Gap Bar must a Momentum Bar and - // Breakes out Zone's Directional Edge ... - // for Bullish: Upper - // for Bearish: Lower - result = config.forceGapBarsBreakout; - if (result) - { - // - // Gap Bar is PBar ... - - // - // Check Gap Bar is Momentum Bar ... - result = - helper - .barAnalyser - .IsMomentum( - pBar, - iDir // - ); - bool isBullishMomentum = - result && - IsBullish(iDir); - bool isBearishMomentum = - result && - IsBearish(iDir); - - // - // Check Gap Bar's Breakout ... - - // - bool isBullishBreakedout = - isBullish && - pBar.IsBullish() && - isBullishMomentum && - pBar.GetUp() > triggerBlock.upper && - pBar.GetDown() < triggerBlock.upper; - - // - bool isBearishBreakedout = - isBearish && - pBar.IsBearish() && - isBearishMomentum && - pBar.GetUp() > triggerBlock.lower && - pBar.GetDown() < triggerBlock.lower; - - // - result = isBullishBreakedout || - isBearishBreakedout; - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } - } - - // - // Validate Zone Has Propper Swing ... - // for Bullish: p2Bar or p3Bar must be a Swing Low ... - // for Bearish: p2Bar or p3Bar must be a Swing High ... - result = config.forceHasSwing; - if (result) - { - // - // p2Bar ... - bool isP2BarSwing = - helper - .barAnalyser - .IsSimpleSwing( - p2Bar, - iDir // - ); - bool isP2BarSwingLow = - isP2BarSwing && - IsBullish(iDir); - bool isP2BarSwingHigh = - isP2BarSwing && - IsBearish(iDir); - - // - // p3Bar ... - bool isP3BarSwing = - helper - .barAnalyser - .IsSimpleSwing( - p3Bar, - iDir // - ); - bool isP3BarSwingLow = - isP3BarSwing && - IsBullish(iDir); - bool isP3BarSwingHigh = - isP3BarSwing && - IsBearish(iDir); - - // - bool hasSwingLow = - isBullish && - (isP2BarSwingLow || - isP3BarSwingLow); - - // - bool hasSwingHigh = - isBearish && - (isP2BarSwingHigh || - isP3BarSwingHigh); - - // - result = - hasSwingLow || - hasSwingHigh; - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } - } - - // - // Validating Using Swing Length ... - result = config.minZoneLength > 0; - if (result) - { - // - XOHCL fromBar; - has = triggerBlock.FromBar(fromBar); if (result) { // - // Retrieve HH and LL ... - ll = fromBar.FindLowest(config.minZoneLength, MODE_LOW); - hh = fromBar.FindHighest(config.minZoneLength, MODE_HIGH); + // Reading Values ... // - // Validate Using HH and LL ... + double zSar = trigger.conditions.sarBuffer[zIDX]; + double cSar = trigger.conditions.sarBuffer[cIDX]; + double pSar = trigger.conditions.sarBuffer[pIDX]; + double p2Sar = trigger.conditions.sarBuffer[p2IDX]; + double p3Sar = trigger.conditions.sarBuffer[p3IDX]; + double p4Sar = trigger.conditions.sarBuffer[p4IDX]; // - bool isBullishValid = - isBullish && - ll >= triggerBlock.lower; - - // - bool isBearishValid = - isBearish && - hh <= triggerBlock.upper; - - // - result = isBullishValid || - isBearishValid; - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } - - // - // Update Zone's From Time ... - triggerBlock.from = GetBarTime( - triggerBlock.symbol, - triggerBlock.period, - fromBar.Index() + config.minZoneLength // - ); - } - - // - fromBar.Clean(); - } - - // - // Validate Max Allowed Entry Distance ... - result = config.maxAllowedEntryDistance > 0; - if (result) - { - // - double base = - isBullish - ? triggerBlock.upper - : triggerBlock.lower; - double entryDistance = MathAbs(zBar.open - base); - result = entryDistance <= config.maxAllowedEntryDistance * points; - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } - } - - // - // Here we Ensure which have a Valid Zone using Different Applied Validations ... - // from now we are Going to Filterd Validate Zones ... - - // - // Check Exists Filters or not ... - result = config.filterBasedOnSar || - config.filterBasedOnRSI || - config.filterBasedOnADX || - config.filterBasedOnTrend; - if (result) - { - // - // Do Apply Several Exists Filters ... - - // - // SAR Filter ... - if (config.filterBasedOnSar) - { - // - // Reading Conditions Values ... - - // - double zSar = conditions.sarBuffer[zIDX]; - double cSar = conditions.sarBuffer[cIDX]; - double pSar = conditions.sarBuffer[pIDX]; - double p2Sar = conditions.sarBuffer[p2IDX]; - double p3Sar = conditions.sarBuffer[p3IDX]; - double p4Sar = conditions.sarBuffer[p4IDX]; - - // - // Create Required Conditions ... + // Preparing Conditions ... // bool isZSarBullish = zSar < zBar.low; @@ -895,47 +424,40 @@ bool DetectTriggerBlock( (isCSarSwitchedToBearish || isPSarSwitchedToBearish); + // + // Apply Result .... + // result = - isBullishFilterd || - isBearishFilterd; - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } + result && + (isBullishFilterd || + isBearishFilterd); } + } + // + // RSI Filter ... + if (config.filterBasedOnRSI) + { // - // RSI Filter ... - if (config.filterBasedOnRSI) + if (result) { // - // Reading Conditions Values ... + // Reading Values ... // - double rsiTrend = (conditions.rsiOBLevel + conditions.rsiOSLevel) / 2; + double rsiTrend = (trigger.conditions.rsiOBLevel + trigger.conditions.rsiOSLevel) / 2; // - double zRSI = conditions.rsiBuffer[zIDX]; - double cRSI = conditions.rsiBuffer[cIDX]; - double pRSI = conditions.rsiBuffer[pIDX]; - double p2RSI = conditions.rsiBuffer[p2IDX]; - double p3RSI = conditions.rsiBuffer[p3IDX]; - double p4RSI = conditions.rsiBuffer[p4IDX]; + double zRSI = trigger.conditions.rsiBuffer[zIDX]; + double cRSI = trigger.conditions.rsiBuffer[cIDX]; + double pRSI = trigger.conditions.rsiBuffer[pIDX]; + double p2RSI = trigger.conditions.rsiBuffer[p2IDX]; + double p3RSI = trigger.conditions.rsiBuffer[p3IDX]; + double p4RSI = trigger.conditions.rsiBuffer[p4IDX]; // - // Create Required Conditions ... + // Preparing Conditions ... // bool isZRSIBullish = zRSI > rsiTrend; @@ -1007,29 +529,29 @@ bool DetectTriggerBlock( // bool isCBarCrossedOverOS = - zRSI > conditions.rsiOSLevel && - cRSI > conditions.rsiOSLevel && - pRSI <= conditions.rsiOSLevel; + zRSI > trigger.conditions.rsiOSLevel && + cRSI > trigger.conditions.rsiOSLevel && + pRSI <= trigger.conditions.rsiOSLevel; // bool isCBarCrossedUnderOB = - zRSI < conditions.rsiOBLevel && - cRSI < conditions.rsiOBLevel && - pRSI >= conditions.rsiOBLevel; + zRSI < trigger.conditions.rsiOBLevel && + cRSI < trigger.conditions.rsiOBLevel && + pRSI >= trigger.conditions.rsiOBLevel; // bool isPBarCrossedOverOS = - zRSI > conditions.rsiOSLevel && - cRSI > conditions.rsiOSLevel && - pRSI > conditions.rsiOSLevel && - p2RSI <= conditions.rsiOSLevel; + zRSI > trigger.conditions.rsiOSLevel && + cRSI > trigger.conditions.rsiOSLevel && + pRSI > trigger.conditions.rsiOSLevel && + p2RSI <= trigger.conditions.rsiOSLevel; // bool isPBarCrossedUnderOB = - zRSI < conditions.rsiOBLevel && - cRSI < conditions.rsiOBLevel && - pRSI < conditions.rsiOBLevel && - p2RSI >= conditions.rsiOBLevel; + zRSI < trigger.conditions.rsiOBLevel && + cRSI < trigger.conditions.rsiOBLevel && + pRSI < trigger.conditions.rsiOBLevel && + p2RSI >= trigger.conditions.rsiOBLevel; // // V Pattern Conditions ... @@ -1124,63 +646,56 @@ bool DetectTriggerBlock( // ); + // + // Apply Result .... + // result = - isBullishFilterd || - isBearishFilterd; - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } + result && + (isBullishFilterd || + isBearishFilterd); } + } + // + // ADX Filter ... + if (config.filterBasedOnADX) + { // - // ADX Filter ... - if (config.filterBasedOnADX) + if (result) { // - // Reading Conditions Values ... + // Reading Values ... // // ADX ... - double zADX = conditions.adxBuffer[zIDX]; - double cADX = conditions.adxBuffer[cIDX]; - double pADX = conditions.adxBuffer[pIDX]; - double p2ADX = conditions.adxBuffer[p2IDX]; - double p3ADX = conditions.adxBuffer[p3IDX]; - double p4ADX = conditions.adxBuffer[p4IDX]; + double zADX = trigger.conditions.adxBuffer[zIDX]; + double cADX = trigger.conditions.adxBuffer[cIDX]; + double pADX = trigger.conditions.adxBuffer[pIDX]; + double p2ADX = trigger.conditions.adxBuffer[p2IDX]; + double p3ADX = trigger.conditions.adxBuffer[p3IDX]; + double p4ADX = trigger.conditions.adxBuffer[p4IDX]; // // ADX +DI ... - double zADXP = conditions.adxpBuffer[zIDX]; - double cADXP = conditions.adxpBuffer[cIDX]; - double pADXP = conditions.adxpBuffer[pIDX]; - double p2ADXP = conditions.adxpBuffer[p2IDX]; - double p3ADXP = conditions.adxpBuffer[p3IDX]; - double p4ADXP = conditions.adxpBuffer[p4IDX]; + double zADXP = trigger.conditions.adxpBuffer[zIDX]; + double cADXP = trigger.conditions.adxpBuffer[cIDX]; + double pADXP = trigger.conditions.adxpBuffer[pIDX]; + double p2ADXP = trigger.conditions.adxpBuffer[p2IDX]; + double p3ADXP = trigger.conditions.adxpBuffer[p3IDX]; + double p4ADXP = trigger.conditions.adxpBuffer[p4IDX]; // // ADX -DI ... - double zADXN = conditions.adxnBuffer[zIDX]; - double cADXN = conditions.adxnBuffer[cIDX]; - double pADXN = conditions.adxnBuffer[pIDX]; - double p2ADXN = conditions.adxnBuffer[p2IDX]; - double p3ADXN = conditions.adxnBuffer[p3IDX]; - double p4ADXN = conditions.adxnBuffer[p4IDX]; + double zADXN = trigger.conditions.adxnBuffer[zIDX]; + double cADXN = trigger.conditions.adxnBuffer[cIDX]; + double pADXN = trigger.conditions.adxnBuffer[pIDX]; + double p2ADXN = trigger.conditions.adxnBuffer[p2IDX]; + double p3ADXN = trigger.conditions.adxnBuffer[p3IDX]; + double p4ADXN = trigger.conditions.adxnBuffer[p4IDX]; // - // Create Required Conditions ... + // Preparing Conditions ... // // Grows ... @@ -1201,28 +716,28 @@ bool DetectTriggerBlock( // Trending ... // - bool isZADXBullish = zADX > conditions.adxThreshold; - bool isZADXBearish = zADX < conditions.adxThreshold; + bool isZADXBullish = zADX > trigger.conditions.adxThreshold; + bool isZADXBearish = zADX < trigger.conditions.adxThreshold; // - bool isCADXBullish = cADX > conditions.adxThreshold; - bool isCADXBearish = cADX < conditions.adxThreshold; + bool isCADXBullish = cADX > trigger.conditions.adxThreshold; + bool isCADXBearish = cADX < trigger.conditions.adxThreshold; // - bool isPADXBullish = pADX > conditions.adxThreshold; - bool isPADXBearish = pADX < conditions.adxThreshold; + bool isPADXBullish = pADX > trigger.conditions.adxThreshold; + bool isPADXBearish = pADX < trigger.conditions.adxThreshold; // - bool isP2ADXBullish = p2ADX > conditions.adxThreshold; - bool isP2ADXBearish = p2ADX < conditions.adxThreshold; + bool isP2ADXBullish = p2ADX > trigger.conditions.adxThreshold; + bool isP2ADXBearish = p2ADX < trigger.conditions.adxThreshold; // - bool isP3ADXBullish = p3ADX > conditions.adxThreshold; - bool isP3ADXBearish = p3ADX < conditions.adxThreshold; + bool isP3ADXBullish = p3ADX > trigger.conditions.adxThreshold; + bool isP3ADXBearish = p3ADX < trigger.conditions.adxThreshold; // - bool isP4ADXBullish = p4ADX > conditions.adxThreshold; - bool isP4ADXBearish = p4ADX < conditions.adxThreshold; + bool isP4ADXBullish = p4ADX > trigger.conditions.adxThreshold; + bool isP4ADXBearish = p4ADX < trigger.conditions.adxThreshold; // bool isCADXSwitchedToBullish = @@ -1350,41 +865,34 @@ bool DetectTriggerBlock( // ); + // + // Apply Result .... + // result = - isBullishFilterd || - isBearishFilterd; - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } + result && + (isBullishFilterd || + isBearishFilterd); } + } + // + // TREND Filter ... + if (config.filterBasedOnTrend) + { // - // TREND Filter ... - if (config.filterBasedOnTrend) + if (result) { // - // Reading Conditions Values ... + // Reading Values ... // - double zTrend = conditions.trendBuffer[zIDX]; - double cTrend = conditions.trendBuffer[cIDX]; - double pTrend = conditions.trendBuffer[pIDX]; - double p2Trend = conditions.trendBuffer[p2IDX]; - double p3Trend = conditions.trendBuffer[p3IDX]; - double p4Trend = conditions.trendBuffer[p4IDX]; + double zTrend = trigger.conditions.trendBuffer[zIDX]; + double cTrend = trigger.conditions.trendBuffer[cIDX]; + double pTrend = trigger.conditions.trendBuffer[pIDX]; + double p2Trend = trigger.conditions.trendBuffer[p2IDX]; + double p3Trend = trigger.conditions.trendBuffer[p3IDX]; + double p4Trend = trigger.conditions.trendBuffer[p4IDX]; // double trends[] = { @@ -1400,15 +908,15 @@ bool DetectTriggerBlock( double trendsAVG = GetAverage(trends); // - double zTrendState = conditions.trendStateBuffer[zIDX]; - double cTrendState = conditions.trendStateBuffer[cIDX]; - double pTrendState = conditions.trendStateBuffer[pIDX]; - double p2TrendState = conditions.trendStateBuffer[p2IDX]; - double p3TrendState = conditions.trendStateBuffer[p3IDX]; - double p4TrendState = conditions.trendStateBuffer[p4IDX]; + double zTrendState = trigger.conditions.trendStateBuffer[zIDX]; + double cTrendState = trigger.conditions.trendStateBuffer[cIDX]; + double pTrendState = trigger.conditions.trendStateBuffer[pIDX]; + double p2TrendState = trigger.conditions.trendStateBuffer[p2IDX]; + double p3TrendState = trigger.conditions.trendStateBuffer[p3IDX]; + double p4TrendState = trigger.conditions.trendStateBuffer[p4IDX]; // - // Create Required Conditions ... + // Preparing Conditions ... // // Grows ... @@ -1533,43 +1041,121 @@ bool DetectTriggerBlock( // ); + // + // Apply Result .... + // result = - isBullishFilterd || - isBearishFilterd; - if (!result) - { - // - zBar.Clean(); - cBar.Clean(); - pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - conditions.Clean(); - triggerBlock.Clean(); - - // - return result; - } + result && + (isBullishFilterd || + isBearishFilterd); } - - // - // SCORE Filter ... - - // - // VOLUME Filter ... } // - result = triggerBlock.IsValid(); - if (result) + // SCORE Filter ... + if (config.filterBasedOnScores) { // - triggerBlock.type = - isBullish - ? ToString(XCA_TRIGGER_BULL) - : ToString(XCA_TRIGGER_BEAR); + if (result) + { + // + // Reading Values ... + + // + double bullishScore = 0; + double bearishScore = 0; + + // + trigger.conditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // + // Preparing Conditions ... + + // + bool isScoreBullish = bullishScore > bearishScore; + bool isScoreBearish = bearishScore > bullishScore; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + isScoreBullish; + + // + bool isBearishFilterd = + isBearish && + isScoreBearish; + + // + // Apply Result .... + + // + result = + result && + (isBullishFilterd || + isBearishFilterd); + } + } + + // + // VOLUME Filter ... + if (config.filterBasedOnVolumes) + { + // + if (result) + { + // + // Reading Values ... + + // + double bullishVolume = 0; + double bearishVolume = 0; + + // + helper + .barAnalyser + .CalculateRangeVolume( + zBar, + bullishVolume, + bearishVolume, + loopback // + ); + + // + // Preparing Conditions ... + + // + bool isVolumeBullish = bullishVolume > bearishVolume; + bool isVolumeBearish = bearishVolume > bullishVolume; + + // + // Summarize Filtering ... + + // + bool isBullishFilterd = + isBullish && + isVolumeBullish; + + // + bool isBearishFilterd = + isBearish && + isVolumeBearish; + + // + // Apply Result .... + + // + result = + result && + (isBullishFilterd || + isBearishFilterd); + } } // @@ -1579,66 +1165,229 @@ bool DetectTriggerBlock( zBar.Clean(); cBar.Clean(); pBar.Clean(); - p2Bar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); // if (!result) { - // - conditions.Clean(); - triggerBlock.Clean(); + trigger.Clean(); + } + + // + // Attach Configuration if Trigger Block Founded ... + if (result) + { + trigger.configuration = config; } // return result; -}; +} -bool DetectTriggerBlock1( - XBoxZone &triggerBlock, - XCAEAConditions &conditions, +/** + * Draw Specified Trigger Block ... + * + * @param trigger: XTriggerBlock instance Reference, specified Trigger Block to Draw + * @param objects: CArrayObj instance Reference Pointer, Objects Array for Providing Drawn Objects + * @param helper: XCXCAEAHelper instance Reference Pointer, XCAEA Market nalyser Helper for acc Drawer + * @param to: datetime, specified Time for update Trigger parts + * + * @return ( bool ) + */ +bool DrawTriggerBlock( + XTriggerBlock &trigger, + CArrayObj *&objects, XCXCAEAHelper *helper, - XCAEATriggerBlockConfiguration &config, - int bar_index = 0, - int loopback = 6 // -) { + datetime to = NULL // +) +{ // bool result = false; - // - conditions.Clean(); - triggerBlock.Clean(); - - // - // Normalize Args ... - loopback = NormalizeInt(loopback, 6); - bar_index = NormalizeInt(bar_index, 0); - // // Validate Args ... - result = helper != NULL; + result = helper != NULL && + trigger.IsValid(); if (!result) { return result; } // - // Provide base Requirements ... + // Update To ... + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + // + trigger.trigger.to = to; + trigger.rLiquidity.to = to; + trigger.fLiquidity.to = to; + } // - string symbol = helper.GetSymbol(); - double points = GetPoints(symbol); - ENUM_TIMEFRAMES period = helper.GetPeriod(); + // Draw OB ... + if (trigger.ob.IsValid()) + { + // + XCBoxObject *iOBObj; + result = helper.poiDrawer.DrawBox( + trigger.ob, + iOBObj // + ); + if (result) + { + objects.Add(iOBObj); + } + ZeroMemory(iOBObj); + + // + if (!result) + { + return result; + } + } // - // Conditions Reading Indexes ... - int zIDX = 0; - int cIDX = zIDX + 1; - int pIDX = cIDX + 1; - int p2IDX = pIDX + 1; - int p3IDX = p2IDX + 1; - int p4IDX = p3IDX + 1; + // Draw FVG ... + if (trigger.fvg.IsValid()) + { + // + XCBoxObject *iFVGObj; + result = helper.poiDrawer.DrawBox( + trigger.fvg, + iFVGObj // + ); + if (result) + { + // + // Style Object ... + color clr = + trigger.fvg.IsBullish() + ? clrAqua + : clrMagenta; + iFVGObj.BoxWidth(2); + iFVGObj.BoxColor(clr); + iFVGObj.BoxStyle(STYLE_SOLID); + + // + // Store Object ... + objects.Add(iFVGObj); + } + ZeroMemory(iFVGObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Trigger ... + if (trigger.trigger.IsValid()) + { + // + XCBoxObject *iTriggerObj; + result = helper.poiDrawer.DrawBox( + trigger.trigger, + iTriggerObj // + ); + if (result) + { + objects.Add(iTriggerObj); + } + ZeroMemory(iTriggerObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Liquidities ... + + // + // Reversla Liquidity ... + if (trigger.rLiquidity.IsValid()) + { + // + XCBoxObject *iLiqObj; + result = helper.poiDrawer.DrawBox( + trigger.rLiquidity, + iLiqObj // + ); + if (result) + { + objects.Add(iLiqObj); + } + ZeroMemory(iLiqObj); + + // + if (!result) + { + return result; + } + } + + // + // Following Liquidity ... + if (trigger.fLiquidity.IsValid()) + { + // + XCBoxObject *iLiqObj; + result = helper.poiDrawer.DrawBox( + trigger.fLiquidity, + iLiqObj // + ); + if (result) + { + objects.Add(iLiqObj); + } + ZeroMemory(iLiqObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Swing Bar ... + if (trigger.swingBar.IsValid()) + { + // + color swingColor = + trigger.fvg.IsBullish() + ? clrAqua + : clrMagenta; + ENUM_X_PRICE swingPType = + trigger.fvg.IsBullish() + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + XCBarArrowObject *swingObj; + result = helper.poiDrawer.CreateBarArrow( + trigger.swingBar, + swingObj, + swingPType, + 159, + swingColor // + ); + if (result) + { + objects.Add(swingObj); + } + ZeroMemory(swingObj); + + // + if (!result) + { + return result; + } + } // return result;