/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class // ------------------------------------------------- // Name: XCXCAYBEAPOIDetector ... // Description: Class for XCATBEA 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 XCATBEA POI Detector" #property strict // // Imports ... #include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" #include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5" #include "../../Libraries/x-saherelm.x-poi.extensions.lib.mq5" // // Definitions ... // enum ENUM_XCATB_PIVOTS { XCATB_NONE, // None XCATB_PEAK, // Peak XCATB_VALE, // Vale XCATB_BULLISH_MT, // MTBull XCATB_BEARISH_MT, // MTBear XCATB_BULLISH_OB, // OBBull XCATB_BEARISH_OB, // OBBear }; // bool IsValid(ENUM_XCATB_PIVOTS value) { // bool result = false; // result = value != XCATB_NONE; // return result; } bool IsSpecifiedValid(ENUM_XCATB_PIVOTS value) { return IsValid(value); } // string ToString(ENUM_XCATB_PIVOTS value) { // string result = NULL; // result = EnumToString(value); // return result; } string ToXString(ENUM_XCATB_PIVOTS value) { return ToString(value); } // ENUM_X_DIRECTION GetDirection(ENUM_XCATB_PIVOTS value) { // ENUM_X_DIRECTION result = X_DIRECTION_NONE; // switch (value) { // case XCATB_VALE: case XCATB_BULLISH_MT: case XCATB_BULLISH_OB: result = X_DIRECTION_BULLISH; break; // case XCATB_PEAK: case XCATB_BEARISH_MT: case XCATB_BEARISH_OB: result = X_DIRECTION_BEARISH; break; } // return result; } // string GetBoxType(ENUM_XCATB_PIVOTS value) { // string result = NULL; // switch (value) { // case XCATB_VALE: case XCATB_PEAK: result = ToString(value); break; // case XCATB_BULLISH_MT: case XCATB_BEARISH_MT: result = "XMT"; break; // case XCATB_BULLISH_OB: case XCATB_BEARISH_OB: result = "XOB"; break; } // return result; } // ENUM_XCATB_PIVOTS GetPivotType(XBoxZone &value) { // ENUM_XCATB_PIVOTS result = XCATB_NONE; // bool has = value.IsValid(); if (!has) { return result; } // bool isPeak = value.type == GetBoxType(XCATB_PEAK) && value.dir == GetDirection(XCATB_PEAK); bool isVale = value.type == GetBoxType(XCATB_VALE) && value.dir == GetDirection(XCATB_VALE); bool isBullishMT = value.type == GetBoxType(XCATB_BULLISH_MT) && value.dir == GetDirection(XCATB_BULLISH_MT); bool isBearishMT = value.type == GetBoxType(XCATB_BEARISH_MT) && value.dir == GetDirection(XCATB_BEARISH_MT); bool isBullishOB = value.type == GetBoxType(XCATB_BULLISH_OB) && value.dir == GetDirection(XCATB_BULLISH_OB); bool isBearishOB = value.type == GetBoxType(XCATB_BEARISH_OB) && value.dir == GetDirection(XCATB_BEARISH_OB); // if (isPeak) { result = XCATB_PEAK; } else if (isVale) { result = XCATB_VALE; } else if (isBullishMT) { result = XCATB_BULLISH_MT; } else if (isBearishMT) { result = XCATB_BEARISH_MT; } else if (isBullishOB) { result = XCATB_BULLISH_OB; } else if (isBearishOB) { result = XCATB_BEARISH_OB; } // return result; } // struct XCATBPivot { // // Props ... datetime to; double value; string symbol; datetime from; double reserve; ENUM_XCATB_PIVOTS type; ENUM_TIMEFRAMES period; // double values[]; // // Constructor ... XCATBPivot() { Clean(); } // // Tools ... /** * Cleanup ... */ void Clean() { // value = 0; to = NULL; reserve = 0; from = NULL; symbol = NULL; period = NULL; type = XCATB_NONE; // SpecifiedClean(values); // ZeroMemory(this); } /** * Validate ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = from < to && value != 0 && IsSpecifiedValid(to) && IsSpecifiedValid(from) && IsSpecifiedValid(type) && IsSpecifiedValid(symbol) && IsSpecifiedValid(period); // return result; } /** * Check a Model is Same as this or not ... * * @param pivot: XCATBPivot ... * * @return ( bool ) */ bool IsSameAs(XCATBPivot &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 (!IsSpecifiedValid(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 (!IsSpecifiedValid(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 (!IsSpecifiedValid(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 XCXCATBEAPOIDetector : public XCBase { // // Public ... public: // // Props ... int maxAllowedPivots; // Max Allowed Holding Pibots ... int pivotVerifications; // Pivots Verifications ... int pivotDetectionLoopbac; // Pivots Detection Loopback ... // // Breaked Pivots ... XBoxZone invalidPivots[]; // // Constructors ... XCXCATBEAPOIDetector( XCX121XCatbHelper *_helper // ) { // helper = _helper; barAnalyser = new XCBarAnalyser(); // Default(); } // // De Constructors ... ~XCXCATBEAPOIDetector() { // CleanPivots(); // ZeroMemory(helper); // delete barAnalyser; ZeroMemory(barAnalyser); } // // Properties ... // // Tools ... // virtual void Default() { // // COMMON ... // maxAllowedPivots = 50; pivotVerifications = 5; pivotDetectionLoopbac = 100; // // PV ... // maxAllowedPVLifetime = 0; selectRejectedPVPivots = false; selectEngulfedPVPivots = false; // detectPeakPivots = false; detectValePivots = false; // detectMTBullishPivots = false; detectMTBearishPivots = false; // detectOBBullishPivots = false; detectOBBearishPivots = false; } // void Detect( int barIndex = 0 // ) { // barIndex = NormalizeInt(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; // newPeakPivotDetected = false; newValePivotDetected = false; newMTBullishPivotDetected = false; newMTBearishPivotDetected = false; newOBBullishPivotDetected = false; newOBBearishPivotDetected = false; // int index = barIndex; int start = index; int end = index + loopback; while (start < end) { // // Retrieve Conditions ... X121XCatbConditions 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; } // // Checking Pivots ... // // 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 // ); } // // MT ... // // Bullish ... if (detectMTBullishPivots) { // newMTBullishPivotDetected = DetectMTPivot( barIndex, X_DIRECTION_BULLISH, zBar, cBar, pBar, p2Bar, conditions // ); } // // Bearish ... if (detectMTBearishPivots) { // newMTBearishPivotDetected = DetectMTPivot( 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 // ); } // // Others ... // start++; // zBar.Clean(); cBar.Clean(); pBar.Clean(); p2Bar.Clean(); conditions.Clean(); } // SortPivots(); } // void Validate( XBoxZone &unavailables[], int barIndex = 0 // ) { // // Implement Validation Senarios ... // // PV ... ValidatePeakValePivots( unavailables, barIndex // ); // // MT ... ValidateMTPivots( unavailables, barIndex // ); // // OB ... ValidateOBPivots( unavailables, barIndex // ); // SortPivots(); } // void CleanPivots() { // Clean(invalidPivots); // peakPivot.Clean(); valePivot.Clean(); // Clean(peakPivots); Clean(valePivots); // Clean(mtBullishPivots); Clean(mtBearishPivots); // Clean(obBullishPivots); Clean(obBearishPivots); } // // Pivots ... // // INVALID Pivots ... // bool HasInvalidPivots() { return HasChild(invalidPivots); } // int CountInvalidPivots() { return ArraySize(invalidPivots); } // // PV ... // int maxAllowedPVLifetime; // Max Allowed PV Life ... bool selectRejectedPVPivots; // Select Rejected PV Pivots ... bool selectEngulfedPVPivots; // Select Engulfed PV Pivots ... // bool DetectPeakAndValePivot( int barIndex, ENUM_X_DIRECTION forDir, XOHCL &zBar, XOHCL &cBar, XOHCL &pBar, XOHCL &p2Bar, X121XCatbConditions &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]; // // Detecting Bar Conditions ... // ENUM_X_DIRECTION cBarDir; // // Rejected ... bool isCBarRejected = 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 = 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 = barAnalyser .IsEngulfed( cBar, cBarDir // ); bool isCBarBullishEngulfed = forBullish && isCBarEngulfed && IsBullish(cBarDir); bool isCBarBearishEngulfed = forBearish && isCBarEngulfed && IsBearish(cBarDir); // bool isPBarEngulfed = 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; // bool isPeakSwitchedToSameLast = isPeakSameLast && !isPeakSameLastPrev; bool isPeakFinishedFromSameLast = !isPeakSameLast && isPeakSameLastPrev; // // VALE ... // bool isValeSameLast = cVale == pVale; bool isValeSameLastPrev = pVale == p2Vale; // 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 = XCATB_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 = XCATB_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 ... // XCATBPivot peakPivot; bool detectPeakPivots; XBoxZone peakPivots[]; bool newPeakPivotDetected; // bool HasPeakPivots() { return HasChild(peakPivots); } // int CountPeakPivots() { return ArraySize(peakPivots); } // int FillPeakPivots(XBoxZone &pivots[]) { // int result = 0; // Clean(pivots); // if (!HasPeakPivots()) { return result; } // int count = CountPeakPivots(); for (int i = 0; i < count; i++) { // XBoxZone iPivot = peakPivots[i]; // AddRef( iPivot, pivots // ); // iPivot.Clean(); } // result = ArraySize(pivots); // return result; } // // VALE ... // XCATBPivot valePivot; bool detectValePivots; XBoxZone valePivots[]; bool newValePivotDetected; // bool HasValePivots() { return HasChild(valePivots); } // int CountValePivots() { return ArraySize(valePivots); } // int FillValePivots(XBoxZone &pivots[]) { // int result = 0; // Clean(pivots); // if (!HasValePivots()) { return result; } // int count = CountValePivots(); for (int i = 0; i < count; i++) { // XBoxZone iPivot = valePivots[i]; // AddRef( iPivot, pivots // ); // iPivot.Clean(); } // result = ArraySize(pivots); // return result; } // // MITIGATIONBLOCK ... // int maxAllowedMTLifetime; // Max Allowed MT Life ... // bool DetectMTPivot( int barIndex, ENUM_X_DIRECTION forDir, XOHCL &zBar, XOHCL &cBar, XOHCL &pBar, XOHCL &p2Bar, X121XCatbConditions &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 ? detectMTBullishPivots : detectMTBearishPivots; 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); // // Detecting Bar Conditions ... // ENUM_X_DIRECTION cBarDir; // // Rejected ... bool isCBarRejected = barAnalyser .IsRejected( cBar, cBarDir, false, // Force Type ... true // Force Fibo Pressure ... ); // bool isCBarBullishRejected = forBullish && isCBarRejected && IsBullish(cBarDir); bool isCBarBearishRejected = forBearish && isCBarRejected && IsBearish(cBarDir); // // Prepare Conditinal Conditions ... // // Summarizing Conditions ... // result = false; // bool hasEndCondition = // forBullish ? isCBarBullishRejected : isCBarBearishRejected // ; // // End up Pivot and Store it ... if (hasEndCondition) { // XBoxZone iPivot; iPivot.to = zBar.time; iPivot.from = cBar.time; iPivot.symbol = cBar.symbol; iPivot.period = cBar.period; // // Bullish ... if (forBullish) { // iPivot.lower = cBar.low; iPivot.upper = cBar.GetDown(); iPivot.dir = X_DIRECTION_BULLISH; iPivot.type = GetBoxType(XCATB_BULLISH_MT); // result = iPivot.IsValid(); if (result) { // newMTBullishPivotDetected = AddBox( iPivot, mtBullishPivots // ); } } // // Bearish ... if (forBearish) { // iPivot.upper = cBar.high; iPivot.lower = cBar.GetUp(); iPivot.dir = X_DIRECTION_BEARISH; iPivot.type = GetBoxType(XCATB_BEARISH_MT); // result = iPivot.IsValid(); if (result) { // newMTBearishPivotDetected = AddBox( iPivot, mtBearishPivots // ); } } } // return result; } // void ValidateMTPivots( XBoxZone &unavailables[], int barIndex = 0 // ) { // bool has = false; // bool applyLifetimeValidating = maxAllowedMTLifetime > 0; // // Bullish ... has = HasMTBullishPivots(); if (has) { // ApplyValidationOnBoxes( mtBullishPivots, unavailables, barIndex // ); // if (applyLifetimeValidating) { // ApplyLifeTimeValidationOnBoxes( mtBullishPivots, maxAllowedMTLifetime, barIndex // ); } } // // Bearish ... has = HasMTBearishPivots(); if (has) { // ApplyValidationOnBoxes( mtBearishPivots, unavailables, barIndex // ); // if (applyLifetimeValidating) { // ApplyLifeTimeValidationOnBoxes( mtBearishPivots, maxAllowedMTLifetime, barIndex // ); } } } // // Bullish ... XBoxZone mtBullishPivots[]; bool detectMTBullishPivots; bool newMTBullishPivotDetected; // bool HasMTBullishPivots() { return HasChild(mtBullishPivots); } // int CountMTBullishPivots() { return ArraySize(mtBullishPivots); } // int FillMTBullishPivots(XBoxZone &pivots[]) { // int result = 0; // Clean(pivots); // if (!HasMTBullishPivots()) { return result; } // int count = CountMTBullishPivots(); for (int i = 0; i < count; i++) { // XBoxZone iPivot = mtBullishPivots[i]; // AddRef( iPivot, pivots // ); // iPivot.Clean(); } // result = ArraySize(pivots); // return result; } // // Bearish ... XBoxZone mtBearishPivots[]; bool detectMTBearishPivots; bool newMTBearishPivotDetected; // bool HasMTBearishPivots() { return HasChild(mtBearishPivots); } // int CountMTBearishPivots() { return ArraySize(mtBearishPivots); } // int FillMTBearishPivots(XBoxZone &pivots[]) { // int result = 0; // Clean(pivots); // if (!HasMTBearishPivots()) { return result; } // int count = CountMTBearishPivots(); for (int i = 0; i < count; i++) { // XBoxZone iPivot = mtBearishPivots[i]; // AddRef( iPivot, pivots // ); // iPivot.Clean(); } // result = ArraySize(pivots); // return result; } // // ORDERBLOCK ... // int maxAllowedOBLifetime; // Max Allowed MT Life ... // bool DetectOBPivot( int barIndex, ENUM_X_DIRECTION forDir, XOHCL &zBar, XOHCL &cBar, XOHCL &pBar, XOHCL &p2Bar, X121XCatbConditions &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; } // // 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); // XBoxZone iPivot; // // Detecting Bar Conditions ... // // // OB ... bool isOB = barAnalyser .IsOB( cBar, iPivot, false, false // ); // bool isBullishOB = isOB && iPivot.IsBullish(); bool isBearishOB = isOB && iPivot.IsBearish(); // // Prepare Conditinal Conditions ... // // Summarizing Conditions ... // result = false; // bool hasEndCondition = // forBullish ? isBullishOB : isBearishOB // ; // // End up Pivot and Store it ... if (hasEndCondition) { // // Bullish ... if (forBullish) { // iPivot.type = GetBoxType(XCATB_BULLISH_OB); // result = iPivot.IsValid(); if (result) { // newOBBullishPivotDetected = AddBox( iPivot, obBullishPivots // ); } } // // Bearish ... if (forBearish) { // iPivot.type = GetBoxType(XCATB_BEARISH_OB); // result = iPivot.IsValid(); if (result) { // newOBBearishPivotDetected = AddBox( iPivot, obBearishPivots // ); } } } // 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 // ); } } } // // Bullish ... XBoxZone obBullishPivots[]; bool detectOBBullishPivots; bool newOBBullishPivotDetected; // bool HasOBBullishPivots() { return HasChild(obBullishPivots); } // int CountOBBullishPivots() { return ArraySize(obBullishPivots); } // int FillOBBullishPivots(XBoxZone &pivots[]) { // int result = 0; // Clean(pivots); // if (!HasOBBullishPivots()) { return result; } // int count = CountOBBullishPivots(); for (int i = 0; i < count; i++) { // XBoxZone iPivot = obBullishPivots[i]; // AddRef( iPivot, pivots // ); // iPivot.Clean(); } // result = ArraySize(pivots); // return result; } // // Bearish ... XBoxZone obBearishPivots[]; bool detectOBBearishPivots; bool newOBBearishPivotDetected; // bool HasOBBearishPivots() { return HasChild(obBearishPivots); } // int CountOBBearishPivots() { return ArraySize(obBearishPivots); } // int FillOBBearishPivots(XBoxZone &pivots[]) { // int result = 0; // Clean(pivots); // if (!HasOBBearishPivots()) { return result; } // int count = CountOBBearishPivots(); for (int i = 0; i < count; i++) { // XBoxZone iPivot = obBearishPivots[i]; // AddRef( iPivot, pivots // ); // iPivot.Clean(); } // result = ArraySize(pivots); // return result; } // // Protected ... protected: // // Props ... // bool AddBox( XBoxZone &box, XBoxZone &boxes[] // ) { // bool result = false; // result = box.IsValid(); if (!result) { return result; } // int idx = -1; bool isExists = FindIndex( 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 = FindIndex( 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 = FindIndex( idx, box, invalidPivots // ); if (!isExists) { // AddRef( box, invalidPivots // ); } } // // Cleanup Resource ... // cBar.Clean(); pBar.Clean(); p2Bar.Clean(); // return result; } // void SortPivots() { // bool has = false; // // Invalid Pivots ... has = HasInvalidPivots(); if (has) { SortBoxes(invalidPivots); } // // PV ... // // PEAK ... has = HasPeakPivots(); if (has) { SortBoxes(peakPivots); } // // VALE ... has = HasValePivots(); if (has) { SortBoxes(valePivots); } // // MT Bullish ... has = HasMTBullishPivots(); if (has) { SortBoxes(mtBullishPivots); } // // MT Bearish ... has = HasMTBearishPivots(); if (has) { SortBoxes(mtBearishPivots); } // // OB Bullish ... has = HasOBBullishPivots(); if (has) { SortBoxes(obBullishPivots); } // // OB Bearish ... has = HasOBBearishPivots(); if (has) { SortBoxes(obBearishPivots); } } // 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 = FindIndex( idx, iBox, invalidPivots // ); if (!isExists) { // AddRef( iBox, invalidPivots // ); } } // iBox.Clean(); } // Clean(tmp); } // // Prrivate ... private: // // Props ... // XCX121XCatbHelper *helper; XCBarAnalyser *barAnalyser; // }; //