/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class // ------------------------------------------------- // Name: XCXCATBEASignaller ... // Description: Class for XCATBEA Signaller ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://saherelm.ir" #property version "1.00" #property description "SaherElm XCXCATBEASignaller Class" #property strict // // Imports ... #include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" #include "../../Classes/x-saherelm.x-guard.class.mq5" #include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5" #include "../Classes/xcatbea.x-poi.detector.class.mq5" #include "../Classes/xcatbea.x-poi.drawer.class.mq5" #include "../Libraries/xcatbea.lib.mq5" #include "../Libraries/xcatbea.signaller.lib.mq5" #include "../Libraries/xcatbea.x-poi.extensions.lib.mq5" // // Definitions ... // // Configure Signalelrs ... struct XCATBEASignallingConfigs { // // Signalling Method ... bool allowSignallingBasedOnConditions; // Signalling Based on Market Conditions bool allowSignallingBasedOnTriggerBlocks; // Signalling Based on Trigger Blocks bool allowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs // // Others ... bool applyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss bool secondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss // // Market Conditions Signall Providers ... bool allowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Starter Signals bool allowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Starter Signals bool allowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Starter Signals bool allowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Starter Signals bool allowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Starter Signals bool allowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Starter Signals // // Constructor ... XCATBEASignallingConfigs() { Clean(); } // // Tools ... // // Cleaning Up ... void Clean() { // allowSignallingBasedOnConditions = false; allowSignallingBasedOnTriggerBlocks = false; allowSignallingBasedOnTriggerBlocksInsideOther = false; // secondsTriggersSLUsingFirstTriggerBlock = false; applyValidateAndFilterOnSelectInsideOthers = false; // allowSignallingConditions1 = false; allowSignallingConditions2 = false; allowSignallingConditions3 = false; allowSignallingConditions4 = false; allowSignallingConditions5 = false; allowSignallingConditions6 = false; } }; // struct XCATBEASignallerInputs { // // Pros ... string symbol; string provider; bool allowDraws; bool allowGuards; int riskToRewardRatio; ENUM_TIMEFRAMES period; double slATRMultiplier; X121XCatbInputs catbInputs; XTriggerBlockFilters filters; XTriggerBlockValidationRules validations; XCATBEASignallingConfigs signallerConfigs; // // Constructor(s) ... XCATBEASignallerInputs() { Clean(); } // // Tools ... // // Cleanup ... void Clean() { // symbol = NULL; period = NULL; provider = NULL; filters.Clean(); catbInputs.Clean(); allowDraws = false; validations.Clean(); allowGuards = false; slATRMultiplier = 0; riskToRewardRatio = 0; signallerConfigs.Clean(); // ZeroMemory(this); } // // Validate ... bool IsValid() { // bool result = false; // result = IsValid(symbol) && IsValid(period) && IsValid(provider) && catbInputs.IsValid() && riskToRewardRatio > 0; // return result; } // }; // // Implementations ... class XCXCATBEASignaller : XCBase { // // Public ... public: // // Props ... // bool allowSignallingBasedOnConditions; // Signalling Based on Market Conditions bool allowSignallingBasedOnTriggerBlocks; // Signalling Based on Trigger Blocks bool allowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs // bool secondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss bool applyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss // // Market Conditions Signall Providers ... bool allowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Starter Signals bool allowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Starter Signals bool allowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Starter Signals bool allowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Starter Signals bool allowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Starter Signals bool allowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Starter Signals // bool allowDraws; // Allow Draws or not ... bool allowGuards; // Allow Guards or not ... int riskToRewardRatio; // Signals R2R ... double slATRMultiplier; // SL ATR Multiplier ... // XBarTracker barTraker; // Bar Tracker ... XCX121XCatbHelper *helper; // XCATB Helper Class instance ... XCBarAnalyser *barAnalyser; // Bar Analyser ... XCXCATBEAPOIDrawer *drawer; // POI Drawer ... XTriggerBlockFilters filters; // Trigger Block Filters ... XCXCATBEAPOIDetector *detector; // POI Detector ... XTriggerBlockValidationRules validations; // Trigger Block Validations ... // XBoxZone cPeak; // Current Peak ... XBoxZone cVale; // Current Vale ... XBoxZone unavailableZones[]; // Un Available Zones ... XTriggerBlock cTriggerBlock; // Currently Selected Trigger Block ... XTriggerBlock triggerBlocks[]; // Founded Trigger Blocks ... bool waitsUntilPeakInvalidate; // Waits Until Peak Invalidate ... bool waitsUntilValeInvalidate; // Waits Until Vale Invalidate ... XTriggerBlock cInsideTriggerBlock; // a TriggerBlock which Currently Selected Trigger Block is Inside it ... // XCATBEAStrategyConditions mConditions; XCATBEAStrategyConditions mConditionsCollection[]; // // Constructor ... XCXCATBEASignaller(XCATBEASignallerInputs &inputs) { Init(inputs); } // // Deconstructor ... ~XCXCATBEASignaller() { DeInit(); } // // Properties ... // string GetSymbol() { return symbol; } // string GetProvider() { return provider; } // ENUM_TIMEFRAMES GetPeriod() { return period; } // double GetR2R() { return riskToRewardRatio; } // // Tick Analyser ... /** * Process Tick ... */ void ProcessTick( XPosition &positions[], XGuard &guards[], XCATBEAStrategyConditions &conditions, bool isActiveSession = true // ) { // Clean(guards); conditions.Clean(); // XOHCL bar; int count = 0; bool has = false; int barIndex = 0; cTriggerBlock.Clean(); cInsideTriggerBlock.Clean(); // // Check Guards ... has = DetectGuards( guards, positions, barIndex // ); // // Check Triggered Conditions ... has = HasChild(mConditionsCollection); if (has) { // int selectedIDX = -1; count = ArraySize(mConditionsCollection); for (int i = 0; i < count; i++) { // // Select indexed Conditions ... XCATBEAStrategyConditions iConditions = mConditionsCollection[i]; // // Check Conditions Triggered ... has = DetectSignalTrigger( iConditions, barIndex // ); if (has) { // selectedIDX = i; conditions = iConditions; iConditions.Clean(); // break; } // // When Setup Invalidated // Signaller Clean Conditions ... if (!has && !iConditions.IsValid()) { // selectedIDX = i; break; } // // Cleanup Resources ... iConditions.Clean(); } // // Check Can Trigger ... has = IsValidIndex(selectedIDX) && conditions.IsValid() && conditions.IsSetuped() && conditions.CanTrigger(); if (has) { // ArrayRemove( mConditionsCollection, selectedIDX, 1 // ); } else { // // Check Selected Index for Invalid Conditions ... if (IsValidIndex(selectedIDX)) { // // Remove Invalidated Conditions ... ArrayRemove( mConditionsCollection, selectedIDX, 1 // ); } // // Cleanup Resource ... conditions.Clean(); } } // // Check Bar Processing ... if (!barTraker.CanProcessBar()) { return; } // // Initialize Bar ... bar.Init( symbol, period, barIndex // ); // // Detect POI(s) ... detector.Detect(barIndex); // // Validate POI(s) ... detector.Validate( unavailableZones, barIndex // ); // // Check Helper Last Changes ... helper.Check(barIndex); // // Draw POI(s) ... if (allowDraws) { // drawer.Draw(bar.time); } // // Detect Trigger Blocks and Collect them ... XTriggerBlock iTriggerBlock; X121XCatbConditions iConditions; XTriggerBlockFilters iFilters; XTriggerBlockValidationRules iValidations; if (applyValidateAndFilterOnSelectInsideOthers) { // // Validations ... iValidations.forceHasSwing = validations.forceHasSwing; iValidations.forceOBBarType = validations.forceOBBarType; iValidations.forceFVGBarType = validations.forceFVGBarType; iValidations.maxAllowedRange = validations.maxAllowedRange; iValidations.minAllowedRange = validations.minAllowedRange; iValidations.minRequiredOBBar = validations.minRequiredOBBar; iValidations.liquidityLoopback = validations.liquidityLoopback; iValidations.forceHasFLiquidity = validations.forceHasFLiquidity; iValidations.forceHasRLiquidity = validations.forceHasRLiquidity; iValidations.validateGapSequence = validations.validateGapSequence; iValidations.minAllowedBlockLength = validations.minAllowedBlockLength; iValidations.validateBlockEdgeBreakout = validations.validateBlockEdgeBreakout; // // Clone Filters and Validations ... iFilters.bosLoopback = filters.bosLoopback; iFilters.filterBasedOnKI = filters.filterBasedOnKI; iFilters.filterBasedOnPV = filters.filterBasedOnPV; iFilters.filterBasedOnSar = filters.filterBasedOnSar; iFilters.filterBasedOnRSI = filters.filterBasedOnRSI; iFilters.filterBasedOnADX = filters.filterBasedOnADX; iFilters.filterBasedOnATR = filters.filterBasedOnATR; iFilters.forceSarSwitched = filters.forceSarSwitched; iFilters.forceHasTrendDir = filters.forceHasTrendDir; iFilters.filterBasedOnTrend = filters.filterBasedOnTrend; iFilters.filterBasedOnDelta = filters.filterBasedOnDelta; iFilters.forceSarOnBothSide = filters.forceSarOnBothSide; iFilters.forceHasTrendPlace = filters.forceHasTrendPlace; iFilters.forceSarHasBreakout = filters.forceSarHasBreakout; iFilters.filterBasedOnVolume = filters.filterBasedOnVolume; iFilters.forceHasRSITrending = filters.forceHasRSITrending; iFilters.forceHasRSIVPattern = filters.forceHasRSIVPattern; iFilters.forceHasRSICrossing = filters.forceHasRSICrossing; iFilters.forceHasADXTrending = filters.forceHasADXTrending; iFilters.forceHasADXCrossing = filters.forceHasADXCrossing; iFilters.forceHasATRTrending = filters.forceHasATRTrending; iFilters.forceHasATRBreakout = filters.forceHasATRBreakout; iFilters.forceHasTrendChange = filters.forceHasTrendChange; iFilters.forceHasTrendTrending = filters.forceHasTrendTrending; iFilters.forceHasTrendRejection = filters.forceHasTrendRejection; iFilters.filterBasedOnSignalBar = filters.filterBasedOnSignalBar; iFilters.forceHasTrendLineInside = filters.forceHasTrendLineInside; iFilters.forceSarHasReversalSide = filters.forceSarHasReversalSide; iFilters.filterBasedOnHKSignalBar = filters.filterBasedOnHKSignalBar; iFilters.forceHasTrendDirOnBothSide = filters.forceHasTrendDirOnBothSide; } has = DetectTriggerBlock( helper, barAnalyser, iTriggerBlock, iConditions, iValidations, iFilters, barIndex, 10 // Loopback ... ); if (has) { // // Add Trigger Block to Collection if not Exists ... AddIfNotExists( iTriggerBlock, triggerBlocks // ); } iFilters.Clean(); iConditions.Clean(); iValidations.Clean(); iTriggerBlock.Clean(); // // Draw Trigger Blocks ... if (allowDraws) { // // Handle To Updating ... // datetime cTime = TimeCurrent(); // DrawTriggerBlocks(cTime); } // // Here we Check Active Session ... // and Prevent Moving forward if there is not // Session actives ... // for improvement Calculation Speeds ... if (isActiveSession) { // // Check Signal Setups ... has = DetectSignalSetup(barIndex); if (has) { // barTraker.Waits(); // AddConditionsIfNotExists(); // mConditions.Clean(); } } // // Cleanup Resources ... bar.Clean(); } // // Signalling Tools ... /** * Detect Setup Conditions based on Signalling ... * * @param maxAllowedSLDistanceInPoint: int, Max Allowed SL Distance in Points (if Bigger thn Zero Provided) ... * * @return ( bool ) */ bool DetectSignalSetup(int barIndex = 0) { // bool result = false; // // Normalize Args ... barIndex = NormalizeInt(barIndex, 0); // // Update All Required Buffers ... helper.Update(barIndex); // bool has = false; datetime cTime = TimeCurrent(); // // cPeak and cVale ... // these Helpes Us to Detect Price Levels ... // // Draw Peak and Vale if Exists ... // // Peak ... if (cPeak.IsValid()) { // cPeak.to = cTime; // drawer.DrawBox(cPeak); } // // Vale ... if (cVale.IsValid()) { // cVale.to = cTime; // drawer.DrawBox(cVale); } // // Try to Validate cPeak an cVale if Exists ... XOHCL zBar; XOHCL cBar; bool isInited = zBar.Init( symbol, period, barIndex // ); isInited = zBar.GetPreviousBar(cBar); isInited = helper.GetConditions( mConditions.conditions, barIndex, 10 // ); if (isInited) { // // Validate cPeak and cVale if Exists ... // // cPeak ... if (cPeak.IsValid()) { // isInited = cBar.high < cPeak.lower; if (!isInited) { // cPeak.Clean(); cVale.Clean(); // waitsUntilPeakInvalidate = false; waitsUntilValeInvalidate = false; } } // // cVale ... if (cVale.IsValid()) { // isInited = cBar.low > cVale.upper; if (!isInited) { // cPeak.Clean(); cVale.Clean(); // waitsUntilPeakInvalidate = false; waitsUntilValeInvalidate = false; } } // // Try To Detect Peak and Vale based on cBar ... // // Selecting Peak ... if (!cPeak.IsValid()) { // XBoxZone tmpPeaks[]; detector.FillPeakPivots(tmpPeaks); while (HasChild(tmpPeaks)) { // // Find Index ... int idx = GetLowest(tmpPeaks); if (!IsValidIndex(idx)) { break; } // // Select ... cPeak = tmpPeaks[idx]; ArrayRemove( tmpPeaks, idx, 1 // ); // // Validate Peak ... bool isValid = cPeak.lower > cBar.high; if (isValid) { break; } // cPeak.Clean(); } Clean(tmpPeaks); } // // Selecting Vale ... if (!cVale.IsValid()) { // XBoxZone tmpVales[]; detector.FillValePivots(tmpVales); while (HasChild(tmpVales)) { // // Find Index ... int idx = GetHighest(tmpVales); if (!IsValidIndex(idx)) { break; } // // Select ... cVale = tmpVales[idx]; ArrayRemove( tmpVales, idx, 1 // ); // // Validate Vale ... bool isValid = cVale.upper < cBar.low; if (isValid) { break; } // cVale.Clean(); } Clean(tmpVales); } } // // Detect Signal Setup Based on Market Conditions ... if (!result && allowSignallingBasedOnConditions) { // // Detect Signalling Zone ... result = DetectSignalZone( helper, drawer, detector, barAnalyser, mConditions.conditions, mConditions.pivotZone, allowSignallingConditions1, allowSignallingConditions2, allowSignallingConditions3, allowSignallingConditions4, allowSignallingConditions5, allowSignallingConditions6, barIndex, 10 // Loopback ... ); if (result) { // // Use Signal Zone ... UseBox(mConditions.pivotZone); // // Prepare Condition ... // // Prepare Signal ... mConditions.dir = mConditions .pivotZone .dir; mConditions.symbol = symbol; mConditions.period = period; mConditions.provider = provider; mConditions.reward = riskToRewardRatio; mConditions.time = mConditions.conditions.bars[0].time; mConditions.setupTime = mConditions.conditions.bars[0].time; // // Prepare Target ... double targets[]; for (int i = 1; i <= riskToRewardRatio; i++) { // Add( (double)i, targets // ); } // // Calculate SL Additions ... double iATR = 0; if (barIndex > 0 && barIndex < ArraySize(helper.atrBuffer)) { iATR = helper.atrBuffer[barIndex]; } double slAdditional = slATRMultiplier * iATR; // // Preparing Signal ... XSignal iSignal; result = ToSignal( mConditions.pivotZone, iSignal, targets, slAdditional // ); if (result) { // mConditions.sl = iSignal.sl; mConditions.tp = iSignal.tp; mConditions.pivot = iSignal.sl; mConditions.entry = iSignal.entry; mConditions.point = iSignal.entry; mConditions.type = ToPositionType(iSignal.type); // // Draw Trigger Block ... if (allowDraws) { // XCBoxObject *iObj; has = drawer .drawer .DrawBox( mConditions.pivotZone, iObj // ); if (has) { mObjects.Add(iObj); } ZeroMemory(iObj); } } iSignal.Clean(); } } // // Detect Signal Setup Based on Trigger Block Detection ... if (!result && allowSignallingBasedOnTriggerBlocks) { // // Detect Trigger Block ... result = DetectTriggerBlock( helper, barAnalyser, mConditions.triggerBlock, mConditions.conditions, validations, filters, barIndex, 10 // Loopback ... ); if (result) { // // Use Trigger Block ... UseTriggerBlock(mConditions.triggerBlock); // // Prepare Condition ... // // Prepare Signal ... mConditions.dir = mConditions .triggerBlock .GetDirection(); mConditions.symbol = symbol; mConditions.period = period; mConditions.provider = provider; mConditions.reward = riskToRewardRatio; mConditions.time = mConditions.conditions.bars[0].time; mConditions.setupTime = mConditions.conditions.bars[0].time; // // Prepare Target ... double targets[]; for (int i = 1; i <= riskToRewardRatio; i++) { // Add( (double)i, targets // ); } // // Calculate SL Additions ... double iATR = 0; if (barIndex > 0 && barIndex < ArraySize(helper.atrBuffer)) { iATR = helper.atrBuffer[barIndex]; } double slAdditional = slATRMultiplier * iATR; // // Preparing Signal ... result = ToSignal( mConditions.triggerBlock.trigger, mConditions.triggerBlock.signal, targets, slAdditional // ); if (result) { // mConditions.triggerBlock.signal.provider = provider; mConditions.sl = mConditions.triggerBlock.signal.sl; mConditions.tp = mConditions.triggerBlock.signal.tp; mConditions.pivot = mConditions.triggerBlock.signal.sl; mConditions.entry = mConditions.triggerBlock.signal.entry; mConditions.point = mConditions.triggerBlock.signal.entry; mConditions.type = ToPositionType(mConditions.triggerBlock.signal.type); // // Draw Trigger Block ... if (allowDraws) { // DrawTriggerBlock( mConditions.triggerBlock, drawer.drawer, mObjects, NULL, // To ... false // Draw Signal ... ); } } } } // // Detect Signal Setup Based On Trigger Blocks Second Entry ... if (!result && allowSignallingBasedOnTriggerBlocksInsideOther) { // // Trigger Block Detection ... result = HasChild(triggerBlocks) && ArraySize(triggerBlocks) > 1 && !waitsUntilPeakInvalidate && !waitsUntilValeInvalidate; if (result) { // // Check Newest Trigger Block ... bool isTriggerBlockSelected = false; XTriggerBlock tmpTBs[]; Copy( triggerBlocks, tmpTBs // ); while (HasChild(tmpTBs)) { // int idx = GetYoungest(tmpTBs); if (!IsValidIndex(idx)) { break; } // // Select ... // and Remove From Collection ... cTriggerBlock = tmpTBs[idx]; ArrayRemove( tmpTBs, idx, 1 // ); // // Validate ... isTriggerBlockSelected = // // Check Bar is Valid ... cBar.IsValid() && // // Currently Happens ... (cTriggerBlock.trigger.to == zBar.time || cTriggerBlock.trigger.to == cBar.time) && // // Price Validations ... (cTriggerBlock.IsBullish() ? cBar.low > cTriggerBlock.trigger.lower : cBar.high < cTriggerBlock.trigger.upper) // ; if (isTriggerBlockSelected) { break; } // // Clean Trigger Block ... cTriggerBlock.Clean(); } Clean(tmpTBs); // // Check Trigger Block Selection ... result = isTriggerBlockSelected; if (result) { // bool isBullish = cTriggerBlock.IsBullish(); bool isBearish = cTriggerBlock.IsBearish(); // // Now we have to Check Newest Trigger Block Place ... int insideTBIDX = DetectInsideTriggerBlock( cTriggerBlock, cInsideTriggerBlock, triggerBlocks // ); // // Check InsideTB is Exists and Valid ... result = cInsideTriggerBlock.IsValid() && IsValidIndex(insideTBIDX); if (result) { // // Now we Have to Detect Peak and Vales ... result = cPeak.IsValid() && cVale.IsValid(); // // If Exists Before Validate them based Trigger Blocks ... if (result) { // // Validate cPeak and cVale based on // cTriggerBlock and cInsideTriggerBlock ... result = // // Peak ... cPeak.lower > cTriggerBlock.trigger.upper && cPeak.lower > cInsideTriggerBlock.trigger.upper && // // Vale ... cVale.upper < cTriggerBlock.trigger.lower && cVale.upper < cInsideTriggerBlock.trigger.lower && // // Bar Validation ... cBar.IsValid() && cBar.low > cVale.upper && cBar.high < cPeak.lower // ; if (!result) { // cPeak.Clean(); cVale.Clean(); // waitsUntilPeakInvalidate = false; waitsUntilValeInvalidate = false; } } // // if not Exists, or Clean them on Invalidating Process, try to Find Corrects ... if (!result) { // // Selecting Peak ... XBoxZone tmpPeaks[]; detector.FillPeakPivots(tmpPeaks); while (HasChild(tmpPeaks)) { // // Find Index ... int idx = GetLowest(tmpPeaks); if (!IsValidIndex(idx)) { break; } // // Select ... cPeak = tmpPeaks[idx]; ArrayRemove( tmpPeaks, idx, 1 // ); // // Validate Peak ... bool isValid = // // Bar Validation ... cBar.IsValid() && cBar.high < cPeak.lower && // // Peak Validation ... cPeak.lower > cTriggerBlock.trigger.upper && cPeak.lower > cInsideTriggerBlock.trigger.upper; if (isValid) { break; } // cPeak.Clean(); } Clean(tmpPeaks); // // Selecting Vale ... XBoxZone tmpVales[]; detector.FillValePivots(tmpVales); while (HasChild(tmpVales)) { // // Find Index ... int idx = GetHighest(tmpVales); if (!IsValidIndex(idx)) { break; } // // Select ... cVale = tmpVales[idx]; ArrayRemove( tmpVales, idx, 1 // ); // // Validate Vale ... bool isValid = // // Bar Validation ... cBar.IsValid() && cBar.low > cVale.upper && // // Vale Validation ... cVale.upper < cTriggerBlock.trigger.lower && cVale.upper < cInsideTriggerBlock.trigger.lower; if (isValid) { break; } // cVale.Clean(); } Clean(tmpVales); // // Summarizing Result ... result = cPeak.IsValid() && cVale.IsValid(); } // // Check Peak and Vale Exists ... if (result) { // // Remove Peak from Detector Collections ... // and Make it unavailable ... UseBox(cPeak); // // Remove Vale from Detector Collections ... // and Make it unavailable ... UseBox(cVale); // // Remove Selected Trigger Block ... // and Make it unavailable ... RemoveTriggerBlock( cTriggerBlock, triggerBlocks // ); UseTriggerBlock(cTriggerBlock); // // Remove Selected Inside Trigger Block ... // and Make it unavailable ... RemoveTriggerBlock( cInsideTriggerBlock, triggerBlocks // ); UseTriggerBlock(cInsideTriggerBlock); // // Update Peak and Vales To ... cPeak.to = cTime; cVale.to = cTime; // // Draw Peak and Vales ... if (allowDraws) { // drawer.DrawBox(cPeak); drawer.DrawBox(cVale); } // // Validate Peaks and Vales ... bool isPeakPassed = false; bool isValePassed = false; cInsideTriggerBlock.trigger.to = cTime; int toIDX = cInsideTriggerBlock.ToIndex(); int fromIDX = cInsideTriggerBlock.FromIndex(); for (int i = toIDX; i < fromIDX; i++) { // // Reading Values ... // double iPeak = helper.GetPeak(i); double iPPeak = helper.GetPeak(i + 1); // double iVale = helper.GetVale(i); double iPVale = helper.GetVale(i + 1); // bool isPeakOverLast = iPeak > iPPeak; bool isPeakUnderLast = iPeak < iPPeak; // bool isValeOverLast = iVale > iPVale; bool isValeUnderLast = iVale < iPVale; // if (!isPeakPassed) { // isPeakPassed = isBullish ? isPeakOverLast : isPeakUnderLast; } // if (!isValePassed) { // isValePassed = isBullish ? isValeUnderLast : isPeakOverLast; } // result = isPeakPassed && isValePassed; if (result) { break; } } if (result) { // // Draw Trigger Blocks if Allowed ... if (allowDraws) { // // Draw Blocks ... // // mObjects.Clear(); // // Detected Block ... DrawTriggerBlock( cTriggerBlock, drawer.drawer, mObjects, cTime, false // Draw Signal ... ); // // Inside Block ... DrawTriggerBlock( cInsideTriggerBlock, drawer.drawer, mObjects, cTime, false // Draw Signal ... ); } // if (isBullish) { waitsUntilPeakInvalidate = true; } else if (isBearish) { waitsUntilValeInvalidate = true; } // mConditions.triggerBlock = cTriggerBlock; } } } } } // // Preparing Conditions based on result ... if (result) { // bool isBullish = mConditions.triggerBlock.IsBullish(); // // Preparing mConditions ... mConditions.dir = mConditions .triggerBlock .GetDirection(); mConditions.symbol = symbol; mConditions.period = period; mConditions.provider = provider; mConditions.reward = riskToRewardRatio; mConditions.time = mConditions.conditions.bars[0].time; mConditions.setupTime = mConditions.conditions.bars[0].time; // // Prepare Target ... double targets[]; for (int i = 1; i <= riskToRewardRatio; i++) { // Add( (double)i, targets // ); } // // Calculate SL Additions ... double iATR = 0; if (barIndex > 0 && barIndex < ArraySize(helper.atrBuffer)) { iATR = helper.atrBuffer[barIndex]; } double slAdditional = slATRMultiplier * iATR; // // Preparing Signal ... result = ToSignal( mConditions.triggerBlock.trigger, mConditions.triggerBlock.signal, targets, slAdditional // ); XSignal insideTBSignal; result = result && ToSignal( cInsideTriggerBlock.trigger, insideTBSignal, targets, slAdditional // ); if (result) { // // Try to Use SL Based on Inside Trigger Block ... double sl = 0; double tp = 0; if (secondsTriggersSLUsingFirstTriggerBlock) { // sl = insideTBSignal.sl; tp = insideTBSignal.tp; // // Add Target for usuall Signal TP ... XTarget iTarget; iTarget.doRF = true; iTarget.target = mConditions.triggerBlock.signal.tp; // AddRef( iTarget, mConditions.targets); // iTarget.Clean(); } else { // sl = mConditions.triggerBlock.signal.sl; tp = mConditions.triggerBlock.signal.tp; } // mConditions.sl = sl; mConditions.tp = tp; mConditions.pivot = sl; mConditions.triggerBlock.signal.provider = provider; mConditions.entry = mConditions.triggerBlock.signal.entry; mConditions.point = mConditions.triggerBlock.signal.entry; mConditions.type = ToPositionType(mConditions.triggerBlock.signal.type); // // Draw Trigger Block ... if (allowDraws) { // DrawTriggerBlock( mConditions.triggerBlock, drawer.drawer, mObjects, NULL, // To ... false // Draw Signal ... ); } } } } // // Check a Signal Setup Exists or not ... result = mConditions.IsValid() && mConditions.IsSetuped(); // // Cleanup Resource ... zBar.Clean(); cBar.Clean(); cTriggerBlock.Clean(); cInsideTriggerBlock.Clean(); // return result; } /** * Detect Trigger Conditions for Specified Signal ... * * @param conditions: XCATBEAStrategyConditions instance Reference, Specified Signal Conditions ... * @param maxAllowedSetupAge: specified Setup Age for Expiration (if bigger than Zero) ... * * @return ( bool ) */ bool DetectSignalTrigger( XCATBEAStrategyConditions &conditions, int barIndex = 0 // ) { // bool result = false; // // Normalize Args ... barIndex = NormalizeInt(barIndex, 0); // // Validate Setup ... result = conditions.IsSetuped(); if (!result) { return result; } // bool has = false; datetime cTime = TimeCurrent(); bool isBullish = IsBullish(conditions.dir); bool isBearish = IsBearish(conditions.dir); // bool isBasedOnPivotZone = conditions.pivotZone.IsValid(); bool isBasedOnTriggerBlock = conditions.triggerBlock.IsValid(); // // Reading Current Market Conditions ... X121XCatbConditions cConditions; result = result && helper.GetConditions( cConditions, barIndex, 10 // ); // // Validate Direction of Setuped Conditions ... result = result && (isBullish || isBearish); // // Detecting Trigger Bar ... // ENUM_X_DIRECTION triggerDir; bool isTriggerBar = barAnalyser .IsValidForTrigger( bar, triggerDir, false, // Allow Cond 1 ... false, // Allow Cond 2 ... false, // Allow Cond 3 ... false, // Allow Cond 4 ... false, // Allow Cond 5 ... false, // Allow Cond 6 ... true // Allow Cond 7 ... // ); bool isBullishTriggerBar = isTriggerBar && IsBullish(triggerDir); bool isBearishTriggerBar = isTriggerBar && IsBearish(triggerDir); // // Do Triggering Senario based on Trigger Block ... if (result && isBasedOnTriggerBlock) { // // Checking Score ... double bullishScore = 0; double bearishScore = 0; conditions .conditions .GenerateScore( bullishScore, bearishScore // ); bool isScorePassed = isBullish ? bullishScore > bearishScore : bearishScore > bullishScore; // // Complete Conditions Here ... if (isScorePassed) { conditions.triggerTime = TimeCurrent(); } } // // Do Triggering based on Market Conditions PivotZones ... if (result && isBasedOnPivotZone) { // // Update Box To ... conditions.pivotZone.to = cTime; // // Draw Box ... XCBoxObject *iObj; has = drawer .drawer .DrawBox( conditions.pivotZone, iObj // ); if (has) { mObjects.Add(iObj); } // // Check atleast 3 Bars Close Outside of applied Edge ... // Check Current Bar is a Trigger Bar ... // TODO: Complete this ... // } // // Do Other Validation Senarios ... // result = conditions.IsValid() && conditions.IsSetuped() && conditions.CanTrigger(); // // Check Setup Age or Setup Validations here ... if (!result) { // // Validate Trigger Block Based Setups ... // // Validate Pivot Zone Based Setups ... // // Validate Setup Age ... } // // Cleanup Resources ... // return result; } /** * Detect Guards bsed on Signalling Class ... * * @param guards: XCAEAGuard instance Collection, Holds Provided Guards ... * @param positions: XPosition instance Collection, Provides Signalling Based Positions for Apply Guards on them ... * @param provider: X121SMCStrategySignalProviderData instance Reference, Specified Data for Cycles ... * * @return ( bool ) */ bool DetectGuards( XGuard &guards[], const XPosition &positions[], int barIndex = 0 // ) { // bool result = false; // // Normalize Args ... Clean(guards); barIndex = NormalizeInt(barIndex, 0); // result = allowGuards && HasChild(positions); if (!result) { return result; } // // TODO: Implement this ... // result = HasChild(guards); // // Cleanup Resources ... // if (!result) { Clean(guards); } // return result; } // // Protected ... protected: // /** * Initialize ... */ void Init(XCATBEASignallerInputs &inputs) { // maxAllowedCollection = 100; // allowSignallingBasedOnConditions = inputs.signallerConfigs.allowSignallingBasedOnConditions; allowSignallingBasedOnTriggerBlocks = inputs.signallerConfigs.allowSignallingBasedOnTriggerBlocks; allowSignallingBasedOnTriggerBlocksInsideOther = inputs.signallerConfigs.allowSignallingBasedOnTriggerBlocksInsideOther; // secondsTriggersSLUsingFirstTriggerBlock = inputs.signallerConfigs.secondsTriggersSLUsingFirstTriggerBlock; applyValidateAndFilterOnSelectInsideOthers = inputs.signallerConfigs.applyValidateAndFilterOnSelectInsideOthers; // allowSignallingConditions1 = inputs.signallerConfigs.allowSignallingConditions1; allowSignallingConditions2 = inputs.signallerConfigs.allowSignallingConditions2; allowSignallingConditions3 = inputs.signallerConfigs.allowSignallingConditions3; allowSignallingConditions4 = inputs.signallerConfigs.allowSignallingConditions4; allowSignallingConditions5 = inputs.signallerConfigs.allowSignallingConditions5; allowSignallingConditions6 = inputs.signallerConfigs.allowSignallingConditions6; // bool has = inputs.IsValid(); if (!has) { return; } // symbol = inputs.symbol; period = inputs.period; filters = inputs.filters; provider = inputs.provider; allowDraws = inputs.allowDraws; allowGuards = inputs.allowGuards; validations = inputs.validations; slATRMultiplier = inputs.slATRMultiplier; riskToRewardRatio = inputs.riskToRewardRatio; // mObjects = new CArrayObj(); // // Initialize Bar Tracker ... has = barTraker.Init( symbol, period // ); if (!has) { return; } // // Initialize Bar Analyser ... barAnalyser = new XCBarAnalyser(); // // initialize Helper ... helper = new XCX121XCatbHelper(); has = helper.Init( symbol, period, inputs.catbInputs // ); if (!has) { return; } // mConditions.Clean(); Clean(mConditionsCollection); // InitPOI(); } /** * DeInitialize ... */ void DeInit() { // mObjects.Clear(); delete mObjects; ZeroMemory(mObjects); // drawer.Clear(); delete drawer; ZeroMemory(drawer); // detector.CleanPivots(); delete detector; ZeroMemory(detector); // delete helper; ZeroMemory(helper); // delete barAnalyser; ZeroMemory(barAnalyser); // barTraker.Clean(); } /** * Add Conditions to Conditions Collection if not Exists ... * * @param maxAllowed: int, Specified Max Allowed Holding Conditions ... * * @return ( int ) */ int AddConditionsIfNotExists( int maxAllowed = 50 // ) { // int result = 0; // // Normalize Args ... maxAllowed = maxAllowedCollection; // bool isSetuped = IsValid(mConditions.setupTime) && HasDirection(mConditions.dir); if (!isSetuped) { return result; } // int count = ArraySize(mConditionsCollection); if (IsValidSize(count)) { // // Copy Original Items ... XCATBEAStrategyConditions tmpItems[]; Copy( mConditionsCollection, tmpItems // ); // // Prese Item Data ... bool isBullish = IsBullish(mConditions.dir); // for (int i = 0; i < count; i++) { // XCATBEAStrategyConditions iItem = tmpItems[i]; // bool canRemove = mConditions.dir == iItem.dir && mConditions.pivot == iItem.pivot; if (canRemove) { // ArrayRemove( mConditionsCollection, i, 1 // ); } } // Clean(tmpItems); } // AddRef( mConditions, mConditionsCollection // ); // // Remove Olds ... CleanupArray( mConditionsCollection, maxAllowed // ); // result = ArraySize(mConditionsCollection); // return result; } /** * Add TriggerBlock if not Exists * inside a Collection ... */ int AddIfNotExists( XTriggerBlock &tb, XTriggerBlock &tbs[], int maxAllowed = 50 // ) { // int result = 0; // // Normalize Args ... maxAllowed = maxAllowedCollection; // // First Validate ... if (!tb.IsValid()) { return result; } // // Check Exists ... // and prevent moving forward if exists ... int idx = -1; bool isExists = FindTriggerBlockIndex( idx, tb, tbs // ); result = !isExists; if (!result) { return result; } // // Add if not Exists ... AddRef( tb, tbs // ); // // Cleanup ... CleanupArray( tbs, maxAllowed // ); // result = ArraySize(tbs); // return result; } /** * Use Specified Box and make it Unavailable ... * * @param box: XBoxZone instance reference ... */ void UseBox(XBoxZone &box) { // // Validate Box ... bool has = box.IsValid(); if (!has) { return; } // // Check Box Added Before or not ... int idx = -1; has = FindBoxIndex( idx, box, unavailableZones // ); if (has) { return; } // // Adding Box Reference to // Unavailable Zones ... AddRef( box, unavailableZones // ); // // Cleanup Array ... CleanupArray( unavailableZones, maxAllowedCollection // ); // } /** * Use Specified Trigger Block and Make it Un Available ... * * @param tb: XTriggerBlock instance reference, Specified Used Trigger Block ... */ void UseTriggerBlock(XTriggerBlock &tb) { // bool has = tb.IsValid(); if (!has) { return; } // // Trigger Box ... has = tb.trigger.IsValid(); if (has) { UseBox(tb.trigger); } // // Order Block Box ... has = tb.ob.IsValid(); if (has) { UseBox(tb.ob); } // // Fair Value Gap ... has = tb.fvg.IsValid(); if (has) { UseBox(tb.fvg); } // // Following Liquidity ... has = tb.fLiquidity.IsValid(); if (has) { UseBox(tb.fLiquidity); } // // Reversal Liquidity ... has = tb.rLiquidity.IsValid(); if (has) { UseBox(tb.rLiquidity); } } /** * Draw Exists Trigger Blocks ... */ void DrawTriggerBlocks(datetime to = NULL) { // // Check Has Child of trigger Blocks ... bool has = HasChild(triggerBlocks); if (!has) { return; } // // Loop through Blocks ... int count = ArraySize(triggerBlocks); for (int i = 0; i < count; i++) { // // Draw Indexed Trigger Block ... DrawTriggerBlock( triggerBlocks[i], drawer.drawer, mObjects, to, false // ); } } // // Private ... private: // // Props ... string symbol; string provider; CArrayObj *mObjects; ENUM_TIMEFRAMES period; int maxAllowedCollection; // Max Allowed Collection Items ... // // Initialize and Configure POI Detector and Drawer ... void InitPOI() { // // Initialize POI Detector ... bool has = helper != NULL; if (has) { // detector = new XCXCATBEAPOIDetector(helper); // // Configure ... // detector.detectPeakPivots = true; detector.detectValePivots = true; // detector.detectMTBullishPivots = true; detector.detectMTBearishPivots = true; // detector.detectOBBullishPivots = true; detector.detectOBBearishPivots = true; } // // Initialize POI Drawer ... has = detector != NULL; if (has) { // drawer = new XCXCATBEAPOIDrawer(detector); // // Configure ... drawer.drawPeakPivots = true; drawer.drawValePivots = true; // XCATBPivotStyle iStyle; // // Styling Peak Pivot ... iStyle.width = 1; iStyle.clr = clrMagenta; iStyle.style = STYLE_SOLID; // drawer.peakPivotStyle = iStyle; // // Styling Vale Pivot ... iStyle.width = 1; iStyle.clr = clrAqua; iStyle.style = STYLE_SOLID; // drawer.valePivotStyle = iStyle; // // Cleanup Resources ... // iStyle.Clean(); } } // }; //