175 lines
6.1 KiB
MQL5
175 lines
6.1 KiB
MQL5
#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);
|
|
}
|
|
};
|