diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index 8f1bb320..37a27cf5 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -2490,6 +2490,57 @@ class XCPOIDrawer : public XCBase return result; } + bool CreateOrderBlock( + XCOrderBlock &zone, + XCBaseObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = zone.IsBullish(); + if (isBullish) + { + // + XCBullishOrderBlockObject *iObj; + result = CreateBullishOrderBlock( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + else + { + // + XCBearishOrderBlockObject *iObj; + result = CreateBearishOrderBlock( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + + // + return result; + } + // // Fair Value Gaps ... @@ -2613,6 +2664,57 @@ class XCPOIDrawer : public XCBase return result; } + bool CreateFairValueGap( + XCFVG &zone, + XCBaseObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = zone.IsBullish(); + if (isBullish) + { + // + XCBullishFairValueGapObject *iObj; + result = CreateBullishFairValueGap( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + else + { + // + XCBearishFairValueGapObject *iObj; + result = CreateBearishFairValueGap( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + + // + return result; + } + // // Ticks Zone ... diff --git a/Documents/BKP/1/poilib.bkp.mq5 b/Documents/BKP/1/poilib.bkp.mq5 index d997474c..75747d6b 100644 --- a/Documents/BKP/1/poilib.bkp.mq5 +++ b/Documents/BKP/1/poilib.bkp.mq5 @@ -7948,3 +7948,288 @@ int DrawFVGOrderBlock( // // +/** + * Check Price Above Specified Zone ... + * + * @param bar: XOHCL instance Reference ... + * + * @return ( bool ) + */ +bool IsPriceAboveZone( + XOHCL &bar, + XCZone *zone // +) +{ + // + bool result = false; + + // + result = + zone != NULL && + bar.IsValid() && + zone.IsValidBoundary(); + if (!result) + { + return result; + } + + // + result = + // + bar.low > zone.Upper() + // + ; + + // + 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 ... + * + * @param bar: XOHCL instance Reference ... + * + * @return ( bool ) + */ +bool IsPriceBelowZone( + XOHCL &bar, + XCZone *zone // +) +{ + // + bool result = false; + + // + result = + zone != NULL && + bar.IsValid() && + zone.IsValidBoundary(); + if (!result) + { + return result; + } + + // + result = + // + bar.high < zone.Lower() + // + ; + + // + 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 ... + * + * @param bar: XOHCL instance Reference ... + * + * @return ( bool ) + */ +bool IsPriceInsideZone( + XOHCL &bar, + XCZone *zone // +) +{ + // + bool result = false; + + // + result = + zone != NULL && + bar.IsValid() && + zone.IsValidBoundary(); + if (!result) + { + return result; + } + + // + result = + // + bar.low <= zone.Upper() + // + && + // + bar.low >= zone.Lower() + // + ; + + // + return result; +} +bool IsPriceInsideZone( + XOHCL &bar, + double upper, + double lower // +) +{ + // + bool result = false; + + // + result = + upper > 0 && + lower > 0 && + upper > lower && + bar.IsValid(); + if (!result) + { + return result; + } + + // + result = + // + bar.low <= upper + // + && + // + bar.low >= lower + // + ; + + // + 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; +} +bool IsPriceInsideZone( + double price, + double upper, + double lower // +) +{ + // + bool result = false; + + // + result = + price > 0 && + upper > 0 && + lower > 0 && + upper > lower; + if (!result) + { + return result; + } + + // + result = + // + price <= upper + // + && + // + price >= lower + // + ; + + // + return result; +} diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index be9d6b51..a4af6881 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -5010,6 +5010,43 @@ struct XBoxZone // return result; } + + /** + * Check Box is Same as another ... + * + * @param box: XBoxZone instance Reference ... + * + * @return ( bool ) + */ + bool IsSame(XBoxZone &box) + { + // + bool result = false; + + // + result = IsValid() && + box.IsValid(); + if (!result) + { + return result; + } + + // + result = + // + dir == box.dir && + from == box.from && + type == box.type && + upper == box.upper && + lower == box.lower && + symbol == box.symbol && + period == box.period + // + ; + + // + return result; + } }; // @@ -5404,292 +5441,6 @@ void CombineStates( } } -/** - * Check Price Above Specified Zone ... - * - * @param bar: XOHCL instance Reference ... - * - * @return ( bool ) - */ -bool IsPriceAboveZone( - XOHCL &bar, - XCZone *zone // -) -{ - // - bool result = false; - - // - result = - zone != NULL && - bar.IsValid() && - zone.IsValidBoundary(); - if (!result) - { - return result; - } - - // - result = - // - bar.low > zone.Upper() - // - ; - - // - 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 ... - * - * @param bar: XOHCL instance Reference ... - * - * @return ( bool ) - */ -bool IsPriceBelowZone( - XOHCL &bar, - XCZone *zone // -) -{ - // - bool result = false; - - // - result = - zone != NULL && - bar.IsValid() && - zone.IsValidBoundary(); - if (!result) - { - return result; - } - - // - result = - // - bar.high < zone.Lower() - // - ; - - // - 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 ... - * - * @param bar: XOHCL instance Reference ... - * - * @return ( bool ) - */ -bool IsPriceInsideZone( - XOHCL &bar, - XCZone *zone // -) -{ - // - bool result = false; - - // - result = - zone != NULL && - bar.IsValid() && - zone.IsValidBoundary(); - if (!result) - { - return result; - } - - // - result = - // - bar.low <= zone.Upper() - // - && - // - bar.low >= zone.Lower() - // - ; - - // - return result; -} -bool IsPriceInsideZone( - XOHCL &bar, - double upper, - double lower // -) -{ - // - bool result = false; - - // - result = - upper > 0 && - lower > 0 && - upper > lower && - bar.IsValid(); - if (!result) - { - return result; - } - - // - result = - // - bar.low <= upper - // - && - // - bar.low >= lower - // - ; - - // - 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; -} -bool IsPriceInsideZone( - double price, - double upper, - double lower // -) -{ - // - bool result = false; - - // - result = - price > 0 && - upper > 0 && - lower > 0 && - upper > lower; - if (!result) - { - return result; - } - - // - result = - // - price <= upper - // - && - // - price >= lower - // - ; - - // - return result; -} - template bool ToZone( T *&source[], @@ -5791,6 +5542,553 @@ bool ToBox( return result; } +template +bool IsSame( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = sourceBox.IsSame(destBox); + + // + return result; +} + +template +bool IsSameDiff( + T *source, + F *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = sourceBox.IsSame(destBox); + + // + return result; +} + +template +bool IsBelow( + T *source, + T *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxBelow( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsBelowDiff( + T *source, + F *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxBelow( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsAbove( + T *source, + T *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxAbove( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsAboveDiff( + T *source, + F *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxAbove( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsInside( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInside( + sourceBox, + destBox // + ); + + // + return result; +} + +template +bool IsInsideDiff( + T *source, + F *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInside( + sourceBox, + destBox // + ); + + // + return result; +} + +template +bool FindIndex( + int &index, + T *item, + T *&items[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + XBoxZone itemBox; + result = ToBox( + itemBox, + item // + ); + if (!result) + { + return result; + } + + // + XBoxZone itemsBox[]; + result = ToBox( + items, + itemsBox // + ); + if (!result) + { + return result; + } + + // + result = FindBoxIndex( + index, + itemBox, + itemsBox // + ); + + // + return result; +} + +/** + * Find Specified Box Index inside a Collection of Boxes ... + * + * @param box: XBoxZone instance Reference ... + * @param boxes: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +bool FindBoxIndex( + int &index, + XBoxZone &box, + XBoxZone &boxes[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + int count = ArraySize(boxes); + result = box.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = boxes[i]; + + // + bool isSame = box.IsSame(iBox); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Check Source Box is Below Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param ignoreInside: bool ... + * + * @return ( bool ) + */ +bool IsBoxBelow( + XBoxZone &source, + XBoxZone &dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSame(dest); + if (!result) + { + return result; + } + + // + if (!ignoreInside) + { + result = source.upper < dest.lower; + } + else + { + result = (source.upper < dest.lower || + source.upper >= dest.upper) && + source.lower < dest.lower; + } + + // + return result; +} + +/** + * Check Source Box is Above Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param ignoreInside: bool ... + * + * @return ( bool ) + */ +bool IsBoxAbove( + XBoxZone &source, + XBoxZone &dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSame(dest); + if (!result) + { + return result; + } + + // + if (!ignoreInside) + { + result = source.lower > dest.upper; + } + else + { + result = (source.lower > dest.upper || + source.lower <= dest.upper) && + source.upper > dest.upper; + } + + // + return result; +} + +/** + * Check Source Box is Inside Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * + * @return ( bool ) + */ +bool IsBoxAbove( + XBoxZone &source, + XBoxZone &dest // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSame(dest); + if (!result) + { + return result; + } + + // + result = source.lower >= dest.lower && + source.upper <= dest.upper; + + // + return result; +} + /** * Converts a Consolidation Zone ... * 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 c9cc5ee2..6afc6b93 100644 --- a/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 +++ b/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 @@ -160,6 +160,7 @@ class XC121SMCCycleHelper : public XCBase symbol, period // ); + mPOIDetector.MaxNumberOfPOIs(requiredPOIS); mPOIDetector.MaxNumberOfRequiredPOIs(requiredPOIS); mPOIDetector.Init(); diff --git a/X121SMCEA/Signals/x-121.smc.xobs.signal.lib.mq5 b/X121SMCEA/Signals/x-121.smc.xobs.signal.lib.mq5 index 6f49f163..9b91460c 100644 --- a/X121SMCEA/Signals/x-121.smc.xobs.signal.lib.mq5 +++ b/X121SMCEA/Signals/x-121.smc.xobs.signal.lib.mq5 @@ -38,10 +38,10 @@ struct XOBTest // XCOrderBlock *ob; - XCFVG *fvg; + XCFVG *fvgs[]; // - datetime fvgActivatedAt; + datetime fvgBreakedAt; datetime rewardedAt; // @@ -62,14 +62,35 @@ struct XOBTest { // ob = NULL; - fvg = NULL; symbol = NULL; period = NULL; rewardedAt = NULL; - fvgActivatedAt = NULL; + fvgBreakedAt = NULL; // reward = 0; + + // + Clean(fvgs); + } + + // + bool HasOB() + { + return ob != NULL && + ob.IsValid(); + } + + // + int CountFVGs() + { + return ArraySize(fvgs); + } + + // + bool HasFVGs() + { + return IsValidSize(CountFVGs()); } }; @@ -688,22 +709,13 @@ bool DetectX121SMCXOBSSignalSetup( if (!isOBTested) { // - XOBTest test; bool hasTest = ReTestMarket( - test, conditions.obTests, consolidationState, analyseState, decisionState, visionCycleHelper.mPOIDrawer // ); - if (hasTest) - { - // - AddRef( - test, - conditions.obTests); - } } // @@ -1257,7 +1269,6 @@ int AddX121SMCXOBSConditionsIfNotExists( * @return ( bool ) */ bool ReTestMarket( - XOBTest &test, XOBTest &tests[], XPOIState &htfState, XPOIState &mtfState, @@ -1271,16 +1282,10 @@ bool ReTestMarket( bool result = false; // - test.Clean(); + Clean(tests); // - int testsCount = ArraySize(tests); - bool hasTests = IsValidSize(testsCount); - XOBTest lastTest; - if (hasTests) - { - lastTest = tests[testsCount - 1]; - } + datetime cTime = TimeCurrent(); // // Detect Order Blocks ... @@ -1290,6 +1295,9 @@ bool ReTestMarket( // Bullish OBs ... XCOrderBlock *bullOBs[]; bool hasYoungestBullOB = false; + XOHCL youngestBullOBStartedBar; + bool isYoungestBullOBStarted = false; + ENUM_X_DIRECTION youngestBullOBStartedDir; XCOrderBlock *youngestBullOB = NULL; int bullOBsCount = ExtractUnActivatedOBs( htfState.bullishOrderBlocks, @@ -1310,7 +1318,15 @@ bool ReTestMarket( hasYoungestBullOB = IsValidIndex(youngestBoxIDX); if (hasYoungestBullOB) { + // youngestBullOB = bullOBs[youngestBoxIDX]; + + // + isYoungestBullOBStarted = youngestBullOB.IsStarted( + X_DIRECTION_BULLISH, + youngestBullOBStartedBar, + youngestBullOBStartedDir // + ); } } @@ -1318,6 +1334,9 @@ bool ReTestMarket( // Bearish OBs ... XCOrderBlock *bearOBs[]; bool hasYoungestBearOB = false; + XOHCL youngestBearOBStartedBar; + bool isYoungestBearOBStarted = false; + ENUM_X_DIRECTION youngestBearOBStartedDir; XCOrderBlock *youngestBearOB = NULL; int bearOBsCount = ExtractUnActivatedOBs( htfState.bearishOrderBlocks, @@ -1338,13 +1357,544 @@ bool ReTestMarket( hasYoungestBearOB = IsValidIndex(youngestBoxIDX); if (hasYoungestBearOB) { + // youngestBearOB = bearOBs[youngestBoxIDX]; + + // + isYoungestBearOBStarted = youngestBearOB.IsStarted( + X_DIRECTION_BEARISH, + youngestBearOBStartedBar, + youngestBearOBStartedDir // + ); } } // - result = isBullOBsPassed || - isBearOBsPassed; + bool hasYoungestOB = hasYoungestBullOB || + hasYoungestBearOB; + result = hasYoungestOB; + if (!result) + { + return result; + } + + // + // Since Youngest Order Blocks is UnActivated ... + // here we found Order Flow ... + // Order Blocks in consequences of Youngest OB which they + // Breaked ... + + // + // Bullish OB ... + int breakedBullOBsCount = 0; + XCOrderBlock *breakedBullOBs[]; + bool hasBreakedBullOBs = false; + if (hasYoungestBullOB) + { + // + bool hasOBs = htfState.HasBullishOrderBlocks(); + int count = htfState.CountBullishOrderBlocks(); + if (hasOBs) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iOB = htfState.bullishOrderBlocks[i]; + ENUM_X_DIRECTION forDir = + iOB.IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Check iOB isn't Same as Youngest OB ... + bool isSameAsYoungest = IsSame( + youngestBullOB, + iOB // + ); + if (isSameAsYoungest) + { + continue; + } + + // + // Bullish Order Blocks must appears Below + // Youngest One ... + bool isBelow = IsBelow( + iOB, + youngestBullOB // + ); + if (!isBelow) + { + continue; + } + + // + XOHCL iBreakerBar; + ENUM_X_DIRECTION iBreakerDir; + bool isIBreaked = iOB.IsBreaked( + forDir, + iBreakerBar, + iBreakerDir // + ); + if (!isIBreaked) + { + continue; + } + + // + // Bullish Order Block Must Valid ... + // Means Price Must be On Top of it after its breake out ... + + // + bool isValid = false; + int fromIndex = iBreakerBar.Index() - 1; + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + iOB.GetSymbol(), + iOB.GetPeriod(), + i // + ); + if (!isInited) + { + continue; + } + + // + isValid = iBar.low > iOB.Upper(); + if (!isValid) + { + break; + } + } + if (!isValid) + { + continue; + } + + // + // Set OB's To Time to Breaker Bar's Time ... + iOB.To(iBreakerBar.time); + + // + // Check Order Block Not Exists ... + int iOBIDX = -1; + bool isIOBExists = FindIndex( + iOBIDX, + iOB, + breakedBullOBs // + ); + if (isIOBExists) + { + continue; + } + + // + Add( + iOB, + breakedBullOBs // + ); + + // + } + } + + // + breakedBullOBsCount = ArraySize(breakedBullOBs); + hasBreakedBullOBs = IsValidSize(breakedBullOBsCount); + } + + // + // Bearish OB ... + int breakedBearOBsCount = 0; + XCOrderBlock *breakedBearOBs[]; + bool hasBreakedBearOBs = false; + if (hasYoungestBearOB) + { + // + bool hasOBs = htfState.HasBearishOrderBlocks(); + int count = htfState.CountBearishOrderBlocks(); + if (hasOBs) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iOB = htfState.bearishOrderBlocks[i]; + ENUM_X_DIRECTION forDir = + iOB.IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Check iOB isn't Same as Youngest OB ... + bool isSameAsYoungest = IsSame( + youngestBearOB, + iOB // + ); + if (isSameAsYoungest) + { + continue; + } + + // + // Bearish Order Blocks must appears Above + // Youngest One ... + bool isAbove = IsAbove( + iOB, + youngestBearOB // + ); + if (!isAbove) + { + continue; + } + + // + XOHCL iBreakerBar; + ENUM_X_DIRECTION iBreakerDir; + bool isIBreaked = iOB.IsBreaked( + forDir, + iBreakerBar, + iBreakerDir // + ); + if (!isIBreaked) + { + continue; + } + + // + // Bearish Order Block Must Valid ... + // Means Price Must be On Bottom of it after its breake out ... + + // + bool isValid = false; + int fromIndex = iBreakerBar.Index() - 1; + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + iOB.GetSymbol(), + iOB.GetPeriod(), + i // + ); + if (!isInited) + { + continue; + } + + // + isValid = iBar.high < iOB.Lower(); + if (!isValid) + { + break; + } + } + if (!isValid) + { + continue; + } + + // + // Set OB's To Time to Breaker Bar's Time ... + iOB.To(iBreakerBar.time); + + // + // Check Order Block Not Exists ... + int iOBIDX = -1; + bool isIOBExists = FindIndex( + iOBIDX, + iOB, + breakedBearOBs // + ); + if (isIOBExists) + { + continue; + } + + // + Add( + iOB, + breakedBearOBs // + ); + + // + } + } + + // + breakedBearOBsCount = ArraySize(breakedBearOBs); + hasBreakedBearOBs = IsValidSize(breakedBearOBsCount); + } + + // + bool hasBreakedOBs = hasBreakedBullOBs || + hasBreakedBearOBs; + result = hasBreakedOBs; + if (!result) + { + return result; + } + + // + // Update Youngest OB To time ... + + // + if (hasYoungestBullOB) + { + youngestBullOB.To(cTime); + } + + // + if (hasYoungestBearOB) + { + youngestBearOB.To(cTime); + } + + // + // Now we Have to Validate Breaked Order Blocks Count in additions to Youngest OB directions ... + + // + bool hasBullishOrderFlow = + // + hasYoungestBullOB && + isYoungestBullOBStarted && + // + breakedBullOBsCount >= 2 + // + ; + + // + bool hasBearishOrderFlow = + // + hasYoungestBearOB && + isYoungestBearOBStarted && + // + breakedBearOBsCount >= 2 + // + ; + + // + ENUM_X_DIRECTION orderFlowDir = X_DIRECTION_NONE; + bool hasOrderFlow = hasBullishOrderFlow || + hasBearishOrderFlow; + if (hasOrderFlow) + { + // + orderFlowDir = + hasBullishOrderFlow + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + result = hasOrderFlow; + if (!result) + { + return result; + } + + // + // here we have try to detect Fair Value Gaps in Related to OrderFlow ... + if (hasBullishOrderFlow) + { + // + for (int i = 0; i < breakedBullOBsCount; i++) + { + // + XCOrderBlock *iOB = breakedBullOBs[i]; + + // + XOHCL iOBBreakerBar; + ENUM_X_DIRECTION iOBBreakerDir; + bool isIOBBreaked = iOB.IsBreaked( + X_DIRECTION_BULLISH, + iOBBreakerBar, + iOBBreakerDir // + ); + if (!isIOBBreaked) + { + continue; + } + + // + int fvgsCount = mtfState.CountBullishFairValueGaps(); + bool hasFVGs = mtfState.HasBullishFairValueGaps(); + if (!hasFVGs) + { + break; + } + + // + XCFVG *iOBFVGs[]; + for (int j = 0; j < fvgsCount; j++) + { + // + XCFVG *jFVG = mtfState.bullishFairValueGaps[j]; + + // + bool isFromPassed = jFVG.From() >= iOB.From(); + if (!isFromPassed) + { + continue; + } + + // + bool isAbovePassed = IsAboveDiff( + jFVG, + iOB, + true // Ignore Inside FVG ... + ); + if (!isAbovePassed) + { + continue; + } + + // + jFVG.To(iOB.To()); + + // + Add( + jFVG, + iOBFVGs // + ); + } + + // + // Check Order Block Has FVG or Not ... + int iOBFVGsCount = ArraySize(iOBFVGs); + bool iOBHasFVG = IsValidSize(iOBFVGsCount); + if (iOBHasFVG) + { + // + XOBTest iTest; + + // + iTest.ob = iOB; + iTest.symbol = iOB.GetSymbol(); + iTest.period = iOB.GetPeriod(); + + // + Copy( + iOBFVGs, + iTest.fvgs // + ); + + // + AddRef( + iTest, + tests // + ); + + // + iTest.Clean(); + } + } + } + else if (hasBearishOrderFlow) + { + // + for (int i = 0; i < breakedBearOBsCount; i++) + { + // + XCOrderBlock *iOB = breakedBearOBs[i]; + + // + XOHCL iOBBreakerBar; + ENUM_X_DIRECTION iOBBreakerDir; + bool isIOBBreaked = iOB.IsBreaked( + X_DIRECTION_BULLISH, + iOBBreakerBar, + iOBBreakerDir // + ); + if (!isIOBBreaked) + { + continue; + } + + // + int fvgsCount = mtfState.CountBearishFairValueGaps(); + bool hasFVGs = mtfState.HasBearishFairValueGaps(); + if (!hasFVGs) + { + break; + } + + // + XCFVG *iOBFVGs[]; + for (int j = 0; j < fvgsCount; j++) + { + // + XCFVG *jFVG = mtfState.bearishFairValueGaps[j]; + + // + bool isFromPassed = jFVG.From() >= iOB.From(); + if (!isFromPassed) + { + continue; + } + + // + bool isBelowPassed = IsBelowDiff( + jFVG, + iOB, + true // Ignore Inside FVG ... + ); + if (!isBelowPassed) + { + continue; + } + + // + jFVG.To(iOB.To()); + + // + Add( + jFVG, + iOBFVGs // + ); + } + + // + // Check Order Block Has FVG or Not ... + int iOBFVGsCount = ArraySize(iOBFVGs); + bool iOBHasFVG = IsValidSize(iOBFVGsCount); + if (iOBHasFVG) + { + // + XOBTest iTest; + + // + iTest.ob = iOB; + iTest.symbol = iOB.GetSymbol(); + iTest.period = iOB.GetPeriod(); + + // + Copy( + iOBFVGs, + iTest.fvgs // + ); + + // + AddRef( + iTest, + tests // + ); + + // + iTest.Clean(); + } + } + } + + // + // Now we Have to Works On Tests Collection ... + + // + int testsCount = ArraySize(tests); + bool hasTests = testsCount >= 2; + result = hasTests; if (!result) { return result; @@ -1385,10 +1935,10 @@ bool ReTestMarket( // XCBearishOrderBlockObject *iObj; bool isCreated = drawer - .CreateBearishOrderBlock( - youngestBearOB, - iObj // - ); + .CreateBearishOrderBlock( + youngestBearOB, + iObj // + ); // if (isCreated) @@ -1401,6 +1951,130 @@ bool ReTestMarket( } } + // // + // // Draw Breaked Bullish OrderBlocks ... + // if (hasBreakedBullOBs) + // { + // // + // for (int i = 0; i < breakedBullOBsCount; i++) + // { + // // + // XCOrderBlock *iOB = breakedBullOBs[i]; + // // iOB.To(cTime); + + // // + // XCBullishOrderBlockObject *iObj; + // bool isCreated = drawer + // .CreateBullishOrderBlock( + // iOB, + // iObj // + // ); + + // // + // if (isCreated) + // { + // // + // Add( + // (XCBaseObject *)iObj, + // drawnObjects // + // ); + // } + // } + // } + + // // + // // Draw Breaked Bearish OrderBlocks ... + // if (hasBreakedBearOBs) + // { + // // + // for (int i = 0; i < breakedBearOBsCount; i++) + // { + // // + // XCOrderBlock *iOB = breakedBearOBs[i]; + // // iOB.To(cTime); + + // // + // XCBearishOrderBlockObject *iObj; + // bool isCreated = drawer + // .CreateBearishOrderBlock( + // iOB, + // iObj // + // ); + + // // + // if (isCreated) + // { + // // + // Add( + // (XCBaseObject *)iObj, + // drawnObjects // + // ); + // } + // } + // } + + // + // Draw Tests ... + if (hasTests) + { + // + for (int i = 0; i < testsCount; i++) + { + // + XOBTest iTest = tests[i]; + + // + bool hasOB = iTest.HasOB(); + if (hasOB) + { + // + bool isBullish = iTest.ob.IsBullish(); + + // + XCBaseObject *obObj; + bool isCreated = drawer + .CreateOrderBlock( + iTest.ob, + obObj // + ); + if (isCreated) + { + // + Add( + obObj, + drawnObjects // + ); + } + } + + // + bool hasFVGs = iTest.HasFVGs(); + int fvgsCount = iTest.CountFVGs(); + for (int j = 0; j < fvgsCount; j++) + { + // + XCFVG *jFVG = iTest.fvgs[j]; + jFVG.To(iTest.ob.To()); + + // + XCBaseObject *fvgObj; + bool isCreated = drawer + .CreateFairValueGap( + jFVG, + fvgObj // + ); + if (isCreated) + { + // + Add( + fvgObj, + drawnObjects // + ); + } + } + } + } + // // END DRAW ... // diff --git a/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 b/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 index c7f2ed3b..a1dee207 100644 --- a/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 +++ b/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 @@ -978,15 +978,21 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy x121Inputs.xpvInputs.hcMethod = hcMethod; x121Inputs.xpvInputs.hcPeriod = hcPeriod; + // + x121Inputs.xhkInputs.xhkIgnoreSmoothingShadows = true; + + // + x121Inputs.xatrInputs.atrMultiplier = 1.5; + x121Inputs.xatrInputs.atrSmoothingMode = X_MA_MODE_EMA; + // // XPV ... - x121Inputs.xpvInputs.showSar = showAll || true; - x121Inputs.xpvInputs.showPeaks = showAll || true; - x121Inputs.xpvInputs.showVales = showAll || true; + x121Inputs.xpvInputs.showSar = showAll || false; + x121Inputs.xpvInputs.showPeaks = showAll || false; + x121Inputs.xpvInputs.showVales = showAll || false; // // XHK ... - x121Inputs.xhkInputs.xhkIgnoreSmoothingShadows = true; // x121Inputs.xhkInputs.drawRawXHKCandles = showAll || false; @@ -997,10 +1003,6 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy x121Inputs.xatrInputs.showATRUpper = showAll || false; x121Inputs.xatrInputs.showATRLower = showAll || false; - // - x121Inputs.xatrInputs.atrMultiplier = 1.5; - x121Inputs.xatrInputs.atrSmoothingMode = X_MA_MODE_EMA; - // // XSTR ... x121Inputs.xstrInputs.showStr = showAll || false;