From 29c9df62c54ceab2f57037d962986277ccfa2bb3 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Tue, 3 Dec 2024 01:03:32 +0330 Subject: [PATCH] Last ... --- Documents/BKP/tmp.x121.smc.mq5 | 330 ++ Documents/BKP/x-121.smc.lib.mq5 | 2161 ++++++++++++ .../x-121.smc.test.strategy.class copy.mq5 | 3064 +++++++++++++++++ Libraries/x-saherelm.common.lib.mq5 | 29 + .../x-121.smc.market.cycle.helper.class.mq5 | 784 +++++ X121SMCEA/Libraries/x-121.smc.lib.mq5 | 8 - .../x-121.smc.test.strategy.class.mq5 | 376 +- 7 files changed, 6420 insertions(+), 332 deletions(-) create mode 100644 Documents/BKP/x-121.smc.lib.mq5 create mode 100644 Documents/BKP/x-121.smc.test.strategy.class copy.mq5 diff --git a/Documents/BKP/tmp.x121.smc.mq5 b/Documents/BKP/tmp.x121.smc.mq5 index 5730d7c0..7cb011d4 100644 --- a/Documents/BKP/tmp.x121.smc.mq5 +++ b/Documents/BKP/tmp.x121.smc.mq5 @@ -2261,3 +2261,333 @@ { bearOB = mBearOB; } + + + +//////////////////////////////////////////////////////////// + + + // + // Detect an Order Block in Vision ... + if (conditions.visionBullOB == NULL || + conditions.visionBearOB == NULL) + { + // + result = DetectOrderBlocks( + NULL, + NULL, + conditions.visionBullOB, + conditions.visionBearOB, + cBar, + mVisionState // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + XCBullishOrderBlockObject *iBullOBObj; + conditions.visionBullOB.To(cTime); + result = mPOIDrawer.CreateBullishOrderBlock( + conditions.visionBullOB, + iBullOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBullOBObj); + } + + // + XCBearishOrderBlockObject *iBearOBObj; + conditions.visionBearOB.To(cTime); + result = mPOIDrawer.CreateBearishOrderBlock( + conditions.visionBearOB, + iBearOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBearOBObj); + } + } + + // + // Consolidation Order Blocks ... + if (conditions.consolidationBullOB == NULL || + conditions.consolidationBearOB == NULL) + { + // + result = DetectOrderBlocks( + conditions.visionBullOB, + conditions.visionBearOB, + conditions.consolidationBullOB, + conditions.consolidationBearOB, + cBar, + mConsolidationState // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + XCBullishOrderBlockObject *iBullOBObj; + conditions.consolidationBullOB.To(cTime); + result = mPOIDrawer.CreateBullishOrderBlock( + conditions.consolidationBullOB, + iBullOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBullOBObj); + } + + // + XCBearishOrderBlockObject *iBearOBObj; + conditions.consolidationBearOB.To(cTime); + result = mPOIDrawer.CreateBearishOrderBlock( + conditions.consolidationBearOB, + iBearOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBearOBObj); + } + } + + // + msg = "OrderBlocks Detected ..."; + Alert(msg); + + // + // Detect Trigger Order Flow ... + if (!HasValidOrderFlow()) + { + // + int samePivots = 40; + int requiredPivots = 10; + + // + bool useVisionState = false; + bool useConsolidationState = false; + bool useVerificationState = false; + bool useAnalyseState = false; + bool useDecisionState = true; + bool useTriggerState = false; + + // + DetectOrderFlow( + cIndex, + samePivots, + requiredPivots, + mTriggerCycleHelper, + mOrderFlow, + mOrderFlowDir, + // + // Filling Pivot State ... + useVisionState, // Use Vision State ... + useConsolidationState, // Use Consolidation State ... + useVerificationState, // Use Verification State ... + useAnalyseState, // Use Analyse State ... + useDecisionState, // Use Decision State ... + useTriggerState // Use Trigger State ... + ); + + // + result = HasValidOrderFlow(); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + bool ignoreSwingHighs = true; + bool ignoreSwingLows = true; + bool ignoreSupportZones = true; + bool ignoreResistanceZones = true; + bool ignoreSupplyZones = true; + bool ignoreDemandZones = true; + bool ignoreBullishOrderBlocks = true; + bool ignoreBearishOrderBlocks = true; + bool ignoreBullishFairValueGaps = true; + bool ignoreBearishFairValueGaps = true; + bool ignoreBullishRejectionBars = true; + bool ignoreBearishRejectionBars = true; + bool ignoreBullishMomentumBars = true; + bool ignoreBearishMomentumBars = true; + + // + RedrawOrderFlow( + false, // Force Clean ... + false, // Same Period ... + true, // Order Flow ... + true, // Order Flow State ... + false, // Only Last Order Flow ... + true, // Only Last Order Flow State ... + // + mOrderFlowDir, // Direction Force ... + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + msg = "Found OrderFlow : " + (IsBullish(mOrderFlowDir) ? "Bullish" : "Berish"); + Alert(msg); + + // + // Check Market Conditions for + // Specified Structure ... + // ENUM_X_DIRECTION marketStructureDir = X_DIRECTION_NONE; + // result = conditions.HasDirection( + // marketStructureDir, + // cBar // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + // msg = "Found Market Strucutre : " + (IsBullish(marketStructureDir) ? "Bullish" : "Berish"); + // Alert(msg); + + // + // conditions.marketStructureDir = marketStructureDir; + + // // + // XPVPivot lastPivot; + // result = GetLastItem( + // lastPivot, + // mOrderFlow // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + + // + // Detect Last FVG ... + // XOHCL breakerBar; + // result = DetectLastBreakerBar( + // cBar, + // breakerBar, + // lastPivot, + // marketStructureDir // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + // msg = "Found Breaker Bar: " + breakerBar.GetTag(); + // Alert(msg); + + // // + // // Detect Nearest Momentum or Rejection Bar ... + // XOHCL decisionBar; + // result = mDecisionCycleHelper.DetectNearestDecisionBar( + // decisionBar, + // marketStructureDir, + // cBar // + // ); + // if (!result) + // { + // return result; + // } + // msg = "Found Decision Bar: " + decisionBar.GetTag(); + // Alert(msg); + + // // + // // Detect Nearest Sar Change ... + // XOHCL sarChangeBar; + // result = mTriggerCycleHelper.DetectNearestCSARChange( + // sarChangeBar, + // cBar // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + // msg = "Found Sar Change Bar: " + sarChangeBar.GetTag(); + // Alert(msg); + + // // + // // Now we Hvae to Check Other Conditions ... + // result = + // // breakerBar.time > sarChangeBar.time && + // // decisionBar.time > breakerBar.time; + // decisionBar.time > sarChangeBar.time; + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + + // // + // // Now we Have Check Direction Related Conditions ... + // if (IsBullish(marketStructureDir)) + // { + // // + // result = + // // bid > decisionBar.high && + // // bid > breakerBar.high && + // bid > sarChangeBar.high && + // bid > conditions.triggerConditions.xchsarConditions.cSars[0]; + // } + // else + // { + // // + // result = + // // bid < decisionBar.low && + // // bid < breakerBar.low && + // bid < sarChangeBar.high && + // bid < conditions.triggerConditions.xchsarConditions.cSars[0]; + // } + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + + // // + // conditions.provider = "X121SMC"; + // if (IsBullish(marketStructureDir)) + // { + // // + // // conditions.sl = decisionBar.low; + // // conditions.sl = breakerBar.low; + // conditions.sl = conditions.triggerConditions.xchsarConditions.cSars[0]; + // } + // else + // { + // // + // // conditions.sl = decisionBar.high; + // // conditions.sl = breakerBar.high; + // conditions.sl = conditions.triggerConditions.xchsarConditions.cSars[0]; + // } diff --git a/Documents/BKP/x-121.smc.lib.mq5 b/Documents/BKP/x-121.smc.lib.mq5 new file mode 100644 index 00000000..19d97b4d --- /dev/null +++ b/Documents/BKP/x-121.smc.lib.mq5 @@ -0,0 +1,2161 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: X121SMCLib +// Description: provide all commonly used functions ... +// +// +// 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 "../../Helpers/x-saherelm.x3ma.helper.mq5" +#include "../../Helpers/x-saherelm.x3vwap.helper.mq5" +#include "../../Helpers/x-saherelm.xchsar.helper.mq5" +#include "../../Helpers/x-saherelm.xpv.helper.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" +#include "../../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../../Libraries/x-saherelm.x-trade.lib.mq5" + +// +// Definitions ... + +const string X121SMCStrategyToken = "X121SMC"; + +const string X121SMCPVToken = "X121SMCPV"; +const string X121SMCBOSToken = "X121SMCBOS"; +const string X121SMCSARToken = "X121SMCSAR"; +const string X121SMCCHOCHToken = "X121SMCCHOCH"; +const string X121SMCPULLBKToken = "X121SMCPULLBK"; + +enum ENUM_X_121_SMC_PROVIDERS +{ + // + X_121_SMC_PROVIDER_NONE, + X_121_SMC_PROVIDER_PV, + X_121_SMC_PROVIDER_BOS, + X_121_SMC_PROVIDER_SAR, + X_121_SMC_PROVIDER_CHOCH, + X_121_SMC_PROVIDER_PULLBK, +}; + +enum ENUM_XPV_PIVOTS +{ + XPV_NONE, + XPV_PEAK, + XPV_VALE, +}; + +struct XPVPivot +{ + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double upper; + double lower; + + // + datetime from; + datetime to; + + // + int repetition; + + // + ENUM_XPV_PIVOTS type; + + // + // Combined all States ... + XPOIState state; + + // + XPVPivot() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + + // + to = NULL; + from = NULL; + symbol = NULL; + period = NULL; + + // + repetition = 0; + + // + type = XPV_NONE; + + // + state.Clean(); + } + + /** + * Validation ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(to) && + IsValid(from) && + IsValid(symbol) && + IsValid(period) && + repetition > 0 && + type != XPV_NONE && + (upper > 0 || lower > 0) + // + ; + + // + return result; + } + + /** + * Check Pivot is Peak ... + * + * @return ( bool ) + */ + bool IsPeak() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_PEAK; + + // + return result; + } + + /** + * Check Pivot is Vale ... + * + * @return ( bool ) + */ + bool IsVale() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_VALE; + + // + return result; + } + + /** + * Calculate Lower for Peaks ... + * + * @return ( double ) + */ + double CalculateLower() + { + // + double result = 0; + + // + if (!IsValid() || + !IsPeak()) + { + return result; + } + + // + int fromIndex = iBarShift( + symbol, + period, + from // + ); + + // + int toIndex = iBarShift( + symbol, + period, + to // + ); + + // + int count = + fromIndex - toIndex; + + // + int llIDX = iLowest( + symbol, + period, + MODE_LOW, + count, + toIndex // + ); + + // + result = + iLow( + symbol, + period, + llIDX // + ); + + // + return result; + } + + /** + * Calculate Upper for Vales ... + * + * @return ( double ) + */ + double CalculateUpper() + { + // + double result = 0; + + // + if (!IsValid() || + !IsVale()) + { + return result; + } + + // + int fromIndex = iBarShift( + symbol, + period, + from // + ); + + // + int toIndex = iBarShift( + symbol, + period, + to // + ); + + // + int count = + fromIndex - toIndex; + + // + int hhIDX = iHighest( + symbol, + period, + MODE_HIGH, + count, + toIndex // + ); + + // + result = + iHigh( + symbol, + period, + hhIDX // + ); + + // + return result; + } + + /** + * Calculate Range of Pivot ... + * + * @return ( double ) + */ + double CalculateRange() + { + // + double result = 0; + + // + if (!IsValid() || + upper <= 0 || + lower <= 0) + { + return result; + } + + // + result = upper - lower; + + // + return result; + } + + /** + * Calculate Middle of Pivot ... + * Used for + * @return ( double ) + */ + double CalculateMid() + { + // + double result = 0; + + // + double range = CalculateRange(); + if (range <= 0) + { + return result; + } + + // + result = lower + (range / 2); + + // + return result; + } + + /** + * Calculate Liquidity Percent for Specified Direction ... + * + * @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ... + * @param price: Double, Specified Price ... + * + * @return ( double ) + */ + double CalculateLiquidityPercent( + ENUM_X_DIRECTION forDirection, + double price = 0 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = state + .CalculateLiquidityPercent( + forDirection, + price // + ); + + // + return result; + } + + // + + /** + * Get Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = symbol + "_" + + ToString(period) + "_" + + ToString(upper) + "," + + ToString(lower) + "_" + + ToString(from) + "," + + ToString(to); + hash = ToMD5(hash); + + // + string typeStr = + type == XPV_PEAK + ? "Peak" + : "Vale"; + + // + result = + // + "XPV_" + + typeStr + "_" + + symbol + "_" + + ToString(period) + + "_" + hash + // + ; + + // + return result; + } + + // +}; + +// +// Each Market Cycle (Time Frame) Conditions +// Model as this Structure ... +struct X121SMCCycleConditions +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + XPVConditions xpvConditions; + X3MAConditions x3maConditions; + X3VWAPConditions x3vwapConditions; + XCHSARConditions xchsarConditions; + + // + XPOIState state; + + // + void X121SMCStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + time = NULL; + + // + state.Clean(); + xpvConditions.Clean(); + x3maConditions.Clean(); + x3vwapConditions.Clean(); + xchsarConditions.Clean(); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + // + ; + + // + return result; + } + + /** + * Check Cycle Conditions Has Bullish State ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool IsBullish( + XOHCL &bar // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + + // + result = + // + // Check Conditions Validation ... + IsValid() && + // + // Check Bar Validation ... + bar.IsValid() && + // + // Check XCHSar Current is Bullish ... + xchsarConditions.isCBullish && + // + // Check X3VWAP is Bullish State ... + x3vwapConditions.isBullishState && + // + // Check X3VWAP is Bullish Ordered ... + x3vwapConditions.isBullishOrdered && + // + // Check Close Over X3MA Fast ... + bar.close > x3maConditions.fasts[index] + // + ; + + // + return result; + } + + /** + * Check Cycle Conditions Has Bearish State ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool IsBearish( + XOHCL &bar // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + + // + result = + // + // Check Conditions Validation ... + IsValid() && + // + // Check Bar Validation ... + bar.IsValid() && + // + // Check XCHSar Current is Bearish ... + xchsarConditions.isCBearish && + // + // Check X3VWAP is Bearish State ... + x3vwapConditions.isBearishState && + // + // Check X3VWAP is Bearish Ordered ... + x3vwapConditions.isBearishOrdered && + // + // Check Close Under X3MA Fast ... + bar.close < x3maConditions.fasts[index] + // + ; + + // + return result; + } + + // + // Reporter Functions ... + + /** + * Generate Provided Scores ... + * + * @param bullishScore: Integer, reference ... + * @param bearishScore: Integer, referenceF ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + if (!IsValid()) + { + return; + } + + // + double bullScore = 0; + double bearScore = 0; + + // // + // // XPV ... + // pvConditions.GenerateScore( + // bullScore, + // bearScore // + // ); + // bullishScore += bullScore; + // bearishScore += bearScore; + } + + /** + * Generate Summary ... + * + * @param onlyCommons: Boolean ... + * @param onlyConditions: Boolean ... + * @param includeScores: Boolean ... + * @param ignoreFalseConditions: Boolean ... + * @param separator: String ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores, + true // + ); + + // // + // // XPV ... + // string pvStr = pvConditions.GenerateSummary( + // false, + // true, + // false, + // ignoreFalseConditions // + // ); + + // + string conditionsStr = + // + // pvStr + separator + + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + "----------" + separator + + (onlyConditions + ? "" + : commonStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Get Unique Identifier ... + * + * @param forObject: Boolean ... + * + * @return ( string ) + */ + string GetTag( + bool forObject = false // + ) + { + // + string result = NULL; + + // + string typeName = GetTypeName(this); + + // + if (!forObject) + { + result = typeName; + } + else + { + // + result = typeName + "_" + + symbol + "_" + ToString(period) + "_" + + ToMD5(time); + } + + // + return result; + } + + // +}; + +// +// Model Signalling Conditions ... +struct X121SMCStrategyConditions +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Cycles Conditions here ... + X121SMCCycleConditions triggerConditions; + X121SMCCycleConditions decisionConditions; + X121SMCCycleConditions analyseConditions; + X121SMCCycleConditions verificationConditions; + X121SMCCycleConditions consolidationConditions; + X121SMCCycleConditions visionConditions; + + // + double sl; + string provider; + XCOrderBlock *visionBullOB; + XCOrderBlock *visionBearOB; + XCOrderBlock *consolidationBullOB; + XCOrderBlock *consolidationBearOB; + ENUM_X_DIRECTION marketStructureDir; + + // + void X121SMCStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + time = NULL; + + // + sl = 0; + provider = NULL; + visionBullOB = NULL; + visionBearOB = NULL; + consolidationBullOB = NULL; + consolidationBearOB = NULL; + marketStructureDir = X_DIRECTION_NONE; + + // + triggerConditions.Clean(); + decisionConditions.Clean(); + analyseConditions.Clean(); + verificationConditions.Clean(); + consolidationConditions.Clean(); + visionConditions.Clean(); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + + // + return result; + } + + /** + * Check Conditions has Ddirection or not ... + * + * @param dir: ENUM_X_DIRECTIOn member ... + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool HasDirection( + ENUM_X_DIRECTION &dir, + XOHCL &bar // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = IsValid() && + bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + int index = bar.Index(); + + // + // Parse Cycles Conditions ... + + // + // Vision ... + + // + bool isVisionBullish = + // + // XCHSar Current is Bullish ... + visionConditions.xchsarConditions.isCBullish && + // + // Close Over X3MA Fast ... + bar.close > visionConditions.x3maConditions.fasts[index] && + // + // X3VWap Fast is Bullish ... + visionConditions.x3vwapConditions.fastStates[index] == + X3VWAP_STATE_BULLISH + // + ; + + // + bool isVisionBearish = + // + // XCHSar Current is Bearish ... + visionConditions.xchsarConditions.isCBearish && + // + // Close Under X3MA Fast ... + bar.close < visionConditions.x3maConditions.fasts[index] && + // + // X3VWap Fast is Bearish ... + visionConditions.x3vwapConditions.fastStates[index] == + X3VWAP_STATE_BEARISH + // + ; + + // + // Check Vision Has Conditions or not ... + bool hasVisionConditions = + isVisionBullish || + isVisionBearish; + result = hasVisionConditions; + if (!result) + { + return result; + } + + // + // Consolidation ... + + // + bool isConsolidationBullish = consolidationConditions.IsBullish(bar); + bool isConsolidationBearish = consolidationConditions.IsBearish(bar); + bool hasConsolidationConditions = + isConsolidationBullish || + isConsolidationBearish; + result = hasConsolidationConditions; + if (!result) + { + return result; + } + + // + // Verification ... + + // + bool isVerificationBullish = verificationConditions.IsBullish(bar); + bool isVerificationBearish = verificationConditions.IsBearish(bar); + bool hasVerificationConditions = + isVerificationBullish || + isVerificationBearish; + result = hasVerificationConditions; + if (!result) + { + return result; + } + + // + // Analyse ... + + // + bool isAnalyseBullish = analyseConditions.IsBullish(bar); + bool isAnalyseBearish = analyseConditions.IsBearish(bar); + bool hasAnalyseConditions = + isAnalyseBullish || + isAnalyseBearish; + result = hasAnalyseConditions; + if (!result) + { + return result; + } + + // + // Decision ... + + // + bool isDecisionBullish = decisionConditions.IsBullish(bar); + bool isDecisionBearish = decisionConditions.IsBearish(bar); + bool hasDecisionConditions = + isDecisionBullish || + isDecisionBearish; + result = hasDecisionConditions; + if (!result) + { + return result; + } + + // + // Analyse Conditions ... + bool hasBullishConditions = + // + isVisionBullish && + isConsolidationBullish && + isVerificationBullish && + isAnalyseBullish && + isDecisionBullish + // + ; + bool hasBearishConditions = + // + isVisionBearish && + isConsolidationBearish && + isVerificationBearish && + isAnalyseBearish && + isDecisionBearish + // + ; + result = hasBullishConditions || + hasBearishConditions; + if (!result) + { + return result; + } + + // + // Specified Conditions Direction ... + dir = + hasBullishConditions + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Reporter Functions ... + + /** + * Generate Provided Scores ... + * + * @param bullishScore: Integer, reference ... + * @param bearishScore: Integer, referenceF ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + if (!IsValid()) + { + return; + } + + // + double bullScore = 0; + double bearScore = 0; + + // // + // // XPV ... + // pvConditions.GenerateScore( + // bullScore, + // bearScore // + // ); + // bullishScore += bullScore; + // bearishScore += bearScore; + } + + /** + * Generate Summary ... + * + * @param onlyCommons: Boolean ... + * @param onlyConditions: Boolean ... + * @param includeScores: Boolean ... + * @param ignoreFalseConditions: Boolean ... + * @param separator: String ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores, + true // + ); + + // // + // // XPV ... + // string pvStr = pvConditions.GenerateSummary( + // false, + // true, + // false, + // ignoreFalseConditions // + // ); + + // + string conditionsStr = + // + // pvStr + separator + + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + "----------" + separator + + (onlyConditions + ? "" + : commonStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Get Unique Identifier ... + * + * @param forObject: Boolean ... + * + * @return ( string ) + */ + string GetTag( + bool forObject = false // + ) + { + // + string result = NULL; + + // + string typeName = GetTypeName(this); + + // + if (!forObject) + { + result = typeName; + } + else + { + // + result = typeName + "_" + + symbol + "_" + ToString(period) + "_" + + ToMD5(time); + } + + // + return result; + } + + // +}; + +// +// +// + +typedef void (*TOnX121SMCSignal)( + XSignal &signal, + X121SMCStrategyConditions &conditions // +); + +// +// Extentions ... + +/** + * Find Oldest Pivot Index ... + * + * @param pivots: XPVPivot instance ... + * @return ( int ) + */ +int FindOldestPivotIndex( + XPVPivot &pivots[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(pivots); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = pivots[i]; + + // + bool isOldest = true; + for (int j = 0; j < count; j++) + { + // + XPVPivot jPivot = pivots[j]; + + // + isOldest = iPivot.from <= jPivot.from; + if (!isOldest) + { + break; + } + } + + // + if (isOldest) + { + // + result = i; + break; + } + } + + // + return result; +} + +/** + * Sort Pivots Based On From Date ... + * + * @param pivots: XPVPivot instance Collection reference ... + */ +void SortPivots( + XPVPivot &pivots[] // +) +{ + // + XPVPivot tmp[]; + Copy( + pivots, + tmp // + ); + + // + Clean(pivots); + + // + while (ArraySize(tmp) > 0) + { + // + if (ArraySize(tmp) == 1) + { + // + AddRef( + tmp[0], + pivots // + ); + + // + ArrayRemove( + tmp, + 0, + 1); + } + else + { + // + int idx = FindOldestPivotIndex(tmp); + if (IsValidIndex(idx)) + { + // + AddRef( + tmp[idx], + pivots // + ); + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + } + } + } + + // + Clean(tmp); +} + +bool IsPivotBreaked( + XPVPivot &pivot, + XPVPivot &pivots[] // +) +{ + // + bool result = false; + + // + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + int count = ArraySize(pivots); + result = IsValidSize(pivots); + if (!result) + { + return result; + } + + // + // For Peaks Highs Must not Broked ... + // For Vales Lows Must not Broked ... + bool isPeak = pivot.IsPeak(); + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = pivots[i]; + + // + result = isPeak + ? iPivot.upper > pivot.upper + : iPivot.lower < pivot.lower; + if (result) + { + break; + } + } + + // + return result; +} + +/** + * Filter Broken Pivots for Detect Order Flow ... + * + * @param pivots: XPVPivot instance Collection reference ... + */ +void FilterBrokenPivots( + XPVPivot &pivots[] // +) +{ + // + XPVPivot tmp[]; + Copy( + pivots, + tmp // + ); + + // + Clean(pivots); + + // + while (ArraySize(tmp) > 0) + { + // + if (ArraySize(tmp) == 1) + { + // + AddRef( + tmp[0], + pivots // + ); + + // + ArrayRemove( + tmp, + 0, + 1 // + ); + } + else + { + // + XPVPivot pivot = tmp[0]; + + // + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + bool isBreaked = IsPivotBreaked( + pivot, + tmp // + ); + if (!isBreaked) + { + // + AddRef( + pivot, + pivots // + ); + } + } + } + + // + Clean(tmp); +} + +/** + * Calculate Order Flow Direction ... + * + * @param orderFlow: XPVPivot instance Collection reference ... + * @param dir: ENUM_X_DIRECTION member reference, Hold's Calculated Direction ... + * + * @return ( bool ) + */ +bool DetectPivotDirection( + XPVPivot &orderFlow[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + int count = ArraySize(orderFlow); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + // For Bullish Direction all Exists lowers must be Greater or Equal Prev ... + bool isBullish = false; + bool canLookupForBullish = true; + + // + // For Bearish Direction all Exists uppers must be Lesser or Equal Prev ... + bool isBearish = false; + bool canLookupForBearish = true; + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = orderFlow[i]; + + // + XPVPivot tmp[]; + Copy( + orderFlow, + tmp // + ); + ArrayRemove( + tmp, + 0, + i + 1 // + ); + + // + int tmpCount = ArraySize(tmp); + if (IsValidSize(tmpCount)) + { + // + for (int j = 0; j < tmpCount; j++) + { + // + XPVPivot jPivot = tmp[j]; + + // + // Check Bullish Direction ... + isBullish = + canLookupForBullish && + jPivot.lower >= iPivot.lower; + if (!isBullish) + { + canLookupForBullish = false; + } + + // + // Check Bearish Direction ... + isBearish = + canLookupForBearish && + jPivot.upper <= iPivot.upper; + if (!isBearish) + { + canLookupForBearish = false; + } + + // + if (!canLookupForBullish && + !canLookupForBearish) + { + break; + } + } + } + Clean(tmp); + } + + // + if (isBullish && + !isBearish) + { + dir = X_DIRECTION_BULLISH; + } + else if (isBearish && + !isBullish) + { + dir = X_DIRECTION_BEARISH; + } + + // + result = dir != X_DIRECTION_NONE; + + // + return result; +} + +/** + * Detect all POIs which inside a Pivot ... + * + * @param pivot: XPVPivot instance, Specified Pivot ... + * @param source: XPOIState instance, Reference to Source State ... + * @param state: XPOIState instance, Reference to Detected Pivots ... + * @param lookupSwingHighs: Boolean ... + * @param lookupSwingLows: Boolean ... + * @param lookupSupportZones: Boolean ... + * @param lookupResistanceZones: Boolean ... + * @param lookupSupplyZones: Boolean ... + * @param lookupDemandZones: Boolean ... + * @param lookupBullishOrderBlocks: Boolean ... + * @param lookupBearishOrderBlocks: Boolean ... + * @param lookupBullishFairValueGaps: Boolean ... + * @param lookupBearishFairValueGaps: Boolean ... + * @param lookupBullishRejectionBars: Boolean ... + * @param lookupBearishRejectionBars: Boolean ... + * @param lookupBullishMomentumBars: Boolean ... + * @param lookupBearishMomentumBars: Boolean ... + */ +void DetectPivotPOIs( + XPVPivot &pivot, + XPOIState &source, + XPOIState &state, + bool lookupSwingHighs = true, + bool lookupSwingLows = true, + bool lookupSupportZones = true, + bool lookupResistanceZones = true, + bool lookupSupplyZones = true, + bool lookupDemandZones = true, + bool lookupBullishOrderBlocks = true, + bool lookupBearishOrderBlocks = true, + bool lookupBullishFairValueGaps = true, + bool lookupBearishFairValueGaps = true, + bool lookupBullishRejectionBars = true, + bool lookupBearishRejectionBars = true, + bool lookupBullishMomentumBars = true, + bool lookupBearishMomentumBars = true // +) +{ + // + state.Clean(); + + // + if (!pivot.IsValid()) + { + return; + } + + // + int count = 0; + + // + state.symbol = pivot.symbol; + state.period = pivot.period; + state.time = TimeCurrent(); + + // + // Swings ... + + // + // Swing High ... + if (lookupSwingHighs) + { + // + count = ArraySize(source.swingHighs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = source.swingHighs[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper; + if (isInside) + { + // + Add( + iSwing, + state.swingHighs // + ); + } + } + } + } + + // + // Swing Low ... + if (lookupSwingLows) + { + // + count = ArraySize(source.swingLows); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = source.swingLows[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iSwing, + state.swingLows // + ); + } + } + } + } + + // + // Support and Resistance Zones ... + + // + // Support Zones ... + if (lookupSupportZones) + { + // + count = ArraySize(source.supportZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = source.supportZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.supportZones // + ); + } + } + } + } + + // + // Resistance Zones ... + if (lookupResistanceZones) + { + // + count = ArraySize(source.resistanceZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = source.resistanceZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.resistanceZones // + ); + } + } + } + } + + // + // Supply and Demand Zones ... + + // + // Supply Zones ... + if (lookupSupplyZones) + { + // + count = ArraySize(source.supplyZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = source.supplyZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.supplyZones // + ); + } + } + } + } + + // + // Demand Zones ... + if (lookupDemandZones) + { + // + count = ArraySize(source.demandZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = source.demandZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.demandZones // + ); + } + } + } + } + + // + // Order Blocks ... + + // + // Bullish Order Blocks ... + if (lookupBullishOrderBlocks) + { + // + count = ArraySize(source.bullishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = source.bullishOrderBlocks[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bullishOrderBlocks // + ); + } + } + } + } + + // + // Bearish Order Blocks ... + if (lookupBearishOrderBlocks) + { + // + count = ArraySize(source.bearishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = source.bearishOrderBlocks[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bearishOrderBlocks // + ); + } + } + } + } + + // + // Fair Value Gaps ... + + // + // Bullish Fair Value Gaps ... + if (lookupBullishFairValueGaps) + { + // + count = ArraySize(source.bullishFairValueGaps); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = source.bullishFairValueGaps[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bullishFairValueGaps // + ); + } + } + } + } + + // + // Bearish Fair Value Gaps ... + if (lookupBearishFairValueGaps) + { + // + count = ArraySize(source.bearishFairValueGaps); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = source.bearishFairValueGaps[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bearishFairValueGaps // + ); + } + } + } + } + + // + // Rejection Bars ... + + // + // Bullish Rejection Bars ... + if (lookupBullishRejectionBars) + { + // + count = ArraySize(source.bullishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iRejection = source.bullishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low <= pivot.upper && + iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iRejection, + state.bullishRejectionBars // + ); + } + } + } + } + + // + // Bearish Rejection Bars ... + if (lookupBearishRejectionBars) + { + // + count = ArraySize(source.bearishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iRejection = source.bearishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper && + iBar.high >= pivot.lower; + if (isInside) + { + // + Add( + iRejection, + state.bearishRejectionBars // + ); + } + } + } + } + + // + // Momentum Bars ... + + // + // Bullish Momentum Bars ... + if (lookupBullishMomentumBars) + { + // + count = ArraySize(source.bullishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iMomentum = source.bullishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low <= pivot.upper && + iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iMomentum, + state.bullishMomentumBars // + ); + } + } + } + } + + // + // Bearish Momenum Bars ... + if (lookupBearishMomentumBars) + { + // + count = ArraySize(source.bearishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iMomentum = source.bearishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper && + iBar.high >= pivot.lower; + if (isInside) + { + // + Add( + iMomentum, + state.bearishMomentumBars // + ); + } + } + } + } +} + +// +// Provider Extensions ... + +/** + * Validate a Signal Provider ... + * + * @param value: ENUM_X_121_SMC_PROVIDERS member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_121_SMC_PROVIDERS value) +{ + // + bool result = false; + + // + result = value != X_121_SMC_PROVIDER_NONE; + + // + return result; +} + +/** + * Converts a Signal Provider to String ... + * + * @param value: ENUM_X_121_SMC_PROVIDERS member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_121_SMC_PROVIDERS value) +{ + // + string result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + switch (value) + { + // + case X_121_SMC_PROVIDER_PV: + result = X121SMCPVToken; + break; + + // + case X_121_SMC_PROVIDER_BOS: + result = X121SMCBOSToken; + break; + + // + case X_121_SMC_PROVIDER_SAR: + result = X121SMCSARToken; + break; + + // + case X_121_SMC_PROVIDER_CHOCH: + result = X121SMCCHOCHToken; + break; + + // + case X_121_SMC_PROVIDER_PULLBK: + result = X121SMCPULLBKToken; + break; + } + + // + return result; +} + +/** + * Parse Specified String as a Signal Provider ... + * + * @param value: String ... + * + * @return ( ENUM_X_121_SMC_PROVIDERS ) + */ +ENUM_X_121_SMC_PROVIDERS ParseProvider(string value) +{ + // + ENUM_X_121_SMC_PROVIDERS result = X_121_SMC_PROVIDER_NONE; + + // + if (!IsValid(value)) + { + return result; + } + + // + if (Contains(X121SMCPVToken, value)) + { + result = X_121_SMC_PROVIDER_PV; + } + else if (Contains(X121SMCBOSToken, value)) + { + result = X_121_SMC_PROVIDER_BOS; + } + else if (Contains(X121SMCSARToken, value)) + { + result = X_121_SMC_PROVIDER_SAR; + } + else if (Contains(X121SMCCHOCHToken, value)) + { + result = X_121_SMC_PROVIDER_CHOCH; + } + else if (Contains(X121SMCPULLBKToken, value)) + { + result = X_121_SMC_PROVIDER_PULLBK; + } + + // + return result; +} + +// \ No newline at end of file diff --git a/Documents/BKP/x-121.smc.test.strategy.class copy.mq5 b/Documents/BKP/x-121.smc.test.strategy.class copy.mq5 new file mode 100644 index 00000000..046a000a --- /dev/null +++ b/Documents/BKP/x-121.smc.test.strategy.class copy.mq5 @@ -0,0 +1,3064 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCX121SMCTestStrategy +// Description: provides all based classes for use ... +// +// +// 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-121.smc.base.strategy.class.mq5" +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" + +// +// Definitions ... + +// +// XStrategy Class Implementation(s) ... +class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy +{ + // + // Public ... + public: + // + + // + // Constructor(s) ... + void XCX121SMCTestStrategy( + // + // Base ... + string _symbol, // Trading Symbol + ENUM_TIMEFRAMES _period // Trading TimeFrame + ) + : XCX121SMCBaseStrategy(_symbol, _period) + { + InitialHelpers(); + } + + // + // Deconstructur ... + void ~XCX121SMCTestStrategy() + { + } + + // + // Overrides Actions ... + + /** + * Destroy All Class Implementations ... + */ + void Destroy() override + { + // + delete mTriggerCycleHelper; + delete mDecisionCycleHelper; + delete mAnalyseCycleHelper; + delete mVerificationCycleHelper; + delete mConsolidationCycleHelper; + delete mVisionCycleHelper; + } + + /** + * Check Conditions For Signal ... + */ + bool HasSignal( + XSignal &signal, + X121SMCStrategyConditions &conditions // + ) override + { + // + bool result = false; + + // + signal.Clean(); + conditions.Clean(); + + // + int pushers = 0; + + // + double sl = 0; + double tp = 0; + double risk = 0; + double entry = 0; + double reward = 0; + double r2r = R2R(); + string provider = ""; + double volume = Volume(); + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY; + ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; + + // + bool hasLong = false; + bool hasShort = false; + + // + double selectedSL = 0; + + // + // Start Calculations ... + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + double points = GetPoints(symbol); + double pip = GetPipPrice(symbol); + double pip2 = 2 * pip; + + // + // Check Spread ... + bool isSpreadPassed = IsSpreadPass(); + result = isSpreadPassed; + if (!result) + { + // + // string message = "Spread is not Passed for Analysing ..."; + // LogAlert(message); + + // + return result; + } + + // + // Detect Conditions ... + result = DetectConditions(conditions); + if (!result) + { + conditions.Clean(); + return result; + } + + // + // Combine all Signals Conditions ... + selectedSL = conditions.sl; + provider = conditions.provider; + + // + hasLong = + // + IsBullish(conditions.marketStructureDir) + // + ; + + // + hasShort = + // + IsBearish(conditions.marketStructureDir) + // + ; + + // + result = hasLong || + hasShort; + + // + // Rmove Signal Condition ... + if (result) + { + // + // TYPE ... + type = + hasLong + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + ENUM_X_POSITION_TYPES xType = + hasLong + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + entry = GetEntry( + conditions.symbol, + type // + ); + + // + sl = + hasLong + ? selectedSL - pip2 + : selectedSL + pip2; + + // + // RISK Reward ... + risk = + hasLong + ? entry - sl + : sl - entry; + reward = risk * r2r; + tp = + hasLong + ? entry + reward + : entry - reward; + + // + signal.sl = sl; + signal.tp = tp; + signal.type = type; + signal.mode = mode; + signal.entry = entry; + signal.volume = volume; + signal.symbol = symbol; + signal.period = period; + signal.pushers = pushers; + signal.provider = provider; + signal.time = TimeCurrent(); + + // + result = PrepareSignal(signal); + if (result) + { + // + Print("PRV: ", provider); + + // + ENUM_X_DIRECTION forDir = ToDirection(signal.type); + bool ignoreSwingHighs = false; + bool ignoreSwingLows = false; + bool ignoreSupportZones = false; + bool ignoreResistanceZones = false; + bool ignoreSupplyZones = false; + bool ignoreDemandZones = false; + bool ignoreBullishOrderBlocks = false; + bool ignoreBearishOrderBlocks = false; + bool ignoreBullishFairValueGaps = false; + bool ignoreBearishFairValueGaps = false; + bool ignoreBullishRejectionBars = false; + bool ignoreBearishRejectionBars = false; + bool ignoreBullishMomentumBars = false; + bool ignoreBearishMomentumBars = false; + if (IsBullish(forDir)) + { + // + ignoreSwingLows = false; + ignoreDemandZones = false; + ignoreSupportZones = false; + ignoreBullishOrderBlocks = false; + ignoreBullishFairValueGaps = false; + ignoreBullishRejectionBars = false; + ignoreBullishMomentumBars = false; + } + else + { + // + ignoreSwingHighs = true; + ignoreSupplyZones = true; + ignoreResistanceZones = true; + ignoreBearishOrderBlocks = true; + ignoreBearishFairValueGaps = false; + ignoreBearishRejectionBars = true; + ignoreBearishMomentumBars = true; + } + + // + RedrawOrderFlow( + true, // Force Clean ... + false, // Same Period ... + true, // Order Flow ... + true, // Order Flow State ... + false, // Only Last Order Flow ... + true, // Only Last Order Flow State ... + // + forDir, // Direction Force ... + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + DrawSignal(signal); + ClearDraws(); + + // + ResetOrderFlow(); + } + + // + hasLong = false; + hasShort = false; + } + + // + return result; + } + + /** + * Customize Strategy Identifier ... + */ + string GetTag() override + { + return X121SMCStrategyToken; + } + + // + // Protected ... + protected: + // + + // + // Props ... + + // + // Trigger Order Flow ... + XPVPivot mOrderFlow[]; + ENUM_X_DIRECTION mOrderFlowDir; + + // + XC121SMCCycleHelper *mTriggerCycleHelper; + XC121SMCCycleHelper *mDecisionCycleHelper; + XC121SMCCycleHelper *mAnalyseCycleHelper; + XC121SMCCycleHelper *mVerificationCycleHelper; + XC121SMCCycleHelper *mConsolidationCycleHelper; + XC121SMCCycleHelper *mVisionCycleHelper; + + // + // Actions ... + + /** + * Detect and Parse Market Conditions ... + * + * @return ( bool ) + */ + bool DetectConditions( + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + string msg = NULL; + + // + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + conditions.time = cTime; + conditions.symbol = symbol; + conditions.period = period; + + // + int conditionsLoopback = 7; + + // + // Fill Cycles Conditions ... + + // + // Trigger ... + mTriggerCycleHelper.GetConditions( + conditions.triggerConditions, + zIndex, + conditionsLoopback // + ); + conditions.triggerConditions.state = mTriggerState; + + // + // Decision ... + mDecisionCycleHelper.GetConditions( + conditions.decisionConditions, + zIndex, + conditionsLoopback // + ); + conditions.decisionConditions.state = mDecisionState; + + // + // Analyse ... + mAnalyseCycleHelper.GetConditions( + conditions.analyseConditions, + zIndex, + conditionsLoopback // + ); + conditions.analyseConditions.state = mAnalyseState; + + // + // Verification ... + mVerificationCycleHelper.GetConditions( + conditions.verificationConditions, + zIndex, + conditionsLoopback // + ); + conditions.verificationConditions.state = mVerificationState; + + // + // Consolidation ... + mConsolidationCycleHelper.GetConditions( + conditions.consolidationConditions, + zIndex, + conditionsLoopback // + ); + conditions.consolidationConditions.state = mConsolidationState; + + // + // Vision ... + mVisionCycleHelper.GetConditions( + conditions.visionConditions, + zIndex, + conditionsLoopback // + ); + conditions.visionConditions.state = mVisionState; + + // + // Detect an Order Block in Vision ... + if (conditions.visionBullOB == NULL || + conditions.visionBearOB == NULL) + { + // + result = DetectOrderBlocks( + NULL, + NULL, + conditions.visionBullOB, + conditions.visionBearOB, + cBar, + mVisionState // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + XCBullishOrderBlockObject *iBullOBObj; + conditions.visionBullOB.To(cTime); + result = mPOIDrawer.CreateBullishOrderBlock( + conditions.visionBullOB, + iBullOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBullOBObj); + } + + // + XCBearishOrderBlockObject *iBearOBObj; + conditions.visionBearOB.To(cTime); + result = mPOIDrawer.CreateBearishOrderBlock( + conditions.visionBearOB, + iBearOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBearOBObj); + } + } + + // + // Consolidation Order Blocks ... + if (conditions.consolidationBullOB == NULL || + conditions.consolidationBearOB == NULL) + { + // + result = DetectOrderBlocks( + conditions.visionBullOB, + conditions.visionBearOB, + conditions.consolidationBullOB, + conditions.consolidationBearOB, + cBar, + mConsolidationState // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + XCBullishOrderBlockObject *iBullOBObj; + conditions.consolidationBullOB.To(cTime); + result = mPOIDrawer.CreateBullishOrderBlock( + conditions.consolidationBullOB, + iBullOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBullOBObj); + } + + // + XCBearishOrderBlockObject *iBearOBObj; + conditions.consolidationBearOB.To(cTime); + result = mPOIDrawer.CreateBearishOrderBlock( + conditions.consolidationBearOB, + iBearOBObj // + ); + if (result) + { + AddObjectIfNotExists(iBearOBObj); + } + } + + // + msg = "OrderBlocks Detected ..."; + Alert(msg); + + // + // Detect Trigger Order Flow ... + if (!HasValidOrderFlow()) + { + // + int samePivots = 40; + int requiredPivots = 10; + + // + bool useVisionState = false; + bool useConsolidationState = false; + bool useVerificationState = false; + bool useAnalyseState = false; + bool useDecisionState = true; + bool useTriggerState = false; + + // + DetectOrderFlow( + cIndex, + samePivots, + requiredPivots, + mTriggerCycleHelper, + mOrderFlow, + mOrderFlowDir, + // + // Filling Pivot State ... + useVisionState, // Use Vision State ... + useConsolidationState, // Use Consolidation State ... + useVerificationState, // Use Verification State ... + useAnalyseState, // Use Analyse State ... + useDecisionState, // Use Decision State ... + useTriggerState // Use Trigger State ... + ); + + // + result = HasValidOrderFlow(); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + bool ignoreSwingHighs = true; + bool ignoreSwingLows = true; + bool ignoreSupportZones = true; + bool ignoreResistanceZones = true; + bool ignoreSupplyZones = true; + bool ignoreDemandZones = true; + bool ignoreBullishOrderBlocks = true; + bool ignoreBearishOrderBlocks = true; + bool ignoreBullishFairValueGaps = true; + bool ignoreBearishFairValueGaps = true; + bool ignoreBullishRejectionBars = true; + bool ignoreBearishRejectionBars = true; + bool ignoreBullishMomentumBars = true; + bool ignoreBearishMomentumBars = true; + + // + RedrawOrderFlow( + false, // Force Clean ... + false, // Same Period ... + true, // Order Flow ... + true, // Order Flow State ... + false, // Only Last Order Flow ... + true, // Only Last Order Flow State ... + // + mOrderFlowDir, // Direction Force ... + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + msg = "Found OrderFlow : " + (IsBullish(mOrderFlowDir) ? "Bullish" : "Berish"); + Alert(msg); + + // + // Check Market Conditions for + // Specified Structure ... + // ENUM_X_DIRECTION marketStructureDir = X_DIRECTION_NONE; + // result = conditions.HasDirection( + // marketStructureDir, + // cBar // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + // msg = "Found Market Strucutre : " + (IsBullish(marketStructureDir) ? "Bullish" : "Berish"); + // Alert(msg); + + // + // conditions.marketStructureDir = marketStructureDir; + + // // + // XPVPivot lastPivot; + // result = GetLastItem( + // lastPivot, + // mOrderFlow // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + + // + // Detect Last FVG ... + // XOHCL breakerBar; + // result = DetectLastBreakerBar( + // cBar, + // breakerBar, + // lastPivot, + // marketStructureDir // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + // msg = "Found Breaker Bar: " + breakerBar.GetTag(); + // Alert(msg); + + // // + // // Detect Nearest Momentum or Rejection Bar ... + // XOHCL decisionBar; + // result = mDecisionCycleHelper.DetectNearestDecisionBar( + // decisionBar, + // marketStructureDir, + // cBar // + // ); + // if (!result) + // { + // return result; + // } + // msg = "Found Decision Bar: " + decisionBar.GetTag(); + // Alert(msg); + + // // + // // Detect Nearest Sar Change ... + // XOHCL sarChangeBar; + // result = mTriggerCycleHelper.DetectNearestCSARChange( + // sarChangeBar, + // cBar // + // ); + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + // msg = "Found Sar Change Bar: " + sarChangeBar.GetTag(); + // Alert(msg); + + // // + // // Now we Hvae to Check Other Conditions ... + // result = + // // breakerBar.time > sarChangeBar.time && + // // decisionBar.time > breakerBar.time; + // decisionBar.time > sarChangeBar.time; + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + + // // + // // Now we Have Check Direction Related Conditions ... + // if (IsBullish(marketStructureDir)) + // { + // // + // result = + // // bid > decisionBar.high && + // // bid > breakerBar.high && + // bid > sarChangeBar.high && + // bid > conditions.triggerConditions.xchsarConditions.cSars[0]; + // } + // else + // { + // // + // result = + // // bid < decisionBar.low && + // // bid < breakerBar.low && + // bid < sarChangeBar.high && + // bid < conditions.triggerConditions.xchsarConditions.cSars[0]; + // } + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + + // // + // conditions.provider = "X121SMC"; + // if (IsBullish(marketStructureDir)) + // { + // // + // // conditions.sl = decisionBar.low; + // // conditions.sl = breakerBar.low; + // conditions.sl = conditions.triggerConditions.xchsarConditions.cSars[0]; + // } + // else + // { + // // + // // conditions.sl = decisionBar.high; + // // conditions.sl = breakerBar.high; + // conditions.sl = conditions.triggerConditions.xchsarConditions.cSars[0]; + // } + + // + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + return result; + } + + /** + * Detect XPV Based POI(s) ... + * + * @param barIndex: Start Bar Index ... + * @param minRepetition: minimum Repeate of POI for Validation ... + * @param requiredPivots: Number of Min Requirement POI(s) ... + * @param pivotHelper: XC121SMCCycleHelper instance Pointer ... + * @param orderFlow: XPVPivot instance Array Reference ... + * @param orderFlowDirection: ENUM_X_DIRECTION member Reference which represents OrderFlow Direction ... + * @param maxAllowedLoopbackBars: Integer, Max Allowed Loopback Bars ... + * + * @return ( bool ) + */ + bool DetectOrderFlow( + int barIndex, + int minRepetition, + int requiredPivots, + XC121SMCCycleHelper *pivotHelper, // XPV Helper ... + XPVPivot &orderFlow[], // OrderFlows ... + ENUM_X_DIRECTION &orderFlowDirection, // Order Flow Direction ... + // + bool useVisionState = true, // Use Vision State ... + bool useConsolidationState = true, // Use Consolidation State ... + bool useVerificationState = true, // Use Verification State ... + bool useAnalyseState = true, // Use Analyse State ... + bool useDecisionState = true, // Use Decision State ... + bool useTriggerState = true, // Use Trigger State ... + // + int maxAllowedLoopbackBars = 576 // + ) + { + // + bool result = false; + + // + orderFlowDirection = X_DIRECTION_NONE; + + // + if (maxAllowedLoopbackBars <= 0) + { + maxAllowedLoopbackBars = 1000; + } + + // + int start = barIndex; + int end = start + maxAllowedLoopbackBars; + + // + Clean(orderFlow); + + // + result = minRepetition > 0 && + requiredPivots > 0 && + pivotHelper != NULL; + if (!result) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + double peak = 0; + XPVPivot peaks[]; + int peakRepeate = 0; + int peakToBarIndex = 0; + int peakFromBarIndex = 0; + + // + double vale = 0; + XPVPivot vales[]; + int valeRepeate = 0; + int valeToBarIndex = 0; + int valeFromBarIndex = 0; + + // + bool canLookupPeak = true; + bool canLookupVale = true; + bool canLookup = true; + while (canLookup) + { + // + // Check Peak ... + double iPeak = pivotHelper.mXPVHelper.GetPeak(barIndex); + if (iPeak != peak) + { + // + if (peak != 0 && + peakRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(peaks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = peaks[i]; + + // + if (iPivot.upper == iPeak) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.lower = 0; + iPivot.upper = peak; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_PEAK; + iPivot.repetition = peakRepeate; + iPivot.to = iTime( + symbol, + period, + peakToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + peakFromBarIndex // + ); + + // + iPivot.lower = iPivot.CalculateLower(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + peaks // + ); + } + } + } + + // + peak = iPeak; + peakRepeate = 0; + peakFromBarIndex = 0; + peakToBarIndex = barIndex; + } + else if (iPeak == peak) + { + // + peakRepeate++; + peakFromBarIndex = barIndex; + } + + // + // Check Vale ... + double iVale = pivotHelper.mXPVHelper.GetVale(barIndex); + if (iVale != vale) + { + // + if (vale != 0 && + valeRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(vales); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = vales[i]; + + // + if (iPivot.lower == iVale) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.upper = 0; + iPivot.lower = vale; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_VALE; + iPivot.repetition = valeRepeate; + iPivot.to = iTime( + symbol, + period, + valeToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + valeFromBarIndex // + ); + + // + iPivot.upper = iPivot.CalculateUpper(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + vales // + ); + } + } + } + + // + vale = iVale; + valeRepeate = 0; + valeFromBarIndex = 0; + valeToBarIndex = barIndex; + } + else if (iVale == vale) + { + // + valeRepeate++; + valeFromBarIndex = barIndex; + } + + // + canLookupPeak = ArraySize(peaks) < requiredPivots; + canLookupVale = ArraySize(vales) < requiredPivots; + canLookup = barIndex < end && + (canLookupPeak || + canLookupVale); + if (canLookup) + { + barIndex++; + } + } + + // + result = IsValidSize(ArraySize(peaks)) || + IsValidSize(ArraySize(vales)); + if (!result) + { + return result; + } + + // + // Detect Order Flow ... + Copy( + peaks, + orderFlow, + false // + ); + Copy( + vales, + orderFlow, + false // + ); + int count = ArraySize(orderFlow); + result = IsValidSize(orderFlow); + if (!result) + { + return result; + } + + // + // Sort Pivots ... + SortPivots(orderFlow); + + // + // Filter Broken Order Flows ... + FilterBrokenPivots(orderFlow); + + // + // Detect Order Flow Direction ... + result = DetectPivotDirection( + orderFlow, + orderFlowDirection // + ); + if (!result) + { + return result; + } + + // + // Find State Inside Pivots and Attached Them to Pivot ... + int orderFlowCount = ArraySize(mOrderFlow); + if (IsValidSize(orderFlowCount)) + { + // + // Loop Through Order Flow ... + for (int i = 0; i < orderFlowCount; i++) + { + // + FillPivotSate( + i, + useVisionState, // Use Vision State ... + useConsolidationState, // Use Consolidation State ... + useVerificationState, // Use Verification State ... + useAnalyseState, // Use Analyse State ... + useDecisionState, // Use Decision State ... + useTriggerState // Use Trigger State ... + ); + } + } + + // + return result; + } + + /** + * Filling Specified Orer Flow Index ... + * + * @param pivotIDX: Integer ... + * @param lookupSwingHighs: Boolean ... + * @param lookupSwingLows: Boolean ... + * @param lookupSupportZones: Boolean ... + * @param lookupResistanceZones: Boolean ... + * @param lookupSupplyZones: Boolean ... + * @param lookupDemandZones: Boolean ... + * @param lookupBullishOrderBlocks: Boolean ... + * @param lookupBearishOrderBlocks: Boolean ... + * @param lookupBullishFairValueGaps: Boolean ... + * @param lookupBearishFairValueGaps: Boolean ... + * @param lookupBullishRejectionBars: Boolean ... + * @param lookupBearishRejectionBars: Boolean ... + * @param lookupBullishMomentumBars: Boolean ... + * @param lookupBearishMomentumBars: Boolean ... + */ + void FillPivotSate( + int pivotIDX, // + bool useVisionState = true, // Use Vision State ... + bool useConsolidationState = true, // Use Consolidation State ... + bool useVerificationState = true, // Use Verification State ... + bool useAnalyseState = true, // Use Analyse State ... + bool useDecisionState = true, // Use Decision State ... + bool useTriggerState = true, // Use Trigger State ... + bool lookupSwingHighs = true, + bool lookupSwingLows = true, + bool lookupSupportZones = true, + bool lookupResistanceZones = true, + bool lookupSupplyZones = true, + bool lookupDemandZones = true, + bool lookupBullishOrderBlocks = true, + bool lookupBearishOrderBlocks = true, + bool lookupBullishFairValueGaps = true, + bool lookupBearishFairValueGaps = true, + bool lookupBullishRejectionBars = true, + bool lookupBearishRejectionBars = true, + bool lookupBullishMomentumBars = true, + bool lookupBearishMomentumBars = true // + ) + { + // + CalculatePivotTickZone(pivotIDX); + + // + // Trigger ... + XPOIState mPivotTriggerState; + if (useTriggerState && + mTriggerState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mTriggerState, + mPivotTriggerState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotTriggerState.HasChild()) + { + mPivotTriggerState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Decision ... + XPOIState mPivotDecisionState; + if (useDecisionState && + mDecisionState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mDecisionState, + mPivotDecisionState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotDecisionState.HasChild()) + { + mPivotDecisionState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Analyse ... + XPOIState mPivotAnalyseState; + if (useAnalyseState && + mAnalyseState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mAnalyseState, + mPivotAnalyseState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotAnalyseState.HasChild()) + { + mPivotAnalyseState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Verification ... + XPOIState mPivotVerificationState; + if (useVerificationState && + mVerificationState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mVerificationState, + mPivotVerificationState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotVerificationState.HasChild()) + { + mPivotVerificationState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Consolidation ... + XPOIState mPivotConsolidationState; + if (useConsolidationState && + mConsolidationState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mConsolidationState, + mPivotConsolidationState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotConsolidationState.HasChild()) + { + mPivotConsolidationState.Fill(mOrderFlow[pivotIDX].state); + } + } + + // + // Vision ... + XPOIState mPivotVisionState; + if (useVisionState && + mVisionState.HasChild()) + { + // + DetectPivotPOIs( + mOrderFlow[pivotIDX], + mVisionState, + mPivotVisionState, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + if (mPivotVisionState.HasChild()) + { + mPivotVisionState.Fill(mOrderFlow[pivotIDX].state); + } + } + } + + /** + * When a BOS Happens ... + * we have to Update Order Flow ... + */ + void UpdateOrderFlow() + { + ResetOrderFlow(); + } + + /** + * Fill Pivot Tick Zone ... + * + * @param pivotIDX: Integer ... + */ + void CalculatePivotTickZone(int pivotIDX) + { + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + bool isInited = false; + + // + datetime from = mOrderFlow[pivotIDX].from; + XOHCL iFromBar; + int iFromBarIndex = iBarShift( + symbol, + period, + from // + ); + isInited = iFromBar.Init( + symbol, + period, + iFromBarIndex // + ); + if (!isInited) + { + return; + } + + // + datetime to = mOrderFlow[pivotIDX].to; + XOHCL iToBar; + int iToBarIndex = iBarShift( + symbol, + period, + to // + ); + isInited = iToBar.Init( + symbol, + period, + iToBarIndex // + ); + if (!isInited) + { + return; + } + + // + XCTicksZone *iZone; + iZone = new XCTicksZone(); + + // + int ticksLevels = mTriggerDetector.TicksRangeZoneLevel(); + int ticksRange = mTriggerDetector.TicksRangeZoneRange(); + isInited = ticksLevels > 0 && + ticksRange > 0; + if (!isInited) + { + return; + } + + // + isInited = iZone.Init( + iFromBar, + iToBar // + ); + if (!isInited) + { + return; + } + + // + mOrderFlow[pivotIDX].state.ticksZone = iZone; + } + + /** + * Validate Order Flow ... + * + * @return ( bool ) + */ + bool HasValidOrderFlow() + { + // + bool result = false; + + // + int orderFlowCount = ArraySize(mOrderFlow); + result = + IsValidSize(orderFlowCount) && + mOrderFlowDir != X_DIRECTION_ALL && + mOrderFlowDir != X_DIRECTION_NONE; + + // + return result; + } + + /** + * Reset Order Flow ... + */ + void ResetOrderFlow() + { + // + Clean(mOrderFlow); + mOrderFlowDir = X_DIRECTION_NONE; + + // + ClearDraws(); + } + + /** + * Detect Breaker Bar ... + * + * @param bar: XOHCL instance ... + * @param breakerBar: XOHCL instance, Breaker Bar ... + * @param pivot: XPVPivot instance ... + * @param forDir: ENUM_X_DIRECTION member, Market Structure Direction ... + * + * @return ( bool ) + */ + bool DetectLastBreakerBar( + XOHCL &bar, + XOHCL &breakerBar, + XPVPivot &pivot, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + pivot.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + // FVG ... + result = DetectLastFVGBreakerBar( + bar, + breakerBar, + pivot, + forDir // + ); + if (result) + { + return result; + } + + // + // Order Block ... + // result = DetectLastOBBreakerBar( + // bar, + // breakerBar, + // pivot, + // forDir // + // ); + // if (result) + // { + // return result; + // } + + // + return result; + } + + bool DetectLastFVGBreakerBar( + XOHCL &bar, + XOHCL &breakerBar, + XPVPivot &pivot, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + pivot.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + bool isBullishDir = IsBullish(forDir); + + // + int fvgsCount = + isBullishDir + ? pivot.state.CountBullishFairValueGaps() + : pivot.state.CountBearishFairValueGaps(); + result = IsValidSize(fvgsCount); + if (!result) + { + return result; + } + + // + int idx = -1; + XCFVG *zone = NULL; + for (int i = 0; i < fvgsCount; i++) + { + // + if (isBullishDir) + { + // + // Bullish FVG ... + if (zone == NULL) + { + // + zone = pivot.state.bullishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + else + { + // + bool isNewer = ((int)zone.From() - (int)bar.time) > ((int)pivot.state.bullishFairValueGaps[i].From() - (int)bar.time); + if (isNewer) + { + // + zone = pivot.state.bullishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + } + } + else + { + // + // Bearish FVG ... + if (zone == NULL) + { + // + zone = pivot.state.bearishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + else + { + // + bool isNewer = ((int)zone.From() - (int)bar.time) > ((int)pivot.state.bearishFairValueGaps[i].From() - (int)bar.time); + if (isNewer) + { + // + zone = pivot.state.bearishFairValueGaps[i]; + + // + bool isBreaked = CheckZoneBreak( + forDir, + bar, + breakerBar, + zone // + ); + if (isBreaked) + { + idx = i; + } + } + } + } + } + + // + result = + breakerBar.IsValid() && + IsValidIndex(idx) && + zone.IsValid(); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Check an FVG is Breaked or not ... + * + * @param forDir: ENUM_X_DIRECTION member, Market Structure Direction ... + * @param bar: XOHCL instance ... + * @param breakerBar: XOHCL instance, Breaker Bar ... + * + * @return ( bool ) + */ + bool CheckZoneBreak( + ENUM_X_DIRECTION forDir, + XOHCL &bar, + XOHCL &breakerBar, + XCFVG *&zone // + ) + { + // + bool result = false; + + // + breakerBar.Clean(); + + // + result = bar.IsValid() && + zone.IsValid() && + forDir != X_DIRECTION_ALL && + forDir != X_DIRECTION_NONE; + if (!result) + { + return result; + } + + // + int start = bar.Index(); + int end = iBarShift( + bar.symbol, + bar.period, + zone.From()); + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + result = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } + + // + if (IsBullish(forDir)) + { + // + // Bullish Break ... + result = iBar.low < zone.Upper() && + iBar.high > zone.Upper() && + iBar.GetDown() < zone.Upper() && + iBar.GetUp() > zone.Upper() && + iBar.IsBullish(); + } + else + { + // + // Bearish Break ... + result = iBar.low < zone.Lower() && + iBar.high > zone.Lower() && + iBar.GetDown() < zone.Lower() && + iBar.GetUp() > zone.Lower() && + iBar.IsBearish(); + } + + // + if (result) + { + // + breakerBar = iBar; + break; + } + } + + // + result = breakerBar.IsValid(); + + // + return result; + } + + /** + * Detect most Upper and Lower Order Blocks ... + * + * @return ( bool ) + */ + bool DetectOrderBlocks( + XCOrderBlock *bullOBBoundary, + XCOrderBlock *bearOBBoundary, + XCOrderBlock *&bullOB, + XCOrderBlock *&bearOB, + XOHCL &bar, + XPOIState &state // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + state.IsValid(); + if (!result) + { + return result; + } + + // + XCOrderBlock *mBullOB = NULL; + if (bullOB == NULL) + { + // + for (int i = 0; i < state.CountBullishOrderBlocks(); i++) + { + // + XCOrderBlock *ob = state.bullishOrderBlocks[i]; + bool isPricePassed = bar.low > ob.Upper(); + if (isPricePassed) + { + // + bool isBoundaryPassed = + bullOBBoundary == NULL + ? true + : ob.Lower() < bullOBBoundary.Upper(); + if (isBoundaryPassed) + { + // + if (mBullOB == NULL) + { + mBullOB = ob; + } + else + { + // + bool isRefined = + mBullOB.Upper() < ob.Upper(); + if (isRefined) + { + mBullOB = ob; + } + } + } + } + } + + // + if (mBullOB != NULL) + { + bullOB = mBullOB; + } + } + + // + XCOrderBlock *mBearOB = NULL; + if (bearOB == NULL) + { + // + for (int i = 0; i < state.CountBearishOrderBlocks(); i++) + { + // + XCOrderBlock *ob = state.bearishOrderBlocks[i]; + bool isPricePassed = bar.high < ob.Lower(); + if (isPricePassed) + { + // + bool isBoundaryPassed = + bearOBBoundary == NULL + ? true + : ob.Upper() > bearOBBoundary.Lower(); + if (isBoundaryPassed) + { + // + if (mBearOB == NULL) + { + mBearOB = ob; + } + else + { + // + bool isRefined = + mBearOB.Lower() > ob.Lower(); + if (isRefined) + { + mBearOB = ob; + } + } + } + } + } + + // + if (mBearOB != NULL) + { + bearOB = mBearOB; + } + } + + // + result = bullOB != NULL && + bearOB != NULL; + + // + return result; + } + + // + // Drawings ... + + /** + * Draw Order Flow ... + */ + void RedrawOrderFlow( + bool forceClearDraws = true, + bool forceDrawSamePeriod = true, + bool drawOrderFlow = true, + bool drawOrderFlowState = true, + bool drawOnlyLastOrderFlow = false, + bool drawOnlyLastOrderFlowState = true, + // + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + // + // Ignores List ... + bool ignoreSwingHighs = false, + bool ignoreSwingLows = false, + bool ignoreSupportZones = false, + bool ignoreResistanceZones = false, + bool ignoreSupplyZones = false, + bool ignoreDemandZones = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBullishRejectionBars = false, + bool ignoreBearishRejectionBars = false, + bool ignoreBullishMomentumBars = false, + bool ignoreBearishMomentumBars = false, + // + // States Drawing ... + bool drawVisionState = false, + bool drawConsolidationState = false, + bool drawVerificationState = false, + bool drawAnalyseState = false, + bool drawDecisionState = false, + bool drawTriggerState = false // + ) + { + // + if (forceClearDraws) + { + ClearDraws(); + } + + // + if (!drawOrderFlow || + !HasValidOrderFlow()) + { + return; + } + + // + int orderFlowCount = ArraySize(mOrderFlow); + for (int i = 0; i < orderFlowCount; i++) + { + // + bool isLast = i == orderFlowCount - 1; + bool canDraw = + !drawOnlyLastOrderFlow || + (isLast && + drawOnlyLastOrderFlow); + if (!canDraw) + { + continue; + } + + // + XPVPivot iPivot = mOrderFlow[i]; + + // + XCXPVPivotObject *iObj; + iObj = new XCXPVPivotObject(); + bool isCreated = iObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + iPivot // + ); + if (isCreated) + { + // + bool canDrawState = + drawOrderFlowState && + (!drawOnlyLastOrderFlowState || + (isLast && + drawOnlyLastOrderFlowState)); + if (canDrawState) + { + // + CustomStateDrawing( + iPivot.state, + forceDrawSamePeriod, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + if (iPivot.IsPeak()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotColor(clrAqua); + iObj.PivotStyle(STYLE_SOLID); + } + + // + if (iPivot.IsVale()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotStyle(STYLE_SOLID); + iObj.PivotColor(clrMagenta); + } + + // + AddObjectIfNotExists(iObj); + } + } + + // + // Draw States ... + + // + // Vision ... + if (drawVisionState) + { + // + CustomStateDrawing( + mVisionState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Consolidation ... + if (drawConsolidationState) + { + // + CustomStateDrawing( + mConsolidationState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Verification ... + if (drawVerificationState) + { + // + CustomStateDrawing( + mVerificationState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Analyse ... + if (drawAnalyseState) + { + // + CustomStateDrawing( + mAnalyseState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Decision ... + if (drawDecisionState) + { + // + CustomStateDrawing( + mDecisionState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // + // Trigger ... + if (drawTriggerState) + { + // + CustomStateDrawing( + mTriggerState, + false, + forDir, + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + } + + /** + * Custom Drawing State ... + * + * @param state: XPOIState instance reference, Specified Which state to Draw ... + * @param forceDrawSamePeriod: Boolean ... + */ + void CustomStateDrawing( + XPOIState &state, + bool forceDrawSamePeriod = false, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + // + // Ignores List ... + bool ignoreSwingHighs = false, + bool ignoreSwingLows = false, + bool ignoreSupportZones = false, + bool ignoreResistanceZones = false, + bool ignoreSupplyZones = false, + bool ignoreDemandZones = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBullishRejectionBars = false, + bool ignoreBearishRejectionBars = false, + bool ignoreBullishMomentumBars = false, + bool ignoreBearishMomentumBars = false // + ) + { + // + XPOIState tmpState = state; + if (forceDrawSamePeriod) + { + // + int count = 0; + ENUM_TIMEFRAMES period = GetPeriod(); + + // + count = state.CountSwingHighs(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing iSwing = state.swingHighs[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.swingHighs, + i, + 1 // + ); + } + } + } + + // + count = state.CountSwingLows(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing iSwing = state.swingLows[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.swingLows, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishMomentumBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar iMomentum = state.bullishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishMomentumBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishMomentumBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar iMomentum = state.bearishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishMomentumBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishRejectionBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar iRejection = state.bullishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishRejectionBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishRejectionBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar iRejection = state.bearishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishRejectionBars, + i, + 1 // + ); + } + } + } + + // + count = state.CountSupportZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone iZone = state.supportZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.supportZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountResistanceZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone iZone = state.resistanceZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.resistanceZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountSupplyZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone iZone = state.supplyZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.supplyZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountDemandZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone iZone = state.demandZones[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.demandZones, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock iZone = state.bullishOrderBlocks[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishOrderBlocks, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock iZone = state.bearishOrderBlocks[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishOrderBlocks, + i, + 1 // + ); + } + } + } + + // + count = state.CountBullishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG iZone = state.bullishFairValueGaps[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillStartBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bullishFairValueGaps, + i, + 1 // + ); + } + } + } + + // + count = state.CountBearishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG iZone = state.bearishFairValueGaps[i]; + + // + XOHCL iBar; + bool isFilled = iZone.FillStartBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isSamePeriod = iBar.period == period; + if (!isSamePeriod) + { + // + ArrayRemove( + tmpState.bearishFairValueGaps, + i, + 1 // + ); + } + } + } + + // + } + + // + bool drawSwingHighs = true; + bool drawSwingLows = true; + bool drawSupportZones = true; + bool drawResistanceZones = true; + bool drawSupplyZones = true; + bool drawDemandZones = true; + bool drawBullishOrderBlocks = true; + bool drawBearishOrderBlocks = true; + bool drawBullishFairValueGaps = true; + bool drawBearishFairValueGaps = true; + bool drawBullishRejectionBars = true; + bool drawBearishRejectionBars = true; + bool drawBullishMomentumBars = true; + bool drawBearishMomentumBars = true; + + // + // Change Drawing Specs Conditions based on + // Provided Direction ... + if (forDir == X_DIRECTION_BULLISH) + { + // + drawSwingLows = true; + drawDemandZones = true; + drawSupportZones = true; + drawBullishOrderBlocks = true; + drawBullishFairValueGaps = true; + drawBullishRejectionBars = true; + drawBullishMomentumBars = true; + + // + drawSwingHighs = false; + drawSupplyZones = false; + drawResistanceZones = false; + drawBearishOrderBlocks = false; + drawBearishFairValueGaps = false; + drawBearishRejectionBars = false; + drawBearishMomentumBars = false; + } + else if (forDir == X_DIRECTION_BEARISH) + { + // + drawSwingLows = false; + drawDemandZones = false; + drawSupportZones = false; + drawBullishOrderBlocks = false; + drawBullishFairValueGaps = false; + drawBullishRejectionBars = false; + drawBullishMomentumBars = false; + + // + drawSwingHighs = true; + drawSupplyZones = true; + drawResistanceZones = true; + drawBearishOrderBlocks = true; + drawBearishFairValueGaps = true; + drawBearishRejectionBars = true; + drawBearishMomentumBars = true; + } + + // + // Apply Ignore List ... + + // + if (ignoreSwingHighs) + { + drawSwingHighs = false; + } + + // + if (ignoreSwingLows) + { + drawSwingLows = false; + } + + // + if (ignoreSupportZones) + { + drawSupportZones = false; + } + + // + if (ignoreResistanceZones) + { + drawResistanceZones = false; + } + + // + if (ignoreSupplyZones) + { + drawSupplyZones = false; + } + + // + if (ignoreDemandZones) + { + drawDemandZones = false; + } + + // + if (ignoreBullishOrderBlocks) + { + drawBullishOrderBlocks = false; + } + + // + if (ignoreBearishOrderBlocks) + { + drawBearishOrderBlocks = false; + } + + // + if (ignoreBullishFairValueGaps) + { + drawBullishFairValueGaps = false; + } + + // + if (ignoreBearishFairValueGaps) + { + drawBearishFairValueGaps = false; + } + + // + if (ignoreBullishRejectionBars) + { + drawBullishRejectionBars = false; + } + + // + if (ignoreBearishRejectionBars) + { + drawBearishRejectionBars = false; + } + + // + if (ignoreBullishMomentumBars) + { + drawBullishMomentumBars = false; + } + + // + if (ignoreBearishMomentumBars) + { + drawBearishMomentumBars = false; + } + + // + DrawState( + tmpState, // State ... + true, // Update To of all Drawings Till now ... + drawSwingHighs, // Draw SwingHighs .. + drawSwingLows, // Draw SwingLows .. + drawSupportZones, // Draw SupportZones .. + drawResistanceZones, // Draw ResistanceZones .. + drawSupplyZones, // Draw SupplyZones .. + drawDemandZones, // Draw DemandZones .. + drawBullishOrderBlocks, // Draw BullishOrderBlocks .. + drawBearishOrderBlocks, // Draw BearishOrderBlocks .. + drawBullishFairValueGaps, // Draw BullishFairValueGaps .. + drawBearishFairValueGaps, // Draw BearishFairValueGaps .. + drawBullishRejectionBars, // Draw BullishRejectionBars .. + drawBearishRejectionBars, // Draw BearishRejectionBars .. + drawBullishMomentumBars, // Draw BullishMomentumBars .. + drawBearishMomentumBars, // Draw BearishMomentumBars .. + true // Draw Ticks Zone ... + ); + } + + // + // Private ... + private: + // + // Props ... + + /** + * Initial Required Indicators Helper ... + */ + void InitialHelpers() + { + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + + // + // XPV ... + XPVInputs xpvInputs; + + // + xpvInputs.Default(); + + // + xpvInputs.scMethod = scMethod; + xpvInputs.scPeriod = scPeriod; + xpvInputs.mcMethod = mcMethod; + xpvInputs.mcPeriod = mcPeriod; + xpvInputs.lcMethod = lcMethod; + xpvInputs.lcPeriod = lcPeriod; + xpvInputs.hcMethod = hcMethod; + xpvInputs.hcPeriod = hcPeriod; + + // + xpvInputs.showPeaksAndVales = true; + xpvInputs.showLevels = false; + xpvInputs.showConsolidations = false; + xpvInputs.showFibo1Levels = false; + xpvInputs.showFibo2Levels = false; + xpvInputs.showFibo3Levels = false; + xpvInputs.showFibo4Levels = false; + xpvInputs.showFibo5Levels = false; + + // + // X3MA ... + X3MAInputs x3maInputs; + + // + x3maInputs.Default(); + + // + // x3maInputs.fastLength = 10; + // x3maInputs.midLength = 25; + // x3maInputs.slowLength = 50; + + // + x3maInputs.showFast = true; + x3maInputs.showMid = false; + x3maInputs.showSlow = false; + + // + // X3VWAP ... + X3VWAPInputs x3vwapInputs; + + // + x3vwapInputs.Default(); + + // + // x3vwapInputs.fastLength = 10; + // x3vwapInputs.midLength = 25; + // x3vwapInputs.slowLength = 50; + + // + x3vwapInputs.showFast = true; + x3vwapInputs.showMid = true; + x3vwapInputs.showSlow = true; + + // + // XCHSAR ... + XCHSARInputs xchsarInputs; + + // + xchsarInputs.Default(); + + // + xchsarInputs.scMethod = scMethod; + xchsarInputs.scPeriod = scPeriod; + xchsarInputs.mcMethod = mcMethod; + xchsarInputs.mcPeriod = mcPeriod; + xchsarInputs.lcMethod = lcMethod; + xchsarInputs.lcPeriod = lcPeriod; + xchsarInputs.hcMethod = hcMethod; + xchsarInputs.hcPeriod = hcPeriod; + + // + xchsarInputs.showCurrent = true; + xchsarInputs.showShort = false; + xchsarInputs.showMedium = false; + xchsarInputs.showLong = false; + xchsarInputs.showHind = false; + + // + // Initialize Cycle Helpers ... + + // + mTriggerCycleHelper = new XC121SMCCycleHelper(); + mTriggerCycleHelper.Init( + symbol, + PERIOD_M1, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mDecisionCycleHelper = new XC121SMCCycleHelper(); + mDecisionCycleHelper.Init( + symbol, + PERIOD_M5, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mAnalyseCycleHelper = new XC121SMCCycleHelper(); + mAnalyseCycleHelper.Init( + symbol, + PERIOD_M15, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mVerificationCycleHelper = new XC121SMCCycleHelper(); + mVerificationCycleHelper.Init( + symbol, + PERIOD_M30, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mConsolidationCycleHelper = new XC121SMCCycleHelper(); + mConsolidationCycleHelper.Init( + symbol, + PERIOD_H1, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + + // + mVisionCycleHelper = new XC121SMCCycleHelper(); + mVisionCycleHelper.Init( + symbol, + PERIOD_H4, + xpvInputs, + x3maInputs, + x3vwapInputs, + xchsarInputs // + ); + } + + // +}; + +// \ No newline at end of file diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index 04a269c1..194114aa 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -10362,6 +10362,35 @@ bool GetLastItem( return result; } +// +// Remove Last Item of Specified Buffer ... +template +bool RemoveLastItem( + T &buffer[] // Specified Buffer +) +{ + // + bool result = false; + + // + int count = ArraySize(buffer); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + ArrayRemove( + buffer, + count - 1, + 1 // + ); + + // + return result; +} + // // Search Array For Specific Item ... template diff --git a/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 b/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 index 5c0b0875..042c89d4 100644 --- a/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 +++ b/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 @@ -26,6 +26,140 @@ // // Definitions ... +struct XSarChange +{ + // + // Props ... + ENUM_X_DIRECTION dir; // Sar Changed To Direction ... + datetime time; // Sar Changed Time ... + double last; // Sar Value Before Change ... + double value; // Sar Value After Change ... + + // + // Constructor ... + XSarChange() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + last = 0; + value = 0; + time = NULL; + dir = X_DIRECTION_NONE; + } + + /** + * Validation ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + last > 0 && + value > 0 && + IsValid(time) && + HasDirection(dir); + + // + return result; + } + + /** + * Initialize ... + * + * @param _last: Last Sar Value ... + * @param _current: Current Sar Value ... + * + * @return ( bool ) + */ + bool Init( + double _last, + double _current, + datetime _time, + ENUM_X_DIRECTION _dir // + ) + { + // + bool result = false; + + // + result = + _last > 0 && + _current > 0 && + IsValid(_time) && + HasDirection(_dir); + if (!result) + { + return result; + } + + // + dir = _dir; + last = _last; + time = _time; + value = _current; + + // + result = IsValid(); + + // + return result; + } + + /** + * Check Change is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = + IsValid() && + IsBullish(dir); + + // + return result; + } + + /** + * Check Change is Bearish ... + * + * @return ( bool ) + */ + bool IsBearishّ() + { + // + bool result = false; + + // + result = + IsValid() && + IsBearish(dir); + + // + return result; + } + + // +}; // // Implementations ... @@ -40,6 +174,8 @@ class XC121SMCCycleHelper : public XCBase // // XPV ... XCXPVHelper *mXPVHelper; + XPVPivot pivots[]; + XPVPivot orderFlow[]; // // X3MA ... @@ -52,6 +188,7 @@ class XC121SMCCycleHelper : public XCBase // // XCHSAR ... XCXCHSARHelper *mXCHSARHelper; + XSarChange sarChanges[]; // // POI Detector ... @@ -271,6 +408,102 @@ class XC121SMCCycleHelper : public XCBase return result; } + /** + * Retrieve Specified Bar ... + * + * @param bar: XOHCL instance ... + * @param index: Integer ... + * + * @return ( bool ) + */ + bool GetBar( + XOHCL &bar, + int index = 0 // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (index < 0) + { + index = 0; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + /** + * Retrieve Specified Bar ... + * + * @param bar: XOHCL instance ... + * @param time: Datetime ... + * + * @return ( bool ) + */ + bool GetBar( + XOHCL &bar, + datetime time = NULL // + ) + { + // + bool result = false; + + // + int index = GetBarIndex(time); + result = GetBar(bar, + index // + ); + + // + return result; + } + + /** + * Retrieve Specified Time Bar Index ... + * + * @param time: DateTime ... + * + * @return ( int ) + */ + int GetBarIndex(datetime time = NULL) + { + // + int result = -1; + + // + time = NormalizeTime(time); + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + result = iBarShift( + symbol, + period, + time // + ); + + // + return result; + } + /** * Retrieve Cycle Conditions ... * @@ -569,6 +802,557 @@ class XC121SMCCycleHelper : public XCBase return result; } + // + // Parabolic Sar Extensions ... + + /** + * Check Sar Changes and Save it ... + * + * @param change: XSarChange instance ... + * @param time: DateTime ... + * + * @return ( bool ) + */ + bool IsSarChanged( + XSarChange &change, + datetime time = NULL // + ) + { + // + bool result = false; + + // + change.Clean(); + + // + XOHCL bar; + result = GetBar( + bar, + time // + ); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = bar.GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + XOHCL prevPrevBar; + result = prevBar.GetPreviousBar(prevPrevBar); + if (!result) + { + return result; + } + + // + prevPrevBar = prevBar; + prevBar = bar; + + // + int index = prevBar.Index(); + + // + double current = mXCHSARHelper.GetC(index); + double prev = mXCHSARHelper.GetC(index + 1); + + // + bool isCurrentBullish = + current < prevBar.low; + bool isPrevBullish = + prev < prevPrevBar.low; + + // + bool isCurrentBearish = + current > prevBar.high; + bool isPrevBearish = + prev > prevPrevBar.high; + + // + bool isChangedToBullish = + isCurrentBullish && + !isPrevBullish; + + // + bool isChangedToBearish = + isCurrentBearish && + !isPrevBearish; + + // + result = isChangedToBullish || + isChangedToBearish; + if (!result) + { + return result; + } + ENUM_X_DIRECTION dir = + isChangedToBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = change + .Init( + prev, + current, + prevBar.time, + dir // + ); + if (!result) + { + return result; + } + + // + XSarChange lastChange; + bool hasLastItem = GetLastItem( + lastChange, + sarChanges // + ); + bool canAdd = !hasLastItem + ? true + : lastChange.time < change.time; + if (canAdd) + { + // + AddRef( + change, + sarChanges // + ); + } + + // + CleanSarChanges(); + + // + return result; + } + + /** + * Cleanup Unused Sar Changes ... + */ + void CleanSarChanges() + { + // + int required = 10; + int count = ArraySize(sarChanges); + if (!IsValidSize(count) || count <= required) + { + return; + } + + // + int mustRemove = count - required; + ArrayRemove( + sarChanges, + 0, + mustRemove // + ); + } + + // + // XPV Extensions ... + + /** + * Detect First Pivot ... + * + * @param pivot: XPVPivot instance ... + * @param time: DateTime ... + * @param minRepetition: Integer, Minimum Repetition ... + * @param maxAllowedLoopbackBars: Integer, Max Allowed LoopBack Bars ... + * + * @return ( bool ) + */ + bool DetectLastPivot( + XPVPivot &pivot, + datetime time = NULL, + int minRepetition = 40, + int maxAllowedLoopbackBars = 576 // + ) + { + // + bool result = false; + + // + pivot.Clean(); + + // + int index = GetBarIndex(time); + result = DetectPivot( + pivot, + index, + minRepetition, + maxAllowedLoopbackBars // + ); + + // + return result; + } + + /** + * Detect Pivot ... + * + * @param pivot: XPVPivot instance ... + * @param barIndex: Integer ... + * @param minRepetition: Integer, Minimum Repetition ... + * @param maxAllowedLoopbackBars: Integer, Max Allowed LoopBack Bars ... + * + * @return ( bool ) + */ + bool DetectPivot( + XPVPivot &pivot, + int barIndex = 0, + int minRepetition = 40, + int maxAllowedLoopbackBars = 576 // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int start = barIndex; + int end = start + maxAllowedLoopbackBars; + + // + double peak = 0; + int peakRepeate = 0; + int peakToBarIndex = 0; + int peakFromBarIndex = 0; + + // + double vale = 0; + int valeRepeate = 0; + int valeToBarIndex = 0; + int valeFromBarIndex = 0; + + // + bool canLookupPeak = true; + bool canLookupVale = true; + bool canLookup = true; + while (canLookup) + { + // + // Check Peak ... + double iPeak = mXPVHelper.GetPeak(barIndex); + if (iPeak != peak) + { + // + if (peak != 0 && + peakRepeate >= minRepetition) + { + // + XPVPivot iPivot; + + // + iPivot.lower = 0; + iPivot.upper = peak; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_PEAK; + iPivot.repetition = peakRepeate; + iPivot.to = iTime( + symbol, + period, + peakToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + peakFromBarIndex // + ); + + // + iPivot.lower = iPivot.CalculateLower(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + pivot = iPivot; + break; + } + } + + // + peak = iPeak; + peakRepeate = 0; + peakFromBarIndex = 0; + peakToBarIndex = barIndex; + } + else if (iPeak == peak) + { + // + peakRepeate++; + peakFromBarIndex = barIndex; + } + + // + // Check Vale ... + double iVale = mXPVHelper.GetVale(barIndex); + if (iVale != vale) + { + // + if (vale != 0 && + valeRepeate >= minRepetition) + { + // + XPVPivot iPivot; + + // + iPivot.upper = 0; + iPivot.lower = vale; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_VALE; + iPivot.repetition = valeRepeate; + iPivot.to = iTime( + symbol, + period, + valeToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + valeFromBarIndex // + ); + + // + iPivot.upper = iPivot.CalculateUpper(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + pivot = iPivot; + break; + } + } + + // + vale = iVale; + valeRepeate = 0; + valeFromBarIndex = 0; + valeToBarIndex = barIndex; + } + else if (iVale == vale) + { + // + valeRepeate++; + valeFromBarIndex = barIndex; + } + + // + canLookupPeak = !pivot.IsValid(); + canLookupVale = !pivot.IsValid(); + canLookup = barIndex < end && + (canLookupPeak || + canLookupVale); + if (canLookup) + { + barIndex++; + } + } + + // + result = pivot.IsValid(); + if (result) + { + // + XPVPivot last; + bool hasLastPivot = GetLastPivot(last); + + // + if (hasLastPivot) + { + // + // Check For Pivot Update ... + bool isLastPivotSameAsCurrent = + pivot.IsValid() && + last.IsValid() && + pivot.from == last.from && + pivot.type == last.type; + if (!isLastPivotSameAsCurrent) + { + // + AddRef( + pivot, + pivots // + ); + + // + CleanPivots(); + } + else + { + // + // Update Last Pivot ... + RemoveLastItem(pivots); + + // + pivot.to = TimeCurrent(); + + // + AddRef( + pivot, + pivots // + ); + + // + CleanPivots(); + } + } + else + { + // + // Add New Pivot ... + AddRef( + pivot, + pivots // + ); + + // + CleanPivots(); + } + } + + // + return result; + } + + /** + * Retriece Last Pivot if Exists ... + * + * @param pivot: XPVPivot instane ... + * + * @return ( bool ) + */ + bool GetLastPivot(XPVPivot &pivot) + { + // + bool result = false; + + // + pivot.Clean(); + + // + int count = ArraySize(pivots); + if (!IsValidSize(count)) + { + return result; + } + + // + result = GetLastItem( + pivot, + pivots // + ); + + // + return result; + } + + /** + * Detect Order Flow ... + * + * @param dir: ENUM_X_DIRECTION member, Hold's Order Flow Direction ... + * @param minPivots: Integer, minimum Required Pivots for Order Flow ... + * + * @return ( bool ) + */ + bool DetectOrderFlow( + ENUM_X_DIRECTION &dir, + int minPivots = 3 // + ) + { + // + bool result = false; + + // + // Normalize Minimum Pivots ... + if (minPivots < 2) + { + minPivots = 2; + } + + // + Clean(orderFlow); + Copy( + pivots, + orderFlow // + ); + + // + // Sort Pivots ... + SortPivots(orderFlow); + + // + // Filter Broken Order Flows ... + FilterBrokenPivots(orderFlow); + + // + int count = ArraySize(orderFlow); + result = IsValidSize(count) && + count >= minPivots; + if (!result) + { + return result; + } + + // + // Detect Order Flow Direction ... + result = DetectPivotDirection( + orderFlow, + dir // + ); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Cleanup Unused Pivots ... + */ + void CleanPivots() + { + // + int required = 10; + int count = ArraySize(pivots); + if (!IsValidSize(count) || count <= required) + { + return; + } + + // + int mustRemove = count - required; + ArrayRemove( + pivots, + 0, + mustRemove // + ); + } + // // Virtuals ... diff --git a/X121SMCEA/Libraries/x-121.smc.lib.mq5 b/X121SMCEA/Libraries/x-121.smc.lib.mq5 index 19d97b4d..a3560cea 100644 --- a/X121SMCEA/Libraries/x-121.smc.lib.mq5 +++ b/X121SMCEA/Libraries/x-121.smc.lib.mq5 @@ -751,10 +751,6 @@ struct X121SMCStrategyConditions // double sl; string provider; - XCOrderBlock *visionBullOB; - XCOrderBlock *visionBearOB; - XCOrderBlock *consolidationBullOB; - XCOrderBlock *consolidationBearOB; ENUM_X_DIRECTION marketStructureDir; // @@ -779,10 +775,6 @@ struct X121SMCStrategyConditions // sl = 0; provider = NULL; - visionBullOB = NULL; - visionBearOB = NULL; - consolidationBullOB = NULL; - consolidationBearOB = NULL; marketStructureDir = X_DIRECTION_NONE; // diff --git a/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 b/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 index 046a000a..d59f5240 100644 --- a/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 +++ b/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 @@ -123,6 +123,15 @@ class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy double pip = GetPipPrice(symbol); double pip2 = 2 * pip; + // + // Detect Conditions ... + result = DetectConditions(conditions); + if (!result) + { + conditions.Clean(); + return result; + } + // // Check Spread ... bool isSpreadPassed = IsSpreadPass(); @@ -137,15 +146,6 @@ class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy return result; } - // - // Detect Conditions ... - result = DetectConditions(conditions); - if (!result) - { - conditions.Clean(); - return result; - } - // // Combine all Signals Conditions ... selectedSL = conditions.sl; @@ -459,330 +459,58 @@ class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy conditions.visionConditions.state = mVisionState; // - // Detect an Order Block in Vision ... - if (conditions.visionBullOB == NULL || - conditions.visionBearOB == NULL) - { + // Detect and Store Parabolic Sar Changes ... + XSarChange sarChange; + bool isSarChanged = mTriggerCycleHelper + .IsSarChanged( + sarChange, + cTime // + ); + + // + // Detect and Store Pivots ... + XPVPivot pivot; + bool isPivotDetected = mTriggerCycleHelper + .DetectPivot(pivot); + if (isPivotDetected) { // - result = DetectOrderBlocks( - NULL, - NULL, - conditions.visionBullOB, - conditions.visionBearOB, - cBar, - mVisionState // + Print("Pivot Detected ..."); + + // + XCXPVPivotObject *iObj; + iObj = new XCXPVPivotObject(); + bool isCreated = iObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + pivot // ); - if (!result) + if (isCreated) { // - conditions.Clean(); - return result; - } + if (pivot.IsPeak()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotColor(clrAqua); + iObj.PivotStyle(STYLE_SOLID); + } - // - XCBullishOrderBlockObject *iBullOBObj; - conditions.visionBullOB.To(cTime); - result = mPOIDrawer.CreateBullishOrderBlock( - conditions.visionBullOB, - iBullOBObj // - ); - if (result) - { - AddObjectIfNotExists(iBullOBObj); - } + // + if (pivot.IsVale()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotStyle(STYLE_SOLID); + iObj.PivotColor(clrMagenta); + } - // - XCBearishOrderBlockObject *iBearOBObj; - conditions.visionBearOB.To(cTime); - result = mPOIDrawer.CreateBearishOrderBlock( - conditions.visionBearOB, - iBearOBObj // - ); - if (result) - { - AddObjectIfNotExists(iBearOBObj); + // + AddObjectIfNotExists(iObj); } } - // - // Consolidation Order Blocks ... - if (conditions.consolidationBullOB == NULL || - conditions.consolidationBearOB == NULL) - { - // - result = DetectOrderBlocks( - conditions.visionBullOB, - conditions.visionBearOB, - conditions.consolidationBullOB, - conditions.consolidationBearOB, - cBar, - mConsolidationState // - ); - if (!result) - { - // - conditions.Clean(); - return result; - } - - // - XCBullishOrderBlockObject *iBullOBObj; - conditions.consolidationBullOB.To(cTime); - result = mPOIDrawer.CreateBullishOrderBlock( - conditions.consolidationBullOB, - iBullOBObj // - ); - if (result) - { - AddObjectIfNotExists(iBullOBObj); - } - - // - XCBearishOrderBlockObject *iBearOBObj; - conditions.consolidationBearOB.To(cTime); - result = mPOIDrawer.CreateBearishOrderBlock( - conditions.consolidationBearOB, - iBearOBObj // - ); - if (result) - { - AddObjectIfNotExists(iBearOBObj); - } - } - - // - msg = "OrderBlocks Detected ..."; - Alert(msg); - - // - // Detect Trigger Order Flow ... - if (!HasValidOrderFlow()) - { - // - int samePivots = 40; - int requiredPivots = 10; - - // - bool useVisionState = false; - bool useConsolidationState = false; - bool useVerificationState = false; - bool useAnalyseState = false; - bool useDecisionState = true; - bool useTriggerState = false; - - // - DetectOrderFlow( - cIndex, - samePivots, - requiredPivots, - mTriggerCycleHelper, - mOrderFlow, - mOrderFlowDir, - // - // Filling Pivot State ... - useVisionState, // Use Vision State ... - useConsolidationState, // Use Consolidation State ... - useVerificationState, // Use Verification State ... - useAnalyseState, // Use Analyse State ... - useDecisionState, // Use Decision State ... - useTriggerState // Use Trigger State ... - ); - - // - result = HasValidOrderFlow(); - if (!result) - { - // - conditions.Clean(); - return result; - } - - // - bool ignoreSwingHighs = true; - bool ignoreSwingLows = true; - bool ignoreSupportZones = true; - bool ignoreResistanceZones = true; - bool ignoreSupplyZones = true; - bool ignoreDemandZones = true; - bool ignoreBullishOrderBlocks = true; - bool ignoreBearishOrderBlocks = true; - bool ignoreBullishFairValueGaps = true; - bool ignoreBearishFairValueGaps = true; - bool ignoreBullishRejectionBars = true; - bool ignoreBearishRejectionBars = true; - bool ignoreBullishMomentumBars = true; - bool ignoreBearishMomentumBars = true; - - // - RedrawOrderFlow( - false, // Force Clean ... - false, // Same Period ... - true, // Order Flow ... - true, // Order Flow State ... - false, // Only Last Order Flow ... - true, // Only Last Order Flow State ... - // - mOrderFlowDir, // Direction Force ... - ignoreSwingHighs, - ignoreSwingLows, - ignoreSupportZones, - ignoreResistanceZones, - ignoreSupplyZones, - ignoreDemandZones, - ignoreBullishOrderBlocks, - ignoreBearishOrderBlocks, - ignoreBullishFairValueGaps, - ignoreBearishFairValueGaps, - ignoreBullishRejectionBars, - ignoreBearishRejectionBars, - ignoreBullishMomentumBars, - ignoreBearishMomentumBars // - ); - } - - // - msg = "Found OrderFlow : " + (IsBullish(mOrderFlowDir) ? "Bullish" : "Berish"); - Alert(msg); - - // - // Check Market Conditions for - // Specified Structure ... - // ENUM_X_DIRECTION marketStructureDir = X_DIRECTION_NONE; - // result = conditions.HasDirection( - // marketStructureDir, - // cBar // - // ); - // if (!result) - // { - // // - // conditions.Clean(); - // return result; - // } - // msg = "Found Market Strucutre : " + (IsBullish(marketStructureDir) ? "Bullish" : "Berish"); - // Alert(msg); - - // - // conditions.marketStructureDir = marketStructureDir; - - // // - // XPVPivot lastPivot; - // result = GetLastItem( - // lastPivot, - // mOrderFlow // - // ); - // if (!result) - // { - // // - // conditions.Clean(); - // return result; - // } - - // - // Detect Last FVG ... - // XOHCL breakerBar; - // result = DetectLastBreakerBar( - // cBar, - // breakerBar, - // lastPivot, - // marketStructureDir // - // ); - // if (!result) - // { - // // - // conditions.Clean(); - // return result; - // } - // msg = "Found Breaker Bar: " + breakerBar.GetTag(); - // Alert(msg); - - // // - // // Detect Nearest Momentum or Rejection Bar ... - // XOHCL decisionBar; - // result = mDecisionCycleHelper.DetectNearestDecisionBar( - // decisionBar, - // marketStructureDir, - // cBar // - // ); - // if (!result) - // { - // return result; - // } - // msg = "Found Decision Bar: " + decisionBar.GetTag(); - // Alert(msg); - - // // - // // Detect Nearest Sar Change ... - // XOHCL sarChangeBar; - // result = mTriggerCycleHelper.DetectNearestCSARChange( - // sarChangeBar, - // cBar // - // ); - // if (!result) - // { - // // - // conditions.Clean(); - // return result; - // } - // msg = "Found Sar Change Bar: " + sarChangeBar.GetTag(); - // Alert(msg); - - // // - // // Now we Hvae to Check Other Conditions ... - // result = - // // breakerBar.time > sarChangeBar.time && - // // decisionBar.time > breakerBar.time; - // decisionBar.time > sarChangeBar.time; - // if (!result) - // { - // // - // conditions.Clean(); - // return result; - // } - - // // - // // Now we Have Check Direction Related Conditions ... - // if (IsBullish(marketStructureDir)) - // { - // // - // result = - // // bid > decisionBar.high && - // // bid > breakerBar.high && - // bid > sarChangeBar.high && - // bid > conditions.triggerConditions.xchsarConditions.cSars[0]; - // } - // else - // { - // // - // result = - // // bid < decisionBar.low && - // // bid < breakerBar.low && - // bid < sarChangeBar.high && - // bid < conditions.triggerConditions.xchsarConditions.cSars[0]; - // } - // if (!result) - // { - // // - // conditions.Clean(); - // return result; - // } - - // // - // conditions.provider = "X121SMC"; - // if (IsBullish(marketStructureDir)) - // { - // // - // // conditions.sl = decisionBar.low; - // // conditions.sl = breakerBar.low; - // conditions.sl = conditions.triggerConditions.xchsarConditions.cSars[0]; - // } - // else - // { - // // - // // conditions.sl = decisionBar.high; - // // conditions.sl = breakerBar.high; - // conditions.sl = conditions.triggerConditions.xchsarConditions.cSars[0]; - // } - // if (!result) {