/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // -------------------------------------- // Name: XPOI // Description: Bar Analysing ... // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Imports ... #include "../Classes/x-saherelm.base.class.mq5" #include "../Libraries/x-saherelm.x-poi.lib.mq5" // // Definitions ... // // Implementations ... class XCBarAnalyser : public XSCBase { // public: // // // Constructor(s) ... void XCBarAnalyser() { } // // Deconstructor ... void ~XCBarAnalyser() { } // // Getter(s) / Setter(s) ... // // Providers ... // // Actions ... // // Commons ... /** * Check Specified Bar's Range is Extended or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param loopback: Integer, Loopback Length ... * * @return ( bool ) */ bool HasExtendedRange( XOHCL &bar, int loopback = 3 // ) { // bool result = false; // if (loopback < 3) { loopback = 3; } // result = bar.IsValid(); if (!result) { return result; } // int index = bar.Index(); int start = index + 1; int end = start + loopback; int count = end - start; result = count >= 1; if (!result) { return result; } // double sum = 0; XOHCL iBar = bar; for (int i = start; i < end; i++) { // bool isRetrieved = iBar.GetPreviousBar(iBar); if (!isRetrieved) { continue; } // sum += iBar.GetRange(); } // result = sum > 0; if (!result) { return result; } // double avg = sum / count; // result = bar.GetRange() >= avg; // return result; } /** * Check Specified Bar's Body is Extended or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param loopback: Integer, Loopback Length ... * * @return ( bool ) */ bool HasExtendedBody( XOHCL &bar, int loopback = 3 // ) { // bool result = false; // if (loopback < 3) { loopback = 3; } // result = bar.IsValid(); if (!result) { return result; } // int index = bar.Index(); int start = index + 1; int end = start + loopback; int count = end - start; result = count >= 1; if (!result) { return result; } // double sum = 0; XOHCL iBar = bar; for (int i = start; i < end; i++) { // bool isRetrieved = iBar.GetPreviousBar(iBar); if (!isRetrieved) { continue; } // sum += iBar.GetBody(); } // result = sum > 0; if (!result) { return result; } // double avg = sum / count; // result = bar.GetBody() >= avg; // return result; } /** * Check Specified Bar's Body and Range is Extended or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param loopback: Integer, Loopback Length ... * * @return ( bool ) */ bool IsExtended( XOHCL &bar, int loopback = 3 // ) { // bool result = false; // bool hasExtendedBody = HasExtendedBody(bar, loopback); bool hasExtendedRange = HasExtendedRange(bar, loopback); result = hasExtendedBody && hasExtendedRange; // return result; } /** * Converts an Specified Bar to Zone ... * * @param bar: XOHCL instance, Specified Bar ... * @param zone: XZone instance, Converted Zone Reference ... * @param dir: ENUM_X_DIRECTION member, Specified Bar Type to Convertion ... * * @return ( bool ) */ bool ToZone( XOHCL &bar, XZone &zone, ENUM_X_DIRECTION dir = X_DIRECTION_BULLISH // ) { // bool result = false; // zone.Clean(); // result = bar.IsValid() && (dir == X_DIRECTION_BULLISH || dir == X_DIRECTION_BEARISH); if (!result) { return result; } // bool isBullish = dir == X_DIRECTION_BULLISH; // zone.from = bar.time; zone.to = TimeCurrent(); zone.prefix = "XBarZone"; // zone.upper = isBullish ? bar.high : bar.GetDown(); // zone.lower = isBullish ? bar.GetUp() : bar.low; // result = zone.IsValid(); // return result; } // // Regular ... /** * Check a Zone is Rejected in Specified Direction or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param zone: XZone instance, Specified Zone ... * @param dir: ENUM_X_DIRECTION member, Specified Rejection Direction ... * * @return ( bool ) */ bool IsRejected( XOHCL &bar, XZone &zone, ENUM_X_DIRECTION dir // ) { // bool result = false; // result = bar.IsValid() && zone.IsValid() && (dir == X_DIRECTION_BULLISH || dir == X_DIRECTION_BEARISH); if (!result) { return result; } // bool isBullish = dir == X_DIRECTION_BULLISH; // ENUM_X_DIRECTION rejectionDir; bool isRejection = IsRejectionBar( rejectionDir, bar, 40 // ); bool isBullishRejection = isRejection && rejectionDir == X_DIRECTION_BULLISH; bool isBearishRejection = isRejection && rejectionDir == X_DIRECTION_BEARISH; // result = isRejection && rejectionDir == dir && (isBullishRejection ? bar.low < zone.upper && bar.low > zone.lower : bar.high > zone.lower && bar.high < zone.upper); // return result; } /** * Check a Zone is Breaked in Specified Direction or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param zone: XZone instance, Specified Zone ... * @param dir: ENUM_X_DIRECTION member, Specified Rejection Direction ... * * @return ( bool ) */ bool IsBreaked( XOHCL &bar, XZone &zone, ENUM_X_DIRECTION dir, bool forceBody = true // ) { // bool result = false; // result = bar.IsValid() && zone.IsValid() && (dir == X_DIRECTION_BULLISH || dir == X_DIRECTION_BEARISH); if (!result) { return result; } // bool isBullish = dir == X_DIRECTION_BULLISH; // ENUM_X_DIRECTION momentumDir; bool isMomentum = IsMomentumBar( momentumDir, bar, 50 // ); bool isBullishBreaked = isMomentum && momentumDir == X_DIRECTION_BULLISH; bool isBearishBreaked = isMomentum && momentumDir == X_DIRECTION_BEARISH; // result = isMomentum && momentumDir == dir && (isBullishBreaked ? bar.IsBullish() && bar.low < zone.lower && bar.high > zone.upper : bar.IsBearish() && bar.high > zone.lower && bar.low < zone.lower); if (result && forceBody) { // result = isBullishBreaked ? bar.IsBullish() && bar.GetUp() > zone.upper && bar.GetDown() < zone.lower : bar.IsBearish() && bar.GetUp() > zone.upper && bar.GetDown() < zone.lower; } // return result; } // // Rejection Bar ... /** * Check Specific Bar is Rejection Bar or not ... * * @param dir: ENUM_X_DIRECTION member, Specified Direction ... * @param bar: XOHCL instance, Specified Bar ... * @param strength: Double, Specified Shadow Percent Range ... * * @return ( bool ) */ bool IsRejectionBar( ENUM_X_DIRECTION &dir, XOHCL &bar, double strength // ) { // bool result = false; // if (strength < 20) { strength = 20; } // dir = X_DIRECTION_NONE; // result = bar.IsValid(); if (!result) { return result; } // double barLowShadow = bar.GetLowShadow(); double barHighShadow = bar.GetHighShadow(); double barRange = bar.GetRange(); double barRangePercent = barRange / 100; // bool isBullishRejectionBar = barLowShadow > barHighShadow && barLowShadow > barRangePercent * 40; // bool isBearishRejectionBar = barHighShadow > barLowShadow && barHighShadow > barRangePercent * 40; // result = isBullishRejectionBar || isBearishRejectionBar; if (result) { // dir = isBullishRejectionBar ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // return result; } /** * Check Specific Bar is Bullish Rejection Bar or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param strength: Double, Specified Shadow Percent Range ... * * @return ( bool ) */ bool IsBullishRejectionBar( XOHCL &bar, double strength = 40 // ) { // bool result = false; // ENUM_X_DIRECTION dir; result = IsRejectionBar( dir, bar, strength // ); result = result && dir == X_DIRECTION_BULLISH; // return result; } /** * Check Specific Bar is Bearish Rejection Bar or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param strength: Double, Specified Shadow Percent Range ... * * @return ( bool ) */ bool IsBearishRejectionBar( XOHCL &bar, double strength = 40 // ) { // bool result = false; // ENUM_X_DIRECTION dir; result = IsRejectionBar( dir, bar, strength // ); result = result && dir == X_DIRECTION_BEARISH; // return result; } // // Momentum Bar ... /** * Check Specific Bar is Momentum Bar or not ... * * @param dir: ENUM_X_DIRECTION member, Specified Direction ... * @param bar: XOHCL instance, Specified Bar ... * @param strength: Double, Specified Shadow Percent Range ... * * @return ( bool ) */ bool IsMomentumBar( ENUM_X_DIRECTION &dir, XOHCL &bar, double strength // ) { // bool result = false; // if (strength < 50) { strength = 50; } // dir = X_DIRECTION_NONE; // double rangePercent = GetBarRangePercent(bar); bool isStrong = bar.GetBody() > rangePercent * strength; // result = isStrong; if (result) { // dir = bar.IsBullish() ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // return result; } /** * Check Specific Bar is Bullish Momentum Bar or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param strength: Double, Specified Shadow Percent Range ... * * @return ( bool ) */ bool IsBullishMomentumBar( XOHCL &bar, double strength = 40 // ) { // bool result = false; // ENUM_X_DIRECTION dir; result = IsMomentumBar( dir, bar, strength // ); result = result && dir == X_DIRECTION_BULLISH; // return result; } /** * Check Specific Bar is Bearish Momentum Bar or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param strength: Double, Specified Shadow Percent Range ... * * @return ( bool ) */ bool IsBearishMomentumBar( XOHCL &bar, double strength = 40 // ) { // bool result = false; // ENUM_X_DIRECTION dir; result = IsMomentumBar( dir, bar, strength // ); result = result && dir == X_DIRECTION_BEARISH; // return result; } // // Engulfing ... /** * Check Bar is Engulfed or not ... * * @param dir: ENUM_X_DIRECTION member, Specified Direction ... * @param bar: XOHCL instance, Speciied Bar ... * @param loopback: Integer, loopback Length ... * * @return ( bool ) */ bool IsEngulfed( ENUM_X_DIRECTION &dir, XOHCL &bar, int loopback // ) { // bool result = false; // dir = X_DIRECTION_NONE; // int hhIDX = 0; double hh = 0; // int llIDX = 0; double ll = 0; // result = CalculateLoopbackHLData( hhIDX, hh, llIDX, ll, bar, loopback // ); if (!result) { return result; } // result = bar.GetDown() < ll && bar.GetUp() > hh; if (result) { // dir = bar.IsBullish() ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // return result; } /** * Check Bar is Bullish Engulfed or not ... * * @param bar: XOHCL instance, Speciied Bar ... * @param loopback: Integer, loopback Length ... * * @return ( bool ) */ bool IsBullishEngulfed( XOHCL &bar, int loopback = 2 // ) { // bool result = false; // ENUM_X_DIRECTION dir; result = IsEngulfed( dir, bar, loopback // ); result = result && dir == X_DIRECTION_BULLISH; // return result; } /** * Check Bar is Bearish Engulfed or not ... * * @param bar: XOHCL instance, Speciied Bar ... * @param loopback: Integer, loopback Length ... * * @return ( bool ) */ bool IsBearishEngulfed( XOHCL &bar, int loopback = 2 // ) { // bool result = false; // ENUM_X_DIRECTION dir; result = IsEngulfed( dir, bar, loopback // ); result = result && dir == X_DIRECTION_BEARISH; // return result; } // // Bar CHOCH ... /** * Check Specified Bar Has CHOCH or not ... * * @param dir: ENUM_X_DIRECTION member, Specified Direction ... * @param bar: XOHCL instance, Speciied Bar ... * @param loopback: Integer, loopback Length ... * @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ... * * @return ( bool ) */ bool HasCHOCH( ENUM_X_DIRECTION &dir, XOHCL &bar, int loopback = 2, bool forceBody = false // ) { // bool result = false; // dir = X_DIRECTION_NONE; // if (loopback < 1) { loopback = 1; } // result = bar.IsValid(); if (!result) { return result; } // string symbol = bar.symbol; ENUM_TIMEFRAMES period = bar.period; // // Calculate Loopback Data ... int index = -1; int start = -1; int end = -1; int count = -1; result = CalculateLoopBackData( index, start, end, count, bar, loopback // ); if (!result) { return result; } // // Calculate Loopback HH and LL Data ... int hhIDX = -1; double hh = -1; int llIDX = -1; double ll = -1; result = CalculateLoopbackHLData( hhIDX, hh, llIDX, ll, bar, loopback // ); if (!result) { return result; } // bool isBullishDirection = bar.high > hh && bar.low > ll; bool isBearishDirection = bar.high < hh && bar.low < ll; result = isBullishDirection || isBearishDirection; if (!result) { return result; } // if (forceBody) { // isBullishDirection = bar.GetUp() > hh && bar.GetDown() > ll; isBearishDirection = bar.GetUp() < hh && bar.GetDown() < ll; result = isBullishDirection || isBearishDirection; if (!result) { return result; } } // // Check Bar's Direction in related to CHOCH Direction ... result = isBullishDirection ? bar.IsBullish() : bar.IsBearish(); if (!result) { return result; } // // Set Direction ... dir = isBullishDirection ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // // Check Loopback End Bar ... XOHCL endBar; result = endBar.Init( symbol, period, end - 1 // ); if (!result) { return result; } // // End Bar Must be InDirect by Specified Bar ... result = isBullishDirection ? endBar.IsBearish() : endBar.IsBullish(); // // Check Loopback for Directional Bars ... // return result; } /** * Check Specified Bar Has Bullish CHOCH or not ... * * @param bar: XOHCL instance, Speciied Bar ... * @param loopback: Integer, loopback Length ... * @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ... * * @return ( bool ) */ bool HasBullishCHOCH( XOHCL &bar, int loopback = 2, bool forceBody = false // ) { // bool result = false; // ENUM_X_DIRECTION dir; result = HasCHOCH( dir, bar, loopback, forceBody // ); result = result && dir == X_DIRECTION_BULLISH; // return result; } /** * Check Specified Bar Has Bearish CHOCH or not ... * * @param bar: XOHCL instance, Speciied Bar ... * @param loopback: Integer, loopback Length ... * @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ... * * @return ( bool ) */ bool HasBearishCHOCH( XOHCL &bar, int loopback = 2, bool forceBody = false // ) { // bool result = false; // ENUM_X_DIRECTION dir; result = HasCHOCH( dir, bar, loopback, forceBody // ); result = result && dir == X_DIRECTION_BEARISH; // return result; } // // Directions ... /** * Check Specified Bar Possible Direction Pressure ... * * @param dir: ENUM_X_DIRECTION member ... * @param bar: XOHCL instance, Specified Bar ... * * @return ( bool ) */ bool HasDirection( ENUM_X_DIRECTION &dir, XOHCL &bar // ) { // bool result = false; // dir = X_DIRECTION_NONE; // result = bar.IsValid(); if (!result) { return result; } // // Check Bar isExtended or not ... bool isExtended = IsExtended( bar, 3 // ); // // Check Rejection ... ENUM_X_DIRECTION rejectionDir; bool isRejection = IsRejectionBar(rejectionDir, bar, 40); bool isBullishRejection = isRejection && rejectionDir == X_DIRECTION_BULLISH; bool isBearishRejection = isRejection && rejectionDir == X_DIRECTION_BEARISH; // // Check Momentum ... ENUM_X_DIRECTION momentumDir; bool isMomentum = IsMomentumBar(momentumDir, bar, 40); bool isBullisMomentumn = isMomentum && momentumDir == X_DIRECTION_BULLISH; bool isBearishMomentum = isMomentum && momentumDir == X_DIRECTION_BEARISH; // // Check Engulfing ... ENUM_X_DIRECTION engulfDir; bool isEngulfed = IsEngulfed( engulfDir, bar, 2 // ); bool isBullishEngulfed = isEngulfed && engulfDir == X_DIRECTION_BULLISH; bool isBearishEngulfed = isEngulfed && engulfDir == X_DIRECTION_BEARISH; // // Check CHOCH ... ENUM_X_DIRECTION chochDir; bool hasCHOCH = HasCHOCH( chochDir, bar, 2, false // ); bool hasBullishCHOCH = hasCHOCH && chochDir == X_DIRECTION_BULLISH; bool hasBearishCHOCH = hasCHOCH && chochDir == X_DIRECTION_BEARISH; // bool hasBullishDirection = // isExtended && (hasBullishCHOCH || isBullishEngulfed) && (isBullisMomentumn || isBullishRejection) // ; // bool hasBearishDirection = // isExtended && (hasBearishCHOCH || isBearishEngulfed) && (isBearishMomentum || isBearishRejection) // ; // result = hasBullishDirection || hasBearishDirection; if (result) { // dir = hasBullishDirection ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // return result; } /** * Check Specified Bar has Possibly Bullish Direction ... * * @param bar: XOHCL instance, Specified Bar ... * * @return ( virtual bool ) */ virtual bool HasBullishDirection( XOHCL &bar // ) { // bool result = false; // ENUM_X_DIRECTION dir; result = HasDirection(dir, bar); result = result && dir == X_DIRECTION_BULLISH; // return result; } /** * Check Specified Bar has Possibly Bearish Direction ... * * @param bar: XOHCL instance, Specified Bar ... * * @return ( virtual bool ) */ virtual bool HasBearishhDirection( XOHCL &bar // ) { // bool result = false; // ENUM_X_DIRECTION dir; result = HasDirection(dir, bar); result = result && dir == X_DIRECTION_BEARISH; // return result; } // protected: // // // Actions ... /** * Calculate Loopback Data for Specific Bar ... * * @param index: Integer, Bar Current Index ... * @param start: Integer, Start of Loopback ... * @param end: Integer, End of Loopback ... * @param count: Integer, Number of Calculating Bars ... * @param bar: XOHCL instance, Specified Bar ... * @param loopback: Integer, Loopback Length ... * @return ( bool ) */ bool CalculateLoopBackData( int &index, int &start, int &end, int &count, XOHCL &bar, int loopback = 1 // ) { // bool result = false; // if (loopback < 1) { loopback = 1; } // index = -1; start = -1; end = -1; count = -1; // result = bar.IsValid(); if (!result) { return result; } // index = bar.Index(); start = index + 1; end = start + loopback; count = end - start; result = count >= 1; if (!result) { return result; } // return result; } /** * Retrieve Loopback HH & LL Data ... * * @param hhIDX: Integer, HH Index ... * @param hh: Double, HH Value ... * @param llIDX: Integer, LL Index ... * @param ll: Double, LL Value ... * @param bar: XOHCL instance ... * @param loopback: Integer, Loopback Length ... * * @return ( bool ) */ bool CalculateLoopbackHLData( int &hhIDX, double &hh, int &llIDX, double &ll, XOHCL &bar, int loopback // ) { // bool result = false; // if (loopback < 1) { loopback = 1; } // int index = -1; int start = -1; int end = -1; int count = -1; result = CalculateLoopBackData( index, start, end, count, bar, loopback // ); if (!result) { return result; } // hhIDX = iHighest( bar.symbol, bar.period, MODE_HIGH, count, start // ); result = IsValidIndex(hhIDX); if (!result) { return result; } // llIDX = iLowest( bar.symbol, bar.period, MODE_LOW, count, start // ); result = IsValidIndex(llIDX); if (!result) { return result; } // hh = iHigh( bar.symbol, bar.period, hhIDX // ); ll = iLow( bar.symbol, bar.period, llIDX // ); // return result; } /** * Calculate Bar Range ... * * @param bar: XOHCL instance ... * * @return ( double ) */ double GetBarRangePercent(XOHCL &bar) { // double result = 0; // result = bar.GetRange() / 100; // return result; } // private: // // // Props ... // // Actions ... // }; //