/////////////////////////////////////////////////////// // // 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 `023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Imports ... #include "../Classes/x-saherelm.base.class.mq5" #include // // Definitions ... // // Definitions ... // // All Available POI(s) ... enum ENUM_XPOIS { // X_POI_NONE, // X_POI_TICKS_ZONES, // Ticks Zone ... // // 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 First Bar ... X_TRADE_DAY_LAST_BAR, // Trading Day Last Bar ... // // Session ... X_SESSION_FIRST_BAR, // Session First Bar ... X_SESSION_LAST_BAR, // Session Last Bar ... // // Momentum Bar ... X_BULLISH_MOMENTUM_BAR_DETECTED, X_BEARISH_MOMENTUM_BAR_DETECTED, // // Rejection Bar ... X_BULLISH_REJECTION_BAR_DETECTED, X_BEARISH_REJECTION_BAR_DETECTED, // // 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, }; // // Implementation ... // // Base POI Model Class ... class XCBasePOI : public XCBase { // public: // // // Constructor ... void XCBasePOI() { // Clean(); // mSep = "_"; mLineSep = "\n"; } // // Deconstructor ... void ~XCBasePOI() { Clean(); } // // Virtual ... /** * Cleanup ... */ virtual void Clean() { mType = X_POI_NONE; } /** * Validate ... * * @return ( virtual bool ) */ virtual bool IsValid() { return false; } /** * Retrieve POI Type ... * * @return ( virtual ENUM_XPOIS member ) */ virtual ENUM_XPOIS Type() { return mType; } /** * Retrieve POI Type ... * * @return ( virtual string ) */ virtual string TypeAsString() { return ToString(mType); } /** * Retrieve POI Tag ... * * @return ( virtual string ) */ virtual string GetTag() { return NULL; } /** * Retrieve POI Tooltip ... * * @return ( virtual string ) */ virtual string GetTooltip() { return NULL; } // protected: // // Props ... string mSep; // Separator ... string mLineSep; // Line Separator ... ENUM_XPOIS mType; // Type ... // private: // }; // // Zone POI Class ... class XCZone : public XCBasePOI { // public: // // // Constructor ... void XCZone() { } // // Deconstructor ... void ~XCZone() { } // // Tools ... // // Getter(s) / Setter(s) ... /** * Get Zone Upper Boundary ... * * @return ( double ) */ double Upper() { return mUpper; } /** * Set Zone Upper Boundary ... */ void Upper(double value) { mUpper = value; } /** * Get Zone Lower Boundary ... * * @return ( double ) */ double Lower() { return mLower; } /** * Set Zone Lower Boundary ... */ void Lower(double value) { mLower = value; } /** * Retrieve Zone Range ... * * @return ( double ) */ double Range() { // double result = 0; // double upper = Upper(); double lower = Lower(); // if (upper > 0 && lower > 0 && upper > lower) { result = upper - lower; } // return result; } double RangePercent() { // double result = 0; // double range = Range(); if (range > 0) { result = range / 100; } // return result; } // // Virtuals ... /** * Get Zone Start Date ... * * @return ( virtual datetime ) */ virtual datetime From() { return NULL; } /** * Get Zone End Date ... * * @return ( virtual datetime ) */ virtual datetime To() { return NULL; } // // Getter(s) / Setter(s) ... // // Overrides ... // // Validators ... /** * Validate Upper and Lower of Zone ... * * @return ( bool ) */ bool IsValidBoundary() { // bool result = false; // result = // mUpper > 0 && mLower > 0 && mUpper >= mLower // ; // return result; } /** * Check From Date of Zone is Valid ... * * @return ( bool ) */ bool IsValidFrom() { // bool result = false; // datetime from = From(); result = IsSpecifiedValid(from); // return result; } // protected: // // Props ... double mUpper; // Zone Upper ... double mLower; // Zone Lower ... // private: // // Props ... // }; // // From To Zone ... class XCFromToZone : public XCBasePOI { // public: // // // Constructor ... void XCFromToZone() { } // // Deconstructor ... void ~XCFromToZone() { } // // Tools ... bool InitFromTo( ENUM_XPOIS type, string title, datetime from // ) { // bool result = false; // result = type != X_POI_NONE && IsSpecifiedValid(from) && IsSpecifiedValid(title); // mType = type; mFrom = from; mTitle = title; mTo = TimeCurrent(); // result = IsValid(); // return result; } bool InitFromTo( ENUM_XPOIS type, string title, datetime from, datetime to // ) { // bool result = false; // result = IsValid(); // result = InitFromTo( type, title, from // ); if (!result) { return result; } // to = NormalizeTime(to); mTo = to; // result = IsValid(); // return result; } // // Getter(s) / Setter(s) ... /** * Get Zone Start Time ... * * @return ( datetime ) */ datetime From() { return mFrom; } /** * Set Zone Start Time ... * * @param value: Datetime */ void From(datetime value) { // value = NormalizeTime(value); // mFrom = value; } /** * Get Zone End Time ... * * @return ( datetime ) */ datetime To() { return mTo; } /** * Set Zone End Time ... * * @param value: Datetime */ void To(datetime value) { // value = NormalizeTime(value); // mTo = value; } /** * Get Title ... * * @return ( string ) */ string Title() { return mTitle; } /** * Set Title ... * * @param value: String ... */ // void Title(string value) // { // mTitle = value; // } // // Overrides ... void Clean() override { // mTo = NULL; mFrom = NULL; mType = X_POI_NONE; } bool IsValid() override { // bool result = false; // result = // mType != X_POI_NONE && IsSpecifiedValid(mTo) && IsSpecifiedValid(mFrom) && IsSpecifiedValid(mTitle) // ; // return result; } string GetTag() override { // string result = NULL; // if (!IsValid()) { return result; } // string hash = TypeAsString() + mSep + ToString(From()) + mSep + Title(); hash = ToMD5(hash); // result = TypeAsString() + "[" + Title() + "]" + mSep + hash; // return result; } // protected: // // private: // // Props ... datetime mFrom; // Start Date datetime mTo; // End Date string mTitle; // Zone Title // }; // // Bar Zone ... class XCBarZone : public XCZone { // public: // // // Constructor ... void XCBarZone() { } // // Deconstructor ... void ~XCBarZone() { } // // Tools ... /** * Initialize POI ... * * @param bar: XOHCL instance ... * @param type: ENUM_XPOIS member ... * @param upperPrice: ENUM_X_PRICE member ... * @param lowerPrice: ENUM_X_PRICE member ... * * @return ( bool ) */ bool InitBarZone( XOHCL &bar, ENUM_XPOIS type, ENUM_X_PRICE upperPrice, ENUM_X_PRICE lowerPrice // ) { // bool result = false; // result = bar.IsValid() && type != X_POI_NONE && upperPrice != lowerPrice; if (!result) { return result; } // mBar = bar; mType = type; mUpperPrice = upperPrice; mLowerPrice = lowerPrice; mUpper = bar.GetPrice(upperPrice); mLower = bar.GetPrice(lowerPrice); // result = IsValidBarZone(); if (result) { // From(bar.time); To(TimeCurrent()); } // return result; } // // Getter(s) / Setter(s) ... /** * Fill Bar as XOHCL struct ... * * @param bar: XOHCL instance ... * * @return ( bool ) */ bool FillBar( XOHCL &bar // ) { // bool result = false; // result = IsValid(); if (!result) { return result; } // bar = mBar; result = mBar.IsValid(); // return result; } /** * Set From Date ... * * @param value: DateTime ... */ void From(datetime value) { // if (!IsValidBarZone()) { return; } // value = NormalizeTime(value); // mFrom = value; } /** * Set To Date ... * * @param value: DateTime ... */ void To(datetime value) { // if (!IsValidBarZone()) { return; } // value = NormalizeTime(value); // mTo = value; } /** * Retrieve Bar Time ... * * @return ( datetime ) */ datetime BarTime() { return mBar.time; } /** * Get Symbol ... * * @return ( string ) */ string GetSymbol() { // string result = NULL; // if (!mBar.IsValid()) { return result; } // return mBar.symbol; // return result; } /** * Get Period ... * * @return ( int ) */ ENUM_TIMEFRAMES GetPeriod() { // ENUM_TIMEFRAMES result = NULL; // if (!mBar.IsValid()) { return result; } // return mBar.period; // return result; } // // Overrides ... void Clean() override { // mBar.Clean(); mUpper = 0; mLower = 0; mType = X_POI_NONE; } datetime From() override { return mFrom; } datetime To() override { return mTo; } string GetTag() override { // string result = NULL; // if (!IsValidBarZone()) { return result; } // string hash = ToMD5(mBar.GetTag()); // result = // TypeAsString() + mSep + ToString(mBar.period) + mSep + hash // ; // return result; } string GetTooltip() override { // string result = NULL; // if (!IsValidBarZone()) { return result; } // return result; } // protected: // // Props ... XOHCL mBar; // Bar ... ENUM_X_PRICE mUpperPrice; // Upper Price Selection ENUM_X_PRICE mLowerPrice; // Lower Price Selection /** * Check Bar Zone Validation ... * * @return ( bool ) */ bool IsValidBarZone() { // bool result = false; // result = mBar.IsValid() && mType != X_POI_NONE && IsValidBoundary(); // return result; } // private: // // Props ... datetime mFrom; datetime mTo; // }; class XCTwoBarZone : public XCZone { // public: // // // Constructor ... void XCTwoBarZone() { } // // Deconstructor ... void ~XCTwoBarZone() { } // // Tools ... /** * Initialize POI ... * * @param bar: XOHCL instance ... * @param type: ENUM_XPOIS member ... * @param upperPrice: ENUM_X_PRICE member ... * @param lowerPrice: ENUM_X_PRICE member ... * * @return ( bool ) */ bool InitTwoBarZone( XOHCL &startBar, XOHCL &endBar, ENUM_XPOIS type, bool useStartBarForUpper, ENUM_X_PRICE upperPrice, ENUM_X_PRICE lowerPrice // ) { // bool result = false; // result = startBar.IsValid() && endBar.IsValid() && startBar.symbol == endBar.symbol && startBar.period == endBar.period && startBar.time < endBar.time && type != X_POI_NONE; if (!result) { return result; } // mType = type; mEndBar = endBar; mStartBar = startBar; mUpperPrice = upperPrice; mLowerPrice = lowerPrice; mUseStartBarForUpper = useStartBarForUpper; mUpper = useStartBarForUpper ? startBar.GetPrice(upperPrice) : endBar.GetPrice(upperPrice); mLower = useStartBarForUpper ? endBar.GetPrice(lowerPrice) : startBar.GetPrice(lowerPrice); // result = IsValidTwoBarZone(); if (result) { // From(startBar.time); To(endBar.time); } // return result; } // // Getter(s) / Setter(s) ... /** * Set From Date ... * * @param value: DateTime ... */ void From(datetime value) { // if (!IsValidTwoBarZone()) { return; } // value = NormalizeTime(value); // mFrom = value; } /** * Set To Date ... * * @param value: DateTime ... */ void To(datetime value) { // if (!IsValidTwoBarZone()) { return; } // value = NormalizeTime(value); // mTo = value; } /** * Fill Start Bar ... * * @param bar: XOHCL instance ... * * @return ( bool ) */ bool FillStartBar(XOHCL &bar) { // bool result = false; // result = IsValidTwoBarZone(); if (!result) { return result; } // bar = mStartBar; // return result; } /** * Fill End Bar ... * * @param bar: XOHCL instance ... * * @return ( bool ) */ bool FillEndBar(XOHCL &bar) { // bool result = false; // result = IsValidTwoBarZone(); if (!result) { return result; } // bar = mEndBar; // return result; } /** * Get Symbol ... * * @return ( string ) */ string GetSymbol() { // string result = NULL; // if (!mStartBar.IsValid()) { return result; } // return mStartBar.symbol; // return result; } /** * Get Period ... * * @return ( int ) */ ENUM_TIMEFRAMES GetPeriod() { // ENUM_TIMEFRAMES result = NULL; // if (!mStartBar.IsValid()) { return result; } // return mStartBar.period; // return result; } // // Overrides ... void Clean() override { // mStartBar.Clean(); mEndBar.Clean(); mUpper = 0; mLower = 0; mUseStartBarForUpper = false; mType = X_POI_NONE; } datetime From() override { return mFrom; } datetime To() override { return mTo; } string GetTag() override { // string result = NULL; // if (!IsValidTwoBarZone()) { return result; } // string hash = ToMD5(mStartBar.GetTag() + mSep + mEndBar.GetTag()); // result = // TypeAsString() + mSep + ToString(mStartBar.period) + mSep + hash // ; // return result; } string GetTooltip() override { // string result = NULL; // if (!IsValidTwoBarZone()) { return result; } // return result; } // protected: // // Props ... XOHCL mStartBar; // Start (Oldest) Bar ... XOHCL mEndBar; // End (Newest) Bar ... bool mUseStartBarForUpper; // Use Start Bar for Upper Calculation ... ENUM_X_PRICE mUpperPrice; // Upper Price Selection ENUM_X_PRICE mLowerPrice; // Lower Price Selection /** * Check Two Bar Zone Validation ... * * @return ( bool ) */ bool IsValidTwoBarZone() { // bool result = false; // result = mStartBar.IsValid() && mEndBar.IsValid() && mStartBar.symbol == mEndBar.symbol && mStartBar.period == mEndBar.period && mStartBar.time < mEndBar.time && mType != X_POI_NONE && IsValidBoundary(); // return result; } // private: // // Props ... datetime mFrom; datetime mTo; // }; // // Swing Class ... class XCSwing : public XCBasePOI { // public: // // // Constructor ... void XCSwing() { } // // Deconstructor ... void ~XCSwing() { } // // Tools ... /** * Initialize POI ... * * @param bar: XOHCL instance ... * @param type: ENUM_XPOIS member ... * * @return ( bool ) */ bool Init( XOHCL &bar, ENUM_XPOIS type // ) { // bool result = false; // result = bar.IsValid() && (type == X_POI_SWING_HIGH || type == X_POI_SWING_LOW); if (!result) { return result; } // mBar = bar; mType = type; // result = IsValid(); // return result; } // // Getter(s) / Setter(s) ... /** * Fill Bar as XOHCL struct ... * * @param bar: XOHCL instance ... * * @return ( bool ) */ bool FillBar( XOHCL &bar // ) { // bool result = false; // result = IsValid(); if (!result) { return result; } // bar = mBar; result = mBar.IsValid(); // return result; } /** * Get Time of Swing ... * * @return ( datetime ) */ datetime GetTime() { // datetime result = NULL; // if (!IsValid() || !mBar.IsValid()) { return result; } // result = mBar.time; // return result; } ENUM_TIMEFRAMES GetPeriod() { // ENUM_TIMEFRAMES result = NULL; // XOHCL bar; bool isFilled = FillBar(bar); if (!isFilled) { return result; } // result = bar.period; // return result; } /** * Check Swing High or not ... * * @return ( bool ) */ bool IsSwingHigh() { // bool result = false; // result = IsValid(); if (!result) { return result; } // result = Type() == X_POI_SWING_HIGH; // return result; } /** * Check Swing Low or not ... * * @return ( bool ) */ bool IsSwingLow() { // bool result = false; // result = IsValid(); if (!result) { return result; } // result = Type() == X_POI_SWING_LOW; // return result; } /** * Get Swing Value ... * * @return ( double ) */ double GetValue() { // double result = 0; // if (!IsValid()) { return result; } // result = IsSwingHigh() ? mBar.high : mBar.low; // return result; } // // Overrides ... void Clean() override { // mBar.Clean(); mType = X_POI_NONE; } bool IsValid() override { // bool result = false; // result = mBar.IsValid() && (mType == X_POI_SWING_HIGH || mType == X_POI_SWING_LOW); // return result; } string GetTag() override { // string result = NULL; // if (!IsValid()) { return result; } // string hash = ToMD5(mBar.GetTag()); // string subType = IsSwingHigh() ? "High" : "Low"; // result = // TypeAsString() + mSep + subType + mSep + ToString(mBar.period) + mSep + hash // ; // return result; } string GetTooltip() override { // string result = NULL; // if (!IsValid()) { return result; } // return result; } // protected: // // Props ... XOHCL mBar; // Swing Bar ... // private: // }; // // Supply Zone ... class XCSupplyZone : public XCBarZone { // public: // // // Constructor ... void XCSupplyZone() { } // // Deconstructor ... void ~XCSupplyZone() { } // // Tools ... /** * Initialize POI ... * * @param bar: XOHCL instance ... * @param range: Integer, Detection Range ... * * @return ( bool ) */ bool Init( XOHCL &bar, int range = 0 // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // result = InitBarZone( bar, X_POI_SUPPLY_ZONE, X_PRICE_HIGH, X_PRICE_LOW // ); if (!result) { return result; } // result = IsValid(); if (result && range > 0) { // datetime time = bar.time; int periodSeconds = PeriodSeconds(bar.period); // datetime from = (datetime)((int)time - (range * periodSeconds)); datetime to = (datetime)((int)time + (range * periodSeconds)); // From(from); To(to); } // return result; } // // Getter(s) / Setter(s) ... // // Overrides ... bool IsValid() override { // bool result = false; // result = IsValidBarZone() && mType == X_POI_SUPPLY_ZONE; // return result; } // protected: // // private: // // }; // // Demand Zone ... class XCDemandZone : public XCBarZone { // public: // // // Constructor ... void XCDemandZone() { } // // Deconstructor ... void ~XCDemandZone() { } // // Tools ... /** * Initialize POI ... * * @param bar: XOHCL instance ... * @param range: Integer, Detection Range ... * * @return ( bool ) */ bool Init( XOHCL &bar, int range = 0 // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // result = InitBarZone( bar, X_POI_DEMAND_ZONE, X_PRICE_HIGH, X_PRICE_LOW // ); if (!result) { return result; } // result = IsValid(); if (result && range > 0) { // datetime time = bar.time; int periodSeconds = PeriodSeconds(bar.period); // datetime from = (datetime)((int)time - (range * periodSeconds)); datetime to = (datetime)((int)time + (range * periodSeconds)); // From(from); To(to); } // return result; } // // Getter(s) / Setter(s) ... // // Overrides ... bool IsValid() override { // bool result = false; // result = IsValidBarZone() && mType == X_POI_DEMAND_ZONE; // return result; } // protected: // // private: // // }; // // Support Zone ... class XCSupportZone : public XCBarZone { // public: // // // Constructor ... void XCSupportZone() { } // // Deconstructor ... void ~XCSupportZone() { } // // Tools ... /** * Initialize POI ... * * @param bar: XOHCL instance ... * @param range: Integer, Detection Range ... * * @return ( bool ) */ bool Init( XOHCL &bar, int range = 0 // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // result = InitBarZone( bar, X_POI_SUPPORT_ZONE, X_PRICE_DOWN, X_PRICE_LOW // ); if (!result) { return result; } // result = IsValid(); if (result && range > 0) { // datetime time = bar.time; int periodSeconds = PeriodSeconds(bar.period); // datetime from = (datetime)((int)time - (range * periodSeconds)); datetime to = (datetime)((int)time + (range * periodSeconds)); // From(from); To(to); } // return result; } // // Getter(s) / Setter(s) ... // // Overrides ... bool IsValid() override { // bool result = false; // result = IsValidBarZone() && mType == X_POI_SUPPORT_ZONE; // return result; } // protected: // // private: // // }; // // Resistance Zone ... class XCResistanceZone : public XCBarZone { // public: // // // Constructor ... void XCResistanceZone() { } // // Deconstructor ... void ~XCResistanceZone() { } // // Tools ... /** * Initialize POI ... * * @param bar: XOHCL instance ... * @param range: Integer, Detection Range ... * * @return ( bool ) */ bool Init( XOHCL &bar, int range = 0 // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // result = InitBarZone( bar, X_POI_RESISTANCE_ZONE, X_PRICE_HIGH, X_PRICE_UP // ); if (!result) { return result; } // result = IsValid(); if (result && range > 0) { // datetime time = bar.time; int periodSeconds = PeriodSeconds(bar.period); // datetime from = (datetime)((int)time - (range * periodSeconds)); datetime to = (datetime)((int)time + (range * periodSeconds)); // From(from); To(to); } // return result; } // // Getter(s) / Setter(s) ... // // Overrides ... bool IsValid() override { // bool result = false; // result = IsValidBarZone() && mType == X_POI_RESISTANCE_ZONE; // return result; } // protected: // // private: // // }; // // Order Block ... class XCOrderBlock : public XCBarZone { // public: // // // Constructor ... void XCOrderBlock() { } // // Deconstructor ... void ~XCOrderBlock() { } // // Tools ... /** * Initialize POI ... * * @param bar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * * @return ( bool ) */ bool Init( XOHCL &bar, ENUM_X_DIRECTION dir // ) { // bool result = false; // result = bar.IsValid() && (dir == X_DIRECTION_BULLISH || dir == X_DIRECTION_BEARISH); if (!result) { return result; } // ENUM_XPOIS mTT = IsSpecifiedBullish(dir) ? X_POI_BULLISH_ORDERBLOCK : X_POI_BEARISH_ORDERBLOCK; // result = InitBarZone( bar, mTT, X_PRICE_HIGH, X_PRICE_LOW // ); if (!result) { return result; } // result = IsValid(); // return result; } // // Getter(s) / Setter(s) ... /** * Check is Bullish ... * * @return ( bool ) */ bool IsBullish() { // bool result = false; // result = IsValid() && Type() == X_POI_BULLISH_ORDERBLOCK; // return result; } /** * Check is Bearish ... * * @return ( bool ) */ bool IsBearish() { // bool result = false; // result = IsValid() && Type() == X_POI_BEARISH_ORDERBLOCK; // return result; } /** * Detect Order Blocks Breaker Bar ... * * @param breakerBar: XOHCL instance Reference ... * * @return ( bool ) */ bool DetectBreakerBar(XOHCL &breakerBar) { // bool result = false; // breakerBar.Clean(); // result = IsValid(); if (!result) { return result; } // XOHCL fromBar; result = FillBar(fromBar); if (!result) { return result; } // int fromIndex = fromBar.Index(); result = fromIndex > 0; if (!result) { return result; } // bool isBullish = IsBullish(); ENUM_X_DIRECTION dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; double value = isBullish ? Upper() : Lower(); // for (int i = fromIndex - 1; i >= 0; i--) { // XOHCL iBar; bool isInited = iBar.Init( fromBar.symbol, fromBar.period, i // ); if (!isInited) { continue; } // isInited = IsBarBreak( value, dir, iBar // ); if (isInited) { // breakerBar = iBar; break; } } // result = breakerBar.IsValid(); // return result; } /** * Check Order Block is Hunted or not ... * * @param huntedBar: XOHCL instance Reference ... * * @return ( bool ) */ bool IsHunted(XOHCL &huntedBar) { // bool result = false; // huntedBar.Clean(); // result = IsValid(); if (!result) { return result; } // XOHCL breakerBar; result = DetectBreakerBar(breakerBar); if (!result) { return result; } // bool isBullish = IsBullish(); // int breakerIndex = breakerBar.Index(); for (int i = breakerIndex - 1; i >= 0; i--) { // XOHCL iBar; result = iBar.Init( breakerBar.symbol, breakerBar.period, i // ); // double price = isBullish ? iBar.low : iBar.high; // result = IsPriceInsideZone( price, Upper(), Lower() // ); if (result) { // huntedBar = iBar; break; } } // result = huntedBar.IsValid(); // return result; } /** * Check Order Block Validation ... * * @return ( bool ) */ bool IsValidOrderBlock() { // bool result = false; // result = IsValid(); if (!result) { return result; } // XOHCL breakerBar; result = DetectBreakerBar(breakerBar); if (!result) { return result; } int breakerBarIndex = breakerBar.Index(); // XOHCL huntedBar; bool isHunted = IsHunted(huntedBar); result = !isHunted; if (!result) { return result; } // bool isBullish = IsBullish(); // for (int i = breakerBarIndex - 1; i >= 0; i--) { // XOHCL iBar; result = iBar.Init( breakerBar.symbol, breakerBar.period, i // ); if (!result) { continue; } // double price = isBullish ? iBar.low : iBar.high; // result = isBullish ? price > Upper() : price < Lower(); if (!result) { return result; } } // return result; } // // Overrides ... bool IsValid() override { // bool result = false; // result = IsValidBarZone() && (mType == X_POI_BULLISH_ORDERBLOCK || mType == X_POI_BEARISH_ORDERBLOCK); // return result; } // protected: // // private: // // }; // // Rejection Bar ... class XCRejectionBar : public XCBarZone { // public: // // // Constructor ... void XCRejectionBar() { } // // Deconstructor ... void ~XCRejectionBar() { } // // Tools ... /** * Initialize POI ... * * @param bar: XOHCL instance ... * * @return ( bool ) */ bool Init( XOHCL &bar // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // bool isBullish = bar.GetLowShadow() > bar.GetHighShadow(); bool isBearish = bar.GetHighShadow() > bar.GetLowShadow(); result = isBullish || isBearish; if (!result) { return result; } // ENUM_X_PRICE upPrice = isBullish ? X_PRICE_HIGH : X_PRICE_DOWN; // ENUM_X_PRICE loPrice = isBullish ? X_PRICE_UP : X_PRICE_LOW; // result = InitBarZone( bar, X_POI_REJECTION_BAR, upPrice, loPrice // ); if (!result) { return result; } // result = IsValid(); // return result; } // // Getter(s) / Setter(s) ... /** * Check is Bullish ... * * @return ( bool ) */ bool IsBullish() { // bool result = false; // result = IsValid() && Type() == X_POI_REJECTION_BAR && mBar.GetLowShadow() > mBar.GetHighShadow(); // return result; } /** * Check is Bearish ... * * @return ( bool ) */ bool IsBearish() { // bool result = false; // result = IsValid() && Type() == X_POI_REJECTION_BAR && mBar.GetHighShadow() > mBar.GetLowShadow(); // return result; } // // Overrides ... bool IsValid() override { // bool result = false; // result = IsValidBarZone() && mType == X_POI_REJECTION_BAR; // return result; } // protected: // // private: // // }; // // Momentum Bar ... class XCMomentumBar : public XCBarZone { // public: // // // Constructor ... void XCMomentumBar() { } // // Deconstructor ... void ~XCMomentumBar() { } // // Tools ... /** * Initialize POI ... * * @param bar: XOHCL instance ... * * @return ( bool ) */ bool Init( XOHCL &bar // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // bool isBullish = bar.IsBullish(); bool isBearish = bar.IsBearish(); result = isBullish || isBearish; if (!result) { return result; } // result = InitBarZone( bar, X_POI_MOMENTUM_BAR, X_PRICE_HIGH, X_PRICE_LOW // ); if (!result) { return result; } // result = IsValid(); // return result; } // // Getter(s) / Setter(s) ... /** * Check is Bullish ... * * @return ( bool ) */ bool IsBullish() { // bool result = false; // result = IsValid() && mBar.IsBullish() && Type() == X_POI_MOMENTUM_BAR; // return result; } /** * Check is Bearish ... * * @return ( bool ) */ bool IsBearish() { // bool result = false; // result = IsValid() && mBar.IsBearish() && Type() == X_POI_MOMENTUM_BAR; // return result; } // // Overrides ... bool IsValid() override { // bool result = false; // result = IsValidBarZone() && mType == X_POI_MOMENTUM_BAR; // return result; } // protected: // // private: // // }; // // Fair Value Gap ... class XCFVG : public XCTwoBarZone { // public: // // // Constructor ... void XCFVG() { } // // Deconstructor ... void ~XCFVG() { } // // Tools ... /** * Initialize POI ... * * @param startBar: XOHCL instance ... * @param endBar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * * @return ( bool ) */ bool Init( XOHCL &startBar, XOHCL &endBar, ENUM_X_DIRECTION dir // ) { // bool result = false; // result = endBar.IsValid() && startBar.IsValid() && (dir == X_DIRECTION_BULLISH || dir == X_DIRECTION_BEARISH); if (!result) { return result; } // bool isDirBullish = IsSpecifiedBullish(dir); ENUM_XPOIS mTT = isDirBullish ? X_POI_BULLISH_FVG : X_POI_BEARISH_FVG; // bool useFistForUpper = isDirBullish ? false : true; ENUM_X_PRICE upPrice = isDirBullish ? X_PRICE_LOW : X_PRICE_HIGH; ENUM_X_PRICE loPrice = isDirBullish ? X_PRICE_HIGH : X_PRICE_LOW; // result = InitTwoBarZone( startBar, endBar, mTT, useFistForUpper, upPrice, loPrice // ); if (!result) { return result; } // result = IsValid(); // return result; } // // Getter(s) / Setter(s) ... /** * Check is Bullish ... * * @return ( bool ) */ bool IsBullish() { // bool result = false; // result = IsValid() && Type() == X_POI_BULLISH_FVG; // return result; } /** * Check is Bearish ... * * @return ( bool ) */ bool IsBearish() { // bool result = false; // result = IsValid() && Type() == X_POI_BEARISH_FVG; // return result; } // // Overrides ... bool IsValid() override { // bool result = false; // result = IsValidTwoBarZone() && (mType == X_POI_BULLISH_FVG || mType == X_POI_BEARISH_FVG); // return result; } // protected: // // private: // // }; // // Ticks Zones ... // class XCTickZone : public CObject { // // Public ... public: // // Props ... string symbol; ENUM_TIMEFRAMES period; // double high; double low; int ticks; double percent; // ulong volume; double volumePercent; // // Compare Two Zone With Each Other ... virtual int Compare( const CObject *node, const int mode = 0 // ) const { // const XCTickZone *other = (XCTickZone *)node; // return other.ticks - ticks; } // bool IsValid() { // bool result = false; // result = high > 0 && low > 0 && high > low && ticks > 0 && percent > 0; // return result; } // // Protected ... protected: // // Private ... private: // }; // class XCTicksZone : public XCTwoBarZone { // public: // // // Constructor ... void XCTicksZone() { Default(); } // // Deconstructor ... void ~XCTicksZone() { } // // Getter(s) / Setter(s) ... /** * Get Number of Ticks Levels ... * * @return ( int ) */ int Levels() { return mLevels; } /** * Set Number of Ticks Levels ... * * @return ( int ) */ void Levels(int value) { // if (value < 2) { value = 2; } // mLevels = value; } /** * Apply Default Config ... */ virtual void Default() { // Levels(10); } // // Tools ... /** * Initialize POI ... * * @param startBar: XOHCL instance ... * @param endBar: XOHCL instance ... * * @return ( bool ) */ bool Init( XOHCL &startBar, XOHCL &endBar // ) { // bool result = false; // result = endBar.IsValid() && startBar.IsValid(); if (!result) { return result; } // // Calculate Start and End Time ... datetime from = startBar.time; datetime to = endBar.time; ulong fromM = ((ulong)startBar.time * 1000); ulong toM = ((ulong)endBar.time * 1000); // // Symbol and Period ... string symbol = startBar.symbol; ENUM_TIMEFRAMES period = startBar.period; // // Prepare Zones Array ... mZones.Clear(); // // Retrieve Ticks between Times ... SpecificClean(mTicks); CopyTicksRange( symbol, mTicks, COPY_TICKS_ALL, fromM, toM // ); // // Ticks Volumes ... int ticksVolumeCount = CopyTickVolume( symbol, PERIOD_M1, from, to, mTickVolumes // ); if (IsValidSize(ticksVolumeCount)) { // mVolumes = 0; for (int i = 0; i < ticksVolumeCount; i++) { mVolumes += mTickVolumes[i]; } } // // Retrieve Highs ... SpecificClean(mHighs); CopyHigh( symbol, period, from, to, mHighs // ); // // Retrieve Lows ... SpecificClean(mLows); CopyLow( symbol, period, from, to, mLows // ); // // Find Highest Value in Range ... int highIDX = ArrayMaximum(mHighs); mRangeHigh = mHighs[highIDX]; // // Find Lowest Value in Range ... int lowIDX = ArrayMinimum(mLows); mRangeLow = mLows[lowIDX]; // datetime mTimes[]; CopyTime( symbol, period, from, to, mTimes // ); mRangeHighTime = mTimes[highIDX]; mRangeLowTime = mTimes[lowIDX]; // double mRangeSize = mRangeHigh - mRangeLow; // // Create Zones ... for (int i = 0; i < Levels(); i++) { // // Instance a New Zone ... XCTickZone *iZone = new XCTickZone(); // iZone.symbol = symbol; iZone.period = period; // // Calculate Each Zones High / Low based on Range ... double iH = mRangeHigh - mRangeSize * i / Levels(); double iL = mRangeHigh - mRangeSize * (i + 1) / Levels(); // // Set Zone High Low Properties ... iZone.low = iL; iZone.high = iH; // // Add Zone to Zone Array Objects ... mZones.Add(iZone); } // // Calculate Each Zone Ticks ... int ticksCount = ArraySize(mTicks); for (int i = 0; i < ticksCount; i++) { // // Retrieve Tick ... MqlTick iTick = mTicks[i]; // // Loop through Zones ... for (int j = 0; j < Levels(); j++) { // // Rejrieve j indexed Zone Object ... XCTickZone *jZone = mZones.At(j); // bool isInRange = IsTickInZoneRange( iTick, jZone // ); if (isInRange) { // jZone.ticks++; break; } } } // // Calculating Zone Percents ... for (int i = 0; i < Levels(); i++) { // XCTickZone *iZone = mZones.At(i); // double percent = CalculateZoneTickPercent(iZone); iZone.percent = percent; } // // Sort Zones Based on Percents ... mZones.Sort(); // mUpper = mRangeHigh; mLower = mRangeLow; mType = X_POI_TICKS_ZONES; mEndBar = endBar; mStartBar = startBar; From(startBar.time); To(endBar.time); // result = IsValid(); if (!result) { return result; } // // Try to Find Out PERIOD_1M times in each zone ... datetime to1M = (datetime)((int)endBar.time + PeriodSeconds(period) - 60); int to1MIndex = iBarShift( symbol, PERIOD_M1, to1M // ); int from1MIndex = iBarShift( symbol, PERIOD_M1, from // ); for (int i = from1MIndex; i > to1MIndex; i--) { // XOHCL iBar; bool isInited = iBar.Init( symbol, PERIOD_M1, i // ); if (!isInited) { continue; } ulong iVolume = iTickVolume( symbol, PERIOD_M1, i // ); // // Loop through Zones ... for (int j = 0; j < Levels(); j++) { // XCTickZone *jZone = mZones.At(j); if (!jZone.IsValid()) { continue; } // // Check iBar is Inside jZone ... bool isIBarInside = iBar.GetUp() < jZone.high && iBar.GetDown() > jZone.low; // iBar.low < jZone.high || // iBar.high > jZone.low; if (isIBarInside) { jZone.volume += iVolume; } } } // // Calculate Volume Percent ... for (int i = 0; i < Levels(); i++) { // XCTickZone *iZone = mZones.At(i); // iZone.volumePercent = (double)(iZone.volume * 100 / mVolumes); } // return result; } // // Getter(s) / Setter(s) ... /** * Retrieve Zones Count ... * * @return ( int ) */ int Count() { return mZones.Total(); } /** * Retrieve Specified Sorted Zones ... * * @param index: Integer ... * * @return ( XCTickZone * ) */ XCTickZone *GetZone(int index) { // if (!IsValidIndex(index)) { return NULL; } // return mZones.At(index); } /** * Calculate Liquidity Percent for Specified Direction ... * * @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ... * @param price: Double, Specified Price ... * * @return ( double ) */ double CalculateLiquidityPercent( ENUM_X_DIRECTION forDirection, double price // ) { // double result = 0; // int count = Count(); if (price <= 0 || !IsValid() || !IsValidSize(count) || forDirection == X_DIRECTION_ALL || forDirection == X_DIRECTION_NONE) { return result; } // bool isBullish = forDirection == X_DIRECTION_BULLISH; // for (int i = 0; i < count; i++) { // XCTickZone *iZone = GetZone(i); // if (iZone.IsValid()) { // result += !isBullish && price > iZone.high ? iZone.percent : isBullish && price < iZone.low ? iZone.percent : 0; } } // return result; } // // Overrides ... bool IsValid() override { // bool result = false; // result = IsValidFrom() && IsValidTwoBarZone() && Levels() > 0 && mZones.Total() == Levels() && mRangeHigh > 0 && mRangeLow > 0; // return result; } // protected: // // private: // // Props ... // MqlTick mTicks[]; double mHighs[]; double mLows[]; ulong mVolumes; ulong mTickVolumes[]; double mRangeHigh; datetime mRangeHighTime; double mRangeLow; datetime mRangeLowTime; // int mLevels; // Number of Ticks Levels ... // CArrayObj mZones; /** * Check a Tick is in a Zone rage or not ... * * @param tick: MqlTick instance ... * @param zone: XCTickZone instance ... * * @return ( bool ) */ bool IsTickInZoneRange( MqlTick &tick, XCTickZone *zone // ) { // bool result = false; // result = // tick.bid >= zone.low && tick.bid <= zone.high // ; // return result; } /** * Calculate Zone Tick Percent ... * * @param zone: XCTickZone instance ... * @param normalizationDigits: Integer ... * * @return ( double ) */ double CalculateZoneTickPercent( XCTickZone *zone, int normalizationDigits = 2 // ) { // double result = 0; // if (normalizationDigits < 2 || normalizationDigits > 5) { normalizationDigits = 2; } // int ticksCount = ArraySize(mTicks); if (ticksCount <= 0) { return result; } // result = (double)zone.ticks / ticksCount * 100; result = NormalizeDouble(result, normalizationDigits); // return result; } // }; // // Trading Day ... class XCDay : public XCFromToZone { // public: // // // Constructor ... void XCDay() { } // // Deconstructor ... void ~XCDay() { } // // Tools ... /** * Initialize POI ... * * @return ( bool ) */ bool Init() { // bool result = false; // result = IsValid(); // return result; } // // Getter(s) / Setter(s) ... // // Overrides ... // protected: // // private: // // }; // // Trading Session ... class XCSession : public XCFromToZone { // public: // // // Constructor ... void XCSession() { } // // Deconstructor ... void ~XCSession() { } // // Tools ... /** * Initialize POI ... * * @return ( bool ) */ bool Init() { // bool result = false; // result = IsValid(); // return result; } // // Getter(s) / Setter(s) ... // // Overrides ... // protected: // // private: // // }; // // // Model Exists Founded POIs ... struct XPOIState { // string symbol; ENUM_TIMEFRAMES period; datetime time; // XCTicksZone *ticksZone; // Ticks Zone ... // XCSwing *swingHighs[]; // Holds Founded Swing Highs ... XCSwing *swingLows[]; // Holds Founded Swing Lows ... XCMomentumBar *bullishMomentumBars[]; // Holds Founded Bullish Momentum Bars ... XCMomentumBar *bearishMomentumBars[]; // Holds Founded Bearish Momentum Bars ... XCRejectionBar *bullishRejectionBars[]; // Holds Founded Bullish Rejection Bars ... XCRejectionBar *bearishRejectionBars[]; // Holds Founded Bearish Rejection Bars ... XCSupportZone *supportZones[]; // Holds Founded Support Zones ... XCResistanceZone *resistanceZones[]; // Holds Founded Resistance Zones ... XCSupplyZone *supplyZones[]; // Holds Founded Supply Zones ... XCDemandZone *demandZones[]; // Holds Founded Demand Zones ... XCOrderBlock *bullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ... XCOrderBlock *bearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ... XCFVG *bullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ... XCFVG *bearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ... // // Constructor ... void XPOIState() { Clean(); } // // Actions ... /** * Cleanup all props ... */ void Clean() { // symbol = NULL; period = NULL; time = NULL; // ticksZone = NULL; // Clean(swingHighs); Clean(swingLows); Clean(bullishMomentumBars); Clean(bearishMomentumBars); Clean(bullishRejectionBars); Clean(bearishRejectionBars); Clean(supportZones); Clean(resistanceZones); Clean(supplyZones); Clean(demandZones); Clean(bullishOrderBlocks); Clean(bearishOrderBlocks); Clean(bullishFairValueGaps); Clean(bearishFairValueGaps); } /** * Validate ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = IsSpecifiedValid(symbol) && IsSpecifiedValid(period) && IsSpecifiedValid(time); // return result; } /** * Check State has Childs or not ... * * @return ( bool ) */ bool HasChild() { // bool result = false; // result = // IsValidSize(CountSwingHighs()) || IsValidSize(CountSwingLows()) || IsValidSize(CountBullishMomentumBars()) || IsValidSize(CountBearishMomentumBars()) || IsValidSize(CountBullishRejectionBars()) || IsValidSize(CountBearishRejectionBars()) || IsValidSize(CountSupportZones()) || IsValidSize(CountResistanceZones()) || IsValidSize(CountSupplyZones()) || IsValidSize(CountDemandZones()) || IsValidSize(CountBullishOrderBlocks()) || IsValidSize(CountBearishOrderBlocks()) || IsValidSize(CountBullishFairValueGaps()) || IsValidSize(CountBearishFairValueGaps()) // ; // return result; } /** * Fill Dest State by Current State's Data ... * * @param dest: XPOIState instance, reference to specified dest ... * */ void Fill(XPOIState &dest) { // if (!IsValid() || !HasChild()) { return; } // dest.symbol = symbol; dest.period = period; dest.time = time; // Copy( swingHighs, dest.swingHighs, false // ); Copy( swingLows, dest.swingLows, false // ); Copy( bullishMomentumBars, dest.bullishMomentumBars, false // ); Copy( bearishMomentumBars, dest.bearishMomentumBars, false // ); Copy( bullishRejectionBars, dest.bullishRejectionBars, false // ); Copy( bearishRejectionBars, dest.bearishRejectionBars, false // ); Copy( supportZones, dest.supportZones, false // ); Copy( resistanceZones, dest.resistanceZones, false // ); Copy( supplyZones, dest.supplyZones, false // ); Copy( demandZones, dest.demandZones, false // ); Copy( bullishOrderBlocks, dest.bullishOrderBlocks, false // ); Copy( bearishOrderBlocks, dest.bearishOrderBlocks, false // ); Copy( bullishFairValueGaps, dest.bullishFairValueGaps, false // ); Copy( bearishFairValueGaps, dest.bearishFairValueGaps, false // ); // } /** * Calculate Liquidity Percent for Specified Direction ... * * @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ... * @param price: Double, Specified Price ... * * @return ( double ) */ double CalculateLiquidityPercent( ENUM_X_DIRECTION forDirection, double price = 0 // ) { // double result = 0; // if (!IsValid() || ticksZone == NULL) { return result; } // // Normalize Price for Actions ... if (price <= 0) { // MqlTick mTick; bool isTickRetrieved = GetTick( symbol, mTick // ); if (isTickRetrieved) { price = mTick.bid; } } // result = ticksZone .CalculateLiquidityPercent( forDirection, price // ); // return result; } // // Counters ... // int CountSwingHighs() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(swingHighs); // return result; } // int CountSwingLows() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(swingLows); // return result; } // int CountBullishMomentumBars() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(bullishMomentumBars); // return result; } // int CountBearishMomentumBars() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(bearishMomentumBars); // return result; } // int CountBullishRejectionBars() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(bullishRejectionBars); // return result; } // int CountBearishRejectionBars() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(bearishRejectionBars); // return result; } // int CountSupportZones() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(supportZones); // return result; } // int CountResistanceZones() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(resistanceZones); // return result; } // int CountSupplyZones() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(supplyZones); // return result; } // int CountDemandZones() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(demandZones); // return result; } // int CountBullishOrderBlocks() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(bullishOrderBlocks); // return result; } // int CountBearishOrderBlocks() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(bearishOrderBlocks); // return result; } // int CountBullishFairValueGaps() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(bullishFairValueGaps); // return result; } // int CountBearishFairValueGaps() { // int result = 0; // if (!IsValid()) { return result; } // result = ArraySize(bearishFairValueGaps); // return result; } // }; // // // // // Pivot Types ... enum ENUM_XPV_PIVOTS { XPV_NONE, XPV_PEAK, XPV_VALE, }; // // Model a Pivot structure ... struct XPVPivot { // string symbol; ENUM_TIMEFRAMES period; // double upper; double lower; // datetime from; datetime to; // int repetition; // ENUM_XPV_PIVOTS type; // // Combined all States ... XPOIState state; // XPVPivot() { Clean(); } // // Tools ... /** * Cleanup ... */ void Clean() { // upper = 0; lower = 0; // to = NULL; from = NULL; symbol = NULL; period = NULL; // repetition = 0; // type = XPV_NONE; // state.Clean(); } /** * Validation ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = // IsValid(to) && IsValid(from) && IsValid(symbol) && IsValid(period) && repetition > 0 && type != XPV_NONE && (upper > 0 || lower > 0) // ; // return result; } /** * Check Pivot is Peak ... * * @return ( bool ) */ bool IsPeak() { // bool result = false; // result = IsValid() && type == XPV_PEAK; // return result; } /** * Check Pivot is Vale ... * * @return ( bool ) */ bool IsVale() { // bool result = false; // result = IsValid() && type == XPV_VALE; // return result; } /** * Calculate Lower for Peaks ... * * @return ( double ) */ double CalculateLower() { // double result = 0; // if (!IsValid() || !IsPeak()) { return result; } // int fromIndex = iBarShift( symbol, period, from // ); // int toIndex = iBarShift( symbol, period, to // ); // int count = fromIndex - toIndex; // int llIDX = iLowest( symbol, period, MODE_LOW, count, toIndex // ); // result = iLow( symbol, period, llIDX // ); // return result; } /** * Calculate Upper for Vales ... * * @return ( double ) */ double CalculateUpper() { // double result = 0; // if (!IsValid() || !IsVale()) { return result; } // int fromIndex = iBarShift( symbol, period, from // ); // int toIndex = iBarShift( symbol, period, to // ); // int count = fromIndex - toIndex; // int hhIDX = iHighest( symbol, period, MODE_HIGH, count, toIndex // ); // result = iHigh( symbol, period, hhIDX // ); // return result; } /** * Calculate Range of Pivot ... * * @return ( double ) */ double CalculateRange() { // double result = 0; // if (!IsValid() || upper <= 0 || lower <= 0) { return result; } // result = upper - lower; // return result; } /** * Calculate Middle of Pivot ... * Used for * @return ( double ) */ double CalculateMid() { // double result = 0; // double range = CalculateRange(); if (range <= 0) { return result; } // result = lower + (range / 2); // return result; } /** * Calculate Liquidity Percent for Specified Direction ... * * @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ... * @param price: Double, Specified Price ... * * @return ( double ) */ double CalculateLiquidityPercent( ENUM_X_DIRECTION forDirection, double price = 0 // ) { // double result = 0; // if (!IsValid()) { return result; } // result = state .CalculateLiquidityPercent( forDirection, price // ); // return result; } /** * Check Price in Premium or not ... * * @return ( bool ) */ bool IsPriceInPremium() { // bool result = false; // result = IsValid(); if (!result) { return result; } // double ask = GetAsk(symbol); double bid = GetBid(symbol); // double mid = CalculateMid(); // result = // ask > mid && bid > mid // ; // return result; } /** * Check Price in Discount or not ... * * @return ( bool ) */ bool IsPriceInDiscount() { // bool result = false; // result = IsValid(); if (!result) { return result; } // double ask = GetAsk(symbol); double bid = GetBid(symbol); // double mid = CalculateMid(); // result = // ask > mid && bid > mid // ; // return result; } // /** * Get Unique Identifier ... * * @return ( string ) */ string GetTag() { // string result = NULL; // if (!IsValid()) { return result; } // string hash = symbol + "_" + ToString(period) + "_" + ToString(upper) + "," + ToString(lower) + "_" + ToString(from) + "," + ToString(to); hash = ToMD5(hash); // string typeStr = type == XPV_PEAK ? "Peak" : "Vale"; // result = // "XPV_" + typeStr + "_" + symbol + "_" + ToString(period) + "_" + hash // ; // return result; } // }; // // Pivots ... struct XPVPivotPoint { // // Props ... double value; int repetition; datetime time; ENUM_XPV_PIVOTS type; // // Constructor ... XPVPivotPoint() { Clean(); } // // Tools ... /** * Cleanup ... */ void Clean() { // value = 0; time = NULL; repetition = 0; type = XPV_NONE; } /** * Validate ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = // value > 0 && IsValid(time) && repetition > 0 && type != XPV_NONE // ; // return result; } /** * Check current Pivot Point is Peak or not ... * * @return ( bool ) */ bool IsPeak() { // bool result = false; // result = IsValid() && type == XPV_PEAK; // return result; } /** * Check current Pivot Point is Vale or not ... * * @return ( bool ) */ bool IsVale() { // bool result = false; // result = IsValid() && type == XPV_VALE; // return result; } // }; // // // // // Consolidation Zone ... struct XConsolidationZone { // // Props ... // string symbol; // Symbol ... ENUM_TIMEFRAMES period; // Period ... // double upper; // Upper ... double lower; // Lower ... // datetime initTime; int loopback; // Loopback ... // ENUM_X_DIRECTION breakDirection; // Break Direction ... XOHCL breakerBar; // Breaker Bar ... // // Constructor ... XConsolidationZone() { Clean(); } // // Tools ... /** * Initialize Zone ... * * @param _symbol: String ... * @param _period: ENUM_TIMEFRAMES member ... * @param _upper: Double ... * @param _lower: Double ... * @param _loopback: Integer ... * * @return ( bool ) */ bool Init( string _symbol, ENUM_TIMEFRAMES _period, double _upper, double _lower, int _loopback // ) { // bool result = false; // _symbol = NormalizeSymbol(_symbol); _period = NormalizePeriod(_period); // result = // _upper > 0 && _lower > 0 && _loopback > 0 // ; if (!result) { return result; } // upper = _upper; lower = _lower; symbol = _symbol; period = _period; loopback = _loopback; // result = IsValid(); if (result) { initTime = TimeCurrent(); } // return result; } /** * Update Breaked State ... */ void Update() { // if (!IsValid()) { return; } // if (IsBreaked()) { return; } // XOHCL cBar; bool isInited = cBar.Init( symbol, period, 0 // ); if (!isInited) { return; } // XOHCL pBar; isInited = cBar.GetPreviousBar(pBar); if (!isInited) { return; } // // Check Consolidation Hounts ... bool isHountTop = cBar.high > upper && cBar.low < upper && cBar.GetUp() < upper; bool isHountBottom = cBar.low < lower && cBar.high > lower && cBar.GetDown() > lower; bool isHounted = isHountTop || isHountBottom; if (isHounted) { // if (isHountTop) { upper = cBar.high; } // if (isHountBottom) { lower = cBar.low; } // return; } // // Check Consolidation Breaks ... bool isBreakTop = (cBar.GetUp() > upper && cBar.GetDown() < upper) || (cBar.low > upper && cBar.high > upper); bool isBreakBottom = (cBar.GetDown() < lower && cBar.GetUp() > lower) || (cBar.high < lower && cBar.low < lower); bool isBreaked = isBreakTop || isBreakBottom; if (!isBreaked) { return; } // // Calculate Break Direction ... breakerBar = cBar; breakDirection = isBreakTop ? X_DIRECTION_BULLISH : isBreakBottom ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; } /** * Cleanup ... */ void Clean() { // upper = 0; lower = 0; loopback = 0; symbol = NULL; period = NULL; initTime = NULL; breakerBar.Clean(); breakDirection = X_DIRECTION_NONE; } /** * Validate ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = // IsValid(symbol) && IsValid(period) && upper > 0 && lower > 0 && loopback > 0 // ; // return result; } /** * Check Zone is Breaked or not ... * * @return ( bool ) */ bool IsBreaked() { // bool result = false; // result = breakerBar.IsValid() && HasDirection(breakDirection); // return result; } /** * Detect Supply Zone if Exists ... * * @return ( bool ) */ bool HasSupplyZone( XCSupplyZone *&zone // ) { // bool result = false; // result = IsBreaked() && breakDirection == X_DIRECTION_BEARISH; if (!result) { return result; } // // Implment Zone Finding ... int index = breakerBar.Index(); int hhIDX = iHighest( symbol, period, MODE_HIGH, loopback, index // ); result = IsValidIndex(hhIDX); if (!result) { return result; } // XOHCL hhBar; result = hhBar.Init( symbol, period, hhIDX // ); if (!result) { return result; } // zone = new XCSupplyZone(); result = zone.Init( hhBar, loopback // ); // return result; } /** * Detect Demand Zone if Exists ... * * @return ( bool ) */ bool HasDemandZone( XCDemandZone *&zone // ) { // bool result = false; // result = IsBreaked() && breakDirection == X_DIRECTION_BULLISH; if (!result) { return result; } // // Implment Zone Finding ... int index = breakerBar.Index(); int llIDX = iLowest( symbol, period, MODE_LOW, loopback, index // ); result = IsValidIndex(llIDX); if (!result) { return result; } // XOHCL llBar; result = llBar.Init( symbol, period, llIDX // ); if (!result) { return result; } // zone = new XCDemandZone(); result = zone.Init( llBar, loopback // ); // return result; } /** * Retrieve Start Time ... * * @return ( datetime ) */ datetime From() { // datetime result = NULL; // if (!IsValid()) { return result; } // int startIndex = iBarShift( symbol, period, initTime // ); // result = iTime( symbol, period, loopback + startIndex // ); // return result; } /** * Retrieve Unique Identifier ... * * @return ( string ) */ string GetTag() { // string result = // GetTypeName(this) + "_" + symbol + "_" + ToString(period) + "_" + ToString(upper) + "_" + ToString(lower) // ; // return result; } // }; /** * Converts a Consolidation Zone ... * * @param zone: XConsolidationZone instance Reference ... * @param dest: XCZone pointer Reference ... * * @return ( bool ) */ bool ToZone( XConsolidationZone &zone, XCZone *&dest // ) { // bool result = false; // dest = NULL; // result = zone.IsValid(); if (!result) { return result; } // dest = new XCZone(); dest.Upper(zone.upper); dest.Lower(zone.lower); result = dest.IsValidBoundary(); // return result; } // // Model Value Changed ... struct XValueChange { // // Props ... double before; // Before Change Value ... double after; // After Change Value ... datetime time; // Change Time ... ENUM_X_DIRECTION dir; // Change Direction ... // // Constructor ... XValueChange() { Clean(); } // // Tools ... /** * Initialize ... * * @param _before: Double, Value Before Change ... * @param _after: Double, Value After Change ... * @param _time: Datetime, Change Time ... * @param _dir: ENUM_X_DIRECTION member, Specified Changed Direction ... * * @return ( bool ) */ bool Init( double _before, // Before Change Value ... double _after, // After Change Value ... ENUM_X_DIRECTION _dir, // Change Direction ... datetime _time = NULL // Change Time ... ) { // bool result = false; // _time = NormalizeTime(_time); // // Validate Inputs ... result = // _after > 0 && _before > 0 && IsValid(_time) && _after != _before && HasDirection(_dir) // ; if (!result) { return result; } // // Set Validated Values ... dir = _dir; time = _time; after = _after; before = _before; // result = IsValid(); // return result; } /** * Cleaning Up ... */ void Clean() { // after = 0; before = 0; time = NULL; dir = X_DIRECTION_NONE; } /** * Validate Model ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = // after > 0 && before > 0 && IsValid(time) && after != before && HasDirection(dir) // ; // return result; } /** * Fill Change Bar ... * * @param bar: XOHCL instance Reference, holds Change Bar ... * @param _symbol: String, Specified Symbol ... * @param _period: ENUM_TIMEFRAMES _period member, Specified Period ... * * @return ( bool ) */ bool FillBar( XOHCL &bar, string _symbol = NULL, ENUM_TIMEFRAMES _period = NULL // ) { // bool result = false; // bar.Clean(); _symbol = NormalizeSymbol(_symbol); _period = NormalizePeriod(_period); // result = IsValid() && IsValid(_symbol) && IsValid(_period); if (!result) { return result; } // result = bar.Init( _symbol, _period, time // ); // return result; } // }; // // Price Zones Model ... struct XPriceZones { // XOHCL bar; // if Based On Bar it's Filled ... double price; // if Based on Price, it's Filled ... // int count; // Exists Zones Count ... // XCFVG *fairValueGap; // Exists Fair Value Gap ... XCSupplyZone *supplyZone; // Exists Supply Zone ... XCDemandZone *demandZone; // Exists Demand Zone ... XCOrderBlock *orderBlock; // Exists Order Block ... XCSupportZone *supportZone; // Exists Support Zone ... XCResistanceZone *resistanceZone; // Exists Resistance Zone ...ّ // // Constructor ... XPriceZones() { Clean(); } /** * Cleanup ... */ void Clean() { // bar.Clean(); price = 0; // supplyZone = NULL; demandZone = NULL; orderBlock = NULL; supportZone = NULL; fairValueGap = NULL; resistanceZone = NULL; } /** * Check Zone is Valid ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = // (IsBasedOnBar() || IsBasedOnPrice()) && IsValidSize(count) // ; // return result; } /** * Check Zones Base on Bar ... * * @return ( bool ) */ bool IsBasedOnBar() { return bar.IsValid(); } /** * Check Zones Based on Price ... * * @return ( bool ) */ bool IsBasedOnPrice() { return price > 0; } /** * Check Has Supply Zone ... * * @return ( bool ) */ bool HasSupplyZone() { // return IsValidSize(count) && supplyZone != NULL && supplyZone.IsValid(); } /** * Check Has Demand Zone ... * * @return ( bool ) */ bool HasDemandZone() { // return IsValidSize(count) && demandZone != NULL && demandZone.IsValid(); } /** * Check Has OrderBlock ... * * @return ( bool ) */ bool HasOrderBlock() { // return IsValidSize(count) && orderBlock != NULL && orderBlock.IsValid(); } /** * Check Has Support Zone ... * * @return ( bool ) */ bool HasSupportZone() { // return IsValidSize(count) && supportZone != NULL && supportZone.IsValid(); } /** * Check Has FairValueGap ... * * @return ( bool ) */ bool HasFairValueGap() { // return IsValidSize(count) && fairValueGap != NULL && fairValueGap.IsValid(); } /** * Check Has Resistance Zone ... * * @return ( bool ) */ bool HasResistanceZone() { // return IsValidSize(count) && resistanceZone != NULL && resistanceZone.IsValid(); } /** * Check Zones are Overal Bullish ... * * @return ( bool ) */ bool IsBullish() { // bool result = false; // result = // HasDemandZone() // || // HasSupportZone() // || // (HasOrderBlock() && orderBlock.IsBullish()) // || // (HasFairValueGap() && fairValueGap.IsBullish()) // ; // return result; } /** * Check Zones are Overal Bearish ... * * @return ( bool ) */ bool IsBearish() { // bool result = false; // result = // HasSupplyZone() // || // HasResistanceZone() // || // (HasOrderBlock() && orderBlock.IsBearish()) // || // (HasFairValueGap() && fairValueGap.IsBearish()) // ; // return result; } /** * Fill Zones Based On required Direction ... * * @param dir: ENUM_X_DIRECTION member ... * * @return ( int ) */ int FillZones( ENUM_X_DIRECTION dir, XCZone *&zones[] // ) { // int result = 0; // Clean(zones); // bool isBullish = IsBullish(dir); bool isBoth = dir == X_DIRECTION_ALL || dir == X_DIRECTION_NONE; // if (isBoth || isBullish) { // if (HasSupportZone()) { // Add( (XCZone *)supportZone, zones // ); } // if (HasDemandZone()) { // Add( (XCZone *)demandZone, zones // ); } // if (HasOrderBlock() && orderBlock.IsBullish()) { // Add( (XCZone *)orderBlock, zones // ); } // if (HasFairValueGap() && fairValueGap.IsBullish()) { // Add( (XCZone *)fairValueGap, zones // ); } } // if (isBoth || !isBullish) { // if (HasResistanceZone()) { // Add( (XCZone *)resistanceZone, zones // ); } // if (HasSupplyZone()) { // Add( (XCZone *)supplyZone, zones // ); } // if (HasOrderBlock() && orderBlock.IsBearish()) { // Add( (XCZone *)orderBlock, zones // ); } // if (HasFairValueGap() && fairValueGap.IsBearish()) { // Add( (XCZone *)fairValueGap, zones // ); } } // s result = ArraySize(zones); // return result; } /** * Calculate Boundary of Zones ... * * @param dir: ENUM_X_DIRECTION Member, Specified Direction ... * @param upper: Double ... * @param lower: Double ... * * @return ( bool ) */ bool GetBoundary( ENUM_X_DIRECTION dir, double &upper, double &lower // ) { // bool result = false; // upper = 0; lower = 0; // XCZone *zones[]; int mCount = FillZones(dir, zones); result = IsValidSize(mCount); if (!result) { return result; } // for (int i = 0; i < mCount; i++) { // XCZone *iZone = zones[i]; // double iUpper = iZone.Upper(); double iLower = iZone.Lower(); // upper = upper == 0 ? iUpper : iUpper > upper ? iUpper : upper; // lower = lower == 0 ? iLower : iLower < lower ? iLower : lower; } // return result; } /** * Calculate Lifetime of Zones ... * * @param dir: ENUM_X_DIRECTION Member, Specified Direction ... * @param from: DateTime ... * @param to: DateTime ... * * @return ( bool ) */ bool GetLifetime( ENUM_X_DIRECTION dir, datetime &from, datetime &to // ) { // bool result = false; // to = NULL; from = NULL; // XCZone *zones[]; int mCount = FillZones(dir, zones); result = IsValidSize(mCount); if (!result) { return result; } // bool isBullish = IsBullish(dir); bool isAll = dir == X_DIRECTION_NONE || dir == X_DIRECTION_ALL; // if (isAll || isBullish) { // // Support Zone ... bool hasSupportZone = HasSupportZone(); if (hasSupportZone) { // XCSupportZone *zone = supportZone; // from = !IsValid(from) || from > zone.From() ? zone.From() : from; // to = !IsValid(to) || to < zone.To() ? zone.To() : from; } // // Demand Zone ... bool hasDemandZone = HasDemandZone(); if (hasDemandZone) { // XCDemandZone *zone = demandZone; // from = !IsValid(from) || from > zone.From() ? zone.From() : from; // to = !IsValid(to) || to < zone.To() ? zone.To() : from; } // // Order Block ... bool hasOrderBlock = HasOrderBlock() && orderBlock.IsBullish(); if (hasOrderBlock) { // XCOrderBlock *zone = orderBlock; // from = !IsValid(from) || from > zone.From() ? zone.From() : from; // to = !IsValid(to) || to < zone.To() ? zone.To() : from; } // // Fair Value Gap ... bool hasFairValueGap = HasFairValueGap() && fairValueGap.IsBullish(); if (hasFairValueGap) { // XCFVG *zone = fairValueGap; // from = !IsValid(from) || from > zone.From() ? zone.From() : from; // to = !IsValid(to) || to < zone.To() ? zone.To() : from; } } // if (isAll || !isBullish) { // // Resistance Zone ... bool hasResistanceZone = HasResistanceZone(); if (hasResistanceZone) { // XCResistanceZone *zone = resistanceZone; // from = !IsValid(from) || from > zone.From() ? zone.From() : from; // to = !IsValid(to) || to < zone.To() ? zone.To() : from; } // // Supply Zone ... bool hasSupplyZone = HasSupplyZone(); if (hasSupplyZone) { // XCSupplyZone *zone = supplyZone; // from = !IsValid(from) || from > zone.From() ? zone.From() : from; // to = !IsValid(to) || to < zone.To() ? zone.To() : from; } // // Order Block ... bool hasOrderBlock = HasOrderBlock() && orderBlock.IsBearish(); if (hasOrderBlock) { // XCOrderBlock *zone = orderBlock; // from = !IsValid(from) || from > zone.From() ? zone.From() : from; // to = !IsValid(to) || to < zone.To() ? zone.To() : from; } // // Fair Value Gap ... bool hasFairValueGap = HasFairValueGap() && fairValueGap.IsBearish(); if (hasFairValueGap) { // XCFVG *zone = fairValueGap; // from = !IsValid(from) || from > zone.From() ? zone.From() : from; // to = !IsValid(to) || to < zone.To() ? zone.To() : from; } } // result = to > from && IsValid(to) && IsValid(from); // return result; } /** * Calculate Box Model Data ... * * @param dir: ENUM_X_DIRECTION Member, Specified Direction ... * @param upper: Double ... * @param lower: Double ... * @param from: DateTime ... * @param to: DateTime ... * * @return ( bool ) */ bool GetBoxData( ENUM_X_DIRECTION dir, double &upper, double &lower, datetime &from, datetime &to // ) { // bool result = false; // bool hasBoundary = GetBoundary( dir, upper, lower // ); // bool hasLifetime = GetLifetime( dir, from, to // ); // result = hasBoundary && hasLifetime; // return result; } // }; // // Market Strucutre Model ... struct XMarketStructure { // string symbol; ENUM_TIMEFRAMES period; // ENUM_X_DIRECTION bias; // XPVPivotPoint vales[]; XPriceZones valePriceZones[]; // XPVPivotPoint peaks[]; XPriceZones peakPriceZones[]; // XOHCL lowestValeBar; XOHCL lowestValePeakBreakeUpBar; XOHCL valeAboveLowestValePeakBar; // XOHCL highestPeakBar; XOHCL peakBelowHighestPeakValeBar; XOHCL highestPeakValeBreakeDownBar; // XMarketStructure() { Clean(); } /** * Cleanup ... */ void Clean() { // symbol = NULL; period = NULL; bias = X_DIRECTION_NONE; // Clean(vales); Clean(peaks); Clean(valePriceZones); Clean(peakPriceZones); // lowestValeBar.Clean(); lowestValePeakBreakeUpBar.Clean(); valeAboveLowestValePeakBar.Clean(); // highestPeakBar.Clean(); peakBelowHighestPeakValeBar.Clean(); highestPeakValeBreakeDownBar.Clean(); } /** * Validate Model ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = IsValid(symbol) && IsValid(period) && bias != X_DIRECTION_NONE; // return result; } /** * Check Bullish Trend ... * * @return ( bool ) */ bool IsBullish() { // bool result = false; // result = // IsValid() && IsBullish(bias) && HasChild(peaks) && HasDirection(bias) && lowestValeBar.IsValid() && HasChild(peakPriceZones) && lowestValePeakBreakeUpBar.IsValid() && valeAboveLowestValePeakBar.IsValid() // ; // return result; } /** * Check Bearish Trend ... * * @return ( bool ) */ bool IsBearish() { // bool result = false; // result = // IsValid() && IsBearish(bias) && HasChild(vales) && HasDirection(bias) && highestPeakBar.IsValid() && HasChild(valePriceZones) && peakBelowHighestPeakValeBar.IsValid() && highestPeakValeBreakeDownBar.IsValid() // ; // return result; } /** * Check Has Trend ... * * @return ( bool ) */ bool HasTrend() { // bool result = false; // result = IsValid() && (IsBullish() || IsBearish()); // return result; } // }; struct XStateZones { // XCSupportZone *supportZones[]; // Holds Founded Support Zones ... XCResistanceZone *resistanceZones[]; // Holds Founded Resistance Zones ... XCSupplyZone *supplyZones[]; // Holds Founded Supply Zones ... XCDemandZone *demandZones[]; // Holds Founded Demand Zones ... XCOrderBlock *bullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ... XCOrderBlock *bearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ... XCFVG *bullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ... XCFVG *bearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ... // XStateZones() { Clean(); } /** * Cleaning Model ... */ void Clean() { // Clean(supportZones); Clean(resistanceZones); Clean(supplyZones); Clean(demandZones); Clean(bullishOrderBlocks); Clean(bearishOrderBlocks); Clean(bullishFairValueGaps); Clean(bearishFairValueGaps); } /** * Validate Model ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = // IsValidSize(CountSupportZones()) || IsValidSize(CountResistanceZones()) || IsValidSize(CountSupplyZones()) || IsValidSize(CountDemandZones()) || IsValidSize(CountBullishOrderBlocks()) || IsValidSize(CountBearishOrderBlocks()) || IsValidSize(CountBullishFairValueGaps()) || IsValidSize(CountBearishFairValueGaps()) // ; // return result; } // // Tools ... // int CountSupportZones() { // int result = 0; // result = ArraySize(supportZones); // return result; } // int CountResistanceZones() { // int result = 0; // result = ArraySize(resistanceZones); // return result; } // int CountSupplyZones() { // int result = 0; // result = ArraySize(supplyZones); // return result; } // int CountDemandZones() { // int result = 0; // result = ArraySize(demandZones); // return result; } // int CountBullishOrderBlocks() { // int result = 0; // result = ArraySize(bullishOrderBlocks); // return result; } // int CountBearishOrderBlocks() { // int result = 0; // result = ArraySize(bearishOrderBlocks); // return result; } // int CountBullishFairValueGaps() { // int result = 0; // result = ArraySize(bullishFairValueGaps); // return result; } // int CountBearishFairValueGaps() { // int result = 0; // result = ArraySize(bearishFairValueGaps); // return result; } }; struct XFVGOrderBlock { // // Props ... XCOrderBlock *orderBlock; XCFVG *fairValueGap; // XStateZones stateZones; // XFVGOrderBlock() { Clean(); } /** * Cleanup Model ... */ void Clean() { // orderBlock = NULL; fairValueGap = NULL; } /** * Validate Model ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = // orderBlock != NULL && fairValueGap != NULL && // stateZones.IsValid() && ((orderBlock.IsBullish() && fairValueGap.IsBullish()) || ((orderBlock.IsBearish() && fairValueGap.IsBearish()))) // ; // return result; } /** * Get Model Direction ... * * @param dir: ENUM_X_DIRECTION member ... * * @return ( bool ) */ bool GetDirection( ENUM_X_DIRECTION &dir // ) { // bool result = false; // dir = X_DIRECTION_NONE; // result = IsValid(); if (!result) { return result; } // dir = orderBlock.IsBullish() ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // return result; } /** * Retrieve Boundary of Zone ... * * @param upper: Upper Boundary ...ّ * @param lower: Lower Bondary ... * @return ( bool ) */ bool GetBoundary( double &upper, double &lower // ) { // bool result = false; // upper = 0; lower = 0; // result = IsValid(); if (!result) { return result; } // upper = orderBlock.Upper(); upper = MathMax(upper, fairValueGap.Upper()); // lower = orderBlock.Lower(); lower = MathMax(lower, fairValueGap.Lower()); // result = lower > 0 && upper > 0 && upper > lower; // return result; } /** * Check Model is same as another Istance ... * * @param value: XFVGOrderBlock instance Reference ... * * @return ( bool ) */ bool IsSameAs(XFVGOrderBlock &value) { // bool result = false; // result = IsValid() && value.IsValid(); if (!result) { return result; } // ENUM_X_DIRECTION dir; result = GetDirection(dir); if (!result) { return result; } // ENUM_X_DIRECTION valueDir; result = value.GetDirection(valueDir); if (!result) { return result; } // result = // dir == valueDir // && // orderBlock.From() == value.orderBlock.From() && orderBlock.Upper() == value.orderBlock.Upper() && orderBlock.Lower() == value.orderBlock.Lower() // && // fairValueGap.From() == value.fairValueGap.From() && fairValueGap.Upper() == value.fairValueGap.Upper() && fairValueGap.Lower() == value.fairValueGap.Lower() // ; // return result; } // }; struct XBoxZone { // // Props ... string symbol; ENUM_TIMEFRAMES period; // double upper; double lower; // datetime from; datetime to; // string type; ENUM_X_DIRECTION dir; // // Constructor ... XBoxZone() { Clean(); } // // Tools ... /** * Cleanup Model ... */ void Clean() { // upper = 0; lower = 0; to = NULL; from = NULL; symbol = NULL; period = NULL; dir = X_DIRECTION_NONE; } /** * Validate Model ... * * @return ( bool ) */ bool IsValid() { // bool result = false; // result = // upper > 0 && lower > 0 && from < to && IsValid(to) && upper > lower && IsValid(from) && IsValid(symbol) && IsValid(period) // ; // 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; // case X_POI_TICKS_ZONES: result = "XTKSZ"; 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_BULLISH_MOMENTUM_BAR_DETECTED: result = "Bullish Momentum Bar Detected"; break; // case X_BEARISH_MOMENTUM_BAR_DETECTED: result = "Bearish Momentum Bar Detected"; break; // case X_BULLISH_REJECTION_BAR_DETECTED: result = "Bullish Rejection Bar Detected"; break; // case X_BEARISH_REJECTION_BAR_DETECTED: result = "Bearish 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; } // // // /** * Find Oldest Pivot Index ... * * @param pivots: XPVPivot instance ... * @return ( int ) */ int FindOldestPivotIndex( XPVPivot &pivots[] // ) { // int result = -1; // int count = ArraySize(pivots); if (!IsValidSize(count)) { return result; } // for (int i = 0; i < count; i++) { // XPVPivot iPivot = pivots[i]; // bool isOldest = true; for (int j = 0; j < count; j++) { // XPVPivot jPivot = pivots[j]; // isOldest = iPivot.from <= jPivot.from; if (!isOldest) { break; } } // if (isOldest) { // result = i; break; } } // return result; } /** * Sort Pivots Based On From Date ... * * @param pivots: XPVPivot instance Collection reference ... */ void SortPivots( XPVPivot &pivots[] // ) { // XPVPivot tmp[]; Copy( pivots, tmp // ); // Clean(pivots); // while (ArraySize(tmp) > 0) { // if (ArraySize(tmp) == 1) { // AddRef( tmp[0], pivots // ); // ArrayRemove( tmp, 0, 1); } else { // int idx = FindOldestPivotIndex(tmp); if (IsValidIndex(idx)) { // AddRef( tmp[idx], pivots // ); // ArrayRemove( tmp, idx, 1 // ); } } } // Clean(tmp); } bool IsPivotBreaked( XPVPivot &pivot, XPVPivot &pivots[] // ) { // bool result = false; // result = pivot.IsValid(); if (!result) { return result; } // int count = ArraySize(pivots); result = IsValidSize(pivots); if (!result) { return result; } // // For Peaks Highs Must not Broked ... // For Vales Lows Must not Broked ... bool isPeak = pivot.IsPeak(); // for (int i = 0; i < count; i++) { // XPVPivot iPivot = pivots[i]; // result = isPeak ? iPivot.upper > pivot.upper : iPivot.lower < pivot.lower; if (result) { break; } } // return result; } /** * Filter Broken Pivots for Detect Order Flow ... * * @param pivots: XPVPivot instance Collection reference ... */ void FilterBrokenPivots( XPVPivot &pivots[] // ) { // XPVPivot tmp[]; Copy( pivots, tmp // ); // Clean(pivots); // while (ArraySize(tmp) > 0) { // if (ArraySize(tmp) == 1) { // AddRef( tmp[0], pivots // ); // ArrayRemove( tmp, 0, 1 // ); } else { // XPVPivot pivot = tmp[0]; // ArrayRemove( tmp, 0, 1 // ); // bool isBreaked = IsPivotBreaked( pivot, tmp // ); if (!isBreaked) { // AddRef( pivot, pivots // ); } } } // Clean(tmp); } /** * Calculate Order Flow Direction ... * * @param orderFlow: XPVPivot instance Collection reference ... * @param dir: ENUM_X_DIRECTION member reference, Hold's Calculated Direction ... * * @return ( bool ) */ bool DetectPivotDirection( XPVPivot &orderFlow[], ENUM_X_DIRECTION &dir // ) { // bool result = false; // dir = X_DIRECTION_NONE; // int count = ArraySize(orderFlow); result = IsValidSize(count); if (!result) { return result; } // // For Bullish Direction all Exists lowers must be Greater or Equal Prev ... bool isBullish = false; bool canLookupForBullish = true; // // For Bearish Direction all Exists uppers must be Lesser or Equal Prev ... bool isBearish = false; bool canLookupForBearish = true; // for (int i = 0; i < count; i++) { // XPVPivot iPivot = orderFlow[i]; // XPVPivot tmp[]; Copy( orderFlow, tmp // ); ArrayRemove( tmp, 0, i + 1 // ); // int tmpCount = ArraySize(tmp); if (IsValidSize(tmpCount)) { // for (int j = 0; j < tmpCount; j++) { // XPVPivot jPivot = tmp[j]; // // Check Bullish Direction ... isBullish = canLookupForBullish && jPivot.lower >= iPivot.lower; if (!isBullish) { canLookupForBullish = false; } // // Check Bearish Direction ... isBearish = canLookupForBearish && jPivot.upper <= iPivot.upper; if (!isBearish) { canLookupForBearish = false; } // if (!canLookupForBullish && !canLookupForBearish) { break; } } } Clean(tmp); } // if (isBullish && !isBearish) { dir = X_DIRECTION_BULLISH; } else if (isBearish && !isBullish) { dir = X_DIRECTION_BEARISH; } // result = dir != X_DIRECTION_NONE; // return result; } /** * Detect all POIs which inside a Pivot ... * * @param pivot: XPVPivot instance, Specified Pivot ... * @param source: XPOIState instance, Reference to Source State ... * @param state: XPOIState instance, Reference to Detected Pivots ... * @param lookupSwingHighs: Boolean ... * @param lookupSwingLows: Boolean ... * @param lookupSupportZones: Boolean ... * @param lookupResistanceZones: Boolean ... * @param lookupSupplyZones: Boolean ... * @param lookupDemandZones: Boolean ... * @param lookupBullishOrderBlocks: Boolean ... * @param lookupBearishOrderBlocks: Boolean ... * @param lookupBullishFairValueGaps: Boolean ... * @param lookupBearishFairValueGaps: Boolean ... * @param lookupBullishRejectionBars: Boolean ... * @param lookupBearishRejectionBars: Boolean ... * @param lookupBullishMomentumBars: Boolean ... * @param lookupBearishMomentumBars: Boolean ... */ void DetectPivotPOIs( XPVPivot &pivot, XPOIState &source, XPOIState &state, bool lookupSwingHighs = true, bool lookupSwingLows = true, bool lookupSupportZones = true, bool lookupResistanceZones = true, bool lookupSupplyZones = true, bool lookupDemandZones = true, bool lookupBullishOrderBlocks = true, bool lookupBearishOrderBlocks = true, bool lookupBullishFairValueGaps = true, bool lookupBearishFairValueGaps = true, bool lookupBullishRejectionBars = true, bool lookupBearishRejectionBars = true, bool lookupBullishMomentumBars = true, bool lookupBearishMomentumBars = true // ) { // state.Clean(); // if (!pivot.IsValid()) { return; } // int count = 0; // state.symbol = pivot.symbol; state.period = pivot.period; state.time = TimeCurrent(); // // Swings ... // // Swing High ... if (lookupSwingHighs) { // count = ArraySize(source.swingHighs); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCSwing *iSwing = source.swingHighs[i]; // XOHCL iBar; bool isFilled = iSwing.FillBar(iBar); if (!isFilled) { continue; } // bool isInside = iBar.high <= pivot.upper; if (isInside) { // // iSwing.To(pivot.to); // Add( iSwing, state.swingHighs // ); } } } } // // Swing Low ... if (lookupSwingLows) { // count = ArraySize(source.swingLows); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCSwing *iSwing = source.swingLows[i]; // XOHCL iBar; bool isFilled = iSwing.FillBar(iBar); if (!isFilled) { continue; } // bool isInside = iBar.low >= pivot.lower; if (isInside) { // // iSwing.To(pivot.to); // Add( iSwing, state.swingLows // ); } } } } // // Support and Resistance Zones ... // // Support Zones ... if (lookupSupportZones) { // count = ArraySize(source.supportZones); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCSupportZone *iZone = source.supportZones[i]; // bool isInside = iZone.Upper() <= pivot.upper && iZone.Lower() >= pivot.lower; if (isInside) { // iZone.To(pivot.to); // Add( iZone, state.supportZones // ); } } } } // // Resistance Zones ... if (lookupResistanceZones) { // count = ArraySize(source.resistanceZones); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCResistanceZone *iZone = source.resistanceZones[i]; // bool isInside = iZone.Upper() <= pivot.upper && iZone.Lower() >= pivot.lower; if (isInside) { // iZone.To(pivot.to); // Add( iZone, state.resistanceZones // ); } } } } // // Supply and Demand Zones ... // // Supply Zones ... if (lookupSupplyZones) { // count = ArraySize(source.supplyZones); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCSupplyZone *iZone = source.supplyZones[i]; // bool isInside = iZone.Upper() <= pivot.upper && iZone.Lower() >= pivot.lower; if (isInside) { // iZone.To(pivot.to); // Add( iZone, state.supplyZones // ); } } } } // // Demand Zones ... if (lookupDemandZones) { // count = ArraySize(source.demandZones); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCDemandZone *iZone = source.demandZones[i]; // bool isInside = iZone.Upper() <= pivot.upper && iZone.Lower() >= pivot.lower; if (isInside) { // iZone.To(pivot.to); // Add( iZone, state.demandZones // ); } } } } // // Order Blocks ... // // Bullish Order Blocks ... if (lookupBullishOrderBlocks) { // count = ArraySize(source.bullishOrderBlocks); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCOrderBlock *iZone = source.bullishOrderBlocks[i]; // bool isInside = iZone.Upper() <= pivot.upper && iZone.Lower() >= pivot.lower; if (isInside) { // iZone.To(pivot.to); // Add( iZone, state.bullishOrderBlocks // ); } } } } // // Bearish Order Blocks ... if (lookupBearishOrderBlocks) { // count = ArraySize(source.bearishOrderBlocks); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCOrderBlock *iZone = source.bearishOrderBlocks[i]; // bool isInside = iZone.Upper() <= pivot.upper && iZone.Lower() >= pivot.lower; if (isInside) { // iZone.To(pivot.to); // Add( iZone, state.bearishOrderBlocks // ); } } } } // // Fair Value Gaps ... // // Bullish Fair Value Gaps ... if (lookupBullishFairValueGaps) { // count = ArraySize(source.bullishFairValueGaps); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCFVG *iZone = source.bullishFairValueGaps[i]; // bool isInside = iZone.Upper() <= pivot.upper && iZone.Lower() >= pivot.lower; if (isInside) { // iZone.To(pivot.to); // Add( iZone, state.bullishFairValueGaps // ); } } } } // // Bearish Fair Value Gaps ... if (lookupBearishFairValueGaps) { // count = ArraySize(source.bearishFairValueGaps); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCFVG *iZone = source.bearishFairValueGaps[i]; // bool isInside = iZone.Upper() <= pivot.upper && iZone.Lower() >= pivot.lower; if (isInside) { // iZone.To(pivot.to); // Add( iZone, state.bearishFairValueGaps // ); } } } } // // Rejection Bars ... // // Bullish Rejection Bars ... if (lookupBullishRejectionBars) { // count = ArraySize(source.bullishRejectionBars); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCRejectionBar *iRejection = source.bullishRejectionBars[i]; // XOHCL iBar; bool isFilled = iRejection.FillBar(iBar); if (!isFilled) { continue; } // bool isInside = iBar.low <= pivot.upper && iBar.low >= pivot.lower; if (isInside) { // iRejection.To(pivot.to); // Add( iRejection, state.bullishRejectionBars // ); } } } } // // Bearish Rejection Bars ... if (lookupBearishRejectionBars) { // count = ArraySize(source.bearishRejectionBars); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCRejectionBar *iRejection = source.bearishRejectionBars[i]; // XOHCL iBar; bool isFilled = iRejection.FillBar(iBar); if (!isFilled) { continue; } // bool isInside = iBar.high <= pivot.upper && iBar.high >= pivot.lower; if (isInside) { // iRejection.To(pivot.to); // Add( iRejection, state.bearishRejectionBars // ); } } } } // // Momentum Bars ... // // Bullish Momentum Bars ... if (lookupBullishMomentumBars) { // count = ArraySize(source.bullishMomentumBars); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCMomentumBar *iMomentum = source.bullishMomentumBars[i]; // XOHCL iBar; bool isFilled = iMomentum.FillBar(iBar); if (!isFilled) { continue; } // bool isInside = iBar.low <= pivot.upper && iBar.low >= pivot.lower; if (isInside) { // iMomentum.To(pivot.to); // Add( iMomentum, state.bullishMomentumBars // ); } } } } // // Bearish Momenum Bars ... if (lookupBearishMomentumBars) { // count = ArraySize(source.bearishMomentumBars); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCMomentumBar *iMomentum = source.bearishMomentumBars[i]; // XOHCL iBar; bool isFilled = iMomentum.FillBar(iBar); if (!isFilled) { continue; } // bool isInside = iBar.high <= pivot.upper && iBar.high >= pivot.lower; if (isInside) { // iMomentum.To(pivot.to); // Add( iMomentum, state.bearishMomentumBars // ); } } } } } /** * Fill Pivot Tick Zone ... * * @param pivot: XPVPivot instance Reference ... */ void CalculatePivotTickZone( XPVPivot &pivot, int ticksLevels, int ticksRange, ENUM_TIMEFRAMES _period = NULL // ) { // string symbol = pivot.symbol; ENUM_TIMEFRAMES period = IsValid(_period) ? _period : pivot.period; // bool isInited = false; // datetime from = pivot.from; XOHCL iFromBar; int iFromBarIndex = iBarShift( symbol, period, from // ); isInited = iFromBar.Init( symbol, period, iFromBarIndex // ); if (!isInited) { return; } // datetime to = pivot.to; XOHCL iToBar; int iToBarIndex = iBarShift( symbol, period, to // ); isInited = iToBar.Init( symbol, period, iToBarIndex // ); if (!isInited) { return; } // if (iFromBarIndex <= iToBarIndex) { return; } // XCTicksZone *iZone; iZone = new XCTicksZone(); // isInited = ticksLevels > 0 && ticksRange > 0; if (!isInited) { return; } // isInited = iZone.Init( iFromBar, iToBar // ); if (!isInited) { return; } // pivot.state.ticksZone = iZone; } /** * Filter State based on Pivot ... * * @param pivot: XPVPivot instance Reference ... * @param state: XPOIState instance Reference ... */ void FilterPivotState( XPVPivot &pivot, XPOIState &state // ) { // bool isValid = pivot.IsValid() && state.IsValid() && state.HasChild(); if (!isValid) { return; } // int count = 0; // double upper = pivot.upper; double lower = pivot.lower; // // // // // Resistance ... count = state.CountResistanceZones(); if (IsValidSize(count)) { // XCResistanceZone *tmp[]; Copy( state.resistanceZones, tmp // ); // for (int i = 0; i < count; i++) { // XCResistanceZone *item = tmp[i]; // bool isValid = IsPriceInsideZone( upper, item // ); if (!isValid) { // ArrayRemove( state.resistanceZones, i, 1 // ); } } // ArrayFree(tmp); } // // Supply ... count = state.CountSupplyZones(); if (IsValidSize(count)) { // XCSupplyZone *tmp[]; Copy( state.supplyZones, tmp // ); // for (int i = 0; i < count; i++) { // XCSupplyZone *item = tmp[i]; // bool isValid = IsPriceInsideZone( upper, item // ); if (!isValid) { // ArrayRemove( state.supplyZones, i, 1 // ); } } // ArrayFree(tmp); } // // Bearish Order Block ... count = state.CountBearishOrderBlocks(); if (IsValidSize(count)) { // XCOrderBlock *tmp[]; Copy( state.bearishOrderBlocks, tmp // ); // for (int i = 0; i < count; i++) { // XCOrderBlock *item = tmp[i]; // bool isValid = IsPriceInsideZone( upper, item // ); if (!isValid) { // ArrayRemove( state.bearishOrderBlocks, i, 1 // ); } } // ArrayFree(tmp); } // // Bearish Fair Value Gap ... count = state.CountBearishFairValueGaps(); if (IsValidSize(count)) { // XCFVG *tmp[]; Copy( state.bearishFairValueGaps, tmp // ); // for (int i = 0; i < count; i++) { // XCFVG *item = tmp[i]; // bool isValid = IsPriceInsideZone( upper, item // ); if (!isValid) { // ArrayRemove( state.bearishFairValueGaps, i, 1 // ); } } // ArrayFree(tmp); } // // // // // Support ... count = state.CountSupportZones(); if (IsValidSize(count)) { // XCSupportZone *tmp[]; Copy( state.supportZones, tmp // ); // for (int i = 0; i < count; i++) { // XCSupportZone *item = tmp[i]; // bool isValid = IsPriceInsideZone( lower, item // ); if (!isValid) { // ArrayRemove( state.supportZones, i, 1 // ); } } // ArrayFree(tmp); } // // Demand ... count = state.CountDemandZones(); if (IsValidSize(count)) { // XCDemandZone *tmp[]; Copy( state.demandZones, tmp // ); // for (int i = 0; i < count; i++) { // XCDemandZone *item = tmp[i]; // bool isValid = IsPriceInsideZone( lower, item // ); if (!isValid) { // ArrayRemove( state.demandZones, i, 1 // ); } } // ArrayFree(tmp); } // // Bullish Order Block ... count = state.CountBullishOrderBlocks(); if (IsValidSize(count)) { // XCOrderBlock *tmp[]; Copy( state.bullishOrderBlocks, tmp // ); // for (int i = 0; i < count; i++) { // XCOrderBlock *item = tmp[i]; // bool isValid = IsPriceInsideZone( lower, item // ); if (!isValid) { // ArrayRemove( state.bullishOrderBlocks, i, 1 // ); } } // ArrayFree(tmp); } // // Bullish Fair Value Gap ... count = state.CountBullishFairValueGaps(); if (IsValidSize(count)) { // XCFVG *tmp[]; Copy( state.bullishFairValueGaps, tmp // ); // for (int i = 0; i < count; i++) { // XCFVG *item = tmp[i]; // bool isValid = IsPriceInsideZone( lower, item // ); if (!isValid) { // ArrayRemove( state.bullishFairValueGaps, i, 1 // ); } } // ArrayFree(tmp); } } /** * Detect Box Date of Specified Pivot ... */ bool DetectPivotStateBoxData( XPVPivot &pivot, double &peakUpper, double &peakLower, datetime &peakFrom, datetime &peakTo, double &valeUpper, double &valeLower, datetime &valeFrom, datetime &valeTo // ) { // bool result = false; // peakUpper = 0; peakLower = 0; valeUpper = 0; valeLower = 0; // peakFrom = NULL; peakTo = NULL; valeFrom = NULL; valeTo = NULL; // result = pivot.IsValid(); if (!result) { return result; } // int count = 0; // // // // // Resistance ... count = pivot.state.CountResistanceZones(); if (IsValidSize(count)) { // XCResistanceZone *tmp[]; Copy( pivot.state.resistanceZones, tmp // ); // for (int i = 0; i < count; i++) { // XCResistanceZone *item = tmp[i]; // if (peakUpper == 0 || peakUpper < item.Upper()) { peakUpper = item.Upper(); } // if (peakLower == 0 || peakLower > item.Lower()) { peakLower = item.Lower(); } // if (!IsValid(peakFrom) || peakFrom > item.From()) { peakFrom = item.From(); } // if (!IsValid(peakTo) || peakTo < item.To()) { peakTo = item.To(); } } // ArrayFree(tmp); } // // Supply ... count = pivot.state.CountSupplyZones(); if (IsValidSize(count)) { // XCSupplyZone *tmp[]; Copy( pivot.state.supplyZones, tmp // ); // for (int i = 0; i < count; i++) { // XCSupplyZone *item = tmp[i]; // if (peakUpper == 0 || peakUpper < item.Upper()) { peakUpper = item.Upper(); } // if (peakLower == 0 || peakLower > item.Lower()) { peakLower = item.Lower(); } // if (!IsValid(peakFrom) || peakFrom > item.From()) { peakFrom = item.From(); } // if (!IsValid(peakTo) || peakTo < item.To()) { peakTo = item.To(); } } // ArrayFree(tmp); } // // Bearish Order Block ... count = pivot.state.CountBearishOrderBlocks(); if (IsValidSize(count)) { // XCOrderBlock *tmp[]; Copy( pivot.state.bearishOrderBlocks, tmp // ); // for (int i = 0; i < count; i++) { // XCOrderBlock *item = tmp[i]; // if (peakUpper == 0 || peakUpper < item.Upper()) { peakUpper = item.Upper(); } // if (peakLower == 0 || peakLower > item.Lower()) { peakLower = item.Lower(); } // if (!IsValid(peakFrom) || peakFrom > item.From()) { peakFrom = item.From(); } // if (!IsValid(peakTo) || peakTo < item.To()) { peakTo = item.To(); } } // ArrayFree(tmp); } // // Bearish Fair Value Gap ... count = pivot.state.CountBearishFairValueGaps(); if (IsValidSize(count)) { // XCFVG *tmp[]; Copy( pivot.state.bearishFairValueGaps, tmp // ); // for (int i = 0; i < count; i++) { // XCFVG *item = tmp[i]; // if (peakUpper == 0 || peakUpper < item.Upper()) { peakUpper = item.Upper(); } // if (peakLower == 0 || peakLower > item.Lower()) { peakLower = item.Lower(); } // if (!IsValid(peakFrom) || peakFrom > item.From()) { peakFrom = item.From(); } // if (!IsValid(peakTo) || peakTo < item.To()) { peakTo = item.To(); } } // ArrayFree(tmp); } // // // // // Support ... count = pivot.state.CountSupportZones(); if (IsValidSize(count)) { // XCSupportZone *tmp[]; Copy( pivot.state.supportZones, tmp // ); // for (int i = 0; i < count; i++) { // XCSupportZone *item = tmp[i]; // if (valeUpper == 0 || valeUpper < item.Upper()) { valeUpper = item.Upper(); } // if (valeLower == 0 || valeLower > item.Lower()) { valeLower = item.Lower(); } // if (!IsValid(valeFrom) || valeFrom > item.From()) { valeFrom = item.From(); } // if (!IsValid(valeTo) || valeTo < item.To()) { valeTo = item.To(); } } // ArrayFree(tmp); } // // Demand ... count = pivot.state.CountDemandZones(); if (IsValidSize(count)) { // XCDemandZone *tmp[]; Copy( pivot.state.demandZones, tmp // ); // for (int i = 0; i < count; i++) { // XCDemandZone *item = tmp[i]; // if (valeUpper == 0 || valeUpper < item.Upper()) { valeUpper = item.Upper(); } // if (valeLower == 0 || valeLower > item.Lower()) { valeLower = item.Lower(); } // if (!IsValid(valeFrom) || valeFrom > item.From()) { valeFrom = item.From(); } // if (!IsValid(valeTo) || valeTo < item.To()) { valeTo = item.To(); } } // ArrayFree(tmp); } // // Bullish Order Block ... count = pivot.state.CountBullishOrderBlocks(); if (IsValidSize(count)) { // XCOrderBlock *tmp[]; Copy( pivot.state.bullishOrderBlocks, tmp // ); // for (int i = 0; i < count; i++) { // XCOrderBlock *item = tmp[i]; // if (valeUpper == 0 || valeUpper < item.Upper()) { valeUpper = item.Upper(); } // if (valeLower == 0 || valeLower > item.Lower()) { valeLower = item.Lower(); } // if (!IsValid(valeFrom) || valeFrom > item.From()) { valeFrom = item.From(); } // if (!IsValid(valeTo) || valeTo < item.To()) { valeTo = item.To(); } } // ArrayFree(tmp); } // // Bullish Fair Value Gap ... count = pivot.state.CountBullishFairValueGaps(); if (IsValidSize(count)) { // XCFVG *tmp[]; Copy( pivot.state.bullishFairValueGaps, tmp // ); // for (int i = 0; i < count; i++) { // XCFVG *item = tmp[i]; // if (valeUpper == 0 || valeUpper < item.Upper()) { valeUpper = item.Upper(); } // if (valeLower == 0 || valeLower > item.Lower()) { valeLower = item.Lower(); } // if (!IsValid(valeFrom) || valeFrom > item.From()) { valeFrom = item.From(); } // if (!IsValid(valeTo) || valeTo < item.To()) { valeTo = item.To(); } } // ArrayFree(tmp); } // result = peakUpper > 0 && peakLower > 0 && valeUpper > 0 && valeLower > 0 && IsValid(peakTo) && IsValid(valeTo) && IsValid(peakFrom) && IsValid(valeFrom) && peakTo > peakFrom && valeTo > valeFrom && peakUpper > peakLower && valeUpper > valeLower; // return result; } /** * Detect Price Inside Zones ... * * @param state: XPOIState instance Reference ... * @param bar: XOHCL instance Reference ... * @param hasSupport: Boolean ... * @param hasResistanceZone: Boolean ... * @param hasSupplyZone: Boolean ... * @param hasDemandZone: Boolean ... * @param hasOrderBlock: Boolean ... * @param hasFairValueGap: Boolean ... * @return ( bool ) */ bool DetectPriceInsideZones( XPOIState &state, XOHCL &bar, int &zonesCount, bool &hasSupportZone, XCSupportZone *&supportZone, bool &hasResistanceZone, XCResistanceZone *&resistanceZone, bool &hasSupplyZone, XCSupplyZone *&supplyZone, bool &hasDemandZone, XCDemandZone *&demandZone, bool &hasOrderBlock, XCOrderBlock *&orderBlock, bool &hasFairValueGap, XCFVG *&fairValueGap // ) { // bool result = false; // zonesCount = 0; // hasSupportZone = false; hasResistanceZone = false; hasSupplyZone = false; hasDemandZone = false; hasOrderBlock = false; hasFairValueGap = false; // supportZone = NULL; resistanceZone = NULL; supplyZone = NULL; demandZone = NULL; orderBlock = NULL; fairValueGap = NULL; // datetime cTime = TimeCurrent(); // result = bar.IsValid() && state.IsValid() && state.HasChild(); if (!result) { return result; } // int count = 0; // // Support Zone ... count = state.CountSupportZones(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCSupportZone *iZone = state.supportZones[i]; // bool isValid = IsPriceInsideZone(bar, iZone); if (isValid) { // supportZone = iZone; } } // hasSupportZone = supportZone != NULL && supportZone.IsValid(); if (hasSupportZone) { // zonesCount++; supportZone.To(cTime); } } // // Resistance Zone ... count = state.CountResistanceZones(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCResistanceZone *iZone = state.resistanceZones[i]; // bool isValid = IsPriceInsideZone(bar, iZone); if (isValid) { // resistanceZone = iZone; } } // hasResistanceZone = resistanceZone != NULL && resistanceZone.IsValid(); if (hasResistanceZone) { // zonesCount++; resistanceZone.To(cTime); } } // // Supply Zone ... count = state.CountSupplyZones(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCSupplyZone *iZone = state.supplyZones[i]; // bool isValid = IsPriceInsideZone(bar, iZone); if (isValid) { // supplyZone = iZone; } } // hasSupplyZone = supplyZone != NULL && supplyZone.IsValid(); if (hasSupplyZone) { // zonesCount++; supplyZone.To(cTime); } } // // Demand Zone ... count = state.CountDemandZones(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCDemandZone *iZone = state.demandZones[i]; // bool isValid = IsPriceInsideZone(bar, iZone); if (isValid) { // demandZone = iZone; } } // hasDemandZone = demandZone != NULL && demandZone.IsValid(); if (hasDemandZone) { // zonesCount++; demandZone.To(cTime); } } // // OrderBlock ... count = state.CountBullishOrderBlocks(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCOrderBlock *iZone = state.bullishOrderBlocks[i]; // bool isValid = IsPriceInsideZone(bar, iZone); if (isValid) { // orderBlock = iZone; } } // hasOrderBlock = orderBlock != NULL && orderBlock.IsValid(); if (hasOrderBlock) { // zonesCount++; orderBlock.To(cTime); } } if (!hasOrderBlock) { // count = state.CountBearishOrderBlocks(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCOrderBlock *iZone = state.bearishOrderBlocks[i]; // bool isValid = IsPriceInsideZone(bar, iZone); if (isValid) { // orderBlock = iZone; } } // hasOrderBlock = orderBlock != NULL && orderBlock.IsValid(); if (hasOrderBlock) { // zonesCount++; orderBlock.To(cTime); } } } // // Fair Value Gap ... count = state.CountBullishFairValueGaps(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCFVG *iZone = state.bullishFairValueGaps[i]; // bool isValid = IsPriceInsideZone(bar, iZone); if (isValid) { // fairValueGap = iZone; } } // hasFairValueGap = fairValueGap != NULL && fairValueGap.IsValid(); if (hasFairValueGap) { // zonesCount++; fairValueGap.To(cTime); } } if (!hasFairValueGap) { // count = state.CountBearishFairValueGaps(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCFVG *iZone = state.bearishFairValueGaps[i]; // bool isValid = IsPriceInsideZone(bar, iZone); if (isValid) { // fairValueGap = iZone; } } // hasFairValueGap = fairValueGap != NULL && fairValueGap.IsValid(); if (hasFairValueGap) { // zonesCount++; fairValueGap.To(cTime); } } } // result = // hasSupportZone || hasResistanceZone || hasSupplyZone || hasDemandZone || hasOrderBlock || hasFairValueGap // ; // return result; } /** * Detect Price Inside Zones ... * * @param state: XPOIState instance Reference ... * @param price: Double ... * @param hasSupport: Boolean ... * @param hasResistanceZone: Boolean ... * @param hasSupplyZone: Boolean ... * @param hasDemandZone: Boolean ... * @param hasOrderBlock: Boolean ... * @param hasFairValueGap: Boolean ... * @return ( bool ) */ bool DetectPriceInsideZones( XPOIState &state, double price, int &zonesCount, bool &hasSupportZone, XCSupportZone *&supportZone, bool &hasResistanceZone, XCResistanceZone *&resistanceZone, bool &hasSupplyZone, XCSupplyZone *&supplyZone, bool &hasDemandZone, XCDemandZone *&demandZone, bool &hasOrderBlock, XCOrderBlock *&orderBlock, bool &hasFairValueGap, XCFVG *&fairValueGap // ) { // bool result = false; // zonesCount = 0; // hasSupportZone = false; hasResistanceZone = false; hasSupplyZone = false; hasDemandZone = false; hasOrderBlock = false; hasFairValueGap = false; // supportZone = NULL; resistanceZone = NULL; supplyZone = NULL; demandZone = NULL; orderBlock = NULL; fairValueGap = NULL; // datetime cTime = TimeCurrent(); // result = price > 0 && state.IsValid() && state.HasChild(); if (!result) { return result; } // int count = 0; // // Support Zone ... count = state.CountSupportZones(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCSupportZone *iZone = state.supportZones[i]; // bool isValid = IsPriceInsideZone(price, iZone); if (isValid) { // supportZone = iZone; } } // hasSupportZone = supportZone != NULL && supportZone.IsValid(); if (hasSupportZone) { // zonesCount++; supportZone.To(cTime); } } // // Resistance Zone ... count = state.CountResistanceZones(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCResistanceZone *iZone = state.resistanceZones[i]; // bool isValid = IsPriceInsideZone(price, iZone); if (isValid) { // resistanceZone = iZone; } } // hasResistanceZone = resistanceZone != NULL && resistanceZone.IsValid(); if (hasResistanceZone) { // zonesCount++; resistanceZone.To(cTime); } } // // Supply Zone ... count = state.CountSupplyZones(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCSupplyZone *iZone = state.supplyZones[i]; // bool isValid = IsPriceInsideZone(price, iZone); if (isValid) { // supplyZone = iZone; } } // hasSupplyZone = supplyZone != NULL && supplyZone.IsValid(); if (hasSupplyZone) { // zonesCount++; supplyZone.To(cTime); } } // // Demand Zone ... count = state.CountDemandZones(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCDemandZone *iZone = state.demandZones[i]; // bool isValid = IsPriceInsideZone(price, iZone); if (isValid) { // demandZone = iZone; } } // hasDemandZone = demandZone != NULL && demandZone.IsValid(); if (hasDemandZone) { // zonesCount++; demandZone.To(cTime); } } // // OrderBlock ... count = state.CountBullishOrderBlocks(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCOrderBlock *iZone = state.bullishOrderBlocks[i]; // bool isValid = IsPriceInsideZone(price, iZone); if (isValid) { // orderBlock = iZone; } } // hasOrderBlock = orderBlock != NULL && orderBlock.IsValid(); if (hasOrderBlock) { // zonesCount++; orderBlock.To(cTime); } } if (!hasOrderBlock) { // count = state.CountBearishOrderBlocks(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCOrderBlock *iZone = state.bearishOrderBlocks[i]; // bool isValid = IsPriceInsideZone(price, iZone); if (isValid) { // orderBlock = iZone; } } // hasOrderBlock = orderBlock != NULL && orderBlock.IsValid(); if (hasOrderBlock) { // zonesCount++; orderBlock.To(cTime); } } } // // Fair Value Gap ... count = state.CountBullishFairValueGaps(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCFVG *iZone = state.bullishFairValueGaps[i]; // bool isValid = IsPriceInsideZone(price, iZone); if (isValid) { // fairValueGap = iZone; } } // hasFairValueGap = fairValueGap != NULL && fairValueGap.IsValid(); if (hasFairValueGap) { // zonesCount++; fairValueGap.To(cTime); } } if (!hasFairValueGap) { // count = state.CountBearishFairValueGaps(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCFVG *iZone = state.bearishFairValueGaps[i]; // bool isValid = IsPriceInsideZone(price, iZone); if (isValid) { // fairValueGap = iZone; } } // hasFairValueGap = fairValueGap != NULL && fairValueGap.IsValid(); if (hasFairValueGap) { // zonesCount++; fairValueGap.To(cTime); } } } // result = // hasSupportZone || hasResistanceZone || hasSupplyZone || hasDemandZone || hasOrderBlock || hasFairValueGap // ; // return result; } bool CalculatePriceInsideZones( XPriceZones &zone, XPOIState &state, double price // ) { // bool result = false; // zone.Clean(); // int zonesCount = 0; bool hasSupplyZone = false; bool hasDemandZone = false; bool hasOrderBlock = false; bool hasSupportZone = false; bool hasFairValueGap = false; bool hasResistanceZone = false; // result = DetectPriceInsideZones( state, price, zone.count, hasSupportZone, zone.supportZone, hasResistanceZone, zone.resistanceZone, hasSupplyZone, zone.supplyZone, hasDemandZone, zone.demandZone, hasOrderBlock, zone.orderBlock, hasFairValueGap, zone.fairValueGap // ); if (!result) { return result; } // zone.price = price; // result = zone.IsValid(); // return result; } bool CalculatePriceInsideZones( XPriceZones &zone, XPOIState &state, XOHCL &bar // ) { // bool result = false; // zone.Clean(); // int zonesCount = 0; bool hasSupplyZone = false; bool hasDemandZone = false; bool hasOrderBlock = false; bool hasSupportZone = false; bool hasFairValueGap = false; bool hasResistanceZone = false; // result = DetectPriceInsideZones( state, bar, zone.count, hasSupportZone, zone.supportZone, hasResistanceZone, zone.resistanceZone, hasSupplyZone, zone.supplyZone, hasDemandZone, zone.demandZone, hasOrderBlock, zone.orderBlock, hasFairValueGap, zone.fairValueGap // ); if (!result) { return result; } // zone.bar = bar; // result = zone.IsValid(); // return result; } /** * Calculate Zone by Providing Specified Data ... * * @param zones: XStateZone instance Reference ... * @param source: XPOIState instance Reference ... * @param upper: Double ... * @param lower: Double ... * @param from: DateTime ... * * @return ( bool ) */ bool CalculateStateZones( XStateZones &zones, XPOIState &source, double upper, double lower, datetime from // ) { // bool result = false; // zones.Clean(); // datetime cTime = TimeCurrent(); // result = // upper > 0 && lower > 0 && upper > lower && IsValid(from) && source.IsValid() && source.HasChild() // ; if (!result) { return result; } // int count = 0; // // Support ... count = source.CountSupportZones(); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCSupportZone *iZone = source.supportZones[i]; // double iUpper = iZone.Upper(); double iLower = iZone.Lower(); datetime iFrom = iZone.From(); // bool isAbove = iUpper > upper && iLower <= upper; // bool isInside = iUpper <= upper && iLower >= lower; // bool isBelow = iUpper >= lower && iLower < lower; // bool isValid = // iFrom > from && (isAbove || isBelow || isInside) // ; if (isValid) { // iZone.To(cTime); Add( iZone, zones.supportZones // ); } } } // // Resistance ... count = source.CountResistanceZones(); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCResistanceZone *iZone = source.resistanceZones[i]; // double iUpper = iZone.Upper(); double iLower = iZone.Lower(); datetime iFrom = iZone.From(); // bool isAbove = iUpper > upper && iLower <= upper; // bool isInside = iUpper <= upper && iLower >= lower; // bool isBelow = iUpper >= lower && iLower < lower; // bool isValid = // iFrom > from && (isAbove || isBelow || isInside) // ; if (isValid) { // iZone.To(cTime); Add( iZone, zones.resistanceZones // ); } } } // // Supply ... count = source.CountSupplyZones(); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCSupplyZone *iZone = source.supplyZones[i]; // double iUpper = iZone.Upper(); double iLower = iZone.Lower(); datetime iFrom = iZone.From(); // bool isAbove = iUpper > upper && iLower <= upper; // bool isInside = iUpper <= upper && iLower >= lower; // bool isBelow = iUpper >= lower && iLower < lower; // bool isValid = // iFrom > from && (isAbove || isBelow || isInside) // ; if (isValid) { // iZone.To(cTime); Add( iZone, zones.supplyZones // ); } } } // // Demand ... count = source.CountDemandZones(); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCDemandZone *iZone = source.demandZones[i]; // double iUpper = iZone.Upper(); double iLower = iZone.Lower(); datetime iFrom = iZone.From(); // bool isAbove = iUpper > upper && iLower <= upper; // bool isInside = iUpper <= upper && iLower >= lower; // bool isBelow = iUpper >= lower && iLower < lower; // bool isValid = // iFrom > from && (isAbove || isBelow || isInside) // ; if (isValid) { // iZone.To(cTime); Add( iZone, zones.demandZones // ); } } } // // Bullish OrderBlocks ... count = source.CountBullishOrderBlocks(); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCOrderBlock *iZone = source.bullishOrderBlocks[i]; // double iUpper = iZone.Upper(); double iLower = iZone.Lower(); datetime iFrom = iZone.From(); // bool isAbove = iUpper > upper && iLower <= upper; // bool isInside = iUpper <= upper && iLower >= lower; // bool isBelow = iUpper >= lower && iLower < lower; // bool isValid = // iFrom > from && (isAbove || isBelow || isInside) // ; if (isValid) { // iZone.To(cTime); Add( iZone, zones.bullishOrderBlocks // ); } } } // // Bearish OrderBlocks ... count = source.CountBearishOrderBlocks(); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCOrderBlock *iZone = source.bearishOrderBlocks[i]; // double iUpper = iZone.Upper(); double iLower = iZone.Lower(); datetime iFrom = iZone.From(); // bool isAbove = iUpper > upper && iLower <= upper; // bool isInside = iUpper <= upper && iLower >= lower; // bool isBelow = iUpper >= lower && iLower < lower; // bool isValid = // iFrom > from && (isAbove || isBelow || isInside) // ; if (isValid) { // iZone.To(cTime); Add( iZone, zones.bearishOrderBlocks // ); } } } // // Bullish FairValueGaps ... count = source.CountBullishFairValueGaps(); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCFVG *iZone = source.bullishFairValueGaps[i]; // double iUpper = iZone.Upper(); double iLower = iZone.Lower(); datetime iFrom = iZone.From(); // bool isAbove = iUpper > upper && iLower <= upper; // bool isInside = iUpper <= upper && iLower >= lower; // bool isBelow = iUpper >= lower && iLower < lower; // bool isValid = // iFrom > from && (isAbove || isBelow || isInside) // ; if (isValid) { // iZone.To(cTime); Add( iZone, zones.bullishFairValueGaps // ); } } } // // Bearish FairValueGaps ... count = source.CountBearishFairValueGaps(); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XCFVG *iZone = source.bearishFairValueGaps[i]; // double iUpper = iZone.Upper(); double iLower = iZone.Lower(); datetime iFrom = iZone.From(); // bool isAbove = iUpper > upper && iLower <= upper; // bool isInside = iUpper <= upper && iLower >= lower; // bool isBelow = iUpper >= lower && iLower < lower; // bool isValid = // iFrom > from && (isAbove || isBelow || isInside) // ; if (isValid) { // iZone.To(cTime); Add( iZone, zones.bearishFairValueGaps // ); } } } // result = zones.IsValid(); // return result; } /** * Add Value Change instance to Exists Collection if it's not Exists ... * * @param item: XValueChange instance Reference ... * @param items: XValueChange instance Array Reference ... * * @return ( int ) */ int AddIfNotExists( XValueChange &item, XValueChange &items[] // ) { // int result = 0; // result = item.IsValid(); if (!result) { return result; } // bool canAdd = false; int count = ArraySize(items); if (!IsValidSize(count)) { canAdd = true; } else { // XValueChange last; bool hasItem = GetLastItem( last, items // ); if (!hasItem) { canAdd = true; } else { // // Compare Last Item with Current ... canAdd = item.time > last.time; } } // // Add Item if Allowed ... if (canAdd) { // AddRef( item, items // ); } // result = ArraySize(items); // return result; } /** * Combine a Collection of States into dest ... * * @param dest: XPOIState instance ... * @param source: XPOIState Collection ... */ void CombineStates( XPOIState &dest, XPOIState &source[] // ) { // dest.Clean(); // int count = ArraySize(source); if (!IsValidSize(count)) { return; } // for (int i = 0; i < count; i++) { // XPOIState iState = source[i]; // if (dest.ticksZone == NULL) { dest.ticksZone = iState.ticksZone; } // Copy( iState.swingHighs, dest.swingHighs, false // ); // Copy( iState.swingLows, dest.swingLows, false // ); // Copy( iState.bullishMomentumBars, dest.bullishMomentumBars, false // ); // Copy( iState.bearishMomentumBars, dest.bearishMomentumBars, false // ); // Copy( iState.bullishRejectionBars, dest.bullishRejectionBars, false // ); // Copy( iState.bearishRejectionBars, dest.bearishRejectionBars, false // ); // Copy( iState.supportZones, dest.supportZones, false // ); // Copy( iState.resistanceZones, dest.resistanceZones, false // ); // Copy( iState.supplyZones, dest.supplyZones, false // ); // Copy( iState.demandZones, dest.demandZones, false // ); // Copy( iState.bullishOrderBlocks, dest.bullishOrderBlocks, false // ); // Copy( iState.bearishOrderBlocks, dest.bearishOrderBlocks, false // ); // Copy( iState.bullishFairValueGaps, dest.bullishFairValueGaps, false // ); // Copy( iState.bearishFairValueGaps, dest.bearishFairValueGaps, false // ); // } } /** * Check Price Above Specified Zone ... * * @param bar: XOHCL instance Reference ... * * @return ( bool ) */ bool IsPriceAboveZone( XOHCL &bar, XCZone *zone // ) { // bool result = false; // result = zone != NULL && bar.IsValid() && zone.IsValidBoundary(); if (!result) { return result; } // result = // bar.low > zone.Upper() // ; // return result; } /** * Check Price Above Specified Zone ... * * @return ( bool ) */ bool IsPriceAboveZone( double price, XCZone *zone // ) { // bool result = false; // result = price > 0 && zone != NULL && zone.IsValidBoundary(); if (!result) { return result; } // result = // price > zone.Upper() // ; // return result; } /** * Check Price Below Specified Zone ... * * @param bar: XOHCL instance Reference ... * * @return ( bool ) */ bool IsPriceBelowZone( XOHCL &bar, XCZone *zone // ) { // bool result = false; // result = zone != NULL && bar.IsValid() && zone.IsValidBoundary(); if (!result) { return result; } // result = // bar.high < zone.Lower() // ; // return result; } /** * Check Price Below Specified Zone ... * * @return ( bool ) */ bool IsPriceBelowZone( double price, XCZone *zone // ) { // bool result = false; // result = price > 0 && zone != NULL && zone.IsValidBoundary(); if (!result) { return result; } // result = // price < zone.Lower() // ; // return result; } /** * Check Price Inside Specified Zone ... * * @param bar: XOHCL instance Reference ... * * @return ( bool ) */ bool IsPriceInsideZone( XOHCL &bar, XCZone *zone // ) { // bool result = false; // result = zone != NULL && bar.IsValid() && zone.IsValidBoundary(); if (!result) { return result; } // result = // bar.low <= zone.Upper() // && // bar.low >= zone.Lower() // ; // return result; } bool IsPriceInsideZone( XOHCL &bar, double upper, double lower // ) { // bool result = false; // result = upper > 0 && lower > 0 && upper > lower && bar.IsValid(); if (!result) { return result; } // result = // bar.low <= upper // && // bar.low >= lower // ; // return result; } /** * Check Price Inside Specified Zone ... * * @return ( bool ) */ bool IsPriceInsideZone( double price, XCZone *zone // ) { // bool result = false; // result = price > 0 && zone != NULL && zone.IsValidBoundary(); if (!result) { return result; } // result = // price <= zone.Upper() // && // price >= zone.Lower() // ; // return result; } bool IsPriceInsideZone( double price, double upper, double lower // ) { // bool result = false; // result = price > 0 && upper > 0 && lower > 0 && upper > lower; if (!result) { return result; } // result = // price <= upper // && // price >= lower // ; // return result; } /** * Calculate Target for Specified Direction ... * * @param bar: XOHCL instance Reference ... * @param state: XPOIState instance Reference ... * @param forDir: ENUM_S_DIRECTION member ... * * @return ( double ) */ double CalculateTarget( XOHCL &bar, XPOIState &state, ENUM_X_DIRECTION forDir // ) { // double result = 0; // if (!state.IsValid() || !state.HasChild() || !HasDirection(forDir)) { return result; } // XCFVG *iFVG = NULL; XCOrderBlock *iOB = NULL; XCSupplyZone *iSupply = NULL; XCDemandZone *iDemand = NULL; XCSupportZone *iSupport = NULL; XCResistanceZone *iResistance = NULL; // bool hasOB = false; bool hasFVG = false; bool hasSupply = false; bool hasDemand = false; bool hasSupport = false; bool hasResistance = false; // int count = 0; // if (IsBearish(forDir)) { // // FVG ... count = state.CountBullishFairValueGaps(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCFVG *iZone = state.bullishFairValueGaps[i]; // bool isValid = IsPriceAboveZone( bar, iZone // ); if (isValid) { // iFVG = iZone; hasFVG = true; break; } } } // // OB ... count = state.CountBullishOrderBlocks(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCOrderBlock *iZone = state.bullishOrderBlocks[i]; // bool isValid = IsPriceAboveZone( bar, iZone // ); if (isValid) { // iOB = iZone; hasOB = true; break; } } } // // SUPPORT ... count = state.CountSupportZones(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCSupportZone *iZone = state.supportZones[i]; // bool isValid = IsPriceAboveZone( bar, iZone // ); if (isValid) { // iSupport = iZone; hasSupport = true; break; } } } // // DEMAND ... count = state.CountDemandZones(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCDemandZone *iZone = state.demandZones[i]; // bool isValid = IsPriceAboveZone( bar, iZone // ); if (isValid) { // iDemand = iZone; hasDemand = true; break; } } } // // Summary ... result = hasFVG ? iFVG.Upper() : hasOB ? iOB.Upper() : hasSupport ? iSupport.Upper() : hasDemand ? iDemand.Upper() : 0; if (hasFVG) { result = MathMax(result, iFVG.Upper()); } if (hasOB) { result = MathMax(result, iOB.Upper()); } if (hasSupport) { result = MathMax(result, iSupport.Upper()); } if (hasDemand) { result = MathMax(result, iDemand.Upper()); } } // if (IsBullish(forDir)) { // // FVG ... count = state.CountBearishFairValueGaps(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCFVG *iZone = state.bearishFairValueGaps[i]; // bool isValid = IsPriceBelowZone( bar, iZone // ); if (isValid) { // iFVG = iZone; hasFVG = true; break; } } } // // OB ... count = state.CountBearishOrderBlocks(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCOrderBlock *iZone = state.bearishOrderBlocks[i]; // bool isValid = IsPriceBelowZone( bar, iZone // ); if (isValid) { // iOB = iZone; hasOB = true; break; } } } // // RESISTANCE ... count = state.CountResistanceZones(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCResistanceZone *iZone = state.resistanceZones[i]; // bool isValid = IsPriceBelowZone( bar, iZone // ); if (isValid) { // iResistance = iZone; hasResistance = true; break; } } } // // SUPPLY ... count = state.CountSupplyZones(); if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCSupplyZone *iZone = state.supplyZones[i]; // bool isValid = IsPriceBelowZone( bar, iZone // ); if (isValid) { // iSupply = iZone; hasSupply = true; break; } } } // // Summary ... result = hasFVG ? iFVG.Lower() : hasOB ? iOB.Lower() : hasSupport ? iSupport.Lower() : hasDemand ? iDemand.Lower() : 0; if (hasFVG) { result = MathMin(result, iFVG.Lower()); } if (hasOB) { result = MathMin(result, iOB.Lower()); } if (hasSupport) { result = MathMin(result, iSupport.Lower()); } if (hasDemand) { result = MathMin(result, iDemand.Lower()); } } // return result; } /** * Detect Valid Order Blocks ... * * @param forDir: ENUM_X_DIRECTION member ... * @param source: XPOIState instance Reference ... * * @return ( int ) */ int DetectValidOrderBlocks( ENUM_X_DIRECTION forDir, XPOIState &source, XCOrderBlock *&orderBlocks[] // ) { // int result = 0; // Clean(orderBlocks); // bool isValid = // source.IsValid() && source.HasChild() && HasDirection(forDir) // ; if (!isValid) { return result; } // datetime cTime = TimeCurrent(); // XOHCL cBar; bool isInited = cBar.Init( source.symbol, source.period, 1 // ); if (!isInited) { return result; } // int count = 0; // // Bullish ... count = source.CountBullishOrderBlocks(); isValid = IsValidSize(count) && IsBullish(forDir); if (isValid) { // for (int i = 0; i < count; i++) { // XCOrderBlock *iOB = source.bullishOrderBlocks[i]; // // Update Order Block Time ... iOB.To(cTime); // // Check Order Block Validation ... isValid = IsValid( forDir, cBar.symbol, cBar.period, iOB.Upper(), iOB.Lower(), iOB.From(), iOB.To() // ); if (isValid) { // Add( iOB, orderBlocks // ); } } } // // Bearish ... count = source.CountBearishOrderBlocks(); isValid = IsValidSize(count) && IsBearish(forDir); if (isValid) { // for (int i = 0; i < count; i++) { // XCOrderBlock *iOB = source.bearishOrderBlocks[i]; // // Update Order Block Time ... iOB.To(cTime); // // Check Order Block Validation ... isValid = IsValid( forDir, cBar.symbol, cBar.period, iOB.Upper(), iOB.Lower(), iOB.From(), iOB.To() // ); if (isValid) { // Add( iOB, orderBlocks // ); } } } // result = ArraySize(orderBlocks); // return result; } /** * Detect Valid Fair Value Gaps ... * * @param forDir: ENUM_X_DIRECTION member ... * @param source: XPOIState instance Reference ... * * @return ( int ) */ int DetectValidFairValueGaps( ENUM_X_DIRECTION forDir, XPOIState &source, XCFVG *&fairValueGaps[] // ) { // int result = 0; // Clean(fairValueGaps); // bool isValid = // source.IsValid() && source.HasChild() && HasDirection(forDir) // ; if (!isValid) { return result; } // datetime cTime = TimeCurrent(); // XOHCL cBar; bool isInited = cBar.Init( source.symbol, source.period, 1 // ); if (!isInited) { return result; } // int count = 0; // // Bullish ... count = source.CountBullishFairValueGaps(); isValid = IsValidSize(count) && IsBullish(forDir); if (isValid) { // for (int i = 0; i < count; i++) { // XCFVG *iFVG = source.bullishFairValueGaps[i]; // // Update FVG Time ... iFVG.To(cTime); // // Check FVG Validation ... isValid = IsValid( forDir, cBar.symbol, cBar.period, iFVG.Upper(), iFVG.Lower(), iFVG.From(), iFVG.To() // ); if (isValid) { // Add( iFVG, fairValueGaps // ); } } } // // Bearish ... count = source.CountBearishFairValueGaps(); isValid = IsValidSize(count) && IsBearish(forDir); if (isValid) { // for (int i = 0; i < count; i++) { // XCFVG *iFVG = source.bearishFairValueGaps[i]; // // Update Order Block Time ... iFVG.To(cTime); // // Check Order Block Validation ... isValid = IsValid( forDir, cBar.symbol, cBar.period, iFVG.Upper(), iFVG.Lower(), iFVG.From(), iFVG.To() // ); if (isValid) { // Add( iFVG, fairValueGaps // ); } } } // result = ArraySize(fairValueGaps); // return result; } /** * Detect Valid Support Zones ... * * @param source: XPOIState instance ... * * @return ( int ) */ int DetectValidSupportZones( XPOIState &source, XCOrderBlock *&bullishOrderBlocks[], XCFVG *&bullishFairValueGaps[], XCSupportZone *&supportZones[] // ) { // int result = 0; // Clean(supportZones); // int obsCount = ArraySize(bullishOrderBlocks); int fvgsCount = ArraySize(bullishFairValueGaps); // bool isValid = // source.IsValid() && source.HasChild() && IsValidSize(obsCount + fvgsCount) // ; if (!isValid) { return result; } // int count = source.CountSupportZones(); for (int i = 0; i < count; i++) { // XCSupportZone *iZone = source.supportZones[i]; // bool isAdded = false; // for (int j = 0; j < obsCount; j++) { // XCOrderBlock *iOB = bullishOrderBlocks[j]; // bool isValid = // IsPriceInsideZone( iZone.Upper(), iOB.Upper(), iOB.Lower() // ) // || // IsPriceInsideZone( iZone.Lower(), iOB.Upper(), iOB.Lower() // ) // ; if (isValid) { // Add( iZone, supportZones // ); // isAdded = true; break; } } // if (isAdded) { continue; } // for (int j = 0; j < fvgsCount; j++) { // XCFVG *iFVG = bullishFairValueGaps[j]; // bool isValid = // IsPriceInsideZone( iZone.Upper(), iFVG.Upper(), iFVG.Lower() // ) // || // IsPriceInsideZone( iZone.Lower(), iFVG.Upper(), iFVG.Lower() // ) // ; if (isValid) { // Add( iZone, supportZones // ); // isAdded = true; break; } } } // result = ArraySize(supportZones); // return result; } /** * Detect Valid Resistance Zones ... * * @param source: XPOIState instance ... * * @return ( int ) */ int DetectValidResistanceZones( XPOIState &source, XCOrderBlock *&bearishOrderBlocks[], XCFVG *&bearishFairValueGaps[], XCResistanceZone *&resistanceZones[] // ) { // int result = 0; // Clean(resistanceZones); // int obsCount = ArraySize(bearishOrderBlocks); int fvgsCount = ArraySize(bearishFairValueGaps); // bool isValid = // source.IsValid() && source.HasChild() && IsValidSize(obsCount + fvgsCount) // ; if (!isValid) { return result; } // int count = source.CountResistanceZones(); for (int i = 0; i < count; i++) { // XCResistanceZone *iZone = source.resistanceZones[i]; // bool isAdded = false; // for (int j = 0; j < obsCount; j++) { // XCOrderBlock *iOB = bearishOrderBlocks[j]; // bool isValid = // IsPriceInsideZone( iZone.Upper(), iOB.Upper(), iOB.Lower() // ) // || // IsPriceInsideZone( iZone.Lower(), iOB.Upper(), iOB.Lower() // ) // ; if (isValid) { // Add( iZone, resistanceZones // ); // isAdded = true; break; } } // if (isAdded) { continue; } // for (int j = 0; j < fvgsCount; j++) { // XCFVG *iFVG = bearishFairValueGaps[j]; // bool isValid = // IsPriceInsideZone( iZone.Upper(), iFVG.Upper(), iFVG.Lower() // ) // || // IsPriceInsideZone( iZone.Lower(), iFVG.Upper(), iFVG.Lower() // ) // ; if (isValid) { // Add( iZone, resistanceZones // ); // isAdded = true; break; } } } // result = ArraySize(resistanceZones); // return result; } /** * Detect Valid Support Zones ... * * @param source: XPOIState instance ... * * @return ( int ) */ int DetectValidDemandZones( XPOIState &source, XCOrderBlock *&bullishOrderBlocks[], XCFVG *&bullishFairValueGaps[], XCDemandZone *&demandZones[] // ) { // int result = 0; // Clean(demandZones); // int obsCount = ArraySize(bullishOrderBlocks); int fvgsCount = ArraySize(bullishFairValueGaps); // bool isValid = // source.IsValid() && source.HasChild() && IsValidSize(obsCount + fvgsCount) // ; if (!isValid) { return result; } // int count = source.CountDemandZones(); for (int i = 0; i < count; i++) { // XCDemandZone *iZone = source.demandZones[i]; // bool isAdded = false; // for (int j = 0; j < obsCount; j++) { // XCOrderBlock *iOB = bullishOrderBlocks[j]; // bool isValid = // IsPriceInsideZone( iZone.Upper(), iOB.Upper(), iOB.Lower() // ) // || // IsPriceInsideZone( iZone.Lower(), iOB.Upper(), iOB.Lower() // ) // ; if (isValid) { // Add( iZone, demandZones // ); // isAdded = true; break; } } // if (isAdded) { continue; } // for (int j = 0; j < fvgsCount; j++) { // XCFVG *iFVG = bullishFairValueGaps[j]; // bool isValid = // IsPriceInsideZone( iZone.Upper(), iFVG.Upper(), iFVG.Lower() // ) // || // IsPriceInsideZone( iZone.Lower(), iFVG.Upper(), iFVG.Lower() // ) // ; if (isValid) { // Add( iZone, demandZones // ); // isAdded = true; break; } } } // result = ArraySize(demandZones); // return result; } /** * Detect Valid Resistance Zones ... * * @param source: XPOIState instance ... * * @return ( int ) */ int DetectValidSupplyZones( XPOIState &source, XCOrderBlock *&bearishOrderBlocks[], XCFVG *&bearishFairValueGaps[], XCSupplyZone *&supplyZones[] // ) { // int result = 0; // Clean(supplyZones); // int obsCount = ArraySize(bearishOrderBlocks); int fvgsCount = ArraySize(bearishFairValueGaps); // bool isValid = // source.IsValid() && source.HasChild() && IsValidSize(obsCount + fvgsCount) // ; if (!isValid) { return result; } // int count = source.CountSupplyZones(); for (int i = 0; i < count; i++) { // XCSupplyZone *iZone = source.supplyZones[i]; // bool isAdded = false; // for (int j = 0; j < obsCount; j++) { // XCOrderBlock *iOB = bearishOrderBlocks[j]; // bool isValid = // IsPriceInsideZone( iZone.Upper(), iOB.Upper(), iOB.Lower() // ) // || // IsPriceInsideZone( iZone.Lower(), iOB.Upper(), iOB.Lower() // ) // ; if (isValid) { // Add( iZone, supplyZones // ); // isAdded = true; break; } } // if (isAdded) { continue; } // for (int j = 0; j < fvgsCount; j++) { // XCFVG *iFVG = bearishFairValueGaps[j]; // bool isValid = // IsPriceInsideZone( iZone.Upper(), iFVG.Upper(), iFVG.Lower() // ) // || // IsPriceInsideZone( iZone.Lower(), iFVG.Upper(), iFVG.Lower() // ) // ; if (isValid) { // Add( iZone, supplyZones // ); // isAdded = true; break; } } } // result = ArraySize(supplyZones); // return result; } /** * Test Market for Detect Order Block FVG ... * * @param forDir: Direction * @param bullishOrderBlocks: Detected Bullish Order Blocks ... * @param bearishOrderBlocks: Detected Bearish Order Blocks ... * @param orderBlockState: Order Block Detection POIState ... * @param fairValueGapState: Fair Value Gap Detection POIState ... * @param barIndex: Bar Index ... * * @return ( bool ) */ bool DetectFVGOB( ENUM_X_DIRECTION &forDir, // Test For Specified Direction ... XFVGOrderBlock &bullishOrderBlocks[], // Bullish Order Blocks ... XFVGOrderBlock &bearishOrderBlocks[], // Bearish Order Blocks ... XPOIState &orderBlockState, // Order Block Detection TF POI(s) ... XPOIState &fairValueGapState, // Fair Value Gap Detection TF POI(s) ... int barIndex = 0 // Bar Index ... ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // forDir = X_DIRECTION_NONE; // // Validate Args ... result = orderBlockState.HasChild() && fairValueGapState.HasChild(); if (!result) { return result; } // string symbol = orderBlockState.symbol; ENUM_TIMEFRAMES period = orderBlockState.period; // // Retrieve Bars ... XOHCL triggerCBar; result = triggerCBar.Init( symbol, period, barIndex // ); // // Select Order Blocks Which Has Big Changes ... int count = 0; datetime cTime = TimeCurrent(); // XOHCL jBar; result = jBar.Init( fairValueGapState.symbol, fairValueGapState.period, barIndex // ); if (!result) { return result; } double jBarLL = jBar.FindLowest(3, MODE_LOW); double jBarHH = jBar.FindHighest(3, MODE_HIGH); // // Bullish ... int bullishOrderBlocksCount = orderBlockState.CountBullishOrderBlocks(); count = bullishOrderBlocksCount; if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCFVG *iFVG = NULL; XStateZones iStateZones; XCOrderBlock *iOb = orderBlockState.bullishOrderBlocks[i]; iOb.To(cTime); // // Find Exit Bar of Bullish OrderBlock Upper ... XOHCL breakerBar; bool hasBreakerBar = iOb.DetectBreakerBar(breakerBar); if (!hasBreakerBar) { continue; } // // Detect Order Block is Hunted Or Not ... XOHCL huntedBar; bool isHunted = iOb.IsHunted(huntedBar); if (isHunted) { continue; } // // Check Validation of Order Block ... bool isValid = iOb.IsValidOrderBlock(); if (!isValid) { continue; } // // Check Order Block Has Fair Value Gap ... int fvgsCount = fairValueGapState.CountBullishFairValueGaps(); bool hasFVG = IsValidSize(fvgsCount); if (!hasFVG) { continue; } // // Detect an FVG for Order Block ... for (int j = fvgsCount - 1; j >= 0; j--) { // XCFVG *jFVG = fairValueGapState.bullishFairValueGaps[j]; // bool isValid = // jFVG.IsBullish() && jBarLL > jFVG.Upper() && jBar.low > jFVG.Upper() && jFVG.From() >= iOb.From() && ((jFVG.Upper() > iOb.Upper() && jFVG.Lower() <= iOb.Upper()) || (jFVG.Upper() <= iOb.Upper() && jFVG.Lower() >= iOb.Lower())) // ; if (isValid) { // jFVG.To(cTime); iFVG = jFVG; break; } } // hasFVG = iFVG != NULL; result = hasFVG; if (!result) { continue; } // // // double upper = MathMax(iOb.Upper(), iFVG.Upper()); // double lower = MathMin(iOb.Lower(), iFVG.Lower()); // datetime from = iFVG.From(); // // // // Detect Price Zones ... // // Based On Decision State ... // bool hasStateZones = CalculateStateZones( // iStateZones, // decisionState, // upper, // lower, // from // // ); // result = hasStateZones; // if (!result) // { // continue; // } // XFVGOrderBlock iModel; iModel.orderBlock = iOb; iModel.fairValueGap = iFVG; // iModel.stateZones = iStateZones; // AddRef( iModel, bullishOrderBlocks // ); } } // // Bearish ... int bearishOrderBlocksCount = orderBlockState.CountBearishOrderBlocks(); count = bearishOrderBlocksCount; if (IsValidSize(count)) { // for (int i = count - 1; i >= 0; i--) { // XCFVG *iFVG = NULL; XStateZones iStateZones; XCOrderBlock *iOb = orderBlockState.bearishOrderBlocks[i]; iOb.To(cTime); // // Find Exit Bar of Bullish OrderBlock Upper ... XOHCL breakerBar; bool hasBreakerBar = iOb.DetectBreakerBar(breakerBar); if (!hasBreakerBar) { continue; } // // Detect Order Block is Hunted Or Not ... XOHCL huntedBar; bool isHunted = iOb.IsHunted(huntedBar); if (isHunted) { continue; } // // Check Validation of Order Block ... bool isValid = iOb.IsValidOrderBlock(); if (!isValid) { continue; } // // Check Order Block Has Fair Value Gap ... int fvgsCount = fairValueGapState.CountBearishFairValueGaps(); bool hasFVG = IsValidSize(fvgsCount); if (!hasFVG) { continue; } // // Detect an FVG for Order Block ... for (int j = fvgsCount - 1; j >= 0; j--) { // XCFVG *jFVG = fairValueGapState.bearishFairValueGaps[j]; // bool isValid = // jFVG.IsBearish() && jBarHH < jFVG.Lower() && jBar.high < jFVG.Lower() && jFVG.From() >= iOb.From() && ((jFVG.Upper() > iOb.Lower() && jFVG.Lower() <= iOb.Lower()) || (jFVG.Upper() <= iOb.Upper() && jFVG.Lower() >= iOb.Lower())) // ; if (isValid) { // jFVG.To(cTime); iFVG = jFVG; break; } } // hasFVG = iFVG != NULL; result = hasFVG; if (!result) { continue; } // double upper = MathMax(iOb.Upper(), iFVG.Upper()); double lower = MathMin(iOb.Lower(), iFVG.Lower()); datetime from = iFVG.From(); // // // // Detect Price Zones ... // // Based On Decision State ... // bool hasStateZones = CalculateStateZones( // iStateZones, // decisionState, // upper, // lower, // from // // ); // result = hasStateZones; // if (!result) // { // continue; // } // XFVGOrderBlock iModel; iModel.orderBlock = iOb; iModel.fairValueGap = iFVG; // iModel.stateZones = iStateZones; // AddRef( iModel, bearishOrderBlocks // ); } } // // Check Order Blocks ... bullishOrderBlocksCount = ArraySize(bullishOrderBlocks); bool hasBullishOrderBlocks = IsValidSize(bullishOrderBlocksCount); // // Check Order Blocks ... bearishOrderBlocksCount = ArraySize(bearishOrderBlocks); bool hasBearishOrderBlocks = IsValidSize(bearishOrderBlocksCount); // result = // hasBullishOrderBlocks || hasBearishOrderBlocks // ; if (!result) { return result; } // bool isBullish = hasBullishOrderBlocks && !hasBearishOrderBlocks; bool isBearish = hasBearishOrderBlocks && !hasBullishOrderBlocks; // forDir = isBullish ? X_DIRECTION_BULLISH : isBearish ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; // result = forDir != X_DIRECTION_NONE; if (!result) { return result; } // return result; } /** * Detect a Zone Breaker Bar ... * * @param toBar: XOHCL instance Reference ... * @param fromBar: XOHCL instance Reference ... * @param breakerBar: XOHCL instance Reference ... * @param forDir: ENUM_X_DIRECTION member ... * @param symbol: String ... * @param period: ENUM_TIMEFRAMES member ... * * @return ( bool ) */ bool HasBreakerBar( XOHCL &toBar, XOHCL &fromBar, XOHCL &breakerBar, ENUM_X_DIRECTION forDir, string symbol, ENUM_TIMEFRAMES period, double upper, double lower, datetime from, datetime to // ) { // bool result = false; // toBar.Clean(); fromBar.Clean(); breakerBar.Clean(); // result = // upper > 0 && lower > 0 && IsValid(to) && upper > lower && IsValid(from) && IsValid(symbol) && IsValid(period) && HasDirection(forDir) // ; if (!result) { return result; } // result = fromBar.Init( symbol, period, from // ); if (!result) { return result; } // result = toBar.Init( symbol, period, to // ); if (!result) { return result; } // int toIndex = toBar.Index(); int fromIndex = fromBar.Index(); // // Detect Zone BreakerBar ... for (int i = fromIndex; i >= toIndex; i--) { // XOHCL iBar; result = iBar.Init( symbol, period, i // ); // if (!result) { continue; } // result = // IsBullish(forDir) ? // iBar.low < upper && iBar.high > upper && iBar.GetUp() > upper // : // iBar.high > lower && iBar.low < lower && iBar.GetDown() < lower // ; if (result) { // breakerBar = iBar; break; } } // result = breakerBar.IsValid(); // return result; } /** * Validate Specified Order Block ... * * @param forDir: ENUM_X_DIRECTION member ... * @param symbol: String ... * @param period: ENUM_TIMEFRAMES member ... * * @return ( bool ) */ bool IsValid( ENUM_X_DIRECTION forDir, string symbol, ENUM_TIMEFRAMES period, double upper, double lower, datetime from, datetime to, bool ignoreBreakerBar = false // ) { // bool result = false; // result = upper > 0 && lower > 0 && IsValid(to) && upper > lower && IsValid(from) && IsValid(symbol) && IsValid(period) && HasDirection(forDir) // ; if (!result) { return result; } // XOHCL toBar; XOHCL fromBar; XOHCL breakerBar; // if (!ignoreBreakerBar) { // result = HasBreakerBar( toBar, fromBar, breakerBar, forDir, symbol, period, upper, lower, from, to // ); if (!result) { return result; } } else { // result = toBar.Init( symbol, period, to // ); if (!result) { return result; } // result = fromBar.Init( symbol, period, from // ); if (!result) { return result; } // breakerBar = fromBar; } // int toIndex = toBar.Index(); int fromIndex = fromBar.Index(); int breakerIndex = breakerBar.Index(); // bool isBreaked = false; for (int i = breakerIndex - 1; i >= toIndex; i--) { // XOHCL iBar; result = iBar.Init( fromBar.symbol, fromBar.period, i // ); // if (!result) { continue; } // isBreaked = // IsBullish(forDir) // ? // iBar.low < upper // : // iBar.high > lower // ; if (isBreaked) { break; } } // result = !isBreaked; // return result; } /** * Get Oldest Zone ... * * @return ( int ) */ int GetOldest( XCZone *&source[] // ) { // int result = -1; // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XCZone *oldest = NULL; for (int i = 0; i < count; i++) { // XCZone *iZone = source[i]; // bool canSet = oldest == NULL || (oldest != NULL && oldest.From() > iZone.From()); if (canSet) { // result = i; oldest = iZone; } } // return result; } /** * Get Youngest Zone ... * * @return ( int ) */ int GetYoungest( XCZone *&source[] // ) { // int result = -1; // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XCZone *youngest = NULL; for (int i = 0; i < count; i++) { // XCZone *iZone = source[i]; // bool canSet = youngest == NULL || (youngest != NULL && youngest.From() < iZone.From()); if (canSet) { // result = i; youngest = iZone; } } // return result; } template bool ToZone( T *&source[], XCZone *&dest[] // ) { // bool result = false; // Clean(dest); // int count = ArraySize(source); result = IsValidSize(count); if (!result) { return result; } // for (int i = 0; i < count; i++) { // T *item = source[i]; // if (item != NULL) { // Add( (XCZone *)item, dest // ); } } // int destCount = ArraySize(dest); result = IsValidSize(destCount); // return result; } // typedef void (*TOnPOIEvent)(ENUM_XPOI_EVENTS event, XCBasePOI *param // ); //