/////////////////////////////////////////////////////// // // 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 XCBase { // public: // // // Constructor(s) ... void XCBarAnalyser() { } // // Deconstructor ... void ~XCBarAnalyser() { } // // Getter(s) / Setter(s) ... // // Providers ... // // 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; } /** * Detect Same Bars ... * * @param bar: XOHCL instance, Start Bar ... * @param dir: ENUM_X_DIRECTION member, Holds Result Direction ... * @param index: Integer, Holds Result Index ... * @param sameBars: Iteger, Required Same Bar ... * * @return ( bool ) */ bool HasSameBars( XOHCL &bar, ENUM_X_DIRECTION &dir, int &index, int sameBars = 3 // ) { // bool result = false; // dir = X_DIRECTION_NONE; // if (sameBars < 1) { sameBars = 1; } // result = bar.IsValid(); if (!result) { return result; } // index = bar.Index(); bool canContinue = true; int sameBullishBarsFounded = 0; int sameBearishBarsFounded = 0; bool canContinueForBullish = true; bool canContinueForBearish = true; while (canContinue) { // XOHCL iBar; result = iBar.Init( bar.symbol, bar.period, index // ); if (!result) { break; } // bool isBullish = iBar.IsBullish(); bool isBearish = iBar.IsBearish(); result = isBullish || isBearish; if (!result) { break; } // if (isBullish) { // sameBullishBarsFounded++; canContinueForBearish = false; } else { // sameBearishBarsFounded++; canContinueForBullish = false; } // result = canContinueForBullish || canContinueForBearish; if (!result) { break; } // canContinueForBullish = canContinueForBullish && sameBullishBarsFounded > 0; // canContinueForBearish = canContinueForBearish && sameBearishBarsFounded > 0; // canContinue = canContinueForBullish || canContinueForBearish; if (canContinue) { index++; } } // bool hasBullishSameBars = sameBullishBarsFounded >= sameBars; // bool hasBearishSameBars = sameBearishBarsFounded >= sameBars; // result = hasBullishSameBars || hasBearishSameBars; if (!result) { return result; } // dir = hasBullishSameBars ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // return result; } /** * Detect Price Consolidation ... * * @param bar: XOHCL instance Reference, Start Bar ... * @param loopback: Integer, Consolidation Range Finder ... * @param upper: Double Reference ... * @param lower: Double Reference ... * @param upperAppliedTo: ENUM_APPLIED_PRICE member, Upper Price ... * @param lowerAppliedTo: ENUM_APPLIED_PRICE member, Lower Price ... * * @return ( bool ) */ bool IsConsolidate( XOHCL &bar, double &upper, double &lower, int loopback = 30, ENUM_APPLIED_PRICE upperAppliedTo = PRICE_HIGH, ENUM_APPLIED_PRICE lowerAppliedTo = PRICE_LOW // ) { // bool result = false; // upper = 0; lower = 0; // if (loopback < 7) { loopback = 7; } // result = bar.IsValid(); if (!result) { return result; } // int consolidationRange = 30; double points = GetPoints(bar.symbol); int index = bar.Index(); // double upperPrice[]; int upperPriceCount = FillPrice( upperPrice, upperAppliedTo, bar.symbol, bar.period, index, loopback // ); // double lowerPrice[]; int lowerPriceCount = FillPrice( lowerPrice, lowerAppliedTo, bar.symbol, bar.period, index, loopback // ); // result = upperPriceCount == lowerPriceCount && lowerPriceCount == loopback; if (!result) { return result; } // upper = upperPrice[ArrayMaximum(upperPrice)]; lower = lowerPrice[ArrayMinimum(lowerPrice)]; // double range = upper - lower; result = range <= consolidationRange * points; // return result; } /** * Check Bar Has Bullish Trend or not ... * * @param bar: XOHCL instance ... * @param forceAll: Boolean ... * * @return ( bool ) */ bool HasBullishTrend( XOHCL &bar, bool forceAll = false // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // XOHCL tmpHSW[]; XOHCL tmpLSW[]; // bool trend1 = HasBullishTrend( bar, tmpHSW, tmpLSW, true // ); // bool trend2 = HasBullishTrend( bar, tmpHSW, tmpLSW, false // ); // if (!forceAll) { // result = trend1; if (!result) { return result; } } // result = trend1 || trend2; // return result; } /** * Check Bar Has Bearish Trend or not ... * * @param bar: XOHCL instance ... * @param forceAll: Boolean ... * * @return ( bool ) */ bool HasBearishTrend( XOHCL &bar, bool forceAll = false // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // XOHCL tmpHSW[]; XOHCL tmpLSW[]; // bool trend1 = HasBearishTrend( bar, tmpHSW, tmpLSW, true // ); // bool trend2 = HasBearishTrend( bar, tmpHSW, tmpLSW, false // ); // if (!forceAll) { // result = trend1; if (!result) { return result; } } // result = trend1 || trend2; // return result; } /** * Check Specified Bar Has Bullish Pattern or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param loopback: Integer, Loopback Length for Patterns ... * @param verifications: Integer, Number of Given Verifications ... * @param checkHammer: Boolean, Specified Check Hammer Pattern ... * @param checkMorningStar: Boolean, Specified Check Morning Star Pattern ... * @param checkBullishMarubozu: Boolean, Specified Check Marubozu Pattern ... * @param checkBullishEngulfing: Boolean, Specified Check Engulfing Pattern ... * * @return ( bool ) */ bool HasBullishPattern( XOHCL &bar, int loopback = 0, int verifications = 1, bool checkHammer = true, bool checkMorningStar = true, bool checkBullishMarubozu = true, bool checkBullishEngulfing = true // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // if (verifications <= 0) { verifications = 1; } // int founded = 0; // int idx = bar.Index(); for (int i = idx; i <= idx + loopback; i++) { // XOHCL iBar; result = iBar.Init( bar.symbol, bar.period, i // ); if (!result) { break; } // bool isHammer = !checkHammer ? false : IsHammer(iBar); if (isHammer) { founded++; } // bool isMorningStar = !checkMorningStar ? false : IsMorningStar(iBar); if (isMorningStar) { founded++; } // bool isBullishMarubozu = !checkBullishMarubozu ? false : IsBullishMarubozu(iBar); if (isBullishMarubozu) { founded++; } // bool isBullishEngulfing = !checkBullishEngulfing ? false : IsBullishEngulfing(iBar); if (isBullishEngulfing) { founded++; } // } // result = result && founded >= verifications; // return result; } /** * Check Specified Bar Has Bearish Pattern or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param loopback: Integer, Loopback Length for Patterns ... * @param verifications: Integer, Number of Given Verifications ... * @param checkShootingStar: Boolean, Specified Check Shooting Star Pattern ... * @param checkEveningStar: Boolean, Specified Check Evening Star Pattern ... * @param checkBearishMarubozu: Boolean, Specified Check Marubozu Pattern ... * @param checkBearishEngulfing: Boolean, Specified Check Engulfing Pattern ... * * @return ( bool ) */ bool HasBearishPattern( XOHCL &bar, int loopback = 0, int verifications = 1, bool checkShootingStar = true, bool checkEveningStar = true, bool checkBearishMarubozu = true, bool checkBearishEngulfing = true // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // if (verifications <= 0) { verifications = 1; } // int founded = 0; // int idx = bar.Index(); for (int i = idx - 1; i <= idx + loopback; i++) { // XOHCL iBar; result = iBar.Init( bar.symbol, bar.period, i // ); if (!result) { break; } // bool isShootingStar = !checkShootingStar ? false : IsShootingStar(iBar); if (isShootingStar) { founded++; } // bool isEveningStar = !checkEveningStar ? false : IsEveningStar(iBar); if (isEveningStar) { founded++; } // bool isBearishMarubozu = !checkBearishMarubozu ? false : IsBearishMarubozu(iBar); if (isBearishMarubozu) { founded++; } // bool isBearishEngulfing = !checkBearishEngulfing ? false : IsBearishEngulfing(iBar); if (isBearishEngulfing) { founded++; } // } // result = result && founded >= verifications; // return result; } // // 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; } /** * Check Specified Bar is Swing High or not ... * * @param bar: XOHCL instnce ... * @param range: Integer, Specified Range ... * * @return ( bool ) */ bool IsSwingHigh( XOHCL &bar, int range = 2 // ) { // bool result = false; // if (range < 1) { range = 1; } // result = bar.IsValid(); if (!result) { return result; } // int index = bar.Index(); result = range > 0 && index >= range; if (!result) { return result; } // string symbol = bar.symbol; ENUM_TIMEFRAMES period = bar.period; // for (int i = 1; i <= range; i++) { // // Prev Bar ... XOHCL iPrevBar; result = iPrevBar.Init( symbol, period, index + i // ); if (!result) { break; } // // Next Bar ... XOHCL iNextBar; result = iNextBar.Init( symbol, period, index - i // ); if (!result) { break; } // result = bar.high >= iPrevBar.high && bar.high >= iNextBar.high; if (!result) { break; } } // return result; } /** * Check Specified Bar is Swing Low or not ... * * @param bar: XOHCL instnce ... * @param range: Integer, Specified Range ... * * @return ( bool ) */ bool IsSwingLow( XOHCL &bar, int range = 2 // ) { // bool result = false; // if (range < 1) { range = 1; } // result = bar.IsValid(); if (!result) { return result; } // int index = bar.Index(); result = range > 0 && index >= range; if (!result) { return result; } // string symbol = bar.symbol; ENUM_TIMEFRAMES period = bar.period; // for (int i = 1; i <= range; i++) { // // Prev Bar ... XOHCL iPrevBar; result = iPrevBar.Init( symbol, period, index + i // ); if (!result) { break; } // // Next Bar ... XOHCL iNextBar; result = iNextBar.Init( symbol, period, index - i // ); if (!result) { break; } // result = bar.low <= iPrevBar.low && bar.low <= iNextBar.low; if (!result) { break; } } // return result; } /** * Check a Bar is Momentum Bar or not ... * * @param bar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * @param extend: Integer ... * @param bodyPercent: Double ... * * @return ( bool ) */ bool IsMomentumBar( XOHCL &bar, ENUM_X_DIRECTION &dir, int extend = 1, double bodyPercent = 70 // ) { // bool result = false; // if (extend < 0) { extend = 0; } // if (bodyPercent < 50) { bodyPercent = 50; } // dir = X_DIRECTION_NONE; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // if (extend > 0) { // result = IsExtended( bar, extend // ); // if (!result) { return result; } } // double body = bar.GetBody(); double rp = GetBarRangePercent(bar); // result = body >= rp * bodyPercent; // if (result) { // dir = bar.IsBullish() ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // return result; } /** * Check a Bar is Rejection Bar or not ... * * @param bar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * @param extend: Integer ... * @param shadowPercent: Double ... * * @return ( bool ) */ bool IsRejectionBar( XOHCL &bar, ENUM_X_DIRECTION &dir, int extend = 1, double shadowPercent = 60 // ) { // bool result = false; // if (extend < 0) { extend = 0; } // if (shadowPercent < 50) { shadowPercent = 50; } // dir = X_DIRECTION_NONE; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // if (extend > 0) { // result = IsExtended( bar, extend // ); // if (!result) { return result; } } // double body = bar.GetBody(); double range = bar.GetRange(); double shadows = bar.GetShadows(); double lowShadow = bar.GetLowShadow(); double highShadow = bar.GetHighShadow(); double rp = GetBarRangePercent(bar); // result = shadows >= rp * shadowPercent; // if (result) { // dir = lowShadow > highShadow ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // return result; } /** * Check Specified Bar is Engulfing Bar or not ... * * @param bar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * @param extend: Integer ... * @param bodyPercent: Double ... * * @return ( bool ) */ bool IsEngulfBar( XOHCL &bar, ENUM_X_DIRECTION &dir, int extend = 1, double bodyPercent = 60 // ) { // bool result = false; // if (extend < 0) { extend = 0; } // if (bodyPercent < 50) { bodyPercent = 50; } // dir = X_DIRECTION_NONE; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // // Previous Bar ... XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // if (extend > 0) { // result = IsExtended( pBar, extend // ); // if (!result) { return result; } } // // Check Engulfig ... result = bar.GetUp() > pBar.GetUp() && bar.GetDown() < pBar.GetDown(); if (!result) { return result; } // // Check Engulfing Direction ... bool isBullishEngulfed = pBar.IsBearish() && bar.IsBullish(); bool isBearishEngulfed = pBar.IsBullish() && bar.IsBearish(); // result = isBullishEngulfed || isBearishEngulfed; if (!result) { return result; } // dir = isBullishEngulfed ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // return result; } /** * Check Specified Bar is Pin Bar or not ... * * @param bar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * @param extend: Integer ... * @param shadowPercent: Double ... * @param bodyPercent: Double ... * * @return ( bool ) */ bool IsPinBar( XOHCL &bar, ENUM_X_DIRECTION &dir, int extend = 1, double shadowPercent = 65, double bodyPercent = 25 // ) { // bool result = false; // dir = X_DIRECTION_NONE; // result = bar.IsValid() && bar.Index() > 0 && bodyPercent > 0 && shadowPercent > 0 && bodyPercent < shadowPercent; if (!result) { return result; } // // Chack Range Extends ... if (extend > 0) { // result = HasExtendedRange( bar, extend // ); if (!result) { return result; } } // // Check Body ... double rangePercent = GetBarRangePercent(bar); // double body = bar.GetBody(); double highShadow = bar.GetHighShadow(); double lowShadow = bar.GetLowShadow(); // // Check Body ... result = body / rangePercent >= bodyPercent; if (!result) { return result; } // bool isPassedHighShadow = highShadow / rangePercent >= shadowPercent; bool isPassedLowShadow = lowShadow / rangePercent >= shadowPercent; result = isPassedLowShadow || isPassedHighShadow; if (!result) { return result; } // dir = isPassedLowShadow ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // return result; } /** * Decision Bar (Pin, Momentum or Rejection) ... * * @param bar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * @param extend: Integer ... * @param shadowForPinAndRejectionBarPercent: Double ... * @param bodyForPinBarPercent: Double ... * @param bodyForEngulfBarPercent: Double ... * @param bodyForMomentumBarPercent: Double ... * * @return ( bool ) */ bool IsDecisionBar( XOHCL &bar, ENUM_X_DIRECTION &dir, int extend = 1, double shadowForPinAndRejectionBarPercent = 65, double bodyForPinBarPercent = 25, double bodyForEngulfBarPercent = 65, double bodyForMomentumBarPercent = 70 // ) { // bool result = false; // dir = X_DIRECTION_NONE; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // // Pin Bar ... ENUM_X_DIRECTION pinDir; bool isPiBar = IsPinBar( bar, pinDir, extend, shadowForPinAndRejectionBarPercent, bodyForPinBarPercent // ); // // Engulfing Bar ... ENUM_X_DIRECTION engulfDir; bool isEngulfBar = IsEngulfBar( bar, engulfDir, extend, bodyForEngulfBarPercent // ); // // Momentum Bar ... ENUM_X_DIRECTION momentumDir; bool isMomentumBar = IsMomentumBar( bar, momentumDir, extend, bodyForMomentumBarPercent // ); // // Rejection Bar ... ENUM_X_DIRECTION rejectionDir; bool isRejectionBar = IsRejectionBar( bar, rejectionDir, extend, shadowForPinAndRejectionBarPercent // ); // result = isPiBar || isEngulfBar || isMomentumBar || isRejectionBar; if (result) { // if (isPiBar) { dir = pinDir; } else if (isEngulfBar) { dir = engulfDir; } else if (isMomentumBar) { dir = momentumDir; } else { dir = rejectionDir; } } // result = IsBullish(dir) || IsBearish(dir); // return result; } /** * Check Fibonacci Level 382 Pressure ... * * @param bar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * * @return ( bool ) */ bool HasFiboPressure( XOHCL &bar, ENUM_X_DIRECTION &dir // ) { // bool result = false; // dir = X_DIRECTION_NONE; // result = bar.IsValid(); if (!result) { return result; } // double bearishFib382 = GetFibonacciLevel( bar.high, bar.low, 0.382, 1 // ); double bullishFib382 = GetFibonacciLevel( bar.high, bar.low, 0.382, -1 // ); // bool isBullish = bar.GetDown() > bearishFib382; bool isBearish = bar.GetUp() < bullishFib382; // result = isBullish || isBearish; if (!result) { return result; } // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // return result; } // // Support and Resistance Zones ... /** * Check a Bar is Support Bar or not ... * * @param bar: XOHCL instance ... * @param range: Integer, Specified Verifiation Range ... * * @return ( bool ) */ bool IsSupport( XOHCL &bar, int range = 21 // ) { // bool result = false; // if (range < 2) { range = 2; } // result = bar.IsValid(); if (!result) { return result; } // int index = bar.Index(); result = range > 0 && index >= range; if (!result) { return result; } // string symbol = bar.symbol; ENUM_TIMEFRAMES period = bar.period; // for (int i = 1; i <= range; i++) { // int prevIDX = index + i; int nextIDX = index - 1; // // Prev Bar ... XOHCL iPrevBar; result = iPrevBar.Init( symbol, period, prevIDX // ); if (!result) { break; } // // Next Bar ... XOHCL iNextBar; result = iNextBar.Init( symbol, period, nextIDX // ); if (!result) { break; } // result = bar.low <= iPrevBar.low && bar.low <= iNextBar.low; if (!result) { break; } } // return result; } /** * Check a Bar is Resistance Bar or not ... * * @param bar: XOHCL instance ... * @param range: Integer, Specified Verifiation Range ... * * @return ( bool ) */ bool IsResistance( XOHCL &bar, int range = 21 // ) { // bool result = false; // if (range < 2) { range = 2; } // result = bar.IsValid(); if (!result) { return result; } // int index = bar.Index(); result = range > 0 && index >= range; if (!result) { return result; } // string symbol = bar.symbol; ENUM_TIMEFRAMES period = bar.period; // for (int i = 1; i <= range; i++) { // int prevIDX = index + i; int nextIDX = index - 1; // // Prev Bar ... XOHCL iPrevBar; result = iPrevBar.Init( symbol, period, prevIDX // ); if (!result) { break; } // // Next Bar ... XOHCL iNextBar; result = iNextBar.Init( symbol, period, nextIDX // ); if (!result) { break; } // result = bar.high >= iPrevBar.high && bar.high >= iNextBar.high; if (!result) { break; } } // return result; } // // Order Blocks ... /** * Detect an Order Block Based on Given Bar ... * * @param bar: XOHCL instance, Specified Start Bar ... * @param ob: XOHCL instance, Fill it if Order Block Found ... * @param dir: ENUM_X_DIRECTION member, Specified Founded Order Block Direction ... * @param sameBars: Integer, Specified Min Same Bars for Detecting Order Block ... * * @return ( bool ) */ bool HasOrderBlock( XOHCL &bar, XOHCL &ob, ENUM_X_DIRECTION &dir, int sameBars = 3 // ) { // bool result = false; // ob.Clean(); dir = X_DIRECTION_NONE; // if (sameBars < 1) { sameBars = 1; } // result = bar.IsValid(); if (!result) { return result; } // int index = 0; result = HasSameBars( bar, dir, index, sameBars // ); if (!result) { return result; } // int obIndex = index; result = ob.Init( bar.symbol, bar.period, obIndex // ); if (!result) { return result; } // return result; } // // Fair Value Gaps ... /** * Detect a Fair Value Gap Based on Given Bar ... * * @param bar: XOHCL instance, Specified Start Bar ... * @param dir: ENUM_X_DIRECTION member, Specified Founded Order Block Direction ... * @param sameBars: Integer, Specified Min Same Bars for Detecting Order Block ... * * @return ( bool ) */ bool HasFairValueGap( XOHCL &bar, XOHCL &prevBar, XOHCL &nextBar, ENUM_X_DIRECTION &dir, int sameBars = 3 // ) { // bool result = false; // prevBar.Clean(); nextBar.Clean(); dir = X_DIRECTION_NONE; // if (sameBars < 1) { sameBars = 1; } // result = bar.IsValid(); if (!result) { return result; } // int index = 0; result = HasSameBars( bar, dir, index, sameBars // ); if (!result) { return result; } // bool isBullish = IsBullish(dir); // int to = bar.Index() + 1; int from = index + 1; for (int i = from; i > to; i--) { // result = prevBar.Init( bar.symbol, bar.period, i // ); if (!result) { break; } // result = nextBar.Init( bar.symbol, bar.period, i - 2 // ); if (!result) { break; } // result = isBullish ? prevBar.high < nextBar.low : prevBar.low > nextBar.high; if (result) { break; } } // if (!result) { // prevBar.Clean(); nextBar.Clean(); dir = X_DIRECTION_NONE; } // return result; } // // Bar CHOCH ... /** * Check Specified Bar Has PullBack 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 HasPullBack( ENUM_X_DIRECTION &dir, XOHCL &bar, int loopback = 3, 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; } // // Tools ... // bool IsStrong( XOHCL &bar, double percent = 50 // Percent of Body ) { // bool result = false; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // result = (bar.GetRange() * percent) / 100 <= bar.GetBody(); // return result; } // bool HasStrongLowShadow( XOHCL &bar, double percent = 50, // Percent of Body int __loopback = 2, double _sharpRatio = 2.5 // ) { // bool result = false; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // result = (bar.GetRange() * percent) / 100 <= bar.GetLowShadow(); if (!result) { return result; } // if (__loopback < 0) { __loopback = 2; } // if (_sharpRatio < 0) { _sharpRatio = 2.5; } // result = bar.Index() > __loopback; if (!result) { return result; } // // Get Highest High and Lowest Low in loopback Range ... int startIndex = bar.Index() - __loopback; int endIndex = bar.Index() + __loopback; int requiredBars = MathAbs(endIndex - startIndex); // // Highs ... double highs[]; int copiedHighs = CopyHigh( bar.symbol, bar.period, startIndex, requiredBars, highs // ); // result = copiedHighs == requiredBars; if (!result) { return result; } // int highestHighIDX = ArrayMaximum(highs); result = IsValidIndex(highestHighIDX); if (!result) { return result; } // double highestHigh = highs[highestHighIDX]; // // Lows ... double lows[]; int copiedLows = CopyLow( bar.symbol, bar.period, startIndex, requiredBars, lows // ); // result = copiedLows == requiredBars; if (!result) { return result; } // int lowestLowIDX = ArrayMinimum(lows); result = IsValidIndex(lowestLowIDX); if (!result) { return result; } // double lowestLow = lows[lowestLowIDX]; // result = bar.low == lowestLow && highestHigh > bar.high; if (!result) { return result; } // // Try to Validate Sharp Ratio ... // Clean(highs); Clean(lows); // // Left Side ... startIndex = bar.Index() + 1; endIndex = startIndex + (__loopback / 2) - 1; requiredBars = MathAbs(endIndex - startIndex); // copiedHighs = CopyHigh( bar.symbol, bar.period, startIndex, requiredBars, highs // ); result = copiedHighs == requiredBars; if (!result) { return result; } // highestHighIDX = ArrayMaximum(highs); result = IsValidIndex(highestHighIDX); if (!result) { return result; } // highestHigh = highs[highestHighIDX]; // copiedLows = CopyLow( bar.symbol, bar.period, startIndex, requiredBars, lows // ); result = copiedLows == requiredBars; if (!result) { return result; } // lowestLowIDX = ArrayMinimum(lows); result = IsValidIndex(lowestLowIDX); if (!result) { return result; } // lowestLow = lows[lowestLowIDX]; // double leftDiff = highestHigh - lowestLow; // Clean(highs); Clean(lows); // // Right Side ... startIndex = bar.Index() - 1; endIndex = startIndex - (__loopback / 2) + 1; requiredBars = MathAbs(endIndex - startIndex); // copiedHighs = CopyHigh( bar.symbol, bar.period, startIndex, requiredBars, highs // ); result = copiedHighs == requiredBars; if (!result) { return result; } // highestHighIDX = ArrayMaximum(highs); result = IsValidIndex(highestHighIDX); if (!result) { return result; } // highestHigh = highs[highestHighIDX]; // copiedLows = CopyLow( bar.symbol, bar.period, startIndex, requiredBars, lows // ); result = copiedLows == requiredBars; if (!result) { return result; } // lowestLowIDX = ArrayMinimum(lows); result = IsValidIndex(lowestLowIDX); if (!result) { return result; } // lowestLow = lows[lowestLowIDX]; // double rightDiff = highestHigh - lowestLow; double diff = MathMax(leftDiff, rightDiff); result = bar.GetLowShadow() >= (diff / 100) * _sharpRatio; // return result; } // bool HasStrongHighShadow( XOHCL &bar, double percent = 50, // Percent of Body int __loopback = 2, double _sharpRatio = 2.5 // ) { // bool result = false; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // result = (bar.GetRange() * percent) / 100 <= bar.GetHighShadow(); if (!result) { return result; } // if (__loopback < 0) { __loopback = 2; } // if (_sharpRatio < 0) { _sharpRatio = 2.5; } // result = bar.Index() > __loopback; if (!result) { return result; } // // Get Highest High and Lowest Low in loopback Range ... int startIndex = bar.Index() - __loopback; int endIndex = bar.Index() + __loopback; int requiredBars = MathAbs(endIndex - startIndex); // // Highs ... double highs[]; int copiedHighs = CopyHigh( bar.symbol, bar.period, startIndex, requiredBars, highs // ); // result = copiedHighs == requiredBars; if (!result) { return result; } // int highestHighIDX = ArrayMaximum(highs); result = IsValidIndex(highestHighIDX); if (!result) { return result; } // double highestHigh = highs[highestHighIDX]; // // Lows ... double lows[]; int copiedLows = CopyLow( bar.symbol, bar.period, startIndex, requiredBars, lows // ); // result = copiedLows == requiredBars; if (!result) { return result; } // int lowestLowIDX = ArrayMinimum(lows); result = IsValidIndex(lowestLowIDX); if (!result) { return result; } // double lowestLow = lows[lowestLowIDX]; // result = bar.high == highestHigh && lowestLow < bar.low; if (!result) { return result; } // // Try to Validate Sharp Ratio ... // Clean(highs); Clean(lows); // // Left Side ... startIndex = bar.Index() + 1; endIndex = startIndex + (__loopback / 2) - 1; requiredBars = MathAbs(endIndex - startIndex); // copiedHighs = CopyHigh( bar.symbol, bar.period, startIndex, requiredBars, highs // ); result = copiedHighs == requiredBars; if (!result) { return result; } // highestHighIDX = ArrayMaximum(highs); result = IsValidIndex(highestHighIDX); if (!result) { return result; } // highestHigh = highs[highestHighIDX]; // copiedLows = CopyLow( bar.symbol, bar.period, startIndex, requiredBars, lows // ); result = copiedLows == requiredBars; if (!result) { return result; } // lowestLowIDX = ArrayMinimum(lows); result = IsValidIndex(lowestLowIDX); if (!result) { return result; } // lowestLow = lows[lowestLowIDX]; // double leftDiff = highestHigh - lowestLow; // Clean(highs); Clean(lows); // // Right Side ... startIndex = bar.Index() - 1; endIndex = startIndex - (__loopback / 2) + 1; requiredBars = MathAbs(endIndex - startIndex); // copiedHighs = CopyHigh( bar.symbol, bar.period, startIndex, requiredBars, highs // ); result = copiedHighs == requiredBars; if (!result) { return result; } // highestHighIDX = ArrayMaximum(highs); result = IsValidIndex(highestHighIDX); if (!result) { return result; } // highestHigh = highs[highestHighIDX]; // copiedLows = CopyLow( bar.symbol, bar.period, startIndex, requiredBars, lows // ); result = copiedLows == requiredBars; if (!result) { return result; } // lowestLowIDX = ArrayMinimum(lows); result = IsValidIndex(lowestLowIDX); if (!result) { return result; } // lowestLow = lows[lowestLowIDX]; // double rightDiff = highestHigh - lowestLow; double diff = MathMax(leftDiff, rightDiff); result = bar.GetHighShadow() >= (diff / 100) * _sharpRatio; // return result; } // bool IsStrongBullish( XOHCL &bar, double percent = 50 // Percent of Body ) { // bool result = false; // result = bar.IsValid() && bar.IsBullish() && IsStrong(bar, percent); // return result; } // bool IsStrongBearish( XOHCL &bar, double percent = 50 // Percent of Body ) { // bool result = false; // result = bar.IsValid() && bar.IsBearish() && IsStrong(bar, percent); // return result; } // bool IsSharpBullish( XOHCL &bar, int __loopback = 2, double _sharpRatio = 2.5 // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // if (__loopback < 0) { __loopback = 2; } // if (_sharpRatio < 0) { _sharpRatio = 2.5; } // int hIDX = bar.FindHighestIndex( __loopback, MODE_HIGH // ); int lIDX = bar.FindLowestIndex( __loopback, MODE_LOW // ); // result = // hIDX >= 0 && lIDX >= 0 && MathAbs(hIDX - bar.Index()) < 2 // ; // if (!result) { return result; } // XOHCL hBar; result = hBar.Init( bar.symbol, bar.period, hIDX // ); if (!result) { return result; } // XOHCL lBar; result = lBar.Init( bar.symbol, bar.period, lIDX // ); if (!result) { return result; } // double lhDif = hBar.high - lBar.low; // int hhIDX = hBar.FindHighestIndex( __loopback, MODE_HIGH // ); // int llIDX = lBar.FindLowestIndex( __loopback, MODE_LOW // ); // XOHCL hhBar; result = hhBar.Init( bar.symbol, bar.period, hhIDX + hIDX // ); if (!result) { return result; } // XOHCL llBar; result = llBar.Init( bar.symbol, bar.period, llIDX + lIDX // ); if (!result) { return result; } // double llhhDif = hhBar.high - llBar.low; // result = // lBar.low > llBar.low && hBar.high > hhBar.high && lhDif >= llhhDif * _sharpRatio // ; // return result; } // bool IsSharpBearish( XOHCL &bar, int __loopback = 2, double _sharpRatio = 2.5 // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // if (__loopback < 0) { __loopback = 2; } // if (_sharpRatio < 0) { _sharpRatio = 2.5; } // int hIDX = bar.FindHighestIndex( __loopback, MODE_HIGH // ); int lIDX = bar.FindLowestIndex( __loopback, MODE_LOW // ); // result = // hIDX >= 0 && lIDX >= 0 && MathAbs(hIDX - bar.Index()) < 2 // ; // if (!result) { return result; } // XOHCL hBar; result = hBar.Init( bar.symbol, bar.period, hIDX // ); if (!result) { return result; } // XOHCL lBar; result = lBar.Init( bar.symbol, bar.period, lIDX // ); if (!result) { return result; } // double lhDif = hBar.high - lBar.low; // int hhIDX = hBar.FindHighestIndex( __loopback, MODE_HIGH // ); // int llIDX = lBar.FindLowestIndex( __loopback, MODE_LOW // ); // XOHCL hhBar; result = hhBar.Init( bar.symbol, bar.period, hhIDX + hIDX // ); if (!result) { return result; } // XOHCL llBar; result = llBar.Init( bar.symbol, bar.period, llIDX + lIDX // ); if (!result) { return result; } // double llhhDif = hhBar.high - llBar.low; // result = // lBar.low < llBar.low && hBar.high < hhBar.high && lhDif >= llhhDif * _sharpRatio // ; // return result; } // // // // // Retrieve Bullish Pressure ... double GetBullishPressure( XOHCL &bar, int __loopback = 7 // ) { // double result = 0; // if (!bar.IsValid()) { return result; } // XOHCL bars[]; int barsCount = GetBars( bars, bar.symbol, bar.period, bar.Index(), __loopback // ); if (!IsValidSize(barsCount)) { return result; } // for (int i = 0; i < barsCount; i++) { result += bars[i].GetLowShadow(); } // return result; } // // Retrieve Bearish Pressure ... double GetBearishPressure( XOHCL &bar, int __loopback = 7 // ) { // double result = 0; // if (!bar.IsValid()) { return result; } // XOHCL bars[]; int barsCount = GetBars( bars, bar.symbol, bar.period, bar.Index(), __loopback // ); if (!IsValidSize(barsCount)) { return result; } // for (int i = 0; i < barsCount; i++) { result += bars[i].GetHighShadow(); } // return result; } // bool HasBullishPressure( XOHCL &bar, int __loopback = 7 // ) { // bool result = false; // if (__loopback < 0) { __loopback = 7; } // result = bar.IsValid(); if (!result) { return result; } // double bullishPressure = GetBullishPressure(bar, __loopback); double bearishPressure = GetBearishPressure(bar, __loopback); // result = // bullishPressure > 0 && bearishPressure >= 0 && bullishPressure > bearishPressure // ; // return result; } // bool HasBearishPressure( XOHCL &bar, int __loopback = 7 // ) { // bool result = false; // if (__loopback < 0) { __loopback = 7; } // result = bar.IsValid(); if (!result) { return result; } // double bullishPressure = GetBullishPressure(bar, __loopback); double bearishPressure = GetBearishPressure(bar, __loopback); // result = // bearishPressure > 0 && bullishPressure >= 0 && bearishPressure > bullishPressure // ; // return result; } // // Retrieve Bullish Power ... double GetBullishPower( XOHCL &bar, int __loopback = 7 // ) { // double result = 0; // if (!bar.IsValid()) { return result; } // XOHCL bars[]; int barsCount = GetBars( bars, bar.symbol, bar.period, bar.Index(), __loopback // ); if (!IsValidSize(barsCount)) { return result; } // for (int i = 0; i < barsCount; i++) { // if (bars[i].IsBullish()) { result += bars[i].GetBody(); } } // return result; } // // Retrieve Bearish Pressure ... double GetBearishPower( XOHCL &bar, int __loopback = 7 // ) { // double result = 0; // if (!bar.IsValid()) { return result; } // XOHCL bars[]; int barsCount = GetBars( bars, bar.symbol, bar.period, bar.Index(), __loopback // ); if (!IsValidSize(barsCount)) { return result; } // for (int i = 0; i < barsCount; i++) { // if (bars[i].IsBearish()) { result += bars[i].GetBody(); } } // return result; } // bool HasBullishPower( XOHCL &bar, int __loopback = 7 // ) { // bool result = false; // if (__loopback < 0) { __loopback = 7; } // result = bar.IsValid(); if (!result) { return result; } // double bullishPressure = GetBullishPower(bar, __loopback); double bearishPressure = GetBearishPower(bar, __loopback); // result = // bullishPressure > 0 && bearishPressure >= 0 && bullishPressure > bearishPressure // ; // return result; } // bool HasBearishPower( XOHCL &bar, int __loopback = 7 // ) { // bool result = false; // if (__loopback < 0) { __loopback = 7; } // result = bar.IsValid(); if (!result) { return result; } // double bullishPressure = GetBullishPower(bar, __loopback); double bearishPressure = GetBearishPower(bar, __loopback); // result = // bearishPressure > 0 && bullishPressure >= 0 && bearishPressure > bullishPressure // ; // return result; } // // Decisions ... // bool IsBullishDecision( XOHCL &bar, double percent = 70 // Percent of Body ) { // bool result = false; // result = // bar.IsValid() && bar.Index() > 0 && bar.IsBullish() && (bar.GetRange() * percent) / 100 <= bar.GetBody() // ; // return result; } // bool IsBearishDecision( XOHCL &bar, double percent = 70 // Percent of Body ) { // bool result = false; // result = // bar.IsValid() && bar.Index() > 0 && bar.IsBearish() && (bar.GetRange() * percent) / 100 <= bar.GetBody() // ; // return result; } // // Candlestic Patterns ... // // Check Doji ... bool IsDoji( XOHCL &bar // ) { // bool result = false; // // Validate Content and Ignore 0 Bar // since it is not Completed ... result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // result = bar.open == bar.close; // return result; } // // Check Hammer ... bool IsHammer( XOHCL &bar, double _upShadowFactor = 0.1, double _downShadowFactor = 0.6, bool applyFib382Check = true, bool applyPrevShadowCheck = true // ) { // bool result = false; // // Validate Content and Ignore 0 Bar // since it is not Completed ... result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // if (_upShadowFactor < 0) { _upShadowFactor = 0.1; } // if (_downShadowFactor < 0) { _upShadowFactor = 0.6; } // double range = bar.GetRange(); // // Check Upper Shadow Must be 0 or Under 10% ... double upShadow = bar.GetHighShadow(); result = upShadow < range * _upShadowFactor; if (!result) { return result; } // // Check Down Shadow Must at least 60% ... double downShadow = bar.GetLowShadow(); result = downShadow > range * _downShadowFactor; if (!result) { return result; } // // Check Fib 382 ... if (result && applyFib382Check) { // double fib382 = GetFibonacciLevel( bar.high, bar.low, 0.382, -1 // ); result = bar.GetDown() > fib382; } // // Check Shadow Based on Prev Bar ... if (result && applyPrevShadowCheck) { // XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // result = bar.low < pBar.low; } // return result; } // // Check Sgooting Star ... // Reversal Hammer ... bool IsShootingStar( XOHCL &bar, double _upShadowFactor = 0.6, double _downShadowFactor = 0.1, bool applyFib382Check = true, bool applyPrevShadowCheck = true // ) { // bool result = false; // // Validate Content and Ignore 0 Bar // since it is not Completed ... result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // if (_upShadowFactor < 0) { _upShadowFactor = 0.6; } // if (_downShadowFactor < 0) { _upShadowFactor = 0.1; } // double range = bar.GetRange(); // // Check Upper Shadow Must be 0 or Under 10% ... double upShadow = bar.GetHighShadow(); result = upShadow > range * _upShadowFactor; if (!result) { return result; } // // Check Down Shadow Must at least 60% ... double downShadow = bar.GetLowShadow(); result = downShadow < range * _downShadowFactor; if (!result) { return result; } // // Check Fib 382 ... if (result && applyFib382Check) { // double fib382 = GetFibonacciLevel( bar.high, bar.low, 0.382, 1 // ); result = bar.GetUp() < fib382; } // // Check Shadow Based on Prev Bar ... if (result && applyPrevShadowCheck) { // XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // result = bar.high > pBar.high; } // return result; } // // Check Bullish Engulfing ... bool IsBullishEngulfing( XOHCL &bar, double _engulfBarBodyFactor = 0.7 // ) { // bool result = false; // // Validate Content and Ignore 0 Bar // since it is not Completed ... result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // if (_engulfBarBodyFactor < 0) { _engulfBarBodyFactor = 0.7; } // // Check Bar Is Bullish ... result = bar.IsBullish(); if (!result) { return result; } // // Retrieve Previous Bar ... XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // double range = bar.GetRange(); double body = bar.GetBody(); // // Check Prev Bar Must Bearish ... result = pBar.IsBearish(); if (!result) { return result; } // // Check Shadows Engulf Prev Bar ... result = // bar.high > pBar.high && bar.low <= pBar.low // ; if (!result) { return result; } // // Check Engulfed Bar Must Inside Engulfer Body ... result = // bar.GetUp() > pBar.GetUp() && bar.GetDown() < pBar.GetDown() // ; if (!result) { return result; } // // Check Body of Engulfing Bar ... if (result && _engulfBarBodyFactor > 0) { result = body >= range * _engulfBarBodyFactor; } // return result; } // // Check Bearish Engulfing ... bool IsBearishEngulfing( XOHCL &bar, double _engulfBarBodyFactor = 0.7 // ) { // bool result = false; // // Validate Content and Ignore 0 Bar // since it is not Completed ... result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // if (_engulfBarBodyFactor < 0) { _engulfBarBodyFactor = 0.7; } // // Check Bar Is Bearish ... result = bar.IsBearish(); if (!result) { return result; } // // Retrieve Previous Bar ... XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // double range = bar.GetRange(); double body = bar.GetBody(); // // Check Prev Bar Must Bullish ... result = pBar.IsBullish(); if (!result) { return result; } // // Check Shadows Engulf Prev Bar ... result = bar.high >= pBar.high && bar.low < pBar.low; if (!result) { return result; } // // Check Engulfed Bar Must Inside Engulfer Body ... result = // bar.GetUp() > pBar.GetUp() && bar.GetDown() < pBar.GetDown() // ; if (!result) { return result; } // // Check Body of Engulfing Bar ... if (result && _engulfBarBodyFactor > 0) { result = body >= range * _engulfBarBodyFactor; } // return result; } // // Check Morning Star Pattern ... bool IsMorningStar( XOHCL &bar, double _middleRangeFactor = 0.3, double _startBodyFactor = 0.6, bool forceCheckMiddleBarDirection = true, bool forceCheckStartBody = true // ) { // bool result = false; // // Validate Content and Ignore 0 Bar // since it is not Completed ... result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // if (_middleRangeFactor < 0) { _middleRangeFactor = 0.3; } // if (_startBodyFactor < 0) { _startBodyFactor = 0.6; } // // Current Bar Must be Bullish ... result = bar.IsBullish(); if (!result) { return result; } // // Retrieve Previous Bar ... XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // // Prev Bar must be Bearish ... if (result && forceCheckMiddleBarDirection) { // result = pBar.IsBearish(); if (!result) { return result; } } // // Retrieve Previous Bar of Prev Bar ... XOHCL ppBar; result = pBar.GetPreviousBar(ppBar); if (!result) { return result; } // // Prev Of Prev Bar Must be Bearish ... result = ppBar.IsBearish(); if (!result) { return result; } // double range = bar.GetRange(); double pRange = pBar.GetRange(); double ppRange = ppBar.GetRange(); // // Middle Bar must be Smaller than Ratio of other ... result = // pRange < range * _middleRangeFactor && pRange < ppRange * _middleRangeFactor // ; if (!result) { return result; } // if (result && forceCheckStartBody) { // result = ppBar.GetBody() > ppRange * _startBodyFactor; if (!result) { return result; } } // return result; } // // Check Evening Star Pattern ... bool IsEveningStar( XOHCL &bar, double _middleRangeFactor = 0.3, double _startBodyFactor = 0.6, bool forceCheckMiddleBarDirection = true, bool forceCheckStartBody = true // ) { // bool result = false; // // Validate Content and Ignore 0 Bar // since it is not Completed ... result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // if (_middleRangeFactor < 0) { _middleRangeFactor = 0.3; } // if (_startBodyFactor < 0) { _startBodyFactor = 0.6; } // // Current Bar Must be Bearish ... result = bar.IsBearish(); if (!result) { return result; } // // Retrieve Previous Bar ... XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // // Prev Bar must be Bullish ... if (result && forceCheckMiddleBarDirection) { // result = pBar.IsBullish(); if (!result) { return result; } } // // Retrieve Previous Bar of Prev Bar ... XOHCL ppBar; result = pBar.GetPreviousBar(ppBar); if (!result) { return result; } // // Prev Of Prev Bar Must be Bullish ... result = ppBar.IsBullish(); if (!result) { return result; } // double range = bar.GetRange(); double pRange = pBar.GetRange(); double ppRange = ppBar.GetRange(); // // Middle Bar must be Smaller than Ratio of other ... result = // pRange < range * _middleRangeFactor && pRange < ppRange * _middleRangeFactor // ; if (!result) { return result; } // if (result && forceCheckStartBody) { // result = ppBar.GetBody() > ppRange * _startBodyFactor; if (!result) { return result; } } // return result; } // // Bullish Marubozu ... bool IsBullishMarubozu(XOHCL &bar) { // bool result = false; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // result = bar.IsBullish(); if (!result) { return result; } // result = // bar.GetUp() == bar.high && bar.GetDown() == bar.low // ; // return result; } // // Bearish Marubozu ... bool IsBearishMarubozu(XOHCL &bar) { // bool result = false; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // result = bar.IsBearish(); if (!result) { return result; } // result = // bar.GetUp() == bar.high && bar.GetDown() == bar.low // ; // return result; } // // Contextual Patterns ... // // Check Swing High ... bool IsBarSwingHigh(XOHCL &bar) { // bool result = false; // // Validate Content and Ignore 0 Bar // since it is not Completed ... result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // // Current Bar Must be Bearish ... result = bar.IsBearish(); if (!result) { return result; } // // Retrieve Prev Bar ... XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // // Prev Bar Must be Bullish ... result = pBar.IsBullish(); if (!result) { return result; } // // Retrieve Prev of Prev Bar ... XOHCL ppBar; result = pBar.GetPreviousBar(ppBar); if (!result) { return result; } // // Prev of Prev Bar Must be Bullish ... result = ppBar.IsBullish(); if (!result) { return result; } // // Check All Highs ... result = // bar.high < pBar.high && pBar.high > ppBar.high // ; // return result; } // // Find Simple 3 Candle Based Swing High ... bool IsSimpleSwingHigh( XOHCL &bar, double thresholdInPoint = 1 // ) { // bool result = false; // int index = bar.Index(); result = index > 0; if (!result) { return result; } // XOHCL nextBar; result = bar.GetNextBar(nextBar); if (!result) { return result; } // XOHCL prevBar; result = bar.GetPreviousBar(prevBar); if (!result) { return result; } // double point = GetPoints(bar.symbol); double requiredOffset = point * thresholdInPoint; // result = bar.high > nextBar.high && bar.high > prevBar.high && (thresholdInPoint <= 0 ? true : MathAbs( MathMax( nextBar.high, prevBar.high) - bar.high) >= requiredOffset); // return result; } // // Find Last Swing High ... bool FindLastSwingHigh( XOHCL &bar, XOHCL &swing // ) { // bool result = false; // swing.Clean(); // result = bar.IsValid(); if (!result) { return result; } // int totalBars = iBars( bar.symbol, bar.period // ); int maxAllowed = MathMin(100, (totalBars / 100)); // int idx = bar.Index(); for (int i = idx; i <= idx + maxAllowed; i++) { // swing.Clean(); result = swing.Init( bar.symbol, bar.period, i // ); if (!result) { // swing.Clean(); break; } // result = IsBarSwingHigh(swing); if (result) { break; } } // return result; } // // Check Swing Low ... bool IsBarSwingLow(XOHCL &bar) { // bool result = false; // // Validate Content and Ignore 0 Bar // since it is not Completed ... result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // // Current Bar Must be Bullish ... result = bar.IsBullish(); if (!result) { return result; } // // Retrieve Prev Bar ... XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // // Prev Bar Must be Bearish ... result = pBar.IsBearish(); if (!result) { return result; } // // Retrieve Prev of Prev Bar ... XOHCL ppBar; result = pBar.GetPreviousBar(ppBar); if (!result) { return result; } // // Prev of Prev Bar Must be Bearish ... result = ppBar.IsBearish(); if (!result) { return result; } // // Check All Lows ... result = // bar.low > pBar.low && pBar.low < ppBar.low // ; // return result; } // // Find Simple 3 Candle Based Swing Low ... bool IsSimpleSwingLow( XOHCL &bar, double thresholdInPoint = 1 // ) { // bool result = false; // int index = bar.Index(); result = index > 0; if (!result) { return result; } // XOHCL nextBar; result = bar.GetNextBar(nextBar); if (!result) { return result; } // XOHCL prevBar; result = bar.GetPreviousBar(prevBar); if (!result) { return result; } // double point = GetPoints(bar.symbol); double requiredOffset = point * thresholdInPoint; // result = bar.low < nextBar.low && bar.low < prevBar.low && (thresholdInPoint <= 0 ? true : MathAbs( MathMax( nextBar.low, prevBar.low) - bar.low) >= requiredOffset); // return result; } // // Find Last Swing Low ... bool FindLastSwingLow( XOHCL &bar, XOHCL &swing // ) { // bool result = false; // swing.Clean(); // result = bar.IsValid(); if (!result) { return result; } // int totalBars = iBars( bar.symbol, bar.period // ); int maxAllowed = MathMin(100, (totalBars / 100)); // int idx = bar.Index(); for (int i = idx; i <= idx + maxAllowed; i++) { // swing.Clean(); result = swing.Init( bar.symbol, bar.period, i // ); if (!result) { // swing.Clean(); break; } // result = IsBarSwingLow(swing); if (result) { break; } } // return result; } // // Check Bullish FVG ... bool HasBullishFVG( XOHCL &bar, double &upper, double &lower, datetime &start, datetime &end, bool forceMiddleBarCheck = true, bool forceCheckLastBarDirection = false // ) { // bool result = false; // upper = 0; lower = 0; // end = NULL; start = NULL; // // Validate Content and Ignore 0 Bar // since it is not Completed ... result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // // Current Bar Must be Bullish ... result = !forceCheckLastBarDirection ? true : bar.IsBullish(); if (!result) { return result; } // // Retrieve Prev Bar ... XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // // Prev Bar Must be Bullish ... result = pBar.IsBullish(); if (!result) { return result; } // // Retrieve Prev of Prev Bar ... XOHCL ppBar; result = pBar.GetPreviousBar(ppBar); if (!result) { return result; } // // Prev of Prev Bar Must be Bullish ... result = ppBar.IsBullish(); if (!result) { return result; } // // Other Conditions ... result = // bar.low > ppBar.high // ; // // Check Middle Bar Range ... if (result && forceMiddleBarCheck) { // result = // pBar.high > bar.low && pBar.low < ppBar.high // ; // if (!result) { return result; } } // if (result) { // end = bar.time; upper = bar.low; lower = ppBar.high; start = ppBar.time; } // return result; } // // Check Bearish FVG ... bool HasBearishFVG( XOHCL &bar, double &upper, double &lower, datetime &start, datetime &end, bool forceMiddleBarCheck = true, bool forceCheckLastBarDirection = false // ) { // bool result = false; // upper = 0; lower = 0; // end = NULL; start = NULL; // // Validate Content and Ignore 0 Bar // since it is not Completed ... result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // // Current Bar Must be Bearish ... result = !forceCheckLastBarDirection ? true : bar.IsBullish(); if (!result) { return result; } // // Retrieve Prev Bar ... XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // // Prev Bar Must be Bearish ... result = pBar.IsBearish(); if (!result) { return result; } // // Retrieve Prev of Prev Bar ... XOHCL ppBar; result = pBar.GetPreviousBar(ppBar); if (!result) { return result; } // // Prev of Prev Bar Must be Bearish ... result = ppBar.IsBearish(); if (!result) { return result; } // // Other Conditions ... result = // bar.high < ppBar.low // ; // // Check Middle Bar Range ... if (result && forceMiddleBarCheck) { // result = // pBar.high > bar.low && pBar.low < ppBar.high // ; // if (!result) { return result; } } // if (result) { // end = bar.time; lower = bar.high; upper = ppBar.low; start = ppBar.time; } // return result; } // // Find Support ... bool HasSupport( XOHCL &bar, XOHCL &dest, ENUM_X_PRICE type = X_PRICE_CLOSE, int _loopback = 21, int tries = 100 // ) { // bool result = false; // dest.Clean(); // if (_loopback < 0) { _loopback = 21; } // if (tries < 0) { tries = 100; } // result = bar.IsValid(); if (!result) { return result; } // double price = bar.GetPrice(type); // for (int i = 1; i < tries; i++) { // int _length = _loopback * i; // int lowestIDX = bar.FindLowestIndex( _length, MODE_LOW // ); result = IsValidIndex(lowestIDX); if (!result) { break; } // XOHCL iLBar; result = iLBar.Init( bar.symbol, bar.period, lowestIDX // ); if (!result) { break; } // result = // price > iLBar.high // ; if (result) { // dest = iLBar; break; } } // result = dest.IsValid(); // return result; } // // Find Resistance ... bool HasResistance( XOHCL &bar, XOHCL &dest, ENUM_X_PRICE type = X_PRICE_CLOSE, int _loopback = 21, int tries = 100 // ) { // bool result = false; // dest.Clean(); // if (_loopback < 0) { _loopback = 21; } // if (tries < 0) { tries = 100; } // result = bar.IsValid(); if (!result) { return result; } // double price = bar.GetPrice(type); // for (int i = 1; i < tries; i++) { // int _length = _loopback * i; // int highestIDX = bar.FindHighestIndex( _length, MODE_LOW // ); result = IsValidIndex(highestIDX); if (!result) { break; } // XOHCL iHBar; result = iHBar.Init( bar.symbol, bar.period, highestIDX // ); if (!result) { break; } // result = // price < iHBar.high // ; if (result) { // dest = iHBar; break; } } // result = dest.IsValid(); // return result; } // // Trend Detection ... // // Find Bullish Trend ... bool HasBullishTrend( XOHCL &bar, XOHCL &highSwingBars[], XOHCL &lowSwingBars[], bool forceMethod2 = false, int _loopback = 3, int tries = 3, ENUM_X_PRICE type = X_PRICE_CLOSE // ) { // bool result = false; // Clean(lowSwingBars); Clean(highSwingBars); // result = bar.IsValid(); if (!result) { return result; } // double price = bar.GetPrice(type); // int lastIDX = bar.Index(); double lastH = 0; double lastL = 0; for (int i = 1; i < tries + 1; i++) { // // Use Regular Method ... if (!forceMethod2) { // int iHIDX = FindSwing( bar.symbol, bar.period, X_SWING_HIGH, _loopback, lastIDX // ); result = IsValidIndex(iHIDX); if (!result) { break; } // XOHCL iHBar; result = iHBar.Init( bar.symbol, bar.period, iHIDX // ); if (!result) { break; } // double iH = iHBar.high; bool isIHAccepted = // iH > 0 && ( // lastH == 0 ? true : iH < lastH // ) // ; if (isIHAccepted) { // AddRef( iHBar, highSwingBars // ); // lastH = iH; lastIDX = iHIDX; } // int iLIDX = FindSwing( bar.symbol, bar.period, X_SWING_LOW, _loopback, lastIDX // ); result = IsValidIndex(iLIDX); if (!result) { break; } // XOHCL iLBar; result = iLBar.Init( bar.symbol, bar.period, iLIDX // ); if (!result) { break; } // double iL = iLBar.low; bool isILAccepted = // iL > 0 && ( // lastL == 0 ? true : iL < lastL // ) // ; if (isILAccepted) { // AddRef( iLBar, lowSwingBars // ); // lastL = iL; lastIDX = iLIDX; } } // // Use Other MEthod ... else { // int _length = i * _loopback; int start = // i == 1 ? 1 : _length - _loopback // ; // int iHIDX = iHighest( bar.symbol, bar.period, MODE_HIGH, _loopback, start // ); result = IsValidIndex(iHIDX); if (!result) { break; } // XOHCL iHBar; result = iHBar.Init( bar.symbol, bar.period, iHIDX // ); if (!result) { break; } // double iH = iHBar.high; bool isIHAccepted = // iH > 0 && ( // lastH == 0 ? true : iH < lastH // ) // ; if (isIHAccepted) { // AddRef( iHBar, highSwingBars // ); // lastH = iH; lastIDX = iHIDX; } // int iLIDX = iLowest( bar.symbol, bar.period, MODE_LOW, _loopback, start // ); result = IsValidIndex(iLIDX); if (!result) { break; } // XOHCL iLBar; result = iLBar.Init( bar.symbol, bar.period, iLIDX // ); if (!result) { break; } // double iL = iLBar.low; bool isILAccepted = // iL > 0 && ( // lastL == 0 ? true : iL < lastL // ) // ; if (isILAccepted) { // AddRef( iLBar, lowSwingBars // ); // lastL = iL; lastIDX = iLIDX; } } } // if (result) { // result = // ArraySize(lowSwingBars) == tries && ArraySize(highSwingBars) == tries // ; } // if (!result) { // Clean(lowSwingBars); Clean(highSwingBars); } // return result; } // // Find Bearish Trend ... bool HasBearishTrend( XOHCL &bar, XOHCL &highSwingBars[], XOHCL &lowSwingBars[], bool forceMethod2 = false, int _loopback = 3, int tries = 3, ENUM_X_PRICE type = X_PRICE_CLOSE // ) { // bool result = false; // Clean(lowSwingBars); Clean(highSwingBars); // result = bar.IsValid(); if (!result) { return result; } // double price = bar.GetPrice(type); // int lastIDX = bar.Index(); double lastH = 0; double lastL = 0; for (int i = 1; i < tries + 1; i++) { // // Use Regular Method ... if (!forceMethod2) { // int iHIDX = FindSwing( bar.symbol, bar.period, X_SWING_HIGH, _loopback, lastIDX // ); result = IsValidIndex(iHIDX); if (!result) { break; } // XOHCL iHBar; result = iHBar.Init( bar.symbol, bar.period, iHIDX // ); if (!result) { break; } // double iH = iHBar.high; bool isIHAccepted = // iH > 0 && ( // lastH == 0 ? true : iH > lastH // ) // ; if (isIHAccepted) { // AddRef( iHBar, highSwingBars // ); // lastH = iH; lastIDX = iHIDX; } // int iLIDX = FindSwing( bar.symbol, bar.period, X_SWING_LOW, _loopback, lastIDX // ); result = IsValidIndex(iLIDX); if (!result) { break; } // XOHCL iLBar; result = iLBar.Init( bar.symbol, bar.period, iLIDX // ); if (!result) { break; } // double iL = iLBar.low; bool isILAccepted = // iL > 0 && ( // lastL == 0 ? true : iL > lastL // ) // ; if (isILAccepted) { // AddRef( iLBar, lowSwingBars // ); // lastL = iL; lastIDX = iLIDX; } } // // Use Other MEthod ... else { // int _length = i * _loopback; int start = // i == 1 ? 1 : _length - _loopback // ; // int iHIDX = iHighest( bar.symbol, bar.period, MODE_HIGH, _loopback, start // ); result = IsValidIndex(iHIDX); if (!result) { break; } // XOHCL iHBar; result = iHBar.Init( bar.symbol, bar.period, iHIDX // ); if (!result) { break; } // double iH = iHBar.high; bool isIHAccepted = // iH > 0 && ( // lastH == 0 ? true : iH > lastH // ) // ; if (isIHAccepted) { // AddRef( iHBar, highSwingBars // ); // lastH = iH; lastIDX = iHIDX; } // int iLIDX = iLowest( bar.symbol, bar.period, MODE_LOW, _loopback, start // ); result = IsValidIndex(iLIDX); if (!result) { break; } // XOHCL iLBar; result = iLBar.Init( bar.symbol, bar.period, iLIDX // ); if (!result) { break; } // double iL = iLBar.low; bool isILAccepted = // iL > 0 && ( // lastL == 0 ? true : iL > lastL // ) // ; if (isILAccepted) { // AddRef( iLBar, lowSwingBars // ); // lastL = iL; lastIDX = iLIDX; } } } // if (result) { // result = // ArraySize(lowSwingBars) == tries && ArraySize(highSwingBars) == tries // ; } // if (!result) { // Clean(lowSwingBars); Clean(highSwingBars); } // return result; } // // Order Blocks ... // // Find Bullish Order Block ... bool HasBullishOrderBlock( XOHCL &bar, XOHCL &orderBlock, int _minimumSameBars = 4 // ) { // bool result = false; // orderBlock.Clean(); // result = bar.IsValid(); if (!result) { return result; } // if (_minimumSameBars < 0) { _minimumSameBars = 4; } // XOHCL cBar; int founded = 0; int cIDX = bar.Index(); bool isEnough = false; while (!isEnough) { // result = cBar.Init( bar.symbol, bar.period, cIDX // ); if (!result) { break; } // result = cBar.IsBullish(); if (!result && cBar.IsBearish()) { break; } // cIDX++; founded++; } // // Here we have to check founded and if it's fill // our requirements ... // cIDX is Order Block Index ... result = // cBar.IsValid() && bar.high > cBar.high && founded >= _minimumSameBars // ; if (!result) { return result; } // result = orderBlock.Init( bar.symbol, bar.period, cIDX // ); if (!result) { // orderBlock.Clean(); return result; } // return result; } // // Find Bearish Order Block ... bool HasBearishOrderBlock( XOHCL &bar, XOHCL &orderBlock, int _minimumSameBars = 4 // ) { // bool result = false; // orderBlock.Clean(); // result = bar.IsValid(); if (!result) { return result; } // if (_minimumSameBars < 0) { _minimumSameBars = 4; } // XOHCL cBar; int founded = 0; int cIDX = bar.Index(); bool isEnough = false; while (!isEnough) { // bool isInited = cBar.Init( bar.symbol, bar.period, cIDX // ); // result = cBar.IsBearish(); if (!result && cBar.IsBullish()) { break; } // cIDX++; founded++; } // // Here we have to check founded and if it's fill // our requirements ... // cIDX is Order Block Index ... result = // cBar.IsValid() && bar.high < cBar.low && founded >= _minimumSameBars // ; if (!result) { return result; } // result = orderBlock.Init( bar.symbol, bar.period, cIDX // ); if (!result) { // orderBlock.Clean(); return result; } // return result; } // protected: // // private: // // // Props ... // // Actions ... // }; //