//+------------------------------------------------------------------+ //| EntrySystem.mqh v3.0 | //| Optimized Entry Signal Generation System | //| Future-Proofed Architecture | //+------------------------------------------------------------------+ #ifndef ENTRY_SYSTEM_MQH #define ENTRY_SYSTEM_MQH #include "DataTypes.mqh" #include //+------------------------------------------------------------------+ //| Entry System Interface - For Future Extensions | //+------------------------------------------------------------------+ interface IEntryStrategy { EntrySignal CheckSignal(const MarketConditions &market); bool ValidateSignal(const EntrySignal &signal); void UpdatePerformance(bool success); }; //+------------------------------------------------------------------+ //| Entry System Class - Optimized & Extensible | //+------------------------------------------------------------------+ class CEntrySystem { private: //--- Configuration EntrySystemConfig m_config; //--- Indicator Management Structure struct IndicatorSet { int ma_fast; int ma_slow; int ma_filter; int rsi; int adx; int bb; int macd; int stoch; int atr; void Initialize() { ma_fast = INVALID_HANDLE; ma_slow = INVALID_HANDLE; ma_filter = INVALID_HANDLE; rsi = INVALID_HANDLE; adx = INVALID_HANDLE; bb = INVALID_HANDLE; macd = INVALID_HANDLE; stoch = INVALID_HANDLE; atr = INVALID_HANDLE; } void Release() { if(ma_fast != INVALID_HANDLE) IndicatorRelease(ma_fast); if(ma_slow != INVALID_HANDLE) IndicatorRelease(ma_slow); if(ma_filter != INVALID_HANDLE) IndicatorRelease(ma_filter); if(rsi != INVALID_HANDLE) IndicatorRelease(rsi); if(adx != INVALID_HANDLE) IndicatorRelease(adx); if(bb != INVALID_HANDLE) IndicatorRelease(bb); if(macd != INVALID_HANDLE) IndicatorRelease(macd); if(stoch != INVALID_HANDLE) IndicatorRelease(stoch); if(atr != INVALID_HANDLE) IndicatorRelease(atr); } }; IndicatorSet m_indicators; //--- Buffer Management struct BufferCache { double ma_fast[3]; double ma_slow[3]; double ma_filter[1]; double rsi[3]; double adx[3]; double bb_upper[3]; double bb_lower[3]; double bb_middle[3]; double macd_main[3]; double macd_signal[3]; double atr[1]; datetime last_update; void Reset() { ArrayInitialize(ma_fast, 0); ArrayInitialize(ma_slow, 0); ArrayInitialize(ma_filter, 0); ArrayInitialize(rsi, 0); ArrayInitialize(adx, 0); ArrayInitialize(bb_upper, 0); ArrayInitialize(bb_lower, 0); ArrayInitialize(bb_middle, 0); ArrayInitialize(macd_main, 0); ArrayInitialize(macd_signal, 0); ArrayInitialize(atr, 0); last_update = 0; } }; BufferCache m_buffers; //--- Signal Tracking struct SignalTracker { datetime last_signal_time; ENUM_SIGNAL_TYPE last_signal_type; int consecutive_signals; int signals_generated; int signals_filtered; double signal_accuracy; void Reset() { last_signal_time = 0; last_signal_type = SIGNAL_NONE; consecutive_signals = 0; signals_generated = 0; signals_filtered = 0; signal_accuracy = 0; } }; SignalTracker m_tracker; //--- Performance Metrics struct PerformanceData { int total_signals; int successful_signals; double avg_confidence; double avg_rr_achieved; datetime best_signal_time; datetime worst_signal_time; void Reset() { total_signals = 0; successful_signals = 0; avg_confidence = 0; avg_rr_achieved = 0; best_signal_time = 0; worst_signal_time = 0; } }; PerformanceData m_performance; //--- Cache Management struct SignalCache { EntrySignal signal; datetime bar_time; bool valid; void Invalidate() { valid = false; } bool IsValid(datetime current_bar) { return valid && bar_time == current_bar; } }; SignalCache m_cache; //--- Time Management datetime m_last_bar_time; bool m_new_bar; //--- Strategy Methods EntrySignal ExecuteMACrossStrategy(const MarketConditions &market); EntrySignal ExecuteMomentumStrategy(const MarketConditions &market); EntrySignal ExecuteBreakoutStrategy(const MarketConditions &market); EntrySignal ExecuteMeanReversionStrategy(const MarketConditions &market); EntrySignal ExecuteContrarianStrategy(const MarketConditions &market); EntrySignal ExecuteMultiStrategy(const MarketConditions &market); EntrySignal ExecuteCustomStrategy(const MarketConditions &market); //--- Helper Methods bool LoadIndicators(); bool UpdateBuffers(); bool IsNewBar(); bool ValidateMarketHours(); bool CheckNewsFilter(const MarketConditions &market); double CalculateSignalScore(const EntrySignal &signal, const MarketConditions &market); void EnhanceSignalWithContext(EntrySignal &signal, const MarketConditions &market); void OptimizeStopTargets(EntrySignal &signal, const MarketConditions &market); double GetATR(); //--- Validation Methods bool ValidateConfiguration(); bool ValidateMarketConditions(const MarketConditions &market); bool ValidateSignalQuality(const EntrySignal &signal, const MarketConditions &market); //--- Utility Methods void LogSignal(const EntrySignal &signal); void UpdateStatistics(const EntrySignal &signal); KeyLevel ConvertSRToKeyLevel(const SRLevel &sr); public: CEntrySystem(); ~CEntrySystem(); //--- Initialization bool Initialize(ENUM_ENTRY_MODE mode, bool enable_multiple = false, int max_positions = 1); bool Initialize(const EntrySystemConfig &config); void Reset(); //--- Main Interface EntrySignal CheckForEntry(const MarketConditions &market); bool ValidateEntry(const EntrySignal &signal, const MarketConditions &market); //--- Configuration void SetConfiguration(const EntrySystemConfig &config); EntrySystemConfig GetConfiguration() const { return m_config; } //--- Performance void UpdatePerformance(ulong ticket, bool success, double rr_achieved); double GetSignalAccuracy() const { return m_tracker.signal_accuracy; } int GetTotalSignals() const { return m_tracker.signals_generated; } int GetFilteredSignals() const { return m_tracker.signals_filtered; } //--- Status bool IsReady() const; datetime GetLastSignalTime() const { return m_tracker.last_signal_time; } ENUM_SIGNAL_TYPE GetLastSignalType() const { return m_tracker.last_signal_type; } //--- Diagnostics string GetStatus(); void PrintDiagnostics(); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CEntrySystem::CEntrySystem() { m_indicators.Initialize(); m_buffers.Reset(); m_tracker.Reset(); m_performance.Reset(); m_cache.Invalidate(); m_last_bar_time = 0; m_new_bar = false; //--- Default configuration m_config.entry_mode = ENTRY_MA_CROSS; m_config.enable_multiple = false; m_config.max_positions = 1; m_config.min_time_between = 60; m_config.signal_threshold = 60; m_config.use_market_hours = true; m_config.start_hour = 8; m_config.end_hour = 20; m_config.friday_close = true; m_config.filter_news = true; m_config.min_rr_ratio = 1.5; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CEntrySystem::~CEntrySystem() { m_indicators.Release(); } //+------------------------------------------------------------------+ //| Initialize with simple parameters | //+------------------------------------------------------------------+ bool CEntrySystem::Initialize(ENUM_ENTRY_MODE mode, bool enable_multiple = false, int max_positions = 1) { m_config.entry_mode = mode; m_config.enable_multiple = enable_multiple; m_config.max_positions = max_positions; return Initialize(m_config); } //+------------------------------------------------------------------+ //| Initialize with full configuration | //+------------------------------------------------------------------+ bool CEntrySystem::Initialize(const EntrySystemConfig &config) { m_config = config; //--- Validate configuration if(!ValidateConfiguration()) { Print("EntrySystem: Invalid configuration"); return false; } //--- Load required indicators if(!LoadIndicators()) { Print("EntrySystem: Failed to load indicators"); return false; } //--- Reset tracking m_tracker.Reset(); m_performance.Reset(); m_cache.Invalidate(); Print("EntrySystem initialized successfully: ", EnumToString(m_config.entry_mode)); return true; } //+------------------------------------------------------------------+ //| Load indicators based on strategy | //+------------------------------------------------------------------+ bool CEntrySystem::LoadIndicators() { //--- Always create ATR for stops m_indicators.atr = iATR(_Symbol, PERIOD_CURRENT, 14); if(m_indicators.atr == INVALID_HANDLE) { Print("EntrySystem: Failed to create ATR indicator"); return false; } //--- Load strategy-specific indicators switch(m_config.entry_mode) { case ENTRY_MA_CROSS: case ENTRY_MA_PULLBACK: m_indicators.ma_fast = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE); m_indicators.ma_slow = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_EMA, PRICE_CLOSE); m_indicators.ma_filter = iMA(_Symbol, PERIOD_CURRENT, 200, 0, MODE_SMA, PRICE_CLOSE); if(m_indicators.ma_fast == INVALID_HANDLE || m_indicators.ma_slow == INVALID_HANDLE) return false; break; case ENTRY_MOMENTUM: m_indicators.rsi = iRSI(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE); m_indicators.adx = iADX(_Symbol, PERIOD_CURRENT, 14); m_indicators.macd = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE); if(m_indicators.rsi == INVALID_HANDLE || m_indicators.adx == INVALID_HANDLE || m_indicators.macd == INVALID_HANDLE) return false; break; case ENTRY_BREAKOUT: case ENTRY_MEAN_REVERSION: m_indicators.bb = iBands(_Symbol, PERIOD_CURRENT, 20, 0, 2.0, PRICE_CLOSE); m_indicators.rsi = iRSI(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE); if(m_config.entry_mode == ENTRY_BREAKOUT) m_indicators.adx = iADX(_Symbol, PERIOD_CURRENT, 14); if(m_indicators.bb == INVALID_HANDLE || m_indicators.rsi == INVALID_HANDLE) return false; break; case ENTRY_MULTI_STRATEGY: //--- Load all indicators for multi-strategy m_indicators.ma_fast = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE); m_indicators.ma_slow = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_EMA, PRICE_CLOSE); m_indicators.ma_filter = iMA(_Symbol, PERIOD_CURRENT, 200, 0, MODE_SMA, PRICE_CLOSE); m_indicators.rsi = iRSI(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE); m_indicators.adx = iADX(_Symbol, PERIOD_CURRENT, 14); m_indicators.bb = iBands(_Symbol, PERIOD_CURRENT, 20, 0, 2.0, PRICE_CLOSE); m_indicators.macd = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE); m_indicators.stoch = iStochastic(_Symbol, PERIOD_CURRENT, 5, 3, 3, MODE_SMA, STO_LOWHIGH); if(m_indicators.ma_fast == INVALID_HANDLE || m_indicators.rsi == INVALID_HANDLE || m_indicators.bb == INVALID_HANDLE) return false; break; case ENTRY_CONTRARIAN: m_indicators.rsi = iRSI(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE); m_indicators.bb = iBands(_Symbol, PERIOD_CURRENT, 20, 0, 2.0, PRICE_CLOSE); m_indicators.stoch = iStochastic(_Symbol, PERIOD_CURRENT, 5, 3, 3, MODE_SMA, STO_LOWHIGH); if(m_indicators.rsi == INVALID_HANDLE || m_indicators.bb == INVALID_HANDLE) return false; break; case ENTRY_CUSTOM: //--- Custom strategy - load minimal indicators m_indicators.rsi = iRSI(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE); break; } return true; } //+------------------------------------------------------------------+ //| Main entry check method | //+------------------------------------------------------------------+ EntrySignal CEntrySystem::CheckForEntry(const MarketConditions &market) { //--- Check cache validity datetime current_bar = iTime(_Symbol, PERIOD_CURRENT, 0); if(m_cache.IsValid(current_bar)) { return m_cache.signal; } //--- Initialize empty signal EntrySignal signal; signal.signal_type = SIGNAL_NONE; signal.entry_price = 0; signal.stop_loss_distance = 0; signal.take_profit_distance = 0; signal.confidence = 0; signal.comment = ""; signal.signal_time = TimeCurrent(); signal.timeframe = Period(); signal.atr_value = 0; signal.spread_value = 0; signal.expected_rr = 0; signal.suggested_risk = 0; //--- Initialize key levels for(int i = 0; i < 5; i++) { signal.key_levels[i].price = 0; signal.key_levels[i].type = ""; signal.key_levels[i].strength = 0; signal.key_levels[i].created = 0; } //--- Validate market conditions if(!ValidateMarketConditions(market)) { return signal; } //--- Check market hours if(!ValidateMarketHours()) { return signal; } //--- Check time since last signal if(TimeCurrent() - m_tracker.last_signal_time < m_config.min_time_between * 60) { return signal; } //--- Check for new bar m_new_bar = IsNewBar(); //--- Update buffers if needed if(m_new_bar || m_config.entry_mode == ENTRY_BREAKOUT) { if(!UpdateBuffers()) { Print("EntrySystem: Failed to update buffers"); return signal; } } //--- Execute strategy switch(m_config.entry_mode) { case ENTRY_MA_CROSS: case ENTRY_MA_PULLBACK: signal = ExecuteMACrossStrategy(market); break; case ENTRY_MOMENTUM: signal = ExecuteMomentumStrategy(market); break; case ENTRY_BREAKOUT: signal = ExecuteBreakoutStrategy(market); break; case ENTRY_MEAN_REVERSION: signal = ExecuteMeanReversionStrategy(market); break; case ENTRY_CONTRARIAN: signal = ExecuteContrarianStrategy(market); break; case ENTRY_MULTI_STRATEGY: signal = ExecuteMultiStrategy(market); break; case ENTRY_CUSTOM: signal = ExecuteCustomStrategy(market); break; } //--- Process valid signals if(signal.signal_type != SIGNAL_NONE) { m_tracker.signals_generated++; //--- Enhance signal with context EnhanceSignalWithContext(signal, market); //--- Optimize stops and targets OptimizeStopTargets(signal, market); //--- Calculate final score signal.confidence = CalculateSignalScore(signal, market); //--- Apply threshold filter if(signal.confidence < m_config.signal_threshold) { m_tracker.signals_filtered++; signal.signal_type = SIGNAL_NONE; return signal; } //--- Final validation if(ValidateSignalQuality(signal, market)) { //--- Update tracking m_tracker.last_signal_time = TimeCurrent(); m_tracker.last_signal_type = signal.signal_type; if(signal.signal_type == m_tracker.last_signal_type) m_tracker.consecutive_signals++; else m_tracker.consecutive_signals = 1; //--- Cache the signal m_cache.signal = signal; m_cache.bar_time = current_bar; m_cache.valid = true; //--- Log and update statistics LogSignal(signal); UpdateStatistics(signal); } else { m_tracker.signals_filtered++; signal.signal_type = SIGNAL_NONE; } } return signal; } //+------------------------------------------------------------------+ //| MA Crossover Strategy | //+------------------------------------------------------------------+ EntrySignal CEntrySystem::ExecuteMACrossStrategy(const MarketConditions &market) { EntrySignal signal; signal.signal_type = SIGNAL_NONE; //--- Check for valid buffers if(m_buffers.ma_fast[0] == 0 || m_buffers.ma_slow[0] == 0) return signal; //--- Detect crossover bool bullish_cross = (m_buffers.ma_fast[2] <= m_buffers.ma_slow[2] && m_buffers.ma_fast[1] > m_buffers.ma_slow[1]); bool bearish_cross = (m_buffers.ma_fast[2] >= m_buffers.ma_slow[2] && m_buffers.ma_fast[1] < m_buffers.ma_slow[1]); //--- Apply filter if available double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID); bool above_filter = (m_buffers.ma_filter[0] == 0) || (current_price > m_buffers.ma_filter[0]); bool below_filter = (m_buffers.ma_filter[0] == 0) || (current_price < m_buffers.ma_filter[0]); //--- Generate signal if(bullish_cross && above_filter) { signal.signal_type = SIGNAL_BUY; signal.entry_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); signal.comment = "MA Bullish Cross"; signal.confidence = 70; //--- Calculate crossover strength double cross_angle = MathAbs(m_buffers.ma_fast[1] - m_buffers.ma_slow[1]) / _Point; if(cross_angle > 20) signal.confidence += 10; if(cross_angle > 50) signal.confidence += 10; } else if(bearish_cross && below_filter) { signal.signal_type = SIGNAL_SELL; signal.entry_price = SymbolInfoDouble(_Symbol, SYMBOL_BID); signal.comment = "MA Bearish Cross"; signal.confidence = 70; double cross_angle = MathAbs(m_buffers.ma_fast[1] - m_buffers.ma_slow[1]) / _Point; if(cross_angle > 20) signal.confidence += 10; if(cross_angle > 50) signal.confidence += 10; } //--- Set initial stops if(signal.signal_type != SIGNAL_NONE) { double atr = GetATR(); signal.stop_loss_distance = atr * 2.0; signal.take_profit_distance = atr * 3.0; signal.atr_value = atr; } return signal; } //+------------------------------------------------------------------+ //| Momentum Strategy | //+------------------------------------------------------------------+ EntrySignal CEntrySystem::ExecuteMomentumStrategy(const MarketConditions &market) { EntrySignal signal; signal.signal_type = SIGNAL_NONE; //--- Check ADX for trend strength if(m_buffers.adx[0] < 25) return signal; //--- Get directional indicators double di_plus = m_buffers.adx[1]; double di_minus = m_buffers.adx[2]; //--- Bullish momentum if(m_buffers.rsi[0] > 50 && m_buffers.rsi[0] < 70 && m_buffers.rsi[0] > m_buffers.rsi[1] && di_plus > di_minus && m_buffers.macd_main[0] > m_buffers.macd_signal[0]) { signal.signal_type = SIGNAL_BUY; signal.entry_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); signal.comment = "Momentum Buy"; signal.confidence = 60; signal.confidence += (m_buffers.adx[0] - 25) * 0.8; signal.confidence += (m_buffers.rsi[0] - 50) * 0.3; signal.confidence = MathMin(signal.confidence, 95); } //--- Bearish momentum else if(m_buffers.rsi[0] < 50 && m_buffers.rsi[0] > 30 && m_buffers.rsi[0] < m_buffers.rsi[1] && di_minus > di_plus && m_buffers.macd_main[0] < m_buffers.macd_signal[0]) { signal.signal_type = SIGNAL_SELL; signal.entry_price = SymbolInfoDouble(_Symbol, SYMBOL_BID); signal.comment = "Momentum Sell"; signal.confidence = 60; signal.confidence += (m_buffers.adx[0] - 25) * 0.8; signal.confidence += (50 - m_buffers.rsi[0]) * 0.3; signal.confidence = MathMin(signal.confidence, 95); } //--- Set stops based on momentum strength if(signal.signal_type != SIGNAL_NONE) { double atr = GetATR(); double stop_multiplier = (m_buffers.adx[0] > 40) ? 1.5 : 2.0; double target_multiplier = (m_buffers.adx[0] > 40) ? 4.0 : 3.0; signal.stop_loss_distance = atr * stop_multiplier; signal.take_profit_distance = atr * target_multiplier; signal.atr_value = atr; } return signal; } //+------------------------------------------------------------------+ //| Update indicator buffers | //+------------------------------------------------------------------+ bool CEntrySystem::UpdateBuffers() { //--- Check if update needed (cache for 1 second) if(TimeCurrent() - m_buffers.last_update < 1) return true; bool success = true; //--- Update ATR if(m_indicators.atr != INVALID_HANDLE) { if(CopyBuffer(m_indicators.atr, 0, 0, 1, m_buffers.atr) < 1) success = false; } //--- Update MA buffers if(m_indicators.ma_fast != INVALID_HANDLE) { if(CopyBuffer(m_indicators.ma_fast, 0, 0, 3, m_buffers.ma_fast) < 3) success = false; } if(m_indicators.ma_slow != INVALID_HANDLE) { if(CopyBuffer(m_indicators.ma_slow, 0, 0, 3, m_buffers.ma_slow) < 3) success = false; } if(m_indicators.ma_filter != INVALID_HANDLE) { if(CopyBuffer(m_indicators.ma_filter, 0, 0, 1, m_buffers.ma_filter) < 1) success = false; } //--- Update RSI if(m_indicators.rsi != INVALID_HANDLE) { if(CopyBuffer(m_indicators.rsi, 0, 0, 3, m_buffers.rsi) < 3) success = false; } //--- Update ADX if(m_indicators.adx != INVALID_HANDLE) { if(CopyBuffer(m_indicators.adx, 0, 0, 3, m_buffers.adx) < 3) success = false; } //--- Update Bollinger Bands if(m_indicators.bb != INVALID_HANDLE) { CopyBuffer(m_indicators.bb, 0, 0, 3, m_buffers.bb_middle); CopyBuffer(m_indicators.bb, 1, 0, 3, m_buffers.bb_upper); CopyBuffer(m_indicators.bb, 2, 0, 3, m_buffers.bb_lower); } //--- Update MACD if(m_indicators.macd != INVALID_HANDLE) { CopyBuffer(m_indicators.macd, 0, 0, 3, m_buffers.macd_main); CopyBuffer(m_indicators.macd, 1, 0, 3, m_buffers.macd_signal); } m_buffers.last_update = TimeCurrent(); return success; } //+------------------------------------------------------------------+ //| Get ATR value | //+------------------------------------------------------------------+ double CEntrySystem::GetATR() { if(m_buffers.atr[0] > 0) return m_buffers.atr[0]; //--- Fallback calculation double sum = 0; for(int i = 1; i <= 14; i++) { double high = iHigh(_Symbol, PERIOD_CURRENT, i); double low = iLow(_Symbol, PERIOD_CURRENT, i); double prev_close = iClose(_Symbol, PERIOD_CURRENT, i + 1); double tr = MathMax(high - low, MathMax(MathAbs(high - prev_close), MathAbs(low - prev_close))); sum += tr; } double atr = sum / 14.0; //--- Ensure valid value if(atr <= 0) atr = 50 * SymbolInfoDouble(_Symbol, SYMBOL_POINT); return atr; } //+------------------------------------------------------------------+ //| Enhance signal with market context | //+------------------------------------------------------------------+ void CEntrySystem::EnhanceSignalWithContext(EntrySignal &signal, const MarketConditions &market) { signal.atr_value = GetATR(); signal.spread_value = market.spread; //--- Add nearest key levels (properly convert SRLevel to KeyLevel) int levels_added = 0; for(int i = 0; i < market.sr_count && i < 10 && levels_added < 5; i++) { double level_distance = MathAbs(signal.entry_price - market.sr_levels[i].price); if(level_distance < signal.atr_value * 2) { signal.key_levels[levels_added] = ConvertSRToKeyLevel(market.sr_levels[i]); levels_added++; } } //--- Calculate expected R:R if(signal.stop_loss_distance > 0) signal.expected_rr = signal.take_profit_distance / signal.stop_loss_distance; else signal.expected_rr = 0; //--- Suggest risk based on confidence if(signal.confidence >= 80) signal.suggested_risk = 2.0; else if(signal.confidence >= 60) signal.suggested_risk = 1.0; else signal.suggested_risk = 0.5; } //+------------------------------------------------------------------+ //| Convert SR level to Key level | //+------------------------------------------------------------------+ KeyLevel CEntrySystem::ConvertSRToKeyLevel(const SRLevel &sr) { KeyLevel key; key.price = sr.price; key.strength = sr.strength; key.created = sr.last_touch; key.type = sr.is_support ? "Support" : "Resistance"; return key; } //+------------------------------------------------------------------+ //| Optimize stop and target distances | //+------------------------------------------------------------------+ void CEntrySystem::OptimizeStopTargets(EntrySignal &signal, const MarketConditions &market) { //--- Minimum stop distance double min_stop = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * SymbolInfoDouble(_Symbol, SYMBOL_POINT) * 1.1; //--- Adjust for market conditions double volatility_factor = 1.0; switch(market.condition) { case MARKET_VOLATILE: volatility_factor = 1.3; break; case MARKET_QUIET: volatility_factor = 0.8; break; case MARKET_TRENDING: case MARKET_TRENDING_UP: case MARKET_TRENDING_DOWN: volatility_factor = 1.1; break; } //--- Apply adjustments signal.stop_loss_distance *= volatility_factor; signal.take_profit_distance *= volatility_factor; //--- Ensure minimums signal.stop_loss_distance = MathMax(signal.stop_loss_distance, min_stop); signal.take_profit_distance = MathMax(signal.take_profit_distance, min_stop); //--- Ensure minimum R:R if(m_config.min_rr_ratio > 0) { double min_tp = signal.stop_loss_distance * m_config.min_rr_ratio; signal.take_profit_distance = MathMax(signal.take_profit_distance, min_tp); } //--- Normalize to point signal.stop_loss_distance = NormalizeDouble(signal.stop_loss_distance, _Digits); signal.take_profit_distance = NormalizeDouble(signal.take_profit_distance, _Digits); } //+------------------------------------------------------------------+ //| Calculate signal score | //+------------------------------------------------------------------+ double CEntrySystem::CalculateSignalScore(const EntrySignal &signal, const MarketConditions &market) { double score = signal.confidence; //--- Market alignment bonus if((signal.signal_type == SIGNAL_BUY && (market.condition == MARKET_TRENDING_UP || market.condition == MARKET_TRENDING)) || (signal.signal_type == SIGNAL_SELL && (market.condition == MARKET_TRENDING_DOWN || market.condition == MARKET_TRENDING))) { score += 10; } //--- Trend strength bonus if(MathAbs(market.trend_strength) > 30) score += 5; if(MathAbs(market.trend_strength) > 50) score += 5; //--- Volatility adjustment if(market.volatility_percentile > 80) score -= 5; else if(market.volatility_percentile < 20) score += 5; //--- Support/Resistance proximity bonus for(int i = 0; i < market.sr_count && i < 10; i++) { double distance = MathAbs(signal.entry_price - market.sr_levels[i].price); if(distance < market.atr * 0.5) { score += market.sr_levels[i].strength / 20.0; } } return MathMin(score, 100); } //+------------------------------------------------------------------+ //| Validate signal quality | //+------------------------------------------------------------------+ bool CEntrySystem::ValidateSignalQuality(const EntrySignal &signal, const MarketConditions &market) { //--- Check stop/target validity if(signal.stop_loss_distance <= 0 || signal.take_profit_distance <= 0) return false; //--- Check spread double max_spread = signal.stop_loss_distance * 0.2; if(market.spread > max_spread) return false; //--- Check news filter if(m_config.filter_news && market.news_event) return false; //--- Check R:R ratio double rr_ratio = signal.take_profit_distance / signal.stop_loss_distance; if(m_config.min_rr_ratio > 0 && rr_ratio < m_config.min_rr_ratio) return false; //--- Strategy-specific validation if(m_config.entry_mode == ENTRY_MOMENTUM && (market.condition == MARKET_RANGING || market.condition == MARKET_QUIET)) return false; if(m_config.entry_mode == ENTRY_MEAN_REVERSION && (market.condition == MARKET_TRENDING_UP || market.condition == MARKET_TRENDING_DOWN)) return false; return true; } //+------------------------------------------------------------------+ //| Validate market conditions | //+------------------------------------------------------------------+ bool CEntrySystem::ValidateMarketConditions(const MarketConditions &market) { if(market.volatility <= 0) return false; if(market.atr <= 0) return false; if(market.spread < 0) return false; return true; } //+------------------------------------------------------------------+ //| Validate configuration | //+------------------------------------------------------------------+ bool CEntrySystem::ValidateConfiguration() { if(m_config.max_positions <= 0) m_config.max_positions = 1; if(m_config.min_time_between < 0) m_config.min_time_between = 0; if(m_config.signal_threshold < 0) m_config.signal_threshold = 0; if(m_config.signal_threshold > 100) m_config.signal_threshold = 100; if(m_config.start_hour < 0 || m_config.start_hour > 23) m_config.start_hour = 0; if(m_config.end_hour < 1 || m_config.end_hour > 24) m_config.end_hour = 24; if(m_config.min_rr_ratio < 0) m_config.min_rr_ratio = 0; return true; } //+------------------------------------------------------------------+ //| Check if new bar | //+------------------------------------------------------------------+ bool CEntrySystem::IsNewBar() { datetime current_bar_time = iTime(_Symbol, PERIOD_CURRENT, 0); if(current_bar_time != m_last_bar_time) { m_last_bar_time = current_bar_time; return true; } return false; } //+------------------------------------------------------------------+ //| Validate market hours | //+------------------------------------------------------------------+ bool CEntrySystem::ValidateMarketHours() { if(!m_config.use_market_hours) return true; MqlDateTime current_time; TimeCurrent(current_time); //--- Weekend check if(current_time.day_of_week == 0 || current_time.day_of_week == 6) return false; //--- Friday close if(m_config.friday_close && current_time.day_of_week == 5 && current_time.hour >= 20) return false; //--- Trading hours if(current_time.hour < m_config.start_hour || current_time.hour >= m_config.end_hour) return false; return true; } //+------------------------------------------------------------------+ //| Log signal details | //+------------------------------------------------------------------+ void CEntrySystem::LogSignal(const EntrySignal &signal) { Print("EntrySystem Signal: ", signal.comment, " | Type: ", SignalTypeToString(signal.signal_type), " | Confidence: ", DoubleToString(signal.confidence, 1), "%", " | R:R: ", DoubleToString(signal.expected_rr, 2), " | Risk: ", DoubleToString(signal.suggested_risk, 1), "%"); } //+------------------------------------------------------------------+ //| Update statistics | //+------------------------------------------------------------------+ void CEntrySystem::UpdateStatistics(const EntrySignal &signal) { m_performance.total_signals++; m_performance.avg_confidence = (m_performance.avg_confidence * (m_performance.total_signals - 1) + signal.confidence) / m_performance.total_signals; } //+------------------------------------------------------------------+ //| Get system status | //+------------------------------------------------------------------+ string CEntrySystem::GetStatus() { string status = "EntrySystem Status:\n"; status += "Mode: " + EnumToString(m_config.entry_mode) + "\n"; status += "Signals Generated: " + IntegerToString(m_tracker.signals_generated) + "\n"; status += "Signals Filtered: " + IntegerToString(m_tracker.signals_filtered) + "\n"; status += "Accuracy: " + DoubleToString(m_tracker.signal_accuracy * 100, 1) + "%\n"; status += "Last Signal: " + TimeToString(m_tracker.last_signal_time) + "\n"; return status; } //+------------------------------------------------------------------+ //| Additional strategy implementations (stubs for extension) | //+------------------------------------------------------------------+ EntrySignal CEntrySystem::ExecuteBreakoutStrategy(const MarketConditions &market) { EntrySignal signal; signal.signal_type = SIGNAL_NONE; // Implementation here return signal; } EntrySignal CEntrySystem::ExecuteMeanReversionStrategy(const MarketConditions &market) { EntrySignal signal; signal.signal_type = SIGNAL_NONE; // Implementation here return signal; } EntrySignal CEntrySystem::ExecuteContrarianStrategy(const MarketConditions &market) { EntrySignal signal; signal.signal_type = SIGNAL_NONE; // Implementation here return signal; } EntrySignal CEntrySystem::ExecuteMultiStrategy(const MarketConditions &market) { EntrySignal signal; signal.signal_type = SIGNAL_NONE; // Implementation here return signal; } EntrySignal CEntrySystem::ExecuteCustomStrategy(const MarketConditions &market) { EntrySignal signal; signal.signal_type = SIGNAL_NONE; // Custom implementation here return signal; } //+------------------------------------------------------------------+ //| Update performance tracking | //+------------------------------------------------------------------+ void CEntrySystem::UpdatePerformance(ulong ticket, bool success, double rr_achieved) { if(success) m_performance.successful_signals++; m_performance.avg_rr_achieved = (m_performance.avg_rr_achieved * m_performance.total_signals + rr_achieved) / (m_performance.total_signals + 1); //--- Update accuracy double alpha = 0.1; m_tracker.signal_accuracy = m_tracker.signal_accuracy * (1 - alpha) + (success ? 1.0 : 0.0) * alpha; } //+------------------------------------------------------------------+ //| Check if system is ready | //+------------------------------------------------------------------+ bool CEntrySystem::IsReady() const { return m_indicators.atr != INVALID_HANDLE; } //+------------------------------------------------------------------+ //| Reset system | //+------------------------------------------------------------------+ void CEntrySystem::Reset() { m_tracker.Reset(); m_performance.Reset(); m_cache.Invalidate(); m_buffers.Reset(); } #endif // ENTRY_SYSTEM_MQH