//+------------------------------------------------------------------+ //| AI_MLEngine_PatternDetector.mqh| //| Machine Learning & Pattern Recognition | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Candlestick Pattern Detector | //+------------------------------------------------------------------+ class CPatternDetector { private: string m_symbol; ENUM_TIMEFRAMES m_timeframe; MqlRates m_rates[]; public: CPatternDetector(string symbol, ENUM_TIMEFRAMES tf) { m_symbol = symbol; m_timeframe = tf; ArraySetAsSeries(m_rates, true); } bool UpdateData() { return CopyRates(m_symbol, m_timeframe, 0, 10, m_rates) > 0; } // Bullish Engulfing bool IsBullishEngulfing() { if(ArraySize(m_rates) < 2) return false; bool prevBearish = m_rates[1].close < m_rates[1].open; bool currBullish = m_rates[0].close > m_rates[0].open; bool engulfs = m_rates[0].close > m_rates[1].open && m_rates[0].open < m_rates[1].close; return prevBearish && currBullish && engulfs; } // Bearish Engulfing bool IsBearishEngulfing() { if(ArraySize(m_rates) < 2) return false; bool prevBullish = m_rates[1].close > m_rates[1].open; bool currBearish = m_rates[0].close < m_rates[0].open; bool engulfs = m_rates[0].close < m_rates[1].open && m_rates[0].open > m_rates[1].close; return prevBullish && currBearish && engulfs; } // Pin Bar (Hammer/Shooting Star) int DetectPinBar() { if(ArraySize(m_rates) < 1) return 0; double body = MathAbs(m_rates[0].close - m_rates[0].open); double upperWick = m_rates[0].high - MathMax(m_rates[0].close, m_rates[0].open); double lowerWick = MathMin(m_rates[0].close, m_rates[0].open) - m_rates[0].low; double totalRange = m_rates[0].high - m_rates[0].low; if(totalRange == 0) return 0; // Bullish Pin (Hammer) if(lowerWick > body * 2 && lowerWick > totalRange * 0.6 && upperWick < body) return 1; // Bearish Pin (Shooting Star) if(upperWick > body * 2 && upperWick > totalRange * 0.6 && lowerWick < body) return -1; return 0; } // Doji bool IsDoji() { if(ArraySize(m_rates) < 1) return false; double body = MathAbs(m_rates[0].close - m_rates[0].open); double totalRange = m_rates[0].high - m_rates[0].low; return (body < totalRange * 0.1); } // Morning/Evening Star (3-candle pattern) int DetectStar() { if(ArraySize(m_rates) < 3) return 0; double body1 = MathAbs(m_rates[2].close - m_rates[2].open); double body2 = MathAbs(m_rates[1].close - m_rates[1].open); double body3 = MathAbs(m_rates[0].close - m_rates[0].open); // Morning Star (Bullish) if(m_rates[2].close < m_rates[2].open && // Bearish candle body2 < body1 * 0.3 && // Small middle candle m_rates[0].close > m_rates[0].open && // Bullish candle m_rates[0].close > m_rates[2].open) // Closes above first candle open return 1; // Evening Star (Bearish) if(m_rates[2].close > m_rates[2].open && // Bullish candle body2 < body1 * 0.3 && // Small middle candle m_rates[0].close < m_rates[0].open && // Bearish candle m_rates[0].close < m_rates[2].open) // Closes below first candle open return -1; return 0; } // Get pattern score (combined) double GetPatternScore() { UpdateData(); double score = 0; if(IsBullishEngulfing()) score += 30; if(IsBearishEngulfing()) score -= 30; int pinBar = DetectPinBar(); score += pinBar * 25; int star = DetectStar(); score += star * 35; if(IsDoji()) score += 0; // Neutral - indecision return score; } }; //+------------------------------------------------------------------+ //| Support & Resistance Level Detector | //+------------------------------------------------------------------+ class CLevelDetector { private: string m_symbol; ENUM_TIMEFRAMES m_timeframe; double m_supportLevels[]; double m_resistanceLevels[]; int m_lookbackBars; public: CLevelDetector(string symbol, ENUM_TIMEFRAMES tf, int lookback = 100) { m_symbol = symbol; m_timeframe = tf; m_lookbackBars = lookback; } void DetectLevels() { ArrayResize(m_supportLevels, 0); ArrayResize(m_resistanceLevels, 0); MqlRates rates[]; ArraySetAsSeries(rates, true); if(CopyRates(m_symbol, m_timeframe, 0, m_lookbackBars, rates) <= 0) return; // Detect swing highs and lows for(int i = 3; i < m_lookbackBars - 3; i++) { // Swing High (Resistance) if(rates[i].high > rates[i-1].high && rates[i].high > rates[i-2].high && rates[i].high > rates[i+1].high && rates[i].high > rates[i+2].high) { AddResistance(rates[i].high); } // Swing Low (Support) if(rates[i].low < rates[i-1].low && rates[i].low < rates[i-2].low && rates[i].low < rates[i+1].low && rates[i].low < rates[i+2].low) { AddSupport(rates[i].low); } } // Cluster nearby levels ClusterLevels(); } void AddSupport(double level) { int size = ArraySize(m_supportLevels); ArrayResize(m_supportLevels, size + 1); m_supportLevels[size] = level; } void AddResistance(double level) { int size = ArraySize(m_resistanceLevels); ArrayResize(m_resistanceLevels, size + 1); m_resistanceLevels[size] = level; } void ClusterLevels() { double threshold = SymbolInfoDouble(m_symbol, SYMBOL_POINT) * 50; // Cluster support levels for(int i = 0; i < ArraySize(m_supportLevels); i++) { for(int j = i + 1; j < ArraySize(m_supportLevels); j++) { if(MathAbs(m_supportLevels[i] - m_supportLevels[j]) < threshold) { m_supportLevels[i] = (m_supportLevels[i] + m_supportLevels[j]) / 2; ArrayRemove(m_supportLevels, j, 1); j--; } } } // Cluster resistance levels for(int i = 0; i < ArraySize(m_resistanceLevels); i++) { for(int j = i + 1; j < ArraySize(m_resistanceLevels); j++) { if(MathAbs(m_resistanceLevels[i] - m_resistanceLevels[j]) < threshold) { m_resistanceLevels[i] = (m_resistanceLevels[i] + m_resistanceLevels[j]) / 2; ArrayRemove(m_resistanceLevels, j, 1); j--; } } } } double GetNearestSupport(double price) { double nearest = 0; double minDist = DBL_MAX; for(int i = 0; i < ArraySize(m_supportLevels); i++) { if(m_supportLevels[i] < price) { double dist = price - m_supportLevels[i]; if(dist < minDist) { minDist = dist; nearest = m_supportLevels[i]; } } } return nearest; } double GetNearestResistance(double price) { double nearest = 0; double minDist = DBL_MAX; for(int i = 0; i < ArraySize(m_resistanceLevels); i++) { if(m_resistanceLevels[i] > price) { double dist = m_resistanceLevels[i] - price; if(dist < minDist) { minDist = dist; nearest = m_resistanceLevels[i]; } } } return nearest; } bool IsNearSupport(double price, double threshold = 0.0005) { double support = GetNearestSupport(price); if(support == 0) return false; return (MathAbs(price - support) / price < threshold); } bool IsNearResistance(double price, double threshold = 0.0005) { double resistance = GetNearestResistance(price); if(resistance == 0) return false; return (MathAbs(price - resistance) / price < threshold); } }; //+------------------------------------------------------------------+ //| Simple Neural Network for Decision Making | //+------------------------------------------------------------------+ class CNeuralNetwork { private: // Simple 3-layer network: Input -> Hidden -> Output int m_inputSize; int m_hiddenSize; int m_outputSize; double m_weightsIH[][]; // Input to Hidden double m_weightsHO[][]; // Hidden to Output double m_biasH[]; double m_biasO[]; public: CNeuralNetwork(int inputSize, int hiddenSize, int outputSize) { m_inputSize = inputSize; m_hiddenSize = hiddenSize; m_outputSize = outputSize; InitializeWeights(); } void InitializeWeights() { // Initialize with small random values ArrayResize(m_weightsIH, m_inputSize); for(int i = 0; i < m_inputSize; i++) { ArrayResize(m_weightsIH[i], m_hiddenSize); for(int j = 0; j < m_hiddenSize; j++) m_weightsIH[i][j] = (MathRand() / 32767.0 - 0.5) * 0.5; } ArrayResize(m_weightsHO, m_hiddenSize); for(int i = 0; i < m_hiddenSize; i++) { ArrayResize(m_weightsHO[i], m_outputSize); for(int j = 0; j < m_outputSize; j++) m_weightsHO[i][j] = (MathRand() / 32767.0 - 0.5) * 0.5; } ArrayResize(m_biasH, m_hiddenSize); ArrayResize(m_biasO, m_outputSize); ArrayInitialize(m_biasH, 0); ArrayInitialize(m_biasO, 0); } double Sigmoid(double x) { return 1.0 / (1.0 + MathExp(-x)); } double ReLU(double x) { return MathMax(0, x); } void Forward(double &inputs[], double &outputs[]) { ArrayResize(outputs, m_outputSize); // Hidden layer double hidden[]; ArrayResize(hidden, m_hiddenSize); for(int j = 0; j < m_hiddenSize; j++) { double sum = m_biasH[j]; for(int i = 0; i < m_inputSize; i++) sum += inputs[i] * m_weightsIH[i][j]; hidden[j] = ReLU(sum); } // Output layer for(int k = 0; k < m_outputSize; k++) { double sum = m_biasO[k]; for(int j = 0; j < m_hiddenSize; j++) sum += hidden[j] * m_weightsHO[j][k]; outputs[k] = Sigmoid(sum); } } // Simplified training (would need proper backpropagation in production) void Train(double &inputs[], double &targets[], double learningRate = 0.01) { // This is a placeholder - implement full backpropagation for production // For now, just forward pass double outputs[]; Forward(inputs, outputs); } }; //+------------------------------------------------------------------+ //| AI Decision Engine - Combines All Intelligence | //+------------------------------------------------------------------+ class CAIDecisionEngine { private: CPatternDetector *m_patternH1; CPatternDetector *m_patternH4; CLevelDetector *m_levelH4; CNeuralNetwork *m_neuralNet; string m_symbol; public: CAIDecisionEngine(string symbol) { m_symbol = symbol; m_patternH1 = new CPatternDetector(symbol, PERIOD_H1); m_patternH4 = new CPatternDetector(symbol, PERIOD_H4); m_levelH4 = new CLevelDetector(symbol, PERIOD_H4, 200); // Neural network: 10 inputs -> 20 hidden -> 3 outputs (Buy/Neutral/Sell) m_neuralNet = new CNeuralNetwork(10, 20, 3); } ~CAIDecisionEngine() { delete m_patternH1; delete m_patternH4; delete m_levelH4; delete m_neuralNet; } double MakeDecision(MarketContext &ctx) { // Update levels m_levelH4.DetectLevels(); // Get pattern scores double patternScoreH1 = m_patternH1.GetPatternScore(); double patternScoreH4 = m_patternH4.GetPatternScore(); // Check proximity to levels ctx.nearSupport = m_levelH4.IsNearSupport(ctx.currentPrice); ctx.nearResistance = m_levelH4.IsNearResistance(ctx.currentPrice); // Prepare neural network inputs (normalized 0-1) double inputs[10]; inputs[0] = (ctx.trendStrengthH1 + 100) / 200.0; // -100 to 100 -> 0 to 1 inputs[1] = (ctx.trendStrengthH4 + 100) / 200.0; inputs[2] = (ctx.trendStrengthD1 + 100) / 200.0; inputs[3] = ctx.volatilityRatio / 3.0; // Normalize assuming max 3x inputs[4] = (patternScoreH1 + 100) / 200.0; inputs[5] = (patternScoreH4 + 100) / 200.0; inputs[6] = ctx.nearSupport ? 1.0 : 0.0; inputs[7] = ctx.nearResistance ? 1.0 : 0.0; inputs[8] = ctx.isNewsTime ? 1.0 : 0.0; inputs[9] = (ctx.usdStrength + 100) / 200.0; // Get neural network decision double outputs[]; m_neuralNet.Forward(inputs, outputs); // outputs[0] = Buy probability // outputs[1] = Neutral probability // outputs[2] = Sell probability // Return decision score: -1 (Strong Sell) to +1 (Strong Buy) double decision = outputs[0] - outputs[2]; return decision; } }; //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| UltraFast_AI_XAUUSD_System.mq5 | //| High-Frequency AI Trading Framework | //| Sub-Second Multi-Factor Analysis | //+------------------------------------------------------------------+ #property copyright "Ultra-Fast AI Gold Trading System" #property version "2.00" #property strict #include #include #include //+------------------------------------------------------------------+ //| INPUT PARAMETERS - Fine-tune for HFT performance | //+------------------------------------------------------------------+ input group "=== CORE SETTINGS ===" input double RiskPercentPerTrade = 1.0; // Risk % per trade input double MaxDailyLoss = 3.0; // Max daily loss % input int MagicNumber = 123456; // EA Magic Number input string TradeComment = "AI_HFT_Gold"; // Trade comment input group "=== HIGH-FREQUENCY SETTINGS ===" input bool EnableSubSecondAnalysis = true; // Enable tick-by-tick analysis input int MinTicksBeforeTrade = 3; // Min ticks for signal confirmation input int MaxSlippagePips = 5; // Max allowed slippage input bool UseMarketExecution = true; // Use instant execution (faster) input int MaxSpreadPips = 30; // Max spread to trade input group "=== MULTI-FACTOR SCORING ===" input double TrendWeight = 30.0; // Trend strength weight % input double VolatilityWeight = 20.0; // Volatility regime weight % input double IndicatorWeight = 25.0; // Indicator confluence weight % input double PatternWeight = 25.0; // Pattern recognition weight % input double MinConfluenceScore = 65.0; // Min score to trade (0-100) input group "=== EXECUTION DISCIPLINE ===" input bool InstantStopLoss = true; // Place SL immediately input double StopLossATRMultiplier = 1.5; // SL = ATR * multiplier input double TakeProfitATRMultiplier = 3.0; // TP = ATR * multiplier input bool UseTrailingStop = true; // Enable trailing stop input double TrailingStopATRMultiplier = 1.0;// Trailing stop distance input group "=== ADVANCED FILTERS ===" input bool FilterHighSpread = true; // Block trades on high spread input bool FilterNewsEvents = true; // Block trades during news input int NewsBufferMinutes = 15; // Minutes before/after news input bool FilterSessionTimes = true; // Trade only in specific sessions input bool AllowLondonSession = true; // Trade during London input bool AllowNYSession = true; // Trade during NY input bool AllowAsianSession = false; // Trade during Asian //+------------------------------------------------------------------+ //| ENUMERATIONS | //+------------------------------------------------------------------+ enum ENUM_MARKET_REGIME { REGIME_STRONG_UPTREND, REGIME_WEAK_UPTREND, REGIME_STRONG_DOWNTREND, REGIME_WEAK_DOWNTREND, REGIME_RANGING, REGIME_BREAKOUT_UP, REGIME_BREAKOUT_DOWN, REGIME_HIGH_VOLATILITY, REGIME_UNKNOWN }; enum ENUM_SIGNAL_STRENGTH { SIGNAL_VERY_STRONG_BUY = 100, SIGNAL_STRONG_BUY = 75, SIGNAL_WEAK_BUY = 50, SIGNAL_NEUTRAL = 0, SIGNAL_WEAK_SELL = -50, SIGNAL_STRONG_SELL = -75, SIGNAL_VERY_STRONG_SELL = -100 }; //+------------------------------------------------------------------+ //| Ultra-Fast Market Context - Optimized for Speed | //+------------------------------------------------------------------+ struct UltraFastContext { // Timing (microsecond precision) datetime lastTickTime; ulong lastTickMicroseconds; int tickCounter; // Price action (immediate) double bid, ask, spread; double lastClose, currentClose; double priceChangeRate; // Price velocity // Market structure ENUM_MARKET_REGIME regime; double trendScore; // -100 to +100 double volatilityScore; // 0 to 100 // Multi-factor scores double indicatorScore; // 0 to 100 double patternScore; // -100 to +100 double confluenceScore; // Final weighted score // Execution context bool canTrade; bool isHighSpread; bool isNewsTime; bool isValidSession; // Risk metrics double atrValue; double dynamicSL; double dynamicTP; void Reset() { tickCounter = 0; regime = REGIME_UNKNOWN; trendScore = 0; volatilityScore = 0; indicatorScore = 0; patternScore = 0; confluenceScore = 0; canTrade = false; } }; //+------------------------------------------------------------------+ //| Ultra-Fast Indicator Engine - Pre-calculated & Cached | //+------------------------------------------------------------------+ class CUltraFastIndicators { private: // Cached handles (initialized once) int h_ema_fast, h_ema_medium, h_ema_slow; int h_rsi, h_macd, h_atr, h_adx; int h_bb, h_stoch; // Cached buffers (updated only on bar change) double cache_ema_fast[3], cache_ema_medium[3], cache_ema_slow[3]; double cache_rsi[3], cache_macd_main[3], cache_macd_signal[3]; double cache_atr[3], cache_adx[3]; double cache_bb_upper[3], cache_bb_lower[3], cache_bb_middle[3]; double cache_stoch_main[3], cache_stoch_signal[3]; // Real-time tick data (updated every tick) double tick_price; double tick_ema_fast; // Exponential smoothing on ticks datetime lastBarTime; string m_symbol; ENUM_TIMEFRAMES m_tf; // Exponential smoothing factor for tick-level EMA double alpha_fast; public: CUltraFastIndicators(string symbol, ENUM_TIMEFRAMES tf = PERIOD_M1) { m_symbol = symbol; m_tf = tf; lastBarTime = 0; tick_ema_fast = 0; alpha_fast = 2.0 / (10.0 + 1.0); // 10-period EMA smoothing InitializeIndicators(); } ~CUltraFastIndicators() { ReleaseIndicators(); } bool InitializeIndicators() { // Initialize all indicators h_ema_fast = iMA(m_symbol, m_tf, 9, 0, MODE_EMA, PRICE_CLOSE); h_ema_medium = iMA(m_symbol, m_tf, 21, 0, MODE_EMA, PRICE_CLOSE); h_ema_slow = iMA(m_symbol, m_tf, 50, 0, MODE_EMA, PRICE_CLOSE); h_rsi = iRSI(m_symbol, m_tf, 14, PRICE_CLOSE); h_macd = iMACD(m_symbol, m_tf, 12, 26, 9, PRICE_CLOSE); h_atr = iATR(m_symbol, m_tf, 14); h_adx = iADX(m_symbol, m_tf, 14); h_bb = iBands(m_symbol, m_tf, 20, 0, 2.0, PRICE_CLOSE); h_stoch = iStochastic(m_symbol, m_tf, 5, 3, 3, MODE_SMA, STO_LOWHIGH); if(h_ema_fast == INVALID_HANDLE || h_rsi == INVALID_HANDLE) { Print("ERROR: Indicator initialization failed!"); return false; } // Pre-fill cache Sleep(100); // Allow indicators to calculate UpdateCache(true); return true; } void ReleaseIndicators() { IndicatorRelease(h_ema_fast); IndicatorRelease(h_ema_medium); IndicatorRelease(h_ema_slow); IndicatorRelease(h_rsi); IndicatorRelease(h_macd); IndicatorRelease(h_atr); IndicatorRelease(h_adx); IndicatorRelease(h_bb); IndicatorRelease(h_stoch); } // Update cache only on new bar (efficient) bool UpdateCache(bool force = false) { datetime currentBarTime = iTime(m_symbol, m_tf, 0); if(!force && currentBarTime == lastBarTime) return false; // No new bar, use cached values lastBarTime = currentBarTime; // Copy all buffers at once (optimized) if(CopyBuffer(h_ema_fast, 0, 0, 3, cache_ema_fast) <= 0) return false; if(CopyBuffer(h_ema_medium, 0, 0, 3, cache_ema_medium) <= 0) return false; if(CopyBuffer(h_ema_slow, 0, 0, 3, cache_ema_slow) <= 0) return false; if(CopyBuffer(h_rsi, 0, 0, 3, cache_rsi) <= 0) return false; if(CopyBuffer(h_macd, 0, 0, 3, cache_macd_main) <= 0) return false; if(CopyBuffer(h_macd, 1, 0, 3, cache_macd_signal) <= 0) return false; if(CopyBuffer(h_atr, 0, 0, 3, cache_atr) <= 0) return false; if(CopyBuffer(h_adx, 0, 0, 3, cache_adx) <= 0) return false; if(CopyBuffer(h_bb, 1, 0, 3, cache_bb_upper) <= 0) return false; if(CopyBuffer(h_bb, 2, 0, 3, cache_bb_lower) <= 0) return false; if(CopyBuffer(h_bb, 0, 0, 3, cache_bb_middle) <= 0) return false; if(CopyBuffer(h_stoch, 0, 0, 3, cache_stoch_main) <= 0) return false; if(CopyBuffer(h_stoch, 1, 0, 3, cache_stoch_signal) <= 0) return false; return true; } // Ultra-fast tick update (sub-millisecond) void UpdateTick(double price) { tick_price = price; // Real-time EMA calculation on ticks if(tick_ema_fast == 0) tick_ema_fast = price; else tick_ema_fast = alpha_fast * price + (1 - alpha_fast) * tick_ema_fast; } // Instant access to cached values (microsecond speed) double GetEMAFast(int shift = 0) { return cache_ema_fast[shift]; } double GetEMAMedium(int shift = 0) { return cache_ema_medium[shift]; } double GetEMASlow(int shift = 0) { return cache_ema_slow[shift]; } double GetRSI(int shift = 0) { return cache_rsi[shift]; } double GetMACD(int shift = 0) { return cache_macd_main[shift]; } double GetMACDSignal(int shift = 0) { return cache_macd_signal[shift]; } double GetATR(int shift = 0) { return cache_atr[shift]; } double GetADX(int shift = 0) { return cache_adx[shift]; } double GetBBUpper(int shift = 0) { return cache_bb_upper[shift]; } double GetBBLower(int shift = 0) { return cache_bb_lower[shift]; } double GetBBMiddle(int shift = 0) { return cache_bb_middle[shift]; } double GetStochMain(int shift = 0) { return cache_stoch_main[shift]; } double GetStochSignal(int shift = 0) { return cache_stoch_signal[shift]; } // Tick-level indicators double GetTickEMA() { return tick_ema_fast; } double GetTickPrice() { return tick_price; } }; //+------------------------------------------------------------------+ //| Ultra-Fast Multi-Factor Analyzer | //+------------------------------------------------------------------+ class CMultiFactorAnalyzer { private: CUltraFastIndicators *indicators; string m_symbol; public: CMultiFactorAnalyzer(string symbol) { m_symbol = symbol; indicators = new CUltraFastIndicators(symbol, PERIOD_M1); } ~CMultiFactorAnalyzer() { delete indicators; } // FACTOR 1: Trend Strength Analysis (-100 to +100) double AnalyzeTrendStrength() { double score = 0; double price = SymbolInfoDouble(m_symbol, SYMBOL_BID); // EMA alignment (50 points max) double ema_fast = indicators.GetEMAFast(); double ema_medium = indicators.GetEMAMedium(); double ema_slow = indicators.GetEMASlow(); if(ema_fast > ema_medium && ema_medium > ema_slow) score += 50; // Perfect bullish alignment else if(ema_fast < ema_medium && ema_medium < ema_slow) score -= 50; // Perfect bearish alignment else score += 0; // Mixed signals // Price position relative to EMAs (30 points max) if(price > ema_fast && price > ema_medium && price > ema_slow) score += 30; else if(price < ema_fast && price < ema_medium && price < ema_slow) score -= 30; // ADX strength confirmation (20 points max) double adx = indicators.GetADX(); if(adx > 25) score *= 1.2; // Boost score in strong trend else if(adx < 15) score *= 0.5; // Reduce score in weak trend return NormalizeDouble(MathMax(-100, MathMin(100, score)), 2); } // FACTOR 2: Volatility Regime Detection (0 to 100) double AnalyzeVolatility() { double atr = indicators.GetATR(); double atr_prev = indicators.GetATR(1); double atr_change = (atr - atr_prev) / atr_prev * 100; // Calculate volatility percentile double score = 50; // Base score // ATR expansion/contraction if(atr_change > 10) score += 30; // Volatility expanding else if(atr_change < -10) score -= 20; // Volatility contracting // Bollinger Band width double bb_upper = indicators.GetBBUpper(); double bb_lower = indicators.GetBBLower(); double bb_width = (bb_upper - bb_lower) / indicators.GetBBMiddle() * 100; if(bb_width > 2.0) score += 20; else if(bb_width < 1.0) score -= 20; return NormalizeDouble(MathMax(0, MathMin(100, score)), 2); } // FACTOR 3: Indicator Confluence Scoring (0 to 100) double AnalyzeIndicatorConfluence() { double score = 0; int bullish_signals = 0; int bearish_signals = 0; // RSI analysis double rsi = indicators.GetRSI(); if(rsi > 50 && rsi < 70) bullish_signals++; else if(rsi < 50 && rsi > 30) bearish_signals++; // MACD analysis double macd = indicators.GetMACD(); double macd_signal = indicators.GetMACDSignal(); if(macd > macd_signal && macd > 0) bullish_signals++; else if(macd < macd_signal && macd < 0) bearish_signals++; // Stochastic analysis double stoch_main = indicators.GetStochMain(); double stoch_signal = indicators.GetStochSignal(); if(stoch_main > stoch_signal && stoch_main < 80) bullish_signals++; else if(stoch_main < stoch_signal && stoch_main > 20) bearish_signals++; // Bollinger Bands position double price = SymbolInfoDouble(m_symbol, SYMBOL_BID); double bb_middle = indicators.GetBBMiddle(); if(price > bb_middle) bullish_signals++; else if(price < bb_middle) bearish_signals++; // Calculate confluence int total_signals = bullish_signals + bearish_signals; if(total_signals > 0) { double confluence_ratio = (double)MathMax(bullish_signals, bearish_signals) / total_signals; score = confluence_ratio * 100; } return NormalizeDouble(score, 2); } // FACTOR 4: Pattern Recognition (-100 to +100) double AnalyzePatterns() { double score = 0; MqlRates rates[]; ArraySetAsSeries(rates, true); if(CopyRates(m_symbol, PERIOD_M1, 0, 5, rates) < 5) return 0; // Bullish Engulfing if(IsBullishEngulfing(rates)) score += 40; // Bearish Engulfing if(IsBearishEngulfing(rates)) score -= 40; // Pin Bar detection int pinBar = DetectPinBar(rates); score += pinBar * 30; // Higher High / Lower Low patterns if(rates[0].high > rates[1].high && rates[1].high > rates[2].high) score += 20; // Bullish momentum else if(rates[0].low < rates[1].low && rates[1].low < rates[2].low) score -= 20; // Bearish momentum return NormalizeDouble(MathMax(-100, MathMin(100, score)), 2); } bool IsBullishEngulfing(MqlRates &rates[]) { return (rates[1].close < rates[1].open && rates[0].close > rates[0].open && rates[0].close > rates[1].open && rates[0].open < rates[1].close); } bool IsBearishEngulfing(MqlRates &rates[]) { return (rates[1].close > rates[1].open && rates[0].close < rates[0].open && rates[0].close < rates[1].open && rates[0].open > rates[1].close); } int DetectPinBar(MqlRates &rates[]) { double body = MathAbs(rates[0].close - rates[0].open); double upperWick = rates[0].high - MathMax(rates[0].close, rates[0].open); double lowerWick = MathMin(rates[0].close, rates[0].open) - rates[0].low; double range = rates[0].high - rates[0].low; if(range == 0) return 0; if(lowerWick > body * 2 && lowerWick > range * 0.6) return 1; // Bullish pin if(upperWick > body * 2 && upperWick > range * 0.6) return -1; // Bearish pin return 0; } // Update indicators (call on new bar only) void UpdateIndicators() { indicators.UpdateCache(); } // Update tick data (call every tick) void UpdateTick(double price) { indicators.UpdateTick(price); } double GetATR() { return indicators.GetATR(); } }; //+------------------------------------------------------------------+ //| Lightning-Fast Execution Engine | //+------------------------------------------------------------------+ class CLightningExecutor { private: CTrade trade; CSymbolInfo symbolInfo; CPositionInfo positionInfo; string m_symbol; int m_magic; public: CLightningExecutor(string symbol, int magic) { m_symbol = symbol; m_magic = magic; trade.SetExpertMagicNumber(m_magic); trade.SetDeviationInPoints(MaxSlippagePips * 10); trade.SetTypeFilling(ORDER_FILLING_IOC); // Immediate or Cancel trade.SetAsyncMode(false); // Synchronous for reliability symbolInfo.Name(m_symbol); } // Execute BUY with instant SL/TP bool ExecuteBuy(double lots, double sl, double tp, string comment) { symbolInfo.Refresh(); double ask = symbolInfo.Ask(); if(!trade.Buy(lots, m_symbol, ask, sl, tp, comment)) { Print("BUY FAILED: ", trade.ResultRetcodeDescription()); return false; } Print("BUY EXECUTED: ", lots, " lots @ ", ask, " | SL:", sl, " TP:", tp); return true; } // Execute SELL with instant SL/TP bool ExecuteSell(double lots, double sl, double tp, string comment) { symbolInfo.Refresh(); double bid = symbolInfo.Bid(); if(!trade.Sell(lots, m_symbol, bid, sl, tp, comment)) { Print("SELL FAILED: ", trade.ResultRetcodeDescription()); return false; } Print("SELL EXECUTED: ", lots, " lots @ ", bid, " | SL:", sl, " TP:", tp); return true; } // Trailing stop implementation void ManageTrailingStop(double atr) { if(!UseTrailingStop) return; for(int i = PositionsTotal() - 1; i >= 0; i--) { if(!positionInfo.SelectByIndex(i)) continue; if(positionInfo.Symbol() != m_symbol || positionInfo.Magic() != m_magic) continue; double trailDistance = atr * TrailingStopATRMultiplier; double currentPrice = positionInfo.Type() == POSITION_TYPE_BUY ? symbolInfo.Bid() : symbolInfo.Ask(); double currentSL = positionInfo.StopLoss(); if(positionInfo.Type() == POSITION_TYPE_BUY) { double newSL = currentPrice - trailDistance; if(newSL > currentSL && newSL < currentPrice) trade.PositionModify(positionInfo.Ticket(), newSL, positionInfo.TakeProfit()); } else { double newSL = currentPrice + trailDistance; if(newSL < currentSL && newSL > currentPrice) trade.PositionModify(positionInfo.Ticket(), newSL, positionInfo.TakeProfit()); } } } bool HasOpenPosition() { for(int i = 0; i < PositionsTotal(); i++) { if(positionInfo.SelectByIndex(i)) { if(positionInfo.Symbol() == m_symbol && positionInfo.Magic() == m_magic) return true; } } return false; } }; //+------------------------------------------------------------------+ //| Main Ultra-Fast Trading Bot | //+------------------------------------------------------------------+ class CUltraFastTradingBot { private: CMultiFactorAnalyzer *analyzer; CLightningExecutor *executor; UltraFastContext ctx; datetime lastBarTime; string m_symbol; public: CUltraFastTradingBot() { m_symbol = _Symbol; analyzer = new CMultiFactorAnalyzer(m_symbol); executor = new CLightningExecutor(m_symbol, MagicNumber); lastBarTime = 0; } ~CUltraFastTradingBot() { delete analyzer; delete executor; } void OnTick() { // Update context ctx.Reset(); ctx.bid = SymbolInfoDouble(m_symbol, SYMBOL_BID); ctx.ask = SymbolInfoDouble(m_symbol, SYMBOL_ASK); ctx.spread = (ctx.ask - ctx.bid) / SymbolInfoDouble(m_symbol, SYMBOL_POINT); // Check if new bar datetime currentBarTime = iTime(m_symbol, PERIOD_M1, 0); if(currentBarTime != lastBarTime) { lastBarTime = currentBarTime; analyzer.UpdateIndicators(); } // Sub-second tick analysis if(EnableSubSecondAnalysis) { analyzer.UpdateTick(ctx.bid); ctx.tickCounter++; } // Pre-flight checks if(!PerformPreflightChecks()) return; // Multi-factor analysis PerformMultiFactorAnalysis(); // Generate and execute signal if(ctx.confluenceScore >= MinConfluenceScore && !executor.HasOpenPosition()) { ExecuteSignal(); } // Manage existing positions executor.ManageTrailingStop(ctx.atrValue); } bool PerformPreflightChecks() { // Spread filter if(FilterHighSpread && ctx.spread > MaxSpreadPips) { ctx.canTrade = false; return false; } // Session filter if(FilterSessionTimes && !IsValidSession()) { ctx.canTrade = false; return false; } // Tick confirmation if(EnableSubSecondAnalysis && ctx.tickCounter < MinTicksBeforeTrade) { ctx.canTrade = false; return false; } ctx.canTrade = true; return true; } void PerformMultiFactorAnalysis() { // Factor 1: Trend ctx.trendScore = analyzer.AnalyzeTrendStrength(); // Factor 2: Volatility ctx.volatilityScore = analyzer.AnalyzeVolatility(); // Factor 3: Indicators ctx.indicatorScore = analyzer.AnalyzeIndicatorConfluence(); // Factor 4: Patterns ctx.patternScore = analyzer.AnalyzePatterns(); // Get ATR ctx.atrValue = analyzer.GetATR(); // Calculate weighted confluence score double trendComponent = (ctx.trendScore + 100) / 2.0 * TrendWeight / 100.0; double volatilityComponent = ctx.volatilityScore * VolatilityWeight / 100.0; double indicatorComponent = ctx.indicatorScore * IndicatorWeight / 100.0; double patternComponent = (ctx.patternScore + 100) / 2.0 * PatternWeight / 100.0; ctx.confluenceScore = trendComponent + volatilityComponent + indicatorComponent + patternComponent; // Determine direction double directionScore = (ctx.trendScore + ctx.patternScore) / 2.0; if(directionScore > 30) ctx.regime = REGIME_STRONG_UPTREND; else if(directionScore < -30) ctx.regime = REGIME_STRONG_DOWNTREND; else ctx.regime = REGIME_RANGING; } void ExecuteSignal() { double lots = CalculatePositionSize(); // Calculate SL/TP if(ctx.regime == REGIME_STRONG_UPTREND) { double sl = ctx.bid - (ctx.atrValue * StopLossATRMultiplier); double tp = ctx.bid + (ctx.atrValue * TakeProfitATRMultiplier); executor.ExecuteBuy(lots, sl, tp, TradeComment); } else if(ctx.regime == REGIME_STRONG_DOWNTREND) { double sl = ctx.ask + (ctx.atrValue * StopLossATRMultiplier); double tp = ctx.ask - (ctx.atrValue * TakeProfitATRMultiplier); executor.ExecuteSell(lots, sl, tp, TradeComment); } } double CalculatePositionSize() { double balance = AccountInfoDouble(ACCOUNT_BALANCE); double riskAmount = balance * RiskPercentPerTrade / 100.0; double slDistance = ctx.atrValue * StopLossATRMultiplier; double tickValue = SymbolInfoDouble(m_symbol, SYMBOL_TRADE_TICK_VALUE); double tickSize = SymbolInfoDouble(m_symbol, SYMBOL_TRADE_TICK_SIZE); double point = SymbolInfoDouble(m_symbol, SYMBOL_POINT); double slValue = slDistance / tickSize * tickValue; double lots = riskAmount / slValue; // Normalize lot size double minLot = SymbolInfoDouble(m_symbol, SYMBOL_VOLUME_MIN); double maxLot = SymbolInfoDouble(m_symbol, SYMBOL_VOLUME_MAX); double lotStep = SymbolInfoDouble(m_symbol, SYMBOL_VOLUME_STEP); lots = MathFloor(lots / lotStep) * lotStep; lots = MathMax(minLot, MathMin(maxLot, lots)); return lots; } bool IsValidSession() { MqlDateTime dt; TimeToStruct(TimeCurrent(), dt); int hour = dt.hour; // London: 08:00-17:00 GMT if(AllowLondonSession && hour >= 8 && hour < 17) return true; // NY: 13:00-22:00 GMT if(AllowNYSession && hour >= 13 && hour < 22) return true; // Asian: 00:00-09:00 GMT if(AllowAsianSession && hour >= 0 && hour < 9) return true; return false; } }; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ CUltraFastTradingBot *bot; int OnInit() { Print("========================================"); Print(" ULTRA-FAST AI GOLD TRADING SYSTEM"); Print(" Sub-Second Multi-Factor Analysis"); Print("========================================"); Print("Confluence Threshold: ", MinConfluenceScore, "%"); Print("Trend Weight: ", TrendWeight, "%"); Print("Volatility Weight: ", VolatilityWeight, "%"); Print("Indicator Weight: ", IndicatorWeight, "%"); Print("Pattern Weight: ", PatternWeight, "%"); Print("========================================"); bot = new CUltraFastTradingBot(); if(bot == NULL) { Print("ERROR: Failed to initialize bot"); return INIT_FAILED; } Print("Bot initialized successfully!"); Print("Waiting for trading signals..."); return INIT_SUCCEEDED; } void OnDeinit(const int reason) { Print("========================================"); Print("EA Stopped. Reason: ", reason); Print("========================================"); delete bot; } void OnTick() { bot.OnTick(); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Dashboard_RiskManagement.mqh | //| Real-Time Performance & Risk Analytics | //+------------------------------------------------------------------+ #include //+------------------------------------------------------------------+ //| Performance Metrics Tracker | //+------------------------------------------------------------------+ class CPerformanceTracker { private: struct TradeRecord { datetime openTime; datetime closeTime; double openPrice; double closePrice; double profit; double lots; int type; // 0=Buy, 1=Sell bool isWin; }; TradeRecord history[]; int totalTrades; int winningTrades; int losingTrades; double totalProfit; double totalLoss; double largestWin; double largestLoss; double currentDrawdown; double maxDrawdown; double initialBalance; double currentBalance; // Daily metrics datetime currentDay; double dailyProfit; int dailyTrades; public: CPerformanceTracker() { Reset(); } void Reset() { totalTrades = 0; winningTrades = 0; losingTrades = 0; totalProfit = 0; totalLoss = 0; largestWin = 0; largestLoss = 0; currentDrawdown = 0; maxDrawdown = 0; initialBalance = AccountInfoDouble(ACCOUNT_BALANCE); currentBalance = initialBalance; dailyProfit = 0; dailyTrades = 0; currentDay = 0; } void RecordTrade(double openPrice, double closePrice, double profit, double lots, int type) { totalTrades++; // Check if new day datetime now = TimeCurrent(); MqlDateTime dt; TimeToStruct(now, dt); datetime today = StringToTime(IntegerToString(dt.year) + "." + IntegerToString(dt.mon) + "." + IntegerToString(dt.day)); if(today != currentDay) { currentDay = today; dailyProfit = 0; dailyTrades = 0; } dailyTrades++; dailyProfit += profit; // Record win/loss if(profit > 0) { winningTrades++; totalProfit += profit; if(profit > largestWin) largestWin = profit; } else if(profit < 0) { losingTrades++; totalLoss += MathAbs(profit); if(MathAbs(profit) > largestLoss) largestLoss = MathAbs(profit); } // Update balance currentBalance += profit; // Calculate drawdown if(currentBalance < initialBalance) { currentDrawdown = (initialBalance - currentBalance) / initialBalance * 100; if(currentDrawdown > maxDrawdown) maxDrawdown = currentDrawdown; } else { currentDrawdown = 0; initialBalance = currentBalance; // New high watermark } } double GetWinRate() { if(totalTrades == 0) return 0; return (double)winningTrades / totalTrades * 100; } double GetProfitFactor() { if(totalLoss == 0) return totalProfit > 0 ? 999 : 0; return totalProfit / totalLoss; } double GetAverageWin() { if(winningTrades == 0) return 0; return totalProfit / winningTrades; } double GetAverageLoss() { if(losingTrades == 0) return 0; return totalLoss / losingTrades; } double GetExpectancy() { if(totalTrades == 0) return 0; return (totalProfit - totalLoss) / totalTrades; } double GetROI() { double startBalance = AccountInfoDouble(ACCOUNT_BALANCE) - (currentBalance - initialBalance); if(startBalance == 0) return 0; return (currentBalance - startBalance) / startBalance * 100; } // Getters int GetTotalTrades() { return totalTrades; } int GetWinningTrades() { return winningTrades; } int GetLosingTrades() { return losingTrades; } double GetTotalProfit() { return totalProfit; } double GetTotalLoss() { return totalLoss; } double GetLargestWin() { return largestWin; } double GetLargestLoss() { return largestLoss; } double GetMaxDrawdown() { return maxDrawdown; } double GetCurrentDrawdown() { return currentDrawdown; } double GetDailyProfit() { return dailyProfit; } int GetDailyTrades() { return dailyTrades; } }; //+------------------------------------------------------------------+ //| Advanced Risk Manager with Real-Time Monitoring | //+------------------------------------------------------------------+ class CAdvancedRiskManager { private: CPerformanceTracker *tracker; // Risk limits double maxDailyLossPercent; double maxDrawdownPercent; double maxPositionSize; // Dynamic risk adjustment bool useAdaptiveRisk; double baseRiskPercent; double currentRiskPercent; // Circuit breaker bool circuitBreakerActive; datetime circuitBreakerUntil; // Correlation monitor double correlationThreshold; public: CAdvancedRiskManager(double dailyLoss, double maxDD, double baseRisk) { tracker = new CPerformanceTracker(); maxDailyLossPercent = dailyLoss; maxDrawdownPercent = maxDD; baseRiskPercent = baseRisk; currentRiskPercent = baseRisk; useAdaptiveRisk = true; circuitBreakerActive = false; } ~CAdvancedRiskManager() { delete tracker; } // Check if trading is allowed bool CanTrade() { // Circuit breaker check if(circuitBreakerActive) { if(TimeCurrent() < circuitBreakerUntil) { Print("CIRCUIT BREAKER ACTIVE - Trading suspended until ", circuitBreakerUntil); return false; } else { circuitBreakerActive = false; Print("Circuit breaker reset - Trading resumed"); } } // Daily loss limit double dailyLoss = -tracker.GetDailyProfit(); double balance = AccountInfoDouble(ACCOUNT_BALANCE); double dailyLossPercent = dailyLoss / balance * 100; if(dailyLossPercent >= maxDailyLossPercent) { ActivateCircuitBreaker(24); // 24 hour suspension Print("DAILY LOSS LIMIT REACHED: ", dailyLossPercent, "% - Circuit breaker activated"); return false; } // Drawdown limit if(tracker.GetCurrentDrawdown() >= maxDrawdownPercent) { ActivateCircuitBreaker(48); // 48 hour suspension Print("MAX DRAWDOWN REACHED: ", tracker.GetCurrentDrawdown(), "% - Circuit breaker activated"); return false; } // Consecutive loss protection if(GetConsecutiveLosses() >= 5) { ActivateCircuitBreaker(6); // 6 hour cooldown Print("5 CONSECUTIVE LOSSES - Cooling down for 6 hours"); return false; } return true; } void ActivateCircuitBreaker(int hours) { circuitBreakerActive = true; circuitBreakerUntil = TimeCurrent() + hours * 3600; } // Adaptive risk calculation double GetCurrentRiskPercent() { if(!useAdaptiveRisk) return baseRiskPercent; // Reduce risk after losses double winRate = tracker.GetWinRate(); double profitFactor = tracker.GetProfitFactor(); currentRiskPercent = baseRiskPercent; // Adjust based on performance if(winRate < 40) currentRiskPercent *= 0.5; // Reduce risk by 50% else if(winRate > 60 && profitFactor > 1.5) currentRiskPercent *= 1.2; // Increase risk by 20% // Drawdown adjustment double dd = tracker.GetCurrentDrawdown(); if(dd > 5) currentRiskPercent *= (1 - dd / 100); // Scale down with drawdown // Keep within bounds currentRiskPercent = MathMax(0.25, MathMin(2.0, currentRiskPercent)); return currentRiskPercent; } int GetConsecutiveLosses() { // Check last 10 positions for consecutive losses int consecutive = 0; for(int i = HistoryDealsTotal() - 1; i >= HistoryDealsTotal() - 10 && i >= 0; i--) { ulong ticket = HistoryDealGetTicket(i); if(ticket == 0) continue; if(HistoryDealGetInteger(ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT) { double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT); if(profit < 0) consecutive++; else break; } } return consecutive; } void RecordTrade(double openPrice, double closePrice, double profit, double lots, int type) { tracker.RecordTrade(openPrice, closePrice, profit, lots, type); } CPerformanceTracker* GetTracker() { return tracker; } }; //+------------------------------------------------------------------+ //| Real-Time Dashboard Display | //+------------------------------------------------------------------+ class CPerformanceDashboard { private: CAdvancedRiskManager *riskManager; // Chart objects CChartObjectLabel lblTitle; CChartObjectLabel lblStats[]; int windowIndex; int xPosition; int yPosition; string prefix; public: CPerformanceDashboard(CAdvancedRiskManager *rm) { riskManager = rm; prefix = "Dashboard_"; windowIndex = 0; xPosition = 10; yPosition = 20; } void Initialize() { // Create title lblTitle.Create(0, prefix + "Title", windowIndex, xPosition, yPosition); lblTitle.Description("═══ AI GOLD SYSTEM PERFORMANCE ═══"); lblTitle.Color(clrYellow); lblTitle.FontSize(10); // Create stat labels ArrayResize(lblStats, 15); string labels[] = { "Total Trades:", "Win Rate:", "Profit Factor:", "Total Profit:", "Max Drawdown:", "Daily P/L:", "Avg Win:", "Avg Loss:", "Expectancy:", "ROI:", "Risk Level:", "Status:", "Largest Win:", "Largest Loss:", "Daily Trades:" }; for(int i = 0; i < 15; i++) { lblStats[i].Create(0, prefix + "Stat" + IntegerToString(i), windowIndex, xPosition, yPosition + 30 + (i * 18)); lblStats[i].Description(labels[i]); lblStats[i].Color(clrWhite); lblStats[i].FontSize(8); } } void Update() { CPerformanceTracker *tracker = riskManager.GetTracker(); UpdateLabel(0, "Total Trades: " + IntegerToString(tracker.GetTotalTrades())); UpdateLabel(1, "Win Rate: " + DoubleToString(tracker.GetWinRate(), 1) + "%", tracker.GetWinRate() >= 50 ? clrLime : clrRed); UpdateLabel(2, "Profit Factor: " + DoubleToString(tracker.GetProfitFactor(), 2), tracker.GetProfitFactor() >= 1.5 ? clrLime : clrOrange); UpdateLabel(3, "Total Profit: $" + DoubleToString(tracker.GetTotalProfit(), 2), tracker.GetTotalProfit() > 0 ? clrLime : clrRed); UpdateLabel(4, "Max DD: " + DoubleToString(tracker.GetMaxDrawdown(), 2) + "%", tracker.GetMaxDrawdown() < 10 ? clrLime : clrRed); UpdateLabel(5, "Daily P/L: $" + DoubleToString(tracker.GetDailyProfit(), 2), tracker.GetDailyProfit() > 0 ? clrLime : clrRed); UpdateLabel(6, "Avg Win: $" + DoubleToString(tracker.GetAverageWin(), 2)); UpdateLabel(7, "Avg Loss: $" + DoubleToString(tracker.GetAverageLoss(), 2)); UpdateLabel(8, "Expectancy: $" + DoubleToString(tracker.GetExpectancy(), 2), tracker.GetExpectancy() > 0 ? clrLime : clrRed); UpdateLabel(9, "ROI: " + DoubleToString(tracker.GetROI(), 2) + "%", tracker.GetROI() > 0 ? clrLime : clrRed); UpdateLabel(10, "Risk Level: " + DoubleToString(riskManager.GetCurrentRiskPercent(), 2) + "%"); UpdateLabel(11, riskManager.CanTrade() ? "Status: ACTIVE" : "Status: SUSPENDED", riskManager.CanTrade() ? clrLime : clrRed); UpdateLabel(12, "Largest Win: $" + DoubleToString(tracker.GetLargestWin(), 2)); UpdateLabel(13, "Largest Loss: $" + DoubleToString(tracker.GetLargestLoss(), 2)); UpdateLabel(14, "Daily Trades: " + IntegerToString(tracker.GetDailyTrades())); } void UpdateLabel(int index, string text, color clr = clrWhite) { if(index >= 0 && index < ArraySize(lblStats)) { lblStats[index].Description(text); lblStats[index].Color(clr); } } void Destroy() { lblTitle.Delete(); for(int i = 0; i < ArraySize(lblStats); i++) lblStats[i].Delete(); } }; //+------------------------------------------------------------------+ //| Signal Quality Analyzer - Pre-Trade Validation | //+------------------------------------------------------------------+ class CSignalQualityAnalyzer { private: double qualityThreshold; public: CSignalQualityAnalyzer(double threshold = 70.0) { qualityThreshold = threshold; } // Comprehensive signal quality scoring (0-100) double AnalyzeSignalQuality(double trendScore, double volatilityScore, double indicatorScore, double patternScore, double atr, double spread) { double quality = 0; // 1. Trend alignment (30 points) if(MathAbs(trendScore) > 70) quality += 30; else if(MathAbs(trendScore) > 40) quality += 15; // 2. Volatility appropriateness (20 points) if(volatilityScore > 40 && volatilityScore < 80) quality += 20; // Ideal volatility else if(volatilityScore > 80) quality += 5; // Too volatile // 3. Indicator confluence (25 points) quality += indicatorScore * 0.25; // 4. Pattern strength (25 points) if(MathAbs(patternScore) > 60) quality += 25; else if(MathAbs(patternScore) > 30) quality += 12; // 5. Spread penalty if(spread > 20) quality *= 0.8; // 20% penalty return NormalizeDouble(quality, 2); } bool IsHighQualitySignal(double quality) { return quality >= qualityThreshold; } }; //+------------------------------------------------------------------+