/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 X121 SMC Signal Class // ------------------------------------------------- // Name: XWZ // 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" // enum ENUM_X121SMC_XWZ_PRIORITY { X121SMC_XWZ_PRIORITY_NONE, X121SMC_XWZ_PRIORITY_WEAK, X121SMC_XWZ_PRIORITY_LOW, X121SMC_XWZ_PRIORITY_REGULAR, X121SMC_XWZ_PRIORITY_HIGH, X121SMC_XWZ_PRIORITY_STRONG_HIGH, }; // struct X121SMCXWZZone { // // Props ... XCFVG *fvg; XCOrderBlock *ob; XCSupplyZone *supply; XCDemandZone *demand; XCSupportZone *support; XCResistanceZone *resistance; XConsolidationZone bullishConsolidationZone; XConsolidationZone bearishConsolidationZone; // XOHCL swingBar; XOHCL breakerBar; XOHCL momentumBar; XOHCL rejectionBar; XBoxZone appliedBox; // // Constructor ... X121SMCXWZZone() { Clean(); } // // Tools ... // void Clean() { // ZeroMemory(ob); ZeroMemory(fvg); ZeroMemory(supply); ZeroMemory(demand); ZeroMemory(support); ZeroMemory(resistance); // swingBar.Clean(); breakerBar.Clean(); appliedBox.Clean(); momentumBar.Clean(); rejectionBar.Clean(); // bullishConsolidationZone.Clean(); bearishConsolidationZone.Clean(); } // bool IsValid() { // return HasOB() && HasFVG() && HasDirection(); } // bool AsBox(XBoxZone &box) { // bool result = false; // box.Clean(); // result = IsValid() && HasDirection(); if (!result) { return result; } // XBoxZone obBox; bool hasOBBox = ToBox( obBox, ob // ); result = hasOBBox; if (!result) { // box.Clean(); obBox.Clean(); return result; } // box = obBox; // obBox.Clean(); // bool hasOB = HasOB(); bool hasFVG = HasFVG(); bool hasSupply = HasSupply(); bool hasDemand = HasDemand(); bool hasSupport = HasSupport(); bool hasResistance = HasResistance(); // // OB Compared since box used obBox ... // if (hasFVG) { // if (fvg.Upper() > box.upper) { box.upper = fvg.Upper(); } // if (fvg.Lower() < box.lower) { box.lower = fvg.Lower(); } } // result = box.IsValid(); // return result; } // bool HasOB() { return ob != NULL && ob.IsValid(); } // bool HasFVG() { return fvg != NULL && fvg.IsValid(); } // bool HasSupply() { return supply != NULL && supply.IsValid(); } // bool HasDemand() { return demand != NULL && demand.IsValid(); } // bool HasSupport() { return support != NULL && support.IsValid(); } // bool HasResistance() { return resistance != NULL && resistance.IsValid(); } // bool HasBullishConsolidationZone() { return bullishConsolidationZone.IsValid() && bullishConsolidationZone.IsBreaked() && IsBullish(bullishConsolidationZone.breakDir); } // bool HasBearishConsolidationZone() { return bearishConsolidationZone.IsValid() && bearishConsolidationZone.IsBreaked() && IsBullish(bearishConsolidationZone.breakDir); } // bool IsBullish() { // return HasOB() && ob.IsBullish() && HasFVG() && fvg.IsBullish() && HasSupport() && HasDemand(); } // bool IsBearish() { // return HasOB() && ob.IsBearish() && HasFVG() && fvg.IsBearish() && HasSupply() && HasResistance(); } // bool HasDirection() { return IsBullish() || IsBearish(); } // ENUM_X_DIRECTION GetDirection() { // ENUM_X_DIRECTION result = X_DIRECTION_NONE; // bool hasDirection = HasDirection(); if (!hasDirection) { return result; } // bool isBullish = IsBullish(); // result = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // return result; } // bool HasCondition( XPOIState &state, int barIndex = 0, ENUM_TIMEFRAMES forPeriod = NULL // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // swingBar.Clean(); breakerBar.Clean(); appliedBox.Clean(); momentumBar.Clean(); rejectionBar.Clean(); // result = IsValid() && HasDirection() && state.IsValid() && state.HasChild(); if (!result) { // swingBar.Clean(); breakerBar.Clean(); appliedBox.Clean(); momentumBar.Clean(); rejectionBar.Clean(); // return result; } // string symbol = ob.GetSymbol(); if (!IsValid(forPeriod)) { forPeriod = ob.GetPeriod(); } datetime cTime = iTime( symbol, forPeriod, barIndex // ); // bool isInside = IsPriceInside( barIndex, forPeriod // ); result = isInside; if (!result) { return result; } // XBoxZone box; result = AsBox(box); if (!result) { // box.Clean(); // swingBar.Clean(); breakerBar.Clean(); appliedBox.Clean(); momentumBar.Clean(); rejectionBar.Clean(); // return result; } // bool isBullish = IsBullish(); ENUM_X_DIRECTION forDir = box.dir; // int supportsCount = 0; bool hasSupports = false; XCSupportZone *supports[]; // int resistancesCount = 0; bool hasResistances = false; XCResistanceZone *resistances[]; // XBoxZone supResBoxes[]; int supresBoxesCount = 0; bool hasSupResBoxes = false; // int count = 0; bool has = false; // has = state.HasSupportZones(); if (has) { // count = state.CountSupportZones(); for (int i = 0; i < count; i++) { // XCSupportZone *iZone = state.supportZones[i]; // iZone.To(cTime); // XBoxZone iBox; bool hasBox = ToBox( iBox, iZone // ); if (!hasBox) { // iBox.Clean(); continue; } // // Check From ... bool isInside = IsBoxInside( iBox, box // ); if (!isInside) { // iBox.Clean(); continue; } // Add( iZone, supports // ); // AddRef( iBox, supResBoxes // ); // iBox.Clean(); } // supportsCount = ArraySize(supports); hasSupports = IsValidSize(supportsCount); // supresBoxesCount = ArraySize(supResBoxes); hasSupResBoxes = IsValidSize(supresBoxesCount); } // has = state.HasResistanceZones(); if (has) { // count = state.CountResistanceZones(); for (int i = 0; i < count; i++) { // XCResistanceZone *iZone = state.resistanceZones[i]; // iZone.To(cTime); // XBoxZone iBox; bool hasBox = ToBox( iBox, iZone // ); if (!hasBox) { // iBox.Clean(); continue; } // // Check From ... bool isInside = IsBoxInside( iBox, box // ); if (!isInside) { // iBox.Clean(); continue; } // Add( iZone, resistances // ); // AddRef( iBox, supResBoxes // ); // iBox.Clean(); } // resistancesCount = ArraySize(resistances); hasResistances = IsValidSize(resistancesCount); // supresBoxesCount = ArraySize(supResBoxes); hasSupResBoxes = IsValidSize(supresBoxesCount); } // result = hasSupResBoxes; if (!result) { // box.Clean(); Clean(supports); Clean(resistances); Clean(supResBoxes); // swingBar.Clean(); breakerBar.Clean(); appliedBox.Clean(); momentumBar.Clean(); rejectionBar.Clean(); // return result; } // // Detect Bars ... // XOHCL zBar; result = zBar.Init( symbol, forPeriod, barIndex // ); if (!result) { // box.Clean(); zBar.Clean(); Clean(supports); Clean(resistances); Clean(supResBoxes); // swingBar.Clean(); breakerBar.Clean(); appliedBox.Clean(); momentumBar.Clean(); rejectionBar.Clean(); // return result; } // XOHCL cBar; result = zBar.GetPreviousBar(cBar); if (!result) { // box.Clean(); zBar.Clean(); cBar.Clean(); Clean(supports); Clean(resistances); Clean(supResBoxes); // swingBar.Clean(); breakerBar.Clean(); appliedBox.Clean(); momentumBar.Clean(); rejectionBar.Clean(); // return result; } // XOHCL pBar; result = cBar.GetPreviousBar(pBar); if (!result) { // box.Clean(); zBar.Clean(); cBar.Clean(); pBar.Clean(); Clean(supports); Clean(resistances); Clean(supResBoxes); // swingBar.Clean(); breakerBar.Clean(); appliedBox.Clean(); momentumBar.Clean(); rejectionBar.Clean(); // return result; } // XOHCL ppBar; result = pBar.GetPreviousBar(ppBar); if (!result) { // box.Clean(); zBar.Clean(); cBar.Clean(); pBar.Clean(); ppBar.Clean(); Clean(supports); Clean(resistances); Clean(supResBoxes); // swingBar.Clean(); breakerBar.Clean(); appliedBox.Clean(); momentumBar.Clean(); rejectionBar.Clean(); // return result; } // // Check Conditions ... // // Detect Start Senario ... // double fiboPressureLevel = GetFiboLevelValue(X_FIBO_LEVEL_382); // double fiboUpDown = GetFibonacciLevel( pBar.high, pBar.low, X_FIBO_LEVEL_382, X_DIRECTION_BEARISH // ); double fiboDownUp = GetFibonacciLevel( pBar.high, pBar.low, X_FIBO_LEVEL_382, X_DIRECTION_BULLISH // ); // bool hasFiboToUpPressure = fiboDownUp > 0 && fiboDownUp <= pBar.GetDown(); bool hasFiboToDownPressure = fiboUpDown > 0 && fiboUpDown >= pBar.GetUp(); // int selectedBoxIDX = -1; for (int j = 0; j < supresBoxesCount; j++) { // double appliedPrice = isBullish ? supResBoxes[j].lower : supResBoxes[j].upper; // // Check Swing Low ... bool isSwingLow = // pBar.low < ppBar.low && pBar.low < cBar.low && zBar.open > pBar.low && // appliedPrice > pBar.low && appliedPrice < pBar.GetDown() // ; bool isPressuredSwingLow = isSwingLow && hasFiboToUpPressure; bool isPressuredStrongSwingLow = pBar.IsBullish() && isPressuredSwingLow; // bool isSwingHigh = // pBar.high > ppBar.high && pBar.high > cBar.high && zBar.open < pBar.high && // appliedPrice < pBar.high && appliedPrice > pBar.GetUp() // ; bool isPressuredSwingHigh = isSwingHigh && hasFiboToDownPressure; bool isPressuredStrongSwingHigh = pBar.IsBearish() && isPressuredSwingHigh; // bool hasValidSwing = isBullish ? isSwingLow : isSwingHigh; bool hasValidPressuredSwing = isBullish ? isPressuredSwingLow : isPressuredSwingHigh; bool hasValidPressuredStrongSwing = isBullish ? isPressuredStrongSwingLow : isPressuredStrongSwingHigh; if (hasValidSwing) { swingBar = pBar; } if (hasValidPressuredSwing) { swingBar = pBar; } if (hasValidPressuredStrongSwing) { swingBar = pBar; } // bool isCBarBreaked = IsBarBreak( appliedPrice, forDir, cBar // ); if (isCBarBreaked) { breakerBar = cBar; } bool isPBarBreaked = IsBarBreak( appliedPrice, forDir, pBar // ); if (!isCBarBreaked && isPBarBreaked) { breakerBar = pBar; } else { isPBarBreaked = false; } bool isPPBarBreaked = IsBarBreak( appliedPrice, forDir, ppBar // ); if (!isCBarBreaked && !isPBarBreaked && isPPBarBreaked) { breakerBar = ppBar; } else { isPPBarBreaked = false; } bool isBoxBreaked = isCBarBreaked || isPBarBreaked || isPPBarBreaked; // bool isCBarRejected = IsBarReject( appliedPrice, forDir, cBar // ); if (isCBarRejected) { rejectionBar = cBar; } bool isPBarRejected = IsBarReject( appliedPrice, forDir, pBar // ); if (!isCBarRejected && isPBarRejected) { rejectionBar = pBar; } else { isPBarRejected = false; } bool isPPBarRejected = IsBarReject( appliedPrice, forDir, ppBar // ); if (!isCBarRejected && !isPBarRejected && isPPBarRejected) { rejectionBar = ppBar; } else { isPPBarRejected = false; } bool isBoxRejected = isCBarRejected || isPBarRejected || isPPBarRejected; // bool hasRejectionBar = false; if (isBullish) { // count = state.CountBullishRejectionBars(); for (int i = 0; i < count; i++) { // XCRejectionBar *iZone = state.bullishRejectionBars[i]; // XOHCL iBar; bool isFilled = iZone.FillBar(iBar); if (!isFilled) { continue; } // int iBarIndex = iBar.Index(); // hasRejectionBar = // (iBarIndex == cBar.Index() || iBarIndex == pBar.Index()) // ; if (hasRejectionBar) { // if (!rejectionBar.IsValid()) { rejectionBar = iBar; } // break; } } } else { // count = state.CountBearishRejectionBars(); for (int i = 0; i < count; i++) { // XCRejectionBar *iZone = state.bearishRejectionBars[i]; // XOHCL iBar; bool isFilled = iZone.FillBar(iBar); if (!isFilled) { continue; } // int iBarIndex = iBar.Index(); // hasRejectionBar = // (iBarIndex == cBar.Index() || iBarIndex == pBar.Index()) // ; if (hasRejectionBar) { // if (!rejectionBar.IsValid()) { rejectionBar = iBar; } // break; } } } // bool hasMomentumBar = false; if (isBullish) { // count = state.CountBullishMomentumBars(); for (int i = 0; i < count; i++) { // XCMomentumBar *iZone = state.bullishMomentumBars[i]; // XOHCL iBar; bool isFilled = iZone.FillBar(iBar); if (!isFilled) { continue; } // int iBarIndex = iBar.Index(); // hasMomentumBar = // (iBarIndex == cBar.Index() || iBarIndex == pBar.Index()) // ; if (hasMomentumBar) { // if (!momentumBar.IsValid()) { momentumBar = iBar; } // break; } } } else { // count = state.CountBearishMomentumBars(); for (int i = 0; i < count; i++) { // XCMomentumBar *iZone = state.bearishMomentumBars[i]; // XOHCL iBar; bool isFilled = iZone.FillBar(iBar); if (!isFilled) { continue; } // int iBarIndex = iBar.Index(); // hasMomentumBar = // (iBarIndex == cBar.Index() || iBarIndex == pBar.Index()) // ; if (hasMomentumBar) { // if (!momentumBar.IsValid()) { momentumBar = iBar; } // break; } } } // bool hasSwing = false; if (isBullish) { // count = state.CountSwingLows(); for (int i = 0; i < count; i++) { // XCSwing *iSwing = state.swingLows[i]; // XOHCL iBar; bool isFilled = iSwing.FillBar(iBar); if (!isFilled) { continue; } // int iBarIndex = iBar.Index(); // hasSwing = // (iBarIndex == cBar.Index() || iBarIndex == pBar.Index()) // ; if (hasSwing) { // if (!swingBar.IsValid()) { swingBar = iBar; } // break; } } } else { // count = state.CountSwingHighs(); for (int i = 0; i < count; i++) { // XCSwing *iSwing = state.swingHighs[i]; // XOHCL iBar; bool isFilled = iSwing.FillBar(iBar); if (!isFilled) { continue; } // int iBarIndex = iBar.Index(); // hasSwing = // (iBarIndex == cBar.Index() || iBarIndex == pBar.Index()) // ; if (hasSwing) { // if (!swingBar.IsValid()) { swingBar = iBar; } // break; } } } // bool hasRequiredValidations = // (hasRejectionBar || hasMomentumBar) // || // (hasRejectionBar || hasSwing) // || // (hasMomentumBar || hasSwing) // ; // result = // (isBoxBreaked && (hasRequiredValidations || hasValidPressuredSwing)) // || // (isBoxRejected && (hasRequiredValidations || hasValidPressuredSwing)) // ; if (result) { // selectedBoxIDX = j; break; } } // result = result && (isBullish ? zBar.open > box.upper : zBar.open < box.lower) && IsValidIndex(selectedBoxIDX); if (result) { appliedBox = supResBoxes[selectedBoxIDX]; } // box.Clean(); zBar.Clean(); cBar.Clean(); pBar.Clean(); ppBar.Clean(); Clean(supports); Clean(resistances); Clean(supResBoxes); // return result; } // bool IsPriceInside( int barIndex = 0, ENUM_TIMEFRAMES forPeriod = NULL // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // result = IsValid() && HasOB() && HasFVG() && HasDirection(); if (!result) { return result; } // string symbol = ob.GetSymbol(); if (forPeriod == NULL) { forPeriod = ob.GetPeriod(); } // ENUM_X_DIRECTION forDir = ob.GetDirection(); bool isBullish = IsBullish(forDir); // // Check Start Bars ... // XOHCL obStartedBar; ENUM_X_DIRECTION obStartedDir; bool isOBStarted = ob.IsStarted( forDir, obStartedBar, obStartedDir // ); result = isOBStarted; if (!result) { return result; } // XOHCL fvgStartedBar; ENUM_X_DIRECTION fvgStartedDir; bool isFVGStarted = fvg.IsStarted( forDir, fvgStartedBar, fvgStartedDir // ); result = isFVGStarted; if (!result) { return result; } // // Get Zone Box ... XBoxZone box; bool hasBox = AsBox(box); result = hasBox; if (!result) { // box.Clean(); // return result; } // // Retrieve Bars ... // XOHCL zBar; result = zBar.Init( symbol, forPeriod, barIndex // ); if (!result) { // box.Clean(); zBar.Clean(); // return result; } // XOHCL cBar; result = zBar.GetPreviousBar(cBar); if (!result) { // box.Clean(); zBar.Clean(); cBar.Clean(); // return result; } // XOHCL pBar; result = cBar.GetPreviousBar(pBar); if (!result) { // box.Clean(); zBar.Clean(); cBar.Clean(); pBar.Clean(); // return result; } // result = // isBullish ? ( // pBar.low > box.upper && cBar.low <= box.upper && zBar.open <= box.upper // ) : ( // pBar.high < box.lower && cBar.high >= box.lower && zBar.open >= box.lower // ) // ; // box.Clean(); zBar.Clean(); cBar.Clean(); pBar.Clean(); // return result; } // }; // struct X121SMCXWZWorkingZone { // string symbol; ENUM_TIMEFRAMES period; // double upper; double lower; // double zoneUpper; double zoneLower; // double quarter1; double quarter2; double quarter3; // datetime to; datetime from; // XOHCL swingBar; XOHCL breakerBar; XOHCL momentumBar; XOHCL rejectionBar; XBoxZone appliedBox; // X121SMCXWZWorkingZone() { Clean(); } // void Clean() { // upper = 0; lower = 0; quarter1 = 0; quarter2 = 0; quarter3 = 0; zoneLower = 0; zoneUpper = 0; // from = NULL; symbol = NULL; period = NULL; // CleanConditionBars(); // ZeroMemory(this); } // void CleanConditionBars() { // swingBar.Clean(); breakerBar.Clean(); appliedBox.Clean(); momentumBar.Clean(); rejectionBar.Clean(); } // bool IsValid() { // bool result = false; // result = lower > 0 && upper > 0 && quarter1 > 0 && quarter2 > 0 && quarter3 > 0 && upper > lower && zoneLower > 0 && zoneUpper > 0 && IsValid(from) && IsValid(symbol) && IsValid(period) && zoneUpper > upper && zoneLower < lower; // return result; } // bool IsDestroyed( ENUM_X_DIRECTION &destroyedDir, int barIndex = 0, ENUM_TIMEFRAMES forPeriod = NULL // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // if (!IsValid(forPeriod)) { forPeriod = period; } // destroyedDir = X_DIRECTION_NONE; // result = IsValid(); if (!result) { return result; } // XOHCL bar; result = bar.Init( symbol, forPeriod, barIndex // ); if (!result) { return result; } // bool isUpperBreaked = bar.high > zoneUpper && bar.close > zoneUpper; // bool isLowerBreaked = bar.low < zoneLower && bar.close < zoneLower; // result = isUpperBreaked || isLowerBreaked; if (result) { // destroyedDir = isUpperBreaked ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // return result; } // }; // // Definitions ... struct X121SMCStrategyXWZSignalConditions { // // Props ... // string symbol; ENUM_TIMEFRAMES period; // double sl; double target; double reward; double amountPercent; ENUM_X_DIRECTION dir; ENUM_X_POSITION_TYPES type; // // Setup Props ... // datetime setupTime; datetime triggerTime; // double pivot; double point; // ENUM_X121SMC_XWZ_PRIORITY priority; // // Working Zone ... XCFVG *fairValueGap; XCOrderBlock *orderBlock; XCSupplyZone *supplyZone; XCDemandZone *demandZone; X121SMCXWZWorkingZone workingZone; // X121SMCXWZZone startZone; // // Constructor ... X121SMCStrategyXWZSignalConditions() { 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; // target = 0; reward = 0; amountPercent = 0; // ZeroMemory(supplyZone); // ZeroMemory(demandZone); // ZeroMemory(orderBlock); // ZeroMemory(fairValueGap); // startZone.Clean(); // workingZone.Clean(); } // // // // bool HasWorkingZone() { return workingZone.IsValid(); } // bool HasOrderBlock() { return orderBlock != NULL && orderBlock.IsValid(); } // bool HasFairValueGap() { return fairValueGap != NULL && fairValueGap.IsValid(); } // bool HasSupplyZone() { return supplyZone != NULL && supplyZone.IsValid(); } // bool HasDemandZone() { return demandZone != NULL && demandZone.IsValid(); } // bool HasStartZone() { return startZone.IsValid(); } // void UpdateTo(datetime value = NULL) { // value = NormalizeTime(value); // bool hasSupplyZone = HasSupplyZone(); if (hasSupplyZone) { supplyZone.To(value); } // bool hasDemandZone = HasDemandZone(); if (hasDemandZone) { demandZone.To(value); } // bool hasOrderBlock = HasOrderBlock(); if (hasOrderBlock) { orderBlock.To(value); } // bool hasFairValueGap = HasFairValueGap(); if (hasFairValueGap) { fairValueGap.To(value); } // // Working Zone ... bool hasWorkingZone = HasWorkingZone(); if (hasWorkingZone) { workingZone.to = value; } // // Start Zone ... bool hasStartZone = HasStartZone(); if (hasStartZone) { // bool hasOB = startZone.HasOB(); if (hasOB) { startZone.ob.To(value); } // bool hasFVG = startZone.HasFVG(); if (hasFVG) { startZone.fvg.To(value); } // bool hasSupply = startZone.HasSupply(); if (hasSupply) { startZone.supply.To(value); } // bool hasDemand = startZone.HasDemand(); if (hasDemand) { startZone.demand.To(value); } // bool hasSupport = startZone.HasSupport(); if (hasSupport) { startZone.support.To(value); } // bool hasResistance = startZone.HasResistance(); if (hasResistance) { startZone.resistance.To(value); } // bool hasBullishCZone = startZone.HasBullishConsolidationZone(); if (hasBullishCZone) { // startZone.bullishConsolidationZone.to = cTime; } // bool hasBearishCZone = startZone.HasBearishConsolidationZone(); if (hasBearishCZone) { // startZone.bearishConsolidationZone.to = cTime; } } } // // // // // Working Zone is an Area which // we decide to trade inside it ... bool ExtractWorkingZone( XPOIState &htfState, XPOIState &mtfState, XPOIState &stfState, int barIndex = 0 // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } int zIndex = barIndex; // result = !HasWorkingZone(); if (!result) { return result; } // result = IsValid(symbol) && IsValid(period); if (!result) { // Clean(); return result; } // datetime cTime = iTime( symbol, period, zIndex // ); // result = // htfState.IsValid() && htfState.HasChild() && htfState.HasSupplyZones() && htfState.HasDemandZones() && // mtfState.IsValid() && mtfState.HasChild() && mtfState.HasSupplyZones() && mtfState.HasDemandZones() && // stfState.IsValid() && stfState.HasChild() // ; if (!result) { return result; } // // Retrieve Highest Supply Zone ... int hSupplyIDX = GetHighest(htfState.supplyZones); int lDemandIDX = GetLowest(htfState.demandZones); // result = // IsValidIndex(hSupplyIDX) && IsValidIndex(lDemandIDX) // ; if (!result) { return result; } // supplyZone = htfState.supplyZones[hSupplyIDX]; demandZone = htfState.demandZones[lDemandIDX]; // result = // supplyZone != NULL && demandZone != NULL && supplyZone.IsValid() && demandZone.IsValid() // ; if (!result) { // Clean(); return result; } // // Check Validation of Supply and Demand Zones ... lDemandIDX = GetLowest(mtfState.demandZones); hSupplyIDX = GetHighest(mtfState.supplyZones); result = IsValidIndex(lDemandIDX) && IsValidIndex(hSupplyIDX); if (!result) { // Clean(); return result; } // // Validate Supply and Demand ... bool isMTFHSupplyInside = IsInside( mtfState.supplyZones[hSupplyIDX], supplyZone); bool isMTFLDemandInside = IsInside( mtfState.demandZones[lDemandIDX], demandZone // ); if (isMTFHSupplyInside && !isMTFLDemandInside) { demandZone = mtfState.demandZones[lDemandIDX]; } else if (!isMTFHSupplyInside && isMTFLDemandInside) { supplyZone = mtfState.supplyZones[hSupplyIDX]; } else if (isMTFHSupplyInside && isMTFLDemandInside) { // supplyZone = mtfState.supplyZones[hSupplyIDX]; demandZone = mtfState.demandZones[lDemandIDX]; } // // Check Zones Validation ... bool hasTrend = supplyZone != NULL && supplyZone.IsValid() && demandZone != NULL && demandZone.IsValid(); result = hasTrend; if (!result) { // Clean(); return result; } // datetime from = MathMax( supplyZone.From(), demandZone.From()); // int fromIndex = iBarShift( symbol, period, from // ); // // Detect Trend ... ENUM_X_DIRECTION trend = X_DIRECTION_NONE; datetime supplyTouch = NULL; datetime demandTouch = NULL; for (int i = zIndex; i < fromIndex; i++) { // XOHCL iBar; bool isInited = iBar.Init( symbol, period, i // ); if (!isInited) { continue; } // bool isTouchSupplyZone = // iBar.low < supplyZone.Lower() && iBar.GetUp() > supplyZone.Lower() // ; if (isTouchSupplyZone && !IsValid(supplyTouch)) { supplyTouch = iBar.time; } // bool isTouchDemandZone = // iBar.high > demandZone.Upper() && iBar.GetDown() < demandZone.Upper() // ; if (isTouchDemandZone && !IsValid(demandTouch)) { demandTouch = iBar.time; } // bool canBreak = IsValid(supplyTouch) && IsValid(demandTouch); // iBar.Clean(); // if (canBreak) { break; } } // hasTrend = // IsValid(supplyTouch) || IsValid(demandTouch) // ; if (hasTrend) { // trend = // supplyTouch > demandTouch ? X_DIRECTION_BEARISH : X_DIRECTION_BULLISH // ; } // // Check Trend ... result = hasTrend; if (!result) { // Clean(); return result; } // bool hasBullishTrend = IsBullish(trend); bool hasBearishTrend = IsBearish(trend); // // Find Order Block and FVG for Trend Approve ... // bool isBullishTrendApproved = false; bool isBearishTrendApproved = false; // // Now We Have to Detect at least One OrderBlock with FVG ... // for Trend Approvement ... bool hasOrderBlock = HasOrderBlock(); bool hasFairValueGap = HasFairValueGap(); if (!hasOrderBlock && !hasFairValueGap) { // int count = 0; bool has = false; // XCFVG *fvg = NULL; XCOrderBlock *ob = NULL; // has = mtfState.HasBullishOrderBlocks(); count = mtfState.CountBullishOrderBlocks(); // if (has) { // // Check Order Block ... for (int i = 0; i < count; i++) { // XCOrderBlock *iOB = mtfState.bullishOrderBlocks[i]; // iOB.To(cTime); // // Check From Passes ... bool isFromPassed = iOB.From() > demandZone.From(); if (!isFromPassed) { continue; } // // Must inside DemandZone ... bool isInsideDemand = IsInsideDiff( iOB, demandZone // ); if (!isInsideDemand) { continue; } // // Check Started ... XOHCL startedBar; ENUM_X_DIRECTION startedDir; bool isStarted = iOB.IsStarted( X_DIRECTION_BULLISH, startedBar, startedDir // ); if (!isStarted) { // startedBar.Clean(); continue; } // // Converts to Box ... XBoxZone obBox; bool hasOBBox = ToBox( obBox, iOB // ); if (!hasOBBox) { // obBox.Clean(); startedBar.Clean(); continue; } // // Check Zone Must not Used before ... bool isUsed = IsBoxUsed( obBox, startedBar.Index() - 1, zIndex // ); if (isUsed) { // obBox.Clean(); startedBar.Clean(); continue; } // ob = iOB; // obBox.Clean(); startedBar.Clean(); // break; } // // Detect Fair Value Gap ... if (ob != NULL && ob.IsValid()) { // has = stfState.HasBullishFairValueGaps(); count = stfState.CountBullishFairValueGaps(); if (has) { // // Check Fir Value Gap ... for (int i = 0; i < count; i++) { // XCFVG *iFVG = stfState.bullishFairValueGaps[i]; // iFVG.To(cTime); // // Check From Passes ... bool isFromPassed = iFVG.From() > ob.From(); if (!isFromPassed) { continue; } // // Check Started ... XOHCL startedBar; ENUM_X_DIRECTION startedDir; bool isStarted = iFVG.IsStarted( X_DIRECTION_BULLISH, startedBar, startedDir // ); if (!isStarted) { // startedBar.Clean(); continue; } // // Converts to Box ... XBoxZone fvgBox; bool hasFVGBox = ToBox( fvgBox, iFVG // ); if (!hasFVGBox) { // fvgBox.Clean(); startedBar.Clean(); continue; } // // Check Inside Order Block ... bool isInside = IsInsideDiff( iFVG, ob, true // Force Side Out ... ); if (!isInside) { continue; } // fvg = iFVG; // fvgBox.Clean(); startedBar.Clean(); // break; } } else { // ob = NULL; } } // if (ob != NULL && fvg != NULL) { // orderBlock = ob; fairValueGap = fvg; } // hasOrderBlock = HasOrderBlock(); hasFairValueGap = HasFairValueGap(); isBullishTrendApproved = hasOrderBlock && hasFairValueGap; } // if (!isBullishTrendApproved) { // has = mtfState.HasBearishOrderBlocks(); count = mtfState.CountBearishOrderBlocks(); // if (has) { // // Check Order Block ... for (int i = 0; i < count; i++) { // XCOrderBlock *iOB = mtfState.bearishOrderBlocks[i]; // iOB.To(cTime); // // Check From Passes ... bool isFromPassed = iOB.From() > supplyZone.From(); if (!isFromPassed) { continue; } // // Must inside DemandZone ... bool isInsideDemand = IsInsideDiff( iOB, supplyZone // ); if (!isInsideDemand) { continue; } // // Check Started ... XOHCL startedBar; ENUM_X_DIRECTION startedDir; bool isStarted = iOB.IsStarted( X_DIRECTION_BEARISH, startedBar, startedDir // ); if (!isStarted) { // startedBar.Clean(); continue; } // // Converts to Box ... XBoxZone obBox; bool hasOBBox = ToBox( obBox, iOB // ); if (!hasOBBox) { // obBox.Clean(); startedBar.Clean(); continue; } // // Check Zone Must not Used before ... bool isUsed = IsBoxUsed( obBox, startedBar.Index() - 1, zIndex // ); if (isUsed) { // obBox.Clean(); startedBar.Clean(); continue; } // ob = iOB; // obBox.Clean(); startedBar.Clean(); // break; } // // Detect Fair Value Gap ... if (ob != NULL && ob.IsValid()) { // has = stfState.HasBearishFairValueGaps(); count = stfState.CountBearishFairValueGaps(); if (has) { // // Check Fir Value Gap ... for (int i = 0; i < count; i++) { // XCFVG *iFVG = stfState.bearishFairValueGaps[i]; // iFVG.To(cTime); // // Check From Passes ... bool isFromPassed = iFVG.From() > ob.From(); if (!isFromPassed) { continue; } // // Check Started ... XOHCL startedBar; ENUM_X_DIRECTION startedDir; bool isStarted = iFVG.IsStarted( X_DIRECTION_BEARISH, startedBar, startedDir // ); if (!isStarted) { // startedBar.Clean(); continue; } // // Converts to Box ... XBoxZone fvgBox; bool hasFVGBox = ToBox( fvgBox, iFVG // ); if (!hasFVGBox) { // fvgBox.Clean(); startedBar.Clean(); continue; } // // Check Inside Order Block ... bool isInside = IsInsideDiff( iFVG, ob, true // Force Side Out ... ); if (!isInside) { continue; } // fvg = iFVG; // fvgBox.Clean(); startedBar.Clean(); // break; } } else { // ob = NULL; } } // if (ob != NULL && fvg != NULL) { // orderBlock = ob; fairValueGap = fvg; } // hasOrderBlock = HasOrderBlock(); hasFairValueGap = HasFairValueGap(); isBearishTrendApproved = hasOrderBlock && hasFairValueGap; } } } // // Check Trend Approved ... bool isTrendApproved = hasOrderBlock && hasFairValueGap && (isBullishTrendApproved || isBearishTrendApproved); result = isTrendApproved; if (!result) { // Clean(); return result; } // // Prepare Working Zone ... workingZone.symbol = symbol; workingZone.period = period; // workingZone.upper = supplyZone.Lower(); workingZone.zoneUpper = supplyZone.Upper(); // workingZone.lower = demandZone.Upper(); workingZone.zoneLower = demandZone.Lower(); // workingZone.from = from; // double upper = workingZone.upper; double range = workingZone.upper - workingZone.lower; double ranegPercent = range / 100; double quarterValue = ranegPercent * 25; // workingZone.quarter1 = upper - (quarterValue * 1); workingZone.quarter2 = upper - (quarterValue * 2); workingZone.quarter3 = upper - (quarterValue * 3); // result = workingZone.IsValid(); if (!result) { Clean(); } // return result; } // bool IsWorkingZoneDestroyed( ENUM_X_DIRECTION &destroyedDir, int barIndex = 0, ENUM_TIMEFRAMES forPeriod = NULL // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // if (!IsValid(forPeriod)) { forPeriod = period; } // destroyedDir = X_DIRECTION_NONE; // result = workingZone.IsValid(); if (!result) { return result; } // result = workingZone.IsDestroyed( destroyedDir, barIndex, forPeriod // ); // return result; } // bool DetectTrend( ENUM_X_DIRECTION &trend, int barIndex = 0, ENUM_TIMEFRAMES forPeriod = NULL // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // if (forPeriod == NULL) { forPeriod = period; } // trend = X_DIRECTION_NONE; // result = HasWorkingZone(); if (!result) { return result; } // int FromIndex = iBarShift( symbol, forPeriod, workingZone.from // ); // datetime supplyTouch = NULL; datetime demandTouch = NULL; for (int i = barIndex; i < FromIndex; i++) { // XOHCL iBar; bool isInited = iBar.Init( symbol, forPeriod, i // ); if (!isInited) { continue; } // bool isTouchSupplyZone = // iBar.low < supplyZone.Lower() && iBar.GetUp() > supplyZone.Lower() // ; if (isTouchSupplyZone && !IsValid(supplyTouch)) { supplyTouch = iBar.time; } // bool isTouchDemandZone = // iBar.high > demandZone.Upper() && iBar.GetDown() < demandZone.Upper() // ; if (isTouchDemandZone && !IsValid(demandTouch)) { demandTouch = iBar.time; } // bool canBreak = IsValid(supplyTouch) && IsValid(demandTouch); // iBar.Clean(); // if (canBreak) { break; } } // result = // IsValid(supplyTouch) || IsValid(demandTouch) // ; if (result) { // trend = // supplyTouch > demandTouch ? X_DIRECTION_BEARISH : X_DIRECTION_BULLISH // ; } // return result; } // bool DetectStartZone( ENUM_X_DIRECTION forDir, XPOIState &state, XC121SMCCycleHelper *cycleHelper // ) { // bool result = false; // result = state.IsValid() && state.HasChild() && HasDirection(forDir); if (!result) { return result; } // bool isBullish = IsBullish(forDir); // int idx = -1; int count = 0; int has = false; // // Supply Zones ... has = state.HasSupplyZones(); if (has) { // idx = GetYoungest(state.supplyZones); if (IsValidIndex(idx)) { startZone.supply = state.supplyZones[idx]; } } // // Demand Zones ... has = state.HasDemandZones(); if (has) { // idx = GetYoungest(state.demandZones); if (IsValidIndex(idx)) { startZone.demand = state.demandZones[idx]; } } // // Support Zones ... has = state.HasSupportZones(); if (has) { // idx = GetYoungest(state.supportZones); if (IsValidIndex(idx)) { startZone.support = state.supportZones[idx]; } } // // Resistance Zones ... has = state.HasResistanceZones(); if (has) { // idx = GetYoungest(state.resistanceZones); if (IsValidIndex(idx)) { startZone.resistance = state.resistanceZones[idx]; } } // // Other Zones ... if (isBullish) { // // Order Block ... has = state.HasBullishOrderBlocks(); if (has) { // idx = GetYoungest(state.bullishOrderBlocks); if (IsValidIndex(idx)) { startZone.ob = state.bullishOrderBlocks[idx]; } } // // Fair Value Gap ... has = state.HasBullishFairValueGaps(); if (has) { // idx = GetYoungest(state.bullishFairValueGaps); if (IsValidIndex(idx)) { startZone.fvg = state.bullishFairValueGaps[idx]; } } } else { // // Order Block ... has = state.HasBearishOrderBlocks(); if (has) { // idx = GetYoungest(state.bearishOrderBlocks); if (IsValidIndex(idx)) { startZone.ob = state.bearishOrderBlocks[idx]; } } // // Fair Value Gap ... has = state.HasBearishFairValueGaps(); if (has) { // idx = GetYoungest(state.bearishFairValueGaps); if (IsValidIndex(idx)) { startZone.fvg = state.bearishFairValueGaps[idx]; } } } // bool hasOBFVG = startZone.HasOB() && startZone.HasFVG(); bool isOBStarted = false; bool isFVGStarted = false; bool isOBActivated = false; bool isFVGActivated = false; bool isOBInsideFVG = false; bool isFVGInsideOB = false; if (hasOBFVG) { // ENUM_X_DIRECTION forDir = startZone.ob.GetDirection(); // XOHCL startedBar; ENUM_X_DIRECTION startedDir; // isOBStarted = startZone.ob.IsStarted( forDir, startedBar, startedDir // ); // isOBActivated = startZone.ob.IsActivated( forDir, startedBar, startedDir // ); // forDir = startZone.fvg.GetDirection(); // isFVGStarted = startZone.fvg.IsStarted( forDir, startedBar, startedDir // ); // isFVGActivated = startZone.fvg.IsActivated( forDir, startedBar, startedDir // ); // isOBInsideFVG = IsInsideDiff( startZone.ob, startZone.fvg // ) || (isBullish ? IsAboveDiff( startZone.ob, startZone.fvg, true // IgnoreInside ) : IsBelowDiff( startZone.ob, startZone.fvg, true // IgnoreInside )); // isFVGInsideOB = IsInsideDiff( startZone.fvg, startZone.ob // ) || (isBullish ? IsAboveDiff( startZone.fvg, startZone.ob, true // IgnoreInside ) : IsBelowDiff( startZone.fvg, startZone.ob, true // IgnoreInside )); // startedBar.Clean(); } // result = isOBStarted && isFVGStarted && !isOBActivated && !isFVGActivated && startZone.IsValid() && (isOBInsideFVG || isFVGInsideOB) && (isBullish ? startZone.IsBullish() : startZone.IsBearish()); if (!result) { // startZone.Clean(); // return result; } // return result; } // void DetectPriority( ENUM_X121SMC_XWZ_PRIORITY &bullish, ENUM_X121SMC_XWZ_PRIORITY &bearish, int barIndex = 0, ENUM_TIMEFRAMES forPeriod = NULL // ) { // bullish = X121SMC_XWZ_PRIORITY_NONE; bearish = X121SMC_XWZ_PRIORITY_NONE; // if (barIndex < 0) { barIndex = 0; } // if (!IsValid(forPeriod)) { forPeriod = period; } // bool hasWorkingZone = HasWorkingZone(); if (!hasWorkingZone) { return; } // XOHCL zBar; bool isInited = zBar.Init( symbol, forPeriod, barIndex // ); if (!isInited) { // zBar.Clean(); return; } // XOHCL cBar; isInited = zBar.GetPreviousBar(cBar); if (!isInited) { // zBar.Clean(); cBar.Clean(); return; } // // ZoneUpper, Upper ... if (cBar.low > workingZone.upper && cBar.high < workingZone.zoneUpper && zBar.low > workingZone.upper && zBar.high < workingZone.zoneUpper) { // bullish = X121SMC_XWZ_PRIORITY_NONE; bearish = X121SMC_XWZ_PRIORITY_STRONG_HIGH; } // // Upper, Quarter1 ... else if (cBar.low > workingZone.quarter1 && cBar.high < workingZone.upper && zBar.low > workingZone.quarter1 && zBar.high < workingZone.upper) { // bullish = X121SMC_XWZ_PRIORITY_WEAK; bearish = X121SMC_XWZ_PRIORITY_HIGH; } // // Quarter1, Quarter2 ... else if (cBar.low > workingZone.quarter2 && cBar.high < workingZone.quarter1 && zBar.low > workingZone.quarter2 && zBar.high < workingZone.quarter1) { // bullish = X121SMC_XWZ_PRIORITY_LOW; bearish = X121SMC_XWZ_PRIORITY_REGULAR; } // // Quarter2, Quarter3 ... else if (cBar.low > workingZone.quarter3 && cBar.high < workingZone.quarter2 && zBar.low > workingZone.quarter3 && zBar.high < workingZone.quarter2) { // bullish = X121SMC_XWZ_PRIORITY_REGULAR; bearish = X121SMC_XWZ_PRIORITY_LOW; } // // Quarter3, Lower ... else if (cBar.low > workingZone.lower && cBar.high < workingZone.quarter3 && zBar.low > workingZone.lower && zBar.high < workingZone.quarter3) { // bullish = X121SMC_XWZ_PRIORITY_HIGH; bearish = X121SMC_XWZ_PRIORITY_WEAK; } // // Lower, ZoneLower ... else if (cBar.low > workingZone.zoneLower && cBar.high < workingZone.lower && zBar.low > workingZone.zoneLower && zBar.high < workingZone.lower) { // bullish = X121SMC_XWZ_PRIORITY_STRONG_HIGH; bearish = X121SMC_XWZ_PRIORITY_NONE; } // zBar.Clean(); cBar.Clean(); } // bool HasWorkingZoneConditions( ENUM_X_DIRECTION &conditionsDir, XPOIState &state, int barIndex = 0, ENUM_TIMEFRAMES forPeriod = NULL // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // conditionsDir = X_DIRECTION_NONE; // result = HasWorkingZone(); if (!result) { return result; } // XBoxZone appliedBox; // // Clean Condition Bars ... workingZone.CleanConditionBars(); // // Validate ... result = state.IsValid() && state.HasChild(); if (!result) { // workingZone.CleanConditionBars(); return result; } // if (!IsValid(forPeriod)) { forPeriod = period; } // datetime cTime = iTime( symbol, forPeriod, barIndex // ); // // Check Supply Zone ... // XBoxZone supplyBox; bool hasSupplyBox = supplyZone != NULL && supplyZone.IsValid() && ToBox( supplyBox, supplyZone // ); if (hasSupplyBox) { // result = CheckBoxForTradeConditions( supplyBox, appliedBox, workingZone.swingBar, workingZone.breakerBar, workingZone.rejectionBar, workingZone.momentumBar, state, barIndex, forPeriod // ); // if (result) { conditionsDir = X_DIRECTION_BEARISH; } } // // Check Demand Zone ... XBoxZone demandBox; bool hasDemandBox = false; if (!result) { // hasDemandBox = demandZone != NULL && demandZone.IsValid() && ToBox( demandBox, demandZone // ); if (hasDemandBox) { // result = CheckBoxForTradeConditions( demandBox, appliedBox, workingZone.swingBar, workingZone.breakerBar, workingZone.rejectionBar, workingZone.momentumBar, state, barIndex, forPeriod // ); // if (result) { conditionsDir = X_DIRECTION_BULLISH; } } } // if (!result) { workingZone.CleanConditionBars(); } // supplyBox.Clean(); demandBox.Clean(); appliedBox.Clean(); // return result; } // double GetSpread() { // double result = 0; // if (!IsValid(symbol)) { return result; } // result = GetSpread( symbol // ); // return result; } // };