/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Common Library // -------------------------------------- // Name: X121SMCLib // Description: provide all commonly used 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 "../../Classes/x-saherelm.base.class.mq5" #include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" #include "../../Helpers/x-saherelm.x121.helper.mq5" #include "../../Libraries/x-saherelm.common.lib.mq5" #include "../../Libraries/x-saherelm.x-poi.lib.mq5" #include "../../Libraries/x-saherelm.x-trade.lib.mq5" // // Definitions ... // const string X121SMCStrategyToken = "X121SMC"; // const string X121SMCXToken = "X121X"; const string X121SMCXHKPVToken = "X121XHKPV"; const string X121SMCXOBPVToken = "X121XOBPV"; // // X121 SMC Providers ... enum ENUM_X_121_SMC_PROVIDERS { // X_121_SMC_PROVIDER_NONE, X_121_SMC_PROVIDER_X, X_121_SMC_PROVIDER_XHKPV, X_121_SMC_PROVIDER_XOBPV, }; // // Guard Actions ... enum ENUM_X_121_SMC_GUARD_ACTIONS { X_121_SMC_GUARD_ACTION_NONE, // Nothing to Do X_121_SMC_GUARD_ACTION_CLOSE, // Close Specified Position X_121_SMC_GUARD_ACTION_CLOSE_ALL, // Close All Positions X_121_SMC_GUARD_ACTION_CLOSE_LONGS, // Close All Long Positions X_121_SMC_GUARD_ACTION_CLOSE_SHORTS, // Close All Short Position X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE, // Partial Close Specified Position X_121_SMC_GUARD_ACTION_TRAIL_STOP, // Trail Stop of Specified Position X_121_SMC_GUARD_ACTION_TRAIL_TARGET, // Trail Target of Specified Position X_121_SMC_GUARD_ACTION_HEDGE, // Hedge Specified Positions }; // // Each Market Cycle (Time Frame) Conditions // Model as this Structure ... struct X121SMCCycleConditions { // string symbol; ENUM_TIMEFRAMES period; datetime time; // X121Conditions x121Conditions; // XPOIState state; // void X121SMCStrategyConditions() { Clean(); } // // Tools ... /** * Cleanup ... */ void Clean() { // symbol = NULL; period = NULL; time = NULL; // state.Clean(); x121Conditions.Clean(); } /** * Validate ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = IsSpecifiedValid(symbol) && IsSpecifiedValid(period) && IsSpecifiedValid(time); // ; // return result; } // // Reporter Functions ... /** * Generate Provided Scores ... * * @param bullishScore: Integer, reference ... * @param bearishScore: Integer, referenceF ... */ void GenerateScore( double &bullishScore, double &bearishScore // ) { // bullishScore = 0; bearishScore = 0; // if (!IsValid()) { return; } // double bullScore = 0; double bearScore = 0; } /** * Generate Summary ... * * @param onlyCommons: Boolean ... * @param onlyConditions: Boolean ... * @param includeScores: Boolean ... * @param ignoreFalseConditions: Boolean ... * @param separator: String ... * * @return ( string ) */ string GenerateSummary( bool onlyCommons = false, bool onlyConditions = false, bool includeScores = true, bool ignoreFalseConditions = true, string separator = "\n" // ) { // string result = NULL; // double bullishScore = 0; double bearishScore = 0; GenerateScore( bullishScore, bearishScore // ); // string commonStr = GenerateSpecifiedCommonSummary( this, separator, includeScores, true // ); // string conditionsStr = // "" // ; // result = // "[" + GetTag() + "]" + separator + "----------" + separator + (onlyConditions ? "" : commonStr) + " " + separator + (onlyCommons ? "" : conditionsStr) + "" // ; // return result; } /** * Get Unique Identifier ... * * @param forObject: Boolean ... * * @return ( string ) */ string GetTag( bool forObject = false // ) { // string result = NULL; // string typeName = GetTypeName(this); // if (!forObject) { result = typeName; } else { // result = typeName + "_" + symbol + "_" + ToString(period) + "_" + ToMD5(time); } // return result; } // }; // // Model Signalling Conditions ... struct X121SMCStrategyConditions { // string symbol; ENUM_TIMEFRAMES period; datetime time; // double sl; double tp; double target; string provider; ENUM_X_DIRECTION signalDir; // X121Conditions conditions; // XPriceZones priceZones; // XPriceZones decisionZones; // XMarketStructure marketStructure; // void X121SMCStrategyConditions() { Clean(); } // // Tools ... /** * Cleanup ... */ void Clean() { // symbol = NULL; period = NULL; time = NULL; // sl = 0; tp = 0; provider = NULL; signalDir = X_DIRECTION_NONE; // conditions.Clean(); // priceZones.Clean(); // decisionZones.Clean(); // marketStructure.Clean(); } /** * Validate ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = IsSpecifiedValid(symbol) && IsSpecifiedValid(period) && IsSpecifiedValid(time); // return result; } /** * Check Conditions Has Valid Bullish Signal ... * * @return ( bool ) */ bool HasBullishSignal() { // bool result = false; // result = (sl > 0 || tp > 0) && IsValid() && HasDirection(signalDir); if (!result) { return result; } // result = IsBullish(signalDir); // return result; } /** * Check Conditions Has Valid Bearish Signal ... * * @return ( bool ) */ bool HasBearishSignal() { // bool result = false; // result = (sl > 0 || tp > 0) && IsValid() && HasDirection(signalDir); if (!result) { return result; } // result = IsBearish(signalDir); // return result; } // // Reporter Functions ... /** * Generate Provided Scores ... * * @param bullishScore: Integer, reference ... * @param bearishScore: Integer, referenceF ... */ void GenerateScore( double &bullishScore, double &bearishScore // ) { // bullishScore = 0; bearishScore = 0; // if (!IsValid()) { return; } // double bullScore = 0; double bearScore = 0; } /** * Generate Summary ... * * @param onlyCommons: Boolean ... * @param onlyConditions: Boolean ... * @param includeScores: Boolean ... * @param ignoreFalseConditions: Boolean ... * @param separator: String ... * * @return ( string ) */ string GenerateSummary( bool onlyCommons = false, bool onlyConditions = false, bool includeScores = true, bool ignoreFalseConditions = true, string separator = "\n" // ) { // string result = NULL; // double bullishScore = 0; double bearishScore = 0; GenerateScore( bullishScore, bearishScore // ); // string commonStr = GenerateSpecifiedCommonSummary( this, separator, includeScores, true // ); // string conditionsStr = // "" // ; // result = // "[" + GetTag() + "]" + separator + "----------" + separator + (onlyConditions ? "" : commonStr) + " " + separator + (onlyCommons ? "" : conditionsStr) + "" // ; // return result; } /** * Get Unique Identifier ... * * @param forObject: Boolean ... * * @return ( string ) */ string GetTag( bool forObject = false // ) { // string result = NULL; // string typeName = GetTypeName(this); // if (!forObject) { result = typeName; } else { // result = typeName + "_" + symbol + "_" + ToString(period) + "_" + ToMD5(time); } // return result; } // }; // // Model a Guard Action ... struct X121SMCGuard { // // Props ... ENUM_X_121_SMC_GUARD_ACTIONS action; datetime time; // string symbol; string provider; // // Specified Position ... ulong ticket; // // Partial Close ... double volumeMultiplier; // // SL Trial ... double sl; // // TP Trial ... double tp; // // Constructor ... X121SMCGuard() { Clean(); } // // Tools ... /** * Cleanup ... */ void Clean() { // time = NULL; action = X_121_SMC_GUARD_ACTION_NONE; // symbol = NULL; provider = NULL; // ticket = 0; // volumeMultiplier = 0; // sl = 0; tp = 0; } /** * Validate ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = // IsValid(time) && IsValid(symbol) && IsValid(provider) && action != X_121_SMC_GUARD_ACTION_NONE // ; if (!result) { return result; } // // Validate Model Based On Specified Guard Actions ... // return result; } }; // // Model Cycle State ... struct X121SMCCycleState { // // Props ... string symbol; ENUM_TIMEFRAMES period; // // Bullish ... XCFVG *bullishFVGs[]; XCOrderBlock *bullishOBs[]; XCDemandZone *demandZones[]; XCSupportZone *supportZones[]; // // Bearish ... XCFVG *bearishFVGs[]; XCOrderBlock *bearishOBs[]; XCSupplyZone *supplyZones[]; XCResistanceZone *resistanceZones[]; // // Constructor ... X121SMCCycleState() { Clean(); } // // Tools ... /** * Cleanup Model ... */ void Clean() { // symbol = NULL; period = NULL; // Clean(bullishFVGs); Clean(bullishOBs); Clean(demandZones); Clean(supportZones); // Clean(bearishFVGs); Clean(bearishOBs); Clean(supplyZones); Clean(resistanceZones); } /** * Validate Model ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = // IsValid(symbol) && IsValid(period) && ( // (HasBullishOBs() && (HasBullishFVGs() || HasSupportZones() || HasDemandZones())) // || (HasBearishOBs() && (HasSupplyZones() || HasBearishFVGs() || HasResistanceZones())) // ) // ; // return result; } // int CountBullishOBs() { return ArraySize(bullishOBs); } // bool HasBullishOBs() { return IsValidSize(CountBullishOBs()); } // int CountBearishOBs() { return ArraySize(bearishOBs); } // bool HasBearishOBs() { return IsValidSize(CountBearishOBs()); } // int CountSupportZones() { return ArraySize(supportZones); } // bool HasSupportZones() { return IsValidSize(CountSupportZones()); } // int CountResistanceZones() { return ArraySize(resistanceZones); } // bool HasResistanceZones() { return IsValidSize(CountResistanceZones()); } // int CountDemandZones() { return ArraySize(demandZones); } // bool HasDemandZones() { return IsValidSize(CountDemandZones()); } // int CountSupplyZones() { return ArraySize(supplyZones); } // bool HasSupplyZones() { return IsValidSize(CountSupplyZones()); } // int CountBullishFVGs() { return ArraySize(bullishFVGs); } // bool HasBullishFVGs() { return IsValidSize(CountBullishFVGs()); } // int CountBearishFVGs() { return ArraySize(bearishFVGs); } // bool HasBearishFVGs() { return IsValidSize(CountBearishFVGs()); } // }; bool DetectPriceInsideBox( XBoxZone &box, X121Conditions &xConditions, X121SMCCycleState &state // ) { // bool result = false; // box.Clean(); // string symbol = state.symbol; ENUM_TIMEFRAMES period = state.period; // box.symbol = symbol; box.period = period; // result = state.IsValid(); if (!result) { return result; } // // Detect Price Inside Order Block ... // bool hasBullishOBs = state.HasBullishOBs(); int bullishOBsCount = state.CountBullishOBs(); // bool hasBearishOBs = state.HasBearishOBs(); int bearishOBsCount = state.CountBearishOBs(); // bool hasOBs = // hasBullishOBs || hasBearishOBs // ; result = hasOBs; if (!result) { return result; } // bool hasPriceInsideOB = false; XCOrderBlock *priceInsideOB = NULL; ENUM_X_DIRECTION boxDir = X_DIRECTION_NONE; // if (hasBullishOBs && !hasPriceInsideOB) { // for (int i = 0; i < bullishOBsCount; i++) { // XCOrderBlock *iOb = state.bullishOBs[i]; // bool isInside = IsPriceInsideZone( xConditions.valesBuffer[1], (XCZone *)iOb // ); if (isInside) { // priceInsideOB = iOb; hasPriceInsideOB = true; boxDir = X_DIRECTION_BULLISH; break; } } } // if (hasBearishOBs && !hasPriceInsideOB) { // for (int i = 0; i < bearishOBsCount; i++) { // XCOrderBlock *iOb = state.bearishOBs[i]; // bool isInside = IsPriceInsideZone( xConditions.peaksBuffer[1], (XCZone *)iOb // ); if (isInside) { // priceInsideOB = iOb; hasPriceInsideOB = true; boxDir = X_DIRECTION_BEARISH; break; } } } // bool hasBullishFVGs = state.HasBullishFVGs(); bool hasBearishFVGs = state.HasBearishFVGs(); bool hasDemandZones = state.HasDemandZones(); bool hasSupplyZones = state.HasSupplyZones(); bool hasSupportZones = state.HasSupportZones(); bool hasResistanceZones = state.HasResistanceZones(); // bool hasBullishZones = // hasBullishFVGs || hasDemandZones || hasSupportZones // ; // bool hasBearishZones = // hasBearishFVGs || hasSupplyZones || hasResistanceZones // ; // bool hasPropperZones = // IsBullish(boxDir) ? hasBullishZones : IsBearish(boxDir) ? hasBearishZones : false // ; // if (!hasPropperZones && hasPriceInsideOB) { // // Use Price Inside OB as Box ... box.to = priceInsideOB.To(); box.from = priceInsideOB.From(); box.upper = priceInsideOB.Upper(); box.lower = priceInsideOB.Lower(); } else if (hasPropperZones && hasPriceInsideOB) { // // Detect Validate Zones ... int count = 0; XBoxZone boxes[]; double upper = 0; double lower = 0; double price = 0; datetime to = NULL; datetime from = NULL; ENUM_X_DIRECTION dir = X_DIRECTION_NONE; if (IsBullish(boxDir)) { // double price = xConditions.valesBuffer[1]; ENUM_X_DIRECTION dir = X_DIRECTION_BULLISH; // // Bullish FVG ... count = state.CountBullishFVGs(); for (int i = 0; i < count; i++) { // XCFVG *iFVG = state.bullishFVGs[i]; // to = iFVG.To(); from = iFVG.From(); upper = iFVG.Upper(); lower = iFVG.Lower(); // bool isInside = IsPriceInsideZone( price, upper, lower // ); if (isInside) { // XBoxZone iBox; // iBox.dir = dir; iBox.symbol = symbol; iBox.period = period; // iBox.to = to; iBox.from = from; iBox.upper = upper; iBox.lower = lower; // if (iBox.IsValid()) { // AddRef( iBox, boxes // ); } } } // // Demand Zones ... count = state.CountDemandZones(); for (int i = 0; i < count; i++) { // XCDemandZone *iDemand = state.demandZones[i]; // to = iDemand.To(); from = iDemand.From(); upper = iDemand.Upper(); lower = iDemand.Lower(); // bool isInside = IsPriceInsideZone( price, upper, lower // ); if (isInside) { // XBoxZone iBox; // iBox.dir = dir; iBox.symbol = symbol; iBox.period = period; // iBox.to = to; iBox.from = from; iBox.upper = upper; iBox.lower = lower; // if (iBox.IsValid()) { // AddRef( iBox, boxes // ); } } } // // Support Zones ... count = state.CountSupportZones(); for (int i = 0; i < count; i++) { // XCSupportZone *iSupport = state.supportZones[i]; // to = iSupport.To(); from = iSupport.From(); upper = iSupport.Upper(); lower = iSupport.Lower(); // bool isInside = IsPriceInsideZone( price, upper, lower // ); if (isInside) { // XBoxZone iBox; // iBox.dir = dir; iBox.symbol = symbol; iBox.period = period; // iBox.to = to; iBox.from = from; iBox.upper = upper; iBox.lower = lower; // if (iBox.IsValid()) { // AddRef( iBox, boxes // ); } } } } else { // double price = xConditions.peaksBuffer[1]; ENUM_X_DIRECTION dir = X_DIRECTION_BEARISH; // // Bearish FVG ... count = state.CountBearishFVGs(); for (int i = 0; i < count; i++) { // XCFVG *iFVG = state.bearishFVGs[i]; // to = iFVG.To(); from = iFVG.From(); upper = iFVG.Upper(); lower = iFVG.Lower(); // bool isInside = IsPriceInsideZone( price, upper, lower // ); if (isInside) { // XBoxZone iBox; // iBox.dir = dir; iBox.symbol = symbol; iBox.period = period; // iBox.to = to; iBox.from = from; iBox.upper = upper; iBox.lower = lower; // if (iBox.IsValid()) { // AddRef( iBox, boxes // ); } } } // // Supply Zones ... count = state.CountSupplyZones(); for (int i = 0; i < count; i++) { // XCSupplyZone *iSupply = state.supplyZones[i]; // to = iSupply.To(); from = iSupply.From(); upper = iSupply.Upper(); lower = iSupply.Lower(); // bool isInside = IsPriceInsideZone( price, upper, lower // ); if (isInside) { // XBoxZone iBox; // iBox.dir = dir; iBox.symbol = symbol; iBox.period = period; // iBox.to = to; iBox.from = from; iBox.upper = upper; iBox.lower = lower; // if (iBox.IsValid()) { // AddRef( iBox, boxes // ); } } } // // Demand Zones ... count = state.CountResistanceZones(); for (int i = 0; i < count; i++) { // XCResistanceZone *iResistance = state.resistanceZones[i]; // to = iResistance.To(); from = iResistance.From(); upper = iResistance.Upper(); lower = iResistance.Lower(); // bool isInside = IsPriceInsideZone( price, upper, lower // ); if (isInside) { // XBoxZone iBox; // iBox.dir = dir; iBox.symbol = symbol; iBox.period = period; // iBox.to = to; iBox.from = from; iBox.upper = upper; iBox.lower = lower; // if (iBox.IsValid()) { // AddRef( iBox, boxes // ); } } } } // int boxesCount = ArraySize(boxes); bool hasBoxes = IsValidSize(boxes); if (hasBoxes) { // // Filter Boxes ... for (int i = 0; i < boxesCount; i++) { // XBoxZone iBox = boxes[i]; // // Upper ... if (box.upper == 0 || box.upper < iBox.upper) { box.upper = iBox.upper; } // // Lower ... if (box.lower == 0 || box.lower < iBox.lower) { box.lower = iBox.lower; } // // To ... if (!IsValid(box.to) || box.to < iBox.to) { box.to = iBox.to; } // // From ... if (!IsValid(box.from) || box.from > iBox.from) { box.from = iBox.from; } } } else { // // Use Price Inside OB as Box ... box.to = priceInsideOB.To(); box.from = priceInsideOB.From(); box.upper = priceInsideOB.Upper(); box.lower = priceInsideOB.Lower(); } } // result = box.IsValid(); // return result; } /** * Add Guard to Collection ... * * @param guard: X121SMCGuard instance ... * @param guards: X121SMCGuard instance Collection ... * * @return ( int ) */ int AddGuard( X121SMCGuard &guard, X121SMCGuard &guards[] // ) { // int result = 0; // if (!guard.IsValid()) { return result; } // AddRef( guard, guards // ); // result = ArraySize(guards); // return result; } // // // typedef void (*TOnX121SMCSignal)( XSignal &signal, X121SMCStrategyConditions &conditions // ); // // Extentions ... /** * Validate a Signal Provider ... * * @param value: ENUM_X_121_SMC_PROVIDERS member ... * * @return ( bool ) */ bool IsValid(ENUM_X_121_SMC_PROVIDERS value) { // bool result = false; // result = value != X_121_SMC_PROVIDER_NONE; // return result; } /** * Converts a Signal Provider to String ... * * @param value: ENUM_X_121_SMC_PROVIDERS member ... * * @return ( string ) */ string ToString(ENUM_X_121_SMC_PROVIDERS value) { // string result = NULL; // if (!IsValid(value)) { return result; } // switch (value) { // case X_121_SMC_PROVIDER_X: result = X121SMCXToken; break; // case X_121_SMC_PROVIDER_XHKPV: result = X121SMCXHKPVToken; break; // case X_121_SMC_PROVIDER_XOBPV: result = X121SMCXOBPVToken; break; } // return result; } /** * Parse Specified String as a Signal Provider ... * * @param value: String ... * * @return ( ENUM_X_121_SMC_PROVIDERS ) */ ENUM_X_121_SMC_PROVIDERS ParseProvider(string value) { // ENUM_X_121_SMC_PROVIDERS result = X_121_SMC_PROVIDER_NONE; // if (!IsValid(value)) { return result; } // if (Contains(X121SMCXToken, value)) { result = X_121_SMC_PROVIDER_X; } else if (Contains(X121SMCXHKPVToken, value)) { result = X_121_SMC_PROVIDER_XHKPV; } else if (Contains(X121SMCXOBPVToken, value)) { result = X_121_SMC_PROVIDER_XOBPV; } // return result; } //