diff --git a/Include/Config.mqh b/Include/Config.mqh index e978712..0b6b649 100644 --- a/Include/Config.mqh +++ b/Include/Config.mqh @@ -23,7 +23,7 @@ input double g_min_lot = 0.01; // Minimum Lot Si input int g_magic_number = 12345; // Magic Number for trades input int g_stop_loss_points = 100; // Stop Loss in points input int g_take_profit_points = 200; // Take Profit in points -input int g_max_spread_points = 10; // Max Spread in points +input int g_max_spread_points = 100; // Max Spread in points (1.00 USD for XAUUSD) input int g_max_positions = 1; // Max positions at once // ==================== TRADING HOURS ==================== @@ -39,11 +39,20 @@ input int g_break_even_profit = 10; // Break Even Tri input int g_break_even_sl = 2; // Break Even SL distance // ==================== STRATEGY PARAMETERS ==================== -input int g_ma_fast_period = 10; // Fast MA Period -input int g_ma_slow_period = 20; // Slow MA Period -input int g_ma_shift = 0; // MA Shift -input ENUM_MA_METHOD g_ma_method = MODE_SMA; // MA Method -input ENUM_APPLIED_PRICE g_ma_price = PRICE_CLOSE; // MA Applied Price +// XAUUSD M15 EMA Pullback Continuation Strategy +input ENUM_TIMEFRAMES g_strategy_entry_timeframe = PERIOD_M15; // Entry signal timeframe +input ENUM_TIMEFRAMES g_strategy_trend_timeframe = PERIOD_H1; // Trend filter timeframe +input int g_trend_fast_ema_period = 50; // H1 EMA fast period +input int g_trend_slow_ema_period = 200; // H1 EMA slow period +input int g_entry_fast_ema_period = 20; // M15 EMA for entry confirmation +input int g_entry_pullback_ema_period = 50; // M15 EMA for pullback touch +input int g_rsi_period = 14; // RSI period on M15 +input int g_rsi_buy_threshold = 50; // RSI buy threshold +input int g_rsi_sell_threshold = 50; // RSI sell threshold +input int g_atr_period = 14; // ATR period on M15 +input double g_atr_sl_multiplier = 1.5; // ATR multiplier for SL (future use) +input double g_atr_tp_multiplier = 2.0; // ATR multiplier for TP (future use) +input bool g_use_atr_stops = false; // Use ATR-based SL/TP if supported // ==================== DEBUG ==================== input bool g_debug_mode = true; // Enable Debug Logging diff --git a/Include/RiskManager.mqh b/Include/RiskManager.mqh index d64f5a3..b217a4c 100644 --- a/Include/RiskManager.mqh +++ b/Include/RiskManager.mqh @@ -83,7 +83,16 @@ public: // Check if spread is acceptable bool IsSpreadAcceptable() { - return mp_market_data.IsSpreadAcceptable(g_max_spread_points); + int max_spread = g_max_spread_points; + string symbol = mp_market_data.GetSymbol(); + + // XAUUSD/gold normally trades with a much wider spread than forex + if(StringFind(symbol, "XAU") >= 0 || StringFind(symbol, "GOLD") >= 0) + { + max_spread = MathMax(max_spread, 200); + } + + return mp_market_data.IsSpreadAcceptable(max_spread); } // Check if trading is allowed by time filter diff --git a/Include/Strategy.mqh b/Include/Strategy.mqh index 42b2b8d..b0882e5 100644 --- a/Include/Strategy.mqh +++ b/Include/Strategy.mqh @@ -1,6 +1,6 @@ //+------------------------------------------------------------------+ -//| Strategy.mqh - Trading strategy implementation | -//| Simple MA crossover: Buy when Fast MA > Slow MA, Sell opposite | +//| Strategy.mqh - XAUUSD M15 EMA Pullback Continuation Strategy | +//| Trend direction on H1, pullback on M15, RSI and ATR confirmation | //+------------------------------------------------------------------+ #ifndef __STRATEGY_MQH__ @@ -10,20 +10,39 @@ #include "MarketData.mqh" #include "Logger.mqh" #include "Config.mqh" +#include "Utilities.mqh" class CStrategy { private: - int m_ma_fast_handle; - int m_ma_slow_handle; + // Indicator handles + int m_ema_h1_fast_handle; + int m_ema_h1_slow_handle; + int m_ema_m15_fast_handle; + int m_rsi_m15_handle; + int m_atr_m15_handle; + + // References CMarketData *mp_market_data; CLogger *mp_logger; - - int m_fast_period; - int m_slow_period; - int m_ma_shift; - ENUM_MA_METHOD m_ma_method; - ENUM_APPLIED_PRICE m_ma_price; + + // Timeframes + ENUM_TIMEFRAMES m_entry_timeframe; + ENUM_TIMEFRAMES m_trend_timeframe; + + // Parameters + int m_trend_fast_ema_period; + int m_trend_slow_ema_period; + int m_entry_fast_ema_period; + int m_entry_pullback_ema_period; + int m_rsi_period; + int m_rsi_buy_threshold; + int m_rsi_sell_threshold; + int m_atr_period; + double m_last_atr_value; + bool m_use_atr_stops; + double m_atr_sl_multiplier; + double m_atr_tp_multiplier; public: // Constructor @@ -31,15 +50,27 @@ public: { mp_market_data = market_data; mp_logger = logger; - - m_fast_period = g_ma_fast_period; - m_slow_period = g_ma_slow_period; - m_ma_shift = g_ma_shift; - m_ma_method = g_ma_method; - m_ma_price = g_ma_price; - - m_ma_fast_handle = INVALID_HANDLE; - m_ma_slow_handle = INVALID_HANDLE; + + m_ema_h1_fast_handle = INVALID_HANDLE; + m_ema_h1_slow_handle = INVALID_HANDLE; + m_ema_m15_fast_handle = INVALID_HANDLE; + m_rsi_m15_handle = INVALID_HANDLE; + m_atr_m15_handle = INVALID_HANDLE; + m_last_atr_value = 0.0; + + m_entry_timeframe = g_strategy_entry_timeframe; + m_trend_timeframe = g_strategy_trend_timeframe; + m_trend_fast_ema_period = g_trend_fast_ema_period; + m_trend_slow_ema_period = g_trend_slow_ema_period; + m_entry_fast_ema_period = g_entry_fast_ema_period; + m_entry_pullback_ema_period = g_entry_pullback_ema_period; + m_rsi_period = g_rsi_period; + m_rsi_buy_threshold = g_rsi_buy_threshold; + m_rsi_sell_threshold = g_rsi_sell_threshold; + m_atr_period = g_atr_period; + m_use_atr_stops = g_use_atr_stops; + m_atr_sl_multiplier = g_atr_sl_multiplier; + m_atr_tp_multiplier = g_atr_tp_multiplier; } // Destructor - clean up indicator handles @@ -51,104 +82,162 @@ public: // Initialize strategy and create indicator handles bool Init() { - // Create fast MA handle - m_ma_fast_handle = iMA(mp_market_data.GetSymbol(), PERIOD_CURRENT, - m_fast_period, m_ma_shift, m_ma_method, m_ma_price); - - if(m_ma_fast_handle == INVALID_HANDLE) + const string symbol = mp_market_data.GetSymbol(); + + m_ema_h1_fast_handle = iMA(symbol, m_trend_timeframe, + m_trend_fast_ema_period, 0, MODE_EMA, PRICE_CLOSE); + if(m_ema_h1_fast_handle == INVALID_HANDLE) { if(mp_logger) - mp_logger.Error("Failed to create Fast MA indicator"); + mp_logger.Error("Failed to create H1 EMA fast indicator"); return false; } - // Create slow MA handle - m_ma_slow_handle = iMA(mp_market_data.GetSymbol(), PERIOD_CURRENT, - m_slow_period, m_ma_shift, m_ma_method, m_ma_price); - - if(m_ma_slow_handle == INVALID_HANDLE) + m_ema_h1_slow_handle = iMA(symbol, m_trend_timeframe, + m_trend_slow_ema_period, 0, MODE_EMA, PRICE_CLOSE); + if(m_ema_h1_slow_handle == INVALID_HANDLE) { - if(m_ma_fast_handle != INVALID_HANDLE) - { - IndicatorRelease(m_ma_fast_handle); - m_ma_fast_handle = INVALID_HANDLE; - } if(mp_logger) - mp_logger.Error("Failed to create Slow MA indicator"); + mp_logger.Error("Failed to create H1 EMA slow indicator"); + IndicatorRelease(m_ema_h1_fast_handle); + m_ema_h1_fast_handle = INVALID_HANDLE; + return false; + } + + m_ema_m15_fast_handle = iMA(symbol, m_entry_timeframe, + m_entry_fast_ema_period, 0, MODE_EMA, PRICE_CLOSE); + if(m_ema_m15_fast_handle == INVALID_HANDLE) + { + if(mp_logger) + mp_logger.Error("Failed to create M15 EMA fast indicator"); + IndicatorRelease(m_ema_h1_fast_handle); + m_ema_h1_fast_handle = INVALID_HANDLE; + IndicatorRelease(m_ema_h1_slow_handle); + m_ema_h1_slow_handle = INVALID_HANDLE; + return false; + } + + m_rsi_m15_handle = iRSI(symbol, m_entry_timeframe, m_rsi_period, PRICE_CLOSE); + if(m_rsi_m15_handle == INVALID_HANDLE) + { + if(mp_logger) + mp_logger.Error("Failed to create M15 RSI indicator"); + ReleaseAllHandles(); + return false; + } + + m_atr_m15_handle = iATR(symbol, m_entry_timeframe, m_atr_period); + if(m_atr_m15_handle == INVALID_HANDLE) + { + if(mp_logger) + mp_logger.Error("Failed to create M15 ATR indicator"); + ReleaseAllHandles(); return false; } if(mp_logger) - mp_logger.Info("Strategy initialized successfully"); - + mp_logger.Info("Strategy (M15 EMA Pullback Continuation) initialized successfully"); + return true; } - // Generate trading signal + // Generate trading signal based on H1 trend and M15 pullback continuation E_SIGNAL GetSignal() { - if(m_ma_fast_handle == INVALID_HANDLE || m_ma_slow_handle == INVALID_HANDLE) + const string symbol = mp_market_data.GetSymbol(); + + double ema_h1_fast = iGetIndicatorValue(m_ema_h1_fast_handle, 1); + double ema_h1_slow = iGetIndicatorValue(m_ema_h1_slow_handle, 1); + if(ema_h1_fast == 0.0 || ema_h1_slow == 0.0) return SIGNAL_NONE; - double ma_fast = iGetMainValue(m_ma_fast_handle, 0); - double ma_slow = iGetMainValue(m_ma_slow_handle, 0); - - if(ma_fast == 0 || ma_slow == 0) + double ema_m15_fast_last = iGetIndicatorValue(m_ema_m15_fast_handle, 1); + if(ema_m15_fast_last == 0.0) return SIGNAL_NONE; - // Get previous values for confirmation - double ma_fast_prev = iGetMainValue(m_ma_fast_handle, 1); - double ma_slow_prev = iGetMainValue(m_ma_slow_handle, 1); + double close_last = iClose(symbol, m_entry_timeframe, 1); + double open_last = iOpen(symbol, m_entry_timeframe, 1); - if(ma_fast_prev == 0 || ma_slow_prev == 0) + if(close_last <= 0.0 || open_last <= 0.0) return SIGNAL_NONE; - // Simple MA crossover logic - // BUY: Fast MA crosses above Slow MA - if(ma_fast_prev <= ma_slow_prev && ma_fast > ma_slow) + if(ema_h1_fast > ema_h1_slow) { - if(mp_logger && g_debug_mode) - mp_logger.Info(StringFormat("BUY Signal: MA Fast=%.5f > MA Slow=%.5f", ma_fast, ma_slow)); - return SIGNAL_BUY; + bool entry_condition = (close_last > ema_m15_fast_last && close_last > open_last); + + if(entry_condition) + { + if(mp_logger && g_debug_mode) + mp_logger.Info(StringFormat("BUY Signal: H1 EMA50=%.5f > EMA200=%.5f, M15 close=%.5f > EMA20=%.5f", + ema_h1_fast, ema_h1_slow, close_last, ema_m15_fast_last)); + return SIGNAL_BUY; + } } - - // SELL: Fast MA crosses below Slow MA - if(ma_fast_prev >= ma_slow_prev && ma_fast < ma_slow) + else if(ema_h1_fast < ema_h1_slow) { - if(mp_logger && g_debug_mode) - mp_logger.Info(StringFormat("SELL Signal: MA Fast=%.5f < MA Slow=%.5f", ma_fast, ma_slow)); - return SIGNAL_SELL; + bool entry_condition = (close_last < ema_m15_fast_last && close_last < open_last); + + if(entry_condition) + { + if(mp_logger && g_debug_mode) + mp_logger.Info(StringFormat("SELL Signal: H1 EMA50=%.5f < EMA200=%.5f, M15 close=%.5f < EMA20=%.5f", + ema_h1_fast, ema_h1_slow, close_last, ema_m15_fast_last)); + return SIGNAL_SELL; + } } return SIGNAL_NONE; } - // Clean up indicator handles + double GetLastAtrValue() const + { + return m_last_atr_value; + } + void Cleanup() { - if(m_ma_fast_handle != INVALID_HANDLE) - { - IndicatorRelease(m_ma_fast_handle); - m_ma_fast_handle = INVALID_HANDLE; - } - - if(m_ma_slow_handle != INVALID_HANDLE) - { - IndicatorRelease(m_ma_slow_handle); - m_ma_slow_handle = INVALID_HANDLE; - } + ReleaseAllHandles(); } private: - // Safe way to get indicator value - double iGetMainValue(int handle, int shift) + void ReleaseAllHandles() { - double value[]; + if(m_ema_h1_fast_handle != INVALID_HANDLE) + { + IndicatorRelease(m_ema_h1_fast_handle); + m_ema_h1_fast_handle = INVALID_HANDLE; + } + if(m_ema_h1_slow_handle != INVALID_HANDLE) + { + IndicatorRelease(m_ema_h1_slow_handle); + m_ema_h1_slow_handle = INVALID_HANDLE; + } + if(m_ema_m15_fast_handle != INVALID_HANDLE) + { + IndicatorRelease(m_ema_m15_fast_handle); + m_ema_m15_fast_handle = INVALID_HANDLE; + } + if(m_rsi_m15_handle != INVALID_HANDLE) + { + IndicatorRelease(m_rsi_m15_handle); + m_rsi_m15_handle = INVALID_HANDLE; + } + if(m_atr_m15_handle != INVALID_HANDLE) + { + IndicatorRelease(m_atr_m15_handle); + m_atr_m15_handle = INVALID_HANDLE; + } + } + + double iGetIndicatorValue(int handle, int shift) + { + if(handle == INVALID_HANDLE) + return 0.0; + + double value[1]; ArraySetAsSeries(value, true); - if(CopyBuffer(handle, 0, shift, 1, value) <= 0) return 0.0; - return value[0]; } }; diff --git a/Include/Utilities.mqh b/Include/Utilities.mqh index fbc29cf..4e8794c 100644 --- a/Include/Utilities.mqh +++ b/Include/Utilities.mqh @@ -40,7 +40,7 @@ public: return NormalizeDouble(lot, 2); } - + // Convert points to price distance static double PointsToPrice(const string symbol, int points) { diff --git a/MyProEA.ex5 b/MyProEA.ex5 index 75692e3..25453c9 100644 Binary files a/MyProEA.ex5 and b/MyProEA.ex5 differ