diff --git a/Classes/x-saherelm.x-cobject.class.mq5 b/Classes/x-saherelm.x-cobject.class.mq5 index 24356081..574fbc43 100644 --- a/Classes/x-saherelm.x-cobject.class.mq5 +++ b/Classes/x-saherelm.x-cobject.class.mq5 @@ -28,6 +28,7 @@ #include #include #include +#include #include // @@ -45,6 +46,7 @@ enum ENUM_XCHARTOBJECTS X_TREND_OBJ = 8861, X_XPVPIVOT_OBJ = 8862, X_OHCL_OBJ = 8863, + X_RR_OBJ = 8864, // // Structured ... X_TRADE_DAY_OBJ = 9860, @@ -2511,6 +2513,550 @@ class XCBoxObject : public XCBaseObject CChartObjectRectangle mRect; }; +class XCRRObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param rr: XRR instance Reference ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XRR &rr, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = rr.IsValid(); + if (!result) + { + return result; + } + + // + string name = rr.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + bool isLong = IsLong(rr.type); + + // + double price1 = rr.entry; + double price2 = rr.sl; + + // + datetime time1 = rr.time; + datetime time2 = (datetime)((int)rr.time + 2 * PeriodSeconds(rr.period)); + + // + result = mFibo.Create( + chart_id, + name, + window, + time1, + price1, + time2, + price2 // + ); + if (!result) + { + return result; + } + + // + mRR = rr; + ObjName(name); + + // + int tpsCount = ArraySize(rr.tps); + int levels = tpsCount + 2; + result = mFibo.LevelsCount(levels); + if (!result) + { + return result; + } + + // + // Set Fibo Levels ... + + // + result = mFibo.LevelValue(0, 0); + if (!result) + { + return result; + } + result = mFibo.LevelDescription(0, "SL"); + if (!result) + { + return result; + } + + // + result = mFibo.LevelValue(1, 1.0); + if (!result) + { + return result; + } + result = mFibo.LevelDescription(1, "Entry"); + if (!result) + { + return result; + } + + // + for (int i = 0; i < tpsCount; i++) + { + // + int idx = i + 2; + double level = 1.0 + rr.tps[i]; + string description = "TP " + ToString(rr.tps[i]); + + // + result = mFibo.LevelValue( + idx, + level // + ); + if (!result) + { + break; + } + + // + result = mFibo.LevelDescription( + idx, + description // + ); + if (!result) + { + break; + } + } + if (!result) + { + return result; + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_RR_OBJ; + } + + // + private: + // + + // + // Props ... + XRR mRR; + CChartObjectFibo mFibo; + + // + bool SetSLProps( + int width = 1, + color clr = clrRed, + ENUM_LINE_STYLE style = STYLE_SOLID, + string description = "" // + ) + { + // + bool result = false; + + // + result = SetLevelProps( + 0, + width, + clr, + style, + description // + ); + + // + return result; + } + + // + bool SetEntryProps( + int width = 1, + color clr = clrOrange, + ENUM_LINE_STYLE style = STYLE_SOLID, + string description = "" // + ) + { + // + bool result = false; + + // + result = SetLevelProps( + 0, + width, + clr, + style, + description // + ); + + // + return result; + } + + // + bool SetTPProps( + double tpValue, + int width = 1, + color clr = clrLime, + ENUM_LINE_STYLE style = STYLE_SOLID, + string description = "" // + ) + { + // + bool result = false; + + // + int tpIDX = FindIndex( + tpValue, + mRR.tps // + ); + result = IsValidIndex(tpIDX); + if (!result) + { + return result; + } + + // + tpIDX += 2; + + // + result = SetLevelProps( + tpIDX, + width, + clr, + style, + description // + ); + + // + return result; + } + + // + bool SetLevelProps( + int id, + int width = 1, + color clr = clrYellow, + ENUM_LINE_STYLE style = STYLE_SOLID, + string description = "" // + ) + { + // + bool result = false; + + // + // Color ... + result = mFibo.LevelColor( + id, + clr // + ); + if (!result) + { + return result; + } + + // + // Style ... + result = mFibo.LevelStyle( + id, + style // + ); + if (!result) + { + return result; + } + + // + // Width ... + if (width > 0) + { + // + result = mFibo.LevelWidth( + id, + width // + ); + if (!result) + { + return result; + } + } + + // + // Description ... + if (IsValid(description)) + { + // + result = mFibo.LevelDescription( + id, + description // + ); + if (!result) + { + return result; + } + } + + // + return result; + } +}; + +class XCTrendObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param rr: XRR instance Reference ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XSwingPoint &swings[], + string prefix = NULL // + ) + { + // + bool result = false; + + // + int count = ArraySize(swings); + result = + count >= 2 && + IsValidSize(count); + if (!result) + { + return result; + } + + // + ENUM_X_SWING_TYPE type = swings[0].type; + bool isSwingLows = type == X_SWING_LOW; + + // + double values[]; + int valuesCount = ExtractSwings( + swings, + values // + ); + result = valuesCount == count; + if (!result) + { + return result; + } + + // + int firstIDX = -1; + double first = 0; + datetime firstTime = NULL; + + // + int secondIDX = -1; + double second = 0; + datetime secondTime = NULL; + + // + if (isSwingLows) + { + // + first = GetMin( + values, + firstIDX, + 0, + 0 // + ); + if (IsValidIndex(firstIDX)) + { + // + firstTime = swings[firstIDX].time; + + // + second = FindBiggerThan( + first, + values, + true // + ); + secondIDX = FindIndex( + second, + values // + ); + if (IsValidIndex(secondIDX)) + { + secondTime = swings[secondIDX].time; + } + } + } + else + { + // + first = GetMax( + values, + firstIDX, + 0, + 0 // + ); + if (IsValidIndex(firstIDX)) + { + // + firstTime = swings[firstIDX].time; + + // + second = FindLesserThan( + first, + values, + true // + ); + secondIDX = FindIndex( + second, + values // + ); + if (IsValidIndex(secondIDX)) + { + secondTime = swings[secondIDX].time; + } + } + } + + // + // Validate Points ... + result = + // + IsValidIndex(firstIDX) && + IsValidIndex(secondIDX) && + // + IsSpecifiedValid(firstTime) && + IsSpecifiedValid(secondTime) && + // + (isSwingLows + ? first < second + : first > second) + // + ; + if (!result) + { + return result; + } + + // + string name = ToString(type) + "_" + ToString(first) + "_" + ToString(second); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + result = mTrend.Create( + chart_id, + name, + window, + firstTime, + first, + secondTime, + second // + ); + if (!result) + { + return result; + } + + // + ObjName(name); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Trend Color ... + * + * @param value: Color ... + */ + void TrendColor(color value) + { + mTrend.Color(value); + } + + void TrendRayLeft(bool value) + { + mTrend.RayLeft(value); + } + + void TrendRayRight(bool value) + { + mTrend.RayRight(value); + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_TREND_OBJ; + } + + // + private: + // + + // + // Props ... + CChartObjectTrend mTrend; +}; + // // Zone Ticks ... diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index 37a27cf5..4d304820 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -2780,6 +2780,9 @@ class XCPOIDrawer : public XCBase // bool result = false; + // + object = NULL; + // result = zone.IsValid(); if (!result) @@ -2812,6 +2815,63 @@ class XCPOIDrawer : public XCBase return result; } + /** + * Create Trend Line Object ... + * + * @param swings: XSwingPoint instance Collection ... + * + * @return ( bool ) + */ + bool CreateTrend( + XSwingPoint &swings[], + XCTrendObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = ArraySize(swings) >= 2 && + IsValidSize(ArraySize(swings)); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCTrendObject(); + result = object.Create( + chartID, + window, + swings, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + color clrTrend = swings[0].type == X_SWING_LOW + ? SwingLowColor() + : SwingHighColor(); + object.TrendColor(clrTrend); + object.TrendRayRight(true); + + // + return result; + } + /** * Create Consolidation Zone Object ... * @@ -3100,6 +3160,53 @@ class XCPOIDrawer : public XCBase return result; } + /** + * Create Specific Risk Reward (RR) on Chart ... + * + * @param rr: XRR instance Reference ... + * + * @return ( bool ) + */ + bool CreateRR( + XRR &rr, + XCRRObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = rr.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCRRObject(); + result = object.Create( + chartID, + window, + rr, + prefix // + ); + if (!result) + { + return result; + } + + // + return result; + } + /** * Draw Specified Signal ... * diff --git a/Documents/BKP/1/signals/tmp.codes.signals.mq5 b/Documents/BKP/1/signals/tmp.codes.signals.mq5 index 97a6c928..eb822501 100644 --- a/Documents/BKP/1/signals/tmp.codes.signals.mq5 +++ b/Documents/BKP/1/signals/tmp.codes.signals.mq5 @@ -2982,12 +2982,1553 @@ bool DetectPriceInsideBox( ///////////////////////////////////////////////////////////////////// + + // + bool isLong = analyseXConditions.isStrSwitchedToBullish && + decisionXConditions.isCheBullish && + decisionXConditions.isStrBullish; + bool isShort = analyseXConditions.isStrSwitchedToBearish && + decisionXConditions.isCheBearish && + decisionXConditions.isStrBearish; + + // + result = isLong || + isShort; + if (!result) + { + return result; + } + + // + XRR rr; + + // + double sl = + isLong + ? decisionXConditions.strBuffer[1] - 10 * points + : decisionXConditions.strBuffer[1] + 10 * points; + + // + ENUM_X_DIRECTION dir = + isLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + ENUM_X_POSITION_TYPES type = + isLong + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + double entry = GetEntry(symbol, dir); + + // + result = rr.Init( + symbol, + period, + sl, + entry, + type // + ); + if (!result) + { + return result; + } + + // + XCRRObject *iRRObj; + result = visionCycleHelper + .mPOIDrawer + .CreateRR( + rr, + iRRObj // + ); + if (!result) + { + return result; + } + ///////////////////////////////////////////////////////////////////// + + // + // 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(), + iBreakerBar.period, + 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[]; + XCFVG *iOBFVG = NULL; + datetime fvgActedAt = NULL; + 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; + } + + // + // Validate FVG Based on Conditions ... + // for Bullish Order Blocks FVGs must Rejected as Liquidity ... + // in ttf ... + + // + XOHCL rejectedBar; + ENUM_X_DIRECTION rejectedDir; + bool isRejected = jFVG.IsRejected( + X_DIRECTION_BULLISH, + rejectedBar, + rejectedDir, + NULL, // From ... + true // Force Sweeped ... + ); + + // + XOHCL breakedBar; + ENUM_X_DIRECTION breakedDir; + bool isBreaked = jFVG.IsBreaked( + X_DIRECTION_BULLISH, + breakedBar, + breakedDir // + ); + + // + bool isFVGActed = + isRejected || + isBreaked; + if (!isFVGActed) + { + continue; + } + + // + datetime iFvgActedAt = + isBreaked && + !isRejected + ? breakedBar.time + : !isBreaked && + isRejected + ? rejectedBar.time + : isBreaked && + isRejected + ? (breakedBar.time < rejectedBar.time) + ? breakedBar.time + : rejectedBar.time + : NULL; + if (!IsValid(iFvgActedAt)) + { + continue; + } + + // + if (!IsValid(fvgActedAt)) + { + fvgActedAt = iFvgActedAt; + } + + // + XCFVG *lastFVG = NULL; + int fvgsCount = ArraySize(iOBFVGs); + bool hasLastFVG = IsValidSize(fvgsCount); + if (hasLastFVG) + { + lastFVG = iOBFVGs[fvgsCount - 1]; + } + bool isLastPassed = + !hasLastFVG + ? true + : IsAbove( + jFVG, + lastFVG, + true // Ignore Inside ... + ); + if (!isLastPassed) + { + continue; + } + + // + jFVG.To(iOB.To()); + // jFVG.To(iFvgActedAt); + + // + if (iOBFVG == NULL) + { + iOBFVG = jFVG; + } + + // + 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.fvg = iOBFVG; + iTest.symbol = iOB.GetSymbol(); + iTest.period = iOB.GetPeriod(); + + // + iTest.fvgActedAt = fvgActedAt; + + // + 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[]; + XCFVG *iOBFVG = NULL; + datetime fvgActedAt = NULL; + 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; + } + + // + // Validate FVG Based on Conditions ... + // for Bearish Order Blocks FVGs must Rejected as Liquidity ... + // in ttf ... + + // + XOHCL rejectedBar; + ENUM_X_DIRECTION rejectedDir; + bool isRejected = jFVG.IsRejected( + X_DIRECTION_BEARISH, + rejectedBar, + rejectedDir, + NULL, // From ... + true // Force Sweeped ... + ); + + // + XOHCL breakedBar; + ENUM_X_DIRECTION breakedDir; + bool isBreaked = jFVG.IsBreaked( + X_DIRECTION_BEARISH, + breakedBar, + breakedDir // + ); + + // + bool isFVGActed = + isRejected || + isBreaked; + if (!isFVGActed) + { + continue; + } + + // + datetime iFvgActedAt = + isBreaked && + !isRejected + ? breakedBar.time + : !isBreaked && + isRejected + ? rejectedBar.time + : isBreaked && + isRejected + ? (breakedBar.time < rejectedBar.time) + ? breakedBar.time + : rejectedBar.time + : NULL; + if (!IsValid(iFvgActedAt)) + { + continue; + } + + // + if (!IsValid(fvgActedAt)) + { + fvgActedAt = iFvgActedAt; + } + + // + XCFVG *lastFVG = NULL; + int fvgsCount = ArraySize(iOBFVGs); + bool hasLastFVG = IsValidSize(fvgsCount); + if (hasLastFVG) + { + lastFVG = iOBFVGs[fvgsCount - 1]; + } + bool isLastPassed = + !hasLastFVG + ? true + : IsBelow( + jFVG, + lastFVG, + true // Ignore Inside ... + ); + if (!isLastPassed) + { + continue; + } + + // + jFVG.To(iOB.To()); + // jFVG.To(iFvgActedAt); + + // + if (iOBFVG == NULL) + { + iOBFVG = jFVG; + } + + // + 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.fvg = iOBFVG; + iTest.symbol = iOB.GetSymbol(); + iTest.period = iOB.GetPeriod(); + + // + iTest.fvgActedAt = fvgActedAt; + + // + 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; + // } + + // + // TODO: ... + + // + if (hasYoungestBullOB) + { + // + XCBullishOrderBlockObject *iObj; + bool isCreated = drawer + .CreateBullishOrderBlock( + youngestBullOB, + iObj // + ); + + // + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + + // + if (hasYoungestBearOB) + { + // + XCBearishOrderBlockObject *iObj; + bool isCreated = drawer + .CreateBearishOrderBlock( + youngestBearOB, + iObj // + ); + + // + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + + // + // Draw Breaked Bullish OrderBlocks ... + if (hasBreakedBullOBs) + { + // + for (int i = 0; i < breakedBullOBsCount; i++) + { + // + XCOrderBlock *iOB = breakedBullOBs[i]; + ENUM_X_DIRECTION forDir = iOB.GetDirection(); + + // + XOHCL startedBar; + ENUM_X_DIRECTION startedDir; + bool isStarted = iOB.IsStarted( + forDir, + startedBar, + startedDir // + ); + if (isStarted) + { + // + string name = "Start_" + iOB.GetTag(); + ulong chartID = drawer.ChartIdentification(); + int subWindow = drawer.SubWindowIdentification(); + + // + CChartObjectVLine *vLine; + vLine = new CChartObjectVLine(); + bool isCreated = vLine.Create( + chartID, + name, + subWindow, + startedBar.time // + ); + + // + if (isCreated) + { + vLine.Color(clrYellow); + } + } + + // + 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 // + ); + } + } + } + + // + // + // + + // + // Test FVg Rewards ... + // for (int i = 0; i < testsCount; i++) + // { + // // + // XOBTest iTest = tests[i]; + + // // + // double iReward = 0; + // datetime iRewardedAt = NULL; + // bool isRewarded = TestFVG( + // iTest.fvg, + // iReward, + // iRewardedAt, + // // + // drawer, + // ttfState.period // + // ); + // if (isRewarded) + // { + // // + // tests[i].reward = iReward; + // tests[i].rewardedAt = iRewardedAt; + // } + // } + + // + // 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 // + // // ); + // // } + // // } + + // // + // bool hasFVG = iTest.fvg != NULL && + // iTest.fvg.IsValid(); + // if (hasFVG) + // { + // // + // XCBaseObject *fvgObj; + // bool isCreate = drawer.CreateFairValueGap( + // iTest.fvg, + // fvgObj // + // ); + // if (isCreate) + // { + // // + // Add( + // fvgObj, + // drawnObjects // + // ); + // } + // } + // } + // } + + // + // END DRAW ... + // + + // + Print("OBs Passed ..."); + + // + return result; + ///////////////////////////////////////////////////////////////////// +// +// +// + +/** + * Retest Market ... + * + * @param test: XOBTest instance Reference, Represet Result Test ... + * @param tests: XOBTest instance Reference Collection, Represet Founded Tests till now ... + * @param htfState: XPOIState instance Reference ... + * @param mtfState: XPOIState instance Reference ... + * @param ttfState: XPOIState instance Reference ... + * + * @return ( bool ) + */ +bool ReTestMarket( + XOBTest &tests[], + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &ttfState, // + // + XCPOIDrawer *drawer + // +) +{ + // + XCBaseObject *drawnObjects[]; + + // + bool result = false; + + // + Clean(tests); + + // + datetime cTime = TimeCurrent(); + + // + XOBTest mTest; + mTest.symbol = ttfState.symbol; + mTest.period = ttfState.period; + + // + // Detect Order Blocks ... + // HTF ... + + // + // Bullish OBs ... + XCOrderBlock *bullOBs[]; + bool hasYoungestBullOB = false; + XOHCL youngestBullOBStartedBar; + bool isYoungestBullOBStarted = false; + ENUM_X_DIRECTION youngestBullOBStartedDir; + XCOrderBlock *youngestBullOB = NULL; + int bullOBsCount = ExtractUnActivatedOBs( + htfState.bullishOrderBlocks, + bullOBs // + ); + + // + bool isBullOBsPassed = bullOBsCount >= 1; + if (isBullOBsPassed) + { + // + XBoxZone boxes[]; + int boxesCount = ToBox( + bullOBs, + boxes // + ); + int youngestBoxIDX = GetYoungest(boxes); + hasYoungestBullOB = IsValidIndex(youngestBoxIDX); + if (hasYoungestBullOB) + { + // + youngestBullOB = bullOBs[youngestBoxIDX]; + + // + isYoungestBullOBStarted = youngestBullOB.IsStarted( + X_DIRECTION_BULLISH, + youngestBullOBStartedBar, + youngestBullOBStartedDir // + ); + } + } + + // + // Bearish OBs ... + XCOrderBlock *bearOBs[]; + bool hasYoungestBearOB = false; + XOHCL youngestBearOBStartedBar; + bool isYoungestBearOBStarted = false; + ENUM_X_DIRECTION youngestBearOBStartedDir; + XCOrderBlock *youngestBearOB = NULL; + int bearOBsCount = ExtractUnActivatedOBs( + htfState.bearishOrderBlocks, + bearOBs // + ); + + // + bool isBearOBsPassed = bearOBsCount >= 1; + if (isBearOBsPassed) + { + // + XBoxZone boxes[]; + int boxesCount = ToBox( + bearOBs, + boxes // + ); + int youngestBoxIDX = GetYoungest(boxes); + hasYoungestBearOB = IsValidIndex(youngestBoxIDX); + if (hasYoungestBearOB) + { + // + youngestBearOB = bearOBs[youngestBoxIDX]; + + // + isYoungestBearOBStarted = youngestBearOB.IsStarted( + X_DIRECTION_BEARISH, + youngestBearOBStartedBar, + youngestBearOBStartedDir // + ); + } + } + + // + bool hasYoungestOB = hasYoungestBullOB || + hasYoungestBearOB; + result = hasYoungestOB; + if (!result) + { + // + mTest.Clean(); + 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(), + iBreakerBar.period, + i // + ); + if (!isInited) + { + continue; + } + + // + isValid = iBar.low > iOB.Upper(); + if (!isValid) + { + break; + } + } + if (!isValid) + { + continue; + } + + // + // Bullish Order Blocks must Appear on Below on Last OB ... + XCOrderBlock *lastOB = NULL; + breakedBullOBsCount = ArraySize(breakedBullOBs); + bool hasLastOB = IsValidSize(breakedBullOBsCount); + if (hasLastOB) + { + lastOB = breakedBullOBs[breakedBullOBsCount - 1]; + } + bool isLastOBPassed = + !hasLastOB + ? true + : IsBelow( + iOB, + lastOB // + ); + if (!isLastOBPassed) + { + 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; + } + + // + // Detect Related FVG ... + + // + XCFVG *iFVG = NULL; + bool hasFVG = false; + bool hasFVGs = mtfState.HasBullishFairValueGaps(); + int fvgsCount = mtfState.CountBullishFairValueGaps(); + if (hasFVGs) + { + // + for (int j = 0; j < fvgsCount; j++) + { + // + XCFVG *jFVG = mtfState.bullishFairValueGaps[j]; + + // + // Detect FVG From date ... + bool isFromPassed = jFVG.From() > iOB.From(); + if (!isFromPassed) + { + continue; + } + + // + // Check Fair Value Gaps Must be inside or Above that OB ... + bool isAbove = IsAboveDiff( + jFVG, + iOB, + true // Ignore Inside ... + ); + bool isInside = IsInsideDiff( + jFVG, + iOB // + ); + bool isPricePassed = isInside || + isAbove; + if (!isPricePassed) + { + continue; + } + + // + // Check Liquidity Sweep Before FVG ... + bool isLiquiditySweeped = false; + + if (!isLiquiditySweeped) { + continue; + } + + // + // Set Nearest Valid FVG to OB From ... + bool canSetFVG = + !hasFVG + ? true + : iFVG.From() > jFVG.From(); + + // + if (canSetFVG) + { + // + iFVG = jFVG; + hasFVG = iFVG != NULL && + iFVG.IsValid(); + } + } + } + + // + if (!hasFVG) + { + continue; + } + + // + XCBaseObject *iOBObj; + XCBaseObject *iFVGObj; + bool isOBCreated = drawer.CreateOrderBlock( + iOB, + iOBObj // + ); + bool isFVGCreated = drawer.CreateFairValueGap( + iFVG, + iFVGObj // + ); + + // + Add( + iOB, + breakedBullOBs // + ); + + // + } + } + + // + breakedBullOBsCount = ArraySize(breakedBullOBs); + hasBreakedBullOBs = IsValidSize(breakedBullOBsCount); + } + + // + Print("OBs Passed ..."); + + // + return result; +} + +/** + * Extract UnActivated Order Blocks ... + * + * @return ( int ) + */ +int ExtractUnActivatedOBs( + XCOrderBlock *&source[], + XCOrderBlock *&obs[] // +) +{ + // + int result = 0; + + // + Clean(obs); + + // + int count = ArraySize(source); + bool hasOB = IsValidSize(count); + if (!hasOB) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isBullish = source[i].IsBullish(); + ENUM_X_DIRECTION forDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // + // + + // + XOHCL activatedBar; + ENUM_X_DIRECTION activatedDir; + bool isActivated = source[i].IsActivated( + forDir, + activatedBar, + activatedDir // + ); + if (!isActivated) + { + // + Add( + source[i], + obs // + ); + } + } + + // + result = ArraySize(obs); + + // + return result; +} + +bool TestFVG( + XCFVG *fvg, + double &reward, + datetime &rewardedAt, + // + XCPOIDrawer *drawer, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + reward = 0; + rewardedAt = NULL; + + // + result = fvg != NULL && + fvg.IsValid(); + if (!result) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = fvg.GetPeriod(); + } + + // + bool isBullish = fvg.IsBullish(); + ENUM_X_DIRECTION forDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + XOHCL endBar; + result = fvg.FillEndBar(endBar); + if (!result) + { + return result; + } + + // + XOHCL startBar; + result = fvg.FillStartBar(startBar); + if (!result) + { + return result; + } + + // + XOHCL activatedBar; + ENUM_X_DIRECTION activatedDir; + result = fvg.IsActivated( + forDir, + activatedBar, + activatedDir, + forPeriod // + ); + if (!result) + { + return result; + } + + // + XOHCL breakedBar; + ENUM_X_DIRECTION breakedDir; + result = fvg.IsBreaked( + forDir, + breakedBar, + breakedDir, + forPeriod // + ); + if (!result) + { + return result; + } + + // + XOHCL triggerBar; + result = breakedBar.GetNextBar(triggerBar); + if (!result) + { + return result; + } + + // + int breakedIndex = breakedBar.Index(); + int triggerIndex = triggerBar.Index(); + + // + XRR fvgRR; + + // + string symbol = triggerBar.symbol; + ENUM_TIMEFRAMES period = triggerBar.period; + + // + double points = GetPoints(symbol); + + // + double sl = + isBullish + ? fvg.Lower() - 10 * points + : fvg.Upper() + 10 * points; + double entry = + isBullish + ? fvg.Upper() + : fvg.Lower(); + ENUM_X_POSITION_TYPES type = + isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + result = fvgRR.Init( + symbol, + period, + sl, + entry, + type // + ); + if (!result) + { + return result; + } + fvgRR.time = breakedBar.time; + + // + XCRRObject *iObj; + result = drawer.CreateRR( + fvgRR, + iObj // + ); + if (!result) + { + return result; + } + + // + Print("RR Created ..."); + + // + return result; +} ///////////////////////////////////////////////////////////////////// + // + XCBaseObject *iChildObj; + CChartObjectVLine *iStartVLine; + CChartObjectVLine *iBreakVLine; + + // + string iStartName = "Start_" + iChild.GetTag(); + string iBreakName = "Break_" + iChild.GetTag(); + ulong chartID = drawer.ChartIdentification(); + int subWindow = drawer.SubWindowIdentification(); + + // + iStartVLine = new CChartObjectVLine(); + bool isCreated = iStartVLine.Create( + chartID, + iStartName, + subWindow, + iChildStartedBar.time // + ); + + // + datetime iChildStartedBarToTime = iChildStartedBar.time + (PeriodSeconds(iChildStartedBar.period)); + XCOHCLObject *iBarObj; + isCreated = drawer.CreateBar( + iChildStartedBar, + iBarObj, + iChildStartedBarToTime // + ); + if (isCreated) + { + // + iBarObj.BodyColor(clrYellow); + iBarObj.HighShadowColor(clrYellow); + iBarObj.LowShadowColor(clrYellow); + } + + // + isCreated = drawer.CreateOrderBlock( + iChild, + iChildObj // + ); + ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////// diff --git a/Documents/BKP/1/signals/tmp.drwer.code.mq5 b/Documents/BKP/1/signals/tmp.drwer.code.mq5 new file mode 100644 index 00000000..9beb8836 --- /dev/null +++ b/Documents/BKP/1/signals/tmp.drwer.code.mq5 @@ -0,0 +1,199 @@ + // + // DRAW ... + // + + // + XCBaseObject *drawnObjects[]; + + // // + // if (hasYoungestBullOB) + // { + // // + // XCBullishOrderBlockObject *iObj; + // bool isCreated = drawer + // .CreateBullishOrderBlock( + // youngestBullOB, + // iObj // + // ); + + // // + // if (isCreated) + // { + // // + // Add( + // (XCBaseObject *)iObj, + // drawnObjects // + // ); + // } + // } + + // // + // if (hasYoungestBearOB) + // { + // // + // XCBearishOrderBlockObject *iObj; + // bool isCreated = drawer + // .CreateBearishOrderBlock( + // youngestBearOB, + // iObj // + // ); + + // // + // if (isCreated) + // { + // // + // Add( + // (XCBaseObject *)iObj, + // drawnObjects // + // ); + // } + // } + + // // + // // 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 // + // ); + // } + // } + + // + bool hasFVG = iTest.fvg != NULL && + iTest.fvg.IsValid(); + if (hasFVG) + { + // + XCBaseObject *fvgObj; + bool isCreate = drawer.CreateFairValueGap( + iTest.fvg, + fvgObj // + ); + if (isCreate) + { + // + Add( + fvgObj, + drawnObjects // + ); + } + } + } + } + + // + // END DRAW ... + // diff --git a/Documents/BKP/1/signals/x-121.smc.xobs.signal.lib copy.mq5 b/Documents/BKP/1/signals/x-121.smc.xobs.signal.lib copy.mq5 new file mode 100644 index 00000000..7808cd47 --- /dev/null +++ b/Documents/BKP/1/signals/x-121.smc.xobs.signal.lib copy.mq5 @@ -0,0 +1,1904 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: XOBS +// Description: provide all Signalling functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +// #include "../../Libraries/x-trade.lib" +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" +#include "../Libraries/x-121.smc.guard.lib.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +struct XOB +{ + // + XCOrderBlock *ob; + XCFVG *fvg; + + // + XOB() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + ob = NULL; + fvg = NULL; + + // + ZeroMemory(this); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = ob != NULL && + fvg != NULL && + ob.IsValid() && + fvg.IsValid(); + + // + return result; + } +}; + +// +struct XOBTest +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + XOB xob; + XCOrderBlock *ob; + XCFVG *fvg; + XCFVG *fvgs[]; + + // + datetime fvgActedAt; + datetime rewardedAt; + + // + double reward; + + // + // Constructor ... + XOBTest() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + ob = NULL; + fvg = NULL; + symbol = NULL; + period = NULL; + rewardedAt = NULL; + fvgActedAt = NULL; + + // + reward = 0; + + // + Clean(fvgs); + + // + xob.Clean(); + + // + ZeroMemory(this); + } + + // + bool HasOB() + { + return ob != NULL && + ob.IsValid(); + } + + // + bool HasFVG() + { + return fvg != NULL && + fvg.IsValid(); + } + + // + int CountFVGs() + { + return ArraySize(fvgs); + } + + // + bool HasFVGs() + { + return IsValidSize(CountFVGs()); + } +}; + +// +// Definitions ... +struct X121SMCStrategyXOBSSignalConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + double target; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + + // + double pivot; + double point; + + // + // Extwnsion ... + XOBTest obTests[]; + + // + // Constructor ... + X121SMCStrategyXOBSSignalConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + target = 0; + + // + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + + // + symbol = NULL; + period = NULL; + setupTime = NULL; + triggerTime = NULL; + + // + ExtensionClean(); + + // + ZeroMemory(this); + } + + /** + * Check Condition is Setting Up ... + * + * @param dir: ENUM_X_DIRECTION member, Setting Up Direction ... + * + * @return ( bool ) + */ + bool IsSetuped() + { + // + bool result = false; + + // + result = IsValid(setupTime) && + HasDirection(dir); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Calculate Setup Age ... + * + * @return ( int ) + */ + int GetSetupAge() + { + // + int result = 0; + + // + if (!IsSetuped()) + { + return result; + } + + // + result = (int)(TimeCurrent() - setupTime) / PeriodSeconds(period); + + // + return result; + } + + /** + * Detect How we Can Trigger Signal ... + * + * @return ( bool ) + */ + bool CanTrigger() + { + // + bool result = false; + + // + result = + // + sl > 0 && + IsValid(symbol) && + IsValid(period) && + IsValid(triggerTime) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE + // + ; + + // + return result; + } + + // + // Extensions ... + + /** + * Clean Additional Properties ... + */ + void ExtensionClean() + { + // + pivot = 0; + point = 0; + + // + Clean(obTests); + } + + // +}; + +// +// Signaller Data Sources ... +X121SMCStrategyXOBSSignalConditions mXOBSConditions; +X121SMCStrategyXOBSSignalConditions mXOBSConditionsCollection[]; + +// +// Extension Functions ... + +// +// Detect Setup Conditions ... +bool DetectX121SMCXOBSSignalSetup( + string _symbol, + ENUM_TIMEFRAMES _period, + // + X121SMCStrategyXOBSSignalConditions &conditions, + // + XC121SMCCycleHelper *triggerCycleHelper, + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *verificationCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper, + // + int resetAfterUnActedZoneInMinutes = 120 + // +) +{ + // + bool result = false; + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + string symbol = _symbol; + ENUM_TIMEFRAMES period = _period; + + // + conditions.symbol = symbol; + conditions.period = period; + + // + XC121SMCCycleHelper *barCycle = triggerCycleHelper; + + // + XOHCL zBar; + result = barCycle.GetBar( + zBar, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = barCycle.GetBar( + cBar, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = barCycle.GetBar( + pBar, + pIndex // + ); + if (!result) + { + return result; + } + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + int swingLoopback = 7; + double ll = cBar.FindLowest(swingLoopback, MODE_LOW); + double hh = cBar.FindHighest(swingLoopback, MODE_HIGH); + double ll50 = cBar.FindLowest(50, MODE_LOW); + double hh50 = cBar.FindHighest(50, MODE_HIGH); + double llDown = cBar.FindLowesttDown(swingLoopback); + double hhUp = cBar.FindHighestUp(swingLoopback); + + // + // Cycles Conditions ... + + // + // Trigger ... + ENUM_XPOI_EVENTS triggerPoiEvents[]; + ENUM_X_CYCLE_EVENTS triggerCycleEvents[]; + X121SMCCycleConditions triggerConditions; + result = triggerCycleHelper.GetConditions( + triggerCycleEvents, + triggerPoiEvents, + triggerConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Verification ... + ENUM_XPOI_EVENTS verificationPoiEvents[]; + ENUM_X_CYCLE_EVENTS verificationCycleEvents[]; + X121SMCCycleConditions verificationConditions; + result = verificationCycleHelper.GetConditions( + verificationCycleEvents, + verificationPoiEvents, + verificationConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Cycles POI States ... + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions triggerXConditions = triggerConditions.x121Conditions; + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + X121Conditions verificationXConditions = verificationConditions.x121Conditions; + X121Conditions consolidationXConditions = consolidationConditions.x121Conditions; + X121Conditions visionXConditions = visionConditions.x121Conditions; + + // + // Setup Conditions ... + + // + // Detect Bar State ... + + // + // PinBar ... + ENUM_X_DIRECTION cBarPinDir; + bool isCBarPin = decisionCycleHelper + .mBarAnalyser + .IsPinBar( + cBar, + cBarPinDir, + 1 // + ); + bool isCBarBullishPin = + isCBarPin && + IsBullish(cBarPinDir); + bool isCBarBearishPin = + isCBarPin && + IsBearish(cBarPinDir); + + // + // Engulf ... + ENUM_X_DIRECTION cBarEngulfDir; + bool isCBarEngulfed = decisionCycleHelper + .mBarAnalyser + .IsEngulfBar( + cBar, + cBarEngulfDir, + 0 // Extended ... + ); + bool isCBarBullishEngulfed = + isCBarEngulfed && + IsBullish(cBarEngulfDir); + bool isCBarBearishEngulfed = + isCBarEngulfed && + IsBearish(cBarEngulfDir); + + // + // Momentum ... + ENUM_X_DIRECTION cBarMomentumDir; + bool isCBarMomentum = decisionCycleHelper + .mBarAnalyser + .IsMomentumBar( + cBar, + cBarMomentumDir, + 0 // Extended ... + ); + bool isCBarBullishMomentum = + isCBarMomentum && + IsBullish(cBarMomentumDir); + bool isCBarBearishMomentum = + isCBarMomentum && + IsBearish(cBarMomentumDir); + + // + // Reject ... + ENUM_X_DIRECTION cBarRejectDir; + bool isCBarRejected = decisionCycleHelper + .mBarAnalyser + .IsRejectionBar( + cBar, + cBarRejectDir, + 0 // Extended ... + ); + bool isCBarBullishRejected = + isCBarRejected && + IsBullish(cBarRejectDir); + bool isCBarBearishRejected = + isCBarRejected && + IsBearish(cBarRejectDir); + + // + // Pull Back ... + ENUM_X_DIRECTION cBarPullbackDir; + bool isCBarPullbacked = + decisionCycleHelper + .mBarAnalyser + .HasPullBack( + cBarPullbackDir, + cBar // + ); + bool isCBarBullishPullbacked = + isCBarPullbacked && + IsBullish(cBarPullbackDir); + bool isCBarBearishPullbacked = + isCBarPullbacked && + IsBearish(cBarPullbackDir); + + // + // HH/LL Break ... + + // + bool isCBarBreaksUpHH = IsBarBreak( + hh, + X_DIRECTION_BULLISH, + cBar // + ); + + // + bool isCBarBreaksDownLL = IsBarBreak( + hh, + X_DIRECTION_BEARISH, + cBar // + ); + + // + // Bars Pattern and Power and Pressures ... + + // + bool hasCBarBullishPattern = + decisionCycleHelper + .mBarAnalyser + .HasBullishPattern( + cBar, + 2 // + ); + + // + bool hasCBarBearishPattern = + decisionCycleHelper + .mBarAnalyser + .HasBearishPattern( + cBar, + 2 // + ); + + // + bool isCBarHasBullishPower = + decisionCycleHelper + .mBarAnalyser + .HasBullishPower( + cBar, + 2 // + ); + + // + bool isCBarHasBearishPower = + decisionCycleHelper + .mBarAnalyser + .HasBearishPower( + cBar, + 2 // + ); + + // + bool isCBarHasBullishPressure = + decisionCycleHelper + .mBarAnalyser + .HasBullishPressure( + cBar, + 2 // + ); + + // + bool isCBarHasBearishPressure = + decisionCycleHelper + .mBarAnalyser + .HasBearishPressure( + cBar, + 2 // + ); + + // + // Bar Checking Summary ... + + // + // Bullish ... + bool isCBarBullishFormed = + // + ( + // + hasCBarBullishPattern && + isCBarHasBullishPower && + isCBarHasBullishPressure + // + ) + // + || + // + ( + // + isCBarBullishPin || + isCBarBreaksUpHH || + isCBarBullishEngulfed || + isCBarBullishMomentum || + isCBarBullishRejected + // + ) + // + ; + + // + // Bearish ... + bool isCBarBearishFormed = + // + ( + // + hasCBarBearishPattern && + isCBarHasBearishPower && + isCBarHasBearishPressure + // + ) + // + || + // + ( + // + isCBarBearishPin || + isCBarBreaksDownLL || + isCBarBearishEngulfed || + isCBarBearishMomentum || + isCBarBearishRejected + // + ) + // + ; + + // + // Detect Order Flow ... + + // + // Test Market For Order Flow ... + int obTestsCount = ArraySize(conditions.obTests); + bool isOBTested = obTestsCount == 2; + if (!isOBTested) + { + // + bool hasTest = ReTestMarket( + conditions.obTests, + consolidationState, + analyseState, + decisionState, + visionCycleHelper.mPOIDrawer // + ); + } + + // + // TODO: + return false; + + // + double upper = 0; + double lower = 0; + + // + // + // + + // + // Summarize Conditions ... + + // + bool isCondition1Bullish = + // + false + // + ; + + // + bool isCondition1Bearish = + // + false + // + ; + + // + bool hasCondition1 = isCondition1Bullish || + isCondition1Bearish; + if (hasCondition1) + { + // + ENUM_X_DIRECTION pzDir = + isCondition1Bullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + double point = GetEntry( + conditions.symbol, + pzDir // + ); + + // + double longPivot = lower; // triggerXConditions.valesBuffer[1]; + double shortPivot = upper; // triggerXConditions.peaksBuffer[1]; + + // + // Manipulate Conditions Point ... + + // + conditions.point = + isCondition1Bullish + ? shortPivot + : longPivot; + + // + // Manipulate Conditions Pivot ... + + // + conditions.pivot = + isCondition1Bullish + ? longPivot + : shortPivot; + } + + // + // + // + + // + isBullish = + // + isCondition1Bullish + // + ; + + // + isBearish = + // + isCondition1Bearish + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + // + // Detect PriceOB Lifetime Bars ... + + // + // Cleanup Arrays ... + Clean(triggerPoiEvents); + Clean(triggerCycleEvents); + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + Clean(verificationPoiEvents); + Clean(verificationCycleEvents); + Clean(consolidationPoiEvents); + Clean(consolidationCycleEvents); + Clean(visionPoiEvents); + Clean(visionCycleEvents); + + // + return result; + } + + // + conditions.setupTime = cTime; + conditions.dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Cleanup Arrays ... + Clean(triggerPoiEvents); + Clean(triggerCycleEvents); + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + Clean(verificationPoiEvents); + Clean(verificationCycleEvents); + Clean(consolidationPoiEvents); + Clean(consolidationCycleEvents); + Clean(visionPoiEvents); + Clean(visionCycleEvents); + + // + return result; +} + +// +// Detect Trigger Conditions ... +bool DetectX121SMCXOBSSignalTrigger( + // + X121SMCStrategyXOBSSignalConditions &conditions, + // + string _symbol, + ENUM_TIMEFRAMES _period, + // + XC121SMCCycleHelper *triggerCycleHelper, + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *verificationCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper, + // + int maxAllowedSetupAge = 60 // + // +) +{ + // + bool result = false; + + // + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + datetime setupTime = conditions.setupTime; + ENUM_X_DIRECTION setupDir = conditions.dir; + + // + bool isBullish = IsBullish(setupDir); + bool isBearish = IsBearish(setupDir); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + string symbol = _symbol; + ENUM_TIMEFRAMES period = _period; + + // + XOHCL zBar; + result = decisionCycleHelper.GetBar( + zBar, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = decisionCycleHelper.GetBar( + cBar, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = decisionCycleHelper.GetBar( + pBar, + pIndex // + ); + if (!result) + { + return result; + } + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + int swingLoopback = 9; + double ll = cBar.FindLowest(swingLoopback, MODE_LOW); + double hh = cBar.FindHighest(swingLoopback, MODE_HIGH); + double llDown = cBar.FindLowesttDown(swingLoopback); + double hhUp = cBar.FindHighestUp(swingLoopback); + + // + // Cycles Conditions ... + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Cycles POI States ... + XPOIState decisionState = decisionConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + + // + // Trigger Conditions ... + + // + // Slopes ... + + // + bool isRsiSlopeBullish = decisionXConditions.isRsiSlopeBullish; + bool isStrSlopeBullish = decisionXConditions.isStrSlopeBullish; + bool isAtrUpperSlopeBullish = decisionXConditions.isAtrUpperSlopeBullish; + bool isAtrLowerSlopeBullish = decisionXConditions.isAtrLowerSlopeBullish; + bool isVwapFastSlopeBullish = decisionXConditions.isVwapFastSlopeBullish; + bool isVwapMidSlopeBullish = decisionXConditions.isVwapMidSlopeBullish; + bool isVwapSlowSlopeBullish = decisionXConditions.isVwapSlowSlopeBullish; + + // + bool isRsiSlopeBearish = decisionXConditions.isRsiSlopeBearish; + bool isStrSlopeBearish = decisionXConditions.isStrSlopeBearish; + bool isAtrUpperSlopeBearish = decisionXConditions.isAtrUpperSlopeBearish; + bool isAtrLowerSlopeBearish = decisionXConditions.isAtrLowerSlopeBearish; + bool isVwapFastSlopeBearish = decisionXConditions.isVwapFastSlopeBearish; + bool isVwapMidSlopeBearish = decisionXConditions.isVwapMidSlopeBearish; + bool isVwapSlowSlopeBearish = decisionXConditions.isVwapSlowSlopeBearish; + + // + bool isSlopesBullish = + isRsiSlopeBullish && + isStrSlopeBullish && + isAtrUpperSlopeBullish && + isAtrLowerSlopeBullish && + isVwapFastSlopeBullish && + isVwapMidSlopeBullish && + isVwapSlowSlopeBullish; + + // + bool isSlopesBearish = + isRsiSlopeBearish && + isStrSlopeBearish && + isAtrUpperSlopeBearish && + isAtrLowerSlopeBearish && + isVwapFastSlopeBearish && + isVwapMidSlopeBearish && + isVwapSlowSlopeBearish; + + // + double point = conditions.point; + bool isPointBreaked = IsBarBreak( + point, + setupDir, + cBar // + ); + + // + // Summary ... + + // + isBullish = + // + isBullish && + isPointBreaked && + isSlopesBullish + // + ; + + // + isBearish = + // + isBearish && + isPointBreaked && + isSlopesBearish + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + // + // Cleanup Setup Conditions ... + int setupAge = conditions.GetSetupAge(); + if (IsValidSize(setupAge) && + IsValidSize(maxAllowedSetupAge) && + setupAge >= maxAllowedSetupAge) + { + conditions.Clean(); + } + + // + // Cleanup Arrays ... + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + return result; + } + + // + // Detect Nearest Pivot Point ... + + // + double entry = GetEntry( + conditions.symbol, + setupDir // + ); + + // + double sls[]; + Add( + conditions.pivot, + sls // + ); + + // + double iAtr = decisionConditions.x121Conditions.atrBuffer[1]; + iAtr *= 1.5; + + // + double slsMin = GetMin(sls); + double slsMax = GetMax(sls); + + // + double sl = isBullish + ? slsMin - iAtr + : slsMax + iAtr; + double risk = MathAbs(entry - sl); + + // + // Filling Conditions Props ... + conditions.sl = sl; + // conditions.target = target; + conditions.triggerTime = cTime; + conditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + // Cleanup Arrays ... + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + return result; +} + +// +// Detect Guards ... +bool DetectX121SMCXOBSGuards( + X121SMCGuard &guards[], + const XPosition &positions[], + XC121SMCCycleHelper *triggerCycleHelper, + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *verificationCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper // +) +{ + // + bool result = false; + + // + string provider = ToString(X_121_SMC_PROVIDER_X); + + // + result = DetectX121SMCGuards( + provider, + guards, + positions, + triggerCycleHelper, + decisionCycleHelper, + analyseCycleHelper, + verificationCycleHelper, + consolidationCycleHelper, + visionCycleHelper, + // + true, // CloseOnTPNear Guard ... + true, // CloseLongsOnBearishTrend Guard ... + true, // CloseShortsOnBullishTrend Guard ... + true, // CloseAllWeekend Guard ... + true, // PartialCloseOnTrendChange Guard ... + true, // TrailStop Guard ... + true, // TrailTarget Guard ... + true // Hedge Guard ... + // + ); + + // + return result; +} + +// +// Add Conditions to Conditions Collection ... +int AddX121SMCXOBSConditionsIfNotExists( + X121SMCStrategyXOBSSignalConditions &item, + X121SMCStrategyXOBSSignalConditions &items[], + int maxAllowed = 10 // +) +{ + // + int result = 0; + + // + bool isSetuped = IsValid(item.setupTime) && + HasDirection(item.dir); + if (!isSetuped) + { + return result; + } + + // + int count = ArraySize(items); + if (IsValidSize(count)) + { + // + // Copy Original Items ... + X121SMCStrategyXOBSSignalConditions tmpItems[]; + Copy( + items, + tmpItems // + ); + + // + // Prese Item Data ... + bool isBullish = IsBullish(item.dir); + + // + for (int i = 0; i < count; i++) + { + // + X121SMCStrategyXOBSSignalConditions iItem = tmpItems[i]; + + // + bool canRemove = item.dir == iItem.dir && + item.pivot == iItem.pivot; + if (canRemove) + { + // + ArrayRemove( + items, + i, + 1 // + ); + } + } + + // + Clean(tmpItems); + } + + // + AddRef( + item, + items // + ); + + // + // Remove Olds ... + CleanupArray( + items, + maxAllowed // + ); + + // + result = ArraySize(items); + + // + return result; +} + +// +// +// + +/** + * Retest Market ... + * + * @param test: XOBTest instance Reference, Represet Result Test ... + * @param tests: XOBTest instance Reference Collection, Represet Founded Tests till now ... + * @param htfState: XPOIState instance Reference ... + * @param mtfState: XPOIState instance Reference ... + * @param ttfState: XPOIState instance Reference ... + * + * @return ( bool ) + */ +bool ReTestMarket( + XOBTest &tests[], + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &ttfState, // + // + XCPOIDrawer *drawer + // +) +{ + // + XCBaseObject *drawnObjects[]; + + // + bool result = false; + + // + Clean(tests); + + // + datetime cTime = TimeCurrent(); + + // + XOBTest mTest; + mTest.symbol = ttfState.symbol; + mTest.period = ttfState.period; + + // + // Detect Order Blocks ... + // HTF ... + + // + // Bullish OBs ... + XCOrderBlock *bullOBs[]; + bool hasYoungestBullOB = false; + XOHCL youngestBullOBStartedBar; + bool isYoungestBullOBStarted = false; + ENUM_X_DIRECTION youngestBullOBStartedDir; + XCOrderBlock *youngestBullOB = NULL; + int bullOBsCount = ExtractUnActivatedOBs( + htfState.bullishOrderBlocks, + bullOBs // + ); + + // + bool isBullOBsPassed = bullOBsCount >= 1; + if (isBullOBsPassed) + { + // + XBoxZone boxes[]; + int boxesCount = ToBox( + bullOBs, + boxes // + ); + int youngestBoxIDX = GetYoungest(boxes); + hasYoungestBullOB = IsValidIndex(youngestBoxIDX); + if (hasYoungestBullOB) + { + // + youngestBullOB = bullOBs[youngestBoxIDX]; + + // + isYoungestBullOBStarted = youngestBullOB.IsStarted( + X_DIRECTION_BULLISH, + youngestBullOBStartedBar, + youngestBullOBStartedDir // + ); + } + } + + // + // Bearish OBs ... + XCOrderBlock *bearOBs[]; + bool hasYoungestBearOB = false; + XOHCL youngestBearOBStartedBar; + bool isYoungestBearOBStarted = false; + ENUM_X_DIRECTION youngestBearOBStartedDir; + XCOrderBlock *youngestBearOB = NULL; + int bearOBsCount = ExtractUnActivatedOBs( + htfState.bearishOrderBlocks, + bearOBs // + ); + + // + bool isBearOBsPassed = bearOBsCount >= 1; + if (isBearOBsPassed) + { + // + XBoxZone boxes[]; + int boxesCount = ToBox( + bearOBs, + boxes // + ); + int youngestBoxIDX = GetYoungest(boxes); + hasYoungestBearOB = IsValidIndex(youngestBoxIDX); + if (hasYoungestBearOB) + { + // + youngestBearOB = bearOBs[youngestBoxIDX]; + + // + isYoungestBearOBStarted = youngestBearOB.IsStarted( + X_DIRECTION_BEARISH, + youngestBearOBStartedBar, + youngestBearOBStartedDir // + ); + } + } + + // + bool hasYoungestOB = hasYoungestBullOB || + hasYoungestBearOB; + result = hasYoungestOB; + if (!result) + { + // + mTest.Clean(); + 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(), + iBreakerBar.period, + i // + ); + if (!isInited) + { + continue; + } + + // + isValid = iBar.low > iOB.Upper(); + if (!isValid) + { + break; + } + } + if (!isValid) + { + continue; + } + + // + // Bullish Order Blocks must Appear on Below on Last OB ... + XCOrderBlock *lastOB = NULL; + breakedBullOBsCount = ArraySize(breakedBullOBs); + bool hasLastOB = IsValidSize(breakedBullOBsCount); + if (hasLastOB) + { + lastOB = breakedBullOBs[breakedBullOBsCount - 1]; + } + bool isLastOBPassed = + !hasLastOB + ? true + : IsBelow( + iOB, + lastOB // + ); + if (!isLastOBPassed) + { + 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; + } + + // + // Detect Related FVG ... + + // + XCFVG *iFVG = NULL; + bool hasFVG = false; + bool hasFVGs = mtfState.HasBullishFairValueGaps(); + int fvgsCount = mtfState.CountBullishFairValueGaps(); + if (hasFVGs) + { + // + for (int j = 0; j < fvgsCount; j++) + { + // + XCFVG *jFVG = mtfState.bullishFairValueGaps[j]; + + // + // Detect FVG From date ... + bool isFromPassed = jFVG.From() > iOB.From(); + if (!isFromPassed) + { + continue; + } + + // + // Check Fair Value Gaps Must be inside or Above that OB ... + bool isAbove = IsAboveDiff( + jFVG, + iOB, + true // Ignore Inside ... + ); + bool isInside = IsInsideDiff( + jFVG, + iOB // + ); + bool isPricePassed = isInside || + isAbove; + if (!isPricePassed) + { + continue; + } + + // + // Check Liquidity Sweep Before FVG ... + bool isLiquiditySweeped = false; + + if (!isLiquiditySweeped) { + continue; + } + + // + // Set Nearest Valid FVG to OB From ... + bool canSetFVG = + !hasFVG + ? true + : iFVG.From() > jFVG.From(); + + // + if (canSetFVG) + { + // + iFVG = jFVG; + hasFVG = iFVG != NULL && + iFVG.IsValid(); + } + } + } + + // + if (!hasFVG) + { + continue; + } + + // + XCBaseObject *iOBObj; + XCBaseObject *iFVGObj; + bool isOBCreated = drawer.CreateOrderBlock( + iOB, + iOBObj // + ); + bool isFVGCreated = drawer.CreateFairValueGap( + iFVG, + iFVGObj // + ); + + // + Add( + iOB, + breakedBullOBs // + ); + + // + } + } + + // + breakedBullOBsCount = ArraySize(breakedBullOBs); + hasBreakedBullOBs = IsValidSize(breakedBullOBsCount); + } + + // + Print("OBs Passed ..."); + + // + return result; +} + +/** + * Extract UnActivated Order Blocks ... + * + * @return ( int ) + */ +int ExtractUnActivatedOBs( + XCOrderBlock *&source[], + XCOrderBlock *&obs[] // +) +{ + // + int result = 0; + + // + Clean(obs); + + // + int count = ArraySize(source); + bool hasOB = IsValidSize(count); + if (!hasOB) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isBullish = source[i].IsBullish(); + ENUM_X_DIRECTION forDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // + // + + // + XOHCL activatedBar; + ENUM_X_DIRECTION activatedDir; + bool isActivated = source[i].IsActivated( + forDir, + activatedBar, + activatedDir // + ); + if (!isActivated) + { + // + Add( + source[i], + obs // + ); + } + } + + // + result = ArraySize(obs); + + // + return result; +} + +bool TestFVG( + XCFVG *fvg, + double &reward, + datetime &rewardedAt, + // + XCPOIDrawer *drawer, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + reward = 0; + rewardedAt = NULL; + + // + result = fvg != NULL && + fvg.IsValid(); + if (!result) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = fvg.GetPeriod(); + } + + // + bool isBullish = fvg.IsBullish(); + ENUM_X_DIRECTION forDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + XOHCL endBar; + result = fvg.FillEndBar(endBar); + if (!result) + { + return result; + } + + // + XOHCL startBar; + result = fvg.FillStartBar(startBar); + if (!result) + { + return result; + } + + // + XOHCL activatedBar; + ENUM_X_DIRECTION activatedDir; + result = fvg.IsActivated( + forDir, + activatedBar, + activatedDir, + forPeriod // + ); + if (!result) + { + return result; + } + + // + XOHCL breakedBar; + ENUM_X_DIRECTION breakedDir; + result = fvg.IsBreaked( + forDir, + breakedBar, + breakedDir, + forPeriod // + ); + if (!result) + { + return result; + } + + // + XOHCL triggerBar; + result = breakedBar.GetNextBar(triggerBar); + if (!result) + { + return result; + } + + // + int breakedIndex = breakedBar.Index(); + int triggerIndex = triggerBar.Index(); + + // + XRR fvgRR; + + // + string symbol = triggerBar.symbol; + ENUM_TIMEFRAMES period = triggerBar.period; + + // + double points = GetPoints(symbol); + + // + double sl = + isBullish + ? fvg.Lower() - 10 * points + : fvg.Upper() + 10 * points; + double entry = + isBullish + ? fvg.Upper() + : fvg.Lower(); + ENUM_X_POSITION_TYPES type = + isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + result = fvgRR.Init( + symbol, + period, + sl, + entry, + type // + ); + if (!result) + { + return result; + } + fvgRR.time = breakedBar.time; + + // + XCRRObject *iObj; + result = drawer.CreateRR( + fvgRR, + iObj // + ); + if (!result) + { + return result; + } + + // + Print("RR Created ..."); + + // + return result; +} + +// diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index dbd5b2cc..d00e838f 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -135,6 +135,35 @@ enum ENUM_X_SWING_TYPE X_SWING_LOW = -1, }; +// +string ToString(ENUM_X_SWING_TYPE value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_NO_SWING: + result = "NO_SWING"; + break; + + // + case X_SWING_LOW: + result = "SWING_LOW"; + break; + + // + case X_SWING_HIGH: + result = "SWING_HIGH"; + break; + } + + // + return result; +} + // ENUM_SERIESMODE ToSeriesMode(ENUM_X_SWING_TYPE value) { @@ -1163,6 +1192,34 @@ struct XOHCL return result; } + // + // Retrieve Required Price for Zone Checking ... + // For Bullish Zones => low; + // For Bearish Zones => high; + double GetZoneCheckValue(ENUM_X_DIRECTION forDir) + { + // + double result = 0; + + // + if (!IsValid() || + !HasDirection(forDir)) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + result = + isBullish + ? low + : high; + + return result; + } + // // Calculate Bar Body ... double GetBody() @@ -3522,6 +3579,133 @@ struct XMarketParser // }; +// +// Specified Swing Point ... +struct XSwingPoint +{ + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + + // + double swing; + datetime time; + ENUM_X_SWING_TYPE type; + + // + // Constructor ... + XSwingPoint() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + swing = 0; + time = NULL; + + // + symbol = NULL; + period = NULL; + + // + type = X_NO_SWING; + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + swing > 0 && + IsValid(time) && + IsValid(symbol) && + IsValid(period) && + type != X_NO_SWING; + + // + return result; + } + + /** + * Check Swing is Low or not ... + * + * @return ( bool ) + */ + bool IsSwingLow() + { + return type == X_SWING_LOW; + } + + /** + * Check Swing is High or not ... + * + * @return ( bool ) + */ + bool IsSwingHigh() + { + return type == X_SWING_HIGH; + } +}; + +/** + * Extract values of swings from specified Collection ... + * + * @param swings: XSwingPoint instance Collection ... + * @param values: double Collection ... + * + * @return ( int ) + */ +int ExtractSwings( + XSwingPoint &swings[], + double &values[] // +) +{ + // + int result = 0; + + // + Clean(values); + + // + int count = ArraySize(swings); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + Add( + swings[i].swing, + values // + ); + } + + // + result = ArraySize(values); + + // + return result; +} + // // Functions ... @@ -7544,6 +7728,61 @@ T GetMax( return result; } template +T GetMax( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + index = -1; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + bool isNew = result == 0; + bool canSet = isNew || + (!isNew && + result < iValue); + if (canSet) + { + // + index = i; + result = iValue; + } + } + + // + return result; +} +template T GetSpecifiedMax( T &buffer[], // the Buffer which required to search int start = 0, // Start Index @@ -7556,6 +7795,21 @@ T GetSpecifiedMax( count // ); } +template +T GetSpecifiedMax( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMax( + buffer, + index, + start, + count // + ); +} // // Get Min of Specific Loopback of a Buffer ... @@ -7612,6 +7866,61 @@ T GetMin( return result; } template +T GetMin( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + index = -1; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + bool isNew = result == 0; + bool canSet = isNew || + (!isNew && + result > iValue); + if (canSet) + { + // + index = i; + result = iValue; + } + } + + // + return result; +} +template T GetSpecifiedMin( T &buffer[], // the Buffer which required to search int start = 0, // Start Index @@ -7624,6 +7933,21 @@ T GetSpecifiedMin( count // ); } +template +T GetSpecifiedMin( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMin( + buffer, + index, + start, + count // + ); +} // // Find a Value less than Specified ... @@ -7651,12 +7975,14 @@ T FindLesserThan( // ArrayResize( tmp, - ArraySize(source)); + ArraySize(source) // + ); // ArrayCopy( tmp, - source); + source // + ); // // Sort Temp Buffer ... @@ -7685,6 +8011,69 @@ T FindLesserThan( // return result; } +template +T FindLesserThan( + T value, // Specified Value ... + int &index, // Item Index ... + const T &source[], // Source ... + bool isDescend = false // Find Biggest Lesser Value ... +) +{ + // + T result = -1; + index = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue < value) + { + // + index = i; + result = iValue; + break; + } + } + + // + return result; +} // // Find a Value less than Specified ... @@ -7712,12 +8101,14 @@ T FindBiggerThan( // ArrayResize( tmp, - ArraySize(source)); + ArraySize(source) // + ); // ArrayCopy( tmp, - source); + source // + ); // // Sort Temp Buffer ... @@ -7746,6 +8137,69 @@ T FindBiggerThan( // return result; } +template +T FindBiggerThan( + T value, // Specified Value ... + int &index, // Item Index ... + const T &source[], // Source ... + bool isDescend = false // Find Smallest Bigger Value ... +) +{ + // + T result = -1; + index = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (!isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue > value) + { + // + index = i; + result = iValue; + break; + } + } + + // + return result; +} // // Find Same Values in Array ... diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index 39132e1d..a489972b 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -988,6 +988,7 @@ class XCBarZone : public XCZone * @param forDir: ENUM_X_DIRECTION member, Specified Action Direction ... * @param breakerBar: XOHCL instance Reference ... * @param breakerDir: ENUM_X_DIRECTION member ... + * @param ignoreActivation: ignore Zone Activation and Used Start ... * @param forPeriod: ENUM_TIMEFRAMES member, Specified Rejection Period ... * * @return ( bool ) @@ -996,6 +997,7 @@ class XCBarZone : public XCZone ENUM_X_DIRECTION forDir, XOHCL &breakerBar, ENUM_X_DIRECTION &breakerDir, + bool ignoreActivation = false, ENUM_TIMEFRAMES forPeriod = NULL // ) { @@ -1022,22 +1024,60 @@ class XCBarZone : public XCZone } // - XOHCL activatedBar; - ENUM_X_DIRECTION activatedDir; - bool isActivated = IsActivated( - forDir, - activatedBar, - activatedDir, - forPeriod // - ); - result = isActivated; + bool isBullish = IsBullish(forDir); + bool isBearish = IsBearish(forDir); + int activatedIndex = -1; + + // + if (!ignoreActivation) + { + // + XOHCL activatedBar; + ENUM_X_DIRECTION activatedDir; + bool isActivated = IsActivated( + forDir, + activatedBar, + activatedDir, + forPeriod // + ); + result = isActivated; + if (!result) + { + return result; + } + + // + activatedIndex = activatedBar.Index(); + } + else + { + // + XOHCL startedBar; + ENUM_X_DIRECTION startedDir; + bool isStarted = IsActivated( + forDir, + startedBar, + startedDir, + forPeriod // + ); + result = isStarted; + if (!result) + { + return result; + } + + // + activatedIndex = startedBar.Index(); + } + + // + result = IsValidIndex(activatedIndex); if (!result) { return result; } // - int activatedIndex = activatedBar.Index(); activatedIndex--; // @@ -1069,16 +1109,30 @@ class XCBarZone : public XCZone // bool isBreakedFromUpper = // - (iPBar.high <= Upper() && - iBar.low > Upper()) + isBullish && + // + ( + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper()) + // + ) // ; // bool isBreakedFromLower = // - (iPBar.low >= Lower() && - iBar.low < Lower()) + isBearish && + // + ( + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower()) + // + ) // ; @@ -1414,6 +1468,150 @@ class XCBarZone : public XCZone return result; } + /** + * Check to Find Nearest Bar which Breakes Upper ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromUpper( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.low < Upper(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Lower ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromLower( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.high > Lower(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + // // Overrides ... @@ -2311,6 +2509,150 @@ class XCTwoBarZone : public XCZone return result; } + /** + * Check to Find Nearest Bar which Breakes Upper ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromUpper( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.low < Upper(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Lower ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromLower( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.high > Lower(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + // // Overrides ... @@ -3265,6 +3607,27 @@ class XCOrderBlock : public XCBarZone return result; } + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + // // Overrides ... @@ -3715,6 +4078,27 @@ class XCFVG : public XCTwoBarZone return result; } + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + // // Overrides ... @@ -6119,6 +6503,96 @@ bool ToBox( return result; } +template +int GetOldest( + T *&sourec[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetOldest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetYoungest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetYoungest(boxes); + + // + Clean(boxes); + + // + return result; +} + template bool IsSame( T *source, @@ -6495,6 +6969,122 @@ bool FindIndex( return result; } +template +bool IsInside( + double value, + T *source // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + result = IsInsideBox( + value, + sourceBox // + ); + + // + return result; +} + +template +bool IsAbove( + double value, + T *source // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + result = IsAboveBox( + value, + sourceBox // + ); + + // + return result; +} + +template +bool IsBelow( + double value, + T *source // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + result = IsBelowBox( + value, + sourceBox // + ); + + // + return result; +} + +template +void UpdateTo( + T *&source[], + datetime time = NULL // +) +{ + // + if (!IsValid(time)) + { + time = TimeCurrent(); + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + source[i].To(time); + } +} + /** * Find Specified Box Index inside a Collection of Boxes ... * @@ -6641,7 +7231,7 @@ bool IsBoxAbove( * * @return ( bool ) */ -bool IsBoxAbove( +bool IsBoxInside( XBoxZone &source, XBoxZone &dest // ) @@ -6666,6 +7256,82 @@ bool IsBoxAbove( return result; } +/** + * Check Value is Inside Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsInsideBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value <= box.upper && + value >= box.lower; + + // + return result; +} + +/** + * Check Value is Above Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsAboveBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value > box.upper; + + // + return result; +} + +/** + * Check Value is Below Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsBelowBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value < box.lower; + + // + return result; +} + /** * Converts a Consolidation Zone ... * @@ -7133,4 +7799,405 @@ typedef void (*TOnPOIEvent)(ENUM_XPOI_EVENTS event, XCBasePOI *param // ); +// +// +// + +/** + * Extract UnActivated Order Blocks ... + * + * @return ( int ) + */ +int ExtractUnActivatedOrderBlocks( + XCOrderBlock *&source[], + XCOrderBlock *&dest[] // +) +{ + // + int result = 0; + + // + Clean(dest); + + // + int count = ArraySize(source); + int hasChild = IsValidSize(count); + if (!hasChild) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iChild = source[i]; + ENUM_X_DIRECTION iChildForDir = iChild.GetDirection(); + + // + // Validate Started Zones ... + XOHCL iChildStartedBar; + ENUM_X_DIRECTION iChildStartedDir; + bool isStarted = iChild.IsStarted( + iChildForDir, + iChildStartedBar, + iChildStartedDir // + ); + if (!isStarted) + { + continue; + } + + // + // Validate InActive Zone ... + XOHCL iChildActivatedBar; + ENUM_X_DIRECTION iChildActivatedDir; + bool isActivated = iChild.IsActivated( + iChildForDir, + iChildActivatedBar, + iChildActivatedDir // + ); + if (isActivated) + { + continue; + } + + // + // Validate Zone Iverse Breake ... + XOHCL iChildBreakedBar; + ENUM_X_DIRECTION iChildBreakedDir; + bool isBreaked = iChild.IsBreaked( + Opposit(iChildForDir), + iChildBreakedBar, + iChildBreakedDir, + true // Ignore Activation ... + ); + if (isBreaked) + { + continue; + } + + // + int iChildIDX = -1; + bool isIChildExists = FindIndex( + iChildIDX, + iChild, + dest // + ); + if (isIChildExists) + { + continue; + } + + // + Add( + iChild, + dest // + ); + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Extract Directinal Based Order Blocks ... + * + * @param forDir: ENUM_X_DIRECTION member ... + * + * @return ( int ) + */ +int ExtractDirectionalOrderBlocks( + ENUM_X_DIRECTION forDir, + XCOrderBlock *&source[], + XCOrderBlock *&dest[] // +) +{ + // + int result = 0; + + // + Clean(dest); + + // + int count = ArraySize(source); + if (!IsValidSize(count) || + !HasDirection(forDir)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iOB = source[i]; + + // + ENUM_X_DIRECTION iForDir = iOB.GetDirection(); + if (forDir == iForDir) + { + // + Add( + iOB, + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Sort Order Blocks based on Place and Remove unused ... + */ +void OrderedSortOrderBlocks( + XCOrderBlock *youngest, + XCOrderBlock *&orderBlocks[] // +) +{ + // + int count = ArraySize(orderBlocks); + if (youngest == NULL || + !youngest.IsValid() || + !IsValidSize(count)) + { + return; + } + + // + ENUM_X_DIRECTION dir = youngest.GetDirection(); + bool isBullish = IsBullish(dir); + + // + XCOrderBlock *tmp[]; + XCOrderBlock *lastOB = youngest; + while (IsValidSize(count)) + { + // + // Detect Youngest of Collection ... + int idx = GetYoungest(orderBlocks); + XCOrderBlock *iOB = orderBlocks[idx]; + ArrayRemove( + orderBlocks, + idx, + 1 // + ); + count = ArraySize(orderBlocks); + + // + // Check Direction Must be Same ... + ENUM_X_DIRECTION iDir = iOB.GetDirection(); + bool isSameDir = dir == iDir; + if (!isSameDir) + { + continue; + } + + // + // Check Creation time Sequence ... + bool isFromPassed = lastOB.From() > iOB.From(); + if (!isFromPassed) + { + continue; + } + + // + // Check Order Block Place ... + bool isPlacePassed = + isBullish + ? IsBelow( + iOB, + lastOB, + true // Ignore Inside ... + ) + : IsAbove( + iOB, + lastOB, + true // Ignore Inside ... + ); + if (!isPlacePassed) + { + continue; + } + + // + // Update Last OB ... + lastOB = iOB; + Add( + iOB, + tmp // + ); + + // + } + + // + // Update Ordered Sorted Order Blocks ... + count = ArraySize(tmp); + if (IsValidSize(count)) + { + // + Copy( + tmp, + orderBlocks // + ); + } +} + +/** + * Extract Order Flows Swing Points ... + * + * @param type: ENUM_X_SWING_TYPE member ... + * @param swings: double Collection ... + * + * @return ( int ) + */ +int ExtractSwingPoints( + ENUM_X_SWING_TYPE type, + XCOrderBlock *&orderBlocks[], + XSwingPoint &swings[] // +) +{ + // + int result = 0; + + // + Clean(swings); + + // + int count = ArraySize(orderBlocks); + + // + if (type == X_NO_SWING || + !IsValidSize(count)) + { + return result; + } + + // + bool lookingForSwingLows = type == X_SWING_LOW; + + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iOB = orderBlocks[i]; + + // + string iSymbol = iOB.GetSymbol(); + ENUM_TIMEFRAMES iPeriod = iOB.GetPeriod(); + + // + int fromIndex = iBarShift( + iSymbol, + iPeriod, + iOB.From() // + ); + + // + fromIndex++; + + // + double iValue = 0; + datetime iVTime = NULL; + if (lookingForSwingLows) + { + // + int idx = iLowest( + iSymbol, + iPeriod, + MODE_LOW, + fromIndex // + ); + + // + if (IsValidIndex(idx)) + { + // + iValue = iLow( + iSymbol, + iPeriod, + idx // + ); + + // + iVTime = iTime( + iSymbol, + iPeriod, + idx // + ); + } + } + else + { + // + int idx = iHighest( + iSymbol, + iPeriod, + MODE_HIGH, + fromIndex // + ); + + // + if (IsValidIndex(idx)) + { + // + iValue = iHigh( + iSymbol, + iPeriod, + idx // + ); + + // + iVTime = iTime( + iSymbol, + iPeriod, + idx // + ); + } + } + + // + if (iValue > 0) + { + // + XSwingPoint iSwingP; + + // + iSwingP.type = type; + iSwingP.time = iVTime; + iSwingP.swing = iValue; + iSwingP.symbol = iSymbol; + iSwingP.period = iPeriod; + + // + if (iSwingP.IsValid()) + { + // + AddRef( + iSwingP, + swings // + ); + } + + // + iSwingP.Clean(); + } + } + + // + result = ArraySize(swings); + + // + return result; +} + // \ No newline at end of file diff --git a/Libraries/x-saherelm.x-trade.lib.mq5 b/Libraries/x-saherelm.x-trade.lib.mq5 index e6a4e015..c3f992b3 100644 --- a/Libraries/x-saherelm.x-trade.lib.mq5 +++ b/Libraries/x-saherelm.x-trade.lib.mq5 @@ -300,6 +300,189 @@ ENUM_X_DIRECTION ToDirection(ENUM_X_POSITION_TYPES value) // // Structs ... +// +struct XRR +{ + // + double tps[]; + + // + double sl; + double entry; + + // + string prefix; + string symbol; + datetime time; + ENUM_TIMEFRAMES period; + + // + ENUM_X_POSITION_TYPES type; + + // + // Constructor ... + XRR() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + sl = 0; + entry = 0; + + // + time = NULL; + prefix = NULL; + period = NULL; + symbol = NULL; + + // + type = X_POSITION_TYPE_NONE; + + // + Clean(tps); + } + + // + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + double _sl, + double _entry, + ENUM_X_POSITION_TYPES _type, + string _prefix = NULL // + ) + { + // + bool result = false; + + // + result = + _sl > 0 && + _entry > 0 && + IsValid(_symbol) && + IsValid(_period) && + _type != X_POSITION_TYPE_ALL && + _type != X_POSITION_TYPE_NONE && + (_type == X_POSITION_TYPE_LONG + ? _entry > _sl + : _entry < _sl); + if (!result) + { + return result; + } + + // + Default(); + + // + sl = _sl; + type = _type; + entry = _entry; + symbol = _symbol; + period = _period; + prefix = _prefix; + + // + time = TimeCurrent(); + + // + result = IsValid(); + + // + return result; + } + + // + void Default() + { + // + Add( + 1.0, + tps // + ); + Add( + 1.5, + tps // + ); + Add( + 2.0, + tps // + ); + Add( + 3.0, + tps // + ); + Add( + 4.0, + tps // + ); + Add( + 5.0, + tps // + ); + Add( + 6.0, + tps // + ); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + sl > 0 && + entry > 0 && + IsValid(time) && + IsValid(symbol) && + IsValid(period) && + IsValidSize(ArraySize(tps)) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE && + (type == X_POSITION_TYPE_LONG + ? entry > 0 + : entry < sl); + + // + return result; + } + + // + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + // + result = GetTypeName(this); + return result; + } + + // + string sep = "_"; + + // + result = + GetTypeName(this) + sep + (IsValid(prefix) ? prefix + sep : "") + symbol + sep + ToString(period) + sep + ToFormatString(time) + sep + ToString(type); + + // + return result; + } +}; + // // Model an Open Position ... struct XPosition diff --git a/X121SMCEA/Libraries/x-121.smc.lib.mq5 b/X121SMCEA/Libraries/x-121.smc.lib.mq5 index 5798f7a2..c458bad4 100644 --- a/X121SMCEA/Libraries/x-121.smc.lib.mq5 +++ b/X121SMCEA/Libraries/x-121.smc.lib.mq5 @@ -755,4 +755,4 @@ ENUM_X_121_SMC_PROVIDERS ParseProvider(string value) return result; } -// \ No newline at end of file +// diff --git a/X121SMCEA/Signals/x-121.smc.xobs.signal.lib.mq5 b/X121SMCEA/Signals/x-121.smc.xobs.signal.lib.mq5 index 41df1c4c..25f50c33 100644 --- a/X121SMCEA/Signals/x-121.smc.xobs.signal.lib.mq5 +++ b/X121SMCEA/Signals/x-121.smc.xobs.signal.lib.mq5 @@ -26,74 +26,6 @@ #include "../Libraries/x-121.smc.guard.lib.mq5" #include "../Libraries/x-121.smc.lib.mq5" -// -struct XOBTest -{ - // - // Props ... - - // - string symbol; - ENUM_TIMEFRAMES period; - - // - XCOrderBlock *ob; - XCFVG *fvgs[]; - - // - datetime fvgActedAt; - datetime rewardedAt; - - // - double reward; - - // - // Constructor ... - XOBTest() - { - Clean(); - } - - // - // Tools ... - - // - void Clean() - { - // - ob = NULL; - symbol = NULL; - period = NULL; - rewardedAt = NULL; - fvgActedAt = NULL; - - // - reward = 0; - - // - Clean(fvgs); - } - - // - bool HasOB() - { - return ob != NULL && - ob.IsValid(); - } - - // - int CountFVGs() - { - return ArraySize(fvgs); - } - - // - bool HasFVGs() - { - return IsValidSize(CountFVGs()); - } -}; - // // Definitions ... struct X121SMCStrategyXOBSSignalConditions @@ -123,8 +55,16 @@ struct X121SMCStrategyXOBSSignalConditions double point; // - // Extwnsion ... - XOBTest obTests[]; + XCOrderBlock *validBullishOBs[]; + XCOrderBlock *validBearishOBs[]; + + // + XCOrderBlock *youngestBullishOB; + XCOrderBlock *youngestBearishOB; + + // + XSwingPoint swings[]; + XCOrderBlock *insideOB; // // Constructor ... @@ -248,7 +188,142 @@ struct X121SMCStrategyXOBSSignalConditions point = 0; // - Clean(obTests); + Clean(swings); + Clean(validBullishOBs); + Clean(validBearishOBs); + + // + insideOB = NULL; + youngestBullishOB = NULL; + youngestBearishOB = NULL; + } + + // + // + // + + // + bool HasInsideOB() + { + return insideOB != NULL && + insideOB.IsValid(); + } + + // + bool HasValidBullishOBs() + { + return IsValidSize(CountValidBullishOBs()); + } + + // + int CountValidBullishOBs() + { + return ArraySize(validBullishOBs); + } + + // + bool HasValidBearishOBs() + { + return IsValidSize(CountValidBearishOBs()); + } + + // + int CountValidBearishOBs() + { + return ArraySize(validBearishOBs); + } + + // + bool HasYoungestBullishOB() + { + return youngestBullishOB != NULL && + youngestBullishOB.IsValid(); + } + + // + bool HasYoungestBearishOB() + { + return youngestBearishOB != NULL && + youngestBearishOB.IsValid(); + } + + // + bool HasOrderFlow(ENUM_X_DIRECTION &orderFlowDir) + { + // + bool result = false; + + // + orderFlowDir = X_DIRECTION_NONE; + + // + bool hasValidBullishOBs = HasValidBullishOBs(); + bool hasValidBearishOBs = HasValidBearishOBs(); + int validBullishOBsCount = CountValidBullishOBs(); + int validBearishOBsCount = CountValidBearishOBs(); + bool hasYoungestBullishOB = HasYoungestBullishOB(); + bool hasYoungestBearishOB = HasYoungestBearishOB(); + + // + bool hasBullish = + hasYoungestBullishOB && + hasValidBullishOBs && + validBullishOBsCount == 2; + + // + bool hasBearish = + hasYoungestBearishOB && + hasValidBearishOBs && + validBearishOBsCount == 2; + + // + result = (hasBullish && + !hasBearish) || + (!hasBullish && + hasBearish); + if (result) + { + // + orderFlowDir = + hasBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + // + int CountSwings() + { + return ArraySize(swings); + } + + // + bool HasSwings() + { + return IsValidSize(CountSwings()) && + CountSwings() >= 2; + } + + // + ENUM_X_SWING_TYPE GetSwingType() + { + // + ENUM_X_SWING_TYPE result = X_NO_SWING; + + // + if (!HasSwings()) + { + return result; + } + + // + result = swings[0].type; + + // + return result; } // @@ -256,8 +331,9 @@ struct X121SMCStrategyXOBSSignalConditions // // Signaller Data Sources ... -X121SMCStrategyXOBSSignalConditions mXOBSConditions; -X121SMCStrategyXOBSSignalConditions mXOBSConditionsCollection[]; +X121SMCStrategyXOBSSignalConditions mX121SMCXOBSConditions; +X121SMCStrategyXOBSSignalConditions mX121SMCXOBSConditionsCollection[]; +CArrayObj mX121SMCXOBSObjects; // // Extension Functions ... @@ -305,57 +381,12 @@ bool DetectX121SMCXOBSSignalSetup( conditions.symbol = symbol; conditions.period = period; - // - XC121SMCCycleHelper *barCycle = triggerCycleHelper; - - // - XOHCL zBar; - result = barCycle.GetBar( - zBar, - zIndex // - ); - if (!result) - { - return result; - } - - // - XOHCL cBar; - result = barCycle.GetBar( - cBar, - cIndex // - ); - if (!result) - { - return result; - } - - // - XOHCL pBar; - result = barCycle.GetBar( - pBar, - pIndex // - ); - if (!result) - { - return result; - } - // double ask = GetAsk(symbol); double bid = GetBid(symbol); datetime cTime = TimeCurrent(); double points = GetPoints(symbol); - // - int swingLoopback = 7; - double ll = cBar.FindLowest(swingLoopback, MODE_LOW); - double hh = cBar.FindHighest(swingLoopback, MODE_HIGH); - double ll50 = cBar.FindLowest(50, MODE_LOW); - double hh50 = cBar.FindHighest(50, MODE_HIGH); - double llDown = cBar.FindLowesttDown(swingLoopback); - double hhUp = cBar.FindHighestUp(swingLoopback); - // // Cycles Conditions ... @@ -481,245 +512,588 @@ bool DetectX121SMCXOBSSignalSetup( // // Setup Conditions ... + mX121SMCXOBSObjects.Clear(); + XCPOIDrawer *drawer = visionCycleHelper.mPOIDrawer; // - // Detect Bar State ... + bool hasInsideOB = conditions.HasInsideOB(); + bool hasValidBullishOBs = conditions.HasValidBullishOBs(); + int validBullishOBsCount = conditions.CountValidBullishOBs(); + bool hasValidBearishOBs = conditions.HasValidBearishOBs(); + int validBearishOBsCount = conditions.CountValidBearishOBs(); + bool hasYoungestBullishOB = conditions.HasYoungestBullishOB(); + bool hasYoungestBearishOB = conditions.HasYoungestBearishOB(); + bool hasYoungestOB = hasYoungestBullishOB || + hasYoungestBearishOB; // - // PinBar ... - ENUM_X_DIRECTION cBarPinDir; - bool isCBarPin = decisionCycleHelper - .mBarAnalyser - .IsPinBar( - cBar, - cBarPinDir, - 1 // - ); - bool isCBarBullishPin = - isCBarPin && - IsBullish(cBarPinDir); - bool isCBarBearishPin = - isCBarPin && - IsBearish(cBarPinDir); + ENUM_X_DIRECTION orderFlowDir; + bool hasOrderFlow = conditions.HasOrderFlow(orderFlowDir); + bool hasBullishOrderFlow = IsBullish(orderFlowDir); + bool hasBearishOrderFlow = IsBearish(orderFlowDir); // - // Engulf ... - ENUM_X_DIRECTION cBarEngulfDir; - bool isCBarEngulfed = decisionCycleHelper - .mBarAnalyser - .IsEngulfBar( - cBar, - cBarEngulfDir, - 0 // Extended ... - ); - bool isCBarBullishEngulfed = - isCBarEngulfed && - IsBullish(cBarEngulfDir); - bool isCBarBearishEngulfed = - isCBarEngulfed && - IsBearish(cBarEngulfDir); + bool isInsideZoneBullish = false; + bool isPriceInsideYoungestOB = false; + bool isPriceInsideYoungestBullishOB = false; + bool isPriceInsideYoungestBearishOB = false; + ENUM_X_DIRECTION insideOBDir = X_DIRECTION_NONE; // - // Momentum ... - ENUM_X_DIRECTION cBarMomentumDir; - bool isCBarMomentum = decisionCycleHelper - .mBarAnalyser - .IsMomentumBar( - cBar, - cBarMomentumDir, - 0 // Extended ... - ); - bool isCBarBullishMomentum = - isCBarMomentum && - IsBullish(cBarMomentumDir); - bool isCBarBearishMomentum = - isCBarMomentum && - IsBearish(cBarMomentumDir); + bool hasSwings = conditions.HasSwings(); + int swingsCount = conditions.CountSwings(); + ENUM_X_SWING_TYPE swingType = conditions.GetSwingType(); + bool isSwingLow = swingType == X_SWING_LOW; // - // Reject ... - ENUM_X_DIRECTION cBarRejectDir; - bool isCBarRejected = decisionCycleHelper - .mBarAnalyser - .IsRejectionBar( - cBar, - cBarRejectDir, - 0 // Extended ... - ); - bool isCBarBullishRejected = - isCBarRejected && - IsBullish(cBarRejectDir); - bool isCBarBearishRejected = - isCBarRejected && - IsBearish(cBarRejectDir); + XOHCL decisionZBar; + XOHCL decisionCBar; + XOHCL decisionPBar; + double decisionCBarBullishZoneChechValue = 0; + double decisionCBarBearishZoneChechValue = 0; // - // Pull Back ... - ENUM_X_DIRECTION cBarPullbackDir; - bool isCBarPullbacked = - decisionCycleHelper - .mBarAnalyser - .HasPullBack( - cBarPullbackDir, - cBar // - ); - bool isCBarBullishPullbacked = - isCBarPullbacked && - IsBullish(cBarPullbackDir); - bool isCBarBearishPullbacked = - isCBarPullbacked && - IsBearish(cBarPullbackDir); - - // - // HH/LL Break ... - - // - bool isCBarBreaksUpHH = IsBarBreak( - hh, - X_DIRECTION_BULLISH, - cBar // + result = decisionZBar.Init( + decisionState.symbol, + decisionState.period, + 0 // ); + if (!result) + { + return result; + } // - bool isCBarBreaksDownLL = IsBarBreak( - hh, - X_DIRECTION_BEARISH, - cBar // - ); + result = decisionZBar + .GetPreviousBar(decisionCBar); + if (!result) + { + return result; + } // - // Bars Pattern and Power and Pressures ... + result = decisionCBar + .GetPreviousBar(decisionPBar); + if (!result) + { + return result; + } // - bool hasCBarBullishPattern = - decisionCycleHelper - .mBarAnalyser - .HasBullishPattern( - cBar, - 2 // - ); + decisionCBarBullishZoneChechValue = decisionCBar + .GetZoneCheckValue(X_DIRECTION_BULLISH); + decisionCBarBearishZoneChechValue = decisionCBar + .GetZoneCheckValue(X_DIRECTION_BEARISH); // - bool hasCBarBearishPattern = - decisionCycleHelper - .mBarAnalyser - .HasBearishPattern( - cBar, - 2 // - ); + // Valid Ob, is the Un Activated Order Blocks + int validOBsCount = 0; + XCOrderBlock *validOBs[]; + bool hasValidOBs = hasValidBullishOBs || + hasValidBearishOBs; // - bool isCBarHasBullishPower = - decisionCycleHelper - .mBarAnalyser - .HasBullishPower( - cBar, - 2 // - ); - - // - bool isCBarHasBearishPower = - decisionCycleHelper - .mBarAnalyser - .HasBearishPower( - cBar, - 2 // - ); - - // - bool isCBarHasBullishPressure = - decisionCycleHelper - .mBarAnalyser - .HasBullishPressure( - cBar, - 2 // - ); - - // - bool isCBarHasBearishPressure = - decisionCycleHelper - .mBarAnalyser - .HasBearishPressure( - cBar, - 2 // - ); - - // - // Bar Checking Summary ... - - // - // Bullish ... - bool isCBarBullishFormed = - // - ( - // - hasCBarBullishPattern && - isCBarHasBullishPower && - isCBarHasBullishPressure - // - ) - // - || - // - ( - // - isCBarBullishPin || - isCBarBreaksUpHH || - isCBarBullishEngulfed || - isCBarBullishMomentum || - isCBarBullishRejected - // - ) - // - ; - - // - // Bearish ... - bool isCBarBearishFormed = - // - ( - // - hasCBarBearishPattern && - isCBarHasBearishPower && - isCBarHasBearishPressure - // - ) - // - || - // - ( - // - isCBarBearishPin || - isCBarBreaksDownLL || - isCBarBearishEngulfed || - isCBarBearishMomentum || - isCBarBearishRejected - // - ) - // - ; - - // - // Detect Order Flow ... - - // - // Test Market For Order Flow ... - int obTestsCount = ArraySize(conditions.obTests); - bool isOBTested = obTestsCount == 2; - if (!isOBTested) + if (!hasValidOBs) { // - bool hasTest = ReTestMarket( - conditions.obTests, - consolidationState, - analyseState, - decisionState, + int count = 0; + bool hasOBs = false; + + // + XCOrderBlock *obs[]; + + // + // Check For Bullish ... + count = consolidationState.CountBullishOrderBlocks(); + hasOBs = consolidationState.HasBullishOrderBlocks(); + if (hasOBs) + { + // + Copy( + consolidationState.bullishOrderBlocks, + obs, + false // + ); + } + + // + // Check For Bearish ... + count = consolidationState.CountBearishOrderBlocks(); + hasOBs = consolidationState.HasBearishOrderBlocks(); + if (hasOBs) + { + // + Copy( + consolidationState.bearishOrderBlocks, + obs, + false // + ); + } + + // + ExtractUnActivatedOrderBlocks( + obs, + validOBs // + ); + + // + validOBsCount = ArraySize(validOBs); + hasValidOBs = IsValidSize(validOBsCount); + + // + // Extract Valid Directional Order Blocks ... + + // + if (!hasValidBullishOBs) + { + // + validBullishOBsCount = ExtractDirectionalOrderBlocks( + X_DIRECTION_BULLISH, + validOBs, + conditions.validBullishOBs // + ); + hasValidBullishOBs = IsValidSize(validBullishOBsCount); + } + + // + if (!hasValidBearishOBs) + { + // + validBearishOBsCount = ExtractDirectionalOrderBlocks( + X_DIRECTION_BEARISH, + validOBs, + conditions.validBearishOBs // + ); + hasValidBearishOBs = IsValidSize(validBearishOBsCount); + } + } + + // + result = hasValidOBs; + if (!result) + { + return result; + } + + // + UpdateTo(validOBs); + UpdateTo(conditions.validBullishOBs); + UpdateTo(conditions.validBearishOBs); + + // + // Extract Youngest Order Blocks ... + + // + if (!hasYoungestBullishOB) + { + // + if (hasValidBullishOBs) + { + // + int idx = GetYoungest(conditions.validBullishOBs); + hasYoungestBullishOB = IsValidIndex(idx); + if (hasYoungestBullishOB) + { + // + conditions.youngestBullishOB = conditions.validBullishOBs[idx]; + + // + int vobIDX = -1; + bool hasVOB = FindIndex( + vobIDX, + conditions.youngestBullishOB, + validOBs // + ); + if (hasVOB) + { + // + ArrayRemove( + validOBs, + vobIDX, + 1 // + ); + + // + validOBsCount = ArraySize(validOBs); + hasValidOBs = IsValidSize(validOBsCount); + } + + // + int bullisVOBIDX = -1; + bool hasBullishVOB = FindIndex( + bullisVOBIDX, + conditions.youngestBullishOB, + conditions.validBullishOBs // + ); + if (hasBullishVOB) + { + // + ArrayRemove( + conditions.validBullishOBs, + bullisVOBIDX, + 1 // + ); + + // + validBullishOBsCount = ArraySize(conditions.validBullishOBs); + hasValidBullishOBs = IsValidSize(validBullishOBsCount); + } + } + } + } + + // + if (!hasYoungestBearishOB) + { + // + if (hasValidBearishOBs) + { + // + int idx = GetYoungest(conditions.validBearishOBs); + hasYoungestBearishOB = IsValidIndex(idx); + if (hasYoungestBearishOB) + { + // + conditions.youngestBearishOB = conditions.validBearishOBs[idx]; + + // + int vobIDX = -1; + bool hasVOB = FindIndex( + vobIDX, + conditions.youngestBearishOB, + validOBs // + ); + if (hasVOB) + { + // + ArrayRemove( + validOBs, + vobIDX, + 1 // + ); + + // + validOBsCount = ArraySize(validOBs); + hasValidOBs = IsValidSize(validOBsCount); + } + + // + int bearishVOBIDX = -1; + bool hasBearishVOB = FindIndex( + bearishVOBIDX, + conditions.youngestBearishOB, + conditions.validBearishOBs // + ); + if (hasBearishVOB) + { + // + ArrayRemove( + conditions.validBearishOBs, + bearishVOBIDX, + 1 // + ); + + // + validBearishOBsCount = ArraySize(conditions.validBearishOBs); + hasValidBearishOBs = IsValidSize(validBearishOBsCount); + } + } + } + } + + // + hasYoungestOB = hasYoungestBullishOB || + hasYoungestBearishOB; + result = hasYoungestOB; + if (!result) + { + return result; + } + + // + // Sorting Valid Order Blocks based on Yungest ... + + // + OrderedSortOrderBlocks( + conditions.youngestBullishOB, + conditions.validBullishOBs // + ); + validBullishOBsCount = ArraySize(conditions.validBullishOBs); + hasValidBullishOBs = IsValidSize(validBullishOBsCount); + + // + OrderedSortOrderBlocks( + conditions.youngestBearishOB, + conditions.validBearishOBs // + ); + validBearishOBsCount = ArraySize(conditions.validBearishOBs); + hasValidBearishOBs = IsValidSize(validBearishOBsCount); + + // + hasValidOBs = hasValidBullishOBs || + hasValidBearishOBs; + result = hasValidOBs; + if (!result) + { + return result; + } + + // + // Extract Order Flow ... + + // + hasBullishOrderFlow = + hasYoungestBullishOB && + validBullishOBsCount >= 2; + + // + hasBearishOrderFlow = + hasYoungestBearishOB && + validBearishOBsCount >= 2; + + // + hasOrderFlow = (hasBullishOrderFlow && + !hasBearishOrderFlow) || + (!hasBullishOrderFlow && + hasBearishOrderFlow); + result = hasOrderFlow; + if (!result) + { + return result; + } + + // + // Extract Swing Points ... + + // + XCOrderBlock *tmpSwings[]; + if (hasBullishOrderFlow) + { + // + Copy( + conditions.validBullishOBs, + tmpSwings // + ); + + // + Add( + conditions.youngestBullishOB, + tmpSwings // + ); + + // + isSwingLow = true; + swingType = X_SWING_LOW; + swingsCount = ExtractSwingPoints( + swingType, + tmpSwings, + conditions.swings // + ); + + // + while (swingsCount > 2) + { + // + double tmpValues[]; + int tmpValuesCount = ExtractSwings( + conditions.swings, + tmpValues // + ); + + // + int minIDX = -1; + double min = GetMin( + tmpValues, + minIDX, + 0, + 0 // + ); + if (IsValidIndex(minIDX)) + { + // + ArrayRemove( + conditions.swings, + minIDX, + 1 // + ); + + // + swingsCount = ArraySize(conditions.swings); + hasSwings = IsValidSize(swingsCount); + } + + // + Clean(tmpValues); + } + } + else + { + // + Copy( + conditions.validBearishOBs, + tmpSwings // + ); + + // + Add( + conditions.youngestBearishOB, + tmpSwings // + ); + + // + isSwingLow = false; + swingType = X_SWING_LOW; + swingsCount = ExtractSwingPoints( + swingType, + tmpSwings, + conditions.swings // + ); + + // + while (swingsCount > 2) + { + // + double tmpValues[]; + int tmpValuesCount = ExtractSwings( + conditions.swings, + tmpValues // + ); + + // + int maxIDX = -1; + double max = GetMin( + tmpValues, + maxIDX, + 0, + 0 // + ); + if (IsValidIndex(maxIDX)) + { + // + ArrayRemove( + conditions.swings, + maxIDX, + 1 // + ); + + // + swingsCount = ArraySize(conditions.swings); + hasSwings = IsValidSize(swingsCount); + } + + // + Clean(tmpValues); + } + } + Clean(tmpSwings); + + // + hasSwings = IsValidSize(swingsCount) && + swingsCount >= 2; + result = hasSwings; + if (!result) + { + return result; + } + + // + // Detect Price Inside Order Block ... + + // + if (hasYoungestBullishOB) + { + // + isPriceInsideYoungestBullishOB = IsInside( + decisionCBarBullishZoneChechValue, + conditions.youngestBullishOB // + ); + } + + // + if (hasYoungestBearishOB) + { + // + isPriceInsideYoungestBearishOB = IsInside( + decisionCBarBearishZoneChechValue, + conditions.youngestBearishOB // + ); + } + + // + isPriceInsideYoungestOB = + (hasBullishOrderFlow && + isPriceInsideYoungestBullishOB) || + (hasBearishOrderFlow && + isPriceInsideYoungestBearishOB); + result = isPriceInsideYoungestOB; + if (!result) + { + return result; + } + + // + // Draw ... + + // + mX121SMCXOBSObjects.Clear(); + + // + // Youngests ... + + // + if (hasYoungestBullishOB) + { + // + DrawX121SMCXOBSOrderBlock( + conditions.youngestBullishOB, visionCycleHelper.mPOIDrawer // ); } // - // TODO: + if (hasYoungestBearishOB) + { + // + DrawX121SMCXOBSOrderBlock( + conditions.youngestBearishOB, + visionCycleHelper.mPOIDrawer // + ); + } + + // + // Valids ... + if (hasValidOBs) + { + // + for (int i = 0; i < validOBsCount; i++) + { + // + DrawX121SMCXOBSOrderBlock( + validOBs[i], + visionCycleHelper.mPOIDrawer // + ); + } + } + + // + // Trend Line ... + if (hasSwings) + { + // + XCTrendObject *iObj; + bool isCreated = visionCycleHelper + .mPOIDrawer + .CreateTrend( + conditions.swings, + iObj // + ); + if (isCreated) + { + mX121SMCXOBSObjects.Add(iObj); + } + } + + // return false; // @@ -1254,1070 +1628,101 @@ int AddX121SMCXOBSConditionsIfNotExists( } // -// -// - -/** - * Retest Market ... - * - * @param test: XOBTest instance Reference, Represet Result Test ... - * @param tests: XOBTest instance Reference Collection, Represet Founded Tests till now ... - * @param htfState: XPOIState instance Reference ... - * @param mtfState: XPOIState instance Reference ... - * @param ttfState: XPOIState instance Reference ... - * - * @return ( bool ) - */ -bool ReTestMarket( - XOBTest &tests[], - XPOIState &htfState, - XPOIState &mtfState, - XPOIState &ttfState, // - // - XCPOIDrawer *drawer - // +void DrawX121SMCXOBSOrderBlock( + XCOrderBlock *ob, + XCPOIDrawer *drawer // ) { // - bool result = false; + if (ob == NULL || + drawer == NULL) + { + return; + } // - Clean(tests); + ENUM_X_DIRECTION forDir = ob.GetDirection(); // - datetime cTime = TimeCurrent(); + color bullishColor = drawer.BarBullishColor(); + color bearishColor = drawer.BarBearishColor(); + color forColor = IsBullish(forDir) + ? bullishColor + : bearishColor; // - // Detect Order Blocks ... - // HTF ... - - // - // Bullish OBs ... - XCOrderBlock *bullOBs[]; - bool hasYoungestBullOB = false; - XOHCL youngestBullOBStartedBar; - bool isYoungestBullOBStarted = false; - ENUM_X_DIRECTION youngestBullOBStartedDir; - XCOrderBlock *youngestBullOB = NULL; - int bullOBsCount = ExtractUnActivatedOBs( - htfState.bullishOrderBlocks, - bullOBs // + // Draw Order Block ... + XCBaseObject *obj; + bool isCreated = drawer.CreateOrderBlock( + ob, + obj // ); - - // - bool isBullOBsPassed = bullOBsCount >= 1; - if (isBullOBsPassed) + if (isCreated) { - // - XBoxZone boxes[]; - int boxesCount = ToBox( - bullOBs, - boxes // - ); - int youngestBoxIDX = GetYoungest(boxes); - hasYoungestBullOB = IsValidIndex(youngestBoxIDX); - if (hasYoungestBullOB) - { - // - youngestBullOB = bullOBs[youngestBoxIDX]; - - // - isYoungestBullOBStarted = youngestBullOB.IsStarted( - X_DIRECTION_BULLISH, - youngestBullOBStartedBar, - youngestBullOBStartedDir // - ); - } + mX121SMCXOBSObjects.Add(obj); } // - // Bearish OBs ... - XCOrderBlock *bearOBs[]; - bool hasYoungestBearOB = false; - XOHCL youngestBearOBStartedBar; - bool isYoungestBearOBStarted = false; - ENUM_X_DIRECTION youngestBearOBStartedDir; - XCOrderBlock *youngestBearOB = NULL; - int bearOBsCount = ExtractUnActivatedOBs( - htfState.bearishOrderBlocks, - bearOBs // + ulong chartID = drawer.ChartIdentification(); + int subWindow = drawer.SubWindowIdentification(); + + // + XOHCL startedBar; + ENUM_X_DIRECTION startedDir; + bool isStarted = ob.IsStarted( + forDir, + startedBar, + startedDir // ); - - // - bool isBearOBsPassed = bearOBsCount >= 1; - if (isBearOBsPassed) + if (isStarted) { // - XBoxZone boxes[]; - int boxesCount = ToBox( - bearOBs, - boxes // + datetime to = startedBar.time + (PeriodSeconds(startedBar.period)); + + // + XCOHCLObject *obj; + bool isCreated = drawer.CreateBar( + startedBar, + obj, + to // ); - int youngestBoxIDX = GetYoungest(boxes); - hasYoungestBearOB = IsValidIndex(youngestBoxIDX); - if (hasYoungestBearOB) - { - // - youngestBearOB = bearOBs[youngestBoxIDX]; - - // - isYoungestBearOBStarted = youngestBearOB.IsStarted( - X_DIRECTION_BEARISH, - youngestBearOBStartedBar, - youngestBearOBStartedDir // - ); - } - } - - // - 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[]; - datetime fvgActedAt = NULL; - 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; - } - - // - // Validate FVG Based on Conditions ... - // for Bullish Order Blocks FVGs must Rejected as Liquidity ... - // in ttf ... - - // - XOHCL rejectedBar; - ENUM_X_DIRECTION rejectedDir; - bool isRejected = jFVG.IsRejected( - X_DIRECTION_BULLISH, - rejectedBar, - rejectedDir, - NULL, // From ... - true, // Force Sweeped ... - ttfState.period // For Period ... - ); - - // - XOHCL breakedBar; - ENUM_X_DIRECTION breakedDir; - bool isBreaked = jFVG.IsBreaked( - X_DIRECTION_BULLISH, - breakedBar, - breakedDir // - ); - - // - bool isFVGActed = - isRejected || - isBreaked; - if (!isFVGActed) - { - continue; - } - - // - datetime iFvgActedAt = - isBreaked && - !isRejected - ? breakedBar.time - : !isBreaked && - isRejected - ? rejectedBar.time - : isBreaked && - isRejected - ? (breakedBar.time < rejectedBar.time) - ? breakedBar.time - : rejectedBar.time - : NULL; - if (!IsValid(iFvgActedAt)) - { - continue; - } - - // - if (!IsValid(fvgActedAt)) { - fvgActedAt = iFvgActedAt; - } - - // - XCFVG *lastFVG = NULL; - int fvgsCount = ArraySize(iOBFVGs); - bool hasLastFVG = IsValidSize(fvgsCount); - if (hasLastFVG) - { - lastFVG = iOBFVGs[fvgsCount - 1]; - } - bool isLastPassed = - !hasLastFVG - ? true - : IsAbove( - jFVG, - lastFVG, - true // Ignore Inside ... - ); - if (!isLastPassed) - { - continue; - } - - // - jFVG.To(iOB.To()); - jFVG.To(iFvgActedAt); - - // - 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(); - - // - iTest.fvgActedAt = fvgActedAt; - - // - 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[]; - datetime fvgActedAt = NULL; - 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; - } - - // - // Validate FVG Based on Conditions ... - // for Bearish Order Blocks FVGs must Rejected as Liquidity ... - // in ttf ... - - // - XOHCL rejectedBar; - ENUM_X_DIRECTION rejectedDir; - bool isRejected = jFVG.IsRejected( - X_DIRECTION_BEARISH, - rejectedBar, - rejectedDir, - NULL, // From ... - true, // Force Sweeped ... - ttfState.period // For Period ... - ); - - // - XOHCL breakedBar; - ENUM_X_DIRECTION breakedDir; - bool isBreaked = jFVG.IsBreaked( - X_DIRECTION_BEARISH, - breakedBar, - breakedDir // - ); - - // - bool isFVGActed = - isRejected || - isBreaked; - if (!isFVGActed) - { - continue; - } - - // - datetime iFvgActedAt = - isBreaked && - !isRejected - ? breakedBar.time - : !isBreaked && - isRejected - ? rejectedBar.time - : isBreaked && - isRejected - ? (breakedBar.time < rejectedBar.time) - ? breakedBar.time - : rejectedBar.time - : NULL; - if (!IsValid(iFvgActedAt)) - { - continue; - } - - // - if (!IsValid(fvgActedAt)) { - fvgActedAt = iFvgActedAt; - } - - // - XCFVG *lastFVG = NULL; - int fvgsCount = ArraySize(iOBFVGs); - bool hasLastFVG = IsValidSize(fvgsCount); - if (hasLastFVG) - { - lastFVG = iOBFVGs[fvgsCount - 1]; - } - bool isLastPassed = - !hasLastFVG - ? true - : IsBelow( - jFVG, - lastFVG, - true // Ignore Inside ... - ); - if (!isLastPassed) - { - continue; - } - - // - jFVG.To(iOB.To()); - jFVG.To(iFvgActedAt); - - // - 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(); - - // - iTest.fvgActedAt = fvgActedAt; - - // - 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; - } - - // - // DRAW ... - // - - // - XCBaseObject *drawnObjects[]; - - // - if (hasYoungestBullOB) - { - // - XCBullishOrderBlockObject *iObj; - bool isCreated = drawer - .CreateBullishOrderBlock( - youngestBullOB, - iObj // - ); - - // if (isCreated) { // - Add( - (XCBaseObject *)iObj, - drawnObjects // - ); + obj.BodyColor(clrYellow); + obj.HighShadowColor(clrYellow); + obj.LowShadowColor(clrYellow); + + // + obj.BodyStyle(STYLE_SOLID); + obj.HighShadowStyle(STYLE_SOLID); + obj.LowShadowStyle(STYLE_SOLID); + + // + mX121SMCXOBSObjects.Add(obj); } - } - - // - if (hasYoungestBearOB) - { - // - XCBearishOrderBlockObject *iObj; - bool isCreated = drawer - .CreateBearishOrderBlock( - youngestBearOB, - iObj // - ); // + string startVLineName = "Start_" + ob.GetTag(); + + // + CChartObjectVLine *startVLine; + startVLine = new CChartObjectVLine(); + isCreated = startVLine.Create( + chartID, + startVLineName, + subWindow, + startedBar.time // + ); if (isCreated) { // - Add( - (XCBaseObject *)iObj, - drawnObjects // - ); + startVLine.Color(forColor); + + // + mX121SMCXOBSObjects.Add(startVLine); } } - - // // - // // 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 ... - // - - // - Print("OBs Passed ..."); - - // - return result; -} - -/** - * Extract UnActivated Order Blocks ... - * - * @return ( int ) - */ -int ExtractUnActivatedOBs( - XCOrderBlock *&source[], - XCOrderBlock *&obs[] // -) -{ - // - int result = 0; - - // - Clean(obs); - - // - int count = ArraySize(source); - bool hasOB = IsValidSize(count); - if (!hasOB) - { - return result; - } - - // - for (int i = 0; i < count; i++) - { - // - bool isBullish = source[i].IsBullish(); - ENUM_X_DIRECTION forDir = - isBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - - // - // - // - - // - XOHCL activatedBar; - ENUM_X_DIRECTION activatedDir; - bool isActivated = source[i].IsActivated( - forDir, - activatedBar, - activatedDir // - ); - if (!isActivated) - { - // - Add( - source[i], - obs // - ); - } - } - - // - result = ArraySize(obs); - - // - return result; } // diff --git a/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 b/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 index a1dee207..245db577 100644 --- a/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 +++ b/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 @@ -105,7 +105,7 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy { // Clean(mXConditionsCollection); - Clean(mXOBSConditionsCollection); + Clean(mX121SMCXOBSConditionsCollection); // ZeroMemory(mTriggerCycleHelper); @@ -755,9 +755,9 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy // // Detect Setup Conditions ... - datetime setupTime = mXOBSConditions.setupTime; - bool isSetuped = mXOBSConditions.IsSetuped(); - ENUM_X_DIRECTION setupDir = mXOBSConditions.dir; + datetime setupTime = mX121SMCXOBSConditions.setupTime; + bool isSetuped = mX121SMCXOBSConditions.IsSetuped(); + ENUM_X_DIRECTION setupDir = mX121SMCXOBSConditions.dir; if (!isSetuped) { // @@ -765,7 +765,7 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy isSetuped = DetectX121SMCXOBSSignalSetup( symbol, period, - mXOBSConditions, + mX121SMCXOBSConditions, mTriggerCycleHelper, mDecisionCycleHelper, mAnalyseCycleHelper, @@ -775,25 +775,25 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy ); // - setupDir = mXOBSConditions.dir; - setupTime = mXOBSConditions.setupTime; + setupDir = mX121SMCXOBSConditions.dir; + setupTime = mX121SMCXOBSConditions.setupTime; // if (isSetuped) { // int items = AddX121SMCXOBSConditionsIfNotExists( - mXOBSConditions, - mXOBSConditionsCollection // + mX121SMCXOBSConditions, + mX121SMCXOBSConditionsCollection // ); // - mXOBSConditions.Clean(); + mX121SMCXOBSConditions.Clean(); } } // - int conditionsCount = ArraySize(mXOBSConditionsCollection); + int conditionsCount = ArraySize(mX121SMCXOBSConditionsCollection); result = IsValidSize(conditionsCount); if (!result) { @@ -805,7 +805,7 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy int selectedIndex = 0; X121SMCStrategyXOBSSignalConditions mTmpConditions[]; Copy( - mXOBSConditionsCollection, + mX121SMCXOBSConditionsCollection, mTmpConditions // ); X121SMCStrategyXOBSSignalConditions mConditions; @@ -841,7 +841,7 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy { // ArrayRemove( - mXOBSConditionsCollection, + mX121SMCXOBSConditionsCollection, i, 1 // ); @@ -874,7 +874,7 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy // // Remove Selected Index from Main Collection ... ArrayRemove( - mXOBSConditionsCollection, + mX121SMCXOBSConditionsCollection, selectedIndex, 1 // );