From af6685f5238c843a398948a895e9b978b5d8115b Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Sun, 14 Jul 2024 15:22:31 +0330 Subject: [PATCH] add order block finder and add some other tools and also test them ... --- Experts/x-simple-test.ea.mq5 | 210 +++++++++- Libraries/x-saherelm.common.lib.mq5 | 599 ++++++++++++++++++++++++++++ 2 files changed, 807 insertions(+), 2 deletions(-) diff --git a/Experts/x-simple-test.ea.mq5 b/Experts/x-simple-test.ea.mq5 index cd98a4aa..4dfce533 100644 --- a/Experts/x-simple-test.ea.mq5 +++ b/Experts/x-simple-test.ea.mq5 @@ -119,11 +119,11 @@ void OnTick() // // Find Morning Star Pattern ... - FindMorningStar(); + // FindMorningStar(); // // Find Evening Star Pattern ... - FindEveningStar(); + // FindEveningStar(); // // Find Swing High Pattern ... @@ -156,6 +156,24 @@ void OnTick() // // Find Bearish Trend ... // FindBearishTrend(); + + // + // Find Bullish Order Block ... + // FindBullishOrderBlock(); + + // + // Find Bearish Order Block ... + // FindBearishOrderBlock(); + + // + // Find Sharp Going Up Price Action ... + // FindSharpBullish(); + + // + // Find Sharp Going Down Price Action ... + // FindSharpBearish(); + + // } // @@ -177,6 +195,64 @@ bool ValidateInputs() // // Custom Testing Functions ... +// +// Find Sharp Going Up Price Action ... +void FindSharpBullish() +{ + // + XOHCL cBar; + bool isInited = cBar.Init( + _Symbol, + _Period, + 1 // + ); + if (!isInited) + { + return; + } + + // + if (!cBar.IsSharpBullish()) + { + return; + } + + // + eaBarTracker.Waits(); + + // + Print("Detect Sharp Bullish Price Action ..."); +} + +// +// Find Sharp Going Down Price Action ... +void FindSharpBearish() +{ + // + XOHCL cBar; + bool isInited = cBar.Init( + _Symbol, + _Period, + 1 // + ); + if (!isInited) + { + return; + } + + // + if (!cBar.IsSharpBearish()) + { + return; + } + + // + eaBarTracker.Waits(); + + // + Print("Detect Sharp Bearish Price Action ..."); +} + // // Find Doji Pattern ... void FindDoji() @@ -1072,4 +1148,134 @@ void FindBearishTrend() Print("Bearish Trend Detected ..."); } +// +// Find Bullish Order Block ... +void FindBullishOrderBlock() { + // + XOHCL cBar; + bool isInited = cBar.Init( + _Symbol, + _Period, + 1 // + ); + if (!isInited) + { + return; + } + + // + XOHCL obBar; + bool hasOB = cBar.HasBullishOrderBlock( + obBar // + ); + if (!hasOB) { + return; + } + + // + eaBarTracker.Waits(); + + // + DrawTrendLine( + ChartID(), + "BULLOB-H-" + ToString((int) obBar.time), + 0, + obBar.time, + obBar.high, + cBar.time, + obBar.high, + clrAqua, + STYLE_SOLID, + 2, + false, + false, + true // + ); + + // + DrawTrendLine( + ChartID(), + "BULLOB-L-" + ToString((int) obBar.time), + 0, + obBar.time, + obBar.low, + cBar.time, + obBar.low, + clrAqua, + STYLE_SOLID, + 2, + false, + false, + true // + ); + + // + Print("Detect new Bullish Order Block ..."); +} + +// +// Find Bearish Order Block ... +void FindBearishOrderBlock() { + // + XOHCL cBar; + bool isInited = cBar.Init( + _Symbol, + _Period, + 1 // + ); + if (!isInited) + { + return; + } + + // + XOHCL obBar; + bool hasOB = cBar.HasBearishOrderBlock( + obBar // + ); + if (!hasOB) { + return; + } + + // + eaBarTracker.Waits(); + + // + DrawTrendLine( + ChartID(), + "BEAROB-H-" + ToString((int) obBar.time), + 0, + obBar.time, + obBar.high, + cBar.time, + obBar.high, + clrMagenta, + STYLE_SOLID, + 2, + false, + false, + true // + ); + + // + DrawTrendLine( + ChartID(), + "BEAROB-L-" + ToString((int) obBar.time), + 0, + obBar.time, + obBar.low, + cBar.time, + obBar.low, + clrMagenta, + STYLE_SOLID, + 2, + false, + false, + true // + ); + + // + Print("Detect new Bearish Order Block ..."); +} + // \ No newline at end of file diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index 58af67d8..fac6f623 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -593,6 +593,22 @@ struct XOHCL return result; } + // + int TotalBars() + { + // + int result = 0; + + // + result = iBars( + symbol, + period // + ); + + // + return result; + } + // // Calculate X_PRICE Specified Type ... double GetPrice(ENUM_X_PRICE mPType) @@ -695,6 +711,146 @@ struct XOHCL return result; } + // + // Find Specific Price ... + bool FindHigherPriceBar( + XOHCL &bar, + double price, + ENUM_X_PRICE _type = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = TotalBars(); + result = IsValidSize(totalBars); + if (!result) + { + return result; + } + + // + int start = Index(); + int maxAllowedLoopback = totalBars / 5; + for (int i = start; i < maxAllowedLoopback; i++) + { + // + result = bar.Init( + symbol, + period, + i // + ); + + // + if (!result) + { + break; + } + + // + double iPrice = bar.GetPrice(_type); + + // + result = + // + iPrice > 0 && + iPrice > price + // + ; + if (result) + { + break; + } + } + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + // Find Specific Price ... + bool FindLowerPriceBar( + XOHCL &bar, + double price, + ENUM_X_PRICE _type = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = TotalBars(); + result = IsValidSize(totalBars); + if (!result) + { + return result; + } + + // + int start = Index(); + int maxAllowedLoopback = totalBars / 5; + for (int i = start; i < maxAllowedLoopback; i++) + { + // + result = bar.Init( + symbol, + period, + i // + ); + + // + if (!result) + { + break; + } + + // + double iPrice = bar.GetPrice(_type); + + // + result = + // + iPrice > 0 && + iPrice < price + // + ; + if (result) + { + break; + } + } + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + // // Calculate Bar Mid Line ... double GetMid() @@ -997,6 +1153,276 @@ struct XOHCL idx + 1 // ); + // + if (!result) + { + bar.Clean(); + } + + // + 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; } @@ -3014,6 +3440,179 @@ struct XOHCL // // 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) + { + // + bool isInited = cBar.Init( + symbol, + period, + cIDX // + ); + + // + 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 ...