diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index a000cfb4..e1d05531 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -2280,6 +2280,80 @@ class XCOrderBlock : public XCBarZone return result; } + /** + * Check Order Block Validation ... + * + * @return ( bool ) + */ + bool IsValidOrderBlock() + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + XOHCL breakerBar; + result = DetectBreakerBar(breakerBar); + if (!result) + { + return result; + } + int breakerBarIndex = breakerBar.Index(); + + // + XOHCL huntedBar; + bool isHunted = IsHunted(huntedBar); + result = !isHunted; + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(); + + // + for (int i = breakerBarIndex - 1; i >= 0; i--) + { + // + XOHCL iBar; + result = iBar.Init( + breakerBar.symbol, + breakerBar.period, + i // + ); + if (!result) + { + continue; + } + + // + double price = + isBullish + ? iBar.low + : iBar.high; + + // + result = + isBullish + ? price > Upper() + : price < Lower(); + if (!result) + { + return result; + } + } + + // + return result; + } + // // Overrides ... @@ -6050,6 +6124,89 @@ struct XMarketStructure // }; +struct XFVGOrderBlock +{ + // + // Props ... + XCOrderBlock *orderBlock; + XCFVG *fairValueGap; + + // + XFVGOrderBlock() + { + Clean(); + } + + /** + * Cleanup Model ... + */ + void Clean() + { + // + orderBlock = NULL; + fairValueGap = NULL; + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + orderBlock != NULL && + fairValueGap != NULL && + ((orderBlock.IsBullish() && + fairValueGap.IsBullish()) || + ((orderBlock.IsBearish() && + fairValueGap.IsBearish()))) + // + ; + + // + return result; + } + + /** + * Get Model Direction ... + * + * @param dir: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ + bool GetDirection( + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + dir = orderBlock.IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } +}; + // // Extensions ... diff --git a/X121SMCEA/Libraries/x-121.smc.lib.mq5 b/X121SMCEA/Libraries/x-121.smc.lib.mq5 index ed5184c0..793edd0a 100644 --- a/X121SMCEA/Libraries/x-121.smc.lib.mq5 +++ b/X121SMCEA/Libraries/x-121.smc.lib.mq5 @@ -720,11 +720,13 @@ ENUM_X_121_SMC_PROVIDERS ParseProvider(string value) // bool TestPOIState( XCPOIDrawer *drawer, - ENUM_X_DIRECTION forDir, // Test For Specified Direction ... - XPOIState &biggerState, // Bigger TF POI(s) ... - XPOIState &midState, // Mid TF POI(s) ... - XPOIState &triggerState, // Trigger TF POI(s) ... - int barIndex = 0 // Bar Index ... + ENUM_X_DIRECTION &forDir, // Test For Specified Direction ... + XFVGOrderBlock &bullishOrderBlocks[], // Bullish Order Blocks ... + XFVGOrderBlock &bearishOrderBlocks[], // Bearish Order Blocks ... + XPOIState &orderBlockState, // Order Block Detection TF POI(s) ... + XPOIState &fairValueGapState, // Fair Value Gap Detection TF POI(s) ... + XPOIState &triggerState, // Trigger TF POI(s) ... + int barIndex = 0 // Bar Index ... ) { // @@ -736,13 +738,15 @@ bool TestPOIState( barIndex = 0; } + // + forDir = X_DIRECTION_NONE; + // // Validate Args ... result = drawer != NULL && - HasDirection(forDir) && - biggerState.HasChild() && - midState.HasChild() && + orderBlockState.HasChild() && + fairValueGapState.HasChild() && triggerState.HasChild(); if (!result) { @@ -750,8 +754,8 @@ bool TestPOIState( } // - string symbol = biggerState.symbol; - ENUM_TIMEFRAMES period = biggerState.period; + string symbol = orderBlockState.symbol; + ENUM_TIMEFRAMES period = orderBlockState.period; // // Retrieve Bars ... @@ -769,8 +773,7 @@ bool TestPOIState( // // Bullish ... - XCOrderBlock *bullishOrderBlocks[]; - int bullishOrderBlocksCount = biggerState.CountBullishOrderBlocks(); + int bullishOrderBlocksCount = orderBlockState.CountBullishOrderBlocks(); count = bullishOrderBlocksCount; if (IsValidSize(count)) { @@ -778,7 +781,8 @@ bool TestPOIState( for (int i = count - 1; i >= 0; i--) { // - XCOrderBlock *iOb = biggerState.bullishOrderBlocks[i]; + XCFVG *iFVG = NULL; + XCOrderBlock *iOb = orderBlockState.bullishOrderBlocks[i]; iOb.To(cTime); // @@ -794,10 +798,74 @@ bool TestPOIState( // Detect Order Block is Hunted Or Not ... XOHCL huntedBar; bool isHunted = iOb.IsHunted(huntedBar); - if (isHunted) { + if (isHunted) + { continue; } + // + // Check Validation of Order Block ... + bool isValid = iOb.IsValidOrderBlock(); + if (!isValid) + { + continue; + } + + // + // Check Order Block Has Fair Value Gap ... + int fvgsCount = fairValueGapState.CountBullishFairValueGaps(); + bool hasFVG = IsValidSize(fvgsCount); + if (!hasFVG) + { + continue; + } + + // + for (int j = fvgsCount - 1; j >= 0; j--) + { + // + XCFVG *jFVG = fairValueGapState.bullishFairValueGaps[j]; + + // + bool isValid = + // + jFVG.IsBullish() + // && + // jFVG.From() > iOb.From() && + // ((jFVG.Upper() > iOb.Upper() && + // jFVG.Lower() <= iOb.Upper()) || + // (jFVG.Upper() <= iOb.Upper() && + // jFVG.Lower() >= iOb.Lower())) + // + ; + if (isValid) + { + // + jFVG.To(cTime); + iFVG = jFVG; + break; + } + } + + // + hasFVG = iFVG != NULL; + result = hasFVG; + if (!result) + { + return result; + } + + // + XFVGOrderBlock iModel; + iModel.orderBlock = iOb; + iModel.fairValueGap = iFVG; + + // + AddRef( + iModel, + bullishOrderBlocks // + ); + // XCBullishOrderBlockObject *iOBObject; bool isInited = drawer.CreateBullishOrderBlock( @@ -817,15 +885,13 @@ bool TestPOIState( ); if (isInited) { - Print(""); } } } // // Bearish ... - XCOrderBlock *bearishOrderBlocks[]; - int bearishOrderBlocksCount = biggerState.CountBearishOrderBlocks(); + int bearishOrderBlocksCount = orderBlockState.CountBearishOrderBlocks(); count = bearishOrderBlocksCount; if (IsValidSize(count)) { @@ -833,15 +899,127 @@ bool TestPOIState( for (int i = count - 1; i >= 0; i--) { // - XCOrderBlock *iOb = biggerState.bearishOrderBlocks[i]; + XCFVG *iFVG = NULL; + XCOrderBlock *iOb = orderBlockState.bearishOrderBlocks[i]; + iOb.To(cTime); + + // + // Find Exit Bar of Bullish OrderBlock Upper ... + XOHCL breakerBar; + bool hasBreakerBar = iOb.DetectBreakerBar(breakerBar); + if (!hasBreakerBar) + { + continue; + } + + // + // Detect Order Block is Hunted Or Not ... + XOHCL huntedBar; + bool isHunted = iOb.IsHunted(huntedBar); + if (isHunted) + { + continue; + } + + // + // Check Validation of Order Block ... + bool isValid = iOb.IsValidOrderBlock(); + if (!isValid) + { + continue; + } + + // + // Check Order Block Has Fair Value Gap ... + int fvgsCount = fairValueGapState.CountBearishFairValueGaps(); + bool hasFVG = IsValidSize(fvgsCount); + if (!hasFVG) + { + continue; + } + + // + for (int j = fvgsCount - 1; j >= 0; j--) + { + // + XCFVG *jFVG = fairValueGapState.bearishFairValueGaps[j]; + + // + bool isValid = + // + jFVG.IsBearish() + // && + // jFVG.From() > iOb.From() && + // jFVG.Upper() > iOb.Lower() && + // jFVG.Lower() <= iOb.Lower() + // + ; + if (isValid) + { + // + jFVG.To(cTime); + iFVG = jFVG; + break; + } + } + + // + hasFVG = iFVG != NULL; + result = hasFVG; + if (!result) + { + return result; + } + + // + XFVGOrderBlock iModel; + iModel.orderBlock = iOb; + iModel.fairValueGap = iFVG; + + // + AddRef( + iModel, + bullishOrderBlocks // + ); + + // + XCBearishOrderBlockObject *iOBObject; + bool isInited = drawer.CreateBearishOrderBlock( + iOb, + iOBObject // + ); + if (isInited) + { + } + + // + XCOHCLObject *iBarObj; + isInited = drawer.CreateBar( + breakerBar, + iBarObj, + cTime // + ); + if (isInited) + { + } } } + // + // Check Order Blocks ... + bullishOrderBlocksCount = ArraySize(bullishOrderBlocks); + bool hasBullishOrderBlocks = IsValidSize(bullishOrderBlocksCount); + + // + // Check Order Blocks ... + bearishOrderBlocksCount = ArraySize(bearishOrderBlocks); + bool hasBearishOrderBlocks = IsValidSize(bearishOrderBlocksCount); + // result = // - IsValidSize(bullishOrderBlocksCount) || - IsValidSize(bearishOrderBlocksCount) + hasBullishOrderBlocks || + hasBearishOrderBlocks // ; if (!result) @@ -849,6 +1027,28 @@ bool TestPOIState( return result; } + // + bool isBullish = hasBullishOrderBlocks && !hasBearishOrderBlocks; + bool isBearish = hasBearishOrderBlocks && !hasBullishOrderBlocks; + bool isAll = hasBullishOrderBlocks && hasBearishOrderBlocks; + + // + forDir = + isBullish + ? X_DIRECTION_BULLISH + : isBearish + ? X_DIRECTION_BEARISH + : isAll + ? X_DIRECTION_ALL + : X_DIRECTION_NONE; + + // + result = forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + // return result; } diff --git a/X121SMCEA/Signals/x-121.smc.xtwpv.signal.lib.mq5 b/X121SMCEA/Signals/x-121.smc.xtwpv.signal.lib.mq5 index c1197e2c..6a63b917 100644 --- a/X121SMCEA/Signals/x-121.smc.xtwpv.signal.lib.mq5 +++ b/X121SMCEA/Signals/x-121.smc.xtwpv.signal.lib.mq5 @@ -48,6 +48,11 @@ struct X121SMCStrategyXTWPVSignalConditions datetime setupTime; datetime triggerTime; + // + // ENUM_X_DIRECTION orderBlockDir; + // XCOrderBlock *bullishOrderBlocks[]; + // XCOrderBlock *bearishOrderBlocks[]; + // // Constructor ... X121SMCStrategyXTWPVSignalConditions() @@ -163,6 +168,9 @@ struct X121SMCStrategyXTWPVSignalConditions void ExtensionClean() { // + // Clean(bullishOrderBlocks); + // Clean(bearishOrderBlocks); + // orderBlockDir = X_DIRECTION_NONE; } // @@ -381,9 +389,14 @@ bool DetectX121SMCXTWPVSiganlSetup( // Setup Conditions ... // - bool isBullishTested = TestPOIState( + ENUM_X_DIRECTION forDir; + XFVGOrderBlock bullishOrderBlocks[]; + XFVGOrderBlock bearishOrderBlocks[]; + bool isTested = TestPOIState( drawer, - X_DIRECTION_BULLISH, + forDir, + bullishOrderBlocks, + bearishOrderBlocks, consolidationState, analyseState, decisionState //