/////////////////////////////////////////////////////// // // 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_PROVIDERS { X121SMC_XWZ_PROVIDER_NONE, X121SMC_XWZ_PROVIDER_PV_ZONE, X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE, X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH, X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE, }; // 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, }; // // Definitions ... // struct X121SMCStrategyXWZWorkingZone { // // Props ... // string symbol; ENUM_TIMEFRAMES period; // double quarter1; double quarter2; double quarter3; // XCSupplyZone *supplyZone; XCDemandZone *demandZone; // XOBFVG waitingZones[]; // CArrayObj mDrawnObjects; CArrayObj mWorkingZoneObjects; // // Constructor ... X121SMCStrategyXWZWorkingZone() { Clean(); } // // Tools ... // void Clean() { // quarter1 = 0; quarter2 = 0; quarter3 = 0; // symbol = NULL; period = NULL; // Clean(waitingZones); // ZeroMemory(supplyZone); ZeroMemory(demandZone); // mDrawnObjects.Clear(); mWorkingZoneObjects.Clear(); } // bool IsValid() { // bool result = false; // result = // quarter1 > 0 && quarter2 > 0 && quarter3 > 0 && HasSupplyZone() && HasDemandZone() && quarter1 > quarter2 && quarter2 > quarter3 // ; // return result; } // bool Init( string _symbol, ENUM_TIMEFRAMES _period, int barIndex, XPOIState &htfState, XPOIState &mtfState, XPOIState &stfState, // XPOIState &ttfState // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // result = // IsValid(_symbol) && IsValid(_period) && // htfState.IsValid() && mtfState.IsValid() && stfState.IsValid() && ttfState.IsValid() && // htfState.HasChild() && mtfState.HasChild() && stfState.HasChild() && ttfState.HasChild() // ; if (!result) { return result; } // symbol = _symbol; period = _period; // int idx = -1; int count = 0; bool has = false; // XOHCL zBar; has = zBar.Init( symbol, period, barIndex // ); result = has; if (!result) { zBar.Clean(); return result; } double ll5 = zBar.FindLowest(5, MODE_LOW); double hh5 = zBar.FindHighest(5, MODE_HIGH); zBar.Clean(); // // Supply Zone ... has = HasSupplyZone(); if (!has) { // idx = GetHighest(mtfState.supplyZones); has = IsValidIndex(idx); if (has) { // supplyZone = mtfState.supplyZones[idx]; has = hh5 < supplyZone.Lower(); if (!has) { supplyZone = NULL; } } } // // Demand Zone ... has = HasDemandZone(); if (!has) { // idx = GetLowest(mtfState.demandZones); has = IsValidIndex(idx); if (has) { // demandZone = mtfState.demandZones[idx]; has = ll5 > demandZone.Upper(); if (!has) { demandZone = NULL; } } } // if (supplyZone != NULL && demandZone != NULL && supplyZone.IsValid() && demandZone.IsValid()) { // double upper = supplyZone.Lower(); double lower = demandZone.Upper(); // double delta = ((upper - lower) / 100) * 25; // quarter1 = upper - (1 * delta); quarter2 = upper - (2 * delta); quarter3 = upper - (3 * delta); } // result = IsValid(); if (!result) { Clean(); } // return result; } // bool DetectZone( XCPOIDrawer *drawer, ENUM_XPOI_EVENTS &obPOIEvents[], ENUM_XPOI_EVENTS &fvgPOIEvents[], ENUM_XPOI_EVENTS &supDemPOIEvents[], XPOIState &obState, XPOIState &fvgState, XPOIState &supDemState // ) { // bool result = false; // result = IsValid() && obState.IsValid() && fvgState.IsValid() && supDemState.IsValid() && obState.HasOrderBlocks() && fvgState.HasFairValueGaps() && supDemState.HasSupplyZones() && supDemState.HasDemandZones(); if (!result) { return result; } // int idx = -1; bool has = false; datetime cTime = TimeCurrent(); // XOBFVG obFVG; XBoxZone obBox; XBoxZone fvgBox; XBoxZone supplyBox; XBoxZone demandBox; // XCFVG *fvg = NULL; XCOrderBlock *ob = NULL; XCSupplyZone *supply = NULL; XCDemandZone *demand = NULL; // // Check New Supply Zone Detection ... bool hasNewSupply = Contains( X_SUPPLY_ZONE_DETECTED, supDemPOIEvents // ); if (hasNewSupply) { // idx = GetYoungest(supDemState.supplyZones); has = IsValidIndex(idx); if (has) { // supply = supDemState.supplyZones[idx]; has = ToBox( supplyBox, supply // ); if (has) { // supply.To(cTime); supplyBox.to = cTime; hasNewSupply = supplyBox.IsValid(); } } } // // Check New Demand Zone Detection ... bool hasNewDemand = Contains( X_DEMAND_ZONE_DETECTED, supDemPOIEvents // ); if (hasNewDemand) { // idx = GetYoungest(supDemState.demandZones); has = IsValidIndex(idx); if (has) { // demand = supDemState.demandZones[idx]; has = ToBox( demandBox, demand // ); if (has) { // demand.To(cTime); demandBox.to = cTime; hasNewDemand = demandBox.IsValid(); } } } // // Check New Fair Value Gap Detection ... bool hasNewFairValueGap = Contains( X_BULLISH_FVG_DETECTED, fvgPOIEvents // ) || Contains( X_BEARISH_FVG_DETECTED, fvgPOIEvents // ); if (hasNewFairValueGap) { // idx = GetYoungest(fvgState.fairValueGaps); has = IsValidIndex(idx); if (has) { // fvg = fvgState.fairValueGaps[idx]; has = ToBox( fvgBox, fvg // ); if (has) { // fvg.To(cTime); fvgBox.to = cTime; hasNewFairValueGap = fvgBox.IsValid(); } } } // // Check New Order Block Detection ... bool hasNewOrderBlock = Contains( X_BULLISH_ORDERBLOCK_DETECTED, obPOIEvents // ) || Contains( X_BEARISH_ORDERBLOCK_DETECTED, obPOIEvents // ); if (hasNewOrderBlock) { // idx = GetYoungest(obState.orderBlocks); has = IsValidIndex(idx); if (has) { // ob = obState.orderBlocks[idx]; has = ToBox( obBox, ob // ); if (has) { // ob.To(cTime); obBox.to = cTime; hasNewOrderBlock = obBox.IsValid(); } } } // // Detect OB FVG ... result = hasNewOrderBlock && hasNewFairValueGap; if (result) { // obFVG.ob = ob; obFVG.AddFVG(fvg); // has = obFVG.IsValid(); if (has) { // // Check Item Is not Exists ... idx = FindIndex( obFVG, waitingZones // ); has = !IsValidIndex(idx); if (has) { // // New Waiting Zone ... AddRef( obFVG, waitingZones // ); } else { // // Update Exists Waiting Zone ... waitingZones[idx].AddFVG(fvg); } } } // // Detect SupDem FVG ... if (!result) { // result = hasNewFairValueGap && (hasNewSupply || hasNewDemand); if (result) { // // Converts Supply or Demand Zone to OrderBlock ... XOHCL bar; ob = new XCOrderBlock(); if (hasNewSupply) { // has = supply.FillBar(bar); if (has) { // has = ob.Init( bar, X_DIRECTION_BEARISH // ); if (has) { // ob.Upper(supply.Upper()); ob.Lower(supply.Lower()); } } } else if (hasNewDemand) { // has = demand.FillBar(bar); if (has) { // has = ob.Init( bar, X_DIRECTION_BULLISH // ); if (has) { // ob.Upper(demand.Upper()); ob.Lower(demand.Lower()); } } } // obFVG.ob = ob; obFVG.AddFVG(fvg); // has = obFVG.IsValid(); if (has) { // // Check Item Is not Exists ... idx = FindIndex( obFVG, waitingZones // ); has = !IsValidIndex(idx); if (has) { // // New Waiting Zone ... AddRef( obFVG, waitingZones // ); } else { // // Update Exists Waiting Zone ... waitingZones[idx].AddFVG(fvg); } } // bar.Clean(); } } // result = HasWaitingZones(); // // Cleanup Resources ... // obFVG.Clean(); obBox.Clean(); fvgBox.Clean(); supplyBox.Clean(); demandBox.Clean(); // ZeroMemory(ob); ZeroMemory(fvg); ZeroMemory(supplyZone); ZeroMemory(demandZone); // return result; } // bool IsDestroyed( int barIndex = 0, ENUM_TIMEFRAMES forPeriod = NULL // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // if (!IsValid(forPeriod)) { forPeriod = period; } // result = IsValid(); if (!result) { return result; } // XOHCL bar; result = bar.Init( symbol, period, barIndex // ); if (!result) { // bar.Clean(); return result; } // XOHCL cBar; result = bar.GetPreviousBar(cBar); if (!result) { // bar.Clean(); cBar.Clean(); // return result; } // bool isSupplyZoneBreaked = // bar.low > supplyZone.Upper() && cBar.low > supplyZone.Upper() // ; // bool isDemandZoneBreaked = // bar.high < demandZone.Lower() && cBar.high < demandZone.Lower() // ; // bar.Clean(); cBar.Clean(); // result = isSupplyZoneBreaked || isDemandZoneBreaked; // return result; } // bool DetectPriority( ENUM_X121SMC_XWZ_PRIORITY &priority, ENUM_X_DIRECTION forDir, int barIndex = 0, ENUM_TIMEFRAMES forPeriod = NULL // ) { // bool result = false; // priority = X121SMC_XWZ_PRIORITY_NONE; // if (barIndex < 0) { barIndex = 0; } // if (!IsValid(forPeriod)) { forPeriod = period; } // result = IsValid() && HasDirection(forDir); if (!result) { return result; } // bool isBullish = IsBullish(forDir); // XOHCL bar; result = bar.Init( symbol, forPeriod, barIndex // ); if (!result) { // bar.Clean(); return result; } // if (bar.high < supplyZone.Upper() && bar.low > supplyZone.Lower()) { // priority = isBullish ? X121SMC_XWZ_PRIORITY_NONE : X121SMC_XWZ_PRIORITY_STRONG_HIGH; } else if (bar.high < supplyZone.Lower() && bar.low > quarter1) { // priority = isBullish ? X121SMC_XWZ_PRIORITY_WEAK : X121SMC_XWZ_PRIORITY_HIGH; } else if (bar.high < quarter1 && bar.low > quarter2) { // priority = isBullish ? X121SMC_XWZ_PRIORITY_LOW : X121SMC_XWZ_PRIORITY_REGULAR; } else if (bar.high < quarter2 && bar.low > quarter3) { // priority = isBullish ? X121SMC_XWZ_PRIORITY_REGULAR : X121SMC_XWZ_PRIORITY_LOW; } else if (bar.high < quarter3 && bar.low > demandZone.Upper()) { // priority = isBullish ? X121SMC_XWZ_PRIORITY_HIGH : X121SMC_XWZ_PRIORITY_WEAK; } else if (bar.high < demandZone.Upper() && bar.low > demandZone.Lower()) { // priority = isBullish ? X121SMC_XWZ_PRIORITY_STRONG_HIGH : X121SMC_XWZ_PRIORITY_NONE; } // result = priority != X121SMC_XWZ_PRIORITY_NONE && priority != X121SMC_XWZ_PRIORITY_WEAK; // bar.Clean(); // return result; } // bool DetectOveralDirection( ENUM_X_DIRECTION &dir // ) { // bool result = false; // dir = X_DIRECTION_NONE; // result = IsValid() && HasSupplyZone() && HasDemandZone(); if (!result) { return result; } // XBoxZone demBox; XBoxZone supBox; result = ToBox( demBox, demandZone // ); if (!result) { // supBox.Clean(); demBox.Clean(); // return result; } result = ToBox( supBox, supplyZone // ); if (!result) { // supBox.Clean(); demBox.Clean(); // return result; } // XOHCL supPriceOutBar; XOHCL demPriceOutBar; result = DetectBoxNearestPriceOut( supBox, supPriceOutBar, period // ); if (!result) { // demBox.Clean(); supBox.Clean(); supPriceOutBar.Clean(); demPriceOutBar.Clean(); // return result; } result = DetectBoxNearestPriceOut( demBox, demPriceOutBar, period // ); if (!result) { // demBox.Clean(); supBox.Clean(); supPriceOutBar.Clean(); demPriceOutBar.Clean(); // return result; } // // Specified Direction ... dir = (supPriceOutBar.IsValid() && demPriceOutBar.IsValid()) ? supPriceOutBar.time > demPriceOutBar.time ? X_DIRECTION_BEARISH : demPriceOutBar.time > supPriceOutBar.time ? X_DIRECTION_BULLISH : X_DIRECTION_NONE : X_DIRECTION_NONE; // result = HasDirection(dir); // // Clean Up Resources ... // demBox.Clean(); supBox.Clean(); supPriceOutBar.Clean(); demPriceOutBar.Clean(); // return result; } // void UpdateTo(datetime value = NULL) { // value = NormalizeTime(value); // int count = 0; bool has = false; // has = HasSupplyZone(); if (has) { supplyZone.To(value); } // has = HasDemandZone(); if (has) { demandZone.To(value); } // has = HasWaitingZones(); if (has) { // count = CountWaitingZones(); for (int i = 0; i < count; i++) { waitingZones[i].UpdateTo(value); } } // } // void Draw( XCPOIDrawer *drawer, bool drawSupplyZone = false, bool drawDemandZone = false, bool drawWaitingZones = false // ) { // if (drawer == NULL) { return; } // int count = 0; bool has = false; bool isCreated = false; // ulong chartID = drawer.ChartIdentification(); int subWindow = drawer.SubWindowIdentification(); color bullishColor = drawer.BarBullishColor(); color bearishColor = drawer.BarBearishColor(); // // Supply Zone ... if (drawSupplyZone) { // has = HasSupplyZone(); if (has) { // XCSupplyZoneObject *iObj; isCreated = drawer.CreateSupplyZone( supplyZone, iObj // ); // if (isCreated) { mWorkingZoneObjects.Add(iObj); } } } // // Demand Zone ... if (drawDemandZone) { // has = HasDemandZone(); if (has) { // XCDemandZoneObject *iObj; isCreated = drawer.CreateDemandZone( demandZone, iObj // ); // if (isCreated) { mWorkingZoneObjects.Add(iObj); } } } // // // // // Quarters ... has = IsValid(); if (has) { // double zoneUpper = supplyZone.Upper(); double upper = supplyZone.Lower(); // double lower = demandZone.Upper(); double zoneLower = demandZone.Lower(); // string prefix = "X121WZone_" + symbol + "_" + ToString(period); // // Zone Upper ... CChartObjectHLine *zoneUpperLine; zoneUpperLine = new CChartObjectHLine(); isCreated = zoneUpperLine.Create( chartID, prefix + "_ZoneTop", subWindow, zoneUpper // ); if (isCreated) { // zoneUpperLine.Color(clrRed); // mWorkingZoneObjects.Add(zoneUpperLine); } // // Zone Lower ... CChartObjectHLine *zoneLowerLine; zoneLowerLine = new CChartObjectHLine(); isCreated = zoneLowerLine.Create( chartID, prefix + "_ZoneDown", subWindow, zoneLower // ); if (isCreated) { // zoneLowerLine.Color(clrRed); // mWorkingZoneObjects.Add(zoneLowerLine); } // // Upper ... CChartObjectHLine *upperLine; upperLine = new CChartObjectHLine(); isCreated = upperLine.Create( chartID, prefix + "_Upper", subWindow, upper // ); if (isCreated) { // upperLine.Color(clrLime); // mWorkingZoneObjects.Add(upperLine); } // // Lower ... CChartObjectHLine *lowerLine; lowerLine = new CChartObjectHLine(); isCreated = lowerLine.Create( chartID, prefix + "_Lower", subWindow, lower // ); if (isCreated) { // lowerLine.Color(clrLime); // mWorkingZoneObjects.Add(lowerLine); } // // Quarters ... // // Quarter 1 ... CChartObjectHLine *q1Line; q1Line = new CChartObjectHLine(); isCreated = q1Line.Create( chartID, prefix + "_Q1", subWindow, quarter1 // ); if (isCreated) { // q1Line.Color(clrYellow); // mWorkingZoneObjects.Add(q1Line); } // // Quarter 2 ... CChartObjectHLine *q2Line; q2Line = new CChartObjectHLine(); isCreated = q2Line.Create( chartID, prefix + "_Q2", subWindow, quarter2 // ); if (isCreated) { // q2Line.Color(clrYellow); // mWorkingZoneObjects.Add(q2Line); } // // Quarter 3 ... CChartObjectHLine *q3Line; q3Line = new CChartObjectHLine(); isCreated = q3Line.Create( chartID, prefix + "_Q3", subWindow, quarter3 // ); if (isCreated) { // q3Line.Color(clrYellow); // mWorkingZoneObjects.Add(q3Line); } } // // Waiting Zones ... if (drawWaitingZones) { // has = HasWaitingZones(); if (has) { // count = CountWaitingZones(); for (int i = 0; i < count; i++) { // XCBaseObject *iObjects[]; int iObjectsCount = drawer.DrawOBFVG( waitingZones[i], iObjects, true, // Draw Order Block ... true, // Draw Fair Value Gaps ... // true, // Draw OB StartedBar ... true, // Draw OB ActivatedBar ... true, // Draw OB BreakedBar ... true, // Draw OB WorkedBar ... // true, // Draw FVG StartedBar ... true, // Draw FVG ActivatedBar ... true, // Draw FVG BreakedBar ... true // Draw FVG WorkedBar ... // ); has = IsValidSize(iObjectsCount); if (has) { // for (int j = 0; j < iObjectsCount; j++) { mDrawnObjects.Add(iObjects[j]); } } } } } // } // // // // bool HasSupplyZone() { return supplyZone != NULL && supplyZone.IsValid(); } // bool HasDemandZone() { return demandZone != NULL && demandZone.IsValid(); } // bool HasWaitingZones() { return HasChild(waitingZones); } // int CountWaitingZones() { return ArraySize(waitingZones); } // }; // struct X121SMCStrategyXWZSignalConditions { // // Props ... // string symbol; ENUM_TIMEFRAMES period; // double sl; double reward; double amountPercent; ENUM_X_DIRECTION dir; ENUM_X_POSITION_TYPES type; // // Setup Props ... // datetime setupTime; datetime triggerTime; // double pivot; double point; double sls[]; double targets[]; // XBoxZone signalBox; // ENUM_X121SMC_XWZ_PRIORITY priority; ENUM_X121SMC_XWZ_PROVIDERS provider; // // Constructor ... X121SMCStrategyXWZSignalConditions() { Clean(); } // // Tools ... /** * Cleaning Up ... */ void Clean() { // sl = 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; // reward = 0; amountPercent = 0; // Clean(sls); Clean(targets); signalBox.Clean(); // provider = X121SMC_XWZ_PROVIDER_NONE; } // // // // void UpdateTo(datetime value = NULL) { // value = NormalizeTime(value); // int count = 0; bool has = false; } // }; // // Extension Functions ... //