şundan çatallanmış SahrJohn/RSI-Stoch-MA-EA
658 satır
No EOL
22 KiB
MQL5
658 satır
No EOL
22 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| SignalCoordinator.mqh |
|
|
//| Smart Signal Coordination & Conflict Prevention |
|
|
//| Coordinates: MA, MFIB, FIB, Stoch, Candlesticks |
|
|
//| Prevents conflicting trades within 5-min timeframes |
|
|
//| Balances BULL/BEAR signals across all modes and states |
|
|
//+------------------------------------------------------------------+
|
|
|
|
//================ SIGNAL STRUCTURES ==================//
|
|
|
|
struct CoordinatedSignal
|
|
{
|
|
string source; // "ma", "mfib", "fib", "stoch", "candle"
|
|
string action; // "reject", "reclaim", "break"
|
|
string direction; // "bullish" or "bearish"
|
|
string signal_type; // "WARN" or "PRAISE"
|
|
double strength; // 0-100
|
|
string location; // Where it happened
|
|
datetime timestamp; // When it happened
|
|
double price; // At what price
|
|
bool at_key_level; // True if at MFIB/FIB/major MA
|
|
};
|
|
|
|
struct SignalCluster
|
|
{
|
|
CoordinatedSignal signals[20]; // Max 20 signals in cluster
|
|
int count;
|
|
string consensus_direction; // "bullish", "bearish", "neutral"
|
|
string consensus_type; // "WARN" or "PRAISE"
|
|
double combined_strength;
|
|
double conflict_score; // 0-100
|
|
datetime cluster_time;
|
|
};
|
|
|
|
//================ GLOBAL COORDINATOR STATE ==================//
|
|
CoordinatedSignal SignalHistory[100];
|
|
int SignalHistoryCount = 0;
|
|
SignalCluster CurrentCluster;
|
|
datetime LastClusterTime = 0;
|
|
|
|
// Signal balance tracking
|
|
int BullWarnCount = 0;
|
|
int BullPraiseCount = 0;
|
|
int BearWarnCount = 0;
|
|
int BearPraiseCount = 0;
|
|
|
|
// Conflict prevention
|
|
datetime LastTradeTime = 0;
|
|
string LastTradeDirection = "";
|
|
int ConflictPreventionSeconds = 300; // 5 minutes
|
|
|
|
//================ SIGNAL COORDINATOR FUNCTIONS ==================//
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Initialize Signal Coordinator |
|
|
//+------------------------------------------------------------------+
|
|
void InitializeSignalCoordinator()
|
|
{
|
|
ArrayInitialize(SignalHistory, 0);
|
|
SignalHistoryCount = 0;
|
|
CurrentCluster.count = 0;
|
|
|
|
BullWarnCount = 0;
|
|
BullPraiseCount = 0;
|
|
BearWarnCount = 0;
|
|
BearPraiseCount = 0;
|
|
|
|
Print("✅ Signal Coordinator initialized");
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Add Signal to Coordinator |
|
|
//+------------------------------------------------------------------+
|
|
bool AddCoordinatedSignal(string source, string action, string direction,
|
|
string signal_type, double strength, string location,
|
|
double price, bool at_key_level)
|
|
{
|
|
// Create signal
|
|
CoordinatedSignal signal;
|
|
signal.source = source;
|
|
signal.action = action;
|
|
signal.direction = direction;
|
|
signal.signal_type = signal_type;
|
|
signal.strength = strength;
|
|
signal.location = location;
|
|
signal.timestamp = TimeCurrent();
|
|
signal.price = price;
|
|
signal.at_key_level = at_key_level;
|
|
|
|
// Check for conflicts
|
|
if(HasConflict(signal))
|
|
{
|
|
Print("⚠️ Signal REJECTED due to conflict: ", signal.source, " ",
|
|
signal.direction, " ", signal.signal_type);
|
|
return false;
|
|
}
|
|
|
|
// Add to history
|
|
if(SignalHistoryCount < ArraySize(SignalHistory))
|
|
{
|
|
SignalHistory[SignalHistoryCount] = signal;
|
|
SignalHistoryCount++;
|
|
}
|
|
|
|
// Add to current cluster
|
|
if(CurrentCluster.count < ArraySize(CurrentCluster.signals))
|
|
{
|
|
CurrentCluster.signals[CurrentCluster.count] = signal;
|
|
CurrentCluster.count++;
|
|
}
|
|
|
|
// Update balance counters
|
|
UpdateBalanceCounters(signal);
|
|
|
|
Print("✅ Signal ADDED: ", signal.source, " ", signal.action, " at ",
|
|
signal.location, " - ", signal.direction, " ", signal.signal_type);
|
|
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check for Signal Conflicts (within 5 min window) |
|
|
//+------------------------------------------------------------------+
|
|
bool HasConflict(CoordinatedSignal &new_signal)
|
|
{
|
|
datetime current_time = TimeCurrent();
|
|
|
|
// Check recent signals (last 5 minutes)
|
|
for(int i = SignalHistoryCount - 1; i >= 0 && i >= SignalHistoryCount - 20; i--)
|
|
{
|
|
if(current_time - SignalHistory[i].timestamp > ConflictPreventionSeconds)
|
|
break;
|
|
|
|
// Same source within 1 minute = skip (duplicate)
|
|
if(SignalHistory[i].source == new_signal.source &&
|
|
current_time - SignalHistory[i].timestamp < 60)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Opposite direction with strong signal = conflict
|
|
if(SignalHistory[i].direction != new_signal.direction &&
|
|
SignalHistory[i].strength >= 70 &&
|
|
new_signal.strength >= 70)
|
|
{
|
|
Print("⚠️ CONFLICT: Strong ", SignalHistory[i].direction,
|
|
" vs ", new_signal.direction, " within 5 min");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Update Balance Counters |
|
|
//+------------------------------------------------------------------+
|
|
void UpdateBalanceCounters(CoordinatedSignal &signal)
|
|
{
|
|
if(signal.direction == "bullish" && signal.signal_type == "WARN")
|
|
BullWarnCount++;
|
|
else if(signal.direction == "bullish" && signal.signal_type == "PRAISE")
|
|
BullPraiseCount++;
|
|
else if(signal.direction == "bearish" && signal.signal_type == "WARN")
|
|
BearWarnCount++;
|
|
else if(signal.direction == "bearish" && signal.signal_type == "PRAISE")
|
|
BearPraiseCount++;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate Signals from Moving Averages (BALANCED) |
|
|
//+------------------------------------------------------------------+
|
|
void GenerateMASignals()
|
|
{
|
|
double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
|
|
// BULLISH MA SIGNALS
|
|
|
|
// Price above MA20 = PRAISE (bullish continuation)
|
|
if(current_price > MA_20_Value)
|
|
{
|
|
AddCoordinatedSignal("ma", "reclaim", "bullish", "PRAISE", 65,
|
|
"ma_20", current_price, false);
|
|
}
|
|
|
|
// Price reclaims MA50 = WARN (potential bounce)
|
|
if(current_price > MA_50_Value &&
|
|
SymbolInfoDouble(_Symbol, SYMBOL_BID) < MA_50_Value)
|
|
{
|
|
AddCoordinatedSignal("ma", "reclaim", "bullish", "WARN", 70,
|
|
"ma_50", MA_50_Value, true);
|
|
}
|
|
|
|
// Price above MA140 = PRAISE (strong trend continuation)
|
|
if(current_price > MA_140_Value)
|
|
{
|
|
AddCoordinatedSignal("ma", "reclaim", "bullish", "PRAISE", 75,
|
|
"ma_140", current_price, true);
|
|
}
|
|
|
|
// Price above MA230 = PRAISE (major trend)
|
|
if(current_price > MA_230_Value)
|
|
{
|
|
AddCoordinatedSignal("ma", "reclaim", "bullish", "PRAISE", 80,
|
|
"ma_230", current_price, true);
|
|
}
|
|
|
|
// BEARISH MA SIGNALS
|
|
|
|
// Price below MA20 = PRAISE (bearish continuation)
|
|
if(current_price < MA_20_Value)
|
|
{
|
|
AddCoordinatedSignal("ma", "break", "bearish", "PRAISE", 65,
|
|
"ma_20", current_price, false);
|
|
}
|
|
|
|
// Price rejects MA50 = WARN (potential rejection)
|
|
if(current_price < MA_50_Value &&
|
|
SymbolInfoDouble(_Symbol, SYMBOL_ASK) > MA_50_Value)
|
|
{
|
|
AddCoordinatedSignal("ma", "reject", "bearish", "WARN", 70,
|
|
"ma_50", MA_50_Value, true);
|
|
}
|
|
|
|
// Price below MA140 = PRAISE (strong bearish trend)
|
|
if(current_price < MA_140_Value)
|
|
{
|
|
AddCoordinatedSignal("ma", "break", "bearish", "PRAISE", 75,
|
|
"ma_140", current_price, true);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate Signals from MFIB Levels (BALANCED) |
|
|
//+------------------------------------------------------------------+
|
|
void GenerateMFIBSignals()
|
|
{
|
|
double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
double tolerance = SymbolInfoDouble(_Symbol, SYMBOL_POINT) * 50;
|
|
|
|
static double prev_price = 0;
|
|
if(prev_price == 0) prev_price = current_price;
|
|
|
|
// Check each MFIB level
|
|
|
|
// MFIB 0.236 (Support)
|
|
if(MathAbs(current_price - MFIB_236) < tolerance)
|
|
{
|
|
if(prev_price < MFIB_236 && current_price >= MFIB_236)
|
|
{
|
|
// Reclaim = PRAISE (bullish continuation)
|
|
AddCoordinatedSignal("mfib", "reclaim", "bullish", "PRAISE", 85,
|
|
"mfib_236", MFIB_236, true);
|
|
}
|
|
else if(prev_price > MFIB_236 && current_price <= MFIB_236)
|
|
{
|
|
// At support = WARN (potential bounce)
|
|
AddCoordinatedSignal("mfib", "reject", "bullish", "WARN", 90,
|
|
"mfib_236", MFIB_236, true);
|
|
}
|
|
}
|
|
|
|
// MFIB 0.382 (Support)
|
|
if(MathAbs(current_price - MFIB_382) < tolerance)
|
|
{
|
|
if(prev_price < MFIB_382 && current_price >= MFIB_382)
|
|
{
|
|
AddCoordinatedSignal("mfib", "reclaim", "bullish", "PRAISE", 85,
|
|
"mfib_382", MFIB_382, true);
|
|
}
|
|
else if(prev_price > MFIB_382)
|
|
{
|
|
AddCoordinatedSignal("mfib", "reject", "bullish", "WARN", 90,
|
|
"mfib_382", MFIB_382, true);
|
|
}
|
|
}
|
|
|
|
// MFIB 0.618 (Resistance)
|
|
if(MathAbs(current_price - MFIB_618) < tolerance)
|
|
{
|
|
if(prev_price < MFIB_618)
|
|
{
|
|
// At resistance = WARN (potential rejection)
|
|
AddCoordinatedSignal("mfib", "reject", "bearish", "WARN", 90,
|
|
"mfib_618", MFIB_618, true);
|
|
}
|
|
else if(prev_price > MFIB_618 && current_price <= MFIB_618)
|
|
{
|
|
// Break below = PRAISE (bearish continuation)
|
|
AddCoordinatedSignal("mfib", "break", "bearish", "PRAISE", 85,
|
|
"mfib_618", MFIB_618, true);
|
|
}
|
|
}
|
|
|
|
// MFIB 0.786 (Resistance)
|
|
if(MathAbs(current_price - MFIB_786) < tolerance)
|
|
{
|
|
if(prev_price < MFIB_786)
|
|
{
|
|
AddCoordinatedSignal("mfib", "reject", "bearish", "WARN", 90,
|
|
"mfib_786", MFIB_786, true);
|
|
}
|
|
else if(prev_price > MFIB_786 && current_price <= MFIB_786)
|
|
{
|
|
AddCoordinatedSignal("mfib", "break", "bearish", "PRAISE", 85,
|
|
"mfib_786", MFIB_786, true);
|
|
}
|
|
}
|
|
|
|
prev_price = current_price;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate Signals from Regular FIB Levels (BALANCED) |
|
|
//+------------------------------------------------------------------+
|
|
void GenerateFIBSignals()
|
|
{
|
|
double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
double tolerance = SymbolInfoDouble(_Symbol, SYMBOL_POINT) * 50;
|
|
|
|
static double prev_fib_price = 0;
|
|
if(prev_fib_price == 0) prev_fib_price = current_price;
|
|
|
|
// Similar to MFIB but with slightly lower strength values
|
|
// 0.236, 0.382 = Support levels
|
|
// 0.618, 0.786 = Resistance levels
|
|
|
|
// FIB 0.236
|
|
if(MathAbs(current_price - FIB_236) < tolerance)
|
|
{
|
|
if(prev_fib_price < FIB_236 && current_price >= FIB_236)
|
|
AddCoordinatedSignal("fib", "reclaim", "bullish", "PRAISE", 75,
|
|
"fib_236", FIB_236, true);
|
|
else if(prev_fib_price > FIB_236)
|
|
AddCoordinatedSignal("fib", "reject", "bullish", "WARN", 80,
|
|
"fib_236", FIB_236, true);
|
|
}
|
|
|
|
// FIB 0.618
|
|
if(MathAbs(current_price - FIB_618) < tolerance)
|
|
{
|
|
if(prev_fib_price < FIB_618)
|
|
AddCoordinatedSignal("fib", "reject", "bearish", "WARN", 80,
|
|
"fib_618", FIB_618, true);
|
|
else if(prev_fib_price > FIB_618 && current_price <= FIB_618)
|
|
AddCoordinatedSignal("fib", "break", "bearish", "PRAISE", 75,
|
|
"fib_618", FIB_618, true);
|
|
}
|
|
|
|
prev_fib_price = current_price;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate Signals from Stochastic (BALANCED) |
|
|
//+------------------------------------------------------------------+
|
|
void GenerateStochSignals()
|
|
{
|
|
// Get current stoch values (from Indicators.mqh)
|
|
double main_line = StochBuffer_Main[0];
|
|
double signal_line = StochBuffer_Signal[0];
|
|
|
|
// BULLISH STOCH SIGNALS
|
|
|
|
// Oversold (<20) = WARN (potential bullish reversal)
|
|
if(main_line < 20)
|
|
{
|
|
AddCoordinatedSignal("stoch", "reject", "bullish", "WARN", 70,
|
|
"oversold", main_line, false);
|
|
}
|
|
|
|
// Crossing up in lower half = PRAISE (bullish momentum building)
|
|
if(main_line > signal_line && main_line < 50 && main_line > 30)
|
|
{
|
|
AddCoordinatedSignal("stoch", "reclaim", "bullish", "PRAISE", 65,
|
|
"midpoint", main_line, false);
|
|
}
|
|
|
|
// BEARISH STOCH SIGNALS
|
|
|
|
// Overbought (>80) = WARN (potential bearish reversal)
|
|
if(main_line > 80)
|
|
{
|
|
AddCoordinatedSignal("stoch", "reject", "bearish", "WARN", 70,
|
|
"overbought", main_line, false);
|
|
}
|
|
|
|
// Crossing down in upper half = PRAISE (bearish momentum building)
|
|
if(main_line < signal_line && main_line > 50 && main_line < 70)
|
|
{
|
|
AddCoordinatedSignal("stoch", "break", "bearish", "PRAISE", 65,
|
|
"midpoint", main_line, false);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate Signals from Candlestick Patterns (BALANCED) |
|
|
//+------------------------------------------------------------------+
|
|
void GenerateCandleSignals()
|
|
{
|
|
// Loop through active patterns detected
|
|
for(int i = 0; i < PatternCount; i++)
|
|
{
|
|
PatternSignal pattern = ActivePatterns[i];
|
|
|
|
string direction = "";
|
|
string action = "";
|
|
|
|
// Determine direction and action from pattern type
|
|
if(pattern.type == PATTERN_REVERSAL_BULLISH)
|
|
{
|
|
direction = "bullish";
|
|
action = "reject"; // Rejecting from support
|
|
}
|
|
else if(pattern.type == PATTERN_REVERSAL_BEARISH)
|
|
{
|
|
direction = "bearish";
|
|
action = "reject"; // Rejecting from resistance
|
|
}
|
|
else if(pattern.type == PATTERN_CONTINUATION_BULL)
|
|
{
|
|
direction = "bullish";
|
|
action = "reclaim"; // Continuing upward
|
|
}
|
|
else if(pattern.type == PATTERN_CONTINUATION_BEAR)
|
|
{
|
|
direction = "bearish";
|
|
action = "break"; // Continuing downward
|
|
}
|
|
|
|
if(direction != "")
|
|
{
|
|
AddCoordinatedSignal("candle", action, direction, pattern.signal_label,
|
|
pattern.adjusted_strength, pattern.location,
|
|
pattern.pattern_price, pattern.at_key_level);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Build Current Signal Cluster |
|
|
//+------------------------------------------------------------------+
|
|
void BuildSignalCluster()
|
|
{
|
|
if(CurrentCluster.count == 0)
|
|
{
|
|
CurrentCluster.consensus_direction = "neutral";
|
|
CurrentCluster.consensus_type = "";
|
|
CurrentCluster.combined_strength = 0;
|
|
CurrentCluster.conflict_score = 0;
|
|
return;
|
|
}
|
|
|
|
// Count directions
|
|
int bullish_count = 0;
|
|
int bearish_count = 0;
|
|
int warn_count = 0;
|
|
int praise_count = 0;
|
|
double total_strength = 0;
|
|
|
|
for(int i = 0; i < CurrentCluster.count; i++)
|
|
{
|
|
if(CurrentCluster.signals[i].direction == "bullish")
|
|
bullish_count++;
|
|
else if(CurrentCluster.signals[i].direction == "bearish")
|
|
bearish_count++;
|
|
|
|
if(CurrentCluster.signals[i].signal_type == "WARN")
|
|
warn_count++;
|
|
else if(CurrentCluster.signals[i].signal_type == "PRAISE")
|
|
praise_count++;
|
|
|
|
total_strength += CurrentCluster.signals[i].strength;
|
|
}
|
|
|
|
// Determine consensus (need 60% agreement)
|
|
double bull_pct = (double)bullish_count / CurrentCluster.count;
|
|
double bear_pct = (double)bearish_count / CurrentCluster.count;
|
|
|
|
if(bull_pct >= 0.6)
|
|
CurrentCluster.consensus_direction = "bullish";
|
|
else if(bear_pct >= 0.6)
|
|
CurrentCluster.consensus_direction = "bearish";
|
|
else
|
|
CurrentCluster.consensus_direction = "neutral";
|
|
|
|
// Determine consensus type
|
|
if(warn_count > praise_count)
|
|
CurrentCluster.consensus_type = "WARN";
|
|
else
|
|
CurrentCluster.consensus_type = "PRAISE";
|
|
|
|
// Calculate combined strength (weighted average)
|
|
CurrentCluster.combined_strength = total_strength / CurrentCluster.count;
|
|
|
|
// Calculate conflict score
|
|
int min_dir = MathMin(bullish_count, bearish_count);
|
|
double dir_conflict = (double)min_dir / CurrentCluster.count;
|
|
|
|
int min_type = MathMin(warn_count, praise_count);
|
|
double type_conflict = (double)min_type / CurrentCluster.count;
|
|
|
|
CurrentCluster.conflict_score = ((dir_conflict * 0.7) + (type_conflict * 0.3)) * 100;
|
|
|
|
CurrentCluster.cluster_time = TimeCurrent();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Should Trade Based on Cluster (AI-ready decision) |
|
|
//+------------------------------------------------------------------+
|
|
bool ShouldTradeFromCluster(SignalCluster &cluster, double &multiplier)
|
|
{
|
|
// Don't trade if high conflict
|
|
if(cluster.conflict_score > 40)
|
|
{
|
|
Print("❌ Trade REJECTED: High conflict score: ", cluster.conflict_score);
|
|
return false;
|
|
}
|
|
|
|
// Don't trade if neutral
|
|
if(cluster.consensus_direction == "neutral")
|
|
{
|
|
Print("❌ Trade REJECTED: No directional consensus");
|
|
return false;
|
|
}
|
|
|
|
// Don't trade if too soon after last trade (same direction)
|
|
if(TimeCurrent() - LastTradeTime < ConflictPreventionSeconds)
|
|
{
|
|
if(LastTradeDirection == cluster.consensus_direction)
|
|
{
|
|
Print("❌ Trade REJECTED: Too soon after last ", LastTradeDirection, " trade");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Calculate multiplier based on strength and conflict
|
|
multiplier = 1.0;
|
|
|
|
// Strength adjustments
|
|
if(cluster.combined_strength >= 85)
|
|
multiplier += 0.3; // Very strong
|
|
else if(cluster.combined_strength >= 75)
|
|
multiplier += 0.2; // Strong
|
|
else if(cluster.combined_strength >= 65)
|
|
multiplier += 0.1; // Moderate
|
|
else if(cluster.combined_strength < 50)
|
|
multiplier -= 0.2; // Weak - be defensive
|
|
|
|
// Conflict adjustments
|
|
if(cluster.conflict_score > 30)
|
|
multiplier -= 0.2;
|
|
else if(cluster.conflict_score > 20)
|
|
multiplier -= 0.1;
|
|
|
|
// Ensure multiplier stays in reasonable range
|
|
multiplier = MathMax(0.5, MathMin(multiplier, 2.0));
|
|
|
|
Print("✅ Trade APPROVED: ", cluster.consensus_direction, " ",
|
|
cluster.consensus_type, " | Strength: ", cluster.combined_strength,
|
|
" | Multiplier: ", multiplier);
|
|
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Get Signal Balance Report |
|
|
//+------------------------------------------------------------------+
|
|
string GetSignalBalanceReport()
|
|
{
|
|
int total_bull = BullWarnCount + BullPraiseCount;
|
|
int total_bear = BearWarnCount + BearPraiseCount;
|
|
int total = total_bull + total_bear;
|
|
|
|
if(total == 0)
|
|
return "No signals yet";
|
|
|
|
double bull_pct = (double)total_bull / total * 100;
|
|
double bear_pct = (double)total_bear / total * 100;
|
|
|
|
string report = StringFormat(
|
|
"Signal Balance:\n" +
|
|
"Bull: %.1f%% (%d warns, %d praise)\n" +
|
|
"Bear: %.1f%% (%d warns, %d praise)\n" +
|
|
"Status: %s",
|
|
bull_pct, BullWarnCount, BullPraiseCount,
|
|
bear_pct, BearWarnCount, BearPraiseCount,
|
|
(bull_pct >= 40 && bull_pct <= 60) ? "BALANCED ✅" : "IMBALANCED ⚠️"
|
|
);
|
|
|
|
return report;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Reset Cluster (call every 5 minutes or after trade) |
|
|
//+------------------------------------------------------------------+
|
|
void ResetSignalCluster()
|
|
{
|
|
CurrentCluster.count = 0;
|
|
CurrentCluster.consensus_direction = "neutral";
|
|
CurrentCluster.consensus_type = "";
|
|
CurrentCluster.combined_strength = 0;
|
|
CurrentCluster.conflict_score = 0;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Cleanup Old Signals (call periodically) |
|
|
//+------------------------------------------------------------------+
|
|
void CleanupOldSignals()
|
|
{
|
|
datetime cutoff = TimeCurrent() - (ConflictPreventionSeconds * 2);
|
|
int new_count = 0;
|
|
|
|
for(int i = 0; i < SignalHistoryCount; i++)
|
|
{
|
|
if(SignalHistory[i].timestamp > cutoff)
|
|
{
|
|
if(new_count != i)
|
|
SignalHistory[new_count] = SignalHistory[i];
|
|
new_count++;
|
|
}
|
|
}
|
|
|
|
SignalHistoryCount = new_count;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Update Last Trade Info (call after opening trade) |
|
|
//+------------------------------------------------------------------+
|
|
void UpdateLastTradeInfo(string direction)
|
|
{
|
|
LastTradeTime = TimeCurrent();
|
|
LastTradeDirection = direction;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Master Signal Coordination Function - Call Every Tick |
|
|
//+------------------------------------------------------------------+
|
|
void CoordinateAllSignals()
|
|
{
|
|
// Step 1: Generate signals from all sources
|
|
GenerateMASignals();
|
|
GenerateMFIBSignals();
|
|
GenerateFIBSignals();
|
|
GenerateStochSignals();
|
|
GenerateCandleSignals(); // From CandlePatterns.mqh
|
|
|
|
// Step 2: Build signal cluster
|
|
BuildSignalCluster();
|
|
|
|
// Step 3: Cleanup old signals (every 100 ticks)
|
|
static int cleanup_counter = 0;
|
|
cleanup_counter++;
|
|
if(cleanup_counter >= 100)
|
|
{
|
|
CleanupOldSignals();
|
|
cleanup_counter = 0;
|
|
}
|
|
} |