mirror of
https://github.com/rithsila/MT5-EA-Sniper-Strategy.git
synced 2026-08-06 23:47:54 +00:00
Complete implementation of all 4 immediate recommendations
✅ COMPLETED FIXES: 1. Calibrate liquidity sweep detection parameters - Reduced MinSweepDistance from 5.0 to 3.0 pips - Reduced SwingLookback from 10 to 5 bars - Increased equal level tolerance from 2.0 to 3.0 pips - Relaxed confirmation criteria from 2x to 0.5x body size - Extended search ranges from 20 to 30 bars 2. Debug and fix bias calculation system - Fixed circular dependency in bias calculation - Allow calculation with limited data instead of failing - Improved error handling for invalid data scenarios 3. Review BOS detection algorithm sensitivity - Increased analysis range from SwingLookback*3 to SwingLookback*8 - Extended search ranges from BOSConfirmationCandles*2 to BOSConfirmationCandles*4 - Relaxed confirmation requirements from 2/3 to 1/3 candles - Extended validity period from 3x to 6x confirmation candles - Implemented more permissive swing point detection 4. Consider adjusting confluence requirements (allow 3/4 criteria vs. requiring all 4) - Added MinConfluenceCount parameter (default: 3) - Implemented ValidateFlexibleConfluence() function - Modified AnalyzeBullishSetup() and AnalyzeBearishSetup() to use flexible validation - Allows trade execution with 3/4 criteria instead of requiring all 4 - Maintains proper sequence validation (Sweep → BOS → FVG → OB) - Includes detailed logging for confluence analysis 🎯 EXPECTED IMPACT: - Should resolve zero trade execution issue - More realistic detection parameters for current market conditions - Flexible confluence system allows trades when 3/4 patterns align - Maintains risk management while improving signal generation Ready for testing with optimized parameters and flexible confluence system.
This commit is contained in:
+267
-318
@@ -49,11 +49,12 @@ input int MaxPositionsPerSymbol = 3; // Maximum positions
|
||||
|
||||
input group "=== Pattern Detection ===" input int OBLookback = 20; // Order Block lookback candles
|
||||
input double MinFVGSize = 3.0; // Minimum FVG size in pips
|
||||
input double MinSweepDistance = 5.0; // Minimum sweep distance in pips
|
||||
input double MinSweepDistance = 3.0; // Minimum sweep distance in pips (reduced from 5.0)
|
||||
input int BOSConfirmationCandles = 3; // BOS confirmation within candles
|
||||
input int SwingLookback = 10; // Swing high/low lookback period
|
||||
input int SwingLookback = 5; // Swing high/low lookback period (reduced from 10)
|
||||
input double OBStrengthFilter = 0.5; // Order Block strength filter (0-1)
|
||||
input bool RequireMultiTFConfirmation = true; // Require multi-timeframe confirmation
|
||||
input int MinConfluenceCount = 3; // Minimum confluence criteria required (3/4 instead of 4/4)
|
||||
|
||||
input group "=== Fibonacci Settings ===" input bool EnableFibonacci = true; // Enable Fibonacci retracement analysis
|
||||
input ENUM_FIBONACCI_MODE FibonacciMode = FIBONACCI_AS_FILTER; // Fibonacci integration mode
|
||||
@@ -380,6 +381,7 @@ double g_fibonacci_percentages[5] = {23.6, 38.2, 50.0, 61.8, 78.6}; // Standard
|
||||
|
||||
//--- Function declarations
|
||||
bool ConfirmBOS(string symbol, ENUM_TIMEFRAMES timeframe, int break_bar, bool is_bullish, double level);
|
||||
bool ValidateFlexibleConfluence(string symbol, bool is_bullish, MarketStructureData &m1_data);
|
||||
|
||||
//--- Phase 4: Advanced Risk Management Function Declarations
|
||||
bool InitializePhase4RiskManagement();
|
||||
@@ -1798,303 +1800,28 @@ bool AnalyzeBullishSetup(string symbol)
|
||||
ArraySize(m1_data.order_blocks), ArraySize(m1_data.fair_value_gaps),
|
||||
ArraySize(m1_data.bos_events), ArraySize(m1_data.liquidity_sweeps)));
|
||||
|
||||
// Step 1: Find valid liquidity sweep (low sweep for bullish setup)
|
||||
LogDebug(StringFormat("Step 1: Looking for valid low sweep (total sweeps: %d)", ArraySize(m1_data.liquidity_sweeps)));
|
||||
LiquiditySweep valid_sweep;
|
||||
bool sweep_found = false;
|
||||
|
||||
for (int i = 0; i < ArraySize(m1_data.liquidity_sweeps); i++)
|
||||
{
|
||||
LogDebug(StringFormat("Checking sweep %d: is_high_sweep=%s, confirmed=%s",
|
||||
i, m1_data.liquidity_sweeps[i].is_high_sweep ? "true" : "false",
|
||||
m1_data.liquidity_sweeps[i].confirmed ? "true" : "false"));
|
||||
|
||||
if (!m1_data.liquidity_sweeps[i].is_high_sweep &&
|
||||
IsLiquiditySweepValid(symbol, PERIOD_M1, m1_data.liquidity_sweeps[i]))
|
||||
{
|
||||
valid_sweep = m1_data.liquidity_sweeps[i];
|
||||
sweep_found = true;
|
||||
LogDebug(StringFormat("Valid low sweep found at level %.5f", valid_sweep.level));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sweep_found)
|
||||
{
|
||||
LogDebug(StringFormat("BLOCKING CONDITION: No valid low sweep found for bullish setup on %s", symbol));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 2: Find opposite direction BOS (bullish BOS after low sweep)
|
||||
BreakOfStructure valid_bos;
|
||||
bool bos_found = false;
|
||||
|
||||
for (int i = 0; i < ArraySize(m1_data.bos_events); i++)
|
||||
{
|
||||
if (m1_data.bos_events[i].is_bullish &&
|
||||
m1_data.bos_events[i].confirmed &&
|
||||
m1_data.bos_events[i].time > valid_sweep.time) // BOS must be after sweep
|
||||
{
|
||||
valid_bos = m1_data.bos_events[i];
|
||||
bos_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bos_found)
|
||||
{
|
||||
LogDebug(StringFormat("No valid bullish BOS found after low sweep on %s", symbol));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3: Find valid FVG between BOS and current price
|
||||
FairValueGap valid_fvg;
|
||||
bool fvg_found = false;
|
||||
|
||||
for (int i = 0; i < ArraySize(m1_data.fair_value_gaps); i++)
|
||||
{
|
||||
if (m1_data.fair_value_gaps[i].is_bullish &&
|
||||
IsFVGValid(symbol, PERIOD_M1, m1_data.fair_value_gaps[i]) &&
|
||||
m1_data.fair_value_gaps[i].time > valid_bos.time) // FVG must be after BOS
|
||||
{
|
||||
valid_fvg = m1_data.fair_value_gaps[i];
|
||||
fvg_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fvg_found)
|
||||
{
|
||||
LogDebug(StringFormat("No valid bullish FVG found after BOS on %s", symbol));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 4: Find fresh bullish Order Block
|
||||
OrderBlock valid_ob;
|
||||
bool ob_found = false;
|
||||
|
||||
for (int i = 0; i < ArraySize(m1_data.order_blocks); i++)
|
||||
{
|
||||
if (m1_data.order_blocks[i].is_bullish &&
|
||||
m1_data.order_blocks[i].is_fresh &&
|
||||
m1_data.order_blocks[i].strength >= OBStrengthFilter &&
|
||||
m1_data.order_blocks[i].time > valid_fvg.time) // OB must be after FVG
|
||||
{
|
||||
valid_ob = m1_data.order_blocks[i];
|
||||
ob_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ob_found)
|
||||
{
|
||||
LogDebug(StringFormat("No valid fresh bullish OB found after FVG on %s", symbol));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 5: Fibonacci validation (if enabled)
|
||||
FibonacciRetracement valid_fibonacci;
|
||||
bool fibonacci_valid = false;
|
||||
|
||||
if (EnableFibonacci)
|
||||
{
|
||||
LogDebug("Step 5: Checking Fibonacci validation for bullish setup");
|
||||
|
||||
// Find a suitable Fibonacci retracement for this setup
|
||||
for (int i = 0; i < ArraySize(g_fibonacci_retracements); i++)
|
||||
{
|
||||
if (ValidateFibonacciSetup(symbol, true, g_fibonacci_retracements[i]))
|
||||
{
|
||||
valid_fibonacci = g_fibonacci_retracements[i];
|
||||
fibonacci_valid = true;
|
||||
LogDebug(StringFormat("Valid Fibonacci retracement found: %.5f to %.5f",
|
||||
valid_fibonacci.swing_high, valid_fibonacci.swing_low));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply mode-based validation logic
|
||||
if (!ShouldTakeTradeBasedOnMode(symbol, true, valid_ob, valid_fvg, valid_sweep,
|
||||
fibonacci_valid ? valid_fibonacci : FibonacciRetracement(),
|
||||
fibonacci_valid))
|
||||
{
|
||||
LogDebug(StringFormat("BLOCKING CONDITION: Mode-based validation failed for %s", symbol));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6: Check multi-timeframe alignment
|
||||
if (RequireMultiTFConfirmation)
|
||||
{
|
||||
if (!IsMultiTimeframeAligned(symbol, true))
|
||||
{
|
||||
LogDebug(StringFormat("Multi-timeframe not aligned for bullish setup on %s", symbol));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7: Execute bullish trade
|
||||
// Phase 5: Record pattern signal detection with Fibonacci info
|
||||
string pattern_name = "OB+BOS+FVG+Sweep_Bullish";
|
||||
if (EnableFibonacci && fibonacci_valid)
|
||||
{
|
||||
pattern_name = "OB+BOS+FVG+Sweep+Fib_Bullish";
|
||||
}
|
||||
RecordPatternSignal(pattern_name, true);
|
||||
|
||||
return ExecuteBullishTradeWithFibonacci(symbol, valid_ob, valid_fvg, valid_sweep,
|
||||
fibonacci_valid ? valid_fibonacci : FibonacciRetracement());
|
||||
// CRITICAL FIX: Use flexible confluence validation instead of requiring all 4 criteria
|
||||
return ValidateFlexibleConfluence(symbol, true, m1_data);
|
||||
}
|
||||
|
||||
bool AnalyzeBearishSetup(string symbol)
|
||||
{
|
||||
LogDebug(StringFormat("=== Analyzing Bearish Setup for %s ===", symbol));
|
||||
|
||||
// Get M1 timeframe data
|
||||
MarketStructureData m1_data;
|
||||
if (!GetTimeframeData(PERIOD_M1, m1_data) || !m1_data.is_valid)
|
||||
{
|
||||
LogDebug(StringFormat("M1 data not available or invalid for %s", symbol));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 1: Find valid liquidity sweep (high sweep for bearish setup)
|
||||
LiquiditySweep valid_sweep;
|
||||
bool sweep_found = false;
|
||||
LogDebug(StringFormat("M1 data available: OB=%d, FVG=%d, BOS=%d, Sweeps=%d",
|
||||
ArraySize(m1_data.order_blocks), ArraySize(m1_data.fair_value_gaps),
|
||||
ArraySize(m1_data.bos_events), ArraySize(m1_data.liquidity_sweeps)));
|
||||
|
||||
for (int i = 0; i < ArraySize(m1_data.liquidity_sweeps); i++)
|
||||
{
|
||||
if (m1_data.liquidity_sweeps[i].is_high_sweep &&
|
||||
IsLiquiditySweepValid(symbol, PERIOD_M1, m1_data.liquidity_sweeps[i]))
|
||||
{
|
||||
valid_sweep = m1_data.liquidity_sweeps[i];
|
||||
sweep_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sweep_found)
|
||||
{
|
||||
LogDebug(StringFormat("No valid high sweep found for bearish setup on %s", symbol));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 2: Find opposite direction BOS (bearish BOS after high sweep)
|
||||
BreakOfStructure valid_bos;
|
||||
bool bos_found = false;
|
||||
|
||||
for (int i = 0; i < ArraySize(m1_data.bos_events); i++)
|
||||
{
|
||||
if (!m1_data.bos_events[i].is_bullish &&
|
||||
m1_data.bos_events[i].confirmed &&
|
||||
m1_data.bos_events[i].time > valid_sweep.time) // BOS must be after sweep
|
||||
{
|
||||
valid_bos = m1_data.bos_events[i];
|
||||
bos_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bos_found)
|
||||
{
|
||||
LogDebug(StringFormat("No valid bearish BOS found after high sweep on %s", symbol));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3: Find valid FVG between BOS and current price
|
||||
FairValueGap valid_fvg;
|
||||
bool fvg_found = false;
|
||||
|
||||
for (int i = 0; i < ArraySize(m1_data.fair_value_gaps); i++)
|
||||
{
|
||||
if (!m1_data.fair_value_gaps[i].is_bullish &&
|
||||
IsFVGValid(symbol, PERIOD_M1, m1_data.fair_value_gaps[i]) &&
|
||||
m1_data.fair_value_gaps[i].time > valid_bos.time) // FVG must be after BOS
|
||||
{
|
||||
valid_fvg = m1_data.fair_value_gaps[i];
|
||||
fvg_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fvg_found)
|
||||
{
|
||||
LogDebug(StringFormat("No valid bearish FVG found after BOS on %s", symbol));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 4: Find fresh bearish Order Block
|
||||
OrderBlock valid_ob;
|
||||
bool ob_found = false;
|
||||
|
||||
for (int i = 0; i < ArraySize(m1_data.order_blocks); i++)
|
||||
{
|
||||
if (!m1_data.order_blocks[i].is_bullish &&
|
||||
m1_data.order_blocks[i].is_fresh &&
|
||||
m1_data.order_blocks[i].strength >= OBStrengthFilter &&
|
||||
m1_data.order_blocks[i].time > valid_fvg.time) // OB must be after FVG
|
||||
{
|
||||
valid_ob = m1_data.order_blocks[i];
|
||||
ob_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ob_found)
|
||||
{
|
||||
LogDebug(StringFormat("No valid fresh bearish OB found after FVG on %s", symbol));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 5: Fibonacci validation (if enabled)
|
||||
FibonacciRetracement valid_fibonacci;
|
||||
bool fibonacci_valid = false;
|
||||
|
||||
if (EnableFibonacci)
|
||||
{
|
||||
LogDebug("Step 5: Checking Fibonacci validation for bearish setup");
|
||||
|
||||
// Find a suitable Fibonacci retracement for this setup
|
||||
for (int i = 0; i < ArraySize(g_fibonacci_retracements); i++)
|
||||
{
|
||||
if (ValidateFibonacciSetup(symbol, false, g_fibonacci_retracements[i]))
|
||||
{
|
||||
valid_fibonacci = g_fibonacci_retracements[i];
|
||||
fibonacci_valid = true;
|
||||
LogDebug(StringFormat("Valid Fibonacci retracement found: %.5f to %.5f",
|
||||
valid_fibonacci.swing_high, valid_fibonacci.swing_low));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply mode-based validation logic
|
||||
if (!ShouldTakeTradeBasedOnMode(symbol, false, valid_ob, valid_fvg, valid_sweep,
|
||||
fibonacci_valid ? valid_fibonacci : FibonacciRetracement(),
|
||||
fibonacci_valid))
|
||||
{
|
||||
LogDebug(StringFormat("BLOCKING CONDITION: Mode-based validation failed for %s", symbol));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6: Check multi-timeframe alignment
|
||||
if (RequireMultiTFConfirmation)
|
||||
{
|
||||
if (!IsMultiTimeframeAligned(symbol, false))
|
||||
{
|
||||
LogDebug(StringFormat("Multi-timeframe not aligned for bearish setup on %s", symbol));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7: Execute bearish trade
|
||||
// Phase 5: Record pattern signal detection with Fibonacci info
|
||||
string pattern_name = "OB+BOS+FVG+Sweep_Bearish";
|
||||
if (EnableFibonacci && fibonacci_valid)
|
||||
{
|
||||
pattern_name = "OB+BOS+FVG+Sweep+Fib_Bearish";
|
||||
}
|
||||
RecordPatternSignal(pattern_name, true);
|
||||
|
||||
return ExecuteBearishTradeWithFibonacci(symbol, valid_ob, valid_fvg, valid_sweep,
|
||||
fibonacci_valid ? valid_fibonacci : FibonacciRetracement());
|
||||
// CRITICAL FIX: Use flexible confluence validation instead of requiring all 4 criteria
|
||||
return ValidateFlexibleConfluence(symbol, false, m1_data);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -3147,7 +2874,7 @@ bool DetectBreakOfStructure(string symbol, ENUM_TIMEFRAMES timeframe, BreakOfStr
|
||||
{
|
||||
ArrayResize(bos_events, 0);
|
||||
|
||||
int bars_to_analyze = MathMin(SwingLookback * 3, iBars(symbol, timeframe) - 10);
|
||||
int bars_to_analyze = MathMin(SwingLookback * 8, iBars(symbol, timeframe) - 10); // Increased from 3x to 8x
|
||||
if (bars_to_analyze < 20)
|
||||
return false;
|
||||
|
||||
@@ -3183,17 +2910,19 @@ void FindSwingPoints(string symbol, ENUM_TIMEFRAMES timeframe, int bars_to_analy
|
||||
double current_low = iLow(symbol, timeframe, i);
|
||||
datetime current_time = iTime(symbol, timeframe, i);
|
||||
|
||||
// Check for swing high
|
||||
// Check for swing high (relaxed criteria - allow equal highs)
|
||||
bool is_swing_high = true;
|
||||
int higher_count = 0;
|
||||
for (int j = 1; j <= SwingLookback; j++)
|
||||
{
|
||||
if (iHigh(symbol, timeframe, i - j) >= current_high ||
|
||||
iHigh(symbol, timeframe, i + j) >= current_high)
|
||||
if (iHigh(symbol, timeframe, i - j) > current_high ||
|
||||
iHigh(symbol, timeframe, i + j) > current_high)
|
||||
{
|
||||
is_swing_high = false;
|
||||
break;
|
||||
higher_count++;
|
||||
}
|
||||
}
|
||||
// Allow swing high if less than 2 bars are higher (more permissive)
|
||||
is_swing_high = (higher_count < 2);
|
||||
|
||||
if (is_swing_high)
|
||||
{
|
||||
@@ -3203,17 +2932,19 @@ void FindSwingPoints(string symbol, ENUM_TIMEFRAMES timeframe, int bars_to_analy
|
||||
swing_high_times[ArraySize(swing_high_times) - 1] = current_time;
|
||||
}
|
||||
|
||||
// Check for swing low
|
||||
// Check for swing low (relaxed criteria - allow equal lows)
|
||||
bool is_swing_low = true;
|
||||
int lower_count = 0;
|
||||
for (int j = 1; j <= SwingLookback; j++)
|
||||
{
|
||||
if (iLow(symbol, timeframe, i - j) <= current_low ||
|
||||
iLow(symbol, timeframe, i + j) <= current_low)
|
||||
if (iLow(symbol, timeframe, i - j) < current_low ||
|
||||
iLow(symbol, timeframe, i + j) < current_low)
|
||||
{
|
||||
is_swing_low = false;
|
||||
break;
|
||||
lower_count++;
|
||||
}
|
||||
}
|
||||
// Allow swing low if less than 2 bars are lower (more permissive)
|
||||
is_swing_low = (lower_count < 2);
|
||||
|
||||
if (is_swing_low)
|
||||
{
|
||||
@@ -3241,7 +2972,7 @@ void AnalyzeBOSPatterns(string symbol, ENUM_TIMEFRAMES timeframe,
|
||||
if (start_bar < 0)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < start_bar && j < BOSConfirmationCandles * 2; j++)
|
||||
for (int j = 0; j < start_bar && j < BOSConfirmationCandles * 4; j++) // Increased search range
|
||||
{
|
||||
double current_high = iHigh(symbol, timeframe, j);
|
||||
double current_close = iClose(symbol, timeframe, j);
|
||||
@@ -3281,7 +3012,7 @@ void AnalyzeBOSPatterns(string symbol, ENUM_TIMEFRAMES timeframe,
|
||||
if (start_bar < 0)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < start_bar && j < BOSConfirmationCandles * 2; j++)
|
||||
for (int j = 0; j < start_bar && j < BOSConfirmationCandles * 4; j++) // Increased search range
|
||||
{
|
||||
double current_low = iLow(symbol, timeframe, j);
|
||||
double current_close = iClose(symbol, timeframe, j);
|
||||
@@ -3332,8 +3063,8 @@ bool ConfirmBOS(string symbol, ENUM_TIMEFRAMES timeframe, int break_bar, bool is
|
||||
}
|
||||
}
|
||||
|
||||
// Require at least 2 out of 3 confirmation candles
|
||||
return confirmation_count >= MathMax(2, BOSConfirmationCandles / 2);
|
||||
// Require at least 1 out of 3 confirmation candles (relaxed from 2)
|
||||
return confirmation_count >= MathMax(1, BOSConfirmationCandles / 3);
|
||||
}
|
||||
|
||||
bool IsBOSValid(string symbol, ENUM_TIMEFRAMES timeframe, BreakOfStructure &bos)
|
||||
@@ -3342,7 +3073,7 @@ bool IsBOSValid(string symbol, ENUM_TIMEFRAMES timeframe, BreakOfStructure &bos)
|
||||
datetime current_time = iTime(symbol, timeframe, 0);
|
||||
int time_diff = (int)((current_time - bos.time) / PeriodSeconds(timeframe));
|
||||
|
||||
if (time_diff > BOSConfirmationCandles * 3)
|
||||
if (time_diff > BOSConfirmationCandles * 6) // Increased validity period from 3x to 6x
|
||||
return false;
|
||||
|
||||
// Check if price is still respecting the BOS level
|
||||
@@ -3558,8 +3289,8 @@ bool DetectLiquiditySweeps(string symbol, ENUM_TIMEFRAMES timeframe, LiquiditySw
|
||||
if (equal_bar < 0)
|
||||
continue;
|
||||
|
||||
// Look for sweep above this equal high
|
||||
for (int j = 0; j < equal_bar && j < 20; j++)
|
||||
// Look for sweep above this equal high (increased search range)
|
||||
for (int j = 0; j < equal_bar && j < 30; j++)
|
||||
{
|
||||
double current_high = iHigh(symbol, timeframe, j);
|
||||
double current_close = iClose(symbol, timeframe, j);
|
||||
@@ -3600,8 +3331,8 @@ bool DetectLiquiditySweeps(string symbol, ENUM_TIMEFRAMES timeframe, LiquiditySw
|
||||
if (equal_bar < 0)
|
||||
continue;
|
||||
|
||||
// Look for sweep below this equal low
|
||||
for (int j = 0; j < equal_bar && j < 20; j++)
|
||||
// Look for sweep below this equal low (increased search range)
|
||||
for (int j = 0; j < equal_bar && j < 30; j++)
|
||||
{
|
||||
double current_low = iLow(symbol, timeframe, j);
|
||||
double current_close = iClose(symbol, timeframe, j);
|
||||
@@ -3646,7 +3377,7 @@ void FindEqualHighsLows(string symbol, ENUM_TIMEFRAMES timeframe, int bars_to_an
|
||||
ArrayResize(equal_low_times, 0);
|
||||
|
||||
double pip_value = CalculatePipValue(symbol);
|
||||
double tolerance = 2.0 * pip_value; // 2 pip tolerance for "equal" levels
|
||||
double tolerance = 3.0 * pip_value; // 3 pip tolerance for "equal" levels (increased from 2.0)
|
||||
|
||||
// Find swing points first
|
||||
double swing_highs[];
|
||||
@@ -3750,8 +3481,8 @@ bool ConfirmLiquiditySweep(string symbol, ENUM_TIMEFRAMES timeframe, int sweep_b
|
||||
double wick_size = sweep_high - sweep_close;
|
||||
double body_size = MathAbs(iClose(symbol, timeframe, sweep_bar) - iOpen(symbol, timeframe, sweep_bar));
|
||||
|
||||
// Wick should be at least 2x the body size
|
||||
if (wick_size < body_size * 2)
|
||||
// Wick should be at least 0.5x the body size (relaxed from 2x)
|
||||
if (wick_size < body_size * 0.5)
|
||||
return false;
|
||||
|
||||
// Close should be below the swept level
|
||||
@@ -3764,8 +3495,8 @@ bool ConfirmLiquiditySweep(string symbol, ENUM_TIMEFRAMES timeframe, int sweep_b
|
||||
double wick_size = sweep_close - sweep_low;
|
||||
double body_size = MathAbs(iClose(symbol, timeframe, sweep_bar) - iOpen(symbol, timeframe, sweep_bar));
|
||||
|
||||
// Wick should be at least 2x the body size
|
||||
if (wick_size < body_size * 2)
|
||||
// Wick should be at least 0.5x the body size (relaxed from 2x)
|
||||
if (wick_size < body_size * 0.5)
|
||||
return false;
|
||||
|
||||
// Close should be above the swept level
|
||||
@@ -3946,9 +3677,13 @@ bool UpdateTimeframeData(string symbol, MarketStructureData &mtf_data)
|
||||
bool bos_success = DetectBreakOfStructure(symbol, mtf_data.timeframe, mtf_data.bos_events);
|
||||
bool sweep_success = DetectLiquiditySweeps(symbol, mtf_data.timeframe, mtf_data.liquidity_sweeps);
|
||||
|
||||
// Consider update successful if at least pattern detection worked
|
||||
// Consider update successful if at least pattern detection worked OR if we have sufficient bars
|
||||
bool patterns_success = ob_success || fvg_success || bos_success || sweep_success;
|
||||
|
||||
// CRITICAL FIX: Allow timeframe to be valid even if no patterns detected, as long as we have data
|
||||
bool has_sufficient_data = iBars(symbol, mtf_data.timeframe) >= 50;
|
||||
bool update_success = patterns_success || has_sufficient_data;
|
||||
|
||||
// Phase 2: Update enhanced multi-timeframe data (always attempt, don't fail on bias calc issues)
|
||||
// Calculate bias strength for this timeframe (don't fail if this doesn't work)
|
||||
mtf_data.current_bias = CalculateBiasStrength(symbol, mtf_data.timeframe);
|
||||
@@ -3981,9 +3716,9 @@ bool UpdateTimeframeData(string symbol, MarketStructureData &mtf_data)
|
||||
|
||||
// Update metadata
|
||||
mtf_data.last_update = iTime(symbol, mtf_data.timeframe, 0);
|
||||
mtf_data.is_valid = patterns_success;
|
||||
mtf_data.is_valid = update_success; // Use the improved success criteria
|
||||
|
||||
if (patterns_success)
|
||||
if (update_success)
|
||||
{
|
||||
LogDebug(StringFormat("%s analysis completed: OB=%d, FVG=%d, BOS=%d, Sweeps=%d, Bias=%.1f%% (%s), Phase=%s",
|
||||
EnumToString(mtf_data.timeframe),
|
||||
@@ -4002,7 +3737,7 @@ bool UpdateTimeframeData(string symbol, MarketStructureData &mtf_data)
|
||||
}
|
||||
}
|
||||
|
||||
return patterns_success;
|
||||
return update_success;
|
||||
}
|
||||
|
||||
void DrawPatternsOnChart(string symbol, MarketStructureData &mtf_data)
|
||||
@@ -4345,13 +4080,21 @@ BiasStrength CalculateBiasStrength(string symbol, ENUM_TIMEFRAMES timeframe)
|
||||
bias.pattern_score = 0.0;
|
||||
|
||||
MarketStructureData mtf_data;
|
||||
if (!GetTimeframeData(timeframe, mtf_data) || !mtf_data.is_valid)
|
||||
if (!GetTimeframeData(timeframe, mtf_data))
|
||||
{
|
||||
LogDebug(StringFormat("Cannot calculate bias strength - invalid data for %s %s",
|
||||
LogDebug(StringFormat("Cannot calculate bias strength - no data available for %s %s",
|
||||
symbol, EnumToString(timeframe)));
|
||||
return bias;
|
||||
}
|
||||
|
||||
// CRITICAL FIX: Allow bias calculation even if mtf_data.is_valid is false
|
||||
// This prevents circular dependency where bias calc needs valid data but data validity depends on patterns
|
||||
if (!mtf_data.is_valid)
|
||||
{
|
||||
LogDebug(StringFormat("Calculating bias with limited data for %s %s (patterns may be incomplete)",
|
||||
symbol, EnumToString(timeframe)));
|
||||
}
|
||||
|
||||
// Calculate BOS Score (0-40 points)
|
||||
bias.bos_score = CalculateBOSScore(mtf_data.bos_events);
|
||||
|
||||
@@ -7432,3 +7175,209 @@ void LogFibonacciAnalysisStatus(string symbol)
|
||||
TimeToString(fib.created_time)));
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Flexible Confluence Validation System |
|
||||
//+------------------------------------------------------------------+
|
||||
bool ValidateFlexibleConfluence(string symbol, bool is_bullish, MarketStructureData &m1_data)
|
||||
{
|
||||
LogDebug(StringFormat("=== Flexible Confluence Validation for %s %s Setup ===",
|
||||
symbol, is_bullish ? "Bullish" : "Bearish"));
|
||||
|
||||
int confluence_count = 0;
|
||||
string confluence_details = "";
|
||||
|
||||
// Criterion 1: Valid Liquidity Sweep
|
||||
bool sweep_valid = false;
|
||||
LiquiditySweep valid_sweep;
|
||||
|
||||
for (int i = 0; i < ArraySize(m1_data.liquidity_sweeps); i++)
|
||||
{
|
||||
bool sweep_direction_match = is_bullish ? !m1_data.liquidity_sweeps[i].is_high_sweep : m1_data.liquidity_sweeps[i].is_high_sweep;
|
||||
|
||||
if (sweep_direction_match && IsLiquiditySweepValid(symbol, PERIOD_M1, m1_data.liquidity_sweeps[i]))
|
||||
{
|
||||
valid_sweep = m1_data.liquidity_sweeps[i];
|
||||
sweep_valid = true;
|
||||
confluence_count++;
|
||||
confluence_details += "✓ Liquidity Sweep ";
|
||||
LogDebug(StringFormat("✓ Valid %s sweep found at %.5f",
|
||||
is_bullish ? "low" : "high", valid_sweep.level));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sweep_valid)
|
||||
{
|
||||
confluence_details += "✗ Liquidity Sweep ";
|
||||
LogDebug(StringFormat("✗ No valid %s sweep found", is_bullish ? "low" : "high"));
|
||||
}
|
||||
|
||||
// Criterion 2: Valid Break of Structure
|
||||
bool bos_valid = false;
|
||||
BreakOfStructure valid_bos;
|
||||
|
||||
for (int i = 0; i < ArraySize(m1_data.bos_events); i++)
|
||||
{
|
||||
if (m1_data.bos_events[i].is_bullish == is_bullish &&
|
||||
m1_data.bos_events[i].confirmed &&
|
||||
IsBOSValid(symbol, PERIOD_M1, m1_data.bos_events[i]))
|
||||
{
|
||||
// If we have a sweep, BOS should be after sweep
|
||||
if (sweep_valid && m1_data.bos_events[i].time <= valid_sweep.time)
|
||||
continue;
|
||||
|
||||
valid_bos = m1_data.bos_events[i];
|
||||
bos_valid = true;
|
||||
confluence_count++;
|
||||
confluence_details += "✓ Break of Structure ";
|
||||
LogDebug(StringFormat("✓ Valid %s BOS found at %.5f",
|
||||
is_bullish ? "bullish" : "bearish", valid_bos.level));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bos_valid)
|
||||
{
|
||||
confluence_details += "✗ Break of Structure ";
|
||||
LogDebug(StringFormat("✗ No valid %s BOS found", is_bullish ? "bullish" : "bearish"));
|
||||
}
|
||||
|
||||
// Criterion 3: Valid Fair Value Gap
|
||||
bool fvg_valid = false;
|
||||
FairValueGap valid_fvg;
|
||||
|
||||
for (int i = 0; i < ArraySize(m1_data.fair_value_gaps); i++)
|
||||
{
|
||||
if (m1_data.fair_value_gaps[i].is_bullish == is_bullish &&
|
||||
IsFVGValid(symbol, PERIOD_M1, m1_data.fair_value_gaps[i]))
|
||||
{
|
||||
// If we have BOS, FVG should be after BOS
|
||||
if (bos_valid && m1_data.fair_value_gaps[i].time <= valid_bos.time)
|
||||
continue;
|
||||
|
||||
valid_fvg = m1_data.fair_value_gaps[i];
|
||||
fvg_valid = true;
|
||||
confluence_count++;
|
||||
confluence_details += "✓ Fair Value Gap ";
|
||||
LogDebug(StringFormat("✓ Valid %s FVG found: %.5f-%.5f",
|
||||
is_bullish ? "bullish" : "bearish", valid_fvg.bottom, valid_fvg.top));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fvg_valid)
|
||||
{
|
||||
confluence_details += "✗ Fair Value Gap ";
|
||||
LogDebug(StringFormat("✗ No valid %s FVG found", is_bullish ? "bullish" : "bearish"));
|
||||
}
|
||||
|
||||
// Criterion 4: Valid Order Block
|
||||
bool ob_valid = false;
|
||||
OrderBlock valid_ob;
|
||||
|
||||
for (int i = 0; i < ArraySize(m1_data.order_blocks); i++)
|
||||
{
|
||||
if (m1_data.order_blocks[i].is_bullish == is_bullish &&
|
||||
m1_data.order_blocks[i].is_fresh &&
|
||||
m1_data.order_blocks[i].strength >= OBStrengthFilter)
|
||||
{
|
||||
// If we have FVG, OB should be after FVG
|
||||
if (fvg_valid && m1_data.order_blocks[i].time <= valid_fvg.time)
|
||||
continue;
|
||||
|
||||
valid_ob = m1_data.order_blocks[i];
|
||||
ob_valid = true;
|
||||
confluence_count++;
|
||||
confluence_details += "✓ Order Block ";
|
||||
LogDebug(StringFormat("✓ Valid %s OB found: %.5f-%.5f (strength: %.2f)",
|
||||
is_bullish ? "bullish" : "bearish", valid_ob.low, valid_ob.high, valid_ob.strength));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ob_valid)
|
||||
{
|
||||
confluence_details += "✗ Order Block ";
|
||||
LogDebug(StringFormat("✗ No valid %s OB found", is_bullish ? "bullish" : "bearish"));
|
||||
}
|
||||
|
||||
// Check if we meet minimum confluence requirements
|
||||
bool confluence_met = confluence_count >= MinConfluenceCount;
|
||||
|
||||
LogDebug(StringFormat("Confluence Summary: %d/4 criteria met (%s)", confluence_count, confluence_details));
|
||||
LogDebug(StringFormat("Minimum required: %d/4 - Result: %s", MinConfluenceCount, confluence_met ? "PASS" : "FAIL"));
|
||||
|
||||
if (!confluence_met)
|
||||
{
|
||||
LogDebug(StringFormat("BLOCKING CONDITION: Insufficient confluence (%d/%d) for %s setup on %s",
|
||||
confluence_count, MinConfluenceCount, is_bullish ? "bullish" : "bearish", symbol));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Additional validations if confluence is met
|
||||
|
||||
// Multi-timeframe alignment check
|
||||
if (RequireMultiTFConfirmation)
|
||||
{
|
||||
if (!IsMultiTimeframeAligned(symbol, is_bullish))
|
||||
{
|
||||
LogDebug(StringFormat("Multi-timeframe not aligned for %s setup on %s",
|
||||
is_bullish ? "bullish" : "bearish", symbol));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Fibonacci validation (if enabled)
|
||||
FibonacciRetracement valid_fibonacci;
|
||||
bool fibonacci_valid = false;
|
||||
|
||||
if (EnableFibonacci)
|
||||
{
|
||||
LogDebug("Checking Fibonacci validation for setup");
|
||||
|
||||
for (int i = 0; i < ArraySize(g_fibonacci_retracements); i++)
|
||||
{
|
||||
if (ValidateFibonacciSetup(symbol, is_bullish, g_fibonacci_retracements[i]))
|
||||
{
|
||||
valid_fibonacci = g_fibonacci_retracements[i];
|
||||
fibonacci_valid = true;
|
||||
LogDebug(StringFormat("Valid Fibonacci retracement found: %.5f to %.5f",
|
||||
valid_fibonacci.swing_high, valid_fibonacci.swing_low));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply mode-based validation logic
|
||||
if (!ShouldTakeTradeBasedOnMode(symbol, is_bullish, valid_ob, valid_fvg, valid_sweep,
|
||||
fibonacci_valid ? valid_fibonacci : FibonacciRetracement(),
|
||||
fibonacci_valid))
|
||||
{
|
||||
LogDebug(StringFormat("BLOCKING CONDITION: Mode-based validation failed for %s", symbol));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Execute trade if all validations pass
|
||||
LogDebug(StringFormat("All validations passed - executing %s trade", is_bullish ? "bullish" : "bearish"));
|
||||
|
||||
// Record pattern signal detection
|
||||
string pattern_name = StringFormat("Flexible_%d_of_4_%s", confluence_count, is_bullish ? "Bullish" : "Bearish");
|
||||
if (EnableFibonacci && fibonacci_valid)
|
||||
{
|
||||
pattern_name += "_Fib";
|
||||
}
|
||||
RecordPatternSignal(pattern_name, true);
|
||||
|
||||
// Execute the trade
|
||||
if (is_bullish)
|
||||
{
|
||||
return ExecuteBullishTradeWithFibonacci(symbol, valid_ob, valid_fvg, valid_sweep,
|
||||
fibonacci_valid ? valid_fibonacci : FibonacciRetracement());
|
||||
}
|
||||
else
|
||||
{
|
||||
return ExecuteBearishTradeWithFibonacci(symbol, valid_ob, valid_fvg, valid_sweep,
|
||||
fibonacci_valid ? valid_fibonacci : FibonacciRetracement());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user