/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Seriallize Library // --------------------------------------- // Name: XPOILib // Description: All models related to POIs ... // // // 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-saherelm.common.lib.mq5" // // Definitions ... // // Definitions ... // // All Available POI(s) ... enum ENUM_XPOIS { // // Trading Day ... X_POI_TRADING_DAY, // Trading Day ... // // Market Session ... X_POI_MARKET_SESSION, // Market Session ... // // Momentum Bar ... X_POI_MOMENTUM_BAR, // Momentum Bar ... // // Rejection Bar ... X_POI_REJECTION_BAR, // Rejection Bar ... // // Swings ... X_POI_SWING_HIGH, // Simple Swing High ... X_POI_SWING_LOW, // Simple Swing Low ... // // Support nad Resistance ... X_POI_SUPPORT_ZONE, // Support Zone ... X_POI_RESISTANCE_ZONE, // Resistance Zone ... // // Supply and Demand Zones ... X_POI_SUPPLY_ZONE, // Supply Zone ... X_POI_DEMAND_ZONE, // Demand Zone ... // // Order Blocks ... X_POI_BULLISH_ORDERBLOCK, // Bullish Order Block ... X_POI_BEARISH_ORDERBLOCK, // Bearish Order Block ... // // Fair Value Gaps ... X_POI_BULLISH_FVG, // Bullish Order Block ... X_POI_BEARISH_FVG, // Bearish Order Block ... }; // // Event Types ... enum ENUM_XPOI_EVENTS { // // Trading Days ... X_TRADE_DAY_FIRST_BAR, // Trading Day Start ... X_TRADE_DAY_LAST_BAR, // Trading Day End ... // // Session ... X_SESSION_FIRST_BAR, // Session First Bar ... X_SESSION_LAST_BAR, // Session Last Bar ... // // Momentum Bar ... X_MOMENTUM_BAR_DETECTED, // Momentum Bar ... // // Rejection Bar ... X_REJECTION_BAR_DETECTED, // Rejection Bar ... // // Swings ... X_SWING_HIGH_DETECTED, X_SWING_LOW_DETECTED, // // Support nad Resistance ... X_SUPPORT_ZONE_DETECTED, // Support Zone ... X_RESISTANCE_ZONE_DETECTED, // Resistance Zone ... // // Supply nad Demand ... X_SUPPLY_ZONE_DETECTED, // Supply Zone ... X_DEMAND_ZONE_DETECTED, // Demand Zone ... // // Order Blocks ... X_BULLISH_ORDERBLOCK_DETECTED, // Bullish Order Block ... X_BEARISH_ORDERBLOCK_DETECTED, // Bearish Order Block ... // // Fair Value Gaps ... X_BULLISH_FVG_DETECTED, // Bullish Fair Value Gapّ ... X_BEARISH_FVG_DETECTED, // Bearish Fair Value Gapّ ... }; // // Forext Sessions ... enum ENUM_XSESSION { X_TOKYO, X_SYDNEY, X_LONDON, X_NEW_YORK, X_FRANKFORT, }; enum ENUM_X_ZONE_EDGE { X_ZONE_UPPER_EDGE, X_ZONE_LOWER_EDGE }; // // Represent a Session Working Time ... struct XSession { // // Props ... ENUM_XSESSION session; // Session Identifier string start; // Start Time string end; // End Time // bool allowDraw; color startColor; ENUM_LINE_STYLE startStyle; color endColor; ENUM_LINE_STYLE endStyle; /** * Constructor ... */ void XSession() { Clean(); } /** * Clean Structure ... */ void Clean() { // start = NULL; end = NULL; // allowDraw = false; endColor = clrAqua; endStyle = STYLE_DOT; startColor = clrAqua; endStyle = STYLE_DOT; } /** * Validate Structure ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = IsValid(start) && IsValid(end); // return result; } /** * Initialize Specified Session ... * * @param _session: ENUM_XSESSION member ... * @param _start: String (Session Start Time) ... * @param _end: String (Session End Time) ... * * @return ( bool ) */ bool Init( ENUM_XSESSION _session, string _start, string _end // ) { // bool result = false; // result = IsValid(_start) && IsValid(_end); if (!result) { return result; } // end = _end; start = _start; session = _session; // result = IsValid(); // return result; } // }; // struct XTradeDay { // datetime from; datetime to; // void XTradeDay() { Clean(); } // void Clean() { // from = NULL; to = NULL; } // bool IsValid() { // bool result = false; // result = IsValid(from) && IsValid(to); // return result; } // string GetTag() { // string result = NULL; // if (!IsValid()) { return result; } // result = ToString(X_POI_TRADING_DAY) + "_" + ToFormatString(from) + "_" + ToFormatString(to); // return result; } // }; // // Detected Session ... struct XMarketSession { // ENUM_XSESSION session; datetime from; datetime to; // void XMarketSession() { Clean(); } // void Clean() { from = NULL; to = NULL; } // bool IsValid() { // bool result = false; // result = IsValid(from) && IsValid(to); // return result; } // string GetTag() { // string result = NULL; // if (!IsValid()) { return result; } // result = ToString(X_POI_MARKET_SESSION) + "_" + ToString(session) + "_" + ToFormatString(from) + "_" + ToFormatString(to) + "_"; // return result; } }; // // Zone Struct ... struct XZone { // // Props ... double upper; double lower; string prefix; // datetime from; datetime to; // // Constructor ... void XZone() { Clean(); } // bool Init( double _upper, double _lower, string _prefix, datetime _from, datetime _to // ) { // bool result = false; // result = _upper > 0 && _lower > 0 && _upper > _lower && IsValid(_prefix) && IsValid(_from); if (!result) { return result; } // NormalizeTime(_to); // upper = _upper; lower = _lower; prefix = _prefix; from = _from; to = _to; // result = IsValid(); // return result; } // void Clean() { // upper = 0; lower = 0; // to = NULL; from = NULL; prefix = NULL; } // bool IsValid() { // bool result = false; // result = upper > 0 && lower > 0 && upper > lower && IsValid(to) && IsValid(from) && IsValid(prefix); // return result; } // double GetRange() { // double result = 0; // if (!IsValid()) { return result; } // result = upper - lower; // return result; } // double GetMiddle() { // double result = 0; // double range = GetRange(); if (range <= 0) { return result; } // result = lower + (range / 2); // return result; } // string GetTag() { // string result = NULL; // result = prefix + "_" + ToString(upper) + "_" + ToString(lower); // return result; } }; // // XOHCL Event Handler ... typedef void (*TXOHCLEventHandler)( ENUM_XPOI_EVENTS event, XOHCL &bar // ); // // POI Event Handler ... typedef void (*TXPOIEventHandler)( ENUM_XPOI_EVENTS event // ); // // Session Event Handler ... typedef void (*TXSessionEventHandler)( ENUM_XSESSION session, ENUM_XPOI_EVENTS event // ); // // Zone Handler ... typedef void (*TXZoneEventHandler)( ENUM_XPOI_EVENTS event, XZone &zone // ); // // Model Exists Founded POIs ... struct XPOIState { // string symbol; ENUM_TIMEFRAMES period; datetime reportedAt; // XTradeDay tradingDays[]; XMarketSession marketSessions[]; // XOHCL momentumBars[]; XOHCL rejectionBars[]; // XOHCL swingHighs[]; XOHCL swingLows[]; // XOHCL supportZones[]; XOHCL resistanceZones[]; // XZone supplyZones[]; XZone demandZones[]; // XZone bullishOrderBlocks[]; XZone bearishOrderBlocks[]; // XZone bullishFVGs[]; XZone bearishFVGs[]; // // Constructor ... void XPOIState() { Clean(); } // // Actions ... /** * Cleanup all props ... */ void Clean() { // symbol = NULL; period = NULL; reportedAt = NULL; // Clean(tradingDays); Clean(marketSessions); // Clean(momentumBars); Clean(rejectionBars); // Clean(swingHighs); Clean(swingLows); // Clean(supportZones); Clean(resistanceZones); // Clean(supplyZones); Clean(demandZones); // Clean(bullishOrderBlocks); Clean(bearishOrderBlocks); // Clean(bullishFVGs); Clean(bearishFVGs); } /** * Fill Trading Days ... * * @param source: XTradeDay instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillTradingDays( XTradeDay &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(tradingDays); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, tradingDays // ); result = ArraySize(tradingDays); // return result; } /** * Fill Market Sessions ... * * @param source: XMarketSession instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillMarketSessions( XMarketSession &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(marketSessions); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, marketSessions // ); result = ArraySize(marketSessions); // return result; } /** * Fill Momentum Bars ... * * @param source: XOHCL instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillMomentumBars( XOHCL &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(momentumBars); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, momentumBars // ); result = ArraySize(momentumBars); // return result; } /** * Fill Retection Bars ... * * @param source: XOHCL instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillRejectionBars( XOHCL &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(rejectionBars); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, rejectionBars // ); result = ArraySize(rejectionBars); // return result; } /** * Fill Swing Highs ... * * @param source: XOHCL instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillSwingHighs( XOHCL &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(swingHighs); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, swingHighs // ); result = ArraySize(swingHighs); // return result; } /** * Fill Swing Lows ... * * @param source: XOHCL instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillSwingLows( XOHCL &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(swingLows); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, swingLows // ); result = ArraySize(swingLows); // return result; } /** * Fill Support Zones ... * * @param source: XOHCL instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillSupportZones( XOHCL &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(supportZones); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, supportZones // ); result = ArraySize(supportZones); // return result; } /** * Fill Resistance Zones ... * * @param source: XOHCL instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillResistanceZones( XOHCL &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(resistanceZones); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, resistanceZones // ); result = ArraySize(resistanceZones); // return result; } /** * Fill Supply Zones ... * * @param source: XZone instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillSupplyZones( XZone &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(supplyZones); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, supplyZones // ); result = ArraySize(supplyZones); // return result; } /** * Fill Demand Zones ... * * @param source: XZone instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillDemandZones( XZone &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(demandZones); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, demandZones // ); result = ArraySize(demandZones); // return result; } /** * Fill Bullish Order Blockss ... * * @param source: XZone instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillBullishOrderBlocks( XZone &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(bullishOrderBlocks); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, bullishOrderBlocks // ); result = ArraySize(bullishOrderBlocks); // return result; } /** * Fill Bearish Order Blockss ... * * @param source: XZone instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillBearishOrderBlocks( XZone &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(bearishOrderBlocks); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, bearishOrderBlocks // ); result = ArraySize(bearishOrderBlocks); // return result; } /** * Fill Bullish FVGs ... * * @param source: XZone instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillBullishFVGs( XZone &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(bullishFVGs); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, bullishFVGs // ); result = ArraySize(bullishFVGs); // return result; } /** * Fill Bearish FVGs ... * * @param source: XZone instance Collection ... * @param forceClean: Boolean ... * * @return ( int ) */ int FillBearishFVGs( XZone &source[], bool forceClean = true // ) { // int result = 0; // if (forceClean) { Clean(bearishFVGs); } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // Copy( source, bearishFVGs // ); result = ArraySize(bearishFVGs); // return result; } // }; // // Extensions ... /** * Converts ENUM_XPOI value to String Representation ... * * @param value: ENUM_XPOI member ... * * @return ( string ) */ string ToString(ENUM_XPOIS value) { // string result = NULL; // switch (value) { // case X_POI_TRADING_DAY: result = "XTDAY"; break; // case X_POI_MARKET_SESSION: result = "XMSESS"; break; // case X_POI_MOMENTUM_BAR: result = "XMNTMB"; break; // case X_POI_REJECTION_BAR: result = "XRJCTB"; break; // case X_POI_SWING_HIGH: result = "XSPH"; break; // case X_POI_SWING_LOW: result = "XSPL"; break; // case X_POI_SUPPORT_ZONE: result = "XSUP"; break; // case X_POI_RESISTANCE_ZONE: result = "XRES"; break; // case X_POI_SUPPLY_ZONE: result = "XSUPPLY"; break; // case X_POI_DEMAND_ZONE: result = "XDEMAND"; break; // case X_POI_BULLISH_ORDERBLOCK: result = "XBULLOB"; break; // case X_POI_BEARISH_ORDERBLOCK: result = "XBEAROB"; break; // case X_POI_BULLISH_FVG: result = "XBULLFVG"; break; // case X_POI_BEARISH_FVG: result = "XBEARFVG"; break; } // return result; } /** * Converts ENUM_XSESSION value to String Representation ... * * @param value: ENUM_XSESSION member ... * * @return ( string ) */ string ToString(ENUM_XSESSION value) { // string result = NULL; // switch (value) { // case X_SYDNEY: result = "Sydney"; break; // case X_TOKYO: result = "Tokyo"; break; // case X_FRANKFORT: result = "FrankGurt"; break; // case X_LONDON: result = "London"; break; // case X_NEW_YORK: result = "NewYork"; break; } // return result; } /** * Generate General Event Messages ... * * @param value: ENUM_XPOI_EVENTS member ... * * @return ( string ) */ string ToString(ENUM_XPOI_EVENTS value) { // string result = NULL; // switch (value) { // case X_TRADE_DAY_FIRST_BAR: result = "First Bar of Day"; break; // case X_TRADE_DAY_LAST_BAR: result = "Last Bar of Day"; break; // case X_SESSION_FIRST_BAR: result = "First Bar of Session"; break; // case X_SESSION_LAST_BAR: result = "Last Bar of Session"; break; // case X_MOMENTUM_BAR_DETECTED: result = "Momentum Bar Detected"; break; // case X_REJECTION_BAR_DETECTED: result = "Rejection Bar Detected"; break; // case X_SWING_HIGH_DETECTED: result = "Swing High Detected"; break; // case X_SWING_LOW_DETECTED: result = "Swing Low Detected"; break; // case X_SUPPORT_ZONE_DETECTED: result = "Support Zone Detected"; break; // case X_RESISTANCE_ZONE_DETECTED: result = "Resistance Zone Detected"; break; // case X_SUPPLY_ZONE_DETECTED: result = "Supply Zone Detected"; break; // case X_DEMAND_ZONE_DETECTED: result = "Demand Zone Detected"; break; // case X_BULLISH_ORDERBLOCK_DETECTED: result = "Bullish Order Block Detected"; break; // case X_BEARISH_ORDERBLOCK_DETECTED: result = "Bearish Orer Block Detected"; break; // case X_BULLISH_FVG_DETECTED: result = "Bullish FVG Detected"; break; // case X_BEARISH_FVG_DETECTED: result = "Bearish FVg Detected"; break; } // return result; } // // XOHCL Extensions ... /** * Check two Bar is Same or not ... * * @param source: XOHCL instance ... * @param dest: XOHCL instance ... * @param force: Check also it's Dates ... * * @return ( bool ) */ bool IsSame( XOHCL &source, XOHCL &dest // ) { // bool result = false; // result = source.IsValid() && dest.IsValid(); if (!result) { return result; } // result = source.open == dest.open && source.close == dest.close && source.high == dest.high && source.low == dest.low; if (!result) { return result; } // return result; } /** * Find Specific Items Index inside a Collection ... * * @param source: XOHCL instance ... * @param dest: XOHCL instance Collection ... * * @return ( int ) */ int FindIndex( XOHCL &source, XOHCL &dest[] // ) { // int result = -1; // if (!source.IsValid()) { return result; } // int count = ArraySize(dest); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // XOHCL iBar = dest[i]; // bool isSame = IsSame( source, iBar // ); if (isSame) { // result = i; break; } } // return result; } /** * Add Specific Bar to List only if Not Exists ... * * @param source: XOHCL instance ... * @param dest: XOHCL instance Collection ... * * @return ( bool ) */ bool AddIfNotExists( XOHCL &source, XOHCL &dest[] // ) { // bool result = false; // result = source.IsValid(); if (!result) { return result; } // int idx = FindIndex(source, dest); bool isExists = IsValidIndex(idx); if (!isExists) { // AddRef( source, dest // ); // result = isExists; } // return result; } // // XZone Extensions ... /** * Check two Zone is Same or not ... * * @param source: XZone instance ... * @param dest: XZone instance ... * @param force: Check also it's Dates ... * * @return ( bool ) */ bool IsSame( XZone &source, XZone &dest, bool force = false // ) { // bool result = false; // result = source.IsValid() && dest.IsValid(); if (!result) { return result; } // result = source.upper == dest.upper && source.lower == dest.lower; if (!result) { return result; } // if (force) { // result = source.from == dest.from && source.to == dest.to; } // return result; } /** * Find Specific Items Index inside a Collection ... * * @param source: XZone instance ... * @param dest: XZone instance Collection ... * * @return ( int ) */ int FindIndex( XZone &source, XZone &dest[] // ) { // int result = -1; // if (!source.IsValid()) { return result; } // int count = ArraySize(dest); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // XZone iZone = dest[i]; // bool isSame = IsSame( source, iZone // ); if (isSame) { // result = i; break; } } // return result; } /** * Add Specific Zone to List only if Not Exists ... * * @param source: XZone instance ... * @param dest: XZone instance Collection ... * * @return ( bool ) */ bool AddIfNotExists( XZone &source, XZone &dest[] // ) { // bool result = false; // result = source.IsValid(); if (!result) { return result; } // int idx = FindIndex(source, dest); bool isExists = IsValidIndex(idx); if (!isExists) { // AddRef( source, dest // ); // result = isExists; } // return result; } // /** * Check if a Zone inside another one ... * * @param source: XZone instance ... * @param dest: XZone instance ... * @param edge: ENUM_X_ZONE_EDGE member, define inside edge of zone ... * @param forceInside: Boolean, if set true means all edges of source must be inside dest ... * * @return ( bool ) */ bool IsInside( XZone &source, XZone &dest, ENUM_X_ZONE_EDGE edge, bool forceInside = true // ) { // bool result = false; // result = source.IsValid() && dest.IsValid(); if (!result) { return result; } // bool isEdgePassed = // edge == X_ZONE_UPPER_EDGE ? source.upper <= dest.upper : source.lower >= dest.lower // ; // bool isForcePassed = // forceInside ? edge == X_ZONE_UPPER_EDGE ? source.lower >= dest.lower : source.upper <= dest.upper : edge == X_ZONE_UPPER_EDGE ? true : true // ; // result = isEdgePassed && isForcePassed; // return result; } bool IsInside( XOHCL &source, XZone &dest, ENUM_X_ZONE_EDGE edge, bool forceInside = true // ) { // bool result = false; // result = source.IsValid() && dest.IsValid(); if (!result) { return result; } // XZone iSource; double upper = edge == X_ZONE_UPPER_EDGE ? source.high : source.GetUp(); double lower = edge == X_ZONE_UPPER_EDGE ? source.GetDown() : source.low; result = iSource.Init( upper, lower, "XOHCL", source.time, TimeCurrent() // ); if (!result) { return result; } // result = IsInside( iSource, dest, edge, forceInside // ); // return result; } /** * Check a Zone is Between to other Zones ... * * @param source: XZone instance ... * @param upper: XZone instance ... * @param lower: XZone instance ... * * @return ( bool ) */ bool IsBetween( XZone &source, XZone &upper, XZone &lower // ) { // bool result = false; // result = source.IsValid(); if (!result) { return result; } // bool isUpperValid = upper.IsValid(); bool isLowerValid = lower.IsValid(); // result = isUpperValid || isLowerValid; if (!result) { return result; } // if (isUpperValid) { // result = source.upper < upper.lower; if (!result) { return result; } } // if (isLowerValid) { // result = source.lower > lower.upper; if (!result) { return result; } } // return result; } bool IsBetween( XOHCL &source, XZone &upper, XZone &lower // ) { // bool result = false; // result = source.IsValid(); if (!result) { return result; } // bool isUpperValid = upper.IsValid(); bool isLowerValid = lower.IsValid(); // result = isUpperValid || isLowerValid; if (!result) { return result; } // if (isUpperValid) { // result = source.high < upper.lower; if (!result) { return result; } } // if (isLowerValid) { // result = source.low > lower.upper; if (!result) { return result; } } // return result; } /** * Check Source breaked Dest from Upper ... * * @param source: XZone instance ... * @param dest: XZone instance ... * * @return ( bool ) */ bool IsBreakeUpper( XZone &source, XZone &dest // ) { // bool result = false; // result = source.IsValid() && dest.IsValid(); if (!result) { return result; } // result = // // Check Boundary ... source.lower <= dest.upper && source.lower >= dest.lower && // // Check Break ... source.upper > dest.upper // ; // return result; } /** * Check Source breaked Dest from Lower ... * * @param source: XZone instance ... * @param dest: XZone instance ... * * @return ( bool ) */ bool IsBreakeLower( XZone &source, XZone &dest // ) { // bool result = false; // result = source.IsValid() && dest.IsValid(); if (!result) { return result; } // result = // // Check Boundary ... source.upper <= dest.upper && source.upper >= dest.lower && // // Check Break ... source.lower < dest.lower // ; // return result; } // // State Extensions ... /** * Normalize and Combine States ... * * @param dest: XPOIState instance ...ّ * @param states: XPOIState instance ...ّ */ void CombineStates( XPOIState &dest, XPOIState &states[] // ) { // dest.Clean(); // int count = ArraySize(states); if (!IsValidSize(count)) { return; } // for (int i = 0; i < count; i++) { // XPOIState iState = states[i]; // dest.symbol = iState.symbol; dest.period = !IsValid(dest.period) || PeriodSeconds(dest.period) < PeriodSeconds(iState.period) ? iState.period : dest.period; dest.reportedAt = !IsValid(dest.reportedAt) || dest.reportedAt > iState.reportedAt ? iState.reportedAt : dest.reportedAt; // // Demand ... int iCount = ArraySize(iState.demandZones); if (IsValidSize(iCount)) { // Copy( iState.demandZones, dest.demandZones, false // ); } // // Supply ... iCount = ArraySize(iState.supplyZones); if (IsValidSize(iCount)) { // Copy( iState.supplyZones, dest.supplyZones, false // ); } // // Order Blocks ... // iCount = ArraySize(iState.bullishOrderBlocks); if (IsValidSize(iCount)) { // Copy( iState.bullishOrderBlocks, dest.bullishOrderBlocks, false // ); } // iCount = ArraySize(iState.bearishOrderBlocks); if (IsValidSize(iCount)) { // Copy( iState.bearishOrderBlocks, dest.bearishOrderBlocks, false // ); } // // Fair Value Gaps ... // iCount = ArraySize(iState.bullishFVGs); if (IsValidSize(iCount)) { // Copy( iState.bullishFVGs, dest.bullishFVGs, false // ); } // iCount = ArraySize(iState.bearishFVGs); if (IsValidSize(iCount)) { // Copy( iState.bearishFVGs, dest.bearishFVGs, false // ); } // // Supports ... iCount = ArraySize(iState.supportZones); if (IsValidSize(iCount)) { // Copy( iState.supportZones, dest.supportZones, false // ); } // // Resistances ... iCount = ArraySize(iState.resistanceZones); if (IsValidSize(iCount)) { // Copy( iState.resistanceZones, dest.resistanceZones, false // ); } // // Swings ... // // Swing Highs ... iCount = ArraySize(iState.swingHighs); if (IsValidSize(iCount)) { // Copy( iState.swingHighs, dest.swingHighs, false // ); } // // Swing Lows ... iCount = ArraySize(iState.swingLows); if (IsValidSize(iCount)) { // Copy( iState.swingLows, dest.swingLows, false // ); } // // Momentum Bars ... iCount = ArraySize(iState.momentumBars); if (IsValidSize(iCount)) { // Copy( iState.momentumBars, dest.momentumBars, false // ); } // // Rejection Bars ... iCount = ArraySize(iState.rejectionBars); if (IsValidSize(iCount)) { // Copy( iState.rejectionBars, dest.rejectionBars, false // ); } } } /** * Check State has Bullish Trend or not ... * * @param state: XPOIState instance ... * * @return ( bool ) */ bool HasBullishTrend(XPOIState &state) { // bool result = false; // // For Bullish Trends ... int count = ArraySize(state.swingLows); result = count >= 2; if (!result) { return result; } // XOHCL lastSwing = state.swingLows[count - 1]; XOHCL prevSwing = state.swingLows[count - 2]; // result = lastSwing.low > prevSwing.low; // return result; } /** * Check State has Bearish Trend or not ... * * @param state: XPOIState instance ... * * @return ( bool ) */ bool HasBearishTrend(XPOIState &state) { // bool result = false; // // For Bullish Trends ... int count = ArraySize(state.swingHighs); result = count >= 2; if (!result) { return result; } // XOHCL lastSwing = state.swingHighs[count - 1]; XOHCL prevSwing = state.swingHighs[count - 2]; // result = lastSwing.high < prevSwing.high; // return result; } //