| #include "..\IStrategy.mqh"
|
| #include "..\KnowledgeBase.mqh"
|
| #include "..\TradeManager.mqh"
|
|
|
| class CForexTrendStrategy : public IStrategy
|
| {
|
| private:
|
| // Trend indicators
|
| int m_emaFast, m_emaMedium, m_emaSlow;
|
| int m_ichimokuTenkan, m_ichimokuKijun, m_ichimokuSenkou;
|
| double m_parabolicStep, m_parabolicMax;
|
|
|
| // Momentum indicators
|
| int m_rsiPeriod, m_adxPeriod;
|
|
|
| // Cached values
|
| double m_ema_fast, m_ema_medium, m_ema_slow;
|
| double m_tenkan, m_kijun, m_senkou_a, m_senkou_b;
|
| double m_parabolic, m_rsi, m_adx;
|
| double m_close0, m_close1;
|
|
|
| public:
|
| CForexTrendStrategy(const string symbol, const ENUM_TIMEFRAMES tf) : IStrategy("ForexTrendStrategy", symbol, tf)
|
| {
|
| // EMA periods for trend identification
|
| m_emaFast = 8; m_emaMedium = 21; m_emaSlow = 50;
|
|
|
| // Ichimoku parameters
|
| m_ichimokuTenkan = 9; m_ichimokuKijun = 26; m_ichimokuSenkou = 52;
|
|
|
| // Parabolic SAR
|
| m_parabolicStep = 0.02; m_parabolicMax = 0.2;
|
|
|
| // Momentum
|
| m_rsiPeriod = 14; m_adxPeriod = 14;
|
|
|
| ResetValues();
|
| }
|
|
|
| virtual string Name() { return "ForexTrendStrategy"; }
|
|
|
| void ResetValues()
|
| {
|
| m_ema_fast = m_ema_medium = m_ema_slow = 0;
|
| m_tenkan = m_kijun = m_senkou_a = m_senkou_b = 0;
|
| m_parabolic = m_rsi = m_adx = 0;
|
| m_close0 = m_close1 = 0;
|
| }
|
|
|
| virtual void Refresh()
|
| {
|
| ResetValues();
|
| m_close0 = iClose(m_symbol, m_timeframe, 0);
|
| m_close1 = iClose(m_symbol, m_timeframe, 1);
|
|
|
| // EMAs
|
| double ema_fast_buffer[], ema_medium_buffer[], ema_slow_buffer[];
|
| int ema_fast_handle = iMA(m_symbol, m_timeframe, m_emaFast, 0, MODE_EMA, PRICE_CLOSE);
|
| int ema_medium_handle = iMA(m_symbol, m_timeframe, m_emaMedium, 0, MODE_EMA, PRICE_CLOSE);
|
| int ema_slow_handle = iMA(m_symbol, m_timeframe, m_emaSlow, 0, MODE_EMA, PRICE_CLOSE);
|
|
|
| if(ema_fast_handle > 0) CopyBuffer(ema_fast_handle, 0, 0, 1, ema_fast_buffer);
|
| if(ema_medium_handle > 0) CopyBuffer(ema_medium_handle, 0, 0, 1, ema_medium_buffer);
|
| if(ema_slow_handle > 0) CopyBuffer(ema_slow_handle, 0, 0, 1, ema_slow_buffer);
|
|
|
| m_ema_fast = ema_fast_buffer[0];
|
| m_ema_medium = ema_medium_buffer[0];
|
| m_ema_slow = ema_slow_buffer[0];
|
|
|
| // Ichimoku
|
| double tenkan_buffer[], kijun_buffer[], senkou_a_buffer[], senkou_b_buffer[];
|
| int ichimoku_handle = iIchimoku(m_symbol, m_timeframe, m_ichimokuTenkan, m_ichimokuKijun, m_ichimokuSenkou);
|
|
|
| if(ichimoku_handle > 0)
|
| {
|
| CopyBuffer(ichimoku_handle, 0, 0, 1, tenkan_buffer);
|
| CopyBuffer(ichimoku_handle, 1, 0, 1, kijun_buffer);
|
| CopyBuffer(ichimoku_handle, 2, 0, 1, senkou_a_buffer);
|
| CopyBuffer(ichimoku_handle, 3, 0, 1, senkou_b_buffer);
|
|
|
| m_tenkan = tenkan_buffer[0];
|
| m_kijun = kijun_buffer[0];
|
| m_senkou_a = senkou_a_buffer[0];
|
| m_senkou_b = senkou_b_buffer[0];
|
| }
|
|
|
| // Parabolic SAR
|
| double sar_buffer[];
|
| int sar_handle = iSAR(m_symbol, m_timeframe, m_parabolicStep, m_parabolicMax);
|
| if(sar_handle > 0) CopyBuffer(sar_handle, 0, 0, 1, sar_buffer);
|
| m_parabolic = sar_buffer[0];
|
|
|
| // RSI
|
| double rsi_buffer[];
|
| int rsi_handle = iRSI(m_symbol, m_timeframe, m_rsiPeriod, PRICE_CLOSE);
|
| if(rsi_handle > 0) CopyBuffer(rsi_handle, 0, 0, 1, rsi_buffer);
|
| m_rsi = rsi_buffer[0];
|
|
|
| // ADX
|
| double adx_buffer[];
|
| int adx_handle = iADX(m_symbol, m_timeframe, m_adxPeriod);
|
| if(adx_handle > 0) CopyBuffer(adx_handle, 0, 0, 1, adx_buffer);
|
| m_adx = adx_buffer[0];
|
| }
|
|
|
| virtual TradeOrder CheckSignal()
|
| {
|
| TradeOrder ord; ord.strategy_name = Name();
|
|
|
| // Trend alignment checks
|
| bool ema_bullish = m_ema_fast > m_ema_medium && m_ema_medium > m_ema_slow;
|
| bool ema_bearish = m_ema_fast < m_ema_medium && m_ema_medium < m_ema_slow;
|
|
|
| // Ichimoku cloud
|
| bool above_cloud = m_close0 > m_senkou_a && m_close0 > m_senkou_b;
|
| bool below_cloud = m_close0 < m_senkou_a && m_close0 < m_senkou_b;
|
|
|
| // Parabolic SAR
|
| bool sar_bullish = m_close0 > m_parabolic;
|
| bool sar_bearish = m_close0 < m_parabolic;
|
|
|
| // Momentum filters
|
| bool rsi_oversold = m_rsi < 30;
|
| bool rsi_overbought = m_rsi > 70;
|
| bool strong_trend = m_adx > 25;
|
|
|
| // Bullish setup
|
| if(ema_bullish && above_cloud && sar_bullish && strong_trend && rsi_oversold)
|
| {
|
| ord.action = ACTION_BUY;
|
| ord.order_type = ORDER_TYPE_BUY;
|
| ord.stop_loss = m_ema_medium;
|
| ord.take_profit = m_close0 + (m_close0 - m_ema_medium) * 2;
|
| ord.trailing_enabled = true;
|
| ord.trailing_type = TRAIL_FIXED_POINTS;
|
| ord.trail_activation_points = 30;
|
| ord.trail_distance_points = 20;
|
| ord.trail_step_points = 5;
|
| return ord;
|
| }
|
|
|
| // Bearish setup
|
| else if(ema_bearish && below_cloud && sar_bearish && strong_trend && rsi_overbought)
|
| {
|
| ord.action = ACTION_SELL;
|
| ord.order_type = ORDER_TYPE_SELL;
|
| ord.stop_loss = m_ema_medium;
|
| ord.take_profit = m_close0 - (m_ema_medium - m_close0) * 2;
|
| ord.trailing_enabled = true;
|
| ord.trailing_type = TRAIL_FIXED_POINTS;
|
| ord.trail_activation_points = 30;
|
| ord.trail_distance_points = 20;
|
| ord.trail_step_points = 5;
|
| return ord;
|
| }
|
|
|
| return ord;
|
| }
|
|
|
| virtual void ExportFeatures(CFeaturesKB* kb, const datetime ts)
|
| {
|
| if(CheckPointer(kb)==POINTER_INVALID) return;
|
|
|
| // Trend strength indicators
|
| double trend_strength = 0;
|
| if(m_ema_fast > m_ema_medium) trend_strength += 1;
|
| if(m_ema_medium > m_ema_slow) trend_strength += 1;
|
| if(m_close0 > m_senkou_a && m_close0 > m_senkou_b) trend_strength += 1;
|
|
|
| (*kb).WriteKV(ts, m_symbol, Name(), "trend_strength", trend_strength);
|
| (*kb).WriteKV(ts, m_symbol, Name(), "rsi", m_rsi);
|
| (*kb).WriteKV(ts, m_symbol, Name(), "adx", m_adx);
|
| (*kb).WriteKV(ts, m_symbol, Name(), "ema_distance", MathAbs(m_close0 - m_ema_medium) / m_ema_medium * 100);
|
| }
|
| };
|