From 29527083b438eddcb5d155b76ffb0351ae1c78d1 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Sun, 18 May 2025 08:53:04 +0330 Subject: [PATCH] Cleanup Trigger Block Detection from xcaea detector and Drawer for Managing it's Differences ... --- Classes/x-saherelm.x-cobject.class.mq5 | 2 +- Documents/BKP/xcaea.x-poi.detector.class.mq5 | 5287 ++++++++++++++++++ XCAEA/Classes/xcaea.x-poi.detector.class.mq5 | 791 +-- XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 | 216 - XCAEA/Libraries/xcaea.signaller.lib.mq5 | 2 +- XCAEA/Signals/xcaea.signaller.class.mq5 | 37 - 6 files changed, 5290 insertions(+), 1045 deletions(-) create mode 100644 Documents/BKP/xcaea.x-poi.detector.class.mq5 diff --git a/Classes/x-saherelm.x-cobject.class.mq5 b/Classes/x-saherelm.x-cobject.class.mq5 index a9726d7b..9088424c 100644 --- a/Classes/x-saherelm.x-cobject.class.mq5 +++ b/Classes/x-saherelm.x-cobject.class.mq5 @@ -156,7 +156,7 @@ string ToString(ENUM_X_CHART_IDS value) } // -// Library Functions ... +// Extensions ... /** * Converts a XBoxZone struct to XSignal instance ... diff --git a/Documents/BKP/xcaea.x-poi.detector.class.mq5 b/Documents/BKP/xcaea.x-poi.detector.class.mq5 new file mode 100644 index 00000000..92118f56 --- /dev/null +++ b/Documents/BKP/xcaea.x-poi.detector.class.mq5 @@ -0,0 +1,5287 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCAEAPOIDetector ... +// Description: Class for XCAEA POI Detector ... +// +// +// 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 Class for XCAEA POI Detector" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Helpers/xcaea.helper.mq5" + +// +// Definitions ... + +// +enum ENUM_XCA_PIVOTS +{ + XCA_NONE, // None + XCA_SWL, // Swing Low + XCA_SWH, // Swing High + XCA_PEAK, // Peak + XCA_VALE, // Vale + XCA_OB_BULL, // OBBull + XCA_OB_BEAR, // OBBear + XCA_FVG_BULL, // FVGBull + XCA_FVG_BEAR, // FVGBear + XCA_RSI_COOS, // RSICOOS + XCA_RSI_CUOB, // RSICUOB + XCA_TREND_BULL, // TrendBull + XCA_TREND_BEAR, // TrendBear + XCA_TRIGGER_BULL, // TriggerBull + XCA_TRIGGER_BEAR, // TriggerBear +}; + +// +bool IsValid(ENUM_XCA_PIVOTS value) +{ + // + bool result = false; + + // + result = value != XCA_NONE; + + // + return result; +} + +// +string ToString(ENUM_XCA_PIVOTS value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +ENUM_X_DIRECTION GetDirection(ENUM_XCA_PIVOTS value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + switch (value) + { + // + case XCA_SWL: + case XCA_VALE: + case XCA_OB_BULL: + case XCA_FVG_BULL: + case XCA_RSI_COOS: + case XCA_TREND_BULL: + case XCA_TRIGGER_BULL: + result = X_DIRECTION_BULLISH; + break; + + // + case XCA_SWH: + case XCA_PEAK: + case XCA_OB_BEAR: + case XCA_FVG_BEAR: + case XCA_RSI_CUOB: + case XCA_TREND_BEAR: + case XCA_TRIGGER_BEAR: + result = X_DIRECTION_BEARISH; + break; + } + + // + return result; +} + +// +string GetBoxType(ENUM_XCA_PIVOTS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case XCA_SWL: + case XCA_SWH: + case XCA_VALE: + case XCA_PEAK: + case XCA_RSI_COOS: + case XCA_RSI_CUOB: + result = ToString(value); + break; + // + case XCA_OB_BULL: + case XCA_OB_BEAR: + result = "XCA_OB"; + break; + // + case XCA_FVG_BULL: + case XCA_FVG_BEAR: + result = "XCA_FVG"; + break; + + // + case XCA_TREND_BULL: + case XCA_TREND_BEAR: + result = "XCA_TREND"; + break; + + // + case XCA_TRIGGER_BULL: + case XCA_TRIGGER_BEAR: + result = "XCA_TRIGGER"; + break; + } + + // + return result; +} + +// +ENUM_XCA_PIVOTS GetPivotType(XBoxZone &value) +{ + // + ENUM_XCA_PIVOTS result = XCA_NONE; + + // + bool has = value.IsValid(); + if (!has) + { + return result; + } + + // + bool isSWL = value.type == GetBoxType(XCA_SWL) && + value.dir == GetDirection(XCA_SWL); + bool isSWH = value.type == GetBoxType(XCA_SWH) && + value.dir == GetDirection(XCA_SWH); + bool isPeak = value.type == GetBoxType(XCA_PEAK) && + value.dir == GetDirection(XCA_PEAK); + bool isVale = value.type == GetBoxType(XCA_VALE) && + value.dir == GetDirection(XCA_VALE); + bool isOBBull = value.type == GetBoxType(XCA_OB_BULL) && + value.dir == GetDirection(XCA_OB_BULL); + bool isOBBear = value.type == GetBoxType(XCA_OB_BEAR) && + value.dir == GetDirection(XCA_OB_BEAR); + bool isFVGBull = value.type == GetBoxType(XCA_FVG_BULL) && + value.dir == GetDirection(XCA_FVG_BULL); + bool isFVGBear = value.type == GetBoxType(XCA_FVG_BEAR) && + value.dir == GetDirection(XCA_FVG_BEAR); + bool isRSICrossedOverOS = value.type == GetBoxType(XCA_RSI_COOS) && + value.dir == GetDirection(XCA_RSI_COOS); + bool isRSICrossedUnderOB = value.type == GetBoxType(XCA_RSI_CUOB) && + value.dir == GetDirection(XCA_RSI_CUOB); + bool isTrendBullish = value.type == GetBoxType(XCA_TREND_BULL) && + value.dir == GetDirection(XCA_TREND_BULL); + bool isTrendBearish = value.type == GetBoxType(XCA_TREND_BEAR) && + value.dir == GetDirection(XCA_TREND_BEAR); + bool isTriggerBullish = value.type == GetBoxType(XCA_TRIGGER_BULL) && + value.dir == GetDirection(XCA_TRIGGER_BULL); + bool isTriggerBearish = value.type == GetBoxType(XCA_TRIGGER_BEAR) && + value.dir == GetDirection(XCA_TRIGGER_BEAR); + + // + if (isSWL) + { + result = XCA_SWL; + } + else if (isSWH) + { + result = XCA_SWH; + } + else if (isPeak) + { + result = XCA_PEAK; + } + else if (isVale) + { + result = XCA_VALE; + } + else if (isOBBull) + { + result = XCA_OB_BULL; + } + else if (isOBBear) + { + result = XCA_OB_BEAR; + } + else if (isFVGBull) + { + result = XCA_FVG_BULL; + } + else if (isFVGBear) + { + result = XCA_FVG_BEAR; + } + else if (isRSICrossedOverOS) + { + result = XCA_RSI_COOS; + } + else if (isRSICrossedUnderOB) + { + result = XCA_RSI_CUOB; + } + else if (isTrendBullish) + { + result = XCA_TREND_BULL; + } + else if (isTrendBearish) + { + result = XCA_TREND_BEAR; + } + else if (isTriggerBullish) + { + result = XCA_TRIGGER_BULL; + } + else if (isTriggerBearish) + { + result = XCA_TRIGGER_BEAR; + } + + // + return result; +} + +// +int ExtractPivots( + XBoxZone &extracted[], + ENUM_XCA_PIVOTS type, + XBoxZone &source[] // +) +{ + // + int result = 0; + + // + Clean(extracted); + + // + bool has = + IsValid(type) && + HasChild(source); + if (!has) + { + return result; + } + + // + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + ENUM_XCA_PIVOTS iType = GetPivotType(iBox); + + // + has = iType == type; + if (has) + { + // + AddRef( + iBox, + extracted // + ); + } + + // + iBox.Clean(); + } + + // + result = ArraySize(extracted); + + // + return result; +} + +// +bool IsFakeBreakeout( + XBoxZone &pivot, + XCXCAEAHelper *helper, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + int fromIDX = pivot.FromIndex(); + result = barIndex < fromIDX; + if (!result) + { + return result; + } + + // + bool isBullish = pivot.IsBullish(); + + // + // Retrieve Required Bars ... + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + result = cBar.Init( + pivot.symbol, + pivot.period, + barIndex // + ); + result = result && + cBar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + // + // Bars Conditions ... + + // + ENUM_X_DIRECTION cBarDir; + + // + // Hammer ... + bool isCBarHammer = helper + .barAnalyser + .IsHammer( + cBar, + cBarDir // + ); + bool isCBarBullishHammer = + isCBarHammer && + IsBullish(cBarDir); + bool isCBarBearishHammer = + isCBarHammer && + IsBearish(cBarDir); + + // + // Rejected ... + bool isCBarRejected = helper + .barAnalyser + .IsRejected( + cBar, + cBarDir, + false, // Force Type ... + true // Force Fibo Pressure ... + ); + bool isCBarBullishRejected = + isCBarRejected && + IsBullish(cBarDir); + bool isCBarBearishRejected = + isCBarRejected && + IsBearish(cBarDir); + + // + // Engulfed ... + bool isCBarEngulfed = helper + .barAnalyser + .IsEngulfed( + cBar, + cBarDir // + ); + bool isCBarBullishEngulfed = + isCBarEngulfed && + IsBullish(cBarDir); + bool isCBarBearishEngulfed = + isCBarEngulfed && + IsBearish(cBarDir); + + // + // Momentum ... + bool isCBarMomentum = helper + .barAnalyser + .IsMomentum( + cBar, + cBarDir, + 1 // + ); + bool isCBarBullishMomentum = + isCBarMomentum && + IsBullish(cBarDir); + bool isCBarBearishMomentum = + isCBarMomentum && + IsBearish(cBarDir); + + // + bool isCBarHasBullishPower = isCBarBullishRejected || + isCBarBullishEngulfed || + isCBarBullishMomentum; + + // + bool isCBarHasBearishPower = isCBarBearishRejected || + isCBarBearishEngulfed || + isCBarBearishMomentum; + + // + bool isBarPowerfull = + isBullish + ? isCBarHasBullishPower + : isCBarHasBearishPower; + + // + double breakPrice = + isBullish + ? pivot.lower + : pivot.upper; + + // + // CBar Must Go back InSide Box ... + bool isBarInside = + cBar.GetUp() > breakPrice && + cBar.GetDown() < breakPrice && + cBar.GetDirection() == pivot.dir; + + // + result = + // + // Bar Must Inside Pivot ... + isBarInside && + // + // Bar Must Has Required Direction Power ... + isBarPowerfull + // + ; + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; +} + +// +struct XCAPivot +{ + // + // Props ... + datetime to; + double value; + string symbol; + datetime from; + double reserve; + ENUM_XCA_PIVOTS type; + ENUM_TIMEFRAMES period; + + // + double values[]; + + // + // Constructor ... + XCAPivot() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + value = 0; + to = NULL; + reserve = 0; + from = NULL; + symbol = NULL; + period = NULL; + type = XCA_NONE; + + // + Clean(values); + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + from < to && + value != 0 && + IsValid(to) && + IsValid(from) && + IsValid(type) && + IsValid(symbol) && + IsValid(period); + + // + return result; + } + + /** + * Check a Model is Same as this or not ... + * + * @param pivot: XCAPivot ... + * + * @return ( bool ) + */ + bool IsSameAs(XCAPivot &pivot) + { + // + bool result = false; + + // + result = + IsValid() && + pivot.IsValid(); + if (!result) + { + return result; + } + + // + result = + to == pivot.to && + from == pivot.from && + type == pivot.type && + value == pivot.value && + symbol == pivot.symbol && + period == pivot.period; + + // + return result; + } + + /** + * Retrieve To Index ... + * + * @param forPeriod: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int ToIndex( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = GetBarIndex( + symbol, + forPeriod, + to // + ); + + // + return result; + } + + /** + * Retrieve From Index ... + * + * @param forPeriod: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int FromIndex( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = GetBarIndex( + symbol, + forPeriod, + from // + ); + + // + return result; + } + + /** + * Retrieve Age of Pivot ... + * + * @param forPeriod: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int GetAge( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + int toIDX = ToIndex(forPeriod); + int fromIDX = FromIndex(forPeriod); + + // + result = fromIDX - toIDX; + + // + return result; + } + + /** + * Converts Pivot to Box ... + * + * @param box: XBoxZone instance reference ... + * + * @return ( bool ) + */ + bool AsBox( + XBoxZone &box // + ) + { + // + bool result = false; + + // + box.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION iDir = GetDirection(type); + + // + result = HasDirection(iDir); + if (!result) + { + return result; + } + + // + bool isBullish = + IsBullish(iDir) && + value < reserve; + + // + bool isBearish = + IsBearish(iDir) && + value > reserve; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + box.to = to; + box.dir = iDir; + box.from = from; + box.symbol = symbol; + box.period = period; + + // + string typeStr = GetBoxType(type); + box.type = typeStr; + + // + box.upper = + isBullish + ? reserve + : value; + box.lower = + isBullish + ? value + : reserve; + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; + } + + // +}; + +// +// Implementations ... +class XCXCAEAPOIDetector : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Pivot Verifications and Max Allowed Holding Items ... + int maxAllowedPivots; // Max Allowed Holding Pibots ... + int pivotVerifications; // Pivots Verifications ... + int pivotDetectionLoopbac; // Pivots Detection Loopback ... + double ticksDividerInPoints; // Ticks and Volume Detection Divider in Point ... + + // + // TREND ... + XBoxZone trendPivotP; // Prev Pivot of Market Trend ... + XBoxZone trendPivotC; // Current Pivot of Market Trend ... + ENUM_X_DIRECTION trendDir; // Trend Direction ... + + // + // Breaked Pivots ... + XBoxZone invalidPivots[]; + + // + // Constructors ... + XCXCAEAPOIDetector( + XCXCAEAHelper *_helper // + ) + { + // + helper = _helper; + drawer = new XCPOIDrawer(); + barAnalyser = new XCBarAnalyser(); + + // + Default(); + } + + // + // De Constructors ... + ~XCXCAEAPOIDetector() + { + // + CleanPivots(); + + // + ZeroMemory(helper); + ZeroMemory(drawer); + ZeroMemory(barAnalyser); + } + + // + // Properties ... + + // + // Tools ... + + // + virtual void Default() + { + // + // COMMON ... + + // + maxAllowedPivots = 50; + pivotVerifications = 5; + ticksDividerInPoints = 15; + pivotDetectionLoopbac = 100; + + // + // SWING ... + + // + maxAllowedSwingLifetime = 0; + + // + detectSWHPivots = false; + detectSWLPivots = false; + + // + // PV ... + + // + detectPeakPivots = false; + detectValePivots = false; + + // + maxAllowedPVLifetime = 0; + applySwingsOnPVPivots = false; + selectRejectedPVPivots = false; + selectEngulfedPVPivots = false; + selectPVWhichStartByFVG = false; + applySupportAndResistanceOnPVPivots = false; + + // + // FVG ... + + // + detectFVGBullishPivots = false; + detectFVGBearishPivots = false; + + // + selectSameBarFVGs = false; + maxAllowedFVGLifetime = 0; + validateFVGUsingPV = false; + applyPVToFVGBoundary = false; + selectRejectedFVGPivots = false; + selectEngulfedFVGPivots = false; + validateFVGUsingManalyser = false; + applyLastBarToFVGBoundary = false; + selectOnlyFVGWhichHasIndirectionalLastBar = false; + + // + // OB ... + maxAllowedOBLifetime = 0; + + // + detectOBBullishPivots = false; + detectOBBearishPivots = false; + + // + // TREND ... + maxAllowedTrendLifetime = 0; + + // + detectTrendBullishPivots = false; + detectTrendBearishPivots = false; + + // + // Trigger Block ... + triggerBlockSwingLength = 7; + triggerBlockMaxAllowedRange = 0; + filterTriggerBlocksBySar = true; + triggerBlockBarHasProperSwing = true; + detectTriggerBlockBullishPivots = false; + detectTriggerBlockBearishPivots = false; + triggerBlockBarPressureValidation = true; + + // + } + + // + void Detect( + int barIndex = 0 // + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int loopback = pivotDetectionLoopbac; + loopback = NormalizeInt(loopback, 50); + + // + int idx = -1; + int count = 0; + bool has = false; + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + + // + newSWHPivotDetected = false; + newSWLPivotDetected = false; + newPeakPivotDetected = false; + newValePivotDetected = false; + newOBBullishPivotDetected = false; + newOBBearishPivotDetected = false; + newFVGBullishPivotDetected = false; + newFVGBearishPivotDetected = false; + newTrendBullishPivotDetected = false; + newTrendBearishPivotDetected = false; + newTriggerBlockBullishPivotDetected = false; + newTriggerBlockBearishPivotDetected = false; + + // + int index = barIndex; + int start = index; + int end = index + loopback; + while (start < end) + { + // + // Retrieve Conditions ... + XCAEAConditions conditions; + has = helper.GetConditions( + conditions, + start, + 10 // + ); + if (!has) + { + conditions.Clean(); + continue; + } + + // + // Retrieve Bars ... + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + has = zBar.Init( + conditions.symbol, + conditions.period, + start // + ); + has = + has && + zBar.GetPreviousBar(cBar); + has = + has && + cBar.GetPreviousBar(pBar); + has = + has && + pBar.GetPreviousBar(p2Bar); + if (!has) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + conditions.Clean(); + + // + continue; + } + + // + // Handle On Time Detection Pivots ... + bool isFirstBar = start == index; + if (isFirstBar) + { + // + // TRIGGER Block ... + // Since Trigger Block Pivots Only Used on Detection Time ... + // we have to Detect only when zBar Index is Zero, means at Last Bar ... + // in this Senario we Have to Ignore LoopBacks ... + + // + // Bullish ... + if (detectTriggerBlockBullishPivots) + { + // + newTriggerBlockBullishPivotDetected = DetectTriggerBlockPivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Bearish ... + if (detectTriggerBlockBearishPivots) + { + // + newTriggerBlockBearishPivotDetected = DetectTriggerBlockPivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + } + + // + // Checking Pivots ... + + // + // SWING ... + + // + // SWH ... + if (detectSWHPivots) + { + // + newSWHPivotDetected = DetectSwingPivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // SWL ... + if (detectSWLPivots) + { + // + newSWLPivotDetected = DetectSwingPivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // PV ... + + // + // PEAK ... + if (detectPeakPivots) + { + // + newPeakPivotDetected = DetectPeakAndValePivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // VALE ... + if (detectValePivots) + { + // + newValePivotDetected = DetectPeakAndValePivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // FVG ... + + // + // Bullish ... + if (detectFVGBullishPivots) + { + // + newFVGBullishPivotDetected = DetectFVGPivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Bearish ... + if (detectFVGBearishPivots) + { + // + newFVGBearishPivotDetected = DetectFVGPivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // OB ... + + // + // Bullish ... + if (detectOBBullishPivots) + { + // + newOBBullishPivotDetected = DetectOBPivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Bearish ... + if (detectOBBearishPivots) + { + // + newOBBearishPivotDetected = DetectOBPivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // TREND ... + + // + // Bullish ... + if (detectTrendBullishPivots) + { + // + newTrendBullishPivotDetected = DetectTrendPivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Bearish ... + if (detectTrendBearishPivots) + { + // + newTrendBearishPivotDetected = DetectTrendPivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Others ... + + // + start++; + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + conditions.Clean(); + } + + // + SortPivots(); + } + + // + void Validate( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + // Implement Validation Senarios ... + + // + // SWING ... + ValidateSwingPivots( + unavailables, + barIndex // + ); + + // + // PV ... + ValidatePeakValePivots( + unavailables, + barIndex // + ); + + // + // OB ... + ValidateOBPivots( + unavailables, + barIndex // + ); + + // + // FVG ... + ValidateFVGPivots( + unavailables, + barIndex // + ); + + // + // TREND ... + ValidateTrendPivots( + unavailables, + barIndex // + ); + + // + // TRIGGER Block ... + ValidateTriggerBlockPivots( + unavailables, + barIndex // + ); + + // + SortPivots(); + } + + // + int FillPivots( + XBoxZone &pivots[], + ENUM_X_DIRECTION forDir = X_DIRECTION_ALL // + ) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (forDir == X_DIRECTION_NONE) + { + return result; + } + + // + int count = 0; + bool has = false; + + // + bool canFillBullish = + forDir == X_DIRECTION_ALL || + forDir == X_DIRECTION_BULLISH; + + // + bool canFillBearish = + forDir == X_DIRECTION_ALL || + forDir == X_DIRECTION_BEARISH; + + // + // Bullish ... + if (canFillBullish) + { + // + Copy( + swlPivots, + pivots, + false // + ); + + // + Copy( + valePivots, + pivots, + false // + ); + + // + Copy( + obBullishPivots, + pivots, + false // + ); + + // + Copy( + fvgBullishPivots, + pivots, + false // + ); + + // + Copy( + trendBullishPivots, + pivots, + false // + ); + } + + // + // Bearish ... + if (canFillBearish) + { + // + Copy( + swhPivots, + pivots, + false // + ); + + // + Copy( + peakPivots, + pivots, + false // + ); + + // + Copy( + obBearishPivots, + pivots, + false // + ); + + // + Copy( + fvgBearishPivots, + pivots, + false // + ); + + // + Copy( + trendBearishPivots, + pivots, + false // + ); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + int FillPivots( + XBoxZone &pivots[], + XBoxZone &unavailables[], + ENUM_XCA_PIVOTS &allowedTypes[], + datetime to = NULL // + ) + { + // + int result = 0; + + // + Clean(pivots); + + // + bool canUpdateTo = IsValid(to); + + // + XBoxZone tmp[]; + bool has = false; + int tmpCount = FillPivots( + tmp, + X_DIRECTION_ALL // + ); + has = IsValidSize(tmpCount); + if (!has) + { + return result; + } + + // + XBoxZone iBox; + while (HasChild(tmp)) + { + // + iBox = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + ENUM_XCA_PIVOTS iType = GetPivotType(iBox); + bool isAllowed = + !HasChild(allowedTypes) + ? true + : Contains( + iType, + allowedTypes // + ); + + // + int idx = -1; + bool isUnAvailable = FindBoxIndex( + idx, + iBox, + unavailables // + ); + + // + if (isAllowed && + !isUnAvailable) + { + // + AddRef( + iBox, + pivots // + ); + } + + // + iBox.Clean(); + } + iBox.Clean(); + + // + result = ArraySize(pivots); + + // + return result; + } + + // + int FillPivots( + XBoxZone &decision, + XBoxZone &pivots[], + XBoxZone &unavailables[], + ENUM_XCA_PIVOTS &allowedTypes[], + datetime to = NULL // + ) + { + // + int result = false; + + // + bool has = false; + has = decision.IsValid(); + if (!has) + { + return result; + } + + // + XBoxZone tmp[]; + int count = FillPivots( + tmp, + unavailables, + allowedTypes, + to // + ); + + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = tmp[i]; + + // + // Validate Box ... + has = + // + // Validate Time .. + iBox.from > decision.from + // + && + // + // Validate Price ... + ( + // + (iBox.upper < decision.upper && + iBox.upper > decision.lower) + // + || + // + (iBox.lower > decision.lower && + iBox.lower < decision.upper) + // + ); + if (has) + { + // + AddRef( + iBox, + pivots // + ); + } + + // + iBox.Clean(); + } + + // + Clean(tmp); + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // Pivots ... + + // + // INVALID Pivots ... + + // + bool HasInvalidPivots() + { + return HasChild(invalidPivots); + } + + // + int CountInvalidPivots() + { + return ArraySize(invalidPivots); + } + + // + // SWING ... + + // + int maxAllowedSwingLifetime; // Max Allowed Swing Life ... + + // + bool DetectSwingPivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + XCAEAConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectSWLPivots + : detectSWHPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + datetime cTime = zBar.time; + string symbol = zBar.symbol; + ENUM_TIMEFRAMES period = zBar.period; + double points = GetPoints(symbol); + + // + // Reading Conditional Values ... + + // + // PEAK ... + double zPeak = conditions.peakBuffer[zIDX]; + double cPeak = conditions.peakBuffer[cIDX]; + double pPeak = conditions.peakBuffer[pIDX]; + double p2Peak = conditions.peakBuffer[p2IDX]; + + // + // VALE ... + double zVale = conditions.valeBuffer[zIDX]; + double cVale = conditions.valeBuffer[cIDX]; + double pVale = conditions.valeBuffer[pIDX]; + double p2Vale = conditions.valeBuffer[p2IDX]; + + // + // SWING High .. + double zSwingHigh = conditions.swingHighBuffer[zIDX]; + double cSwingHigh = conditions.swingHighBuffer[cIDX]; + double pSwingHigh = conditions.swingHighBuffer[pIDX]; + double p2SwingHigh = conditions.swingHighBuffer[p2IDX]; + + // + // SWING Low ... + double zSwingLow = conditions.swingLowBuffer[zIDX]; + double cSwingLow = conditions.swingLowBuffer[cIDX]; + double pSwingLow = conditions.swingLowBuffer[pIDX]; + double p2SwingLow = conditions.swingLowBuffer[p2IDX]; + + // + // Prepare Conditinal Conditions ... + + // + // SWH ... + + // + bool isSWHSameLast = cSwingHigh == pSwingHigh; + bool isSWHSameLastPrev = pSwingHigh == p2SwingHigh; + + // + bool isSWHSwitchedToSameLast = isSWHSameLast && + !isSWHSameLastPrev; + bool isSWHFinishedFromSameLast = !isSWHSameLast && + isSWHSameLastPrev; + + // + // SWL ... + + // + bool isSWLSameLast = cSwingLow == pSwingLow; + bool isSWLSameLastPrev = pSwingLow == p2SwingLow; + + // + bool isSWLSwitchedToSameLast = isSWLSameLast && + !isSWLSameLastPrev; + bool isSWLFinishedFromSameLast = !isSWLSameLast && + isSWLSameLastPrev; + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasStartCondition = + // + forBullish + ? isSWLFinishedFromSameLast + : isSWHFinishedFromSameLast + // + ; + + // + bool hasContinuationCondition = + // + forBullish + ? isSWLSameLast + : isSWHSameLast + // + ; + + // + bool hasEndCondition = + // + forBullish + ? isSWLSwitchedToSameLast + : isSWHSwitchedToSameLast + // + ; + + // + // + // + + // + // ReInstance Pivot ... + if (hasStartCondition) + { + // + // SWL ... + if (forBullish) + { + // + swlPivot.Clean(); + + // + swlPivot.type = XCA_SWL; + swlPivot.symbol = symbol; + swlPivot.period = period; + + // + swlPivot.to = pBar.time; + swlPivot.from = pBar.time; + swlPivot.value = pSwingLow; + swlPivot.reserve = pVale; + } + + // + // SWH ... + if (forBearish) + { + // + swhPivot.Clean(); + + // + swhPivot.type = XCA_SWH; + swhPivot.symbol = symbol; + swhPivot.period = period; + + // + swhPivot.to = pBar.time; + swhPivot.from = pBar.time; + swhPivot.value = pSwingHigh; + swhPivot.reserve = pPeak; + } + } + + // + // Calculate and Fill Pivot Requirements ... + if (hasContinuationCondition) + { + // + // SWL ... + if (forBullish) + { + // + swlPivot.from = pBar.time; + + // + swlPivot.reserve = + swlPivot.reserve == 0 + ? pVale + : MathMin(swlPivot.reserve, pVale); + } + + // + // SWH ... + if (forBearish) + { + // + swhPivot.from = pBar.time; + + // + swhPivot.reserve = + swhPivot.reserve == 0 + ? pPeak + : MathMin(swhPivot.reserve, pPeak); + } + } + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + // SWL ... + if (forBullish) + { + // + result = + swlPivot.IsValid() && + swlPivot.GetAge() >= pivotVerifications; + if (result) + { + // + XBoxZone iBox; + result = swlPivot.AsBox(iBox); + if (result) + { + // + newSWLPivotDetected = AddBox( + iBox, + swlPivots // + ); + } + + // + iBox.Clean(); + } + + // + swlPivot.Clean(); + } + + // + // SWH ... + if (forBearish) + { + // + result = + swhPivot.IsValid() && + swhPivot.GetAge() >= pivotVerifications; + if (result) + { + // + XBoxZone iBox; + result = swhPivot.AsBox(iBox); + if (result) + { + // + newSWHPivotDetected = AddBox( + iBox, + swhPivots // + ); + } + + // + iBox.Clean(); + } + + // + swhPivot.Clean(); + } + } + + // + return result; + } + + // + void ValidateSwingPivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedSwingLifetime > 0; + + // + // SWH ... + has = HasSWHPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + swhPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + swhPivots, + maxAllowedSwingLifetime, + barIndex // + ); + } + } + + // + // SWL ... + has = HasSWLPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + swlPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + swlPivots, + maxAllowedSwingLifetime, + barIndex // + ); + } + } + } + + // + // SWL ... + + // + XCAPivot swlPivot; + bool detectSWLPivots; + XBoxZone swlPivots[]; + bool newSWLPivotDetected; + + // + bool HasSWLPivots() + { + return HasChild(swlPivots); + } + + // + int CountSWLPivots() + { + return ArraySize(swlPivots); + } + + // + // SWH ... + + // + XCAPivot swhPivot; + bool detectSWHPivots; + XBoxZone swhPivots[]; + bool newSWHPivotDetected; + + // + bool HasSWHPivots() + { + return HasChild(swhPivots); + } + + // + int CountSWHPivots() + { + return ArraySize(swhPivots); + } + + // + // PV ... + + // + int maxAllowedPVLifetime; // Max Allowed PV Life ... + bool applySwingsOnPVPivots; // Apply Swings on PV Pivots ... + bool selectRejectedPVPivots; // Select Rejected PV Pivots ... + bool selectEngulfedPVPivots; // Select Engulfed PV Pivots ... + bool selectPVWhichStartByFVG; // Select PV Pivots Which Starts by FVG ... + bool applySupportAndResistanceOnPVPivots; // Apply Support and Resistance on PV Pivots ... + + // + bool DetectPeakAndValePivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + XCAEAConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectValePivots + : detectPeakPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + datetime cTime = zBar.time; + string symbol = zBar.symbol; + ENUM_TIMEFRAMES period = zBar.period; + double points = GetPoints(symbol); + + // + // Reading Conditional Values ... + + // + // PEAK ... + double zPeak = conditions.peakBuffer[zIDX]; + double cPeak = conditions.peakBuffer[cIDX]; + double pPeak = conditions.peakBuffer[pIDX]; + double p2Peak = conditions.peakBuffer[p2IDX]; + + // + // PEAK Golden ... + double zPeakGolden = conditions.peakGoldenBuffer[zIDX]; + double cPeakGolden = conditions.peakGoldenBuffer[cIDX]; + double pPeakGolden = conditions.peakGoldenBuffer[pIDX]; + double p2PeakGolden = conditions.peakGoldenBuffer[p2IDX]; + + // + // VALE ... + double zVale = conditions.valeBuffer[zIDX]; + double cVale = conditions.valeBuffer[cIDX]; + double pVale = conditions.valeBuffer[pIDX]; + double p2Vale = conditions.valeBuffer[p2IDX]; + + // + // VALE Golden ... + double zValeGolden = conditions.valeGoldenBuffer[zIDX]; + double cValeGolden = conditions.valeGoldenBuffer[cIDX]; + double pValeGolden = conditions.valeGoldenBuffer[pIDX]; + double p2ValeGolden = conditions.valeGoldenBuffer[p2IDX]; + + // + // SWING High .. + double zSwingHigh = conditions.swingHighBuffer[zIDX]; + double cSwingHigh = conditions.swingHighBuffer[cIDX]; + double pSwingHigh = conditions.swingHighBuffer[pIDX]; + double p2SwingHigh = conditions.swingHighBuffer[p2IDX]; + + // + // SWING Low ... + double zSwingLow = conditions.swingLowBuffer[zIDX]; + double cSwingLow = conditions.swingLowBuffer[cIDX]; + double pSwingLow = conditions.swingLowBuffer[pIDX]; + double p2SwingLow = conditions.swingLowBuffer[p2IDX]; + + // + // SUPPORT ... + double zSupport = conditions.supportBuffer[zIDX]; + double cSupport = conditions.supportBuffer[cIDX]; + double pSupport = conditions.supportBuffer[pIDX]; + double p2Support = conditions.supportBuffer[p2IDX]; + + // + // RESISTANCE ... + double zResistance = conditions.resistanceBuffer[zIDX]; + double cResistance = conditions.resistanceBuffer[cIDX]; + double pResistance = conditions.resistanceBuffer[pIDX]; + double p2Resistance = conditions.resistanceBuffer[p2IDX]; + + // + // Detecting Bar Conditions ... + + // + ENUM_X_DIRECTION cBarDir; + + // + // Rejected ... + bool isCBarRejected = helper + .barAnalyser + .IsRejected( + cBar, + cBarDir, + false, // Force Type ... + false // Force Fibo Pressure ... + ); + + // + bool isCBarBullishRejected = + forBullish && + isCBarRejected && + IsBullish(cBarDir); + bool isCBarBearishRejected = + forBearish && + isCBarRejected && + IsBearish(cBarDir); + + // + bool isPBarRejected = helper + .barAnalyser + .IsRejected( + pBar, + cBarDir, + false, // Force Type ... + false // Force Fibo Pressure ... + ); + bool isPBarBullishRejected = + forBullish && + isPBarRejected && + IsBullish(cBarDir); + bool isPBarBearishRejected = + forBearish && + isPBarRejected && + IsBearish(cBarDir); + + // + bool isBarBullishRejected = + forBullish && + (isCBarBullishRejected || + isPBarBullishRejected); + + // + bool isBarBearishRejected = + forBearish && + (isCBarBearishRejected || + isPBarBearishRejected); + + // + // Engulfed ... + bool isCBarEngulfed = helper + .barAnalyser + .IsEngulfed( + cBar, + cBarDir // + ); + bool isCBarBullishEngulfed = + forBullish && + isCBarEngulfed && + IsBullish(cBarDir); + bool isCBarBearishEngulfed = + forBearish && + isCBarEngulfed && + IsBearish(cBarDir); + + // + bool isPBarEngulfed = helper + .barAnalyser + .IsEngulfed( + pBar, + cBarDir // + ); + bool isPBarBullishEngulfed = + forBullish && + isPBarEngulfed && + IsBullish(cBarDir); + bool isPBarBearishEngulfed = + forBearish && + isPBarEngulfed && + IsBearish(cBarDir); + + // + bool isBarBullishEngulfed = + forBullish && + (isCBarBullishEngulfed || + isPBarBullishEngulfed); + + // + bool isBarBearishEngulfed = + forBearish && + (isCBarBearishEngulfed || + isPBarBearishEngulfed); + + // + // Prepare Conditinal Conditions ... + + // + // PEAK ... + + // + bool isPeakSameLast = cPeak == pPeak; + bool isPeakSameLastPrev = pPeak == p2Peak; + + // + if (applySwingsOnPVPivots) + { + // + isPeakSameLast = + isPeakSameLast && + cSwingHigh == cPeak && + cSwingHigh == pSwingHigh; + + // + isPeakSameLastPrev = + isPeakSameLastPrev && + pSwingHigh == pPeak && + pSwingHigh == p2SwingHigh; + } + + // + if (applySupportAndResistanceOnPVPivots) + { + // + isPeakSameLast = + isPeakSameLast && + cResistance == cPeak && + cResistance == pResistance; + + // + isPeakSameLastPrev = + isPeakSameLastPrev && + pResistance == pPeak && + pResistance == p2Resistance; + } + + // + bool isPeakSwitchedToSameLast = isPeakSameLast && + !isPeakSameLastPrev; + bool isPeakFinishedFromSameLast = !isPeakSameLast && + isPeakSameLastPrev; + + // + // VALE ... + + // + bool isValeSameLast = cVale == pVale; + bool isValeSameLastPrev = pVale == p2Vale; + + // + if (applySwingsOnPVPivots) + { + // + isValeSameLast = + isValeSameLast && + cSwingLow == cVale && + cSwingLow == pSwingLow; + + // + isValeSameLastPrev = + isValeSameLastPrev && + pSwingLow == pVale && + pSwingLow == p2SwingLow; + } + + // + if (applySupportAndResistanceOnPVPivots) + { + // + isValeSameLast = + isValeSameLast && + cSupport == cVale && + cSupport == pSupport; + + // + isValeSameLastPrev = + isValeSameLastPrev && + pSupport == pVale && + pSupport == p2Support; + } + + // + bool isValeSwitchedToSameLast = isValeSameLast && + !isValeSameLastPrev; + bool isValeFinishedFromSameLast = !isValeSameLast && + isValeSameLastPrev; + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasStartCondition = + // + forBullish + ? isValeFinishedFromSameLast + : isPeakFinishedFromSameLast + // + ; + + // + bool hasContinuationCondition = + // + forBullish + ? isValeSameLast + : isPeakSameLast + // + ; + + // + bool hasEndCondition = + // + forBullish + ? isValeSwitchedToSameLast + : isPeakSwitchedToSameLast + // + ; + + // + // Apply Validations ... + if (hasEndCondition) + { + // + bool hasSelectionType = selectRejectedPVPivots || + selectEngulfedPVPivots; + + // + bool isPVRejected = + forBullish + ? (isBarBullishRejected && + selectRejectedPVPivots) + : (isBarBearishRejected && + selectRejectedPVPivots); + + // + bool isPVEngulfed = + forBullish + ? (isBarBullishEngulfed && + selectEngulfedPVPivots) + : (isBarBearishEngulfed && + selectEngulfedPVPivots); + + // + bool isBarPassed = + !hasSelectionType + ? true + : isPVRejected || + isPVEngulfed; + + // + hasEndCondition = + isBarPassed && + hasEndCondition; + if (!hasEndCondition) + { + // + // VALE ... + if (forBullish) + { + valePivot.Clean(); + } + + // + // PEAK ... + if (forBearish) + { + peakPivot.Clean(); + } + } + } + + // + // + // + + // + // ReInstance Pivot ... + if (hasStartCondition) + { + // + // VALE ... + if (forBullish) + { + // + valePivot.Clean(); + + // + valePivot.type = XCA_VALE; + valePivot.symbol = symbol; + valePivot.period = period; + + // + valePivot.to = pBar.time; + valePivot.from = pBar.time; + valePivot.value = pVale; + valePivot.reserve = pValeGolden; + } + + // + // PEAK ... + if (forBearish) + { + // + peakPivot.Clean(); + + // + peakPivot.type = XCA_PEAK; + peakPivot.symbol = symbol; + peakPivot.period = period; + + // + peakPivot.to = pBar.time; + peakPivot.from = pBar.time; + peakPivot.value = pPeak; + peakPivot.reserve = pPeakGolden; + } + } + + // + // Calculate and Fill Pivot Requirements ... + if (hasContinuationCondition) + { + // + // VALE ... + if (forBullish) + { + // + valePivot.from = pBar.time; + + // + valePivot.reserve = + valePivot.reserve == 0 + ? pValeGolden + : MathMin(valePivot.reserve, pValeGolden); + } + + // + // PEAK ... + if (forBearish) + { + // + peakPivot.from = pBar.time; + + // + peakPivot.reserve = + peakPivot.reserve == 0 + ? pPeakGolden + : MathMax(peakPivot.reserve, pPeakGolden); + } + } + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + // VALE ... + if (forBullish) + { + // + result = + valePivot.IsValid() && + valePivot.GetAge() >= pivotVerifications; + if (result) + { + // + XBoxZone iBox; + result = valePivot.AsBox(iBox); + if (result) + { + // + newValePivotDetected = AddBox( + iBox, + valePivots // + ); + } + + // + iBox.Clean(); + } + + // + valePivot.Clean(); + } + + // + // PEAK ... + if (forBearish) + { + // + result = + peakPivot.IsValid() && + peakPivot.GetAge() >= pivotVerifications; + if (result) + { + // + XBoxZone iBox; + result = peakPivot.AsBox(iBox); + if (result) + { + // + newPeakPivotDetected = AddBox( + iBox, + peakPivots // + ); + } + + // + iBox.Clean(); + } + + // + peakPivot.Clean(); + } + } + + // + return result; + } + + // + void ValidatePeakValePivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedPVLifetime > 0; + + // + // PEAK ... + has = HasPeakPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + peakPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + peakPivots, + maxAllowedPVLifetime, + barIndex // + ); + } + } + + // + // VALE ... + has = HasValePivots(); + if (has) + { + // + ApplyValidationOnBoxes( + valePivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + valePivots, + maxAllowedPVLifetime, + barIndex // + ); + } + } + } + + // + // PEAK ... + + // + XCAPivot peakPivot; + bool detectPeakPivots; + XBoxZone peakPivots[]; + bool newPeakPivotDetected; + + // + bool HasPeakPivots() + { + return HasChild(peakPivots); + } + + // + int CountPeakPivots() + { + return ArraySize(peakPivots); + } + + // + // VALE ... + + // + XCAPivot valePivot; + bool detectValePivots; + XBoxZone valePivots[]; + bool newValePivotDetected; + + // + bool HasValePivots() + { + return HasChild(valePivots); + } + + // + int CountValePivots() + { + return ArraySize(valePivots); + } + + // + // OB ... + int maxAllowedOBLifetime; // Max Allowed OB Life ... + + // + bool DetectOBPivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + XCAEAConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectOBBullishPivots + : detectOBBearishPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Prepare Conditinal Conditions ... + + // + // Default OB Detection ... + XBoxZone obBox; + bool isOB = barAnalyser.IsOB( + cBar, + obBox, + true, // OB FVG Bar Type ... + true // TWO Bar Verification ... + ); + bool isBullishOB = + isOB && + forBullish && + obBox.IsBullish(); + bool isBearishOB = + isOB && + forBearish && + obBox.IsBearish(); + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasStartCondition = false; + bool hasContinuationCondition = false; + bool hasEndCondition = isBullishOB || + isBearishOB; + + // + // ReInstance Pivot ... + if (hasStartCondition) + { + // + } + + // + // Calculate and Fill Pivot Requirements ... + if (hasContinuationCondition) + { + // + } + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + XBoxZone iBox; + XCAPivot iPivot; + + // + iPivot.to = obBox.to; + iPivot.from = obBox.from; + iPivot.symbol = obBox.symbol; + iPivot.period = obBox.period; + iPivot.type = forBullish + ? XCA_OB_BULL + : XCA_OB_BEAR; + iPivot.value = forBullish + ? obBox.lower + : obBox.upper; + iPivot.reserve = forBullish + ? obBox.upper + : obBox.lower; + + // + result = iPivot.IsValid(); + if (result) + { + // + result = iPivot.AsBox(iBox); + if (result) + { + // + if (forBullish) + { + // + result = AddBox( + iBox, + obBullishPivots // + ); + } + else + { + // + result = AddBox( + iBox, + obBearishPivots // + ); + } + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + + // + return result; + } + + // + void ValidateOBPivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedOBLifetime > 0; + + // + // Bullish ... + has = HasOBBullishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + obBullishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + obBullishPivots, + maxAllowedOBLifetime, + barIndex // + ); + } + } + + // + // Bearish ... + has = HasOBBearishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + obBearishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + obBearishPivots, + maxAllowedOBLifetime, + barIndex // + ); + } + } + } + + // + // OB Bullish Pivots ... + + // + bool detectOBBullishPivots; + XBoxZone obBullishPivots[]; + bool newOBBullishPivotDetected; + + // + bool HasOBBullishPivots() + { + return HasChild(obBullishPivots); + } + + // + int CountOBBullishPivots() + { + return ArraySize(obBullishPivots); + } + + // + // OB Bearish Pivots ... + + // + bool detectOBBearishPivots; + XBoxZone obBearishPivots[]; + bool newOBBearishPivotDetected; + + // + bool HasOBBearishPivots() + { + return HasChild(obBearishPivots); + } + + // + int CountOBBearishPivots() + { + return ArraySize(obBearishPivots); + } + + // + // FVG ... + + // + bool selectSameBarFVGs; // Select FVGs which has Same Type Bars ... + bool validateFVGUsingPV; // Detect FVG Type Two ( Validating Using PV ) ... + int maxAllowedFVGLifetime; // Max Allowed FVG Life ... + bool applyPVToFVGBoundary; // Apply PV to FVG Boundary ... + bool selectRejectedFVGPivots; // Select Rejected FVG Pivots ... + bool selectEngulfedFVGPivots; // Select Engulfed FVG Pivots ... + bool validateFVGUsingManalyser; // Detect FVG Type One ( Validating Using MAnalyser ) ... + bool applyLastBarToFVGBoundary; // Apply Last Bar to FVG Boundary ... + bool selectOnlyFVGWhichHasIndirectionalLastBar; // Select Only FVGs which has Indirectionsl Last Bar, uses to Order Block ... + + // + bool DetectFVGPivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + XCAEAConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectFVGBullishPivots + : detectFVGBearishPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + datetime cTime = zBar.time; + string symbol = zBar.symbol; + ENUM_TIMEFRAMES period = zBar.period; + double points = GetPoints(symbol); + + // + // Reading Conditional Values ... + + // + // PEAK ... + double zPeak = conditions.peakBuffer[zIDX]; + double cPeak = conditions.peakBuffer[cIDX]; + double pPeak = conditions.peakBuffer[pIDX]; + double p2Peak = conditions.peakBuffer[p2IDX]; + + // + // VALE ... + double zVale = conditions.valeBuffer[zIDX]; + double cVale = conditions.valeBuffer[cIDX]; + double pVale = conditions.valeBuffer[pIDX]; + double p2Vale = conditions.valeBuffer[p2IDX]; + + // + // MANALYSER ... + + // + // MAH ... + double zMAH = conditions.mahBuffer[zIDX]; + double cMAH = conditions.mahBuffer[cIDX]; + double pMAH = conditions.mahBuffer[pIDX]; + double p2MAH = conditions.mahBuffer[p2IDX]; + + // + // MAL ... + double zMAL = conditions.malBuffer[zIDX]; + double cMAL = conditions.malBuffer[cIDX]; + double pMAL = conditions.malBuffer[pIDX]; + double p2MAL = conditions.malBuffer[p2IDX]; + + // + // MAC ... + double zMAC = conditions.macBuffer[zIDX]; + double cMAC = conditions.macBuffer[cIDX]; + double pMAC = conditions.macBuffer[pIDX]; + double p2MAC = conditions.macBuffer[p2IDX]; + + // + // Detecting Bar Conditions ... + + // + ENUM_X_DIRECTION p2BarDir; + + // + // Rejected ... + bool isP2BarRejected = helper + .barAnalyser + .IsRejected( + p2Bar, + p2BarDir, + false, // Force Type ... + true // Force Fibo Pressure ... + ); + bool isP2BarBullishRejected = + isP2BarRejected && + IsBullish(p2BarDir); + bool isP2BarBearishRejected = + isP2BarRejected && + IsBearish(p2BarDir); + + // + // Engulfed ... + bool isP2BarEngulfed = helper + .barAnalyser + .IsEngulfed( + p2Bar, + p2BarDir // + ); + bool isP2BarBullishEngulfed = + isP2BarEngulfed && + IsBullish(p2BarDir); + bool isP2BarBearishEngulfed = + isP2BarEngulfed && + IsBearish(p2BarDir); + + // + // Prepare Conditinal Conditions ... + + // + // Default FVG Detection ... + XBoxZone fvgBox; + bool isFVG = barAnalyser.IsFVG( + cBar, + fvgBox // + ); + bool isBullishFVG = + isFVG && + forBullish && + fvgBox.IsBullish(); + bool isBearishFVG = + isFVG && + forBearish && + fvgBox.IsBearish(); + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasStartCondition = false; + bool hasContinuationCondition = false; + bool hasEndCondition = isBullishFVG || + isBearishFVG; + + // + // Apply all Filtering ... + if (hasEndCondition) + { + // + XOHCL p3Bar; + p2Bar.GetPreviousBar(p3Bar); + + // + bool isFVGValid = true; + + // + // Validate FVG Using Manalyser ... + bool isManalyserValid = false; + if (validateFVGUsingManalyser) + { + // + isManalyserValid = + hasEndCondition && + (forBullish + ? fvgBox.upper <= cMAL + : fvgBox.lower >= cMAH); + } + + // + // Validate FVG Using PV ... + bool isPVValid = false; + if (validateFVGUsingPV) + { + // + isPVValid = + hasEndCondition && + (forBullish + ? (p2Peak < pPeak || + pPeak < cPeak) + : (p2Vale > pVale || + pVale > cVale)); + } + + // + // Select Pure FVG ... + bool isPureFVGValid = + !validateFVGUsingPV && + !validateFVGUsingManalyser; + + // + // Summarise Validation ... + isFVGValid = + isPVValid || + isPureFVGValid || + isManalyserValid; + + // + bool isFVGBarPassed = false; + + // + // Select Same Bars FVGs ... + bool isFVGHasSameBar = true; + if (selectSameBarFVGs) + { + // + isFVGHasSameBar = + forBullish + ? (cBar.IsBullish() && + pBar.IsBullish() && + p2Bar.IsBullish()) + : (cBar.IsBearish() && + pBar.IsBearish() && + p2Bar.IsBearish()); + isFVGBarPassed = + isFVGBarPassed || + isFVGHasSameBar; + } + + // + // Select Rejected FVG ... + bool isFVGRejected = true; + if (selectRejectedFVGPivots) + { + // + isFVGRejected = + (forBullish + ? isP2BarBullishRejected + : isP2BarBearishRejected); + isFVGBarPassed = + isFVGBarPassed || + isFVGRejected; + } + + // + // Select Engulfed FVG ... + bool isFVGEngulfed = true; + if (selectEngulfedFVGPivots) + { + // + isFVGEngulfed = + (forBullish + ? isP2BarBullishEngulfed + : isP2BarBearishEngulfed); + isFVGBarPassed = + isFVGBarPassed || + isFVGEngulfed; + } + + // + // Select Only FVGs Which Has Indirectional Last Bar ... + bool isFVGHasIndirectionalStart = true; + if (selectOnlyFVGWhichHasIndirectionalLastBar) + { + // + isFVGHasIndirectionalStart = + p3Bar.IsValid() && + (forBullish + ? p3Bar.IsBearish() + : p3Bar.IsBullish()); + isFVGBarPassed = + isFVGBarPassed || + isFVGHasIndirectionalStart; + } + + // + // Summarise Bar Pass ... + isFVGBarPassed = + (selectSameBarFVGs || + selectRejectedFVGPivots || + selectEngulfedFVGPivots || + selectOnlyFVGWhichHasIndirectionalLastBar) + ? isFVGBarPassed + : true; + + // + hasEndCondition = isFVGValid && + isFVGBarPassed; + + // + // Apply Boundary ... + if (hasEndCondition) + { + // + double iValue = + forBullish + ? fvgBox.upper + : fvgBox.lower; + + // + if (applyPVToFVGBoundary) + { + // + fvgBox.upper = + forBullish + ? fvgBox.upper + : cPeak; + + // + fvgBox.lower = + forBullish + ? cVale + : fvgBox.lower; + } + + // + if (applyLastBarToFVGBoundary) + { + // + fvgBox.lower = MathMin(p3Bar.low, fvgBox.lower); + fvgBox.upper = MathMax(p3Bar.high, fvgBox.upper); + } + } + + // + p3Bar.Clean(); + } + + // + // ReInstance Pivot ... + if (hasStartCondition) + { + // + } + + // + // Calculate and Fill Pivot Requirements ... + if (hasContinuationCondition) + { + // + } + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + XBoxZone iBox; + XCAPivot iPivot; + + // + iPivot.to = fvgBox.to; + iPivot.from = fvgBox.from; + iPivot.symbol = fvgBox.symbol; + iPivot.period = fvgBox.period; + iPivot.type = forBullish + ? XCA_FVG_BULL + : XCA_FVG_BEAR; + iPivot.value = forBullish + ? fvgBox.lower + : fvgBox.upper; + iPivot.reserve = forBullish + ? fvgBox.upper + : fvgBox.lower; + + // + result = iPivot.IsValid(); + if (result) + { + // + result = iPivot.AsBox(iBox); + if (result) + { + // + if (forBullish) + { + // + result = AddBox( + iBox, + fvgBullishPivots // + ); + } + else + { + // + result = AddBox( + iBox, + fvgBearishPivots // + ); + } + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + + // + return result; + } + + // + void ValidateFVGPivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedFVGLifetime > 0; + + // + // Bullish ... + has = HasFVGBullishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + fvgBullishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + fvgBullishPivots, + maxAllowedFVGLifetime, + barIndex // + ); + } + } + + // + // Bearish ... + has = HasFVGBearishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + fvgBearishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + fvgBearishPivots, + maxAllowedFVGLifetime, + barIndex // + ); + } + } + } + + // + // FVG Bullish Pivots ... + + // + bool detectFVGBullishPivots; + XBoxZone fvgBullishPivots[]; + bool newFVGBullishPivotDetected; + + // + bool HasFVGBullishPivots() + { + return HasChild(fvgBullishPivots); + } + + // + int CountFVGBullishPivots() + { + return ArraySize(fvgBullishPivots); + } + + // + // FVG Bearish Pivots ... + + // + bool detectFVGBearishPivots; + XBoxZone fvgBearishPivots[]; + bool newFVGBearishPivotDetected; + + // + bool HasFVGBearishPivots() + { + return HasChild(fvgBearishPivots); + } + + // + int CountFVGBearishPivots() + { + return ArraySize(fvgBearishPivots); + } + + // + // TREND ... + + // + int maxAllowedTrendLifetime; // Max Allowed Trend Life ... + + // + bool DetectTrendPivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + XCAEAConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectTrendBullishPivots + : detectTrendBearishPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + datetime cTime = zBar.time; + string symbol = zBar.symbol; + ENUM_TIMEFRAMES period = zBar.period; + double points = GetPoints(symbol); + + // + // Reading Conditional Values ... + + // + // TREND ... + double zTrend = conditions.trendBuffer[zIDX]; + double cTrend = conditions.trendBuffer[cIDX]; + double pTrend = conditions.trendBuffer[pIDX]; + double p2Trend = conditions.trendBuffer[p2IDX]; + + // + // TREND State ... + double zTrendState = conditions.trendStateBuffer[zIDX]; + double cTrendState = conditions.trendStateBuffer[cIDX]; + double pTrendState = conditions.trendStateBuffer[pIDX]; + double p2TrendState = conditions.trendStateBuffer[p2IDX]; + + // + // Prepare Conditinal Conditions ... + + // + // Bullish ... + + // + bool isTrendBullish = + cTrendState > 0; + bool isTrendBullishPrev = + pTrendState > 0; + + // + bool isTrendSwitchedToBullish = isTrendBullish && + !isTrendBullishPrev; + bool isTrendFinishedFromBullish = !isTrendBullish && + isTrendBullishPrev; + + // + // Bearish ... + + // + bool isTrendBearish = + cTrendState < 0; + bool isTrendBearishPrev = + pTrendState < 0; + + // + bool isTrendSwitchedToBearish = isTrendBearish && + !isTrendBearishPrev; + bool isTrendFinishedFromBearish = !isTrendBearish && + isTrendBearishPrev; + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasStartCondition = + forBullish + ? isTrendFinishedFromBullish + : isTrendFinishedFromBearish; + bool hasContinuationCondition = + forBullish + ? isTrendBullish + : isTrendBearish; + bool hasEndCondition = + forBullish + ? isTrendSwitchedToBullish + : isTrendSwitchedToBearish; + + // + // ReInstance Pivot ... + if (hasStartCondition) + { + // + // Bullish ... + if (forBullish) + { + // + trendBullishPivot.Clean(); + + // + trendBullishPivot.symbol = symbol; + trendBullishPivot.period = period; + trendBullishPivot.type = XCA_TREND_BULL; + + // + trendBullishPivot.to = pBar.time; + trendBullishPivot.from = pBar.time; + trendBullishPivot.value = pTrend; + trendBullishPivot.reserve = pTrend; + } + + // + // Bearish ... + if (forBearish) + { + // + trendBearishPivot.Clean(); + + // + trendBearishPivot.symbol = symbol; + trendBearishPivot.period = period; + trendBearishPivot.type = XCA_TREND_BEAR; + + // + trendBearishPivot.to = pBar.time; + trendBearishPivot.from = pBar.time; + trendBearishPivot.value = pTrend; + trendBearishPivot.reserve = pTrend; + } + } + + // + // Calculate and Fill Pivot Requirements ... + if (hasContinuationCondition) + { + // + // Bullish ... + if (forBullish) + { + // + trendBullishPivot.from = pBar.time; + + // + Add( + pTrend, + trendBullishPivot.values // + ); + Add( + pTrend, + trendBullishPivot.values // + ); + } + + // + // Bearish ... + if (forBearish) + { + // + trendBearishPivot.from = pBar.time; + + // + Add( + pTrend, + trendBearishPivot.values // + ); + Add( + pTrend, + trendBearishPivot.values // + ); + } + } + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + // Bullish ... + if (forBullish) + { + // + // Update Values ... + trendBullishPivot.value = GetMin(trendBullishPivot.values); + trendBullishPivot.reserve = GetMax(trendBullishPivot.values); + + // + result = + trendBullishPivot.IsValid() && + trendBullishPivot.GetAge() >= pivotVerifications; + if (result) + { + // + XBoxZone iBox; + result = trendBullishPivot.AsBox(iBox); + if (result) + { + // + newTrendBullishPivotDetected = AddBox( + iBox, + trendBullishPivots // + ); + } + + // + iBox.Clean(); + } + + // + trendBullishPivot.Clean(); + } + + // + // Bearish ... + if (forBearish) + { + // + // Update Values ... + trendBearishPivot.value = GetMax(trendBearishPivot.values); + trendBearishPivot.reserve = GetMin(trendBearishPivot.values); + + // + result = + trendBearishPivot.IsValid() && + trendBearishPivot.GetAge() >= pivotVerifications; + if (result) + { + // + XBoxZone iBox; + result = trendBearishPivot.AsBox(iBox); + if (result) + { + // + newTrendBearishPivotDetected = AddBox( + iBox, + trendBearishPivots // + ); + } + + // + iBox.Clean(); + } + + // + trendBearishPivot.Clean(); + } + } + + // + return result; + } + + // + void ValidateTrendPivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedTrendLifetime > 0; + + // + // Bullish ... + has = HasTrendBullishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + trendBullishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + trendBullishPivots, + maxAllowedTrendLifetime, + barIndex // + ); + } + } + + // + // Bearish ... + has = HasTrendBearishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + trendBearishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + trendBearishPivots, + maxAllowedTrendLifetime, + barIndex // + ); + } + } + } + + // + // Bullish ... + + // + XCAPivot trendBullishPivot; + XBoxZone trendBullishPivots[]; + bool detectTrendBullishPivots; + bool newTrendBullishPivotDetected; + + // + bool HasTrendBullishPivots() + { + return HasChild(trendBullishPivots); + } + + // + int CountTrendBullishPivots() + { + return ArraySize(trendBullishPivots); + } + + // + // Bearish ... + + // + XCAPivot trendBearishPivot; + XBoxZone trendBearishPivots[]; + bool detectTrendBearishPivots; + bool newTrendBearishPivotDetected; + + // + bool HasTrendBearishPivots() + { + return HasChild(trendBearishPivots); + } + + // + int CountTrendBearishPivots() + { + return ArraySize(trendBearishPivots); + } + + // + // TRIGGER Blocks ... + + // + int triggerBlockSwingLength; + int filterTriggerBlocksBySar; + double triggerBlockMaxAllowedRange; + bool triggerBlockBarHasProperSwing; + bool triggerBlockBarPressureValidation; + + // + bool DetectTriggerBlockPivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + XCAEAConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectTriggerBlockBullishPivots + : detectTriggerBlockBearishPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + + // + datetime cTime = zBar.time; + string symbol = zBar.symbol; + ENUM_TIMEFRAMES period = zBar.period; + double points = GetPoints(symbol); + + // + // Reading Conditional Values ... + + // + // Prepare Conditinal Conditions ... + + // + // Checking Base Block Exists ... + XBoxZone iBlock; + result = helper.barAnalyser.IsOB( + cBar, + iBlock, + true, // Force FVG Bar Type ... + true // Force Two Bar ... + ); + if (!result) + { + // + iBlock.Clean(); + + // + return result; + } + + // + // Bullish ... + bool isBullish = + result && + forBullish && + iBlock.IsBullish(); + + // + // Bearish ... + bool isBearish = + result && + forBearish && + iBlock.IsBearish(); + + // + // Summarizing Conditions ... + + // + result = isBullish || + isBearish; + if (!result) + { + // + iBlock.Clean(); + + // + return result; + } + + // + // Adding Pivot to Box Type ... + string iType = isBullish + ? GetBoxType(XCA_TRIGGER_BULL) + : GetBoxType(XCA_TRIGGER_BEAR); + iBlock.type = iType; + + // + // Validate TriggerBlock ... + XOHCL p3Bar; + XOHCL p4Bar; + result = + p2Bar.GetPreviousBar(p3Bar); + result = + result && + p3Bar.GetPreviousBar(p4Bar); + if (!result) + { + // + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + + // + return result; + } + ENUM_X_DIRECTION iDir; + + // + // Validating Range ... + if (triggerBlockMaxAllowedRange > 0) + { + // + double blockRange = iBlock.GetRange(); + result = blockRange <= triggerBlockMaxAllowedRange * points; + if (!result) + { + // + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + + // + return result; + } + } + + // + // Validate Using Swing Bars ... + if (triggerBlockBarHasProperSwing) + { + // + // Check Has Proper Swing ... + + // + // CBar ... + bool isCBarSimpleSwing = + barAnalyser.IsSimpleSwing( + cBar, + iDir // + ); + bool isCBarBullishSimpleSwing = + isCBarSimpleSwing && + IsBullish(iDir); + bool isCBarBearishSimpleSwing = + isCBarSimpleSwing && + IsBearish(iDir); + + // + // PBar ... + bool isPBarSimpleSwing = + barAnalyser.IsSimpleSwing( + pBar, + iDir // + ); + bool isPBarBullishSimpleSwing = + isPBarSimpleSwing && + IsBullish(iDir); + bool isPBarBearishSimpleSwing = + isPBarSimpleSwing && + IsBearish(iDir); + + // + // P2Bar ... + bool isP2BarSimpleSwing = + barAnalyser.IsSimpleSwing( + p2Bar, + iDir // + ); + bool isP2BarBullishSimpleSwing = + isP2BarSimpleSwing && + IsBullish(iDir); + bool isP2BarBearishSimpleSwing = + isP2BarSimpleSwing && + IsBearish(iDir); + + // + // P3Bar ... + bool isP3BarSimpleSwing = + barAnalyser.IsSimpleSwing( + p3Bar, + iDir // + ); + bool isP3BarBullishSimpleSwing = + isP3BarSimpleSwing && + IsBullish(iDir); + bool isP3BarBearishSimpleSwing = + isP3BarSimpleSwing && + IsBearish(iDir); + + // + // P4Bar ... + bool isP4BarSimpleSwing = + barAnalyser.IsSimpleSwing( + p4Bar, + iDir // + ); + bool isP4BarBullishSimpleSwing = + isP4BarSimpleSwing && + IsBullish(iDir); + bool isP4BarBearishSimpleSwing = + isP4BarSimpleSwing && + IsBearish(iDir); + + // + // Summarise Validation ... + + // + bool isBullishSwimpleSwing = + isBullish && + (isCBarBullishSimpleSwing || + isPBarBullishSimpleSwing || + isP2BarBullishSimpleSwing || + isP3BarBullishSimpleSwing || + isP4BarBullishSimpleSwing); + + // + bool isBearishSwimpleSwing = + isBearish && + (isCBarBearishSimpleSwing || + isPBarBearishSimpleSwing || + isP2BarBearishSimpleSwing || + isP3BarBearishSimpleSwing || + isP4BarBearishSimpleSwing); + + // + result = isBullishSwimpleSwing || + isBearishSwimpleSwing; + if (!result) + { + // + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + + // + return result; + } + } + + // + // Validating Using Bar Pressure ... + if (triggerBlockBarPressureValidation) + { + // + // Check pBar is Momentum Bar ... + // and Breakd Block Side ... + + // + bool isCBarMomentum = barAnalyser.IsMomentum( + pBar, + iDir // + ); + bool isCBarBullishMomentum = + isCBarMomentum && + IsBullish(iDir); + bool isCBarBearishMomentum = + isCBarMomentum && + IsBearish(iDir); + + // + bool isPBarMomentum = barAnalyser.IsMomentum( + pBar, + iDir // + ); + bool isPBarBullishMomentum = + isPBarMomentum && + IsBullish(iDir); + bool isPBarBearishMomentum = + isPBarMomentum && + IsBearish(iDir); + + // + bool isBullishBreakedOut = + isBullish && + forBullish && + pBar.IsBullish() && + (isCBarBullishMomentum || + isPBarBullishMomentum) && + pBar.GetUp() > iBlock.upper && + pBar.GetDown() < iBlock.upper; + + // + bool isBearishBreakedOut = + isBearish && + forBearish && + pBar.IsBearish() && + (isCBarBearishMomentum || + isPBarBearishMomentum) && + pBar.GetUp() > iBlock.lower && + pBar.GetDown() < iBlock.lower; + + // + result = + isBullishBreakedOut || + isBearishBreakedOut; + if (!result) + { + // + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + + // + return result; + } + } + + // + // Extract to and from Info ... + + // + int toIDX = iBlock.ToIndex(); + int fromIDX = iBlock.FromIndex(); + + // + XOHCL toBar; + XOHCL fromBar; + + // + result = iBlock.ToBar(toBar); + result = result && + iBlock.FromBar(fromBar); + if (!result) + { + // + toBar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + fromBar.Clean(); + + // + return result; + } + + // + // Validating Using HH and LL ... + if (triggerBlockSwingLength > 0) + { + // + double toLL = toBar.FindLowest(triggerBlockSwingLength, MODE_LOW); + double toHH = toBar.FindHighest(triggerBlockSwingLength, MODE_HIGH); + + // + double fromLL = fromBar.FindLowest(triggerBlockSwingLength, MODE_LOW); + double fromHH = fromBar.FindHighest(triggerBlockSwingLength, MODE_HIGH); + + // + double selectedLL = fromLL; // MathMin(toLL, fromLL); + double selectedHH = fromHH; // MathMax(toHH, fromHH); + + // + bool isBullishSwingPassed = + isBullish && + forBullish && + selectedLL >= iBlock.lower; + + // + bool isBearishSwingPassed = + isBearish && + forBearish && + selectedHH <= iBlock.upper; + + // + result = isBullishSwingPassed || + isBearishSwingPassed; + if (!result) + { + // + toBar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + fromBar.Clean(); + + // + return result; + } + } + + // + // Apply Filters ... + bool hasFilter = + filterTriggerBlocksBySar; + if (hasFilter) + { + // + // Sar Filtering ... + if (filterTriggerBlocksBySar) + { + // + // Reading Conditions ... + + // + 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]; + + // + // Preparing Constom Conditions ... + + // + bool isZSarBullish = zSar < zBar.low; + bool isCSarBullish = cSar < cBar.low; + bool isPSarBullish = pSar < pBar.low; + bool isP2SarBullish = p2Sar < p2Bar.low; + bool isP3SarBullish = p3Sar < p3Bar.low; + + // + bool isZSarBearish = zSar > zBar.high; + bool isCSarBearish = cSar > cBar.high; + bool isPSarBearish = pSar > pBar.high; + bool isP2SarBearish = p2Sar > p2Bar.high; + bool isP3SarBearish = p3Sar > p3Bar.high; + + // + bool isCSarSwitchedToBullish = + isCSarBullish && + !isPSarBullish; + bool isPSarSwitchedToBullish = + isPSarBullish && + !isP2SarBullish; + bool isP2SarSwitchedToBullish = + isP2SarBullish && + !isP3SarBullish; + + // + bool isCSarSwitchedToBearish = + isCSarBearish && + !isPSarBearish; + bool isPSarSwitchedToBearish = + isPSarBearish && + !isP2SarBearish; + bool isP2SarSwitchedToBearish = + isP2SarBearish && + !isP3SarBearish; + + // + // Summarize Custom Conditions ... + + // + // Bullish ... + + // + bool isCSarBullishPassed = + isZSarBullish && + isCSarSwitchedToBullish; + + // + bool isPSarBullishPassed = + isZSarBullish && + isCSarBullish && + isPSarSwitchedToBullish; + + // + bool isP2SarBullishPassed = + isZSarBullish && + isCSarBullish && + isPSarBullish && + isP2SarSwitchedToBullish; + + // + // Bearish ... + + // + bool isCSarBearishPassed = + isZSarBearish && + isCSarSwitchedToBearish; + + // + bool isPSarBearishPassed = + isZSarBearish && + isCSarBearish && + isPSarSwitchedToBearish; + + // + bool isP2SarBearishPassed = + isZSarBearish && + isCSarBearish && + isPSarBearish && + isP2SarSwitchedToBearish; + + // + // Summarize Conditions ... + + // + bool isBullishFiltered = + isBullish && + forBullish && + (isCSarBullishPassed || + isPSarBullishPassed || + isP2SarBullishPassed); + + // + bool isBearishFiltered = + isBearish && + forBearish && + (isCSarBearishPassed || + isPSarBearishPassed || + isP2SarBearishPassed); + + // + result = isBullishFiltered || + isBearishFiltered; + if (!result) + { + // + toBar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + fromBar.Clean(); + + // + return result; + } + } + } + + // + // Summarize ... + + // + isBullish = + isBullish && + forBullish && + iBlock.IsValid(); + + // + isBearish = + isBearish && + forBearish && + iBlock.IsValid(); + + // + result = isBullish || + isBearish; + if (!result) + { + iBlock.Clean(); + } + + // + // Storing Pivot ... + + // + if (isBullish) + { + // + result = AddBox( + iBlock, + triggerBlockBullishPivots // + ); + } + + // + if (isBearish) + { + // + result = AddBox( + iBlock, + triggerBlockBearishPivots // + ); + } + + // + // Cleanup Resource ... + + // + toBar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + fromBar.Clean(); + + // + return result; + } + + // + void ValidateTriggerBlockPivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + // Since Trigger Blocks Doesnt Use Multiple Times, + // there is not any Validation Required for them ... + bool has = false; + + // + // bool applyLifetimeValidating = maxAllowedTriggerBlockLifetime > 0; + + // + // Bullish ... + has = HasTriggerBlockBullishPivots(); + if (has) + { + } + + // + // Bearish ... + has = HasTriggerBlockBearishPivots(); + if (has) + { + } + } + + // + // Bullish ... + + // + XBoxZone triggerBlockBullishPivots[]; + bool detectTriggerBlockBullishPivots; + bool newTriggerBlockBullishPivotDetected; + + // + bool HasTriggerBlockBullishPivots() + { + return HasChild(triggerBlockBullishPivots); + } + + // + int CountTriggerBlockBullishPivots() + { + return ArraySize(triggerBlockBullishPivots); + } + + // + // Bearish ... + + // + bool detectTriggerBlockBearishPivots; + XBoxZone triggerBlockBearishPivots[]; + bool newTriggerBlockBearishPivotDetected; + + // + bool HasTriggerBlockBearishPivots() + { + return HasChild(triggerBlockBearishPivots); + } + + // + int CountTriggerBlockBearishPivots() + { + return ArraySize(triggerBlockBearishPivots); + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Prrivate ... + private: + // + // Props ... + + // + XCPOIDrawer *drawer; + XCXCAEAHelper *helper; + XCBarAnalyser *barAnalyser; + + // + bool AddBox( + XBoxZone &box, + XBoxZone &boxes[] // + ) + { + // + bool result = false; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + bool isExists = FindBoxIndex( + idx, + box, + boxes // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + int before = ArraySize(boxes); + + // + AddRef( + box, + boxes // + ); + + // + int after = ArraySize(boxes); + + // + result = after > before; + + // + return result; + } + + // + bool ValidateBox( + XBoxZone &box, + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize Bar Index ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Ceck Input Box is Valid ... + result = box.IsValid(); + if (!result) + { + return result; + } + + // + // Check Input Box is Available ... + bool canCheckUnAvailableBoxes = HasChild(unavailables); + if (canCheckUnAvailableBoxes) + { + // + int idx = -1; + bool isUnAvailable = FindBoxIndex( + idx, + box, + unavailables // + ); + result = !isUnAvailable; + if (!result) + { + return result; + } + } + + // + // Check Input Box is Breaked or not ... + + // + // Check Bar Index must after Box To Index ... + int toIDX = box.ToIndex(); + int fromIDX = box.FromIndex(); + result = toIDX > barIndex && + fromIDX > barIndex && + fromIDX > toIDX; + if (!result) + { + return result; + } + + // + // Detect Box Applied Boundary Price ... + // For Checking Break of Box ... + bool isBullish = box.IsBullish(); + double boundary = + isBullish + ? box.lower + : box.upper; + + // + // for validating Box Break we have to wait At Least 3 Bars Close + // out of Box Boundary ... + int barsLength = 3; + + // + // Calculate Start Checking Bar Index ... + int startCheckBreaktionBarIndex = toIDX - barsLength; + bool isBarIndexValid = startCheckBreaktionBarIndex > 0 && + barIndex < startCheckBreaktionBarIndex; + result = isBarIndexValid; + if (!result) + { + // + // Assume Box is Valid if Bar Index not Valid for Checking ... + result = true; + return result; + } + + // + // Try to Check Box Validation if Everything is OK ... + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + bool isValid = false; + bool isBreaked = false; + for (int i = barIndex; i < startCheckBreaktionBarIndex; i++) + { + // + // Initialize Bars ... + isValid = cBar.Init( + box.symbol, + box.period, + i + 1 // + ); + isValid = + result && + cBar.GetPreviousBar(pBar); + isValid = + result && + pBar.GetPreviousBar(p2Bar); + if (!isValid) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + result = false; + + // + break; + } + + // + // Preparing Conditions ... + + // + bool isBullishBreaked = + isBullish && + cBar.close < boundary && + pBar.close < boundary && + p2Bar.close < boundary; + + // + bool isBearishBreaked = + !isBullish && + cBar.close > boundary && + pBar.close > boundary && + p2Bar.close > boundary; + + // + // Calculate Result ... + isBreaked = isBullishBreaked || + isBearishBreaked; + if (isBreaked) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + result = false; + + // + break; + } + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + } + + // + result = isValid && + !isBreaked; + if (!result) + { + // + int idx = -1; + bool isExists = FindBoxIndex( + idx, + box, + invalidPivots // + ); + if (!isExists) + { + // + AddRef( + box, + invalidPivots // + ); + } + } + + // + // Cleanup Resource ... + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + void CleanPivots() + { + // + Clean(invalidPivots); + + // + swlPivot.Clean(); + swhPivot.Clean(); + peakPivot.Clean(); + valePivot.Clean(); + trendBullishPivot.Clean(); + trendBearishPivot.Clean(); + + // + Clean(swlPivots); + Clean(swhPivots); + + // + Clean(peakPivots); + Clean(valePivots); + + // + Clean(obBullishPivots); + Clean(obBearishPivots); + + // + Clean(fvgBullishPivots); + Clean(fvgBearishPivots); + + // + Clean(trendBullishPivots); + Clean(trendBearishPivots); + + // + Clean(triggerBlockBullishPivots); + Clean(triggerBlockBearishPivots); + } + + // + void SortPivots() + { + // + bool has = false; + + // + // Invalid Pivots ... + has = HasInvalidPivots(); + if (has) + { + ApplySortOnBoxes(invalidPivots); + } + + // + // SWING ... + + // + // SWH ... + has = HasSWHPivots(); + if (has) + { + ApplySortOnBoxes(swhPivots); + } + + // + // SWL ... + has = HasSWLPivots(); + if (has) + { + ApplySortOnBoxes(swlPivots); + } + + // + // PV ... + + // + // PEAK ... + has = HasPeakPivots(); + if (has) + { + ApplySortOnBoxes(peakPivots); + } + + // + // VALE ... + has = HasValePivots(); + if (has) + { + ApplySortOnBoxes(valePivots); + } + + // + // OB ... + + // + // Bullish ... + has = HasOBBullishPivots(); + if (has) + { + ApplySortOnBoxes(obBullishPivots); + } + + // + // Bearish ... + has = HasOBBearishPivots(); + if (has) + { + ApplySortOnBoxes(obBearishPivots); + } + + // + // FVG ... + + // + // Bullish ... + has = HasFVGBullishPivots(); + if (has) + { + ApplySortOnBoxes(fvgBullishPivots); + } + + // + // Bearish ... + has = HasFVGBearishPivots(); + if (has) + { + ApplySortOnBoxes(fvgBearishPivots); + } + + // + // TREND ... + + // + // Bullish ... + has = HasTrendBullishPivots(); + if (has) + { + ApplySortOnBoxes(trendBullishPivots); + } + + // + // Bearish ... + has = HasTrendBearishPivots(); + if (has) + { + ApplySortOnBoxes(trendBearishPivots); + } + + // + // TRIGGER Block ... + + // + // Bullish ... + has = HasTriggerBlockBullishPivots(); + if (has) + { + ApplySortOnBoxes(triggerBlockBullishPivots); + } + + // + // Bearish ... + has = HasTriggerBlockBearishPivots(); + if (has) + { + ApplySortOnBoxes(triggerBlockBearishPivots); + } + } + + // + void ApplySortOnBoxes( + XBoxZone &items[] // + ) + { + // + int idx = -1; + bool has = false; + + // + has = HasChild(items); + if (!has) + { + return; + } + + // + XBoxZone tmp[]; + Copy( + items, + tmp // + ); + Clean(items); + + // + while (HasChild(tmp)) + { + // + idx = GetOldest(tmp); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XBoxZone iBox = tmp[idx]; + ArrayRemove( + tmp, + idx, + 1 // + ); + + // + AddRef( + iBox, + items // + ); + } + + // + CleanupArray( + items, + maxAllowedPivots // + ); + + // + Clean(tmp); + } + + // + void ApplyValidationOnBoxes( + XBoxZone &items[], + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + has = HasChild(items); + if (!has) + { + return; + } + + // + XBoxZone tmp[]; + Copy( + items, + tmp // + ); + Clean(items); + while (HasChild(tmp)) + { + // + XBoxZone iBox = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = ValidateBox( + iBox, + unavailables, + barIndex // + ); + if (has) + { + // + AddRef( + iBox, + items // + ); + } + + // + iBox.Clean(); + // + } + + // + Clean(tmp); + } + + // + void ApplyLifeTimeValidationOnBoxes( + XBoxZone &items[], + int maxAllowedAge = 0, + int barIndex = 0 // + ) + { + // + bool has = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + has = + maxAllowedAge > 0 && + HasChild(items); + if (!has) + { + return; + } + + // + datetime cTime = GetBarTime( + helper.GetSymbol(), + helper.GetPeriod(), + barIndex // + ); + + // + XBoxZone tmp[]; + Copy( + items, + tmp // + ); + Clean(items); + + // + while (HasChild(tmp)) + { + // + XBoxZone iBox = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + datetime defTo = iBox.to; + iBox.to = cTime; + + // + int iAge = iBox.GetAge(); + has = iAge <= maxAllowedAge; + iBox.to = defTo; + if (has) + { + // + AddRef( + iBox, + items // + ); + } + else + { + // + int idx = -1; + bool isExists = FindBoxIndex( + idx, + iBox, + invalidPivots // + ); + if (!isExists) + { + // + AddRef( + iBox, + invalidPivots // + ); + } + } + + // + iBox.Clean(); + } + + // + Clean(tmp); + } + + // +}; + +// \ No newline at end of file diff --git a/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 b/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 index 92118f56..c5701267 100644 --- a/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 +++ b/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 @@ -929,16 +929,6 @@ class XCXCAEAPOIDetector : public XCBase detectTrendBullishPivots = false; detectTrendBearishPivots = false; - // - // Trigger Block ... - triggerBlockSwingLength = 7; - triggerBlockMaxAllowedRange = 0; - filterTriggerBlocksBySar = true; - triggerBlockBarHasProperSwing = true; - detectTriggerBlockBullishPivots = false; - detectTriggerBlockBearishPivots = false; - triggerBlockBarPressureValidation = true; - // } @@ -980,8 +970,6 @@ class XCXCAEAPOIDetector : public XCBase newFVGBearishPivotDetected = false; newTrendBullishPivotDetected = false; newTrendBearishPivotDetected = false; - newTriggerBlockBullishPivotDetected = false; - newTriggerBlockBearishPivotDetected = false; // int index = barIndex; @@ -1035,51 +1023,7 @@ class XCXCAEAPOIDetector : public XCBase // continue; } - - // - // Handle On Time Detection Pivots ... - bool isFirstBar = start == index; - if (isFirstBar) - { - // - // TRIGGER Block ... - // Since Trigger Block Pivots Only Used on Detection Time ... - // we have to Detect only when zBar Index is Zero, means at Last Bar ... - // in this Senario we Have to Ignore LoopBacks ... - - // - // Bullish ... - if (detectTriggerBlockBullishPivots) - { - // - newTriggerBlockBullishPivotDetected = DetectTriggerBlockPivot( - barIndex, - X_DIRECTION_BULLISH, - zBar, - cBar, - pBar, - p2Bar, - conditions // - ); - } - - // - // Bearish ... - if (detectTriggerBlockBearishPivots) - { - // - newTriggerBlockBearishPivotDetected = DetectTriggerBlockPivot( - barIndex, - X_DIRECTION_BEARISH, - zBar, - cBar, - pBar, - p2Bar, - conditions // - ); - } - } - + // // Checking Pivots ... @@ -1320,13 +1264,6 @@ class XCXCAEAPOIDetector : public XCBase barIndex // ); - // - // TRIGGER Block ... - ValidateTriggerBlockPivots( - unavailables, - barIndex // - ); - // SortPivots(); } @@ -3941,709 +3878,6 @@ class XCXCAEAPOIDetector : public XCBase return ArraySize(trendBearishPivots); } - // - // TRIGGER Blocks ... - - // - int triggerBlockSwingLength; - int filterTriggerBlocksBySar; - double triggerBlockMaxAllowedRange; - bool triggerBlockBarHasProperSwing; - bool triggerBlockBarPressureValidation; - - // - bool DetectTriggerBlockPivot( - int barIndex, - ENUM_X_DIRECTION forDir, - XOHCL &zBar, - XOHCL &cBar, - XOHCL &pBar, - XOHCL &p2Bar, - XCAEAConditions &conditions // - ) - { - // - bool result = false; - - // - // Checking Direction ... - result = HasDirection(forDir); - if (!result) - { - return result; - } - - // - bool forBullish = IsBullish(forDir); - bool forBearish = IsBearish(forDir); - - // - // Check Allowed ... - result = - forBullish - ? detectTriggerBlockBullishPivots - : detectTriggerBlockBearishPivots; - if (!result) - { - return result; - } - - // - // Validate Args ... - result = - // - barIndex >= 0 && - zBar.IsValid() && - cBar.IsValid() && - pBar.IsValid() && - p2Bar.IsValid() - // - ; - if (!result) - { - return result; - } - - // - // Define Requirements ... - - // - int zIDX = 0; - int cIDX = zIDX + 1; - int pIDX = cIDX + 1; - int p2IDX = pIDX + 1; - int p3IDX = p2IDX + 1; - - // - datetime cTime = zBar.time; - string symbol = zBar.symbol; - ENUM_TIMEFRAMES period = zBar.period; - double points = GetPoints(symbol); - - // - // Reading Conditional Values ... - - // - // Prepare Conditinal Conditions ... - - // - // Checking Base Block Exists ... - XBoxZone iBlock; - result = helper.barAnalyser.IsOB( - cBar, - iBlock, - true, // Force FVG Bar Type ... - true // Force Two Bar ... - ); - if (!result) - { - // - iBlock.Clean(); - - // - return result; - } - - // - // Bullish ... - bool isBullish = - result && - forBullish && - iBlock.IsBullish(); - - // - // Bearish ... - bool isBearish = - result && - forBearish && - iBlock.IsBearish(); - - // - // Summarizing Conditions ... - - // - result = isBullish || - isBearish; - if (!result) - { - // - iBlock.Clean(); - - // - return result; - } - - // - // Adding Pivot to Box Type ... - string iType = isBullish - ? GetBoxType(XCA_TRIGGER_BULL) - : GetBoxType(XCA_TRIGGER_BEAR); - iBlock.type = iType; - - // - // Validate TriggerBlock ... - XOHCL p3Bar; - XOHCL p4Bar; - result = - p2Bar.GetPreviousBar(p3Bar); - result = - result && - p3Bar.GetPreviousBar(p4Bar); - if (!result) - { - // - p3Bar.Clean(); - p4Bar.Clean(); - iBlock.Clean(); - - // - return result; - } - ENUM_X_DIRECTION iDir; - - // - // Validating Range ... - if (triggerBlockMaxAllowedRange > 0) - { - // - double blockRange = iBlock.GetRange(); - result = blockRange <= triggerBlockMaxAllowedRange * points; - if (!result) - { - // - p3Bar.Clean(); - p4Bar.Clean(); - iBlock.Clean(); - - // - return result; - } - } - - // - // Validate Using Swing Bars ... - if (triggerBlockBarHasProperSwing) - { - // - // Check Has Proper Swing ... - - // - // CBar ... - bool isCBarSimpleSwing = - barAnalyser.IsSimpleSwing( - cBar, - iDir // - ); - bool isCBarBullishSimpleSwing = - isCBarSimpleSwing && - IsBullish(iDir); - bool isCBarBearishSimpleSwing = - isCBarSimpleSwing && - IsBearish(iDir); - - // - // PBar ... - bool isPBarSimpleSwing = - barAnalyser.IsSimpleSwing( - pBar, - iDir // - ); - bool isPBarBullishSimpleSwing = - isPBarSimpleSwing && - IsBullish(iDir); - bool isPBarBearishSimpleSwing = - isPBarSimpleSwing && - IsBearish(iDir); - - // - // P2Bar ... - bool isP2BarSimpleSwing = - barAnalyser.IsSimpleSwing( - p2Bar, - iDir // - ); - bool isP2BarBullishSimpleSwing = - isP2BarSimpleSwing && - IsBullish(iDir); - bool isP2BarBearishSimpleSwing = - isP2BarSimpleSwing && - IsBearish(iDir); - - // - // P3Bar ... - bool isP3BarSimpleSwing = - barAnalyser.IsSimpleSwing( - p3Bar, - iDir // - ); - bool isP3BarBullishSimpleSwing = - isP3BarSimpleSwing && - IsBullish(iDir); - bool isP3BarBearishSimpleSwing = - isP3BarSimpleSwing && - IsBearish(iDir); - - // - // P4Bar ... - bool isP4BarSimpleSwing = - barAnalyser.IsSimpleSwing( - p4Bar, - iDir // - ); - bool isP4BarBullishSimpleSwing = - isP4BarSimpleSwing && - IsBullish(iDir); - bool isP4BarBearishSimpleSwing = - isP4BarSimpleSwing && - IsBearish(iDir); - - // - // Summarise Validation ... - - // - bool isBullishSwimpleSwing = - isBullish && - (isCBarBullishSimpleSwing || - isPBarBullishSimpleSwing || - isP2BarBullishSimpleSwing || - isP3BarBullishSimpleSwing || - isP4BarBullishSimpleSwing); - - // - bool isBearishSwimpleSwing = - isBearish && - (isCBarBearishSimpleSwing || - isPBarBearishSimpleSwing || - isP2BarBearishSimpleSwing || - isP3BarBearishSimpleSwing || - isP4BarBearishSimpleSwing); - - // - result = isBullishSwimpleSwing || - isBearishSwimpleSwing; - if (!result) - { - // - p3Bar.Clean(); - p4Bar.Clean(); - iBlock.Clean(); - - // - return result; - } - } - - // - // Validating Using Bar Pressure ... - if (triggerBlockBarPressureValidation) - { - // - // Check pBar is Momentum Bar ... - // and Breakd Block Side ... - - // - bool isCBarMomentum = barAnalyser.IsMomentum( - pBar, - iDir // - ); - bool isCBarBullishMomentum = - isCBarMomentum && - IsBullish(iDir); - bool isCBarBearishMomentum = - isCBarMomentum && - IsBearish(iDir); - - // - bool isPBarMomentum = barAnalyser.IsMomentum( - pBar, - iDir // - ); - bool isPBarBullishMomentum = - isPBarMomentum && - IsBullish(iDir); - bool isPBarBearishMomentum = - isPBarMomentum && - IsBearish(iDir); - - // - bool isBullishBreakedOut = - isBullish && - forBullish && - pBar.IsBullish() && - (isCBarBullishMomentum || - isPBarBullishMomentum) && - pBar.GetUp() > iBlock.upper && - pBar.GetDown() < iBlock.upper; - - // - bool isBearishBreakedOut = - isBearish && - forBearish && - pBar.IsBearish() && - (isCBarBearishMomentum || - isPBarBearishMomentum) && - pBar.GetUp() > iBlock.lower && - pBar.GetDown() < iBlock.lower; - - // - result = - isBullishBreakedOut || - isBearishBreakedOut; - if (!result) - { - // - p3Bar.Clean(); - p4Bar.Clean(); - iBlock.Clean(); - - // - return result; - } - } - - // - // Extract to and from Info ... - - // - int toIDX = iBlock.ToIndex(); - int fromIDX = iBlock.FromIndex(); - - // - XOHCL toBar; - XOHCL fromBar; - - // - result = iBlock.ToBar(toBar); - result = result && - iBlock.FromBar(fromBar); - if (!result) - { - // - toBar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - iBlock.Clean(); - fromBar.Clean(); - - // - return result; - } - - // - // Validating Using HH and LL ... - if (triggerBlockSwingLength > 0) - { - // - double toLL = toBar.FindLowest(triggerBlockSwingLength, MODE_LOW); - double toHH = toBar.FindHighest(triggerBlockSwingLength, MODE_HIGH); - - // - double fromLL = fromBar.FindLowest(triggerBlockSwingLength, MODE_LOW); - double fromHH = fromBar.FindHighest(triggerBlockSwingLength, MODE_HIGH); - - // - double selectedLL = fromLL; // MathMin(toLL, fromLL); - double selectedHH = fromHH; // MathMax(toHH, fromHH); - - // - bool isBullishSwingPassed = - isBullish && - forBullish && - selectedLL >= iBlock.lower; - - // - bool isBearishSwingPassed = - isBearish && - forBearish && - selectedHH <= iBlock.upper; - - // - result = isBullishSwingPassed || - isBearishSwingPassed; - if (!result) - { - // - toBar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - iBlock.Clean(); - fromBar.Clean(); - - // - return result; - } - } - - // - // Apply Filters ... - bool hasFilter = - filterTriggerBlocksBySar; - if (hasFilter) - { - // - // Sar Filtering ... - if (filterTriggerBlocksBySar) - { - // - // Reading Conditions ... - - // - 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]; - - // - // Preparing Constom Conditions ... - - // - bool isZSarBullish = zSar < zBar.low; - bool isCSarBullish = cSar < cBar.low; - bool isPSarBullish = pSar < pBar.low; - bool isP2SarBullish = p2Sar < p2Bar.low; - bool isP3SarBullish = p3Sar < p3Bar.low; - - // - bool isZSarBearish = zSar > zBar.high; - bool isCSarBearish = cSar > cBar.high; - bool isPSarBearish = pSar > pBar.high; - bool isP2SarBearish = p2Sar > p2Bar.high; - bool isP3SarBearish = p3Sar > p3Bar.high; - - // - bool isCSarSwitchedToBullish = - isCSarBullish && - !isPSarBullish; - bool isPSarSwitchedToBullish = - isPSarBullish && - !isP2SarBullish; - bool isP2SarSwitchedToBullish = - isP2SarBullish && - !isP3SarBullish; - - // - bool isCSarSwitchedToBearish = - isCSarBearish && - !isPSarBearish; - bool isPSarSwitchedToBearish = - isPSarBearish && - !isP2SarBearish; - bool isP2SarSwitchedToBearish = - isP2SarBearish && - !isP3SarBearish; - - // - // Summarize Custom Conditions ... - - // - // Bullish ... - - // - bool isCSarBullishPassed = - isZSarBullish && - isCSarSwitchedToBullish; - - // - bool isPSarBullishPassed = - isZSarBullish && - isCSarBullish && - isPSarSwitchedToBullish; - - // - bool isP2SarBullishPassed = - isZSarBullish && - isCSarBullish && - isPSarBullish && - isP2SarSwitchedToBullish; - - // - // Bearish ... - - // - bool isCSarBearishPassed = - isZSarBearish && - isCSarSwitchedToBearish; - - // - bool isPSarBearishPassed = - isZSarBearish && - isCSarBearish && - isPSarSwitchedToBearish; - - // - bool isP2SarBearishPassed = - isZSarBearish && - isCSarBearish && - isPSarBearish && - isP2SarSwitchedToBearish; - - // - // Summarize Conditions ... - - // - bool isBullishFiltered = - isBullish && - forBullish && - (isCSarBullishPassed || - isPSarBullishPassed || - isP2SarBullishPassed); - - // - bool isBearishFiltered = - isBearish && - forBearish && - (isCSarBearishPassed || - isPSarBearishPassed || - isP2SarBearishPassed); - - // - result = isBullishFiltered || - isBearishFiltered; - if (!result) - { - // - toBar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - iBlock.Clean(); - fromBar.Clean(); - - // - return result; - } - } - } - - // - // Summarize ... - - // - isBullish = - isBullish && - forBullish && - iBlock.IsValid(); - - // - isBearish = - isBearish && - forBearish && - iBlock.IsValid(); - - // - result = isBullish || - isBearish; - if (!result) - { - iBlock.Clean(); - } - - // - // Storing Pivot ... - - // - if (isBullish) - { - // - result = AddBox( - iBlock, - triggerBlockBullishPivots // - ); - } - - // - if (isBearish) - { - // - result = AddBox( - iBlock, - triggerBlockBearishPivots // - ); - } - - // - // Cleanup Resource ... - - // - toBar.Clean(); - p3Bar.Clean(); - p4Bar.Clean(); - iBlock.Clean(); - fromBar.Clean(); - - // - return result; - } - - // - void ValidateTriggerBlockPivots( - XBoxZone &unavailables[], - int barIndex = 0 // - ) - { - // - // Since Trigger Blocks Doesnt Use Multiple Times, - // there is not any Validation Required for them ... - bool has = false; - - // - // bool applyLifetimeValidating = maxAllowedTriggerBlockLifetime > 0; - - // - // Bullish ... - has = HasTriggerBlockBullishPivots(); - if (has) - { - } - - // - // Bearish ... - has = HasTriggerBlockBearishPivots(); - if (has) - { - } - } - - // - // Bullish ... - - // - XBoxZone triggerBlockBullishPivots[]; - bool detectTriggerBlockBullishPivots; - bool newTriggerBlockBullishPivotDetected; - - // - bool HasTriggerBlockBullishPivots() - { - return HasChild(triggerBlockBullishPivots); - } - - // - int CountTriggerBlockBullishPivots() - { - return ArraySize(triggerBlockBullishPivots); - } - - // - // Bearish ... - - // - bool detectTriggerBlockBearishPivots; - XBoxZone triggerBlockBearishPivots[]; - bool newTriggerBlockBearishPivotDetected; - - // - bool HasTriggerBlockBearishPivots() - { - return HasChild(triggerBlockBearishPivots); - } - - // - int CountTriggerBlockBearishPivots() - { - return ArraySize(triggerBlockBearishPivots); - } - // // Protected ... protected: @@ -4937,10 +4171,6 @@ class XCXCAEAPOIDetector : public XCBase // Clean(trendBullishPivots); Clean(trendBearishPivots); - - // - Clean(triggerBlockBullishPivots); - Clean(triggerBlockBearishPivots); } // @@ -5051,25 +4281,6 @@ class XCXCAEAPOIDetector : public XCBase { ApplySortOnBoxes(trendBearishPivots); } - - // - // TRIGGER Block ... - - // - // Bullish ... - has = HasTriggerBlockBullishPivots(); - if (has) - { - ApplySortOnBoxes(triggerBlockBullishPivots); - } - - // - // Bearish ... - has = HasTriggerBlockBearishPivots(); - if (has) - { - ApplySortOnBoxes(triggerBlockBearishPivots); - } } // diff --git a/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 b/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 index aadcb344..1031fc77 100644 --- a/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 +++ b/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 @@ -94,8 +94,6 @@ class XCXCAEAPOIDrawer : public XCBase bool drawFVGBearishPivots; bool drawTrendBullishPivots; bool drawTrendBearishPivots; - bool drawTriggerBlockBullishPivots; - bool drawTriggerBlockBearishPivots; // // Styling ... @@ -124,10 +122,6 @@ class XCXCAEAPOIDrawer : public XCBase XCAPivotStyle trendBullishPivotStyle; XCAPivotStyle trendBearishPivotStyle; - // - XCAPivotStyle triggerBlockBullishPivotStyle; - XCAPivotStyle triggerBlockBearishPivotStyle; - // // Constructors ... XCXCAEAPOIDrawer( @@ -175,8 +169,6 @@ class XCXCAEAPOIDrawer : public XCBase drawFVGBearishPivots = false; drawTrendBullishPivots = false; drawTrendBearishPivots = false; - drawTriggerBlockBullishPivots = false; - drawTriggerBlockBearishPivots = false; // // Styling ... @@ -220,11 +212,6 @@ class XCXCAEAPOIDrawer : public XCBase // TREND ... trendBullishPivotStyle = defaultBullishStyle; trendBearishPivotStyle = defaultBearishStyle; - - // - // TRIGGER ... - triggerBlockBullishPivotStyle = defaultBullishStyle; - triggerBlockBearishPivotStyle = defaultBearishStyle; } // @@ -254,11 +241,6 @@ class XCXCAEAPOIDrawer : public XCBase // TREND ... DrawTrendBullishPivots(to); DrawTrendBearishPivots(to); - - // - // TRIGGER ... - DrawTriggerBullishPivots(to); - DrawTriggerBearishPivots(to); } // @@ -403,24 +385,6 @@ class XCXCAEAPOIDrawer : public XCBase to // ); break; - - // - case XCA_TRIGGER_BULL: - // - DrawTriggerBlockBullishPivot( - box, - to // - ); - break; - - // - case XCA_TRIGGER_BEAR: - // - DrawTriggerBlockBearishPivot( - box, - to // - ); - break; } } // @@ -926,76 +890,6 @@ class XCXCAEAPOIDrawer : public XCBase } } - // - void DrawTriggerBullishPivots(datetime to = NULL) - { - // - bool has = drawTriggerBlockBullishPivots; - if (!has) - { - return; - } - - // - has = detector.HasTriggerBlockBullishPivots(); - if (!has) - { - return; - } - - // - int count = detector.CountTriggerBlockBullishPivots(); - for (int i = 0; i < count; i++) - { - // - XBoxZone iBox = detector.triggerBlockBullishPivots[i]; - - // - DrawTriggerBlockBullishPivot( - iBox, - to // - ); - - // - iBox.Clean(); - } - } - - // - void DrawTriggerBearishPivots(datetime to = NULL) - { - // - bool has = drawTriggerBlockBearishPivots; - if (!has) - { - return; - } - - // - has = detector.HasTriggerBlockBearishPivots(); - if (!has) - { - return; - } - - // - int count = detector.CountTriggerBlockBearishPivots(); - for (int i = 0; i < count; i++) - { - // - XBoxZone iBox = detector.triggerBlockBearishPivots[i]; - - // - DrawTriggerBlockBearishPivot( - iBox, - to // - ); - - // - iBox.Clean(); - } - } - // // One Item Drawers ... @@ -1529,116 +1423,6 @@ class XCXCAEAPOIDrawer : public XCBase ZeroMemory(iObj); } - // - void DrawTriggerBlockBullishPivot( - XBoxZone &item, - datetime to = NULL // - ) - { - // - bool has = drawTriggerBlockBullishPivots; - if (!has) - { - return; - } - - // - has = item.IsValid() && - item.type == GetBoxType(XCA_TRIGGER_BULL) && - item.dir == GetDirection(XCA_TRIGGER_BULL); - if (!has) - { - return; - } - - // - // Since Trigger Blocks only Used Once ... - to = NULL; - bool canUpdateTo = IsValid(to); - if (canUpdateTo) - { - item.to = to; - } - - // - XCBoxObject *iObj; - has = drawer.DrawBox( - item, - iObj // - ); - if (has) - { - // - // Style Object ... - ApplyPivotStyle( - iObj, - triggerBlockBullishPivotStyle // - ); - - // - // Store Object ... - mTriggerBlockBullishPivotObjects.Add(iObj); - } - - // - ZeroMemory(iObj); - } - - // - void DrawTriggerBlockBearishPivot( - XBoxZone &item, - datetime to = NULL // - ) - { - // - bool has = drawTriggerBlockBearishPivots; - if (!has) - { - return; - } - - // - has = item.IsValid() && - item.type == GetBoxType(XCA_TRIGGER_BEAR) && - item.dir == GetDirection(XCA_TRIGGER_BEAR); - if (!has) - { - return; - } - - // - // Since Trigger Blocks only Used Once ... - to = NULL; - bool canUpdateTo = IsValid(to); - if (canUpdateTo) - { - item.to = to; - } - - // - XCBoxObject *iObj; - has = drawer.DrawBox( - item, - iObj // - ); - if (has) - { - // - // Style Object ... - ApplyPivotStyle( - iObj, - triggerBlockBearishPivotStyle // - ); - - // - // Store Object ... - mTriggerBlockBearishPivotObjects.Add(iObj); - } - - // - ZeroMemory(iObj); - } - // // Protected ... protected: diff --git a/XCAEA/Libraries/xcaea.signaller.lib.mq5 b/XCAEA/Libraries/xcaea.signaller.lib.mq5 index ce57c5de..58480f6b 100644 --- a/XCAEA/Libraries/xcaea.signaller.lib.mq5 +++ b/XCAEA/Libraries/xcaea.signaller.lib.mq5 @@ -1055,7 +1055,7 @@ bool DetectDecisionZone( // // Custom Senarios ... -, + // bool isCond1Bullish = // diff --git a/XCAEA/Signals/xcaea.signaller.class.mq5 b/XCAEA/Signals/xcaea.signaller.class.mq5 index 040de941..58db14ec 100644 --- a/XCAEA/Signals/xcaea.signaller.class.mq5 +++ b/XCAEA/Signals/xcaea.signaller.class.mq5 @@ -1030,20 +1030,6 @@ class XCXCAEASignaller : XCBase detector.detectTrendBullishPivots = false; detector.detectTrendBearishPivots = false; - // - // TRIGGER Blocks ... - - // - detector.triggerBlockSwingLength = 7; - detector.triggerBlockMaxAllowedRange = 0; - detector.filterTriggerBlocksBySar = true; - detector.triggerBlockBarHasProperSwing = true; - detector.triggerBlockBarPressureValidation = true; - - // - detector.detectTriggerBlockBullishPivots = true; - detector.detectTriggerBlockBearishPivots = true; - // // DRAWER ... @@ -1066,8 +1052,6 @@ class XCXCAEASignaller : XCBase drawer.drawFVGBearishPivots = false; drawer.drawTrendBullishPivots = false; drawer.drawTrendBearishPivots = false; - drawer.drawTriggerBlockBullishPivots = false; - drawer.drawTriggerBlockBearishPivots = false; // // Configure Styles ... @@ -1176,27 +1160,6 @@ class XCXCAEASignaller : XCBase trendBearishStyle.style = STYLE_DOT; drawer.trendBearishPivotStyle = trendBearishStyle; trendBearishStyle.Clean(); - - // - // TRIGGER ... - - // - // Bullish ... - XCAPivotStyle triggerBlockBullishStyle; - triggerBlockBullishStyle.width = 2; - triggerBlockBullishStyle.clr = clrLime; - triggerBlockBullishStyle.style = STYLE_DOT; - drawer.triggerBlockBullishPivotStyle = triggerBlockBullishStyle; - triggerBlockBullishStyle.Clean(); - - // - // Bearish ... - XCAPivotStyle triggerBlockBearishStyle; - triggerBlockBearishStyle.width = 2; - triggerBlockBearishStyle.clr = clrRed; - triggerBlockBearishStyle.style = STYLE_DOT; - drawer.triggerBlockBearishPivotStyle = triggerBlockBearishStyle; - triggerBlockBearishStyle.Clean(); } //