/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // -------------------------------------- // Name: XSCX121Strategy // 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-saherelm.x-poi.class.mq5" #include "../../Classes/x-saherelm.xalert.class.mq5" #include "../../Classes/x-saherelm.xtrade.class.mq5" #include "../Libraries/x-121.smc.lib.mq5" // // Helper(s) ... // // XStrategy Class Implementation(s) ... class XCX121SMCStrategy : public XSCBaseAlert { // // Public ... public: // // // Constructor(s) ... void XCX121SMCStrategy( // // Base ... string _symbol, // Trading Symbol ENUM_TIMEFRAMES _period // Trading TimeFrame ) { // mSymbol = _symbol; mPeriod = _period; // Init(); } // // Deconstructor ... void ~XCX121SMCStrategy() { DeInit(); } // // Getter / Setter (s) ... /** * Retrieve Symbol ... * * @return ( string ) */ string Symbol() { return mSymbol; } /** * Retrieve TimeFrame ... * * @return ( ENUM_TIMEFRAMES ) */ ENUM_TIMEFRAMES Period() { return mPeriod; } /** * Check Strategy is Disabled or not ... * * @return ( bool ) */ bool IsDisabled() { return mForceDisabled; } /** * Get Chart Id ... * * @return ( long ) */ long ChartIdentification() { return mChartID; } /** * Set Chart Id ... * * @param value: Long ... */ void ChartIdentification(long value) { // if (value < 0) { value = 0; } // mChartID = value; if (mPOIDrawer != NULL) { mPOIDrawer.ChartIdentification(value); } } /** * Get Sub Window Id ... * * @return ( int ) */ int SubWindowIdentification() { return mSubWindow; } /** * Set Sub Window Id ... * * @param value: Integer ... */ void SubWindowIdentification(int value) { // if (value < 0) { value = 0; } // mSubWindow = value; if (mPOIDrawer != NULL) { mPOIDrawer.SubWindowIdentification(value); } } /** * Get Signal Volume ... * * @return ( double ) */ double Volume() { return mVolume; } /** * Set Signal Volume ... * * @param value: Double ... */ void Volume(double value) { // if (value < 0.01) { value = 0.01; } // mVolume = value; } /** * Get Risk/Reward Ratio ... * * @return ( double ) */ double R2R() { return mR2R; } /** * Set Risk/Reward Ratio ... * * @param value: Double ... */ void R2R(double value) { // if (value < 0) { value = 1.5; } // mR2R = value; } /** * Get Max Allowed Spread ... * * @return ( double ) */ double MaxAllowedSpread() { return mMaxAllowedSpread; } /** * Set Max Allowed Spread ... * * @param value: Double ... */ void MaxAllowedSpread(double value) { mMaxAllowedSpread = value; } /** * Get Long Signalling State ... * * @return ( bool ) */ bool AllowLong() { return mAllowLong; } /** * Set Long Signalling State ... * * @param value: Boolean ... */ void AllowLong(bool value) { mAllowLong = value; } /** * Get Short Signalling State ... * * @return ( bool ) */ bool AllowShort() { return mAllowShort; } /** * Set Short Signalling State ... * * @param value: Argument 1 */ void AllowShort(bool value) { mAllowShort = value; } // // Actions ... /** * Disable Strategy ... */ void Disable() { mForceDisabled = true; } /** * Enable Strategy ... */ void Enable() { mForceDisabled = false; } /** * Register Signal Event Handler ... * * @param handler: an Instance of TOnXSignal ... */ void AddXSignalEventHandler(TOnX121SMCSignal handler) { // Add( handler, mSignalEventHandlers // ); } // // Virtual Actions ... // // Check Conditions For Signal and Execute Signal ... virtual void HandleTick() { // // Check State ... if (IsDisabled()) { return; } // // Check Signalling State ... if (!AllowLong() && !AllowShort()) { return; } // // Check Bar Tracker State ... if (!mBarTracker.CanProcessBar()) { return; } // // Retrieve Current Tick and Check it's Time // by Last Issued Tick ... MqlTick cTick; bool hasTick = GetTick( mSymbol, cTick // ); bool isSameAsLast = cTick.time == mLastTick.time; if (isSameAsLast) { return; } // // Update Last Issued Tick ... mLastTick = cTick; SaveTickData(); CleanupTicks(); // // Update POIs ... // ENUM_XPOI_EVENTS _1DStates[]; m1DPOI.Update(_1DStates); // ENUM_XPOI_EVENTS _4HStates[]; m4HPOI.Update(_4HStates); // // // ENUM_XPOI_EVENTS _4HSupDemStates[]; // m4HSupDemPOI.Update(_4HSupDemStates); // ENUM_XPOI_EVENTS _15MStates[]; m15MPOI.Update(_15MStates); // ENUM_XPOI_EVENTS _5MStates[]; m5MPOI.Update(_5MStates); // ENUM_XPOI_EVENTS _1MStates[]; m1MPOI.Update(_1MStates); // // Check Current Processing Tick has Signal or not ... XSignal signal; X121SMCStrategyConditions conditions; bool hasSignal = HasSignal( signal, conditions // ); if (!hasSignal) { return; } // // Waits Until Next Candle if Current Tick has Signal ... mBarTracker.Waits(); // // Notify Signal Event Handlers ... NotifyOnSignalEventHandlers( signal, conditions // ); // DrawSignal( signal, conditions // ); // // ClearDraws(); } // // Check Conditions For Signal ... virtual bool HasSignal( XSignal &signal, X121SMCStrategyConditions &conditions // ) { // 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(); 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; // // Start Calculations ... // double points = GetPoints(mSymbol); // int zIndex = 0; int cIndex = zIndex + 1; int pIndex = cIndex + 1; int ppIndex = pIndex + 1; // // Retrieve Bars ... // // Zero Bar ... XOHCL zBar; result = zBar.Init( mSymbol, mPeriod, zIndex // ); if (!result) { return result; } // // Last Bar ... XOHCL cBar; result = cBar.Init( mSymbol, mPeriod, cIndex // ); if (!result) { return result; } // // Previous Bar ... XOHCL pBar; result = pBar.Init( mSymbol, mPeriod, pIndex // ); if (!result) { return result; } // bool isSpreadPassed = IsSpreadPass(); result = isSpreadPassed; if (!result) { return result; } // // Reading POI(s) ... // // 1D ... XPOIState _1DState; m1DPOI.GetState(_1DState); // // 4H ... XPOIState _4HState; m4HPOI.GetState(_4HState); // // 15M ... XPOIState _15MState; m15MPOI.GetState(_15MState); // // 5M ... XPOIState _5MState; m5MPOI.GetState(_5MState); // // 1M ... XPOIState _1MState; m1MPOI.GetState(_1MState); // // Combine States ... XPOIState _CState; XPOIState _States[]; AddRef( _1DState, _States // ); AddRef( _4HState, _States // ); AddRef( _15MState, _States // ); AddRef( _5MState, _States // ); AddRef( _1MState, _States // ); CombineStates( _CState, _States // ); // // Try to Implement SMC Based Conditions ... // // 1- First Step is Find a Supply and Demand Zone ... // - [] this Zone must be Fresh ... // - [] contains Engulfing ... // - [] has Order Block ... // - [] has FVG ... bool isDetected = DetectImportantPOIs( conditions, _1DState, _4HState, _15MState, _5MState, _1MState // ); if (isDetected) { // // Check Conditions for Removing Exists ... RemoveConditionsIfExists(conditions); // // Add New Condition ... AddRef( conditions, mConditions // ); } // conditions.Clean(); // // Check Conditions for Signal ... int conditionsCount = ArraySize(mConditions); if (!IsValidSize(conditionsCount)) { // result = false; return result; } // // Loop through Conditions for Filter Based on POIs ... int conditionsIDX = -1; for (int i = 0; i < conditionsCount; i++) { // result = false; hasLong = false; hasShort = false; X121SMCStrategyConditions iConditions = mConditions[i]; // X121SMCMarketStructure structure; DetectMarketStructure( structure, iConditions, _1DState, _4HState, _15MState, _5MState, _1MState // ); // bool isAllowLong = AllowLong(); bool isAllowShort = AllowShort(); result = isAllowLong || isAllowShort; if (!result) { break; } // bool hasValidDemand = HasValidDemand(iConditions); bool hasValidSupply = HasValidSupply(iConditions); result = hasValidDemand || hasValidSupply; if (!result) { break; } // bool isPriceInsideDemandZone = pBar.high < iConditions.demandZone.upper; bool isPriceInsideSupplyZone = pBar.low > iConditions.supplyZone.lower; // bool isTicksBullish = IsTicksBullish(); bool isTicksBearish = IsTicksBearish(); bool isTicksHasMomentum = IsTicksHasMomentum(); // double _1Pip = GetPipPrice(iConditions.symbol); // // Longs ... bool canCheckLong = isAllowLong && hasValidDemand && isTicksBullish && isTicksHasMomentum && isPriceInsideDemandZone; if (canCheckLong) { // hasLong = false; type = POSITION_TYPE_BUY; entry = GetEntry(mSymbol, type); // double slCandidates[]; int slCandidatesCount = DetectSLCandidates( slCandidates, entry, iConditions, X_POSITION_TYPE_LONG // ); // // Find Demand Zone ... hasLong = slCandidatesCount > 2; // if (hasLong) { // double selectedSL = GetMin(slCandidates); sl = selectedSL - (5 * _1Pip); risk = entry - sl; reward = risk * r2r; tp = entry + reward; // conditionsIDX = i; mConditions[i].CleanDemand(); // break; } } // // Shorts ... bool canCheckShort = isAllowShort && hasValidSupply && isTicksBearish && isTicksHasMomentum && isPriceInsideSupplyZone; if (canCheckShort) { // hasShort = false; DrawMarketStructure( structure, X_POSITION_TYPE_SHORT // ); DrawConditions(iConditions); ClearDraws(); // if (hasShort) { // type = POSITION_TYPE_SELL; entry = GetEntry(mSymbol, type); sl = iConditions.supplyZone.upper + (10 * points); risk = sl - entry; reward = risk * r2r; tp = entry - reward; // conditionsIDX = i; mConditions[i].CleanSupply(); // break; } } } // result = hasLong || hasShort; // // Rmove Signal Condition ... if (result) { // if (IsValidIndex(conditionsIDX)) { // conditions = mConditions[conditionsIDX]; // bool hasValidDemand = HasValidDemand(mConditions[conditionsIDX]); bool hasValidSupply = HasValidSupply(mConditions[conditionsIDX]); // if (!hasValidDemand && !hasValidSupply) { // ArrayRemove( mConditions, conditionsIDX, 1 // ); } } // signal.sl = sl; signal.tp = tp; signal.type = type; signal.mode = mode; signal.entry = entry; signal.volume = volume; signal.symbol = mSymbol; signal.pushers = pushers; signal.provider = GetTag(); signal.time = TimeCurrent(); signal.period = _5MState.period; // result = PrepareSignal(signal); // hasLong = false; hasShort = false; } // return result; } // // Overrides ... // // Customize Strategy Identifier ... string GetTag() override { return X121SMCStrategyToken; } // // Protected ... protected: // // // Props ... // // Actions ... /** * Check Spread Passed for Positions... * * @return ( bool ) */ bool IsSpreadPass() { // bool result = false; // int length = 5; double pointValue = GetPoints(mSymbol); double maxAllowedSpread = MaxAllowedSpread(); if (maxAllowedSpread > 0) { maxAllowedSpread *= pointValue; } else { maxAllowedSpread = 0; } // int ticksCount = ArraySize(mTicks); if (ticksCount <= length) { return result; } // int start = -1; int end = -1; CalculateTicksParams( start, end, length + 1 // ); result = IsValidIndex(start) && IsValidIndex(end); if (!result) { return result; } // end -= 1; double spreadAVG = 0; for (int i = start; i < end; i++) { spreadAVG += mTicks[i].spread; } spreadAVG /= length; // double lastSpread = mTicks[ticksCount - 1].spread; // result = lastSpread <= spreadAVG && (maxAllowedSpread <= 0 ? true : lastSpread <= maxAllowedSpread); // return result; } /** * Check Ticks is Bullish or not ... * * @return ( bool ) */ bool IsTicksBullish() { // bool result = false; // int start = -1; int end = -1; int requiredBullishTicks = 5; CalculateTicksParams( start, end, requiredBullishTicks // ); result = IsValidIndex(start) && IsValidIndex(end); if (!result) { return result; } // result = true; for (int i = start + 1; i < end; i++) { // XTick iTick = mTicks[i]; XTick prevTick = mTicks[i - 1]; // bool isBullish = iTick.bid >= prevTick.bid; result = result && isBullish; if (!result) { break; } } // return result; } /** * Check Ticks is Bearish or not ... * * @return ( bool ) */ bool IsTicksBearish() { // bool result = false; // int start = -1; int end = -1; int requiredBearishTicks = 5; CalculateTicksParams( start, end, requiredBearishTicks // ); result = IsValidIndex(start) && IsValidIndex(end); if (!result) { return result; } // result = true; for (int i = start + 1; i < end; i++) { // XTick iTick = mTicks[i]; XTick prevTick = mTicks[i - 1]; // bool isBearish = iTick.bid <= prevTick.bid; result = result && isBearish; if (!result) { break; } } // return result; } /** * Check Ticks Has Momentum or not ... * * @return ( bool ) */ bool IsTicksHasMomentum() { // bool result = false; // int start = -1; int end = -1; int requiredTicksForMomentum = 5; CalculateTicksParams( start, end, requiredTicksForMomentum // ); result = IsValidIndex(start) && IsValidIndex(end); if (!result) { return result; } // result = true; int lastDiff = 0; for (int i = start + 1; i < end; i++) { // XTick iTick = mTicks[i]; XTick prevTick = mTicks[i - 1]; // int timeDiff = MathAbs((int)iTick.time - (int)prevTick.bid); if (lastDiff <= 0) { lastDiff = timeDiff; } result = result && timeDiff >= lastDiff; if (!result) { break; } // lastDiff = timeDiff; } // return result; } /** * Prepare and Normalize Signal for Execution in Strategy ... * * @param signal: XSignal instance ... * * @return ( bool ) */ bool PrepareSignal(XSignal &signal) { // bool result = false; // // Check Strategy Is Enables ... result = !IsDisabled(); if (!result) { return result; } // // Validate Signal ... result = signal.IsValid(); if (!result) { return result; } // bool isLong = IsLong(signal.type); // // TODO: Implement Signal Preparation Mechanism here ... // return result; } /** * Update Supply and Demand Zones ... * * @param conditions: X121SMCStrategyConditions instance ... * @param d1State: XPOIState instance ... * @param h4State: XPOIState instance ... * @param m15State: XPOIState instance ... * @param m5State: XPOIState instance ... * @param m1State: XPOIState instance ... */ bool DetectImportantPOIs( X121SMCStrategyConditions &conditions, XPOIState &d1State, XPOIState &h4State, XPOIState &m15State, XPOIState &m5State, XPOIState &m1State // ) { // bool result = false; // // Prepare Conditions ... // datetime time = TimeCurrent(); // conditions.Clean(); conditions.time = time; conditions.symbol = mSymbol; conditions.period = mPeriod; // // // bool d1HasBullishTrend = HasBullishTrend(d1State); // bool d1HasBearishTrend = HasBearishTrend(d1State); // // // bool h4HasBullishTrend = HasBullishTrend(h4State); // bool h4HasBearishTrend = HasBearishTrend(h4State); // // // bool m15HasBullishTrend = HasBullishTrend(m15State); // bool m15HasBearishTrend = HasBearishTrend(m15State); // // // bool m5HasBullishTrend = HasBullishTrend(m5State); // bool m5HasBearishTrend = HasBearishTrend(m5State); // // // bool m1HasBullishTrend = HasBullishTrend(m1State); // bool m1HasBearishTrend = HasBearishTrend(m1State); // // // bool isBullishTrendValid = h4HasBullishTrend && // m15HasBullishTrend && // m1HasBullishTrend; // if (isBullishTrendValid) // { // Print("isBullishTrendValid"); // } // // // bool isBearishTrendValid = h4HasBearishTrend && // m15HasBearishTrend && // m1HasBearishTrend; // if (isBearishTrendValid) // { // Print("isBearishTrendValid"); // } // // Combine States ... XPOIState states[]; AddRef( d1State, states // ); AddRef( h4State, states // ); AddRef( m15State, states // ); AddRef( m5State, states // ); AddRef( m1State, states // ); XPOIState cState; CombineStates( cState, states // ); // int supplyZonesCount = ArraySize(m15State.supplyZones); int demandZonesCount = ArraySize(m15State.demandZones); result = IsValidSize(demandZonesCount) || IsValidSize(supplyZonesCount); if (!result) { return result; } // bool checkDemands = true; bool checkSupplies = true; // // Demand Zone ... if (checkDemands) { // for (int i = 0; i < demandZonesCount; i++) { // // Demand Zone ... XZone iDemandZone = m15State.demandZones[i]; iDemandZone.to = time; conditions.demandZone = iDemandZone; // // Order Blocks ... // CState ... int orderBlocksCount = ArraySize(cState.bullishOrderBlocks); if (IsValidSize(orderBlocksCount)) { // for (int j = 0; j < orderBlocksCount; j++) { // XZone jZone = cState.bullishOrderBlocks[j]; // bool isInside = IsInside( jZone, iDemandZone, X_ZONE_LOWER_EDGE, true // ); if (isInside) { // jZone.to = TimeCurrent(); // AddIfNotExists( jZone, conditions.bullishOrderBlocks // ); } } } // // Support Zones ... // CState ... int supportsCount = ArraySize(cState.supportZones); if (IsValidSize(supportsCount)) { // for (int j = 0; j < supportsCount; j++) { // XOHCL jBar = cState.supportZones[j]; // bool isInside = IsInside( jBar, iDemandZone, X_ZONE_LOWER_EDGE, true // ); if (isInside) { // AddIfNotExists( jBar, conditions.supports // ); } } } // // Fair Value Gaps ... // CState ... int fvgsCount = ArraySize(cState.bullishFVGs); if (IsValidSize(fvgsCount)) { // for (int j = 0; j < fvgsCount; j++) { // XZone jFVG = cState.bullishFVGs[j]; // bool isInside = IsInside( jFVG, iDemandZone, X_ZONE_LOWER_EDGE, true // ); if (isInside) { // jFVG.to = TimeCurrent(); // AddIfNotExists( jFVG, conditions.bullishFVGs // ); } } } // // Swings ... // CState ... int swingsCount = ArraySize(cState.swingLows); if (IsValidSize(swingsCount)) { // for (int j = 0; j < swingsCount; j++) { // XOHCL jBar = cState.swingLows[j]; // bool isInside = IsInside( jBar, iDemandZone, X_ZONE_LOWER_EDGE, true // ); if (isInside) { // AddIfNotExists( jBar, conditions.swingLows // ); } } } // // Momentum Bars ... // CState ... int momentumBarsCount = ArraySize(cState.momentumBars); if (IsValidSize(momentumBarsCount)) { // for (int j = 0; j < momentumBarsCount; j++) { // XOHCL jBar = cState.momentumBars[j]; // bool isInside = jBar.IsBullish() && jBar.time > iDemandZone.from && IsInside( jBar, iDemandZone, X_ZONE_LOWER_EDGE, true // ); if (isInside) { // AddIfNotExists( jBar, conditions.bullishMomentumBars // ); } } } // // Rejection Bars ... // CState ... int rejectionBarsCount = ArraySize(cState.rejectionBars); if (IsValidSize(rejectionBarsCount)) { // for (int j = 0; j < rejectionBarsCount; j++) { // XOHCL jBar = cState.rejectionBars[j]; // bool isInside = jBar.GetLowShadow() > jBar.GetHighShadow() && jBar.time > iDemandZone.from && IsInside( jBar, iDemandZone, X_ZONE_LOWER_EDGE, true // ); if (isInside) { // AddIfNotExists( jBar, conditions.bullishRejectionBars // ); } } } // bool hasValidDemandZone = HasValidDemand(conditions); if (!hasValidDemandZone) { conditions.CleanDemand(); } else { break; } } } // // Supply Zone ... if (checkSupplies) { // for (int i = 0; i < supplyZonesCount; i++) { // // Supply Zone ... XZone iSupplyZone = m15State.supplyZones[i]; iSupplyZone.to = time; conditions.supplyZone = iSupplyZone; // // Order Blocks ... // CState ... int orderBlocksCount = ArraySize(cState.bearishOrderBlocks); if (IsValidSize(orderBlocksCount)) { // for (int j = 0; j < orderBlocksCount; j++) { // XZone jZone = cState.bearishOrderBlocks[j]; // bool isInside = IsInside( jZone, iSupplyZone, X_ZONE_UPPER_EDGE, true // ); if (isInside) { // jZone.to = TimeCurrent(); // AddIfNotExists( jZone, conditions.bearishOrderBlocks // ); } } } // // Resistance Zones ... // CState ... int resistancesCount = ArraySize(cState.resistanceZones); if (IsValidSize(resistancesCount)) { // for (int j = 0; j < resistancesCount; j++) { // XOHCL jBar = cState.resistanceZones[j]; // bool isInside = IsInside( jBar, iSupplyZone, X_ZONE_UPPER_EDGE, true // ); if (isInside) { // AddIfNotExists( jBar, conditions.resistances // ); } } } // // Fair Value Gaps ... // CState ... int fvgsCount = ArraySize(cState.bearishFVGs); if (IsValidSize(fvgsCount)) { // for (int j = 0; j < fvgsCount; j++) { // XZone jFVG = cState.bearishFVGs[j]; // bool isInside = IsInside( jFVG, iSupplyZone, X_ZONE_UPPER_EDGE, true // ); if (isInside) { // jFVG.to = TimeCurrent(); // AddIfNotExists( jFVG, conditions.bearishFVGs // ); } } } // // Swings ... // CState ... int swingsCount = ArraySize(cState.swingHighs); if (IsValidSize(swingsCount)) { // for (int j = 0; j < swingsCount; j++) { // XOHCL jBar = cState.swingHighs[j]; // bool isInside = IsInside( jBar, iSupplyZone, X_ZONE_UPPER_EDGE, true // ); if (isInside) { // AddIfNotExists( jBar, conditions.swingHighs // ); } } } // // Momentum Bars ... // CState ... int momentumBarsCount = ArraySize(cState.momentumBars); if (IsValidSize(momentumBarsCount)) { // for (int j = 0; j < momentumBarsCount; j++) { // XOHCL jBar = cState.momentumBars[j]; // bool isInside = jBar.IsBearish() && jBar.time > iSupplyZone.from && IsInside( jBar, iSupplyZone, X_ZONE_UPPER_EDGE, true // ); if (isInside) { // AddIfNotExists( jBar, conditions.bearishMomentumBars // ); } } } // // Rejection Bars ... // CState ... int rejectionBarsCount = ArraySize(cState.rejectionBars); if (IsValidSize(rejectionBarsCount)) { // for (int j = 0; j < rejectionBarsCount; j++) { // XOHCL jBar = cState.rejectionBars[j]; // bool isInside = jBar.GetLowShadow() < jBar.GetHighShadow() && jBar.time > iSupplyZone.from && IsInside( jBar, iSupplyZone, X_ZONE_UPPER_EDGE, true // ); if (isInside) { // AddIfNotExists( jBar, conditions.bearishRejectionBars // ); } } } // bool hasValidSupplyZone = HasValidSupply(conditions); if (!hasValidSupplyZone) { conditions.CleanSupply(); } else { break; } } } // // Demand ... // Used for Long ... bool hasValidDemandZone = HasValidDemand(conditions); // // Supply ... // Used for Short ... bool hasValidSupplyZone = HasValidSupply(conditions); // // Check Conditions is Valid or not ... result = hasValidDemandZone || hasValidSupplyZone; if (!result) { conditions.Clean(); } // return result; } /** * Validate a Condition ... * * @param conditions: Argument 1 * @return ( bool ) */ bool ValidateConditions(X121SMCStrategyConditions &conditions) { // bool result = false; // result = conditions.IsValid(); if (!result) { return result; } // bool hasValidDemnd = HasValidDemand(conditions); bool hasValidSupply = HasValidSupply(conditions); result = hasValidDemnd || hasValidSupply; if (!result) { return result; } // int zIndex = 0; int cIndex = zIndex + 1; int pIndex = cIndex + 1; // XOHCL zBar; result = zBar.Init( mSymbol, mPeriod, zIndex // ); if (!result) { return result; } // XOHCL cBar; result = cBar.Init( mSymbol, mPeriod, cIndex // ); if (!result) { return result; } // result = hasValidDemnd ? cBar.high < conditions.demandZone.upper && zBar.high < conditions.demandZone.upper && cBar.low > conditions.demandZone.lower && zBar.low > conditions.demandZone.lower : hasValidSupply ? cBar.high < conditions.demandZone.upper && zBar.high < conditions.demandZone.upper && cBar.low > conditions.demandZone.lower && zBar.low > conditions.demandZone.lower : false; // return result; } /** * Check Conditions has Valid Demand ... * * @param conditions: X121SMCStrategyConditions instance ... * * @return ( bool ) */ bool HasValidDemand(X121SMCStrategyConditions &conditions) { // bool result = false; // result = conditions.IsValid(); if (!result) { return result; } // result = // conditions.demandZone.IsValid() && (ArraySize(conditions.supports) > 0 || ArraySize(conditions.swingLows) > 0 || ArraySize(conditions.bullishFVGs) > 0 || ArraySize(conditions.bullishOrderBlocks) > 0 || ArraySize(conditions.bullishMomentumBars) > 0 || ArraySize(conditions.bullishRejectionBars) > 0) // ; // return result; } /** * Check Conditions has Valid Supply ... * * @param conditions: X121SMCStrategyConditions instance ... * * @return ( bool ) */ bool HasValidSupply(X121SMCStrategyConditions &conditions) { // bool result = false; // result = conditions.IsValid(); if (!result) { return result; } // result = // conditions.supplyZone.IsValid() && (ArraySize(conditions.swingHighs) > 0 || ArraySize(conditions.bearishFVGs) > 0 || ArraySize(conditions.resistances) > 0 || ArraySize(conditions.bearishOrderBlocks) > 0 || ArraySize(conditions.bearishMomentumBars) > 0 || ArraySize(conditions.bearishRejectionBars) > 0) // ; // return result; } /** * Detect Market Structure for Specified Conditions ... * * @param structure: X121SMCMarketStructure instance ... * @param conditions: X121SMCStrategyConditions instance ... * @param d1State: XPOIState instance ... * @param h4State: XPOIState instance ... * @param m15State: XPOIState instance ... * @param m5State: XPOIState instance ... * @param m1State: XPOIState instance ... */ void DetectMarketStructure( X121SMCMarketStructure &structure, X121SMCStrategyConditions &conditions, XPOIState &d1State, XPOIState &h4State, XPOIState &m15State, XPOIState &m5State, XPOIState &m1State // ) { // structure.Clean(); // if (!conditions.IsValid()) { return; } // bool hasValidDemand = HasValidDemand(conditions); bool hasValidSupply = HasValidSupply(conditions); if (!hasValidDemand && !hasValidSupply) { return; } // structure.supplyZone = conditions.supplyZone; structure.demandZone = conditions.demandZone; // // Combine States ... XPOIState cState; XPOIState states[]; AddRef( d1State, states // ); AddRef( h4State, states // ); AddRef( m15State, states // ); // AddRef( // m5State, // states // // ); // AddRef( // m1State, // states // // ); CombineStates( cState, states // ); // datetime cTime = TimeCurrent(); // // Supply Zones ... int supplysCount = ArraySize(cState.supplyZones); if (IsValidSize(supplysCount)) { // for (int i = 0; i < supplysCount; i++) { // XZone iZone = cState.supplyZones[i]; // bool isBetween = IsBetween( iZone, structure.supplyZone, structure.demandZone // ); if (isBetween) { // iZone.to = cTime; // AddIfNotExists( iZone, structure.supplyZones // ); } } } // // Demand Zones ... int demandsCount = ArraySize(cState.demandZones); if (IsValidSize(demandsCount)) { // for (int i = 0; i < demandsCount; i++) { // XZone iZone = cState.demandZones[i]; // bool isBetween = IsBetween( iZone, structure.supplyZone, structure.demandZone // ); if (isBetween) { // iZone.to = cTime; // AddIfNotExists( iZone, structure.demandZones // ); } } } // // Order Blocks ... // // Bullish OBs ... int bullishOBsCount = ArraySize(cState.bullishOrderBlocks); if (IsValidSize(bullishOBsCount)) { // for (int i = 0; i < bullishOBsCount; i++) { // XZone iZone = cState.bullishOrderBlocks[i]; // bool isBetween = IsBetween( iZone, structure.supplyZone, structure.demandZone // ); if (isBetween) { // iZone.to = cTime; // AddIfNotExists( iZone, structure.bullishOrderBlocks // ); } } } // // Bearish OBs ... int bearishOBsCount = ArraySize(cState.bearishOrderBlocks); if (IsValidSize(bearishOBsCount)) { // for (int i = 0; i < bearishOBsCount; i++) { // XZone iZone = cState.bearishOrderBlocks[i]; // bool isBetween = IsBetween( iZone, structure.supplyZone, structure.demandZone // ); if (isBetween) { // iZone.to = cTime; // AddIfNotExists( iZone, structure.bearishOrderBlocks // ); } } } // // Fair Value Gaps ... // // Bullish FVGs ... int bullishFVGsCount = ArraySize(cState.bullishFVGs); if (IsValidSize(bullishFVGsCount)) { // for (int i = 0; i < bullishFVGsCount; i++) { // XZone iZone = cState.bullishFVGs[i]; // bool isBetween = IsBetween( iZone, structure.supplyZone, structure.demandZone // ); if (isBetween) { // iZone.to = cTime; // AddIfNotExists( iZone, structure.bullishFVGs // ); } } } // // Bearish FVGs ... int bearishFVGsCount = ArraySize(cState.bearishFVGs); if (IsValidSize(bearishFVGsCount)) { // for (int i = 0; i < bearishFVGsCount; i++) { // XZone iZone = cState.bearishFVGs[i]; // bool isBetween = IsBetween( iZone, structure.supplyZone, structure.demandZone // ); if (isBetween) { // iZone.to = cTime; // AddIfNotExists( iZone, structure.bearishFVGs // ); } } } // // Swing Highs ... int swingHighsCount = ArraySize(cState.swingHighs); if (IsValidSize(swingHighsCount)) { // for (int i = 0; i < swingHighsCount; i++) { // XOHCL iBar = cState.swingHighs[i]; // bool isBetween = IsBetween( iBar, structure.supplyZone, structure.demandZone // ); if (isBetween) { // AddIfNotExists( iBar, structure.swingHighs // ); } } } // // Swing Lows ... int swingLowsCount = ArraySize(cState.swingLows); if (IsValidSize(swingLowsCount)) { // for (int i = 0; i < swingLowsCount; i++) { // XOHCL iBar = cState.swingLows[i]; // bool isBetween = IsBetween( iBar, structure.supplyZone, structure.demandZone // ); if (isBetween) { // AddIfNotExists( iBar, structure.swingLows // ); } } } // // Support Zones ... int supportsCount = ArraySize(cState.supportZones); if (IsValidSize(supportsCount)) { // for (int i = 0; i < supportsCount; i++) { // XOHCL iBar = cState.supportZones[i]; // bool isBetween = IsBetween( iBar, structure.supplyZone, structure.demandZone // ); if (isBetween) { // AddIfNotExists( iBar, structure.supports // ); } } } // // Resistance Zones ... int resistancesCount = ArraySize(cState.resistanceZones); if (IsValidSize(resistancesCount)) { // for (int i = 0; i < resistancesCount; i++) { // XOHCL iBar = cState.resistanceZones[i]; // bool isBetween = IsBetween( iBar, structure.supplyZone, structure.demandZone // ); if (isBetween) { // AddIfNotExists( iBar, structure.resistances // ); } } } // // Momentum Bars ... int momentumBarCount = ArraySize(cState.momentumBars); if (IsValidSize(momentumBarCount)) { // for (int i = 0; i < momentumBarCount; i++) { // XOHCL iBar = cState.momentumBars[i]; // bool isBetween = IsBetween( iBar, structure.supplyZone, structure.demandZone // ); if (isBetween) { // bool isBullish = iBar.IsBullish(); // if (isBullish) { // AddIfNotExists( iBar, structure.bullishMomentumBars // ); } else { // AddIfNotExists( iBar, structure.bearishMomentumBars // ); } } } } // // Rejection Bars ... int rejectionBarCount = ArraySize(cState.rejectionBars); if (IsValidSize(rejectionBarCount)) { // for (int i = 0; i < rejectionBarCount; i++) { // XOHCL iBar = cState.rejectionBars[i]; // bool isBetween = IsBetween( iBar, structure.supplyZone, structure.demandZone // ); if (isBetween) { // bool isBullish = iBar.GetLowShadow() > iBar.GetHighShadow(); // if (isBullish) { // AddIfNotExists( iBar, structure.bullishRejectionBars // ); } else { // AddIfNotExists( iBar, structure.bearishRejectionBars // ); } } } } } /** * Search Conditions for Find SL Candidates ... * * @param candidates: Double Array ... * @param entry: Double ... * @param structure: X121SMCStrategyConditions instance ... * @param type: ENUM_X_POSITION_TYPES member ... * * @return ( int ) */ int DetectSLCandidates( double &candidates[], double entry, X121SMCStrategyConditions &conditions, ENUM_X_POSITION_TYPES type // ) { // int result = 0; // if (type == X_POSITION_TYPE_NONE || type == X_POSITION_TYPE_ALL) { return result; } // Clean(candidates); // XOHCL candidateBars[]; if (type == X_POSITION_TYPE_LONG) { // // Search Bullish Momentum, Rejection Bars and Swing Lows ... // // Swing Lows ... Copy( conditions.swingLows, candidateBars, false // ); // // Bullish Momentum Bars ... Copy( conditions.bullishMomentumBars, candidateBars, false // ); // // Bullish Rejection Bars ... Copy( conditions.bullishRejectionBars, candidateBars, false // ); // int count = ArraySize(candidateBars); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XOHCL iBar = candidateBars[i]; // if (iBar.low < entry) { // Add( iBar.low, candidates // ); } } } } else if (type == X_POSITION_TYPE_SHORT) { // // Search Bearish Momentum, Rejection Bars and Swing Highs ... // // Swing Highs ... Copy( conditions.swingHighs, candidateBars, false // ); // // Bearish Momentum Bars ... Copy( conditions.bearishMomentumBars, candidateBars, false // ); // // Bearish Rejection Bars ... Copy( conditions.bearishRejectionBars, candidateBars, false // ); // int count = ArraySize(candidateBars); if (IsValidSize(count)) { // for (int i = 0; i < count; i++) { // XOHCL iBar = candidateBars[i]; // if (iBar.high > entry) { // Add( iBar.low, candidates // ); } } } } // Clean(candidateBars); result = ArraySize(candidates); // return result; } /** * Combine a Conditions by Conditions List and Remove it if Exists ... * * @param conditions: X121SMCStrategyConditions instance ... */ void RemoveConditionsIfExists(X121SMCStrategyConditions &conditions) { // int count = ArraySize(mConditions); if (!IsValidSize(count)) { return; } // bool hasValidSupply = HasValidSupply(conditions); bool hasValidDemand = HasValidDemand(conditions); if (!hasValidSupply && !hasValidDemand) { return; } // int idx = -1; for (int i = 0; i < count; i++) { // X121SMCStrategyConditions iConditions = mConditions[i]; // bool isSupplySame = hasValidSupply && HasValidSupply(iConditions) && conditions.supplyZone.from == iConditions.supplyZone.from && conditions.supplyZone.upper == iConditions.supplyZone.upper && conditions.supplyZone.lower == iConditions.supplyZone.lower; bool isDemandSame = hasValidDemand && HasValidDemand(iConditions) && conditions.demandZone.from == iConditions.demandZone.from && conditions.demandZone.upper == iConditions.demandZone.upper && conditions.demandZone.lower == iConditions.demandZone.lower; // if (isSupplySame || isDemandSame) { // idx = i; break; } } // if (IsValidIndex(idx)) { // ArrayRemove( mConditions, idx, 1 // ); } } /** * Clear All Conditions ... */ void ClearConditions() { Clean(mConditions); } // /** * Notified Signal Event Handler(s) ... * * @param signal: XSignal instance ... * @param conditions: XStrategyConditions instance ... */ void NotifyOnSignalEventHandlers( XSignal &signal, X121SMCStrategyConditions &conditions // ) { // if (!signal.IsValid() || !conditions.IsValid()) { return; } // int count = ArraySize(mSignalEventHandlers); if (!IsValidSize(count)) { return; } // for (int i = 0; i < count; i++) { // mSignalEventHandlers[i]( signal, conditions // ); } } // // Draw Functions ... /** * Clear all Drawn Objects ... */ void ClearDraws() { mDrawnObjects.Clear(); } /** * Remove Specified Drawn Object ... * * @param name: Object name ... */ void RemoveObject(string name) { // if (!IsValid(name)) { return; } // int count = mDrawnObjects.Total(); if (!IsValidSize(count)) { return; } // int idx = -1; for (int i = 0; i < count; i++) { // string iName = ((CChartObject *)mDrawnObjects.At(i)).Name(); string iObjName = NULL; if (!IsValid(iName)) { iObjName = ((XCBaseObject *)mDrawnObjects.At(i)).ObjName(); } // if ((IsValid(iName) && iName == name) || (IsValid(iObjName) && iObjName == name)) { // idx = i; break; } } // if (IsValidIndex(idx)) { mDrawnObjects.Delete(idx); } } /** * Draw Specific Condition ... * * @param conditions: X121SMCStrategyConditions instance ... */ void DrawConditions(X121SMCStrategyConditions &conditions) { // if (!conditions.IsValid()) { return; } // datetime time = TimeCurrent(); bool hasValidDemand = HasValidDemand(conditions); bool hasValidSupply = HasValidSupply(conditions); if (!hasValidDemand && !hasValidSupply) { return; } // // Demand Zone ... if (hasValidDemand) { // // Demand ... XCDemandZoneObject *iObj; bool isCreated = mPOIDrawer.CreateDemandZone( conditions.demandZone, iObj // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } // // Order Blocks ... int obsCount = ArraySize(conditions.bullishOrderBlocks); if (IsValidSize(obsCount)) { // for (int i = 0; i < obsCount; i++) { // XZone iZone = conditions.bullishOrderBlocks[i]; // XCBullishOrderBlockObject *iObj; bool isCreated = mPOIDrawer.CreateBullishOrderBlock( iZone, iObj // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } } } // // Fair Value Gaps ... int fvgsCount = ArraySize(conditions.bullishFVGs); if (IsValidSize(fvgsCount)) { // for (int i = 0; i < fvgsCount; i++) { // XZone iZone = conditions.bullishFVGs[i]; // XCBullishFVGObject *iObj; bool isCreated = mPOIDrawer.CreateBullishFVG( iZone, iObj // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } } } // // Supports ... int supportsCount = ArraySize(conditions.supports); if (IsValidSize(supportsCount)) { // for (int i = 0; i < supportsCount; i++) { // XOHCL iBar = conditions.supports[i]; // XCSupportZoneObject *iObj; bool isCreated = mPOIDrawer.CreateSupportZone( iBar, iObj, time // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } } } // // Swings ... int swingsCount = ArraySize(conditions.swingLows); if (IsValidSize(swingsCount)) { // for (int i = 0; i < swingsCount; i++) { // XOHCL iBar = conditions.swingLows[i]; // XCSwingLowObject *iObj; bool isCreated = mPOIDrawer.CreateSwingLow( iBar, iObj // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } } } // // Momentum Bars ... int momentumBarsCount = ArraySize(conditions.bullishMomentumBars); if (IsValidSize(momentumBarsCount)) { // for (int i = 0; i < momentumBarsCount; i++) { // XOHCL iBar = conditions.bullishMomentumBars[i]; // XCBullishMomentumBarObject *iObj; bool isCreated = mPOIDrawer.CreateBullishMomentumBar( iBar, iObj // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } } } // // Rejection Bars ... int rejectionBarsCount = ArraySize(conditions.bullishRejectionBars); if (IsValidSize(rejectionBarsCount)) { // for (int i = 0; i < rejectionBarsCount; i++) { // XOHCL iBar = conditions.bullishRejectionBars[i]; // XCBullishRejectionBarObject *iObj; bool isCreated = mPOIDrawer.CreateBullishRejectionBar( iBar, iObj // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } } } } // // Supply Zone ... if (hasValidSupply) { // // Supply ... XCSupplyZoneObject *iObj; bool isCreated = mPOIDrawer.CreateSupplyZone( conditions.supplyZone, iObj // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } // // Order Blocks ... int obsCount = ArraySize(conditions.bearishOrderBlocks); if (IsValidSize(obsCount)) { // for (int i = 0; i < obsCount; i++) { // XZone iZone = conditions.bearishOrderBlocks[i]; // XCBearishOrderBlockObject *iObj; bool isCreated = mPOIDrawer.CreateBearishOrderBlock( iZone, iObj // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } } } // // Fair Value Gaps ... int fvgsCount = ArraySize(conditions.bearishFVGs); if (IsValidSize(fvgsCount)) { // for (int i = 0; i < fvgsCount; i++) { // XZone iZone = conditions.bearishFVGs[i]; // XCBearishFVGObject *iObj; bool isCreated = mPOIDrawer.CreateBearishFVG( iZone, iObj // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } } } // // Resistances ... int resistancesCount = ArraySize(conditions.resistances); if (IsValidSize(resistancesCount)) { // for (int i = 0; i < resistancesCount; i++) { // XOHCL iBar = conditions.resistances[i]; // XCResistanceZoneObject *iObj; bool isCreated = mPOIDrawer.CreateResistanceZone( iBar, iObj, time // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } } } // // Swings ... int swingsCount = ArraySize(conditions.swingHighs); if (IsValidSize(swingsCount)) { // for (int i = 0; i < swingsCount; i++) { // XOHCL iBar = conditions.swingHighs[i]; // XCSwingHighObject *iObj; bool isCreated = mPOIDrawer.CreateSwingHigh( iBar, iObj // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } } } // // Momentum Bars ... int momentumBarsCount = ArraySize(conditions.bearishMomentumBars); if (IsValidSize(momentumBarsCount)) { // for (int i = 0; i < momentumBarsCount; i++) { // XOHCL iBar = conditions.bearishMomentumBars[i]; // XCBearishMomentumBarObject *iObj; bool isCreated = mPOIDrawer.CreateBearishMomentumBar( iBar, iObj // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } } } // // Rejection Bars ... int rejectionBarsCount = ArraySize(conditions.bearishRejectionBars); if (IsValidSize(rejectionBarsCount)) { // for (int i = 0; i < rejectionBarsCount; i++) { // XOHCL iBar = conditions.bearishRejectionBars[i]; // XCBearishRejectionBarObject *iObj; bool isCreated = mPOIDrawer.CreateBearishRejectionBar( iBar, iObj // ); if (isCreated) { // // RemoveObject(iObj.ObjName()); mDrawnObjects.Add(iObj); } } } } } /** * Draw Specified Market Struture ... * * @param structure: X121SMCMarketStructure instance ... */ void DrawMarketStructure( X121SMCMarketStructure &structure, ENUM_X_POSITION_TYPES type = X_POSITION_TYPE_ALL // ) { // datetime cTime = TimeCurrent(); // bool canAll = type == X_POSITION_TYPE_ALL; bool canLong = type == X_POSITION_TYPE_LONG; bool canShort = type == X_POSITION_TYPE_SHORT; // // Supply Zones ... int supplysCount = ArraySize(structure.supplyZones); if ((canAll || canLong) && IsValidSize(supplysCount)) { // for (int i = 0; i < supplysCount; i++) { // XZone iZone = structure.supplyZones[i]; // XCSupplyZoneObject *iObj; bool isCreated = mPOIDrawer.CreateSupplyZone( iZone, iObj // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Demand Zones ... int demandsCount = ArraySize(structure.demandZones); if ((canAll || canShort) && IsValidSize(demandsCount)) { // for (int i = 0; i < demandsCount; i++) { // XZone iZone = structure.demandZones[i]; // XCDemandZoneObject *iObj; bool isCreated = mPOIDrawer.CreateDemandZone( iZone, iObj // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Order Blocks ... // // Bullish OBs ... int bullishOBsCount = ArraySize(structure.bullishOrderBlocks); if ((canAll || canShort) && IsValidSize(bullishOBsCount)) { // for (int i = 0; i < bullishOBsCount; i++) { // XZone iZone = structure.bullishOrderBlocks[i]; // XCBullishOrderBlockObject *iObj; bool isCreated = mPOIDrawer.CreateBullishOrderBlock( iZone, iObj // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Bearish OBs ... int bearishOBsCount = ArraySize(structure.bearishOrderBlocks); if ((canAll || canLong) && IsValidSize(bearishOBsCount)) { // for (int i = 0; i < bearishOBsCount; i++) { // XZone iZone = structure.bearishOrderBlocks[i]; // XCBearishOrderBlockObject *iObj; bool isCreated = mPOIDrawer.CreateBearishOrderBlock( iZone, iObj // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Fair Value Gaps ... // // Bullish FVGs ... int bullishFVGsCount = ArraySize(structure.bullishFVGs); if ((canAll || canShort) && IsValidSize(bullishFVGsCount)) { // for (int i = 0; i < bullishFVGsCount; i++) { // XZone iZone = structure.bullishFVGs[i]; // XCBullishFVGObject *iObj; bool isCreated = mPOIDrawer.CreateBullishFVG( iZone, iObj // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Bearish FVGs ... int bearishFVGsCount = ArraySize(structure.bearishFVGs); if ((canAll || canLong) && IsValidSize(bearishFVGsCount)) { // for (int i = 0; i < bearishFVGsCount; i++) { // XZone iZone = structure.bearishFVGs[i]; // XCBearishFVGObject *iObj; bool isCreated = mPOIDrawer.CreateBearishFVG( iZone, iObj // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Swing Highs ... int swingHighsCount = ArraySize(structure.swingHighs); if ((canAll || canLong) && IsValidSize(swingHighsCount)) { // for (int i = 0; i < swingHighsCount; i++) { // XOHCL iBar = structure.swingHighs[i]; // XCSwingHighObject *iObj; bool isCreated = mPOIDrawer.CreateSwingHigh( iBar, iObj // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Swing Lows ... int swingLowsCount = ArraySize(structure.swingLows); if ((canAll || canShort) && IsValidSize(swingLowsCount)) { // for (int i = 0; i < swingLowsCount; i++) { // XOHCL iBar = structure.swingLows[i]; // XCSwingLowObject *iObj; bool isCreated = mPOIDrawer.CreateSwingLow( iBar, iObj // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Support Zones ... int supportsCount = ArraySize(structure.supports); if ((canAll || canShort) && IsValidSize(supportsCount)) { // for (int i = 0; i < supportsCount; i++) { // XOHCL iBar = structure.supports[i]; // XCSupportZoneObject *iObj; bool isCreated = mPOIDrawer.CreateSupportZone( iBar, iObj, cTime // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Resistance Zones ... int resistancesCount = ArraySize(structure.resistances); if ((canAll || canLong) && IsValidSize(resistancesCount)) { // for (int i = 0; i < resistancesCount; i++) { // XOHCL iBar = structure.resistances[i]; // XCResistanceZoneObject *iObj; bool isCreated = mPOIDrawer.CreateResistanceZone( iBar, iObj, cTime // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Momentum Bars ... // // Bullish Momentum Bars ... int momentumBarCount = ArraySize(structure.bullishMomentumBars); if ((canAll || canShort) && IsValidSize(momentumBarCount)) { // for (int i = 0; i < momentumBarCount; i++) { // XOHCL iBar = structure.bullishMomentumBars[i]; // XCBullishMomentumBarObject *iObj; bool isCreated = mPOIDrawer.CreateBullishMomentumBar( iBar, iObj // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Bearish Momentum Bars ... momentumBarCount = ArraySize(structure.bearishMomentumBars); if ((canAll || canLong) && IsValidSize(momentumBarCount)) { // for (int i = 0; i < momentumBarCount; i++) { // XOHCL iBar = structure.bearishMomentumBars[i]; // XCBearishMomentumBarObject *iObj; bool isCreated = mPOIDrawer.CreateBearishMomentumBar( iBar, iObj // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Rejection Bars ... // // Bullish Rejection Bars ... int rejectionBarCount = ArraySize(structure.bullishRejectionBars); if ((canAll || canShort) && IsValidSize(rejectionBarCount)) { // for (int i = 0; i < rejectionBarCount; i++) { // XOHCL iBar = structure.bullishRejectionBars[i]; // XCBullishRejectionBarObject *iObj; bool isCreated = mPOIDrawer.CreateBullishRejectionBar( iBar, iObj // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } // // Bearish Rejection Bars ... rejectionBarCount = ArraySize(structure.bearishRejectionBars); if ((canAll || canLong) && IsValidSize(rejectionBarCount)) { // for (int i = 0; i < rejectionBarCount; i++) { // XOHCL iBar = structure.bearishRejectionBars[i]; // XCBearishRejectionBarObject *iObj; bool isCreated = mPOIDrawer.CreateBearishRejectionBar( iBar, iObj // ); if (isCreated) { // mDrawnObjects.Add(iObj); } } } } /** * Draw Specified Signal ... * * @param signal: XSignal instance ... * @param conditions: X121SMCStrategyConditions instance ... */ void DrawSignal( XSignal &signal, X121SMCStrategyConditions &conditions // ) { // if (!signal.IsValid() || !conditions.IsValid()) { // return; } // // DrawConditions(conditions); // string name = signal.GetTag(); RemoveObject(name); // XCSignalObject *iObj; iObj = new XCSignalObject(); // bool isCreated = iObj.Create( ChartID(), name, 0, signal // ); if (!isCreated) { return; } // iObj.TPWidth(1); iObj.TPColor(clrGreen); iObj.TPWidth(STYLE_DOT); // iObj.SLWidth(1); iObj.SLColor(clrRed); iObj.SLWidth(STYLE_DOT); // iObj.EntryWidth(1); iObj.EntryColor(clrYellow); iObj.EntryWidth(STYLE_DOT); // mDrawnObjects.Add(iObj); // bool drawConditions = true; if (drawConditions) { DrawConditions(conditions); } } // // Private ... private: // // Props ... // string mSymbol; // Trading Symbol ... ENUM_TIMEFRAMES mPeriod; // Trading TimeFrame ... bool mForceDisabled; // Force Disabled ... bool mAllowLong; // Allow Long Signals bool mAllowShort; // Allow Short Signals double mR2R; // Risk/Rewar Ratio ... double mVolume; // Static Volume Per Trades ... double mMaxAllowedSpread; // Max Allowed Spread ... // long mChartID; // Chart ID ... int mSubWindow; // Sub Window ID ... XCPOIDrawer *mPOIDrawer; // POI Drawer Class ... // XTick mTicks[]; // Hold Ticks Data ... MqlTick mLastTick; // Last Issued Tick ... // XBarTracker mBarTracker; // Strategy Time Tracker ... // // Point Of Interests ... XCPOI *m1DPOI; XCPOI *m4HPOI; XCPOI *m15MPOI; XCPOI *m5MPOI; XCPOI *m1MPOI; // // Collect all Drawn Objects ... CArrayObj mDrawnObjects; // XOHCL mSwingHigh; CChartObjectHLine *mSwingHighObject; // XOHCL mSwingLow; CChartObjectHLine *mSwingLowObject; // X121SMCStrategyConditions mConditions[]; // // On X121 Signal Recieved Event Handler(s) ... TOnX121SMCSignal mSignalEventHandlers[]; // // Actions ... /** * Install all Helpers and Prepare all Configurations for required Indicators ... */ void Init() { // mForceDisabled = false; // R2R(1.5); Volume(0.01); // ChartIdentification(0); SubWindowIdentification(0); // // Configure POI Drawer if Required ... mPOIDrawer = new XCPOIDrawer(); mPOIDrawer.ChartIdentification(0); mPOIDrawer.SubWindowIdentification(0); // mPOIDrawer.DemandZoneFill(false); mPOIDrawer.SupplyZoneFill(false); mPOIDrawer.BullishFVGFill(false); mPOIDrawer.BearishFVGFill(false); mPOIDrawer.SupportZoneFill(false); mPOIDrawer.ResistanceZoneFill(false); mPOIDrawer.BullishOrderBlockFill(false); mPOIDrawer.BearishOrderBlockFill(false); // string symbol = Symbol(); ENUM_TIMEFRAMES period = Period(); // // Initialize Bar Tracker ... mBarTracker.Init( symbol, period // ); // // Initialize POIs ... // // 1D Period ... // POI Detector ... m1DPOI = new XCPOI( symbol, PERIOD_D1 // ); // m1DPOI.DisableDrawPOIs(); m1DPOI.SupplyZonePeriod(PERIOD_W1); m1DPOI.DemandZonePeriod(PERIOD_W1); m1DPOI.SubWindowIdentification(0); m1DPOI.ChartIdentification(ChartID()); // m1DPOI.Init(); // // 4H Period ... // POI Detector ... m4HPOI = new XCPOI( symbol, PERIOD_H4 // ); // m4HPOI.DisableDrawPOIs(); m4HPOI.SupplyZonePeriod(PERIOD_D1); m4HPOI.DemandZonePeriod(PERIOD_D1); m4HPOI.SubWindowIdentification(0); m4HPOI.ChartIdentification(ChartID()); // m4HPOI.Init(); // // 15M Period ... // POI Detector ... m15MPOI = new XCPOI( symbol, PERIOD_M15 // ); // m15MPOI.DisableDrawPOIs(); m15MPOI.MaxNumberOfRequiredPOIs(2); m15MPOI.SupplyZonePeriod(PERIOD_H4); m15MPOI.DemandZonePeriod(PERIOD_H4); m15MPOI.SubWindowIdentification(0); m15MPOI.ChartIdentification(ChartID()); // m15MPOI.Init(); // // 5M Period ... // POI Detector ... m5MPOI = new XCPOI( symbol, PERIOD_M5 // ); // m5MPOI.DisableDrawPOIs(); m5MPOI.MaxNumberOfRequiredPOIs(2); m5MPOI.SupplyZonePeriod(PERIOD_M15); m5MPOI.DemandZonePeriod(PERIOD_M15); m5MPOI.SubWindowIdentification(0); m5MPOI.ChartIdentification(ChartID()); // m5MPOI.Init(); // // 1M Period ... // POI Detector ... m1MPOI = new XCPOI( symbol, PERIOD_M1 // ); // m1MPOI.DisableDrawPOIs(); m1MPOI.SupplyZonePeriod(PERIOD_M5); m1MPOI.DemandZonePeriod(PERIOD_M5); m1MPOI.SubWindowIdentification(0); m1MPOI.ChartIdentification(ChartID()); // m1MPOI.Init(); // } /** * De Initialize all Tools ... */ void DeInit() { // delete m1DPOI; delete m4HPOI; delete m5MPOI; delete m1MPOI; delete m15MPOI; // delete mPOIDrawer; // ClearDraws(); } /** * Reste Bar Tracker ... */ void ResetBarTracker() { mBarTracker.Clean(); } /** * Cleanup Ticks Size ... */ void CleanupTicks() { // int maxRequiredTicks = 50; int ticksCount = ArraySize(mTicks); if (!IsValidSize(ticksCount) || ticksCount <= maxRequiredTicks) { return; } // int removeCount = ticksCount - maxRequiredTicks; if (!IsValidSize(removeCount)) { return; } // ArrayRemove( mTicks, 0, removeCount // ); } /** * Add new Tick Data to Collection ... */ void SaveTickData() { // XTick tick; bool isInited = tick.Init(mSymbol); if (!isInited) { return; } // AddRef( tick, mTicks // ); } /** * Calculate Ticks Param for Looping through Last n items ... * * @param start: Integer Reference to Start ... * @param end: Integer Reference to End ... * @param numOfLastTicks: Integer Max Number of Required N Last Ticks ... */ void CalculateTicksParams( int &start, int &end, int numOfLastTicks = 5 // ) { // start = -1; end = -1; // int count = ArraySize(mTicks); // start = count - numOfLastTicks; if (start < 0) { start = 0; } // end = start + numOfLastTicks; if (end > count) { end = count; } } // }; //