diff --git a/Helpers/x-saherelm.xfima.helper.mq5 b/Helpers/x-saherelm.xfima.helper.mq5 index f4269fda..bf4fb3f8 100644 --- a/Helpers/x-saherelm.xfima.helper.mq5 +++ b/Helpers/x-saherelm.xfima.helper.mq5 @@ -1525,10 +1525,24 @@ class XCXFIMAHelper : public XCBaseHelper return result; } + /** + * Retrieve Fast, Slow, MA Bond Upper/Lower, HK Bond Upper/Lower and PB Bond Upper/Lower Min/Max ... + * + * @param min: double, minimum value ... + * @param max: double, maximum value ... + * @param barIndex: int, Specified Bar Index ... + * + * @return ( bool ) + */ bool GetBoundaryValues( double &min, double &max, - int barIndex = 0 // + int barIndex = 0, + bool containsFastSlow = true, + bool containsMABond = true, + bool containsHKBound = true, + bool containsPBBond = true, + bool containsFiboLevels = false // ) { // @@ -1591,19 +1605,57 @@ class XCXFIMAHelper : public XCBaseHelper } // - double values[11] = { - fast, - slow, - fiboLower, - fiboUpper, - fiboMiddle, - maBondUpper, - maBondLower, - pbBondUpper, - pbBondLower, - hkBondUpper, - hkBondLower // - }; + double values[]; + + // + if (containsFastSlow) + { + // + Add(fast, values); + Add(slow, values); + } + + // + if (containsMABond) + { + // + Add(maBondUpper, values); + Add(maBondLower, values); + } + + // + if (containsHKBound) + { + // + Add(hkBondUpper, values); + Add(hkBondLower, values); + } + + // + if (containsPBBond) + { + // + Add(pbBondUpper, values); + Add(pbBondLower, values); + } + + // + if (containsFiboLevels) + { + // + Add(fiboLower, values); + Add(fiboUpper, values); + Add(fiboMiddle, values); + } + + // + result = HasChild(values); + if (!result) + { + return result; + } + + // min = GetMin(values); max = GetMax(values); @@ -3841,6 +3893,492 @@ class XCXFIMAHelper : public XCBaseHelper return result; } + /** + * Detect XFIMA Based POI Bars ... + * + * @param bars: XOHCL, reference collection to holds detected bars ... + * @param dirs: ENUM_X_DIRECTION, reference collection to holds detected bars Direction ... + * @param barIndex: int, Specified Bar Index ... + * @param forDir: ENUM_X_DIRECTION, specified which Direction of potential bars looking for ... + * @param requiredNumberOfBars: int, Specified how many bars looking for ... + * @param maxAllowedLoopbackLength: int, Specified Max Allowed Looping back trhough Bars for Detection ... + * @return ( int ) + */ + int DetectXFIMAPOIBars( + XOHCL &bars[], + ENUM_X_DIRECTION &dirs[], + int barIndex = 0, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + int requiredNumberOfBars = 300, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(bars); + XClean(dirs); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + requiredNumberOfBars = NormalizeInt(requiredNumberOfBars, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + XOHCL iBar; + int idx = barIndex - 1; + int start = barIndex; + bool isBullish = false; + bool isBearish = false; + double iMin = EMPTY_VALUE; + double iMax = EMPTY_VALUE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + int end = start + maxAllowedLoopbackLength; + while (ArraySize(bars) < requiredNumberOfBars || + idx < maxAllowedLoopbackLength) + { + // + idx++; + has = iBar.Init( + mSymbol, + mPeriod, + idx // + ); + if (!has) + { + continue; + } + + // + has = GetBoundaryValues( + iMin, + iMax, + idx // + ); + if (!has) + { + continue; + } + + // + isBullish = iBar.low < iMin; + isBearish = iBar.high > iMax; + has = + !HasDirection(forDir) + ? ((isBullish && !isBearish) || + (isBearish && !isBullish)) + : IsXBullish(forDir) + ? (isBullish && !isBearish) + : (isBearish && !isBullish); + if (has) + { + // + iDir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + AddRef( + iBar, + bars // + ); + + // + Add( + iDir, + dirs // + ); + } + } + + // + result = ArraySize(bars); + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; + } + + int DetectXFIMAReversalPOIBars( + XOHCL &bars[], + ENUM_X_DIRECTION &dirs[], + int barIndex = 0, + bool forceTouchBoundary = false, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + int requiredNumberOfBars = 300, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(bars); + XClean(dirs); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + requiredNumberOfBars = NormalizeInt(requiredNumberOfBars, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // Detect POI Bars ... + XOHCL decisionBars[]; + ENUM_X_DIRECTION decisionBarDirs[]; + int decisionBarsCount = DetectXFIMAPOIBars( + decisionBars, + decisionBarDirs, + barIndex, + forDir, + requiredNumberOfBars, + maxAllowedLoopbackLength // + ); + has = IsValidSize(decisionBarsCount); + if (!has) + { + // + XClean(decisionBars); + XClean(decisionBarDirs); + + // + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + double iMin = EMPTY_VALUE; + double iMax = EMPTY_VALUE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < decisionBarsCount; i++) + { + // + // Read Boundary Values ... + has = GetBoundaryValues(iMin, iMax, i); + if (!has) + { + continue; + } + + // + // Check Bar Decision Direction ... + isBullish = IsXBullish(decisionBarDirs[i]); + isBearish = IsXBearish(decisionBarDirs[i]); + + // + // Validate ... + + // + isBullish = + isBullish && + decisionBars[i].IsBullish(); + + // + isBearish = + isBearish && + decisionBars[i].IsBearish(); + + // + if (forceTouchBoundary) + { + // + isBullish = + isBullish && + (decisionBars[i].high > iMin || + decisionBars[i].GetUp() > iMin); + + // + isBearish = + isBearish && + (decisionBars[i].low < iMax || + decisionBars[i].GetDown() < iMax); + } + + // + has = (isBullish && !isBearish) || + (isBearish && !isBullish); + if (!has) + { + continue; + } + + // + iDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Validate For Dir ... + has = !HasDirection(forDir) + ? HasDirection(iDir) + : iDir == forDir; + if (has) + { + // + AddRef( + decisionBars[i], + bars // + ); + + // + Add( + iDir, + dirs // + ); + } + } + + // + result = ArraySize(bars); + + // + // Cleanup Resources ... + XClean(decisionBars); + XClean(decisionBarDirs); + + // + return result; + } + + int DetectXFIMAContinuationalPOIBars( + XOHCL &bars[], + ENUM_X_DIRECTION &dirs[], + int barIndex = 0, + bool forceTouchBoundary = false, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + int requiredNumberOfBars = 300, + int maxAllowedLoopbackLength = 1500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(bars); + XClean(dirs); + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + requiredNumberOfBars = NormalizeInt(requiredNumberOfBars, 5); + maxAllowedLoopbackLength = NormalizeInt(maxAllowedLoopbackLength, 50); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + // Detect POI Bars ... + XOHCL decisionBars[]; + ENUM_X_DIRECTION decisionBarDirs[]; + int decisionBarsCount = DetectXFIMAPOIBars( + decisionBars, + decisionBarDirs, + barIndex, + forDir, + requiredNumberOfBars, + maxAllowedLoopbackLength // + ); + has = IsValidSize(decisionBarsCount); + if (!has) + { + // + XClean(decisionBars); + XClean(decisionBarDirs); + + // + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + double iMin = EMPTY_VALUE; + double iMax = EMPTY_VALUE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + for (int i = 0; i < decisionBarsCount; i++) + { + // + // Read Boundary Values ... + has = GetBoundaryValues(iMin, iMax, i); + if (!has) + { + continue; + } + + // + // Validate ... + + // + isBullish = + decisionBars[i].high > iMax && + IsXBearish(decisionBarDirs[i]); + // && + // decisionBars[i].IsBullish(); + + // + isBearish = + decisionBars[i].low < iMin && + IsXBullish(decisionBarDirs[i]); + // && + // decisionBars[i].IsBearish(); + + // + // Check Direction ... + has = + isBullish || + !isBearish; + // has = (isBullish && !isBearish) || + // (isBearish && !isBullish); + if (!has) + { + continue; + } + + // + iDir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Validate For Dir ... + has = !HasDirection(forDir) + ? HasDirection(iDir) + : iDir == forDir; + if (has) + { + // + AddRef( + decisionBars[i], + bars // + ); + + // + Add( + iDir, + dirs // + ); + } + + // // + // isBullish = + // (decisionBars[i].low > iMax || + // decisionBars[i].GetDown() > iMax) && + // IsXBearish(decisionBarDirs[i]) && + // decisionBars[i].IsBullish(); + + // // + // isBearish = + // (decisionBars[i].high < iMin || + // decisionBars[i].GetUp() < iMin) && + // IsXBullish(decisionBarDirs[i]) && + // decisionBars[i].IsBearish(); + + // // + // if (forceTouchBoundary) + // { + // // + // isBullish = + // isBullish && + // decisionBars[i].low < iMax && + // decisionBars[i].GetUp() > iMax; + + // // + // isBearish = + // isBearish && + // decisionBars[i].high > iMin && + // decisionBars[i].GetDown() < iMin; + // } + + // // + // has = (isBullish && !isBearish) || + // (isBearish && !isBullish); + // if (!has) + // { + // continue; + // } + + // // + // iDir = + // isBullish + // ? X_DIRECTION_BULLISH + // : X_DIRECTION_BEARISH; + + // // + // // Validate For Dir ... + // has = !HasDirection(forDir) + // ? HasDirection(iDir) + // : iDir == forDir; + // if (has) + // { + // // + // AddRef( + // decisionBars[i], + // bars // + // ); + + // // + // Add( + // iDir, + // dirs // + // ); + // } + + // + AddRef( + decisionBars[i], + bars // + ); + + // + Add( + decisionBarDirs[i], + dirs // + ); + } + + // + result = ArraySize(bars); + + // + // Cleanup Resources ... + XClean(decisionBars); + XClean(decisionBarDirs); + + // + return result; + } + // // Values Retrievers ... diff --git a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 index 70f09ed9..34d94e52 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -450,6 +450,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller public: // // Props ... + CArrayObj barObjects; CArrayObj zoneObjects; CArrayObj pivotObjects; XFIMAPatternDetectorConfig analyserConfig; @@ -670,14 +671,14 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // ); // - XPivot fimaPivots[]; - int fimaPivotsCount = fimaHelper.DetecteXFIMAPivots( - fimaPivots, - iBar.Index(), - 50, // Number of Pivots ... - 7, // Validation Length ... - 500 // Loopback ... - ); + // XPivot fimaPivots[]; + // int fimaPivotsCount = fimaHelper.DetecteXFIMAPivots( + // fimaPivots, + // iBar.Index(), + // 50, // Number of Pivots ... + // 7, // Validation Length ... + // 500 // Loopback ... + // ); // // // has = IsValidSize(fimaZonesCount); @@ -702,22 +703,71 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // } // } + // // + // has = IsValidSize(fimaPivotsCount); + // if (has) + // { + // // + // // Draw Detected Pivots ... + // for (int i = 0; i < fimaPivotsCount; i++) + // { + // // + // XCBarArrowObject *iObj; + // has = poiDrawer.DrawPivot( + // fimaPivots[i], + // iObj); + // if (has) + // { + // pivotObjects.Add(iObj); + // } + // } + // } + // - has = IsValidSize(fimaPivotsCount); + // Detect DecisionBars ... + XOHCL decisionBars[]; + ENUM_X_DIRECTION decisionBarDirs[]; + int decisionBarsCount = fimaHelper.DetectXFIMAContinuationalPOIBars( + decisionBars, + decisionBarDirs, + iBar.Index(), + true, + X_DIRECTION_ALL, // For Dir ... + 300 // Required Number of Bars ... + ); + // int decisionBarsCount = fimaHelper.DetectXFIMAPOIBars( + // decisionBars, + // decisionBarDirs, + // iBar.Index(), + // true, + // X_DIRECTION_ALL, // For Dir ... + // 300 // Required Number of Bars ... + // ); + + // + has = IsValidSize(decisionBarsCount); if (has) { // - // Draw Detected Pivots ... - for (int i = 0; i < fimaPivotsCount; i++) + for (int i = 0; i < decisionBarsCount; i++) { // XCBarArrowObject *iObj; - has = poiDrawer.DrawPivot( - fimaPivots[i], - iObj); + has = poiDrawer.DrawBarArrow( + decisionBars[i], + iObj, + IsXBullish(decisionBarDirs[i]) ? X_PRICE_LOW : X_PRICE_HIGH, + 159, + IsXBullish(decisionBarDirs[i]) ? clrYellow : clrDarkOrange, + 5, + IsXBullish(decisionBarDirs[i]) ? ANCHOR_BOTTOM : ANCHOR_TOP, + "XOHCL_" + ToXString(TimeToSeconds(decisionBars[i].time)), + true, // Ignore Bar Tag ... + 5 // Threshold ... + ); if (has) { - pivotObjects.Add(iObj); + barObjects.Add(iObj); } } }