/////////////////////////////////////////////////////// // // 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, }; // struct X121SMCXWZWorkingZone { // string symbol; ENUM_TIMEFRAMES period; // double upper; double lower; // double zoneUpper; double zoneLower; // double quarter1; double quarter2; double quarter3; // datetime from; // X121SMCXWZWorkingZone() { Clean(); } // void Clean() { // upper = 0; lower = 0; quarter1 = 0; quarter2 = 0; quarter3 = 0; zoneLower = 0; zoneUpper = 0; // from = NULL; symbol = NULL; period = NULL; // ZeroMemory(this); } // 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 DetectOveralTrend( XOHCL &touchedBar, ENUM_X_DIRECTION &trendDir, int barIndex = 0 // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // trendDir = X_DIRECTION_NONE; // result = IsValid(); if (!result) { return result; } // int fromBarIndex = iBarShift( symbol, period, from // ); result = IsValidIndex(fromBarIndex); if (!result) { return result; } // XOHCL nearestUpperTouchedBar; XOHCL nearestLowerTouchedBar; bool hasNearestUpperTouchedBar = false; bool hasNearestLowerTouchedBar = false; for (int i = barIndex; i < fromBarIndex; i++) { // XOHCL iBar; bool isInited = iBar.Init( symbol, period, i // ); // hasNearestUpperTouchedBar = nearestUpperTouchedBar.IsValid(); if (!hasNearestUpperTouchedBar) { // bool isBarTouchedUpper = iBar.high > upper; if (isBarTouchedUpper) { // nearestUpperTouchedBar = iBar; hasNearestUpperTouchedBar = true; } } // hasNearestLowerTouchedBar = nearestLowerTouchedBar.IsValid(); if (!hasNearestLowerTouchedBar) { // bool isBarTouchedLower = iBar.low < lower; if (isBarTouchedLower) { // nearestLowerTouchedBar = iBar; hasNearestLowerTouchedBar = true; } } // if (hasNearestUpperTouchedBar && hasNearestLowerTouchedBar) { break; } } // result = hasNearestUpperTouchedBar || hasNearestLowerTouchedBar; if (result) { // if (hasNearestUpperTouchedBar && !hasNearestLowerTouchedBar) { // trendDir = X_DIRECTION_BEARISH; touchedBar = nearestUpperTouchedBar; } else if (!hasNearestUpperTouchedBar && hasNearestLowerTouchedBar) { // trendDir = X_DIRECTION_BULLISH; touchedBar = nearestLowerTouchedBar; } else if (hasNearestUpperTouchedBar && hasNearestLowerTouchedBar) { // trendDir = nearestUpperTouchedBar.time < nearestLowerTouchedBar.time ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // if (IsBullish(trendDir)) { touchedBar = nearestLowerTouchedBar; } else { touchedBar = nearestUpperTouchedBar; } } } // 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; // // 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; // delete supplyZone; ZeroMemory(supplyZone); // delete demandZone; ZeroMemory(demandZone); // workingZone.Clean(); } // // // // bool HasWorkingZone() { return workingZone.IsValid(); } // // Working Zone is an Area which // we decide to trade inside it ... bool ExtractWorkingZone( XPOIState &state // ) { // bool result = false; // result = !HasWorkingZone(); if (!result) { return result; } // result = state.IsValid() && state.HasChild() && state.HasSupplyZones() && state.HasDemandZones(); if (!result) { return result; } // // Retrieve Highest Supply Zone ... int hSupplyIDX = GetHighest(state.supplyZones); int lDemandIDX = GetLowest(state.demandZones); // result = // IsValidIndex(hSupplyIDX) && IsValidIndex(lDemandIDX) // ; if (!result) { return result; } // supplyZone = state.supplyZones[hSupplyIDX]; demandZone = state.demandZones[lDemandIDX]; // result = // supplyZone != NULL && demandZone != NULL && supplyZone.IsValid() && demandZone.IsValid() // ; if (!result) { // Clean(); return result; } // workingZone.symbol = symbol; workingZone.period = period; // workingZone.upper = supplyZone.Lower(); workingZone.zoneUpper = supplyZone.Upper(); // workingZone.lower = demandZone.Upper(); workingZone.zoneLower = demandZone.Lower(); // workingZone.from = MathMax(supplyZone.From(), demandZone.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 HasOrderBlock() { return orderBlock != NULL && orderBlock.IsValid(); } // bool HasFairValueGap() { return fairValueGap != NULL && fairValueGap.IsValid(); } // void UpdateTo(datetime value = NULL) { // value = NormalizeTime(value); // if (supplyZone != NULL) { supplyZone.To(value); } // if (demandZone != NULL) { demandZone.To(value); } // if (orderBlock != NULL) { orderBlock.To(value); } // if (fairValueGap != NULL) { fairValueGap.To(value); } } // };