From faa50c55d2e16994f3bf7273d10579ff0a2aae37 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Wed, 1 Jan 2025 22:04:17 +0330 Subject: [PATCH] last ... --- Classes/x-saherelm.x-bar.analyser.class.mq5 | 3462 +++++++++++++++- Classes/x-saherelm.x-cobject.class.mq5 | 311 +- Classes/x-saherelm.x-poi.drawer.class.mq5 | 320 ++ Helpers/x-saherelm.x121.helper.mq5 | 196 + Libraries/x-saherelm.common.lib.mq5 | 3636 +---------------- Libraries/x-saherelm.x-poi.lib.mq5 | 999 +++++ .../x-121.smc.market.cycle.helper.class.mq5 | 654 ++- .../Signals/x-121.smc.xtwpv.signal.lib.mq5 | 6 + 8 files changed, 5962 insertions(+), 3622 deletions(-) diff --git a/Classes/x-saherelm.x-bar.analyser.class.mq5 b/Classes/x-saherelm.x-bar.analyser.class.mq5 index ea635ad0..577fea6b 100644 --- a/Classes/x-saherelm.x-bar.analyser.class.mq5 +++ b/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -474,14 +474,16 @@ class XCBarAnalyser : public XCBase XOHCL tmpLSW[]; // - bool trend1 = bar.HasBullishTrend( + bool trend1 = HasBullishTrend( + bar, tmpHSW, tmpLSW, true // ); // - bool trend2 = bar.HasBullishTrend( + bool trend2 = HasBullishTrend( + bar, tmpHSW, tmpLSW, false // @@ -535,14 +537,16 @@ class XCBarAnalyser : public XCBase XOHCL tmpLSW[]; // - bool trend1 = bar.HasBearishTrend( + bool trend1 = HasBearishTrend( + bar, tmpHSW, tmpLSW, true // ); // - bool trend2 = bar.HasBearishTrend( + bool trend2 = HasBearishTrend( + bar, tmpHSW, tmpLSW, false // @@ -630,7 +634,7 @@ class XCBarAnalyser : public XCBase bool isHammer = !checkHammer ? false - : iBar.IsHammer(); + : IsHammer(iBar); if (isHammer) { founded++; @@ -640,7 +644,7 @@ class XCBarAnalyser : public XCBase bool isMorningStar = !checkMorningStar ? false - : iBar.IsMorningStar(); + : IsMorningStar(iBar); if (isMorningStar) { founded++; @@ -650,7 +654,7 @@ class XCBarAnalyser : public XCBase bool isBullishMarubozu = !checkBullishMarubozu ? false - : iBar.IsBullishMarubozu(); + : IsBullishMarubozu(iBar); if (isBullishMarubozu) { founded++; @@ -660,7 +664,7 @@ class XCBarAnalyser : public XCBase bool isBullishEngulfing = !checkBullishEngulfing ? false - : iBar.IsBullishEngulfing(); + : IsBullishEngulfing(iBar); if (isBullishEngulfing) { founded++; @@ -740,7 +744,7 @@ class XCBarAnalyser : public XCBase bool isShootingStar = !checkShootingStar ? false - : iBar.IsShootingStar(); + : IsShootingStar(iBar); if (isShootingStar) { founded++; @@ -750,7 +754,7 @@ class XCBarAnalyser : public XCBase bool isEveningStar = !checkEveningStar ? false - : iBar.IsEveningStar(); + : IsEveningStar(iBar); if (isEveningStar) { founded++; @@ -760,7 +764,7 @@ class XCBarAnalyser : public XCBase bool isBearishMarubozu = !checkBearishMarubozu ? false - : iBar.IsBearishMarubozu(); + : IsBearishMarubozu(iBar); if (isBearishMarubozu) { founded++; @@ -770,7 +774,7 @@ class XCBarAnalyser : public XCBase bool isBearishEngulfing = !checkBearishEngulfing ? false - : iBar.IsBearishEngulfing(); + : IsBearishEngulfing(iBar); if (isBearishEngulfing) { founded++; @@ -2175,6 +2179,3440 @@ class XCBarAnalyser : public XCBase return result; } + // + // Tools ... + + // + bool IsStrong( + XOHCL &bar, + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = + (bar.GetRange() * percent) / 100 <= bar.GetBody(); + + // + return result; + } + + // + bool HasStrongLowShadow( + XOHCL &bar, + double percent = 50, // Percent of Body + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = + (bar.GetRange() * percent) / 100 <= bar.GetLowShadow(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + result = bar.Index() > __loopback; + if (!result) + { + return result; + } + + // + // Get Highest High and Lowest Low in loopback Range ... + int startIndex = bar.Index() - __loopback; + int endIndex = bar.Index() + __loopback; + int requiredBars = MathAbs(endIndex - startIndex); + + // + // Highs ... + double highs[]; + int copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + + // + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + int highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + double highestHigh = highs[highestHighIDX]; + + // + // Lows ... + double lows[]; + int copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + + // + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + int lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + double lowestLow = lows[lowestLowIDX]; + + // + result = bar.low == lowestLow && + highestHigh > bar.high; + if (!result) + { + return result; + } + + // + // Try to Validate Sharp Ratio ... + + // + Clean(highs); + Clean(lows); + + // + // Left Side ... + startIndex = bar.Index() + 1; + endIndex = startIndex + (__loopback / 2) - 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double leftDiff = highestHigh - lowestLow; + + // + Clean(highs); + Clean(lows); + + // + // Right Side ... + startIndex = bar.Index() - 1; + endIndex = startIndex - (__loopback / 2) + 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double rightDiff = highestHigh - lowestLow; + double diff = MathMax(leftDiff, rightDiff); + result = bar.GetLowShadow() >= (diff / 100) * _sharpRatio; + + // + return result; + } + + // + bool HasStrongHighShadow( + XOHCL &bar, + double percent = 50, // Percent of Body + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = + (bar.GetRange() * percent) / 100 <= bar.GetHighShadow(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + result = bar.Index() > __loopback; + if (!result) + { + return result; + } + + // + // Get Highest High and Lowest Low in loopback Range ... + int startIndex = bar.Index() - __loopback; + int endIndex = bar.Index() + __loopback; + int requiredBars = MathAbs(endIndex - startIndex); + + // + // Highs ... + double highs[]; + int copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + + // + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + int highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + double highestHigh = highs[highestHighIDX]; + + // + // Lows ... + double lows[]; + int copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + + // + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + int lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + double lowestLow = lows[lowestLowIDX]; + + // + result = bar.high == highestHigh && + lowestLow < bar.low; + if (!result) + { + return result; + } + + // + // Try to Validate Sharp Ratio ... + + // + Clean(highs); + Clean(lows); + + // + // Left Side ... + startIndex = bar.Index() + 1; + endIndex = startIndex + (__loopback / 2) - 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double leftDiff = highestHigh - lowestLow; + + // + Clean(highs); + Clean(lows); + + // + // Right Side ... + startIndex = bar.Index() - 1; + endIndex = startIndex - (__loopback / 2) + 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double rightDiff = highestHigh - lowestLow; + double diff = MathMax(leftDiff, rightDiff); + result = bar.GetHighShadow() >= (diff / 100) * _sharpRatio; + + // + return result; + } + + // + bool IsStrongBullish( + XOHCL &bar, + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + bar.IsBullish() && + IsStrong(bar, percent); + + // + return result; + } + + // + bool IsStrongBearish( + XOHCL &bar, + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + bar.IsBearish() && + IsStrong(bar, percent); + + // + return result; + } + + // + bool IsSharpBullish( + XOHCL &bar, + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + int hIDX = bar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + int lIDX = bar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + result = + // + hIDX >= 0 && + lIDX >= 0 && + MathAbs(hIDX - bar.Index()) < 2 + // + ; + + // + if (!result) + { + return result; + } + + // + XOHCL hBar; + result = hBar.Init( + bar.symbol, + bar.period, + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL lBar; + result = lBar.Init( + bar.symbol, + bar.period, + lIDX // + ); + if (!result) + { + return result; + } + + // + double lhDif = hBar.high - lBar.low; + + // + int hhIDX = hBar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + + // + int llIDX = lBar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + XOHCL hhBar; + result = hhBar.Init( + bar.symbol, + bar.period, + hhIDX + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + bar.symbol, + bar.period, + llIDX + lIDX // + ); + if (!result) + { + return result; + } + + // + double llhhDif = hhBar.high - llBar.low; + + // + result = + // + lBar.low > llBar.low && + hBar.high > hhBar.high && + lhDif >= llhhDif * _sharpRatio + // + ; + + // + return result; + } + + // + bool IsSharpBearish( + XOHCL &bar, + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + int hIDX = bar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + int lIDX = bar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + result = + // + hIDX >= 0 && + lIDX >= 0 && + MathAbs(hIDX - bar.Index()) < 2 + // + ; + + // + if (!result) + { + return result; + } + + // + XOHCL hBar; + result = hBar.Init( + bar.symbol, + bar.period, + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL lBar; + result = lBar.Init( + bar.symbol, + bar.period, + lIDX // + ); + if (!result) + { + return result; + } + + // + double lhDif = hBar.high - lBar.low; + + // + int hhIDX = hBar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + + // + int llIDX = lBar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + XOHCL hhBar; + result = hhBar.Init( + bar.symbol, + bar.period, + hhIDX + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + bar.symbol, + bar.period, + llIDX + lIDX // + ); + if (!result) + { + return result; + } + + // + double llhhDif = hhBar.high - llBar.low; + + // + result = + // + lBar.low < llBar.low && + hBar.high < hhBar.high && + lhDif >= llhhDif * _sharpRatio + // + ; + + // + return result; + } + + // + // + // + + // + // Retrieve Bullish Pressure ... + double GetBullishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + result += bars[i].GetLowShadow(); + } + + // + return result; + } + + // + // Retrieve Bearish Pressure ... + double GetBearishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + result += bars[i].GetHighShadow(); + } + + // + return result; + } + + // + bool HasBullishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPressure(bar, __loopback); + double bearishPressure = GetBearishPressure(bar, __loopback); + + // + result = + // + bullishPressure > 0 && + bearishPressure >= 0 && + bullishPressure > bearishPressure + // + ; + + // + return result; + } + + // + bool HasBearishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPressure(bar, __loopback); + double bearishPressure = GetBearishPressure(bar, __loopback); + + // + result = + // + bearishPressure > 0 && + bullishPressure >= 0 && + bearishPressure > bullishPressure + // + ; + + // + return result; + } + + // + // Retrieve Bullish Power ... + double GetBullishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + // + if (bars[i].IsBullish()) + { + result += bars[i].GetBody(); + } + } + + // + return result; + } + + // + // Retrieve Bearish Pressure ... + double GetBearishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + // + if (bars[i].IsBearish()) + { + result += bars[i].GetBody(); + } + } + + // + return result; + } + + // + bool HasBullishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPower(bar, __loopback); + double bearishPressure = GetBearishPower(bar, __loopback); + + // + result = + // + bullishPressure > 0 && + bearishPressure >= 0 && + bullishPressure > bearishPressure + // + ; + + // + return result; + } + + // + bool HasBearishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPower(bar, __loopback); + double bearishPressure = GetBearishPower(bar, __loopback); + + // + result = + // + bearishPressure > 0 && + bullishPressure >= 0 && + bearishPressure > bullishPressure + // + ; + + // + return result; + } + + // + // Decisions ... + + // + bool IsBullishDecision( + XOHCL &bar, + double percent = 70 // Percent of Body + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + bar.Index() > 0 && + bar.IsBullish() && + (bar.GetRange() * percent) / 100 <= bar.GetBody() + // + ; + + // + return result; + } + + // + bool IsBearishDecision( + XOHCL &bar, + double percent = 70 // Percent of Body + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + bar.Index() > 0 && + bar.IsBearish() && + (bar.GetRange() * percent) / 100 <= bar.GetBody() + // + ; + + // + return result; + } + + // + // Candlestic Patterns ... + + // + // Check Doji ... + bool IsDoji( + XOHCL &bar // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = bar.open == bar.close; + + // + return result; + } + + // + // Check Hammer ... + bool IsHammer( + XOHCL &bar, + double _upShadowFactor = 0.1, + double _downShadowFactor = 0.6, + bool applyFib382Check = true, + bool applyPrevShadowCheck = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_upShadowFactor < 0) + { + _upShadowFactor = 0.1; + } + + // + if (_downShadowFactor < 0) + { + _upShadowFactor = 0.6; + } + + // + double range = bar.GetRange(); + + // + // Check Upper Shadow Must be 0 or Under 10% ... + double upShadow = bar.GetHighShadow(); + result = upShadow < range * _upShadowFactor; + if (!result) + { + return result; + } + + // + // Check Down Shadow Must at least 60% ... + double downShadow = bar.GetLowShadow(); + result = downShadow > range * _downShadowFactor; + if (!result) + { + return result; + } + + // + // Check Fib 382 ... + if (result && applyFib382Check) + { + // + double fib382 = GetFibonacciLevel( + bar.high, + bar.low, + 0.382, + -1 // + ); + result = bar.GetDown() > fib382; + } + + // + // Check Shadow Based on Prev Bar ... + if (result && applyPrevShadowCheck) + { + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = bar.low < pBar.low; + } + + // + return result; + } + + // + // Check Sgooting Star ... + // Reversal Hammer ... + bool IsShootingStar( + XOHCL &bar, + double _upShadowFactor = 0.6, + double _downShadowFactor = 0.1, + bool applyFib382Check = true, + bool applyPrevShadowCheck = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_upShadowFactor < 0) + { + _upShadowFactor = 0.6; + } + + // + if (_downShadowFactor < 0) + { + _upShadowFactor = 0.1; + } + + // + double range = bar.GetRange(); + + // + // Check Upper Shadow Must be 0 or Under 10% ... + double upShadow = bar.GetHighShadow(); + result = upShadow > range * _upShadowFactor; + if (!result) + { + return result; + } + + // + // Check Down Shadow Must at least 60% ... + double downShadow = bar.GetLowShadow(); + result = downShadow < range * _downShadowFactor; + if (!result) + { + return result; + } + + // + // Check Fib 382 ... + if (result && applyFib382Check) + { + // + double fib382 = GetFibonacciLevel( + bar.high, + bar.low, + 0.382, + 1 // + ); + result = bar.GetUp() < fib382; + } + + // + // Check Shadow Based on Prev Bar ... + if (result && applyPrevShadowCheck) + { + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = bar.high > pBar.high; + } + + // + return result; + } + + // + // Check Bullish Engulfing ... + bool IsBullishEngulfing( + XOHCL &bar, + double _engulfBarBodyFactor = 0.7 // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_engulfBarBodyFactor < 0) + { + _engulfBarBodyFactor = 0.7; + } + + // + // Check Bar Is Bullish ... + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double body = bar.GetBody(); + + // + // Check Prev Bar Must Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Check Shadows Engulf Prev Bar ... + result = + // + bar.high > pBar.high && + bar.low <= pBar.low + // + ; + if (!result) + { + return result; + } + + // + // Check Engulfed Bar Must Inside Engulfer Body ... + result = + // + bar.GetUp() > pBar.GetUp() && + bar.GetDown() < pBar.GetDown() + // + ; + if (!result) + { + return result; + } + + // + // Check Body of Engulfing Bar ... + if (result && _engulfBarBodyFactor > 0) + { + result = body >= range * _engulfBarBodyFactor; + } + + // + return result; + } + + // + // Check Bearish Engulfing ... + bool IsBearishEngulfing( + XOHCL &bar, + double _engulfBarBodyFactor = 0.7 // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_engulfBarBodyFactor < 0) + { + _engulfBarBodyFactor = 0.7; + } + + // + // Check Bar Is Bearish ... + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double body = bar.GetBody(); + + // + // Check Prev Bar Must Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Check Shadows Engulf Prev Bar ... + result = bar.high >= pBar.high && + bar.low < pBar.low; + if (!result) + { + return result; + } + + // + // Check Engulfed Bar Must Inside Engulfer Body ... + result = + // + bar.GetUp() > pBar.GetUp() && + bar.GetDown() < pBar.GetDown() + // + ; + if (!result) + { + return result; + } + + // + // Check Body of Engulfing Bar ... + if (result && _engulfBarBodyFactor > 0) + { + result = body >= range * _engulfBarBodyFactor; + } + + // + return result; + } + + // + // Check Morning Star Pattern ... + bool IsMorningStar( + XOHCL &bar, + double _middleRangeFactor = 0.3, + double _startBodyFactor = 0.6, + bool forceCheckMiddleBarDirection = true, + bool forceCheckStartBody = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_middleRangeFactor < 0) + { + _middleRangeFactor = 0.3; + } + + // + if (_startBodyFactor < 0) + { + _startBodyFactor = 0.6; + } + + // + // Current Bar Must be Bullish ... + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar must be Bearish ... + if (result && forceCheckMiddleBarDirection) + { + // + result = pBar.IsBearish(); + if (!result) + { + return result; + } + } + + // + // Retrieve Previous Bar of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev Of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double pRange = pBar.GetRange(); + double ppRange = ppBar.GetRange(); + + // + // Middle Bar must be Smaller than Ratio of other ... + result = + // + pRange < range * _middleRangeFactor && + pRange < ppRange * _middleRangeFactor + // + ; + if (!result) + { + return result; + } + + // + if (result && forceCheckStartBody) + { + // + result = ppBar.GetBody() > ppRange * _startBodyFactor; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Check Evening Star Pattern ... + bool IsEveningStar( + XOHCL &bar, + double _middleRangeFactor = 0.3, + double _startBodyFactor = 0.6, + bool forceCheckMiddleBarDirection = true, + bool forceCheckStartBody = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_middleRangeFactor < 0) + { + _middleRangeFactor = 0.3; + } + + // + if (_startBodyFactor < 0) + { + _startBodyFactor = 0.6; + } + + // + // Current Bar Must be Bearish ... + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar must be Bullish ... + if (result && forceCheckMiddleBarDirection) + { + // + result = pBar.IsBullish(); + if (!result) + { + return result; + } + } + + // + // Retrieve Previous Bar of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev Of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double pRange = pBar.GetRange(); + double ppRange = ppBar.GetRange(); + + // + // Middle Bar must be Smaller than Ratio of other ... + result = + // + pRange < range * _middleRangeFactor && + pRange < ppRange * _middleRangeFactor + // + ; + if (!result) + { + return result; + } + + // + if (result && forceCheckStartBody) + { + // + result = ppBar.GetBody() > ppRange * _startBodyFactor; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Bullish Marubozu ... + bool IsBullishMarubozu(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + result = + // + bar.GetUp() == bar.high && + bar.GetDown() == bar.low + // + ; + + // + return result; + } + + // + // Bearish Marubozu ... + bool IsBearishMarubozu(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + result = + // + bar.GetUp() == bar.high && + bar.GetDown() == bar.low + // + ; + + // + return result; + } + + // + // Contextual Patterns ... + + // + // Check Swing High ... + bool IsBarSwingHigh(XOHCL &bar) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bearish ... + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Check All Highs ... + result = + // + bar.high < pBar.high && + pBar.high > ppBar.high + // + ; + + // + return result; + } + + // + // Find Simple 3 Candle Based Swing High ... + bool IsSimpleSwingHigh( + XOHCL &bar, + double thresholdInPoint = 1 // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + result = index > 0; + if (!result) + { + return result; + } + + // + XOHCL nextBar; + result = bar.GetNextBar(nextBar); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = bar.GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + double point = GetPoints(bar.symbol); + double requiredOffset = point * thresholdInPoint; + + // + result = + bar.high > nextBar.high && + bar.high > prevBar.high && + (thresholdInPoint <= 0 + ? true + : MathAbs( + MathMax( + nextBar.high, + prevBar.high) - + bar.high) >= requiredOffset); + + // + return result; + } + + // + // Find Last Swing High ... + bool FindLastSwingHigh( + XOHCL &bar, + XOHCL &swing // + ) + { + // + bool result = false; + + // + swing.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = iBars( + bar.symbol, + bar.period // + ); + int maxAllowed = MathMin(100, (totalBars / 100)); + + // + int idx = bar.Index(); + for (int i = idx; i <= idx + maxAllowed; i++) + { + // + swing.Clean(); + result = swing.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + // + swing.Clean(); + break; + } + + // + result = IsBarSwingHigh(swing); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Check Swing Low ... + bool IsBarSwingLow(XOHCL &bar) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bullish ... + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Check All Lows ... + result = + // + bar.low > pBar.low && + pBar.low < ppBar.low + // + ; + + // + return result; + } + + // + // Find Simple 3 Candle Based Swing Low ... + bool IsSimpleSwingLow( + XOHCL &bar, + double thresholdInPoint = 1 // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + result = index > 0; + if (!result) + { + return result; + } + + // + XOHCL nextBar; + result = bar.GetNextBar(nextBar); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = bar.GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + double point = GetPoints(bar.symbol); + double requiredOffset = point * thresholdInPoint; + + // + result = + bar.low < nextBar.low && + bar.low < prevBar.low && + (thresholdInPoint <= 0 + ? true + : MathAbs( + MathMax( + nextBar.low, + prevBar.low) - + bar.low) >= requiredOffset); + + // + return result; + } + + // + // Find Last Swing Low ... + bool FindLastSwingLow( + XOHCL &bar, + XOHCL &swing // + ) + { + // + bool result = false; + + // + swing.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = iBars( + bar.symbol, + bar.period // + ); + int maxAllowed = MathMin(100, (totalBars / 100)); + + // + int idx = bar.Index(); + for (int i = idx; i <= idx + maxAllowed; i++) + { + // + swing.Clean(); + result = swing.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + // + swing.Clean(); + break; + } + + // + result = IsBarSwingLow(swing); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Check Bullish FVG ... + bool HasBullishFVG( + XOHCL &bar, + double &upper, + double &lower, + datetime &start, + datetime &end, + bool forceMiddleBarCheck = true, + bool forceCheckLastBarDirection = false // + ) + { + // + bool result = false; + + // + upper = 0; + lower = 0; + + // + end = NULL; + start = NULL; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bullish ... + result = + !forceCheckLastBarDirection + ? true + : bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Other Conditions ... + result = + // + bar.low > ppBar.high + // + ; + + // + // Check Middle Bar Range ... + if (result && forceMiddleBarCheck) + { + // + result = + // + pBar.high > bar.low && + pBar.low < ppBar.high + // + ; + + // + if (!result) + { + return result; + } + } + + // + if (result) + { + // + end = bar.time; + upper = bar.low; + lower = ppBar.high; + start = ppBar.time; + } + + // + return result; + } + + // + // Check Bearish FVG ... + bool HasBearishFVG( + XOHCL &bar, + double &upper, + double &lower, + datetime &start, + datetime &end, + bool forceMiddleBarCheck = true, + bool forceCheckLastBarDirection = false // + ) + { + // + bool result = false; + + // + upper = 0; + lower = 0; + + // + end = NULL; + start = NULL; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bearish ... + result = + !forceCheckLastBarDirection + ? true + : bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Other Conditions ... + result = + // + bar.high < ppBar.low + // + ; + + // + // Check Middle Bar Range ... + if (result && forceMiddleBarCheck) + { + // + result = + // + pBar.high > bar.low && + pBar.low < ppBar.high + // + ; + + // + if (!result) + { + return result; + } + } + + // + if (result) + { + // + end = bar.time; + lower = bar.high; + upper = ppBar.low; + start = ppBar.time; + } + + // + return result; + } + + // + // Find Support ... + bool HasSupport( + XOHCL &bar, + XOHCL &dest, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int _loopback = 21, + int tries = 100 // + ) + { + // + bool result = false; + + // + dest.Clean(); + + // + if (_loopback < 0) + { + _loopback = 21; + } + + // + if (tries < 0) + { + tries = 100; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + for (int i = 1; i < tries; i++) + { + // + int _length = _loopback * i; + + // + int lowestIDX = bar.FindLowestIndex( + _length, + MODE_LOW // + ); + result = IsValidIndex(lowestIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + lowestIDX // + ); + if (!result) + { + break; + } + + // + result = + // + price > iLBar.high + // + ; + if (result) + { + // + dest = iLBar; + break; + } + } + + // + result = dest.IsValid(); + + // + return result; + } + + // + // Find Resistance ... + bool HasResistance( + XOHCL &bar, + XOHCL &dest, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int _loopback = 21, + int tries = 100 // + ) + { + // + bool result = false; + + // + dest.Clean(); + + // + if (_loopback < 0) + { + _loopback = 21; + } + + // + if (tries < 0) + { + tries = 100; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + for (int i = 1; i < tries; i++) + { + // + int _length = _loopback * i; + + // + int highestIDX = bar.FindHighestIndex( + _length, + MODE_LOW // + ); + result = IsValidIndex(highestIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + highestIDX // + ); + if (!result) + { + break; + } + + // + result = + // + price < iHBar.high + // + ; + if (result) + { + // + dest = iHBar; + break; + } + } + + // + result = dest.IsValid(); + + // + return result; + } + + // + // Trend Detection ... + + // + // Find Bullish Trend ... + bool HasBullishTrend( + XOHCL &bar, + XOHCL &highSwingBars[], + XOHCL &lowSwingBars[], + bool forceMethod2 = false, + int _loopback = 3, + int tries = 3, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + Clean(lowSwingBars); + Clean(highSwingBars); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + int lastIDX = bar.Index(); + double lastH = 0; + double lastL = 0; + for (int i = 1; i < tries + 1; i++) + { + // + // Use Regular Method ... + if (!forceMethod2) + { + // + int iHIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_HIGH, + _loopback, + lastIDX // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH < lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_LOW, + _loopback, + lastIDX // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL < lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + // + // Use Other MEthod ... + else + { + // + int _length = i * _loopback; + int start = + // + i == 1 + ? 1 + : _length - _loopback + // + ; + + // + int iHIDX = iHighest( + bar.symbol, + bar.period, + MODE_HIGH, + _loopback, + start // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH < lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = iLowest( + bar.symbol, + bar.period, + MODE_LOW, + _loopback, + start // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL < lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + } + + // + if (result) + { + // + result = + // + ArraySize(lowSwingBars) == tries && + ArraySize(highSwingBars) == tries + // + ; + } + + // + if (!result) + { + // + Clean(lowSwingBars); + Clean(highSwingBars); + } + + // + return result; + } + + // + // Find Bearish Trend ... + bool HasBearishTrend( + XOHCL &bar, + XOHCL &highSwingBars[], + XOHCL &lowSwingBars[], + bool forceMethod2 = false, + int _loopback = 3, + int tries = 3, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + Clean(lowSwingBars); + Clean(highSwingBars); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + int lastIDX = bar.Index(); + double lastH = 0; + double lastL = 0; + for (int i = 1; i < tries + 1; i++) + { + // + // Use Regular Method ... + if (!forceMethod2) + { + // + int iHIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_HIGH, + _loopback, + lastIDX // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH > lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_LOW, + _loopback, + lastIDX // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL > lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + // + // Use Other MEthod ... + else + { + // + int _length = i * _loopback; + int start = + // + i == 1 + ? 1 + : _length - _loopback + // + ; + + // + int iHIDX = iHighest( + bar.symbol, + bar.period, + MODE_HIGH, + _loopback, + start // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH > lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = iLowest( + bar.symbol, + bar.period, + MODE_LOW, + _loopback, + start // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL > lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + } + + // + if (result) + { + // + result = + // + ArraySize(lowSwingBars) == tries && + ArraySize(highSwingBars) == tries + // + ; + } + + // + if (!result) + { + // + Clean(lowSwingBars); + Clean(highSwingBars); + } + + // + return result; + } + + // + // Order Blocks ... + + // + // Find Bullish Order Block ... + bool HasBullishOrderBlock( + XOHCL &bar, + XOHCL &orderBlock, + int _minimumSameBars = 4 // + ) + { + // + bool result = false; + + // + orderBlock.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (_minimumSameBars < 0) + { + _minimumSameBars = 4; + } + + // + XOHCL cBar; + int founded = 0; + int cIDX = bar.Index(); + bool isEnough = false; + while (!isEnough) + { + // + result = cBar.Init( + bar.symbol, + bar.period, + cIDX // + ); + if (!result) + { + break; + } + + // + result = cBar.IsBullish(); + if (!result && cBar.IsBearish()) + { + break; + } + + // + cIDX++; + founded++; + } + + // + // Here we have to check founded and if it's fill + // our requirements ... + // cIDX is Order Block Index ... + result = + // + cBar.IsValid() && + bar.high > cBar.high && + founded >= _minimumSameBars + // + ; + if (!result) + { + return result; + } + + // + result = orderBlock.Init( + bar.symbol, + bar.period, + cIDX // + ); + if (!result) + { + // + orderBlock.Clean(); + return result; + } + + // + return result; + } + + // + // Find Bearish Order Block ... + bool HasBearishOrderBlock( + XOHCL &bar, + XOHCL &orderBlock, + int _minimumSameBars = 4 // + ) + { + // + bool result = false; + + // + orderBlock.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (_minimumSameBars < 0) + { + _minimumSameBars = 4; + } + + // + XOHCL cBar; + int founded = 0; + int cIDX = bar.Index(); + bool isEnough = false; + while (!isEnough) + { + // + bool isInited = cBar.Init( + bar.symbol, + bar.period, + cIDX // + ); + + // + result = cBar.IsBearish(); + if (!result && cBar.IsBullish()) + { + break; + } + + // + cIDX++; + founded++; + } + + // + // Here we have to check founded and if it's fill + // our requirements ... + // cIDX is Order Block Index ... + result = + // + cBar.IsValid() && + bar.high < cBar.low && + founded >= _minimumSameBars + // + ; + if (!result) + { + return result; + } + + // + result = orderBlock.Init( + bar.symbol, + bar.period, + cIDX // + ); + if (!result) + { + // + orderBlock.Clean(); + return result; + } + + // + return result; + } + // protected: // diff --git a/Classes/x-saherelm.x-cobject.class.mq5 b/Classes/x-saherelm.x-cobject.class.mq5 index 383fc7fd..215ba7a7 100644 --- a/Classes/x-saherelm.x-cobject.class.mq5 +++ b/Classes/x-saherelm.x-cobject.class.mq5 @@ -44,6 +44,7 @@ enum ENUM_XCHARTOBJECTS X_SIGNAL_OBJ = 8860, X_TREND_OBJ = 8861, X_XPVPIVOT_OBJ = 8862, + X_OHCL_OBJ = 8863, // // Structured ... X_TRADE_DAY_OBJ = 9860, @@ -76,7 +77,10 @@ enum ENUM_X_CHART_IDS X_ENTRY, X_TARGET, X_SL, - X_TP + X_TP, + X_BAR_H_SHW, + X_BAR_BDY, + X_BAR_L_SHW, }; string ToString(ENUM_X_CHART_IDS value) @@ -126,6 +130,23 @@ string ToString(ENUM_X_CHART_IDS value) case X_TP: result = "TP"; break; + + // + case X_BAR_H_SHW: + result = "HSHW"; + break; + + // + case X_BAR_BDY: + result = "BODY"; + break; + + // + case X_BAR_L_SHW: + result = "LSHW"; + break; + + // } // @@ -2216,6 +2237,292 @@ class XCXPVPivotObject : public XCBaseObject CChartObjectTrend mTrend; }; +class XCOHCLObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param pivot: XPVPivot instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XOHCL &bar, + datetime to, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + IsValid(to); + if (!result) + { + return result; + } + + // + string name = bar.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + // High Shadow ... + string hShadowName = ToString(X_BAR_H_SHW) + "_" + nameMD5; + + // + result = mHighShadowRect.Create( + chart_id, + hShadowName, + window, + bar.time, + bar.high, + to, + bar.GetUp() // + ); + if (!result) + { + return result; + } + + // + // Body ... + string bodyName = ToString(X_BAR_BDY) + "_" + nameMD5; + + // + result = mBodyRect.Create( + chart_id, + bodyName, + window, + bar.time, + bar.GetUp(), + to, + bar.GetDown() // + ); + if (!result) + { + // + mHighShadowRect.Delete(); + mHighShadowRect.Detach(); + return result; + } + + // + // Low Shadow ... + string lShadowName = ToString(X_BAR_L_SHW) + "_" + nameMD5; + + // + result = mLowShadowRect.Create( + chart_id, + lShadowName, + window, + bar.time, + bar.GetDown(), + to, + bar.low // + ); + if (!result) + { + // + mBodyRect.Delete(); + mBodyRect.Detach(); + mHighShadowRect.Delete(); + mHighShadowRect.Detach(); + return result; + } + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Pivot Width ... + * + * @param value: Integer ... + */ + void HighShadowWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mHighShadowRect.Width(value); + } + + /** + * Set Pivot Color ... + * + * @param value: Color ... + */ + void HighShadowColor(color value) + { + mHighShadowRect.Color(value); + } + + /** + * Set Pivot Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void HighShadowStyle(ENUM_LINE_STYLE value) + { + mHighShadowRect.Style(value); + } + + /** + * Set Pivot Fill ... + * + * @param value: Boolean ... + */ + void HighShadowFill(bool value) + { + mHighShadowRect.Fill(value); + } + + /** + * Set Pivot Width ... + * + * @param value: Integer ... + */ + void BodyWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBodyRect.Width(value); + } + + /** + * Set Pivot Color ... + * + * @param value: Color ... + */ + void BodyColor(color value) + { + mBodyRect.Color(value); + } + + /** + * Set Pivot Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BodyStyle(ENUM_LINE_STYLE value) + { + mBodyRect.Style(value); + } + + /** + * Set Pivot Fill ... + * + * @param value: Boolean ... + */ + void BodyFill(bool value) + { + mBodyRect.Fill(value); + } + + /** + * Set Pivot Width ... + * + * @param value: Integer ... + */ + void LowShadowWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mLowShadowRect.Width(value); + } + + /** + * Set Pivot Color ... + * + * @param value: Color ... + */ + void LowShadowColor(color value) + { + mLowShadowRect.Color(value); + } + + /** + * Set Pivot Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void LowShadowStyle(ENUM_LINE_STYLE value) + { + mLowShadowRect.Style(value); + } + + /** + * Set Pivot Fill ... + * + * @param value: Boolean ... + */ + void LowShadowFill(bool value) + { + mLowShadowRect.Fill(value); + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_OHCL_OBJ; + } + + // + private: + // + + // + // Props ... + CChartObjectRectangle mHighShadowRect; + CChartObjectRectangle mBodyRect; + CChartObjectRectangle mLowShadowRect; +}; + // // Zone Ticks ... @@ -2455,7 +2762,7 @@ class XCTickZoneObject : public XCBaseObject } // - int fromToDiff = ((int) to - (int) from); + int fromToDiff = ((int)to - (int)from); datetime labelsDate = (datetime)((int)to - (fromToDiff / 5)); // diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index b1a0646d..d9540298 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -123,6 +123,196 @@ class XCPOIDrawer : public XCBase mSubWindowIdentification = value; } + // + // XOHCL ... + + /** + * Get Bar Width ... + * + * @return ( int ) + */ + int BarWidth() + { + return mBarWidth; + } + + /** + * Set Bar Width ... + * + * @param value: Integer ... + */ + void BarWidth(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mBarWidth = value; + } + + /** + * Get Bar Bullish Color ... + * + * @return ( color ) + */ + color BarBullishColor() + { + return mBarBullishColor; + } + + /** + * Set Bar Bullish Color ... + * + * @param value: Color ... + */ + void BarBullishColor(color value) + { + mBarBullishColor = value; + } + + /** + * Get Bar Bearish Color ... + * + * @return ( color ) + */ + color BarBearishColor() + { + return mBarBearishColor; + } + + /** + * Set Bar Bearish Color ... + * + * @param value: Color ... + */ + void BarBearishColor(color value) + { + mBarBearishColor = value; + } + + /** + * Get Fill Bar High Shadow State ... + * + * @return ( bool ) + */ + bool BarFillHighShadow() + { + return mBarFillHighShadow; + } + + /** + * Set Fill Bar High Shadow State ... + * + * @param value: Boolean ... + */ + void BarFillHighShadow(bool value) + { + mBarFillHighShadow = value; + } + + /** + * Get Bar High Shadow Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BarHighShadowStyle() + { + return mBarHighShadowStyle; + } + + /** + * Set Bar High Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BarHighShadowStyle(ENUM_LINE_STYLE value) + { + mBarHighShadowStyle = value; + } + + /** + * Get Fill Bar Body State ... + * + * @return ( bool ) + */ + bool BarFillBody() + { + return mBarFillBody; + } + + /** + * Set Fill Bar Body State ... + * + * @param value: Boolean ... + */ + void BarFillBody(bool value) + { + mBarFillBody = value; + } + + /** + * Get Bar Body Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BarBodyStyle() + { + return mBarBodyStyle; + } + + /** + * Set Bar Body Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BarBodyStyle(ENUM_LINE_STYLE value) + { + mBarBodyStyle = value; + } + + /** + * Get Fill Bar Low Show State ... + * + * @return ( bool ) + */ + bool BarFillLowShadow() + { + return mBarFillLowShadow; + } + + /** + * Set Fill Bar Low Show State ... + * + * @param value: Boolean ... + */ + void BarFillLowShadow(bool value) + { + mBarFillLowShadow = value; + } + + /** + * Get Bar Low Shadow Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BarLowShadowStyle() + { + return mBarLowShadowStyle; + } + + /** + * Set Bar Low Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BarLowShadowStyle(ENUM_LINE_STYLE value) + { + mBarLowShadowStyle = value; + } + // // Swing Low ... @@ -1285,6 +1475,17 @@ class XCPOIDrawer : public XCBase ChartIdentification(0); SubWindowIdentification(0); + // + BarWidth(1); + BarBearishColor(clrRed); + BarBullishColor(clrLime); + BarFillBody(false); + BarFillHighShadow(false); + BarFillLowShadow(false); + BarBodyStyle(STYLE_DOT); + BarLowShadowStyle(STYLE_DOT); + BarHighShadowStyle(STYLE_DOT); + // int arrowWidth = 1; @@ -2550,6 +2751,113 @@ class XCPOIDrawer : public XCBase return result; } + /** + * Create Bar Object ... + * + * @param bar: XOHCL instance Reference .. + * @param object: XCOHCLObject pointer Reference .. + * @param to: Datetime ... + * + * @return ( bool ) + */ + bool CreateBar( + XOHCL &bar, + XCOHCLObject *&object, + datetime to = NULL // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (!IsValid(to)) + { + to = bar.time + PeriodSeconds(bar.period); + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int width = BarWidth(); + + // + color bullishColor = BarBullishColor(); + color bearishColor = BarBearishColor(); + + // + bool fillBody = BarFillBody(); + bool fillHighShadow = BarFillHighShadow(); + bool fillLowShadow = BarFillLowShadow(); + + // + ENUM_LINE_STYLE bodyStyle = BarBodyStyle(); + ENUM_LINE_STYLE highShadowStyle = BarHighShadowStyle(); + ENUM_LINE_STYLE lowShadowStyle = BarLowShadowStyle(); + + // + object = new XCOHCLObject(); + result = object.Create( + chartID, + window, + bar, + to, + prefix // + ); + if (result) + { + // + // Apply Styling ... + + // + object.BodyWidth(width); + object.LowShadowWidth(width); + object.HighShadowWidth(width); + + // + object.BodyStyle(bodyStyle); + object.LowShadowStyle(lowShadowStyle); + object.HighShadowStyle(highShadowStyle); + + // + bool isBullish = bar.IsBullish(); + if (isBullish) + { + // + object.BodyColor(bullishColor); + object.LowShadowColor(bullishColor); + object.HighShadowColor(bullishColor); + } + else + { + // + object.BodyColor(bearishColor); + object.LowShadowColor(bearishColor); + object.HighShadowColor(bearishColor); + } + + // + object.BodyFill(fillBody); + object.HighShadowFill(fillHighShadow); + object.LowShadowFill(fillLowShadow); + } + + // + return result; + } + /** * Draw Specified Signal ... * @@ -3300,6 +3608,18 @@ class XCPOIDrawer : public XCBase long mChartIdentification; // Chart Id ... int mSubWindowIdentification; // Sub Window ... + // + // XOHCL ... + int mBarWidth; // Bar Width ... + color mBarBullishColor; // Bar Bullish Color ... + color mBarBearishColor; // Bar Bearish Color ... + bool mBarFillHighShadow; // Fill Bar High Shadow ... + ENUM_LINE_STYLE mBarHighShadowStyle; // Bar High Shadow Style ... + bool mBarFillBody; // Fill Bar Body ... + ENUM_LINE_STYLE mBarBodyStyle; // Bar Body Style ... + bool mBarFillLowShadow; // Fill Bar Low Show ... + ENUM_LINE_STYLE mBarLowShadowStyle; // Bar Low Shadow Style ... + // // Swing Low ... int mSwingLowWidth; // Swing Low Width ... diff --git a/Helpers/x-saherelm.x121.helper.mq5 b/Helpers/x-saherelm.x121.helper.mq5 index e4bfb887..9f8cc718 100644 --- a/Helpers/x-saherelm.x121.helper.mq5 +++ b/Helpers/x-saherelm.x121.helper.mq5 @@ -1747,6 +1747,202 @@ class XCX121Helper : public XCBaseHelper ); } + // + double GetLowestPeak( + int barIndex, + int &index, + double &vale, + int loopback = 576 // + ) + { + // + double result = 0; + + // + index = -1; + vale = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + for (int i = 0; i < barIndex + loopback; i++) + { + // + double iPeak = GetPeak(i); + if (iPeak == 0) + { + break; + } + + // + if (iPeak > 0 && (result == 0 || + result >= iPeak)) + { + // + index = i; + result = iPeak; + vale = GetVale(index); + } + } + + // + return result; + } + + // + double GetHighestPeak( + int barIndex, + int &index, + double &vale, + int loopback = 576 // + ) + { + // + double result = 0; + + // + index = -1; + vale = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + for (int i = 0; i < barIndex + loopback; i++) + { + // + double iPeak = GetPeak(i); + if (iPeak == 0) + { + break; + } + + // + if (iPeak > 0 && (result == 0 || + result <= iPeak)) + { + // + index = i; + result = iPeak; + vale = GetVale(index); + } + } + + // + return result; + } + + // + double GetLowestVale( + int barIndex, + int &index, + double &peak, + int loopback = 576 // + ) + { + // + double result = 0; + + // + index = -1; + peak = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + for (int i = 0; i < barIndex + loopback; i++) + { + // + double iPeak = GetVale(i); + if (iPeak == 0) + { + break; + } + + // + if (iPeak > 0 && (result == 0 || + result >= iPeak)) + { + // + index = i; + result = iPeak; + peak = GetPeak(index); + } + } + + // + return result; + } + + // + double GetHighestVale( + int barIndex, + int &index, + double &peak, + int loopback = 576 // + ) + { + // + double result = 0; + + // + index = -1; + peak = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + for (int i = 0; i < barIndex + loopback; i++) + { + // + double iPeak = GetVale(i); + if (iPeak == 0) + { + break; + } + + // + if (iPeak > 0 && (result == 0 || + result <= iPeak)) + { + // + index = i; + result = iPeak; + peak = GetPeak(index); + } + } + + // + return result; + } + // // CURRENT ... diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index a51b6f51..234260a6 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -1644,827 +1644,6 @@ struct XOHCL return result; } - // - bool IsStrong( - double percent = 50 // Percent of Body - ) - { - // - bool result = false; - - // - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - result = - (GetRange() * percent) / 100 <= GetBody(); - - // - return result; - } - - // - bool HasStrongLowShadow( - double percent = 50, // Percent of Body - int __loopback = 2, - double _sharpRatio = 2.5 // - ) - { - // - bool result = false; - - // - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - result = - (GetRange() * percent) / 100 <= GetLowShadow(); - if (!result) - { - return result; - } - - // - if (__loopback < 0) - { - __loopback = 2; - } - - // - if (_sharpRatio < 0) - { - _sharpRatio = 2.5; - } - - // - result = Index() > __loopback; - if (!result) - { - return result; - } - - // - // Get Highest High and Lowest Low in loopback Range ... - int startIndex = Index() - __loopback; - int endIndex = Index() + __loopback; - int requiredBars = MathAbs(endIndex - startIndex); - - // - // Highs ... - double highs[]; - int copiedHighs = CopyHigh( - symbol, - period, - startIndex, - requiredBars, - highs // - ); - - // - result = copiedHighs == requiredBars; - if (!result) - { - return result; - } - - // - int highestHighIDX = ArrayMaximum(highs); - result = IsValidIndex(highestHighIDX); - if (!result) - { - return result; - } - - // - double highestHigh = highs[highestHighIDX]; - - // - // Lows ... - double lows[]; - int copiedLows = CopyLow( - symbol, - period, - startIndex, - requiredBars, - lows // - ); - - // - result = copiedLows == requiredBars; - if (!result) - { - return result; - } - - // - int lowestLowIDX = ArrayMinimum(lows); - result = IsValidIndex(lowestLowIDX); - if (!result) - { - return result; - } - - // - double lowestLow = lows[lowestLowIDX]; - - // - result = low == lowestLow && - highestHigh > high; - if (!result) - { - return result; - } - - // - // Try to Validate Sharp Ratio ... - - // - Clean(highs); - Clean(lows); - - // - // Left Side ... - startIndex = Index() + 1; - endIndex = startIndex + (__loopback / 2) - 1; - requiredBars = MathAbs(endIndex - startIndex); - - // - copiedHighs = CopyHigh( - symbol, - period, - startIndex, - requiredBars, - highs // - ); - result = copiedHighs == requiredBars; - if (!result) - { - return result; - } - - // - highestHighIDX = ArrayMaximum(highs); - result = IsValidIndex(highestHighIDX); - if (!result) - { - return result; - } - - // - highestHigh = highs[highestHighIDX]; - - // - copiedLows = CopyLow( - symbol, - period, - startIndex, - requiredBars, - lows // - ); - result = copiedLows == requiredBars; - if (!result) - { - return result; - } - - // - lowestLowIDX = ArrayMinimum(lows); - result = IsValidIndex(lowestLowIDX); - if (!result) - { - return result; - } - - // - lowestLow = lows[lowestLowIDX]; - - // - double leftDiff = highestHigh - lowestLow; - - // - Clean(highs); - Clean(lows); - - // - // Right Side ... - startIndex = Index() - 1; - endIndex = startIndex - (__loopback / 2) + 1; - requiredBars = MathAbs(endIndex - startIndex); - - // - copiedHighs = CopyHigh( - symbol, - period, - startIndex, - requiredBars, - highs // - ); - result = copiedHighs == requiredBars; - if (!result) - { - return result; - } - - // - highestHighIDX = ArrayMaximum(highs); - result = IsValidIndex(highestHighIDX); - if (!result) - { - return result; - } - - // - highestHigh = highs[highestHighIDX]; - - // - copiedLows = CopyLow( - symbol, - period, - startIndex, - requiredBars, - lows // - ); - result = copiedLows == requiredBars; - if (!result) - { - return result; - } - - // - lowestLowIDX = ArrayMinimum(lows); - result = IsValidIndex(lowestLowIDX); - if (!result) - { - return result; - } - - // - lowestLow = lows[lowestLowIDX]; - - // - double rightDiff = highestHigh - lowestLow; - double diff = MathMax(leftDiff, rightDiff); - result = GetLowShadow() >= (diff / 100) * _sharpRatio; - - // - return result; - } - - // - bool HasStrongHighShadow( - double percent = 50, // Percent of Body - int __loopback = 2, - double _sharpRatio = 2.5 // - ) - { - // - bool result = false; - - // - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - result = - (GetRange() * percent) / 100 <= GetHighShadow(); - if (!result) - { - return result; - } - - // - if (__loopback < 0) - { - __loopback = 2; - } - - // - if (_sharpRatio < 0) - { - _sharpRatio = 2.5; - } - - // - result = Index() > __loopback; - if (!result) - { - return result; - } - - // - // Get Highest High and Lowest Low in loopback Range ... - int startIndex = Index() - __loopback; - int endIndex = Index() + __loopback; - int requiredBars = MathAbs(endIndex - startIndex); - - // - // Highs ... - double highs[]; - int copiedHighs = CopyHigh( - symbol, - period, - startIndex, - requiredBars, - highs // - ); - - // - result = copiedHighs == requiredBars; - if (!result) - { - return result; - } - - // - int highestHighIDX = ArrayMaximum(highs); - result = IsValidIndex(highestHighIDX); - if (!result) - { - return result; - } - - // - double highestHigh = highs[highestHighIDX]; - - // - // Lows ... - double lows[]; - int copiedLows = CopyLow( - symbol, - period, - startIndex, - requiredBars, - lows // - ); - - // - result = copiedLows == requiredBars; - if (!result) - { - return result; - } - - // - int lowestLowIDX = ArrayMinimum(lows); - result = IsValidIndex(lowestLowIDX); - if (!result) - { - return result; - } - - // - double lowestLow = lows[lowestLowIDX]; - - // - result = high == highestHigh && - lowestLow < low; - if (!result) - { - return result; - } - - // - // Try to Validate Sharp Ratio ... - - // - Clean(highs); - Clean(lows); - - // - // Left Side ... - startIndex = Index() + 1; - endIndex = startIndex + (__loopback / 2) - 1; - requiredBars = MathAbs(endIndex - startIndex); - - // - copiedHighs = CopyHigh( - symbol, - period, - startIndex, - requiredBars, - highs // - ); - result = copiedHighs == requiredBars; - if (!result) - { - return result; - } - - // - highestHighIDX = ArrayMaximum(highs); - result = IsValidIndex(highestHighIDX); - if (!result) - { - return result; - } - - // - highestHigh = highs[highestHighIDX]; - - // - copiedLows = CopyLow( - symbol, - period, - startIndex, - requiredBars, - lows // - ); - result = copiedLows == requiredBars; - if (!result) - { - return result; - } - - // - lowestLowIDX = ArrayMinimum(lows); - result = IsValidIndex(lowestLowIDX); - if (!result) - { - return result; - } - - // - lowestLow = lows[lowestLowIDX]; - - // - double leftDiff = highestHigh - lowestLow; - - // - Clean(highs); - Clean(lows); - - // - // Right Side ... - startIndex = Index() - 1; - endIndex = startIndex - (__loopback / 2) + 1; - requiredBars = MathAbs(endIndex - startIndex); - - // - copiedHighs = CopyHigh( - symbol, - period, - startIndex, - requiredBars, - highs // - ); - result = copiedHighs == requiredBars; - if (!result) - { - return result; - } - - // - highestHighIDX = ArrayMaximum(highs); - result = IsValidIndex(highestHighIDX); - if (!result) - { - return result; - } - - // - highestHigh = highs[highestHighIDX]; - - // - copiedLows = CopyLow( - symbol, - period, - startIndex, - requiredBars, - lows // - ); - result = copiedLows == requiredBars; - if (!result) - { - return result; - } - - // - lowestLowIDX = ArrayMinimum(lows); - result = IsValidIndex(lowestLowIDX); - if (!result) - { - return result; - } - - // - lowestLow = lows[lowestLowIDX]; - - // - double rightDiff = highestHigh - lowestLow; - double diff = MathMax(leftDiff, rightDiff); - result = GetHighShadow() >= (diff / 100) * _sharpRatio; - - // - return result; - } - - // - bool IsStrongBullish( - double percent = 50 // Percent of Body - ) - { - // - bool result = false; - - // - result = - IsStrong(percent) && IsBullish(); - - // - return result; - } - - // - bool IsStrongBearish( - double percent = 50 // Percent of Body - ) - { - // - bool result = false; - - // - result = - IsStrong(percent) && IsBearish(); - - // - return result; - } - - // - bool IsSharpBullish( - int __loopback = 2, - double _sharpRatio = 2.5 // - ) - { - // - bool result = false; - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - if (__loopback < 0) - { - __loopback = 2; - } - - // - if (_sharpRatio < 0) - { - _sharpRatio = 2.5; - } - - // - int hIDX = FindHighestIndex( - __loopback, - MODE_HIGH // - ); - int lIDX = FindLowestIndex( - __loopback, - MODE_LOW // - ); - - // - result = - // - hIDX >= 0 && - lIDX >= 0 && - MathAbs(hIDX - Index()) < 2 - // - ; - - // - if (!result) - { - return result; - } - - // - XOHCL hBar; - result = hBar.Init( - symbol, - period, - hIDX // - ); - if (!result) - { - return result; - } - - // - XOHCL lBar; - result = lBar.Init( - symbol, - period, - lIDX // - ); - if (!result) - { - return result; - } - - // - double lhDif = hBar.high - lBar.low; - - // - int hhIDX = hBar.FindHighestIndex( - __loopback, - MODE_HIGH // - ); - - // - int llIDX = lBar.FindLowestIndex( - __loopback, - MODE_LOW // - ); - - // - XOHCL hhBar; - result = hhBar.Init( - symbol, - period, - hhIDX + hIDX // - ); - if (!result) - { - return result; - } - - // - XOHCL llBar; - result = llBar.Init( - symbol, - period, - llIDX + lIDX // - ); - if (!result) - { - return result; - } - - // - double llhhDif = hhBar.high - llBar.low; - - // - result = - // - lBar.low > llBar.low && - hBar.high > hhBar.high && - lhDif >= llhhDif * _sharpRatio - // - ; - - // - return result; - } - - // - bool IsSharpBearish( - int __loopback = 2, - double _sharpRatio = 2.5 // - ) - { - // - bool result = false; - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - if (__loopback < 0) - { - __loopback = 2; - } - - // - if (_sharpRatio < 0) - { - _sharpRatio = 2.5; - } - - // - int hIDX = FindHighestIndex( - __loopback, - MODE_HIGH // - ); - int lIDX = FindLowestIndex( - __loopback, - MODE_LOW // - ); - - // - result = - // - hIDX >= 0 && - lIDX >= 0 && - MathAbs(hIDX - Index()) < 2 - // - ; - - // - if (!result) - { - return result; - } - - // - XOHCL hBar; - result = hBar.Init( - symbol, - period, - hIDX // - ); - if (!result) - { - return result; - } - - // - XOHCL lBar; - result = lBar.Init( - symbol, - period, - lIDX // - ); - if (!result) - { - return result; - } - - // - double lhDif = hBar.high - lBar.low; - - // - int hhIDX = hBar.FindHighestIndex( - __loopback, - MODE_HIGH // - ); - - // - int llIDX = lBar.FindLowestIndex( - __loopback, - MODE_LOW // - ); - - // - XOHCL hhBar; - result = hhBar.Init( - symbol, - period, - hhIDX + hIDX // - ); - if (!result) - { - return result; - } - - // - XOHCL llBar; - result = llBar.Init( - symbol, - period, - llIDX + lIDX // - ); - if (!result) - { - return result; - } - - // - double llhhDif = hhBar.high - llBar.low; - - // - result = - // - lBar.low < llBar.low && - hBar.high < hhBar.high && - lhDif >= llhhDif * _sharpRatio - // - ; - - // - return result; - } - // // Find Highest Bar Index ... int FindHighestIndex( @@ -2670,359 +1849,16 @@ struct XOHCL } // - // Retrieve Bullish Pressure ... - double GetBullishPressure( - int __loopback = 7 // - ) - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - XOHCL bars[]; - int barsCount = GetBars( - bars, - symbol, - period, - Index(), - __loopback // - ); - if (!IsValidSize(barsCount)) - { - return result; - } - - // - for (int i = 0; i < barsCount; i++) - { - result += bars[i].GetLowShadow(); - } - - // - return result; - } - - // - // Retrieve Bearish Pressure ... - double GetBearishPressure( - int __loopback = 7 // - ) - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - XOHCL bars[]; - int barsCount = GetBars( - bars, - symbol, - period, - Index(), - __loopback // - ); - if (!IsValidSize(barsCount)) - { - return result; - } - - // - for (int i = 0; i < barsCount; i++) - { - result += bars[i].GetHighShadow(); - } - - // - return result; - } - - // - bool HasBullishPressure( - int __loopback = 7 // - ) - { - // - bool result = false; - - // - if (__loopback < 0) - { - __loopback = 7; - } - - // - double bullishPressure = GetBullishPressure(__loopback); - double bearishPressure = GetBearishPressure(__loopback); - - // - result = - // - bullishPressure > 0 && - bearishPressure >= 0 && - bullishPressure > bearishPressure - // - ; - - // - return result; - } - - // - bool HasBearishPressure( - int __loopback = 7 // - ) - { - // - bool result = false; - - // - if (__loopback < 0) - { - __loopback = 7; - } - - // - double bullishPressure = GetBullishPressure(__loopback); - double bearishPressure = GetBearishPressure(__loopback); - - // - result = - // - bearishPressure > 0 && - bullishPressure >= 0 && - bearishPressure > bullishPressure - // - ; - - // - return result; - } - - // - // Retrieve Bullish Power ... - double GetBullishPower( - int __loopback = 7 // - ) - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - XOHCL bars[]; - int barsCount = GetBars( - bars, - symbol, - period, - Index(), - __loopback // - ); - if (!IsValidSize(barsCount)) - { - return result; - } - - // - for (int i = 0; i < barsCount; i++) - { - // - if (bars[i].IsBullish()) - { - result += bars[i].GetBody(); - } - } - - // - return result; - } - - // - // Retrieve Bearish Pressure ... - double GetBearishPower( - int __loopback = 7 // - ) - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - XOHCL bars[]; - int barsCount = GetBars( - bars, - symbol, - period, - Index(), - __loopback // - ); - if (!IsValidSize(barsCount)) - { - return result; - } - - // - for (int i = 0; i < barsCount; i++) - { - // - if (bars[i].IsBearish()) - { - result += bars[i].GetBody(); - } - } - - // - return result; - } - - // - bool HasBullishPower( - int __loopback = 7 // - ) - { - // - bool result = false; - - // - if (__loopback < 0) - { - __loopback = 7; - } - - // - double bullishPressure = GetBullishPower(__loopback); - double bearishPressure = GetBearishPower(__loopback); - - // - result = - // - bullishPressure > 0 && - bearishPressure >= 0 && - bullishPressure > bearishPressure - // - ; - - // - return result; - } - - // - bool HasBearishPower( - int __loopback = 7 // - ) - { - // - bool result = false; - - // - if (__loopback < 0) - { - __loopback = 7; - } - - // - double bullishPressure = GetBullishPower(__loopback); - double bearishPressure = GetBearishPower(__loopback); - - // - result = - // - bearishPressure > 0 && - bullishPressure >= 0 && - bearishPressure > bullishPressure - // - ; - - // - return result; - } - - // - // Decisions ... - - // - bool IsBullishDecision( - double percent = 70 // Percent of Body - ) + // Check Bar Breaked Up ... + bool IsBreakeUp(double value) { // bool result = false; // result = - // - IsValid() && - Index() > 0 && - IsBullish() && - (GetRange() * percent) / 100 <= GetBody() - // - ; - - // - return result; - } - - // - bool IsBearishDecision( - double percent = 70 // Percent of Body - ) - { - // - bool result = false; - - // - result = - // - IsValid() && - Index() > 0 && - IsBearish() && - (GetRange() * percent) / 100 <= GetBody() - // - ; - - // - return result; - } - - // - // Touches ... - - // - bool IsBullishTouched(double price) - { - // - bool result = false; - - // - result = - // - IsValid() - // - && - // - price > 0 - // - ; + value > 0 && + IsValid(); if (!result) { return result; @@ -3039,18 +1875,17 @@ struct XOHCL // result = // - (pBar.low <= price || - pBar.GetDown() <= price) - // - && - // - (pBar.high > price || - pBar.GetUp() > price) - // - && - // - open > price && - low > price + low > value && + ( + // + (pBar.low < value && + pBar.high > value) + // + || + // + (pBar.high < value) + // + ) // ; @@ -3059,21 +1894,16 @@ struct XOHCL } // - bool IsBearishTouched(double price) + // Check Bar Breaked Down ... + bool IsBreakeDown(double value) { // bool result = false; // result = - // - IsValid() - // - && - // - price > 0 - // - ; + value > 0 && + IsValid(); if (!result) { return result; @@ -3090,18 +1920,17 @@ struct XOHCL // result = // - (pBar.high >= price || - pBar.GetUp() >= price) - // - && - // - (pBar.low < price || - pBar.GetDown() < price) - // - && - // - open < price && - high < price + high < value && + ( + // + (pBar.high > value && + pBar.low < value) + // + || + // + (pBar.low > value) + // + ) // ; @@ -3109,2197 +1938,6 @@ struct XOHCL return result; } - // - // Candlestic Patterns ... - - // - // Check Doji ... - bool IsDoji() - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - result = open == close; - - // - return result; - } - - // - // Check Hammer ... - bool IsHammer( - double _upShadowFactor = 0.1, - double _downShadowFactor = 0.6, - bool applyFib382Check = true, - bool applyPrevShadowCheck = true // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - if (_upShadowFactor < 0) - { - _upShadowFactor = 0.1; - } - - // - if (_downShadowFactor < 0) - { - _upShadowFactor = 0.6; - } - - // - double range = GetRange(); - - // - // Check Upper Shadow Must be 0 or Under 10% ... - double upShadow = GetHighShadow(); - result = upShadow < range * _upShadowFactor; - if (!result) - { - return result; - } - - // - // Check Down Shadow Must at least 60% ... - double downShadow = GetLowShadow(); - result = downShadow > range * _downShadowFactor; - if (!result) - { - return result; - } - - // - // Check Fib 382 ... - if (result && applyFib382Check) - { - // - double fib382 = GetFibonacciLevel( - high, - low, - 0.382, - -1 // - ); - result = GetDown() > fib382; - } - - // - // Check Shadow Based on Prev Bar ... - if (result && applyPrevShadowCheck) - { - // - XOHCL pBar; - result = GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - result = low < pBar.low; - } - - // - return result; - } - - // - // Check Sgooting Star ... - // Reversal Hammer ... - bool IsShootingStar( - double _upShadowFactor = 0.6, - double _downShadowFactor = 0.1, - bool applyFib382Check = true, - bool applyPrevShadowCheck = true // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - if (_upShadowFactor < 0) - { - _upShadowFactor = 0.6; - } - - // - if (_downShadowFactor < 0) - { - _upShadowFactor = 0.1; - } - - // - double range = GetRange(); - - // - // Check Upper Shadow Must be 0 or Under 10% ... - double upShadow = GetHighShadow(); - result = upShadow > range * _upShadowFactor; - if (!result) - { - return result; - } - - // - // Check Down Shadow Must at least 60% ... - double downShadow = GetLowShadow(); - result = downShadow < range * _downShadowFactor; - if (!result) - { - return result; - } - - // - // Check Fib 382 ... - if (result && applyFib382Check) - { - // - double fib382 = GetFibonacciLevel( - high, - low, - 0.382, - 1 // - ); - result = GetUp() < fib382; - } - - // - // Check Shadow Based on Prev Bar ... - if (result && applyPrevShadowCheck) - { - // - XOHCL pBar; - result = GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - result = high > pBar.high; - } - - // - return result; - } - - // - // Check Bullish Engulfing ... - bool IsBullishEngulfing( - double _engulfBarBodyFactor = 0.7 // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - if (_engulfBarBodyFactor < 0) - { - _engulfBarBodyFactor = 0.7; - } - - // - // Check Bar Is Bullish ... - result = IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Previous Bar ... - XOHCL pBar; - result = GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - double range = GetRange(); - double body = GetBody(); - - // - // Check Prev Bar Must Bearish ... - result = pBar.IsBearish(); - if (!result) - { - return result; - } - - // - // Check Shadows Engulf Prev Bar ... - result = - // - high > pBar.high && - low <= pBar.low - // - ; - if (!result) - { - return result; - } - - // - // Check Engulfed Bar Must Inside Engulfer Body ... - result = - // - GetUp() > pBar.GetUp() && - GetDown() < pBar.GetDown() - // - ; - if (!result) - { - return result; - } - - // - // Check Body of Engulfing Bar ... - if (result && _engulfBarBodyFactor > 0) - { - result = body >= range * _engulfBarBodyFactor; - } - - // - return result; - } - - // - // Check Bearish Engulfing ... - bool IsBearishEngulfing( - double _engulfBarBodyFactor = 0.7 // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - if (_engulfBarBodyFactor < 0) - { - _engulfBarBodyFactor = 0.7; - } - - // - // Check Bar Is Bearish ... - result = IsBearish(); - if (!result) - { - return result; - } - - // - // Retrieve Previous Bar ... - XOHCL pBar; - result = GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - double range = GetRange(); - double body = GetBody(); - - // - // Check Prev Bar Must Bullish ... - result = pBar.IsBullish(); - if (!result) - { - return result; - } - - // - // Check Shadows Engulf Prev Bar ... - result = high >= pBar.high && low < pBar.low; - if (!result) - { - return result; - } - - // - // Check Engulfed Bar Must Inside Engulfer Body ... - result = - // - GetUp() > pBar.GetUp() && - GetDown() < pBar.GetDown() - // - ; - if (!result) - { - return result; - } - - // - // Check Body of Engulfing Bar ... - if (result && _engulfBarBodyFactor > 0) - { - result = body >= range * _engulfBarBodyFactor; - } - - // - return result; - } - - // - // Check Morning Star Pattern ... - bool IsMorningStar( - double _middleRangeFactor = 0.3, - double _startBodyFactor = 0.6, - bool forceCheckMiddleBarDirection = true, - bool forceCheckStartBody = true // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - if (_middleRangeFactor < 0) - { - _middleRangeFactor = 0.3; - } - - // - if (_startBodyFactor < 0) - { - _startBodyFactor = 0.6; - } - - // - // Current Bar Must be Bullish ... - result = IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Previous Bar ... - XOHCL pBar; - result = GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Prev Bar must be Bearish ... - if (result && forceCheckMiddleBarDirection) - { - // - result = pBar.IsBearish(); - if (!result) - { - return result; - } - } - - // - // Retrieve Previous Bar of Prev Bar ... - XOHCL ppBar; - result = pBar.GetPreviousBar(ppBar); - if (!result) - { - return result; - } - - // - // Prev Of Prev Bar Must be Bearish ... - result = ppBar.IsBearish(); - if (!result) - { - return result; - } - - // - double range = GetRange(); - double pRange = pBar.GetRange(); - double ppRange = ppBar.GetRange(); - - // - // Middle Bar must be Smaller than Ratio of other ... - result = - // - pRange < range * _middleRangeFactor && - pRange < ppRange * _middleRangeFactor - // - ; - if (!result) - { - return result; - } - - // - if (result && forceCheckStartBody) - { - // - result = ppBar.GetBody() > ppRange * _startBodyFactor; - if (!result) - { - return result; - } - } - - // - return result; - } - - // - // Check Evening Star Pattern ... - bool IsEveningStar( - double _middleRangeFactor = 0.3, - double _startBodyFactor = 0.6, - bool forceCheckMiddleBarDirection = true, - bool forceCheckStartBody = true // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - if (_middleRangeFactor < 0) - { - _middleRangeFactor = 0.3; - } - - // - if (_startBodyFactor < 0) - { - _startBodyFactor = 0.6; - } - - // - // Current Bar Must be Bearish ... - result = IsBearish(); - if (!result) - { - return result; - } - - // - // Retrieve Previous Bar ... - XOHCL pBar; - result = GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Prev Bar must be Bullish ... - if (result && forceCheckMiddleBarDirection) - { - // - result = pBar.IsBullish(); - if (!result) - { - return result; - } - } - - // - // Retrieve Previous Bar of Prev Bar ... - XOHCL ppBar; - result = pBar.GetPreviousBar(ppBar); - if (!result) - { - return result; - } - - // - // Prev Of Prev Bar Must be Bullish ... - result = ppBar.IsBullish(); - if (!result) - { - return result; - } - - // - double range = GetRange(); - double pRange = pBar.GetRange(); - double ppRange = ppBar.GetRange(); - - // - // Middle Bar must be Smaller than Ratio of other ... - result = - // - pRange < range * _middleRangeFactor && - pRange < ppRange * _middleRangeFactor - // - ; - if (!result) - { - return result; - } - - // - if (result && forceCheckStartBody) - { - // - result = ppBar.GetBody() > ppRange * _startBodyFactor; - if (!result) - { - return result; - } - } - - // - return result; - } - - // - // Bullish Marubozu ... - bool IsBullishMarubozu() - { - // - bool result = false; - - // - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - result = IsBullish(); - if (!result) - { - return result; - } - - // - result = - // - GetUp() == high && - GetDown() == low - // - ; - - // - return result; - } - - // - // Bearish Marubozu ... - bool IsBearishMarubozu() - { - // - bool result = false; - - // - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - result = IsBearish(); - if (!result) - { - return result; - } - - // - result = - // - GetUp() == high && - GetDown() == low - // - ; - - // - return result; - } - - // - // Contextual Patterns ... - - // - // Check Swing High ... - bool IsSwingHigh() - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - // Current Bar Must be Bearish ... - result = IsBearish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev Bar ... - XOHCL pBar; - result = GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Prev Bar Must be Bullish ... - result = pBar.IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev of Prev Bar ... - XOHCL ppBar; - result = pBar.GetPreviousBar(ppBar); - if (!result) - { - return result; - } - - // - // Prev of Prev Bar Must be Bullish ... - result = ppBar.IsBullish(); - if (!result) - { - return result; - } - - // - // Check All Highs ... - result = - // - high < pBar.high && - pBar.high > ppBar.high - // - ; - - // - return result; - } - - // - // Find Simple 3 Candle Based Swing High ... - bool IsSimpleSwingHigh(double thresholdInPoint = 1) - { - // - bool result = false; - - // - int index = Index(); - result = index > 0; - if (!result) - { - return result; - } - - // - XOHCL nextBar; - result = GetNextBar(nextBar); - if (!result) - { - return result; - } - - // - XOHCL prevBar; - result = GetPreviousBar(prevBar); - if (!result) - { - return result; - } - - // - double point = GetPoints(symbol); - double requiredOffset = point * thresholdInPoint; - - // - result = - high > nextBar.high && - high > prevBar.high && - (thresholdInPoint <= 0 - ? true - : MathAbs( - MathMax( - nextBar.high, - prevBar.high) - - high) >= requiredOffset); - - // - return result; - } - - // - // Find Last Swing High ... - bool FindLastSwingHigh(XOHCL &swing) - { - // - bool result = false; - - // - swing.Clean(); - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - int totalBars = iBars( - symbol, - period // - ); - int maxAllowed = MathMin(100, (totalBars / 100)); - - // - int idx = Index(); - for (int i = idx; i <= idx + maxAllowed; i++) - { - // - swing.Clean(); - result = swing.Init( - symbol, - period, - i // - ); - if (!result) - { - // - swing.Clean(); - break; - } - - // - result = swing.IsSwingHigh(); - if (result) - { - break; - } - } - - // - return result; - } - - // - // Check Swing Low ... - bool IsSwingLow() - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - // Current Bar Must be Bullish ... - result = IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev Bar ... - XOHCL pBar; - result = GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Prev Bar Must be Bearish ... - result = pBar.IsBearish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev of Prev Bar ... - XOHCL ppBar; - result = pBar.GetPreviousBar(ppBar); - if (!result) - { - return result; - } - - // - // Prev of Prev Bar Must be Bearish ... - result = ppBar.IsBearish(); - if (!result) - { - return result; - } - - // - // Check All Lows ... - result = - // - low > pBar.low && - pBar.low < ppBar.low - // - ; - - // - return result; - } - - // - // Find Simple 3 Candle Based Swing Low ... - bool IsSimpleSwingLow(double thresholdInPoint = 1) - { - // - bool result = false; - - // - int index = Index(); - result = index > 0; - if (!result) - { - return result; - } - - // - XOHCL nextBar; - result = GetNextBar(nextBar); - if (!result) - { - return result; - } - - // - XOHCL prevBar; - result = GetPreviousBar(prevBar); - if (!result) - { - return result; - } - - // - double point = GetPoints(symbol); - double requiredOffset = point * thresholdInPoint; - - // - result = - low < nextBar.low && - low < prevBar.low && - (thresholdInPoint <= 0 - ? true - : MathAbs( - MathMax( - nextBar.low, - prevBar.low) - - low) >= requiredOffset); - - // - return result; - } - - // - // Find Last Swing Low ... - bool FindLastSwingLow(XOHCL &swing) - { - // - bool result = false; - - // - swing.Clean(); - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - int totalBars = iBars( - symbol, - period // - ); - int maxAllowed = MathMin(100, (totalBars / 100)); - - // - int idx = Index(); - for (int i = idx; i <= idx + maxAllowed; i++) - { - // - swing.Clean(); - result = swing.Init( - symbol, - period, - i // - ); - if (!result) - { - // - swing.Clean(); - break; - } - - // - result = swing.IsSwingLow(); - if (result) - { - break; - } - } - - // - return result; - } - - // - // Check Bullish FVG ... - bool HasBullishFVG( - double &upper, - double &lower, - datetime &start, - datetime &end, - bool forceMiddleBarCheck = true, - bool forceCheckLastBarDirection = false // - ) - { - // - bool result = false; - - // - upper = 0; - lower = 0; - - // - end = NULL; - start = NULL; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - // Current Bar Must be Bullish ... - result = - !forceCheckLastBarDirection - ? true - : IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev Bar ... - XOHCL pBar; - result = GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Prev Bar Must be Bullish ... - result = pBar.IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev of Prev Bar ... - XOHCL ppBar; - result = pBar.GetPreviousBar(ppBar); - if (!result) - { - return result; - } - - // - // Prev of Prev Bar Must be Bullish ... - result = ppBar.IsBullish(); - if (!result) - { - return result; - } - - // - // Other Conditions ... - result = - // - low > ppBar.high - // - ; - - // - // Check Middle Bar Range ... - if (result && forceMiddleBarCheck) - { - // - result = - // - pBar.high > low && - pBar.low < ppBar.high - // - ; - - // - if (!result) - { - return result; - } - } - - // - if (result) - { - // - end = time; - upper = low; - lower = ppBar.high; - start = ppBar.time; - } - - // - return result; - } - - // - // Check Bearish FVG ... - bool HasBearishFVG( - double &upper, - double &lower, - datetime &start, - datetime &end, - bool forceMiddleBarCheck = true, - bool forceCheckLastBarDirection = false // - ) - { - // - bool result = false; - - // - upper = 0; - lower = 0; - - // - end = NULL; - start = NULL; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = IsValid() && Index() > 0; - if (!result) - { - return result; - } - - // - // Current Bar Must be Bearish ... - result = - !forceCheckLastBarDirection - ? true - : IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev Bar ... - XOHCL pBar; - result = GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Prev Bar Must be Bearish ... - result = pBar.IsBearish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev of Prev Bar ... - XOHCL ppBar; - result = pBar.GetPreviousBar(ppBar); - if (!result) - { - return result; - } - - // - // Prev of Prev Bar Must be Bearish ... - result = ppBar.IsBearish(); - if (!result) - { - return result; - } - - // - // Other Conditions ... - result = - // - high < ppBar.low - // - ; - - // - // Check Middle Bar Range ... - if (result && forceMiddleBarCheck) - { - // - result = - // - pBar.high > low && - pBar.low < ppBar.high - // - ; - - // - if (!result) - { - return result; - } - } - - // - if (result) - { - // - end = time; - lower = high; - upper = ppBar.low; - start = ppBar.time; - } - - // - return result; - } - - // - // Find Support ... - bool HasSupport( - XOHCL &bar, - ENUM_X_PRICE type = X_PRICE_CLOSE, - int _loopback = 21, - int tries = 100 // - ) - { - // - bool result = false; - - // - bar.Clean(); - - // - if (_loopback < 0) - { - _loopback = 21; - } - - // - if (tries < 0) - { - tries = 100; - } - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - double price = GetPrice(type); - - // - for (int i = 1; i < tries; i++) - { - // - int _length = _loopback * i; - - // - int lowestIDX = FindLowestIndex( - _length, - MODE_LOW // - ); - result = IsValidSize(lowestIDX); - if (!result) - { - break; - } - - // - XOHCL iLBar; - result = iLBar.Init( - symbol, - period, - lowestIDX // - ); - if (!result) - { - break; - } - - // - result = - // - price > iLBar.high - // - ; - if (result) - { - // - bar = iLBar; - break; - } - } - - // - return result; - } - - // - // Find Resistance ... - bool HasResistance( - XOHCL &bar, - ENUM_X_PRICE type = X_PRICE_CLOSE, - int _loopback = 21, - int tries = 100 // - ) - { - // - bool result = false; - - // - bar.Clean(); - - // - if (_loopback < 0) - { - _loopback = 21; - } - - // - if (tries < 0) - { - tries = 100; - } - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - double price = GetPrice(type); - - // - for (int i = 1; i < tries; i++) - { - // - int _length = _loopback * i; - - // - int highestIDX = FindHighestIndex( - _length, - MODE_LOW // - ); - result = IsValidSize(highestIDX); - if (!result) - { - break; - } - - // - XOHCL iHBar; - result = iHBar.Init( - symbol, - period, - highestIDX // - ); - if (!result) - { - break; - } - - // - result = - // - price < iHBar.high - // - ; - if (result) - { - // - bar = iHBar; - break; - } - } - - // - return result; - } - - // - // Trend Detection ... - - // - // Find Bullish Trend ... - bool HasBullishTrend( - XOHCL &highSwingBars[], - XOHCL &lowSwingBars[], - bool forceMethod2 = false, - int _loopback = 3, - int tries = 3, - ENUM_X_PRICE type = X_PRICE_CLOSE // - ) - { - // - bool result = false; - - // - Clean(lowSwingBars); - Clean(highSwingBars); - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - double price = GetPrice(type); - - // - int lastIDX = Index(); - double lastH = 0; - double lastL = 0; - for (int i = 1; i < tries + 1; i++) - { - // - // Use Regular Method ... - if (!forceMethod2) - { - // - int iHIDX = FindSwing( - symbol, - period, - X_SWING_HIGH, - _loopback, - lastIDX // - ); - result = IsValidIndex(iHIDX); - if (!result) - { - break; - } - - // - XOHCL iHBar; - result = iHBar.Init( - symbol, - period, - iHIDX // - ); - if (!result) - { - break; - } - - // - double iH = iHBar.high; - bool isIHAccepted = - // - iH > 0 && - ( - // - lastH == 0 - ? true - : iH < lastH - // - ) - // - ; - if (isIHAccepted) - { - // - AddRef( - iHBar, - highSwingBars // - ); - - // - lastH = iH; - lastIDX = iHIDX; - } - - // - int iLIDX = FindSwing( - symbol, - period, - X_SWING_LOW, - _loopback, - lastIDX // - ); - result = IsValidIndex(iLIDX); - if (!result) - { - break; - } - - // - XOHCL iLBar; - result = iLBar.Init( - symbol, - period, - iLIDX // - ); - if (!result) - { - break; - } - - // - double iL = iLBar.low; - bool isILAccepted = - // - iL > 0 && - ( - // - lastL == 0 - ? true - : iL < lastL - // - ) - // - ; - if (isILAccepted) - { - // - AddRef( - iLBar, - lowSwingBars // - ); - - // - lastL = iL; - lastIDX = iLIDX; - } - } - // - // Use Other MEthod ... - else - { - // - int _length = i * _loopback; - int start = - // - i == 1 - ? 1 - : _length - _loopback - // - ; - - // - int iHIDX = iHighest( - symbol, - period, - MODE_HIGH, - _loopback, - start // - ); - result = IsValidIndex(iHIDX); - if (!result) - { - break; - } - - // - XOHCL iHBar; - result = iHBar.Init( - symbol, - period, - iHIDX // - ); - if (!result) - { - break; - } - - // - double iH = iHBar.high; - bool isIHAccepted = - // - iH > 0 && - ( - // - lastH == 0 - ? true - : iH < lastH - // - ) - // - ; - if (isIHAccepted) - { - // - AddRef( - iHBar, - highSwingBars // - ); - - // - lastH = iH; - lastIDX = iHIDX; - } - - // - int iLIDX = iLowest( - symbol, - period, - MODE_LOW, - _loopback, - start // - ); - result = IsValidIndex(iLIDX); - if (!result) - { - break; - } - - // - XOHCL iLBar; - result = iLBar.Init( - symbol, - period, - iLIDX // - ); - if (!result) - { - break; - } - - // - double iL = iLBar.low; - bool isILAccepted = - // - iL > 0 && - ( - // - lastL == 0 - ? true - : iL < lastL - // - ) - // - ; - if (isILAccepted) - { - // - AddRef( - iLBar, - lowSwingBars // - ); - - // - lastL = iL; - lastIDX = iLIDX; - } - } - } - - // - if (result) - { - // - result = - // - ArraySize(lowSwingBars) == tries && - ArraySize(highSwingBars) == tries - // - ; - } - - // - if (!result) - { - // - Clean(lowSwingBars); - Clean(highSwingBars); - } - - // - return result; - } - - // - // Find Bearish Trend ... - bool HasBearishTrend( - XOHCL &highSwingBars[], - XOHCL &lowSwingBars[], - bool forceMethod2 = false, - int _loopback = 3, - int tries = 3, - ENUM_X_PRICE type = X_PRICE_CLOSE // - ) - { - // - bool result = false; - - // - Clean(lowSwingBars); - Clean(highSwingBars); - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - double price = GetPrice(type); - - // - int lastIDX = Index(); - double lastH = 0; - double lastL = 0; - for (int i = 1; i < tries + 1; i++) - { - // - // Use Regular Method ... - if (!forceMethod2) - { - // - int iHIDX = FindSwing( - symbol, - period, - X_SWING_HIGH, - _loopback, - lastIDX // - ); - result = IsValidIndex(iHIDX); - if (!result) - { - break; - } - - // - XOHCL iHBar; - result = iHBar.Init( - symbol, - period, - iHIDX // - ); - if (!result) - { - break; - } - - // - double iH = iHBar.high; - bool isIHAccepted = - // - iH > 0 && - ( - // - lastH == 0 - ? true - : iH > lastH - // - ) - // - ; - if (isIHAccepted) - { - // - AddRef( - iHBar, - highSwingBars // - ); - - // - lastH = iH; - lastIDX = iHIDX; - } - - // - int iLIDX = FindSwing( - symbol, - period, - X_SWING_LOW, - _loopback, - lastIDX // - ); - result = IsValidIndex(iLIDX); - if (!result) - { - break; - } - - // - XOHCL iLBar; - result = iLBar.Init( - symbol, - period, - iLIDX // - ); - if (!result) - { - break; - } - - // - double iL = iLBar.low; - bool isILAccepted = - // - iL > 0 && - ( - // - lastL == 0 - ? true - : iL > lastL - // - ) - // - ; - if (isILAccepted) - { - // - AddRef( - iLBar, - lowSwingBars // - ); - - // - lastL = iL; - lastIDX = iLIDX; - } - } - // - // Use Other MEthod ... - else - { - // - int _length = i * _loopback; - int start = - // - i == 1 - ? 1 - : _length - _loopback - // - ; - - // - int iHIDX = iHighest( - symbol, - period, - MODE_HIGH, - _loopback, - start // - ); - result = IsValidIndex(iHIDX); - if (!result) - { - break; - } - - // - XOHCL iHBar; - result = iHBar.Init( - symbol, - period, - iHIDX // - ); - if (!result) - { - break; - } - - // - double iH = iHBar.high; - bool isIHAccepted = - // - iH > 0 && - ( - // - lastH == 0 - ? true - : iH > lastH - // - ) - // - ; - if (isIHAccepted) - { - // - AddRef( - iHBar, - highSwingBars // - ); - - // - lastH = iH; - lastIDX = iHIDX; - } - - // - int iLIDX = iLowest( - symbol, - period, - MODE_LOW, - _loopback, - start // - ); - result = IsValidIndex(iLIDX); - if (!result) - { - break; - } - - // - XOHCL iLBar; - result = iLBar.Init( - symbol, - period, - iLIDX // - ); - if (!result) - { - break; - } - - // - double iL = iLBar.low; - bool isILAccepted = - // - iL > 0 && - ( - // - lastL == 0 - ? true - : iL > lastL - // - ) - // - ; - if (isILAccepted) - { - // - AddRef( - iLBar, - lowSwingBars // - ); - - // - lastL = iL; - lastIDX = iLIDX; - } - } - } - - // - if (result) - { - // - result = - // - ArraySize(lowSwingBars) == tries && - ArraySize(highSwingBars) == tries - // - ; - } - - // - if (!result) - { - // - Clean(lowSwingBars); - Clean(highSwingBars); - } - - // - return result; - } - - // - // Order Blocks ... - - // - // Find Bullish Order Block ... - bool HasBullishOrderBlock( - XOHCL &orderBlock, - int _minimumSameBars = 4 // - ) - { - // - bool result = false; - - // - orderBlock.Clean(); - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - if (_minimumSameBars < 0) - { - _minimumSameBars = 4; - } - - // - XOHCL cBar; - int founded = 0; - int cIDX = Index(); - bool isEnough = false; - while (!isEnough) - { - // - result = cBar.Init( - symbol, - period, - cIDX // - ); - if (!result) - { - break; - } - - // - result = cBar.IsBullish(); - if (!result && cBar.IsBearish()) - { - break; - } - - // - cIDX++; - founded++; - } - - // - // Here we have to check founded and if it's fill - // our requirements ... - // cIDX is Order Block Index ... - result = - // - cBar.IsValid() && - high > cBar.high && - founded >= _minimumSameBars - // - ; - if (!result) - { - return result; - } - - // - result = orderBlock.Init( - symbol, - period, - cIDX // - ); - if (!result) - { - // - orderBlock.Clean(); - return result; - } - - // - return result; - } - - // - // Find Bearish Order Block ... - bool HasBearishOrderBlock( - XOHCL &orderBlock, - int _minimumSameBars = 4 // - ) - { - // - bool result = false; - - // - orderBlock.Clean(); - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - if (_minimumSameBars < 0) - { - _minimumSameBars = 4; - } - - // - XOHCL cBar; - int founded = 0; - int cIDX = Index(); - bool isEnough = false; - while (!isEnough) - { - // - bool isInited = cBar.Init( - symbol, - period, - cIDX // - ); - - // - result = cBar.IsBearish(); - if (!result && cBar.IsBullish()) - { - break; - } - - // - cIDX++; - founded++; - } - - // - // Here we have to check founded and if it's fill - // our requirements ... - // cIDX is Order Block Index ... - result = - // - cBar.IsValid() && - high < cBar.low && - founded >= _minimumSameBars - // - ; - if (!result) - { - return result; - } - - // - result = orderBlock.Init( - symbol, - period, - cIDX // - ); - if (!result) - { - // - orderBlock.Clean(); - return result; - } - - // - return result; - } - - // - // Order Blocks ... - - // - // Supply and Demand ... - // // Other ... string GetTag(string prefix = "") @@ -5334,220 +1972,6 @@ struct XOHCL } }; -// -struct XTrend -{ - // - string symbol; - ENUM_TIMEFRAMES period; - - // - datetime at; - - // - XOHCL swingHighs[]; - XOHCL swingLows[]; - - // - bool isBullish; - bool isBearish; - - // - void XTrend() - { - Clean(); - } - - // - // Tools ... - - /** - * Initialize ... - * - * @param _symbol: String ... - * @param _period: ENUM_TIMEFRAMES member ... - * - * @return ( bool ) - */ - bool Init( - string _symbol, - ENUM_TIMEFRAMES _period = NULL // - ) - { - // - bool result = false; - - // - NormalizePeriod(_period); - - // - result = IsValid(_symbol) && - IsValid(_period); - if (!result) - { - return result; - } - - // - symbol = _symbol; - period = _period; - - // - XOHCL bar; - result = bar.Init( - symbol, - period, - 0 // - ); - if (!result) - { - return result; - } - - // - XOHCL tmpBULLSWH[]; - XOHCL tmpBULLSWL[]; - bool hasBullishTrend = bar.HasBullishTrend( - tmpBULLSWH, - tmpBULLSWL, - true // - ); - - // - XOHCL tmpBEARSWH[]; - XOHCL tmpBEARSWL[]; - bool hasBearishTrend = bar.HasBearishTrend( - tmpBEARSWH, - tmpBEARSWL, - true // - ); - - // - if (hasBullishTrend) - { - // - Copy( - tmpBULLSWH, - swingHighs // - ); - - // - Copy( - tmpBULLSWL, - swingLows // - ); - } - // - else if (hasBearishTrend) - { - // - Copy( - tmpBEARSWH, - swingHighs // - ); - - // - Copy( - tmpBEARSWL, - swingLows // - ); - } - - // - if (hasBullishTrend || - hasBullishTrend) - { - at = TimeCurrent(); - } - - // - result = IsValid(); - - // - return result; - } - - /** - * Clean ... - */ - void Clean() - { - // - symbol = NULL; - period = NULL; - at = NULL; - - // - isBullish = false; - isBearish = false; - - // - Clean(swingLows); - Clean(swingHighs); - } - - /** - * Validate ... - * - * @return ( bool ) - */ - bool IsValid() - { - // - bool result = false; - - // - result = - IsValid(symbol) && - IsValid(period) && - IsValid(at) && - (isBullish || - isBearish) && - (ArraySize(swingHighs) > 0 || - ArraySize(swingLows) > 0); - - // - return result; - } - - /** - * Generate Unique Identifier ... - * - * @return ( string ) - */ - string GetTag() - { - // - string result = NULL; - - // - if (!IsValid()) - { - return result; - } - - // - string hash = symbol + "," + ToString(period) + "," + ToFormatString(at); - hash = ToMD5(hash); - - // - result = - // - "XTrend_" + - (isBullish ? "Bullish_" : "Bearish_") + - symbol + "_" + - ToString(period) + "_" + - hash - // - ; - - // - return result; - } - - // -}; - // // Tracking Times ... struct XTimeTracker diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index 14b36a25..0f54ba18 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -4972,6 +4972,457 @@ struct XValueChange // }; +// +// Price Zones Model ... +struct XPriceZones +{ + // + XOHCL bar; // if Based On Bar it's Filled ... + double price; // if Based on Price, it's Filled ... + + // + int count; // Exists Zones Count ... + + // + XCFVG *fairValueGap; // Exists Fair Value Gap ... + XCSupplyZone *supplyZone; // Exists Supply Zone ... + XCDemandZone *demandZone; // Exists Demand Zone ... + XCOrderBlock *orderBlock; // Exists Order Block ... + XCSupportZone *supportZone; // Exists Support Zone ... + XCResistanceZone *resistanceZone; // Exists Resistance Zone ...ّ + + // + // Constructor ... + XPriceZones() + { + Clean(); + } + + /** + * Cleanup ... + */ + void Clean() + { + // + bar.Clean(); + price = 0; + + // + supplyZone = NULL; + demandZone = NULL; + orderBlock = NULL; + supportZone = NULL; + fairValueGap = NULL; + resistanceZone = NULL; + } + + /** + * Check Zone is Valid ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + (IsBasedOnBar() || + IsBasedOnPrice()) && + IsValidSize(count) + // + ; + + // + return result; + } + + /** + * Check Zones Base on Bar ... + * + * @return ( bool ) + */ + bool IsBasedOnBar() + { + return bar.IsValid(); + } + + /** + * Check Zones Based on Price ... + * + * @return ( bool ) + */ + bool IsBasedOnPrice() + { + return price > 0; + } + + /** + * Check Has Supply Zone ... + * + * @return ( bool ) + */ + bool HasSupplyZone() + { + // + return IsValidSize(count) && + supplyZone != NULL && + supplyZone.IsValid(); + } + + /** + * Check Has Demand Zone ... + * + * @return ( bool ) + */ + bool HasDemandZone() + { + // + return IsValidSize(count) && + demandZone != NULL && + demandZone.IsValid(); + } + + /** + * Check Has OrderBlock ... + * + * @return ( bool ) + */ + bool HasOrderBlock() + { + // + return IsValidSize(count) && + orderBlock != NULL && + orderBlock.IsValid(); + } + + /** + * Check Has Support Zone ... + * + * @return ( bool ) + */ + bool HasSupportZone() + { + // + return IsValidSize(count) && + supportZone != NULL && + supportZone.IsValid(); + } + + /** + * Check Has FairValueGap ... + * + * @return ( bool ) + */ + bool HasFairValueGap() + { + // + return IsValidSize(count) && + fairValueGap != NULL && + fairValueGap.IsValid(); + } + + /** + * Check Has Resistance Zone ... + * + * @return ( bool ) + */ + bool HasResistanceZone() + { + // + return IsValidSize(count) && + resistanceZone != NULL && + resistanceZone.IsValid(); + } + + /** + * Check Zones are Overal Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = + // + HasDemandZone() + // + || + // + HasSupportZone() + // + || + // + (HasOrderBlock() && + orderBlock.IsBullish()) + // + || + // + (HasFairValueGap() && + fairValueGap.IsBullish()) + // + ; + + // + return result; + } + + /** + * Check Zones are Overal Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = + // + HasSupplyZone() + // + || + // + HasResistanceZone() + // + || + // + (HasOrderBlock() && + orderBlock.IsBearish()) + // + || + // + (HasFairValueGap() && + fairValueGap.IsBearish()) + // + ; + + // + return result; + } + + /** + * Fill Zones Based On required Direction ... + * + * @param dir: ENUM_X_DIRECTION member ... + * + * @return ( int ) + */ + int FillZones( + ENUM_X_DIRECTION dir, + XCZone *&zones[] // + ) + { + // + int result = 0; + + // + Clean(zones); + + // + if (dir == X_DIRECTION_NONE) + { + return result; + } + + // + bool isBullish = IsBullish(dir); + bool isBoth = dir == X_DIRECTION_ALL; + + // + if (isBoth || isBullish) + { + // + if (HasSupportZone()) + { + // + Add( + (XCZone *)supportZone, + zones // + ); + } + + // + if (HasDemandZone()) + { + // + Add( + (XCZone *)demandZone, + zones // + ); + } + + // + if (HasOrderBlock() && + orderBlock.IsBullish()) + { + // + Add( + (XCZone *)orderBlock, + zones // + ); + } + + // + if (HasFairValueGap() && + fairValueGap.IsBullish()) + { + // + Add( + (XCZone *)fairValueGap, + zones // + ); + } + } + + // + if (isBoth || !isBullish) + { + // + if (HasResistanceZone()) + { + // + Add( + (XCZone *)resistanceZone, + zones // + ); + } + + // + if (HasSupplyZone()) + { + // + Add( + (XCZone *)supplyZone, + zones // + ); + } + + // + if (HasOrderBlock() && + orderBlock.IsBearish()) + { + // + Add( + (XCZone *)orderBlock, + zones // + ); + } + + // + if (HasFairValueGap() && + fairValueGap.IsBearish()) + { + // + Add( + (XCZone *)fairValueGap, + zones // + ); + } + } + + // s + result = ArraySize(zones); + + // + return result; + } + + /** + * Calculate Boundary of Zones ... + * + * @param dir: ENUM_X_DIRECTION Member, Specified Direction ... + * @param upper: Double ... + * @param lower: Double ... + * + * @return ( bool ) + */ + bool GetBoundary( + ENUM_X_DIRECTION dir, + double &upper, + double &lower // + ) + { + // + bool result = false; + + // + upper = 0; + lower = 0; + + // + XCZone *zones[]; + int mCount = FillZones(dir, zones); + result = IsValidSize(mCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < mCount; i++) + { + // + XCZone *iZone = zones[i]; + + // + double iUpper = iZone.Upper(); + double iLower = iZone.Lower(); + + // + upper = + upper == 0 + ? iUpper + : iUpper > upper + ? iUpper + : upper; + + // + lower = + lower == 0 + ? iLower + : iLower < lower + ? iLower + : lower; + } + + // + return result; + } + + // +}; + +struct XMarketStructure +{ + // + string symbol; + ENUM_TIMEFRAMES period; + + // + ENUM_X_DIRECTION bias; + + // + XPVPivotPoint vales[]; + XPVPivotPoint peaks[]; + + // + XOHCL lowestValeBar; + XOHCL lowestValePeakBreakeUpBar; + XOHCL valeAboveLowestValePeakBar; + + // + XOHCL highestPeakBar; + XOHCL peakBelowHighestPeakValeBar; + XOHCL highestPeakValeBreakeDownBar; +}; + // // Extensions ... @@ -6495,6 +6946,448 @@ bool DetectPriceInsideZones( return result; } +/** + * Detect Price Inside Zones ... + * + * @param state: XPOIState instance Reference ... + * @param price: Double ... + * @param hasSupport: Boolean ... + * @param hasResistanceZone: Boolean ... + * @param hasSupplyZone: Boolean ... + * @param hasDemandZone: Boolean ... + * @param hasOrderBlock: Boolean ... + * @param hasFairValueGap: Boolean ... + * @return ( bool ) + */ +bool DetectPriceInsideZones( + XPOIState &state, + double price, + int &zonesCount, + bool &hasSupportZone, + XCSupportZone *&supportZone, + bool &hasResistanceZone, + XCResistanceZone *&resistanceZone, + bool &hasSupplyZone, + XCSupplyZone *&supplyZone, + bool &hasDemandZone, + XCDemandZone *&demandZone, + bool &hasOrderBlock, + XCOrderBlock *&orderBlock, + bool &hasFairValueGap, + XCFVG *&fairValueGap // +) +{ + // + bool result = false; + + // + zonesCount = 0; + + // + hasSupportZone = false; + hasResistanceZone = false; + hasSupplyZone = false; + hasDemandZone = false; + hasOrderBlock = false; + hasFairValueGap = false; + + // + supportZone = NULL; + resistanceZone = NULL; + supplyZone = NULL; + demandZone = NULL; + orderBlock = NULL; + fairValueGap = NULL; + + // + datetime cTime = TimeCurrent(); + + // + result = price > 0 && + state.IsValid() && + state.HasChild(); + if (!result) + { + return result; + } + + // + int count = 0; + + // + // Support Zone ... + count = state.CountSupportZones(); + if (IsValidSize(count)) + { + // + for (int i = count - 1; i >= 0; i--) + { + // + XCSupportZone *iZone = state.supportZones[i]; + + // + bool isValid = IsPriceInsideZone(price, iZone); + if (isValid) + { + // + supportZone = iZone; + } + } + + // + hasSupportZone = supportZone != NULL && + supportZone.IsValid(); + if (hasSupportZone) + { + // + zonesCount++; + supportZone.To(cTime); + } + } + + // + // Resistance Zone ... + count = state.CountResistanceZones(); + if (IsValidSize(count)) + { + // + for (int i = count - 1; i >= 0; i--) + { + // + XCResistanceZone *iZone = state.resistanceZones[i]; + + // + bool isValid = IsPriceInsideZone(price, iZone); + if (isValid) + { + // + resistanceZone = iZone; + } + } + + // + hasResistanceZone = resistanceZone != NULL && + resistanceZone.IsValid(); + if (hasResistanceZone) + { + // + zonesCount++; + resistanceZone.To(cTime); + } + } + + // + // Supply Zone ... + count = state.CountSupplyZones(); + if (IsValidSize(count)) + { + // + for (int i = count - 1; i >= 0; i--) + { + // + XCSupplyZone *iZone = state.supplyZones[i]; + + // + bool isValid = IsPriceInsideZone(price, iZone); + if (isValid) + { + // + supplyZone = iZone; + } + } + + // + hasSupplyZone = supplyZone != NULL && + supplyZone.IsValid(); + if (hasSupplyZone) + { + // + zonesCount++; + supplyZone.To(cTime); + } + } + + // + // Demand Zone ... + count = state.CountDemandZones(); + if (IsValidSize(count)) + { + // + for (int i = count - 1; i >= 0; i--) + { + // + XCDemandZone *iZone = state.demandZones[i]; + + // + bool isValid = IsPriceInsideZone(price, iZone); + if (isValid) + { + // + demandZone = iZone; + } + } + + // + hasDemandZone = demandZone != NULL && + demandZone.IsValid(); + if (hasDemandZone) + { + // + zonesCount++; + demandZone.To(cTime); + } + } + + // + // OrderBlock ... + count = state.CountBullishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = count - 1; i >= 0; i--) + { + // + XCOrderBlock *iZone = state.bullishOrderBlocks[i]; + + // + bool isValid = IsPriceInsideZone(price, iZone); + if (isValid) + { + // + orderBlock = iZone; + } + } + + // + hasOrderBlock = orderBlock != NULL && + orderBlock.IsValid(); + if (hasOrderBlock) + { + // + zonesCount++; + orderBlock.To(cTime); + } + } + if (!hasOrderBlock) + { + // + count = state.CountBearishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = count - 1; i >= 0; i--) + { + // + XCOrderBlock *iZone = state.bearishOrderBlocks[i]; + + // + bool isValid = IsPriceInsideZone(price, iZone); + if (isValid) + { + // + orderBlock = iZone; + } + } + + // + hasOrderBlock = orderBlock != NULL && + orderBlock.IsValid(); + if (hasOrderBlock) + { + // + zonesCount++; + orderBlock.To(cTime); + } + } + } + + // + // Fair Value Gap ... + count = state.CountBullishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = count - 1; i >= 0; i--) + { + // + XCFVG *iZone = state.bullishFairValueGaps[i]; + + // + bool isValid = IsPriceInsideZone(price, iZone); + if (isValid) + { + // + fairValueGap = iZone; + } + } + + // + hasFairValueGap = fairValueGap != NULL && + fairValueGap.IsValid(); + if (hasFairValueGap) + { + // + zonesCount++; + fairValueGap.To(cTime); + } + } + if (!hasFairValueGap) + { + // + count = state.CountBearishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = count - 1; i >= 0; i--) + { + // + XCFVG *iZone = state.bearishFairValueGaps[i]; + + // + bool isValid = IsPriceInsideZone(price, iZone); + if (isValid) + { + // + fairValueGap = iZone; + } + } + + // + hasFairValueGap = fairValueGap != NULL && + fairValueGap.IsValid(); + if (hasFairValueGap) + { + // + zonesCount++; + fairValueGap.To(cTime); + } + } + } + + // + result = + // + hasSupportZone || + hasResistanceZone || + hasSupplyZone || + hasDemandZone || + hasOrderBlock || + hasFairValueGap + // + ; + + // + return result; +} + +bool CalculatePriceInsideZones( + XPriceZones &zone, + XPOIState &state, + double price // +) +{ + // + bool result = false; + + // + zone.Clean(); + + // + int zonesCount = 0; + bool hasSupplyZone = false; + bool hasDemandZone = false; + bool hasOrderBlock = false; + bool hasSupportZone = false; + bool hasFairValueGap = false; + bool hasResistanceZone = false; + + // + result = DetectPriceInsideZones( + state, + price, + zone.count, + hasSupportZone, + zone.supportZone, + hasResistanceZone, + zone.resistanceZone, + hasSupplyZone, + zone.supplyZone, + hasDemandZone, + zone.demandZone, + hasOrderBlock, + zone.orderBlock, + hasFairValueGap, + zone.fairValueGap // + ); + if (!result) + { + return result; + } + + // + zone.price = price; + + // + result = zone.IsValid(); + + // + return result; +} + +bool CalculatePriceInsideZones( + XPriceZones &zone, + XPOIState &state, + XOHCL &bar // +) +{ + // + bool result = false; + + // + zone.Clean(); + + // + int zonesCount = 0; + bool hasSupplyZone = false; + bool hasDemandZone = false; + bool hasOrderBlock = false; + bool hasSupportZone = false; + bool hasFairValueGap = false; + bool hasResistanceZone = false; + + // + result = DetectPriceInsideZones( + state, + bar, + zone.count, + hasSupportZone, + zone.supportZone, + hasResistanceZone, + zone.resistanceZone, + hasSupplyZone, + zone.supplyZone, + hasDemandZone, + zone.demandZone, + hasOrderBlock, + zone.orderBlock, + hasFairValueGap, + zone.fairValueGap // + ); + if (!result) + { + return result; + } + + // + zone.bar = bar; + + // + result = zone.IsValid(); + + // + return result; +} + /** * Add Value Change instance to Exists Collection if it's not Exists ... * @@ -6740,6 +7633,40 @@ bool IsPriceAboveZone( return result; } +/** + * Check Price Above Specified Zone ... + * + * @return ( bool ) + */ +bool IsPriceAboveZone( + double price, + XCZone *zone // +) +{ + // + bool result = false; + + // + result = + price > 0 && + zone != NULL && + zone.IsValidBoundary(); + if (!result) + { + return result; + } + + // + result = + // + price > zone.Upper() + // + ; + + // + return result; +} + /** * Check Price Below Specified Zone ... * @@ -6782,6 +7709,40 @@ bool IsPriceBelowZone( return result; } +/** + * Check Price Below Specified Zone ... + * + * @return ( bool ) + */ +bool IsPriceBelowZone( + double price, + XCZone *zone // +) +{ + // + bool result = false; + + // + result = + price > 0 && + zone != NULL && + zone.IsValidBoundary(); + if (!result) + { + return result; + } + + // + result = + // + price < zone.Lower() + // + ; + + // + return result; +} + /** * Check Price Inside Specified Zone ... * @@ -6830,6 +7791,44 @@ bool IsPriceInsideZone( return result; } +/** + * Check Price Inside Specified Zone ... + * + * @return ( bool ) + */ +bool IsPriceInsideZone( + double price, + XCZone *zone // +) +{ + // + bool result = false; + + // + result = + price > 0 && + zone != NULL && + zone.IsValidBoundary(); + if (!result) + { + return result; + } + + // + result = + // + price <= zone.Upper() + // + && + // + price >= zone.Lower() + // + ; + + // + return result; +} + /** * Calculate Target for Specified Direction ... * diff --git a/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 b/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 index cc6e596f..56f95f1c 100644 --- a/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 +++ b/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 @@ -519,6 +519,656 @@ class XC121SMCCycleHelper : public XCBase return result; } + bool DetectMarketStructure( + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + int barIndex = 0; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int highestPeakIndex = -1; + double highestPeakVale = 0; + double highestPeak = mX121Helper + .GetHighestPeak( + barIndex, + highestPeakIndex, + highestPeakVale // + ); + + // + int lowestValeIndex = -1; + double lowestValePeak = 0; + double lowestVale = mX121Helper + .GetLowestVale( + barIndex, + lowestValeIndex, + lowestValePeak // + ); + + // + result = IsValidIndex(highestPeakIndex) && + IsValidIndex(lowestValeIndex); + if (!result) + { + return result; + } + + // + dir = + highestPeakIndex < lowestValeIndex + ? X_DIRECTION_BEARISH + : highestPeakIndex > lowestValeIndex + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(dir); + + // + // Looking for Change Of Character Proved ... + + // + // Bullish Bias: + // - Price Must Break Up Lowst Vale's Peak; + // - Create a Vale Above Lowest Vale's Peak; + + // + // Bearish Bias: + // - Price Must Breake Down HighestPeak's Vale; + // - Create a Peak Under Highest Peak's Vale; + + // + // Checking Peak Breake Up ... + int lowestValePeakBreakeUpIndex = -1; + for (int i = lowestValeIndex; i >= barIndex; i--) + { + // + XOHCL iBar; + result = GetBar(iBar, i); + if (!result) + { + continue; + } + + // + bool isBreake = iBar.IsBreakeUp(lowestValePeak); + if (isBreake) + { + // + lowestValePeakBreakeUpIndex = i; + break; + } + } + bool isValidBreakeUpLowestValePeak = IsValidIndex(lowestValePeakBreakeUpIndex) && + lowestValePeakBreakeUpIndex <= lowestValeIndex; + + // + // Checking Vale Breake Down ... + int highestPeakValeBreakeDownIndex = -1; + for (int i = highestPeakIndex; i >= barIndex; i--) + { + // + XOHCL iBar; + result = GetBar(iBar, i); + if (!result) + { + continue; + } + + // + bool isBreake = iBar.IsBreakeDown(highestPeakVale); + if (isBreake) + { + // + highestPeakValeBreakeDownIndex = i; + break; + } + } + bool isValidBreakeDownHighestPeakVale = IsValidIndex(highestPeakValeBreakeDownIndex) && + highestPeakValeBreakeDownIndex <= highestPeakIndex; + // + result = isBullish + ? isValidBreakeUpLowestValePeak + : isValidBreakeDownHighestPeakVale; + if (!result) + { + return result; + } + + // + // Checking Create a Vale above Peak ... + int valeAboveLowestValePeakIndex = -1; + double valeAboveLowestValePeakPeak = 0; + for (int i = lowestValePeakBreakeUpIndex; i >= barIndex; i--) + { + // + double iVale = mX121Helper.GetVale(i); + + // + bool isValid = + iVale > 0 && + iVale > lowestValePeak; + if (isValid) + { + // + valeAboveLowestValePeakIndex = i; + valeAboveLowestValePeakPeak = mX121Helper.GetPeak(i); + break; + } + } + bool isValidValeAboveLowestValePeak = IsValidIndex(valeAboveLowestValePeakIndex) && + valeAboveLowestValePeakIndex < lowestValePeakBreakeUpIndex; + + // + // Checking Create a Peak below Vale ... + int peakBelowHighestPeakValeIndex = -1; + double peakBelowHighestPeakValeVale = 0; + for (int i = highestPeakValeBreakeDownIndex; i >= barIndex; i--) + { + // + double iPeak = mX121Helper.GetPeak(i); + + // + bool isValid = + iPeak > 0 && + iPeak < highestPeakVale; + if (isValid) + { + // + peakBelowHighestPeakValeIndex = i; + peakBelowHighestPeakValeVale = mX121Helper.GetVale(i); + break; + } + } + bool isValidPeakBelowHighestPeakVale = IsValidIndex(peakBelowHighestPeakValeIndex) && + peakBelowHighestPeakValeIndex < highestPeakValeBreakeDownIndex; + + // + result = isBullish ? isValidValeAboveLowestValePeak + : isValidPeakBelowHighestPeakVale; + if (!result) + { + return result; + } + + // + // Now we Have to Detect Valid Peaks and Valid Vales Here ... + // based on Detected Range ... + + // + XPVPivotPoint vales[]; + XPVPivotPoint peaks[]; + XPVPivotPoint iPeakPoint; + XPVPivotPoint iValePoint; + XPriceZones peakPriceZone; + XPriceZones valePriceZone; + XPriceZones peakPriceZones[]; + XPriceZones valePriceZones[]; + + // + XPOIState state; + mPOIDetector.GetState( + state // + ); + + // + int minRepetition = 5; // ValidPivotRepetition(); + + // + int from = + isBullish + ? valeAboveLowestValePeakIndex + : peakBelowHighestPeakValeIndex; + for (int i = from; i >= barIndex; i--) + { + // + XOHCL iBar; + bool isInited = GetBar(iBar, i); + + // + double iPeak = mX121Helper.GetPeak(i); + double iVale = mX121Helper.GetVale(i); + + // + bool hasPeakPriceInsideZone = CalculatePriceInsideZones( + peakPriceZone, + state, + iPeak // + ); + bool hasValePriceInsideZone = CalculatePriceInsideZones( + valePriceZone, + state, + iVale // + ); + + // + if (hasPeakPriceInsideZone) + { + // + // Peak ... + if (!iPeakPoint.IsValid()) + { + // + // Initialization ... + iPeakPoint.value = iPeak; + iPeakPoint.repetition = 1; + iPeakPoint.type = XPV_PEAK; + iPeakPoint.time = iBar.time; + } + else + { + // + if (iPeakPoint.value == iPeak) + { + iPeakPoint.repetition++; + } + else + { + // + if (iPeakPoint.repetition > minRepetition) + { + // + AddRef( + iPeakPoint, + peaks // + ); + + // + AddRef( + peakPriceZone, + peakPriceZones // + ); + } + + // + iPeakPoint.Clean(); + peakPriceZone.Clean(); + iPeakPoint.value = iPeak; + iPeakPoint.repetition = 1; + iPeakPoint.type = XPV_PEAK; + iPeakPoint.time = iBar.time; + } + } + } + + // + if (hasValePriceInsideZone) + { + // + // Vale ... + if (!iValePoint.IsValid()) + { + // + // Initialization ... + iValePoint.value = iVale; + iValePoint.repetition = 1; + iValePoint.type = XPV_VALE; + iValePoint.time = iBar.time; + } + else + { + // + if (iValePoint.value == iVale) + { + iValePoint.repetition++; + } + else + { + // + if (iValePoint.repetition > minRepetition) + { + // + AddRef( + iValePoint, + vales // + ); + + // + AddRef( + valePriceZone, + valePriceZones // + ); + } + + // + iValePoint.Clean(); + valePriceZone.Clean(); + iValePoint.value = iVale; + iValePoint.repetition = 1; + iValePoint.type = XPV_VALE; + iValePoint.time = iBar.time; + } + } + } + } + + // + // in Bullish Bias we Looking for Vales Oder ... + // in Bearish Bias we Looking for Peaks Oder ... + + // + // Draw ... + XCBaseObject *drawnObjects[]; + + // + // Bearish Bias ... + if (isBullish) + { + // + // Draw Lowest Vale Bar ... + XOHCL lowestValeBar; + result = GetBar( + lowestValeBar, + lowestValeIndex // + ); + if (!result) + { + return result; + } + XCOHCLObject *iLowestValeBarObj; + bool isCreated = mPOIDetector.mDrawer.CreateBar( + lowestValeBar, + iLowestValeBarObj, + TimeCurrent() // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iLowestValeBarObj, + drawnObjects // + ); + } + + // + // Draw Lowest Vale Peak Breaker Bar ... + XOHCL lowestValePeakBreakeUpBar; + if (isValidBreakeUpLowestValePeak) + { + // + result = GetBar( + lowestValePeakBreakeUpBar, + lowestValePeakBreakeUpIndex // + ); + if (!result) + { + return result; + } + + // + XCOHCLObject *iObj; + bool isCreated = mPOIDetector.mDrawer.CreateBar( + lowestValePeakBreakeUpBar, + iObj, + TimeCurrent() // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + + // + // Draw Vale Above Lowest Vale Peak ... + XOHCL valeAboveLowestValePeakBar; + if (isValidValeAboveLowestValePeak) + { + // + result = GetBar(valeAboveLowestValePeakBar, + valeAboveLowestValePeakIndex // + ); + if (!result) + { + return result; + } + + // + XCOHCLObject *iObj; + bool isCreated = mPOIDetector.mDrawer.CreateBar( + valeAboveLowestValePeakBar, + iObj, + TimeCurrent() // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + + // + // Draw Vales ... + int valesCount = ArraySize(vales); + if (IsValidSize(valesCount)) + { + // + for (int i = 0; i < valesCount; i++) + { + // + iValePoint = vales[i]; + + // + CChartObjectTrend *iValeObj; + iValeObj = new CChartObjectTrend(); + + // + string iValeName = "XVALE_" + ToString(iValePoint.value); + + // + long chartID = mPOIDetector.mDrawer.ChartIdentification(); + int window = mPOIDetector.mDrawer.SubWindowIdentification(); + + // + bool isCreate = iValeObj.Create( + chartID, + iValeName, + window, + iValePoint.time, + iValePoint.value, + TimeCurrent(), + iValePoint.value // + ); + if (isCreated) + { + } + } + } + + // + // Draw Price Zone ... + valesCount = ArraySize(valePriceZones); + if (IsValidSize(valesCount)) + { + // + for (int i = 0; i < valesCount; i++) + { + // + XPriceZones iZone = valePriceZones[i]; + + // + bool hasSupport = iZone.HasSupportZone(); + if (hasSupport) + { + // + XCSupportZoneObject *iObj; + bool isCreated = mPOIDetector.mDrawer.CreateSupportZone( + iZone.supportZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + } + + // + // Bullish Bias Drawn ... + if (!isBullish) + { + // + // Draw Highest Peak Bar ... + XOHCL highestPeakBar; + result = GetBar( + highestPeakBar, + highestPeakIndex // + ); + if (!result) + { + return result; + } + XCOHCLObject *iHighestPeakBarObj; + bool isCreated = mPOIDetector.mDrawer.CreateBar( + highestPeakBar, + iHighestPeakBarObj, + TimeCurrent() // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iHighestPeakBarObj, + drawnObjects // + ); + } + + // + // Draw Highest Peak Vale Breaker Bar ... + XOHCL highestPeakValeBreakeDownBar; + if (isValidBreakeDownHighestPeakVale) + { + // + result = GetBar( + highestPeakValeBreakeDownBar, + highestPeakValeBreakeDownIndex // + ); + if (!result) + { + return result; + } + + // + XCOHCLObject *iObj; + bool isCreated = mPOIDetector.mDrawer.CreateBar( + highestPeakValeBreakeDownBar, + iObj, + TimeCurrent() // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + + // + // Draw Peak Below Highest Peak Vale ... + XOHCL peakBelowHighestPeakValeBar; + if (isValidPeakBelowHighestPeakVale) + { + // + result = GetBar(peakBelowHighestPeakValeBar, + peakBelowHighestPeakValeIndex // + ); + if (!result) + { + return result; + } + + // + XCOHCLObject *iObj; + bool isCreated = mPOIDetector.mDrawer.CreateBar( + peakBelowHighestPeakValeBar, + iObj, + TimeCurrent() // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + + // + // Draw Peaks ... + int peaksCount = ArraySize(peaks); + if (IsValidSize(peaksCount)) + { + // + for (int i = 0; i < peaksCount; i++) + { + // + iPeakPoint = peaks[i]; + + // + CChartObjectTrend *iPeakObj; + iPeakObj = new CChartObjectTrend(); + + // + string iPeakName = "XPEAK_" + ToString(iPeakPoint.value); + + // + long chartID = mPOIDetector.mDrawer.ChartIdentification(); + int window = mPOIDetector.mDrawer.SubWindowIdentification(); + + // + bool isCreate = iPeakObj.Create( + chartID, + iPeakName, + window, + iPeakPoint.time, + iPeakPoint.value, + TimeCurrent(), + iPeakPoint.value // + ); + if (isCreated) + { + } + } + } + } + + // + return result; + } + // // Tools ... @@ -3143,8 +3793,8 @@ class XC121SMCCycleHelper : public XCBase XValueChange mVWapStateChanges[]; // Holds Vales Changes ... // - int mConsolidationLoopback; // Consolidation Loopback Length ... - XConsolidationZone mConsolidationZones[]; // Holds Consolidation Zones ... + int mConsolidationLoopback; // Consolidation Loopback Length ... + XConsolidationZone mConsolidationZones[]; // Holds Consolidation Zones ... XConsolidationZone mActiveConsolidationZone; // Holds Actiove Consolidation Zone ... // XCConsolidationZoneObject *mActiveConsolidationZoneObj; diff --git a/X121SMCEA/Signals/x-121.smc.xtwpv.signal.lib.mq5 b/X121SMCEA/Signals/x-121.smc.xtwpv.signal.lib.mq5 index 74e3cc07..c449707b 100644 --- a/X121SMCEA/Signals/x-121.smc.xtwpv.signal.lib.mq5 +++ b/X121SMCEA/Signals/x-121.smc.xtwpv.signal.lib.mq5 @@ -646,6 +646,12 @@ bool DetectX121SMCXTWPVSiganlSetup( // // Setup Conditions ... + // + ENUM_X_DIRECTION biasDir; + bool hasMarketStructure = + analyseCycleHelper + .DetectMarketStructure(biasDir); + // XOHCL analyseCBar; result = analyseCycleHelper.GetBar(