//+------------------------------------------------------------------+ //| Strategy.mqh - Trading strategy implementation | //| Simple MA crossover: Buy when Fast MA > Slow MA, Sell opposite | //+------------------------------------------------------------------+ #ifndef __STRATEGY_MQH__ #define __STRATEGY_MQH__ #include "Signal.mqh" #include "MarketData.mqh" #include "Logger.mqh" #include "Config.mqh" class CStrategy { private: int m_ma_fast_handle; int m_ma_slow_handle; 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; public: // Constructor CStrategy(CMarketData *market_data, CLogger *logger) { 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; } // Destructor - clean up indicator handles ~CStrategy() { Cleanup(); } // 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) { if(mp_logger) mp_logger.Error("Failed to create Fast MA 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) { if(mp_logger) mp_logger.Error("Failed to create Slow MA indicator"); return false; } if(mp_logger) mp_logger.Info("Strategy initialized successfully"); return true; } // Generate trading signal E_SIGNAL GetSignal() { if(m_ma_fast_handle == INVALID_HANDLE || m_ma_slow_handle == INVALID_HANDLE) 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) 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); if(ma_fast_prev == 0 || ma_slow_prev == 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(mp_logger && g_debug_mode) mp_logger.Info(StringFormat("BUY Signal: MA Fast=%.5f > MA Slow=%.5f", ma_fast, ma_slow)); return SIGNAL_BUY; } // SELL: Fast MA crosses below Slow MA if(ma_fast_prev >= ma_slow_prev && ma_fast < ma_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; } return SIGNAL_NONE; } // Clean up indicator handles 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; } } private: // Safe way to get indicator value double iGetMainValue(int handle, int shift) { double value[]; ArraySetAsSeries(value, true); if(CopyBuffer(handle, 0, shift, 1, value) <= 0) return 0.0; return value[0]; } }; #endif //__STRATEGY_MQH__