diff --git a/Experts/xcatb.test.ea.mq5 b/Experts/xcatb.test.ea.mq5 index 7ff5a07e..2620d9f1 100644 --- a/Experts/xcatb.test.ea.mq5 +++ b/Experts/xcatb.test.ea.mq5 @@ -80,30 +80,30 @@ input double eaSLAtrMultiplier = 0; // ATR Multiplier for SL // // Volume ... input group "Volume"; -input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_EQUITY; // Volume Applying Type -input double eaStaticVoluem = 0.0; // Static Volume -input double eaDynamicVolumeStepBalance = 0.0; // Step of Balance for Increase Volume -input double eaDynamicVolumeStepVolume = X_MIN_VOLUME; // Step of Volume Increasing -input double eaConstantRiskBalance = 0.0; // Constant Risk Balance per Trade -input double eaConstantPercent = 0.5; // Constant Percent of Balance Per Trade -input double eaConstantBalance = 0.0; // Constant Balance for Calculations +input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_CONSTANT; // Volume Applying Type +input double eaStaticVoluem = 0.0; // Static Volume +input double eaDynamicVolumeStepBalance = 0.0; // Step of Balance for Increase Volume +input double eaDynamicVolumeStepVolume = X_MIN_VOLUME; // Step of Volume Increasing +input double eaConstantRiskBalance = 5.0; // Constant Risk Balance per Trade +input double eaConstantPercent = 0.0; // Constant Percent of Balance Per Trade +input double eaConstantBalance = 1000.0; // Constant Balance for Calculations // // Management ... // eaSessions => (SYDNEY_02:00_14:00),(NY_19:00_23:00) input group "Management"; -input bool eaAllowTrade = true; // Allow Trade on Signals -input bool eaAllowLongs = true; // Allow Long Trades -input bool eaAllowShorts = true; // Allow Short Trades -input string eaSessions = ""; // Active Sessions +input bool eaAllowTrade = true; // Allow Trade on Signals +input bool eaAllowLongs = true; // Allow Long Trades +input bool eaAllowShorts = true; // Allow Short Trades +input string eaSessions = ""; // Active Sessions input ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD eaRestrictionsPeriod = XCATBEA_TRADE_RESTRICATION_NONE; // Restrictions Period -input int eaMaxAllowedTPs = 0; // Max Allowed TP(s) in Restrictions Period -input int eaMaxAllowedSLs = 0; // Max Allowed SL(s) in Restrictions Period -input int eaMaxAllowedTrades = 0; // Max Allowed Trades in Restrictions Period -input int eaMaxAllowedPositions = 5; // Max Allowed Same Time Trades -input double eaMaxAllowedSpread = 25; // Max Allowed Spread For Trade -input double eaMaxAllowedDrawdownFactor = 0.3; // Max Allowed DrawDown for Trade -input string eaCloseAllOpenTradesAt = ""; // Close All Open Trades per Day At Specified Time +input int eaMaxAllowedTPs = 0; // Max Allowed TP(s) in Restrictions Period +input int eaMaxAllowedSLs = 0; // Max Allowed SL(s) in Restrictions Period +input int eaMaxAllowedTrades = 0; // Max Allowed Trades in Restrictions Period +input int eaMaxAllowedPositions = 5; // Max Allowed Same Time Trades +input double eaMaxAllowedSpread = 25; // Max Allowed Spread For Trade +input double eaMaxAllowedDrawdownFactor = 0.3; // Max Allowed DrawDown for Trade +input string eaCloseAllOpenTradesAt = ""; // Close All Open Trades per Day At Specified Time // // Alert ... @@ -351,7 +351,7 @@ void OnTick() // // Prepare Target ... double targets[]; - for (int i = 1; i <= eaInputs.signalR2R; i++) + for (int i = 1; i <= eaSignalR2R; i++) { // Add( @@ -368,7 +368,7 @@ void OnTick() { iATR = eaHelper.atrBuffer[barIndex]; } - double slAdditional = eaInputs.slAtrMultiplier * iATR; + double slAdditional = eaSLAtrMultiplier * iATR; // // Preparing Signal ... @@ -729,15 +729,9 @@ void InitRequirements() eaInputs.showPV = true; eaInputs.showSar = true; eaInputs.showTrend = true; - eaInputs.drawSignals = false; eaInputs.showATRBand = false; eaInputs.showPVGolden = true; - // - // Signal ... - eaInputs.signalR2R = eaSignalR2R; - eaInputs.slAtrMultiplier = eaSLAtrMultiplier; - // // Set Validators ... eaInputs.forceHasSwing = eaForceHasSwing; diff --git a/Helpers/x-saherelm.x121.xcatb.helper.mq5 b/Helpers/x-saherelm.x121.xcatb.helper.mq5 index 6bfab823..7b186198 100644 --- a/Helpers/x-saherelm.x121.xcatb.helper.mq5 +++ b/Helpers/x-saherelm.x121.xcatb.helper.mq5 @@ -98,10 +98,10 @@ struct X121XCatbInputs // // Signal ... - int signalR2R; // Risk Reward Ratio - bool drawSignals; // Draw Signal - bool drawTriggerBlock; // Draw Trigger Block - double slAtrMultiplier; // ATR Multiplier for SL + // int signalR2R; // Risk Reward Ratio + // bool drawSignals; // Draw Signal + // bool drawTriggerBlock; // Draw Trigger Block + // double slAtrMultiplier; // ATR Multiplier for SL // // Validating ... @@ -179,13 +179,6 @@ struct X121XCatbInputs hcPeriod = NULL; // Hind Period appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle - // - // Signal ... - signalR2R = 0; // Risk Reward Ratio - drawSignals = false; // Draw Signal - drawTriggerBlock = false; // Draw Trigger Block - slAtrMultiplier = 0; // ATR Multiplier for SL - // // Validating ... forceHasSwing = false; // Force Blocks to Have Swing @@ -256,13 +249,6 @@ struct X121XCatbInputs hcPeriod = NULL; // Hind Period appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle - // - // Signal ... - signalR2R = 4; // Risk Reward Ratio - drawSignals = false; // Draw Signal - drawTriggerBlock = false; // Draw Trigger Block - slAtrMultiplier = 1.0; // ATR Multiplier for SL - // // Validating ... forceHasSwing = false; // Force Blocks to Have Swing @@ -320,16 +306,16 @@ struct X121XCatbInputs { // showPV = false; - showPVGolden = false; showSar = false; showTrend = false; showATRBand = false; + showPVGolden = false; showSignalBars = false; showHKSignalBars = false; // - drawSignals = false; - drawTriggerBlock = false; + // drawSignals = false; + // drawTriggerBlock = false; } // @@ -1582,11 +1568,6 @@ class XCX121XCatbHelper : public XCBaseHelper mInputs.hcMethod, mInputs.hcPeriod, mInputs.appliedCycle, - "", // Signal ... - mInputs.signalR2R, - mInputs.drawSignals, - mInputs.drawTriggerBlock, - mInputs.slAtrMultiplier, "", // Validating ... mInputs.forceHasSwing, mInputs.forceOBBarType, diff --git a/Indicators/x-saherelm.x121.xcatb.mq5 b/Indicators/x-saherelm.x121.xcatb.mq5 index 29432e7e..b47d658a 100644 --- a/Indicators/x-saherelm.x121.xcatb.mq5 +++ b/Indicators/x-saherelm.x121.xcatb.mq5 @@ -79,14 +79,6 @@ input ENUM_TIMEFRAMES hcPeriod = NULL; // Hind Period // this Cycle Used for All Calculations ... input ENUM_X_MARKET_CYCLES appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle -// -// Signal ... -input group "Signal"; -input int signalR2R = 4; // Risk Reward Ratio -input bool drawSignals = true; // Draw Signal -input bool drawTriggerBlock = true; // Draw Trigger Block -input double slAtrMultiplier = 1.0; // ATR Multiplier for SL - // // Validating ... input group "Validating"; diff --git a/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 b/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 index 6275f2b9..f9c37bf1 100644 --- a/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 +++ b/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 @@ -21,9 +21,9 @@ // // Imports ... -#include "../Libraries/xcatbea.lib.mq5" #include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" #include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/xcatbea.lib.mq5" // // Definiions ... @@ -145,12 +145,13 @@ struct XTriggerBlockValidationRules bool forceOBBarType; // Force Order Block to Has InDirectional Bars ... int minRequiredOBBar; // Min Required OB Bar ... bool forceFVGBarType; // Force Fair Value Gaps Bars Type ... + int liquidityLoopback; // Liquidity Detection Loopback ... double maxAllowedRange; // Max Allowed Order Block Range ... double minAllowedRange; // Min Allowed Order Block Range ... bool forceHasFLiquidity; // Force Order Block To Has Reversal Liquidity ... bool forceHasRLiquidity; // Force Order Block to Has Following Liquidity ... - int liquidityLoopback; // Liquidity Detection Loopback ... bool validateGapSequence; // Validate Fair Value Gaps Bar Sequences ... + int minAllowedBlockLength; // Min Allowed Block Length ... bool validateBlockEdgeBreakout; // Validate Order Block Edge Breakeout ... // @@ -175,6 +176,7 @@ struct XTriggerBlockValidationRules forceHasSwing = false; forceOBBarType = false; forceFVGBarType = false; + minAllowedBlockLength = 0; forceHasFLiquidity = false; forceHasRLiquidity = false; validateGapSequence = false; @@ -203,7 +205,11 @@ struct XTriggerBlockFilters bool filterBasedOnHKSignalBar; // Filter Based On HK Signal Bar ... // - int bosLoopback; // PV Based Filtering BOS Lookup ... + int bosLoopback; // PV Based Filtering BOS Lookup ... + bool forceSarSwitched; // SAR Switched on Sides for Filtering ... + bool forceSarOnBothSide; // SAR Check on Both Sides for Filtering ... + bool forceSarHasBreakout; // SAR Must Has Reversal Direction in Trigger Block ... + bool forceSarHasReversalSide; // SAR Must Has Reversal Direction in Trigger Block ... // // Constructor(s) ... @@ -233,6 +239,10 @@ struct XTriggerBlockFilters // bosLoopback = 0; + forceSarSwitched = false; + forceSarOnBothSide = false; + forceSarHasBreakout = false; + forceSarHasReversalSide = false; // ZeroMemory(this); @@ -409,6 +419,7 @@ bool DetectTriggerBlock1( // validations.liquidityLoopback = 144; // validations.forceHasFLiquidity = true; // validations.forceHasRLiquidity = true; + // validations.minAllowedBlockLength = 7; // // Apply Validations ... @@ -434,8 +445,13 @@ bool DetectTriggerBlock1( // // TODO: Remove this ... - filters.bosLoopback = 30; - filters.filterBasedOnPV = true; + // filters.bosLoopback = 0; + // filters.filterBasedOnPV = true; + // filters.filterBasedOnSar = false; + // filters.forceSarSwitched = false; + // filters.forceSarOnBothSide = true; + // filters.forceSarHasBreakout = true; + // filters.forceSarHasReversalSide = false; // // Apply Filtering ... @@ -937,6 +953,75 @@ bool ValidateTriggerBlock( iBar.Clean(); } + // + // Validating Block Length Based on Direction ... + if (result && + validations.minAllowedBlockLength) + { + // + count = 0; + fromIDX = triggerBlock.FromIndex(); + int sIDX = fromIDX; + has = true; + while (has) + { + // + // Initialize iBar ... + has = iBar.Init( + conditions.symbol, + conditions.period, + sIDX // + ); + + // + has = + has && + (isBullish + ? iBar.low > triggerBlock.trigger.lower + : iBar.high < triggerBlock.trigger.upper); + + // + if (!has) + { + break; + } + + // + sIDX++; + count++; + iBar.Clean(); + } + + // + result = + iBar.IsValid() && + count >= validations.minAllowedBlockLength; + if (result) + { + // + // Update Trigger Block ... + bool usaMinAllowedForBlockLength = false; + if (usaMinAllowedForBlockLength) + { + fromIDX = fromIDX + validations.minAllowedBlockLength; + } + else + { + fromIDX = sIDX - 1; + } + + // + triggerBlock.trigger.from = GetBarTime( + conditions.symbol, + conditions.period, + fromIDX // + ); + } + + // + iBar.Clean(); + } + // if (!result) { @@ -1057,12 +1142,20 @@ bool FilterTriggerBlock( // For PV Filtering ... // - // Detect Bos ... + // Detect BOS ... + + // + // When Loopback for BOS has Specified Value ... + // we Lookup for BOS on Specific Period ... if (filters.bosLoopback > 0) { // has = true; + int fBOSIDX = -1; + int rBOSIDX = -1; bool isBOS = false; + bool isFBOS = false; + bool isRBOS = false; bool isPeakOverLast = false; bool isValeUnderLast = false; toIDX = triggerBlock.ob.ToIndex(); @@ -1088,6 +1181,26 @@ bool FilterTriggerBlock( iVale > 0 && iVale < iPVale; + // + isFBOS = + isBullish + ? isPeakOverLast + : isValeUnderLast; + if (isFBOS) + { + fBOSIDX = sIDX; + } + + // + isRBOS = + isBullish + ? isValeUnderLast + : isPeakOverLast; + if (isRBOS) + { + rBOSIDX = sIDX; + } + // isBOS = (isBullish && @@ -1106,7 +1219,210 @@ bool FilterTriggerBlock( } // - result = isBOS; + isFBOS = IsValidIndex(fBOSIDX); + isRBOS = IsValidIndex(rBOSIDX); + + // + result = isBOS && + isFBOS && + !isRBOS; + } + + // + // When Loopback for BOS has not Specified Value ... + // we Lookup for BOS on GAP End Bar ... + if (filters.bosLoopback <= 0) + { + // + toIDX = triggerBlock.ToIndex(); + + // + // Initialize iBar ... + result = iBar.Init( + conditions.symbol, + conditions.period, + toIDX // + ); + result = + result && + (isBullish ? iBar.high > helper.GetPeak(toIDX + 1) + : iBar.low < helper.GetVale(toIDX + 1)); + } + } + + // + // Filter Based on SAR ... + if (result && + filters.filterBasedOnSar) + { + // + toIDX = triggerBlock.ToIndex(); + fromIDX = triggerBlock.FromIndex(); + + // + double iSarState = helper.GetSarState(toIDX); + double iPSarState = helper.GetSarState(toIDX + 1); + + // + double iFSarState = helper.GetSarState(fromIDX); + double iPFSarState = helper.GetSarState(fromIDX + 1); + + // + bool isSarBullish = + iSarState > 0; + + // + bool isSarBearish = + iSarState < 0; + + // + bool isFSarBullish = + iFSarState > 0; + + // + bool isFSarBearish = + iFSarState < 0; + + // + bool isSarSwitchedToBullish = + iSarState > 0 && + iPSarState <= 0; + + // + bool isSarSwitchedToBearish = + iSarState < 0 && + iPSarState >= 0; + + // + bool isFSarSwitchedToBullish = + iFSarState > 0 && + iPFSarState <= 0; + + // + bool isFSarSwitchedToBearish = + iFSarState < 0 && + iPFSarState >= 0; + + // + // Creating Filters ... + + // + bool isToFilterPassed = + !filters.forceSarSwitched + ? (isBullish + ? isSarBullish + : isSarBearish) + : (isBullish + ? isSarSwitchedToBullish + : isSarSwitchedToBearish); + + // + bool isFromFilterPassed = + !filters.forceSarSwitched + ? (isBullish + ? isFSarBullish + : isFSarBearish) + : (isBullish + ? isFSarSwitchedToBullish + : isFSarSwitchedToBearish); + + // + result = + !filters.forceSarOnBothSide + ? isToFilterPassed + : isToFilterPassed && + isFromFilterPassed; + + // + // Check Sar Has Reversal Direction inside Trigger Block ... + if (result && + filters.forceSarHasReversalSide) + { + // + toIDX = triggerBlock.ToIndex(); + fromIDX = triggerBlock.FromIndex(); + for (int i = toIDX; i < fromIDX; i++) + { + // + double iSarState = helper.GetSarState(i); + + // + has = + isBullish + ? iSarState > 0 + : iSarState < 0; + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Force Sar Breakouts ... + // in this Senario Sar must in following Direction and + // there is not any Switches ... + // but must breakout Bar the last in Reversal Direction + // of Sar ... + if (result && + filters.forceSarHasBreakout) + { + // + bool isSarBullishStart = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBullish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBearish.IsValid() && + // + // Current Close is Over previous Sar ... + conditions.bars[cIDX].close > helper.lastSarBearish.after && + // + // Before Close is not Over previous Sar ... + conditions.bars[pIDX].close <= helper.lastSarBearish.after + // + ) + // + ; + + // + bool isSarBearishStart = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBearish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBullish.IsValid() && + // + // Current Close is Under previous ... + conditions.bars[cIDX].close < helper.lastSarBullish.after && + // + // Before Close is not Under previous ... + conditions.bars[pIDX].close >= helper.lastSarBullish.after + // + ) + // + ; + + // + result = + isBullish + ? isSarBullishStart + : isSarBearishStart; + } + + // + if (result) + { + Print("Filter Passed ..."); } }