/////////////////////////////////////////////////////// // // 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 ... // // Extensions ... void FillLiquidity( XOHCL &lBar, ENUM_X_DIRECTION lDir, XBoxZone &lq, datetime to // ) { // // Normalize Args ... lq.Clean(); to = NormalizeTime(to); // // Validate Args ... bool has = lBar.IsValid() && HasDirection(lDir); if (!has) { return; } // lq.to = to; lq.dir = lDir; lq.type = "XLQ"; lq.from = lBar.time; lq.symbol = lBar.symbol; lq.period = lBar.period; lq.upper = IsBullish(lDir) ? lBar.GetDown() : lBar.high; lq.lower = IsBullish(lDir) ? lBar.low : lBar.GetUp(); } // // Implementations ... class XCBarAnalyser : public XCBase { // public: // // // Constructor(s) ... void XCBarAnalyser() { } // // Deconstructor ... void ~XCBarAnalyser() { } // // Getter(s) / Setter(s) ... // // Providers ... /** * 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; } /** * Fill Prices ... * * @param prices: double collection * @param bar: XOHCL instance reference, Provides Start ... * @param loopback: int, Specified How Many Bars Process ... * @param type: ENUM_X_PRICE member, Specified Price Type ... * * @return ( bool ) */ int FillPrice( double &prices[], XOHCL &bar, int loopback = 14, ENUM_X_PRICE type = X_PRICE_CLOSE // ) { // int result = 0; // Clean(prices); // loopback = NormalizeInt(loopback, 1); // bool has = IsValid(type) && bar.IsValid(); if (!has) { 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; has = CalculateLoopbackData( index, start, end, count, bar, loopback // ); if (!has) { return result; } // for (int i = start; i < end; i++) { // XOHCL iBar; bool isInited = iBar.Init( symbol, period, i // ); if (!isInited) { // iBar.Clean(); continue; } // double iPrice = iBar.GetPrice(type); // isInited = NotEmptyZero(iPrice); if (isInited) { // Add( iPrice, prices // ); } // iBar.Clean(); } // result = ArraySize(prices); has = result == count; if (!has) { // Clean(prices); } // ArrayReverse(prices); // return result; } /** * Calculate Price Range ... * * @param ranges: double Collection, Calculated Ranges ... * @param bar: XOHCL instance Reference, Start Bar ... * @param forceBody: bool, Force to Calculate Range using Body ... * @param forceDiff: bool, Force to Calculate Range using Onl Price Diff ... * @param loopback: int, loopback period for Range Calculations ... * * @return ( int ) */ int GetPriceRange( double &ranges[], XOHCL &bar, bool forceBody = false, bool forceDiff = false, int loopback = 14 // ) { // int result = 0; // Clean(ranges); // loopback = NormalizeInt(loopback, 1); // if (!bar.IsValid()) { return result; } // bool has = false; // // Select Uppers Prices ... double uppers[]; int uppersCount = 0; if (forceBody) { // has = FillPrice( uppers, bar, loopback, X_PRICE_UP // ); } else { // has = FillPrice( uppers, bar, loopback, X_PRICE_HIGH // ); } if (has) { uppersCount = ArraySize(uppers); } // // Select Lower Prices ... double lowers[]; int lowersCount = 0; if (forceBody) { // has = FillPrice( lowers, bar, loopback, X_PRICE_DOWN // ); } else { // has = FillPrice( lowers, bar, loopback, X_PRICE_LOW // ); } if (has) { lowersCount = ArraySize(lowers); } // // Validate Filled Prices ... has = IsValidSize(uppersCount) && IsValidSize(lowersCount) && uppersCount == lowersCount; if (!has) { // Clean(uppers); Clean(lowers); // return result; } // for (int i = 0; i < uppersCount; i++) { // double iDiff = uppers[i] - lowers[i]; double iValue = forceDiff ? iDiff : lowers[i] + iDiff; // Add( iValue, ranges // ); } // result = ArraySize(ranges); ArrayReverse(ranges); // // Cleanup Resources ... // Clean(uppers); Clean(lowers); // return result; } /** * Retrieve Price Velocities ... * * @param velocities: double Collection, Price Velocities ... * @param bar: XOHCL instance Reference, Start Bar ... * @param type: ENUM_X_PRICE member ... * @param loopback: int, loopback period for Calculations ... * * @return ( int ) */ int GetPriceVelocity( double &velocities[], XOHCL &bar, ENUM_X_PRICE type = X_PRICE_CLOSE, int loopback = 14 // ) { // int result = 0; // Clean(velocities); loopback = NormalizeInt(loopback, 1); // result = IsValid(type) && bar.IsValid(); // int to = bar.Index(); int from = to + loopback; for (int i = to; i < from; i++) { // double iPrice = GetAppliedPrice( bar.symbol, bar.period, i, type // ); // double pPrice = GetAppliedPrice( bar.symbol, bar.period, i + 1, type // ); // double iVelocity = MathAbs(iPrice - pPrice); Add( iVelocity, velocities // ); } // result = ArraySize(velocities); // return result; } /** * Calculate Price Change Percent ... * * @param bar: XOHCL instance Reference, Start Bar ... * @param type: ENUM_X_PRICE member, Specified Price Type ... * @param loopback: int, loopback period for Range Calculated ... * * @return ( double ) */ double GetPriceChangeRate( XOHCL &bar, ENUM_X_PRICE type = X_PRICE_MEDIAN, int loopback = 14 // ) { // double result = 0; // bool has = false; // loopback = NormalizeInt(loopback, 1); // has = bar.IsValid() && IsValid(type); if (!has) { return result; } // XOHCL oldBar; has = oldBar.Init( bar.symbol, bar.period, bar.Index() + loopback // ); if (!has) { // oldBar.Clean(); // return result; } double newPrice = bar.GetPrice(type); double oldPrice = oldBar.GetPrice(type); // result = ((newPrice - oldPrice) / oldPrice) / 100; // oldBar.Clean(); // return result; } /** * Detect Range Block ... */ bool DetectRangeBlocks( XOHCL &bar, XBoxZone &upper, XBoxZone &lower, int loopback = 288, ENUM_SERIESMODE upperRangeUpperMode = MODE_HIGH, ENUM_SERIESMODE upperRangeLowerMode = MODE_LOW, ENUM_SERIESMODE lowerRangeUpperMode = MODE_HIGH, ENUM_SERIESMODE lowerRangeLowerMode = MODE_LOW // ) { // bool result = false; // // Normalize Args ... upper.Clean(); lower.Clean(); loopback = NormalizeInt(loopback, 10); // // Validate Args ... result = bar.IsValid(); if (!result) { return result; } // XOHCL iBar; result = iBar.Init( bar.symbol, bar.period, bar.Index() + loopback // ); if (!result) { // iBar.Clean(); // return result; } // double hhUpper = iBar.FindHighest(loopback, upperRangeUpperMode); double hhLower = iBar.FindHighest(loopback, upperRangeLowerMode); // double llUpper = iBar.FindLowest(loopback, lowerRangeUpperMode); double llLower = iBar.FindLowest(loopback, lowerRangeLowerMode); // double bhhUpper = bar.FindHighest(iBar.Index() - bar.Index(), upperRangeUpperMode); double bhhLower = bar.FindHighest(iBar.Index() - bar.Index(), upperRangeLowerMode); // double bllUpper = bar.FindLowest(iBar.Index() - bar.Index(), lowerRangeUpperMode); double bllLower = bar.FindLowest(iBar.Index() - bar.Index(), lowerRangeLowerMode); // hhUpper = MathMax(hhUpper, bhhUpper); hhLower = MathMax(hhLower, bhhLower); // llUpper = MathMin(llUpper, bllUpper); llLower = MathMin(llLower, bllLower); // datetime from = GetBarTime( iBar.symbol, iBar.period, iBar.Index() + loopback // ); // upper.from = from; upper.type = "XRNG"; upper.to = bar.time; upper.upper = hhUpper; upper.lower = hhLower; upper.symbol = iBar.symbol; upper.period = iBar.period; upper.dir = X_DIRECTION_BEARISH; // lower.from = from; lower.type = "XRNG"; lower.to = bar.time; lower.upper = llUpper; lower.lower = llLower; lower.symbol = iBar.symbol; lower.period = iBar.period; lower.dir = X_DIRECTION_BULLISH; // result = upper.IsValid() && lower.IsValid(); if (!result) { // iBar.Clean(); upper.Clean(); lower.Clean(); } // iBar.Clean(); // return result; } /** * Calculate Specified Bars Range Volume ... * * @param bar: XOHCL instance reference ... * @param bullishVolume: double * @param bearishVolume: double * @param loopback: int * * @return ( bool ) */ bool CalculateRangeVolume( XOHCL &bar, double &bullishVolume, double &bearishVolume, int loopback = 5 // ) { // bool result = false; // // Normalize Args ... bullishVolume = 0; bearishVolume = 0; loopback = NormalizeInt(loopback, 3); // // Validate ... result = bar.IsValid(); if (!result) { return result; } // XOHCL iBar; bool has = false; int start = bar.Index(); int end = start + loopback; for (int i = start; i <= end; i++) { // iBar.Clean(); has = iBar.Init( bar.symbol, bar.period, i // ); if (!has) { // iBar.Clean(); // break; } // bool isBullish = iBar.IsBullish(); bool isBearish = iBar.IsBearish(); // if (isBullish) { bullishVolume += (double)iBar.volume; } else if (isBearish) { bearishVolume += (double)iBar.volume; } else { // bullishVolume += (double)iBar.volume; bearishVolume += (double)iBar.volume; } // iBar.Clean(); } // result = iBar.IsValid(); // iBar.Clean(); // 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() + 1; 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 if (isBearish) { // sameBearishBarsFounded++; canContinueForBullish = false; } else { // sameBullishBarsFounded = 0; sameBearishBarsFounded = 0; canContinueForBullish = false; canContinueForBearish = 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; } // index--; // dir = hasBullishSameBars ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // 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 forDir, ENUM_X_FIBO_LEVELS level // ) { // bool result = false; // result = bar.IsValid() && HasDirection(forDir); if (!result) { return result; } // bool isBullish = IsBullish(forDir); bool isBearish = IsBearish(forDir); // double fiboLevelValue = GetFibonacciLevel( bar.high, bar.low, level, forDir // ); // bool isBullishPressured = isBullish && bar.GetDown() > fiboLevelValue; bool isBearishPressured = isBearish && bar.GetUp() < fiboLevelValue; // result = isBullishPressured || isBearishPressured; // return result; } /** * Detect Big Price Change Happens or not ... * * @param bar: XOHCL instance reference, Start Bar ... * @param dir: ENUM_X_DIRECTION member, Event Direction ... * @param rootIDX: int, Root of Momentum Index ... * @param type: ENUM_X_PRICE member, Price Type ... * @param forcBodyInRange: bool, Use Body in Range Detection ... * @param rangeExtendMultiplier: double, a Multiplier for Checking Price Range ... * * @return ( bool ) */ bool IsSharp( XOHCL &bar, ENUM_X_DIRECTION &dir, int &rootIDX, ENUM_X_PRICE type = X_PRICE_CLOSE, bool forcBodyInRange = true, double rangeExtendMultiplier = 2.0 // ) { // bool result = false; // dir = X_DIRECTION_NONE; rangeExtendMultiplier = NormalizeDouble(rangeExtendMultiplier, 1); // result = bar.IsValid() && IsValid(type); if (!result) { return result; } // double minPriceChangePercent = 0; int loopback = GetPeriodSharpData( minPriceChangePercent, bar.period // ); // // Retrieve Price Change Percent ... double priceChangePercent = GetPriceChangeRate( bar, type, loopback // ); // // Velocities ... double velocities[]; int velocitiesCount = GetPriceVelocity( velocities, bar, type, loopback // ); double velocitiesAvg = GetAverage(velocities); double oldPrice = GetAppliedPrice( bar.symbol, bar.period, bar.Index() + loopback, type // ); double newPrice = bar.GetPrice(type); double currVelocity = MathAbs(oldPrice - newPrice); // // Calculate HH and LL ... // double hh = 0; double ll = 0; int hhIDX = -1; int llIDX = -1; result = CalculateLoopbackHLData( hhIDX, hh, llIDX, ll, bar, loopback // ); result = result && ll > 0 && hh > ll && IsValidIndex(llIDX) && IsValidIndex(hhIDX); if (!result) { return result; } // int hhDiff = (hhIDX - bar.Index()); int llDiff = (llIDX - bar.Index()); // // Bool Get Boundary Direction ... // // Check Price Change Rate ... // bool isBullish = // hhDiff <= 1 && llIDX > hhIDX && priceChangePercent > 0 && priceChangePercent >= minPriceChangePercent && currVelocity > (velocitiesAvg * rangeExtendMultiplier) // ; // bool isBearish = // llDiff <= 1 && hhIDX > llIDX && priceChangePercent < 0 && MathAbs(priceChangePercent) >= minPriceChangePercent && currVelocity > (velocitiesAvg * rangeExtendMultiplier) // ; // result = isBullish || isBearish; if (result) { // rootIDX = isBullish ? llIDX : hhIDX; // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // return result; } // // Actions ... /** * Check a Bar is End of an OrderBlock Bar or Not ... * * @param bar: XOHCL ... * @param box: XBoxZone ... * @param forceFVGBarType: bool, Force all Bars must be Same as Direction ... * @param forceOBTwoBar: bool, Force Two Bars of OB Start must be InDirection ... * * @return ( bool ) */ bool IsOB( XOHCL &bar, XBoxZone &box, bool forceFVGBarType = false, bool forceOBTwoBar = false // ) { // bool result = false; // box.Clean(); // result = bar.IsValid(); if (!result) { return result; } // // Check Bar Must be FVG ... result = IsFVG( bar, box, forceFVGBarType // ); if (!result) { // box.Clean(); // return result; } // box.type = "XOB"; // bool isBullish = box.IsBullish(); bool isBearish = box.IsBearish(); // // Order Block Includes an FVG which Starts by atleast One // or More Indirectional Bars ... XOHCL fvgLastBar; XOHCL fvgLastBarPrev; XOHCL fvgLastBarPrev2; // int barIndex = bar.Index(); int fvgLastBarIndex = barIndex + 3; result = fvgLastBar.Init( bar.symbol, bar.period, fvgLastBarIndex // ); result = result && fvgLastBar.GetPreviousBar(fvgLastBarPrev); result = result && fvgLastBarPrev.GetPreviousBar(fvgLastBarPrev2); if (!result) { // box.Clean(); fvgLastBar.Clean(); fvgLastBarPrev.Clean(); fvgLastBarPrev2.Clean(); // return result; } // // Check FVG Last Bar ... // bool isBullishBlock = isBullish && (fvgLastBar.IsBearish() || (fvgLastBar.IsBullish() && fvgLastBarPrev.IsBearish())); // bool isBearishBlock = isBearish && (fvgLastBar.IsBullish() || (fvgLastBar.IsBearish() && fvgLastBarPrev.IsBullish())); // // Update Box ... // if (isBullishBlock || isBearishBlock) { // box.from = fvgLastBar.time; // box.lower = MathMin(box.lower, fvgLastBar.low); box.upper = MathMax(box.upper, fvgLastBar.high); } // // Apply Force Two Bar ... if (forceOBTwoBar) { // isBullishBlock = isBullishBlock && fvgLastBarPrev.IsBearish(); // isBearishBlock = isBearishBlock && fvgLastBarPrev.IsBullish(); // // Update Box ... if (isBullishBlock || isBearishBlock) { // box.from = fvgLastBarPrev.time; box.lower = MathMin(box.lower, fvgLastBarPrev.low); box.upper = MathMax(box.upper, fvgLastBarPrev.high); } } // result = isBullishBlock || isBearishBlock; if (!result) { // box.Clean(); fvgLastBar.Clean(); fvgLastBarPrev.Clean(); // return result; } // result = box.IsValid(); // // Cleanup Resources ... // fvgLastBar.Clean(); fvgLastBarPrev.Clean(); // return result; } /** * Check a Bar is End of an FVG Bar or Not ... * * @param bar: XOHCL ... * @param box: XBoxZone ... * @param forceType: bool, Force all Bars must be Same as Direction ... * * @return ( bool ) */ bool IsFVG( XOHCL &bar, XBoxZone &box, bool forceType = false // ) { // bool result = false; // box.Clean(); // result = bar.IsValid(); if (!result) { return result; } // XOHCL pBar; XOHCL p2Bar; result = bar.GetPreviousBar(pBar); result = result && pBar.GetPreviousBar(p2Bar); if (!result) { // pBar.Clean(); p2Bar.Clean(); // return result; } // bool isBullish = p2Bar.high < bar.low; bool isBearish = p2Bar.low > bar.high; // result = isBullish || isBearish; // // Apply Force Type ... if (result) { // if (isBullish) { // result = bar.IsBullish() && pBar.IsBullish() && p2Bar.IsBullish(); } else if (isBearish) { // result = bar.IsBearish() && pBar.IsBearish() && p2Bar.IsBearish(); } } // if (result) { // box.to = bar.time; box.from = p2Bar.time; box.symbol = bar.symbol; box.period = bar.period; box.dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; box.upper = isBullish ? bar.low : p2Bar.low; box.lower = isBullish ? p2Bar.high : bar.high; box.type = "XFVG"; } // pBar.Clean(); p2Bar.Clean(); // result = box.IsValid(); // return result; } /** * Check a Bar is a Trigger Box or Not ... * * @param bar: XOHCL instance Referernce, Specified Start Bar to Check ... * @param trigger: XBoxZone instance Reference, Holds Detected Trigger Bar ... * @param ob: XBoxZone instance Reference, Holds Detected Trigger Bar's OB ... * @param fvg: XBoxZone instance Reference, Holds Detected Trigger Bar's FVG ... * @param rLiquidity: XBoxZone instance Reference, Holds Detected Trigger Bar's Reversal Side Liquidity ... * @param fLiquidity: XBoxZone instance Reference, Holds Detected Trigger Bar's Following Side Liquidity ... * @param swingBar: XOHCL instance Referernce, Holds Detected Trigger Bar's Swing ... * @param loopback: int, Loopback Bars Count ... * @param maxAllowedRange: double, Max Allowed Trigger's OB Range ... * @param minAllowedBlockEdgeLength: int, Min Allowed Block Edge Validation Length ... * @param forceOBOppositBar: bool, Force OB to Start by Opposite Bar ... * @param forceFVGBarType: bool, Force FVG to Has Same Bar Type ... * @param forceGapBarBreakout: bool, Force Gap Bar Breakout OB Edge ... * @param forceHasSwingBar: bool, Force Has Swing Bar ... * @param forceHasLiquidity: bool, Force Has Following Liquidity ... * @param forceHasReversalLiquidity: bool, Force Has Reversal Liquidity ... * * @return ( bool ) */ bool IsTrigger( XOHCL &bar, XBoxZone &trigger, XBoxZone &ob, XBoxZone &fvg, XBoxZone &rLiquidity, XBoxZone &fLiquidity, XOHCL &swingBar, int loopback = 10, double maxAllowedRange = 0.0, int minAllowedBlockEdgeLength = 0, bool forceOBOppositBar = true, bool forceFVGBarType = true, bool forceGapBarBreakout = true, bool forceHasSwingBar = true, bool forceHasLiquidity = true, bool forceHasReversalLiquidity = true // ) { // bool result = false; // // Normalize Args ... ob.Clean(); fvg.Clean(); trigger.Clean(); swingBar.Clean(); rLiquidity.Clean(); fLiquidity.Clean(); loopback = NormalizeInt(loopback, 5); // // Validate Args ... result = bar.IsValid(); if (!result) { return result; } // XOHCL pBar; XOHCL tmpBar; XOHCL tmpPBar; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; // result = bar.GetPreviousBar(pBar); // // Detect Base Order Block ... result = result && // // Order Block Detection ... IsOB( pBar, ob, forceFVGBarType, forceOBOppositBar // ) && // // Gap Detection ... IsFVG( pBar, fvg, forceFVGBarType // ); if (result) { // trigger = ob; trigger.type = "XTRG"; } // // Reading Requirements ... // double points = GetPoints(bar.symbol); // bool isBullish = ob.IsBullish(); bool isBearish = ob.IsBearish(); // int toIDX = trigger.ToIndex(); int fromIDX = trigger.FromIndex(); // // Validate Gaps Bar Breakeout ... if (result && forceGapBarBreakout) { // // Extract Gap Bar ... tmpBar.Clean(); tmpPBar.Clean(); result = // // Retrieve Bars ... fvg.ToBar(tmpBar) && tmpBar.GetPreviousBar(tmpPBar) && // // Validate Gap Bar is Momentum Bar ... IsMomentum( tmpPBar, iDir, 1 // ) && iDir == fvg.dir && // // Validate ... (isBullish ? tmpPBar.close > ob.upper : tmpPBar.close < ob.lower); // tmpBar.Clean(); tmpPBar.Clean(); } // // Validate Range ... if (result && maxAllowedRange > 0) { // double range = ob.GetRange(); result = range <= (maxAllowedRange * points); } // // Validating Swing Bar ... if (result && forceHasSwingBar) { // int swingIDX = -1; result = ob.FromBar(tmpBar); if (result) { // // Detect Swing Bar Index ... if (isBullish) { swingIDX = tmpBar.FindLowestIndex(loopback, MODE_LOW); } else if (isBearish) { swingIDX = tmpBar.FindHighestIndex(loopback, MODE_HIGH); } result = IsValidIndex(swingIDX); if (result) { // // Initialize Swing Bar ... result = swingBar.Init( bar.symbol, bar.period, swingIDX // ); } // // Update Trigger Block based on Swing Bar ... result = swingBar.IsValid(); if (result) { // // Update From ... trigger.from = ((datetime)MathMin((int)trigger.from, (int)swingBar.time)); // // Update Edge ... if (isBullish) { trigger.lower = MathMin(trigger.lower, swingBar.GetDown()); } else if (isBearish) { trigger.upper = MathMax(trigger.upper, swingBar.GetUp()); } } } // tmpBar.Clean(); } // // Validate Min Block Edge ... if (result && minAllowedBlockEdgeLength > 0) { // fromIDX = trigger.FromIndex(); if (result) { // // Looping Back ... for (int i = fromIDX; i < fromIDX + minAllowedBlockEdgeLength; i++) { // // Initialize i Bar ... result = tmpBar.Init( bar.symbol, bar.period, i // ); result = result && (isBullish ? tmpBar.low > trigger.lower : tmpBar.high > trigger.upper); if (!result) { break; } // tmpBar.Clean(); } result = tmpBar.IsValid(); // // Update Trigger Block ... if (result) { trigger.from = ((datetime)(MathMin((int)trigger.from, (int)tmpBar.time))); } } // tmpBar.Clean(); } // // Validating Liquidity ... if (result && (forceHasLiquidity || forceHasReversalLiquidity)) { // // Try to Detect Liquidity ... toIDX = ob.ToIndex(); for (int i = toIDX; i < toIDX + (loopback * 10); i++) { // // Initialize i Bar ... result = tmpBar.Init( bar.symbol, bar.period, i // ); if (!result) { break; } // // Detect Liquidity ... bool isRejected = result && IsRejected( tmpBar, iDir, false, // Force Bar Type ... true // Force Fibo Pressure ... ); bool isBullishRejected = isRejected && IsBullish(iDir); bool isBearishRejected = isRejected && IsBearish(iDir); // // Validate Liquidities ... if (isBullish) { // if (isBullishRejected && forceHasLiquidity && !fLiquidity.IsValid() && tmpBar.low < trigger.lower) { // // Filling Following Liquidity ... FillLiquidity( tmpBar, trigger.dir, fLiquidity, trigger.to // ); } // if (isBearishRejected && !rLiquidity.IsValid() && forceHasReversalLiquidity && tmpBar.high > trigger.upper) { // // Filling Revrsal Liquidity ... FillLiquidity( tmpBar, Opposit(trigger.dir), rLiquidity, trigger.to // ); } } else if (isBearish) { // if (isBearishRejected && forceHasLiquidity && !fLiquidity.IsValid() && tmpBar.high > trigger.upper) { // // Filling Following Liquidity ... FillLiquidity( tmpBar, trigger.dir, fLiquidity, trigger.to // ); } // if (isBullishRejected && !rLiquidity.IsValid() && forceHasReversalLiquidity && tmpBar.low < trigger.lower) { // // Filling Reversal Liquidity ... FillLiquidity( tmpBar, Opposit(trigger.dir), rLiquidity, trigger.to // ); } } // if ((!forceHasLiquidity ? true : fLiquidity.IsValid()) && (!forceHasReversalLiquidity ? true : rLiquidity.IsValid())) { break; } // tmpBar.Clean(); } tmpBar.Clean(); // result = (!forceHasLiquidity ? true : fLiquidity.IsValid()) && (!forceHasReversalLiquidity ? true : rLiquidity.IsValid()); } // // Cleanup Resources ... // pBar.Clean(); tmpBar.Clean(); tmpPBar.Clean(); // if (!result) { // ob.Clean(); fvg.Clean(); trigger.Clean(); swingBar.Clean(); rLiquidity.Clean(); fLiquidity.Clean(); // return result; } // return result; } // // Candlestick ... /** * Check Specified Bar is Doji Pattern or not ... * * @param bar: XOHCL instance reference, Specified Bar to Check ... * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... * @param shadowMultiplier: double, Specified Shadow Multiplier ... * * @return ( bool ) */ bool IsDoji( XOHCL &bar, ENUM_X_DIRECTION &dir, double shadowMultiplier = 1.5 // ) { // bool result = false; // dir = X_DIRECTION_NONE; shadowMultiplier = NormalizeDouble(shadowMultiplier, 1.5, 3); // result = bar.IsValid(); if (!result) { return result; } // double body = bar.GetBody(); double range = bar.GetRange(); // result = body > 0 && range > 0 ? (body / range < 0.1) : false; if (result) { // dir = bar.GetLowShadow() >= (bar.GetHighShadow() * shadowMultiplier) ? X_DIRECTION_BULLISH : bar.GetHighShadow() >= (bar.GetLowShadow() * shadowMultiplier) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; // result = HasDirection(dir); } // return result; } /** * Check Specified Bar is Swing or not ... * * @param bar: XOHCL instance reference, Specified Bar to Check ... * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... * @param loopback: int, Specified Loopback ... * * @return ( bool ) */ bool IsSwing( XOHCL &bar, ENUM_X_DIRECTION &dir, int loopback = 7 // ) { // bool result = false; // dir = X_DIRECTION_NONE; loopback = NormalizeInt(loopback, 1); // result = bar.IsValid(); if (!result) { return result; } // XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { // pBar.Clean(); return result; } // XOHCL ppBar; result = pBar.GetPreviousBar(ppBar); if (!result) { // pBar.Clean(); ppBar.Clean(); return result; } // bool isBullish = // pBar.low < bar.low && pBar.low < ppBar.low && bar.GetDown() > pBar.low // ; // bool isBearish = // pBar.high > bar.high && pBar.high > ppBar.high && bar.GetUp() < pBar.high // ; // result = isBullish || isBearish; if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // ppBar.Clean(); int pBarIDX = pBar.Index(); for (int i = pBarIDX + 1; i < pBarIDX + loopback; i++) { // bool has = ppBar.Init( pBar.symbol, pBar.period, i // ); // isBullish = has && isBullish && pBar.low < ppBar.low; // isBearish = has && isBearish && pBar.high > ppBar.high; } // result = isBullish || isBearish; if (!result) { dir = X_DIRECTION_NONE; } } // // Cleanup Resources ... // pBar.Clean(); ppBar.Clean(); // return result; } /** * Check Specified Bar's Prev Bar is Simple Swing or not ... * * @param bar: XOHCL instance reference, Specified Bar to it's Prev Check ... * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... * * @return ( bool ) */ bool IsSimpleSwing( XOHCL &bar, ENUM_X_DIRECTION &dir // ) { // bool result = false; // dir = X_DIRECTION_NONE; // // Valdate Args ... result = bar.IsValid(); // // Reading Requirements ... XOHCL cBar; XOHCL pBar; XOHCL p2Bar; result = bar.GetPreviousBar(cBar); result = result && cBar.GetPreviousBar(pBar); result = result && pBar.GetPreviousBar(p2Bar); if (!result) { // cBar.Clean(); pBar.Clean(); p2Bar.Clean(); // return result; } // // Now we Have to Check pBar is Swing Low or High ... // bool isPBarSwingLow = pBar.low < cBar.low && pBar.low < p2Bar.low; // bool isPBarSwingHigh = pBar.high > cBar.high && pBar.high > p2Bar.high; // result = isPBarSwingLow || isPBarSwingHigh; if (result) { // dir = isPBarSwingLow ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // // Cleanup Resourses ... // cBar.Clean(); pBar.Clean(); p2Bar.Clean(); // return result; } /** * Check Specified Bar is Hammer Pattern or not ... * * @param bar: XOHCL instance reference, Specified Bar to Check ... * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... * @param bodyMultiplier: double, Specified Body Multiplier ... * * @return ( bool ) */ bool IsHammer( XOHCL &bar, ENUM_X_DIRECTION &dir, double bodyMultiplier = 2.0 // ) { // bool result = false; // dir = X_DIRECTION_NONE; bodyMultiplier = NormalizeDouble(bodyMultiplier, 1.5, 3); // result = bar.IsValid(); if (!result) { return result; } // double body = bar.GetBody(); double lShadow = bar.GetLowShadow(); double hShadow = bar.GetHighShadow(); // bool isBullish = hShadow < body && lShadow > (bodyMultiplier * body); // bool isBearish = lShadow < body && hShadow > (bodyMultiplier * body); // result = isBullish || isBearish; if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // return result; } /** * Check Specified Bar is Engulfed Prev Bar or not ... * * @param bar: XOHCL instance reference, Specified Bar to Check ... * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... * * @return ( bool ) */ bool IsEngulfed( XOHCL &bar, ENUM_X_DIRECTION &dir // ) { // bool result = false; // dir = X_DIRECTION_NONE; // result = bar.IsValid(); if (!result) { return result; } // XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { // pBar.Clean(); return result; } // result = bar.GetBody() > pBar.GetBody(); if (!result) { // pBar.Clean(); return result; } // bool isBullish = bar.IsBullish() && pBar.IsBearish() && bar.GetDown() <= pBar.GetDown() && bar.GetUp() > pBar.GetUp(); // bool isBearish = bar.IsBearish() && pBar.IsBullish() && bar.GetUp() >= pBar.GetUp() && bar.GetDown() < pBar.GetDown(); // result = isBullish || isBearish; if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // // Cleanup Resources ... // pBar.Clean(); // return result; } /** * Check Specified Bar is Momentum Bar or not ... * * @param bar: XOHCL instance reference, Specified Bar to Check ... * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... * @param forceBarType: bool, Force Apply Bar Type ... * @param forceFiboPressure: bool, Force Apply Bar Type ... * * @return ( bool ) */ bool IsRejected( XOHCL &bar, ENUM_X_DIRECTION &dir, bool forceBarType = true, bool forceFiboPressure = true // ) { // bool result = false; // dir = X_DIRECTION_NONE; // result = bar.IsValid(); if (!result) { return result; } // XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { // pBar.Clean(); return result; } // bool isBullish = // bar.low < pBar.low && bar.GetShadows() > bar.GetBody() && bar.GetLowShadow() > bar.GetBody() && bar.GetLowShadow() > bar.GetHighShadow() // ; // bool isBearish = // bar.high > pBar.high && bar.GetShadows() > bar.GetBody() && bar.GetHighShadow() > bar.GetBody() && bar.GetHighShadow() > bar.GetLowShadow() // ; // result = isBullish || isBearish; if (!result) { // pBar.Clean(); return result; } // // Check Force Type ... if (forceBarType) { // isBullish = isBullish && bar.IsBullish(); // isBearish = isBearish && bar.IsBearish(); // result = isBullish || isBearish; if (!result) { // pBar.Clean(); return result; } } // // Check Force Fibo Pressure ... if (forceFiboPressure) { // bool hasBullishFiboPressure = HasFiboPressure( bar, X_DIRECTION_BULLISH, X_FIBO_LEVEL_236 // ); // bool hasBearishFiboPressure = HasFiboPressure( bar, X_DIRECTION_BEARISH, X_FIBO_LEVEL_236 // ); // isBullish = isBullish && hasBullishFiboPressure; // isBearish = isBearish && hasBearishFiboPressure; } // result = isBullish || isBearish; if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // pBar.Clean(); // return result; } /** * Check Specified Bar is Momentum Bar or not ... * * @param bar: XOHCL instance reference, Specified Bar to Check ... * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... * @param loopback: int, Specified Loopback ... * * @return ( bool ) */ bool IsMomentum( XOHCL &bar, ENUM_X_DIRECTION &dir, int loopback = 2 // ) { // bool result = false; // dir = X_DIRECTION_NONE; loopback = NormalizeInt(loopback, 1); // result = bar.IsValid(); if (!result) { return result; } // XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { // pBar.Clean(); return result; } // // Calculate HH and LL ... double hh = 0; double ll = 0; int hhIDX = -1; int llIDX = -1; result = CalculateLoopbackHLData( hhIDX, hh, llIDX, ll, bar, loopback // s ); result = result && ll > 0 && hh > ll && IsValidIndex(llIDX) && IsValidIndex(hhIDX); if (!result) { // pBar.Clean(); return result; } // bool isBullish = bar.low > ll && bar.close >= hh && bar.IsBullish() && bar.low > pBar.low && bar.high > pBar.high && bar.GetBody() > pBar.GetBody() && bar.GetRange() > pBar.GetRange() && bar.GetShadows() < pBar.GetShadows(); // bool isBearish = bar.high < hh && bar.close <= ll && bar.IsBearish() && bar.low < pBar.low && bar.high < pBar.high && bar.GetBody() > pBar.GetBody() && bar.GetRange() > pBar.GetRange() && bar.GetShadows() < pBar.GetShadows(); // result = isBullish || isBearish; if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // pBar.Clean(); // return result; } /** * Check Specified Bar is Pullback or not ... * * @param bar: XOHCL instance reference, Specified Bar to Check ... * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... * @param loopback: int, Specified Loopback ... * @param forceBody: bool, Force Using Body ... * * @return ( bool ) */ bool IsPullback( XOHCL &bar, ENUM_X_DIRECTION &dir, int loopback = 3, bool forceBody = false // ) { // bool result = false; // dir = X_DIRECTION_NONE; loopback = NormalizeInt(loopback, 3); // result = bar.IsValid(); if (!result) { return result; } // // Check Bar Must Engulfed ... result = IsEngulfed( bar, dir // ); if (!result) { return result; } // // Calculate HH and LL ... double hh = 0; double ll = 0; int hhIDX = -1; int llIDX = -1; result = CalculateLoopbackHLData( hhIDX, hh, llIDX, ll, bar, loopback // ); result = result && ll > 0 && hh > ll && IsValidIndex(llIDX) && IsValidIndex(hhIDX); if (!result) { return result; } // bool isBullish = bar.high > hh && bar.low > ll; // bool isBearish = bar.high < hh && bar.low < ll; // result = isBullish || isBearish; if (result) { // if (forceBody) { // isBullish = isBullish && bar.GetUp() > hh && bar.GetDown() > ll && llIDX == bar.Index() + 1; // isBearish = isBearish && bar.GetUp() < hh && bar.GetDown() < ll && hhIDX == bar.Index() + 1; // result = isBullish || isBearish; } // if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } } // return result; } /** * Check Specified Bar is Sequence Edge Breaker Bar or not ... * * @param bar: XOHCL instance reference, Specified Bar to Check ... * @param dir: ENUM_X_DIRECTION member, Holds Founded Direction ... * @param loopback: int, Specified Loopback ... * * @return ( bool ) */ bool IsSeqBreakEdge( XOHCL &bar, ENUM_X_DIRECTION &dir, int loopback = 3 // ) { // bool result = false; // // Normalize Args ... dir = X_DIRECTION_NONE; loopback = NormalizeInt(loopback, 3); // // Validate Args ... result = bar.IsValid(); if (!result) { return result; } // bool isBullish = false; bool isBearish = false; // // Check Has Sequence or not ... XOHCL pBar; XOHCL iBar; XOHCL iPBar; bool has = false; int index = bar.Index(); int start = index + 1; int end = start + loopback - 1; bool hasBullishSeq = true; bool hasBearishSeq = true; for (int i = start; i < end; i++) { // // Initialize Indexed Bar(s) ... has = iBar.Init( bar.symbol, bar.period, i // ); has = has && iBar.GetPreviousBar(iPBar); // // Bullish Sequence ... if (hasBullishSeq) { // hasBullishSeq = has && iBar.low > iPBar.low; } // // Bearish Sequence ... if (hasBearishSeq) { // hasBearishSeq = has && iBar.high < iPBar.high; } // if (!hasBullishSeq && !hasBearishSeq) { break; } // iBar.Clean(); iPBar.Clean(); } iBar.Clean(); iPBar.Clean(); // // Check a Sequence Detect ... result = hasBullishSeq || hasBearishSeq; if (!result) { // pBar.Clean(); iBar.Clean(); iPBar.Clean(); // return result; } // // Retrieve Previous Bar ... result = bar.GetPreviousBar(pBar); // // Now we Have Ensure has a Sequence ... // isBullish = result && hasBearishSeq && bar.high > pBar.high; // isBearish = result && hasBullishSeq && bar.low < pBar.low; // // Summarizing Result ... result = isBullish || isBearish; if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // // Cleanup Resources ... pBar.Clean(); iBar.Clean(); iPBar.Clean(); // return result; } /** * Check Specified Bar is Sequence Type Breaker Bar or not ... * * @param bar: XOHCL instance reference, Specified Bar to Check ... * @param dir: ENUM_X_DIRECTION member, Holds Founded Direction ... * @param loopback: int, Specified Loopback ... * * @return ( bool ) */ bool IsSeqBreakType( XOHCL &bar, ENUM_X_DIRECTION &dir, int loopback = 3 // ) { // bool result = false; // // Normalize Args ... dir = X_DIRECTION_NONE; loopback = NormalizeInt(loopback, 3); // // Validate Args ... result = bar.IsValid(); if (!result) { return result; } // bool isBullish = false; bool isBearish = false; // // Check Has Sequence or not ... XOHCL iBar; bool has = false; int index = bar.Index(); int start = index + 1; int end = start + loopback; bool hasBullishSeq = true; bool hasBearishSeq = true; for (int i = start; i < end; i++) { // // Initialize Indexed Bar(s) ... has = iBar.Init( bar.symbol, bar.period, i // ); // // Bullish Sequence ... if (hasBullishSeq) { // hasBullishSeq = has && iBar.IsBullish(); } // // Bearish Sequence ... if (hasBearishSeq) { // hasBearishSeq = has && iBar.IsBearish(); } // if (!hasBullishSeq && !hasBearishSeq) { break; } // iBar.Clean(); } iBar.Clean(); // // Check a Sequence Detect ... result = hasBullishSeq || hasBearishSeq; if (!result) { // iBar.Clean(); // return result; } // // Now we Have Ensure has a Sequence ... // isBullish = result && hasBearishSeq && bar.IsBullish(); // isBearish = result && hasBullishSeq && bar.IsBearish(); // // Summarizing Result ... result = isBullish || isBearish; if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // // Cleanup Resources ... iBar.Clean(); // return result; } /** * Check Specified Bar is Fully Sequence Breker Bar or not ... * * @param bar: XOHCL instance reference, Specified Bar to Check ... * @param dir: ENUM_X_DIRECTION member, Holds Founded Direction ... * @param loopback: int, Specified Loopback ... * * @return ( bool ) */ bool IsSeqBreak( XOHCL &bar, ENUM_X_DIRECTION &dir, int loopback = 3 // ) { // bool result = false; // // Normalize Args ... dir = X_DIRECTION_NONE; loopback = NormalizeInt(loopback, 3); // // Validate Args ... result = bar.IsValid(); if (!result) { return result; } // // Check Seq Edge ... ENUM_X_DIRECTION seqEdgeDir; bool isSeqEdgeBreaked = IsSeqBreakEdge( bar, seqEdgeDir // ); // // Check Seq Type ... ENUM_X_DIRECTION seqTypeDir; bool isSeqTypeBreaked = IsSeqBreakType( bar, seqTypeDir // ); // // Check Result ... result = isSeqEdgeBreaked && isSeqTypeBreaked && seqEdgeDir == seqTypeDir; if (result) { dir = seqEdgeDir; } // return result; } // // // /** * Check a Bar is Valid for Specified Direction of Positions ... * * @param bar: XOHCL instance, Start Bar ... * @param dir: ENUM_X_DIRECTION member, Provide Direction ... * * @return ( bool ) */ bool IsValidForTrigger( XOHCL &bar, ENUM_X_DIRECTION &dir, bool allowCond1 = true, bool allowCond2 = true, bool allowCond3 = true, bool allowCond4 = true, bool allowCond5 = true, bool allowCond6 = true, bool allowCond7 = true // ) { // bool result = false; // // Normalize Args ... dir = X_DIRECTION_NONE; // // Validate Args ... result = bar.IsValid(); if (!result) { return result; } // // Prepare Requirements ... XOHCL pBar; XOHCL p2Bar; int loopback = 3; bool isBullish = false; bool isBearish = false; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; // // Retrieve Bar's Prev ... result = bar.GetPreviousBar(pBar); result = result && pBar.GetPreviousBar(p2Bar); // // Handle Detect Trigger Bar ... if (result) { // // Check States ... // // Rejected ... bool isRejected = IsRejected( pBar, iDir, false, // Force Type ... true // Force Fibo Pressure ... ); bool isBullishRejected = isRejected && IsBullish(iDir); bool isBearishRejected = isRejected && IsBearish(iDir); // // Simple Rejected ... bool isSimpleRejected = IsRejected( pBar, iDir, false, // Force Type ... false // Force Fibo Pressure ... ); bool isSimpleBullishRejected = isSimpleRejected && IsBullish(iDir); bool isSimpleBearishRejected = isSimpleRejected && IsBearish(iDir); // // Full Directional Rejection ... bool isFullRejected = IsRejected( pBar, iDir, true, // Force Type ... true // Force Fibo Pressure ... ); bool isFullBullishRejected = isFullRejected && IsBullish(iDir); bool isFullBearishRejected = isRejected && IsBearish(iDir); // // Engulfed ... bool isEngulfed = IsEngulfed( pBar, iDir // ); bool isBullishEngulfed = isEngulfed && IsBullish(iDir); bool isBearishEngulfed = isEngulfed && IsBearish(iDir); // // Momentum ... bool isMomentum = IsMomentum( pBar, iDir // ); bool isBullishMomentum = isMomentum && IsBullish(iDir); bool isBearishMomentum = isMomentum && IsBearish(iDir); // // Simple Swing ... bool isSwing = IsSimpleSwing( pBar, iDir // ); bool isBullishSwing = isSwing && IsBullish(iDir); bool isBearishSwing = isSwing && IsBearish(iDir); // // Full Swing ... bool isFullSwing = IsSwing( pBar, iDir, 5 // ); bool isFullBullishSwing = isFullSwing && IsBullish(iDir); bool isFullBearishSwing = isFullSwing && IsBearish(iDir); // // Sequence Breaker ... bool isSeqBreak = IsSeqBreak( pBar, iDir, 3 // ); bool isBullishSeqBreak = isSeqBreak && IsBullish(iDir); bool isBearishSeqBreak = isSeqBreak && IsBearish(iDir); // // Now we have to Combine Conditions ... // // Cond 1 ... bool isBullishCond1 = false; bool isBearishCond1 = false; if (allowCond1) { // // Bullish ... isBullishCond1 = // isFullBullishRejected // ; // // Bearish ... isBearishCond1 = // isFullBearishRejected // ; } // // Cond 2 ... bool isBullishCond2 = false; bool isBearishCond2 = false; if (allowCond2) { // // Bullish ... isBullishCond2 = // isBullishSwing && isBullishRejected // ; // // Bearish ... isBearishCond2 = // isBearishSwing && isBearishRejected // ; } // // Cond 3 ... bool isBullishCond3 = false; bool isBearishCond3 = false; if (allowCond3) { // // Bullish ... isBullishCond3 = // isBullishSwing && (isBullishRejected || isBullishEngulfed || isBullishMomentum) // ; // // Bearish ... isBearishCond3 = // isBearishSwing && (isBearishRejected || isBearishEngulfed || isBearishMomentum) // ; } // // Cond 4 ... bool isBullishCond4 = false; bool isBearishCond4 = false; if (allowCond4) { // // Bullish ... isBullishCond4 = // isBullishSwing && isBullishSeqBreak && (isBullishRejected || isBullishEngulfed || isBullishMomentum) // ; // // Bearish ... isBearishCond4 = // isBearishSwing && isBearishSeqBreak && (isBearishRejected || isBearishEngulfed || isBearishMomentum) // ; } // // Cond 5 ... bool isBullishCond5 = false; bool isBearishCond5 = false; if (allowCond5) { // // Bullish ... isBullishCond5 = // isFullBullishSwing && (isBullishRejected || isBullishEngulfed || isBullishMomentum) // ; // // Bearish ... isBearishCond5 = // isFullBearishSwing && (isBearishRejected || isBearishEngulfed || isBearishMomentum) // ; } // // Cond 6 ... bool isBullishCond6 = false; bool isBearishCond6 = false; if (allowCond6) { // // Bullish ... isBullishCond6 = // p2Bar.IsBearish() && pBar.IsBullish() && pBar.low < p2Bar.low && pBar.high > p2Bar.high && pBar.GetDown() <= p2Bar.GetDown() && (isBullishEngulfed || isBullishMomentum || isSimpleBullishRejected) // ; // // Bearish ... isBearishCond6 = // p2Bar.IsBullish() && pBar.IsBearish() && pBar.high > p2Bar.high && pBar.low < p2Bar.low && pBar.GetUp() >= p2Bar.GetUp() && (isBearishEngulfed || isBearishMomentum || isSimpleBearishRejected) // ; } // // Cond 7 ... bool isBullishCond7 = false; bool isBearishCond7 = false; if (allowCond7) { // // Bullish ... isBullishCond7 = // p2Bar.IsBearish() && pBar.IsBullish() && pBar.low < p2Bar.low && pBar.high > p2Bar.high && pBar.GetUp() >= p2Bar.GetUp() // ; // // Bearish ... isBearishCond7 = // p2Bar.IsBullish() && pBar.IsBearish() && pBar.high > p2Bar.high && pBar.low < p2Bar.low && pBar.GetDown() <= p2Bar.GetDown() // ; } // // Summarizie Result ... // isBullish = // isBullishCond1 || isBullishCond2 || isBullishCond3 || isBullishCond4 || isBullishCond5 || isBullishCond6 || isBullishCond7 // ; // isBearish = // isBearishCond1 || isBearishCond2 || isBearishCond3 || isBearishCond4 || isBearishCond5 || isBearishCond6 || isBearishCond7 // ; } // // Summarize Result ... result = (isBullish && !isBearish) || (isBearish && !isBullish); if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // // Cleanup Resources ... pBar.Clean(); p2Bar.Clean(); // return result; } // protected: // // private: // // // Props ... // // Actions ... // }; //