2025-09-20 02:27:35 -04:00
|
|
|
#include "..\IStrategy.mqh"
|
|
|
|
|
#include "..\KnowledgeBase.mqh"
|
|
|
|
|
#include "..\TradeManager.mqh"
|
|
|
|
|
|
|
|
|
|
class CMultiIndicatorStrategy : public IStrategy
|
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
// Indicator parameters
|
|
|
|
|
int m_rsiPeriod, m_macdFast, m_macdSlow, m_macdSignal;
|
|
|
|
|
int m_stochK, m_stochD, m_stochSlow;
|
|
|
|
|
int m_cciPeriod, m_williamsPeriod;
|
|
|
|
|
int m_momentumPeriod, m_rocPeriod;
|
|
|
|
|
int m_schaffPeriod, m_vortexPeriod;
|
|
|
|
|
|
|
|
|
|
// Cached indicator values
|
|
|
|
|
double m_rsi, m_macd_main, m_macd_signal;
|
|
|
|
|
double m_stoch_k, m_stoch_d;
|
|
|
|
|
double m_cci, m_williams;
|
|
|
|
|
double m_momentum, m_roc;
|
|
|
|
|
double m_schaff, m_vortex_plus, m_vortex_minus;
|
|
|
|
|
double m_close0, m_close1;
|
|
|
|
|
|
|
|
|
|
// Score calculation
|
|
|
|
|
double m_bullish_score, m_bearish_score;
|
|
|
|
|
int m_min_score_threshold;
|
|
|
|
|
|
|
|
|
|
public:
|
2026-02-05 23:31:20 -05:00
|
|
|
CMultiIndicatorStrategy(const string symbol, const ENUM_TIMEFRAMES tf) : IStrategy("MultiIndicatorStrategy", symbol, tf)
|
2025-09-20 02:27:35 -04:00
|
|
|
{
|
|
|
|
|
// Initialize parameters
|
|
|
|
|
m_rsiPeriod = 14; m_macdFast = 12; m_macdSlow = 26; m_macdSignal = 9;
|
|
|
|
|
m_stochK = 14; m_stochD = 3; m_stochSlow = 3;
|
|
|
|
|
m_cciPeriod = 14; m_williamsPeriod = 14;
|
|
|
|
|
m_momentumPeriod = 14; m_rocPeriod = 14;
|
|
|
|
|
m_schaffPeriod = 23; m_vortexPeriod = 14;
|
|
|
|
|
m_min_score_threshold = 3;
|
|
|
|
|
|
|
|
|
|
ResetValues();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual string Name() { return "MultiIndicatorStrategy"; }
|
|
|
|
|
|
|
|
|
|
void ResetValues()
|
|
|
|
|
{
|
|
|
|
|
m_rsi = m_macd_main = m_macd_signal = 0;
|
|
|
|
|
m_stoch_k = m_stoch_d = 0;
|
|
|
|
|
m_cci = m_williams = 0;
|
|
|
|
|
m_momentum = m_roc = 0;
|
|
|
|
|
m_schaff = m_vortex_plus = m_vortex_minus = 0;
|
|
|
|
|
m_close0 = m_close1 = 0;
|
|
|
|
|
m_bullish_score = m_bearish_score = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void Refresh()
|
|
|
|
|
{
|
|
|
|
|
ResetValues();
|
2026-02-05 23:31:20 -05:00
|
|
|
m_close0 = iClose(m_symbol, m_timeframe, 0);
|
|
|
|
|
m_close1 = iClose(m_symbol, m_timeframe, 1);
|
2025-09-20 02:27:35 -04:00
|
|
|
|
|
|
|
|
// RSI
|
|
|
|
|
double rsi_buffer[];
|
2026-02-05 23:31:20 -05:00
|
|
|
int rsi_handle = iRSI(m_symbol, m_timeframe, m_rsiPeriod, PRICE_CLOSE);
|
2025-09-20 02:27:35 -04:00
|
|
|
if(rsi_handle > 0 && CopyBuffer(rsi_handle, 0, 0, 1, rsi_buffer) == 1)
|
|
|
|
|
m_rsi = rsi_buffer[0];
|
|
|
|
|
|
|
|
|
|
// MACD
|
|
|
|
|
double macd_main[], macd_signal[];
|
2026-02-05 23:31:20 -05:00
|
|
|
int macd_handle = iMACD(m_symbol, m_timeframe, m_macdFast, m_macdSlow, m_macdSignal, PRICE_CLOSE);
|
2025-09-20 02:27:35 -04:00
|
|
|
if(macd_handle > 0)
|
|
|
|
|
{
|
|
|
|
|
CopyBuffer(macd_handle, 0, 0, 1, macd_main);
|
|
|
|
|
CopyBuffer(macd_handle, 1, 0, 1, macd_signal);
|
|
|
|
|
m_macd_main = macd_main[0];
|
|
|
|
|
m_macd_signal = macd_signal[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Stochastic
|
|
|
|
|
double stoch_k[], stoch_d[];
|
2026-02-05 23:31:20 -05:00
|
|
|
int stoch_handle = iStochastic(m_symbol, m_timeframe, m_stochK, m_stochD, m_stochSlow, MODE_SMA, STO_LOWHIGH);
|
2025-09-20 02:27:35 -04:00
|
|
|
if(stoch_handle > 0)
|
|
|
|
|
{
|
|
|
|
|
CopyBuffer(stoch_handle, 0, 0, 1, stoch_k);
|
|
|
|
|
CopyBuffer(stoch_handle, 1, 0, 1, stoch_d);
|
|
|
|
|
m_stoch_k = stoch_k[0];
|
|
|
|
|
m_stoch_d = stoch_d[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CCI
|
|
|
|
|
double cci_buffer[];
|
2026-02-05 23:31:20 -05:00
|
|
|
int cci_handle = iCCI(m_symbol, m_timeframe, m_cciPeriod, PRICE_TYPICAL);
|
2025-09-20 02:27:35 -04:00
|
|
|
if(cci_handle > 0 && CopyBuffer(cci_handle, 0, 0, 1, cci_buffer) == 1)
|
|
|
|
|
m_cci = cci_buffer[0];
|
|
|
|
|
|
|
|
|
|
// Williams %R
|
|
|
|
|
double williams_buffer[];
|
2026-02-05 23:31:20 -05:00
|
|
|
int williams_handle = iWPR(m_symbol, m_timeframe, m_williamsPeriod);
|
2025-09-20 02:27:35 -04:00
|
|
|
if(williams_handle > 0 && CopyBuffer(williams_handle, 0, 0, 1, williams_buffer) == 1)
|
|
|
|
|
m_williams = williams_buffer[0];
|
|
|
|
|
|
|
|
|
|
// Momentum
|
|
|
|
|
double momentum_buffer[];
|
2026-02-05 23:31:20 -05:00
|
|
|
int momentum_handle = iMomentum(m_symbol, m_timeframe, m_momentumPeriod, PRICE_CLOSE);
|
2025-09-20 02:27:35 -04:00
|
|
|
if(momentum_handle > 0 && CopyBuffer(momentum_handle, 0, 0, 1, momentum_buffer) == 1)
|
|
|
|
|
m_momentum = momentum_buffer[0];
|
|
|
|
|
|
|
|
|
|
// ROC (manual): ((Close(0) - Close(period)) / Close(period)) * 100
|
2026-02-05 23:31:20 -05:00
|
|
|
double close_now = iClose(m_symbol, m_timeframe, 0);
|
|
|
|
|
double close_n = iClose(m_symbol, m_timeframe, m_rocPeriod);
|
2025-09-20 02:27:35 -04:00
|
|
|
if(close_n!=0.0)
|
|
|
|
|
m_roc = 100.0 * (close_now - close_n) / close_n;
|
|
|
|
|
|
|
|
|
|
// Calculate composite scores
|
|
|
|
|
CalculateScores();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CalculateScores()
|
|
|
|
|
{
|
|
|
|
|
m_bullish_score = 0;
|
|
|
|
|
m_bearish_score = 0;
|
|
|
|
|
|
|
|
|
|
// RSI scoring
|
|
|
|
|
if(m_rsi < 30) m_bullish_score += 1;
|
|
|
|
|
else if(m_rsi > 70) m_bearish_score += 1;
|
|
|
|
|
|
|
|
|
|
// MACD scoring
|
|
|
|
|
if(m_macd_main > m_macd_signal && m_macd_main > 0) m_bullish_score += 1;
|
|
|
|
|
else if(m_macd_main < m_macd_signal && m_macd_main < 0) m_bearish_score += 1;
|
|
|
|
|
|
|
|
|
|
// Stochastic scoring
|
|
|
|
|
if(m_stoch_k < 20 && m_stoch_k > m_stoch_d) m_bullish_score += 1;
|
|
|
|
|
else if(m_stoch_k > 80 && m_stoch_k < m_stoch_d) m_bearish_score += 1;
|
|
|
|
|
|
|
|
|
|
// CCI scoring
|
|
|
|
|
if(m_cci < -100) m_bullish_score += 1;
|
|
|
|
|
else if(m_cci > 100) m_bearish_score += 1;
|
|
|
|
|
|
|
|
|
|
// Williams %R scoring
|
|
|
|
|
if(m_williams < -80) m_bullish_score += 1;
|
|
|
|
|
else if(m_williams > -20) m_bearish_score += 1;
|
|
|
|
|
|
|
|
|
|
// Momentum scoring
|
|
|
|
|
if(m_momentum > 100) m_bullish_score += 1;
|
|
|
|
|
else if(m_momentum < 100) m_bearish_score += 1;
|
|
|
|
|
|
|
|
|
|
// ROC scoring
|
|
|
|
|
if(m_roc > 0) m_bullish_score += 1;
|
|
|
|
|
else if(m_roc < 0) m_bearish_score += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual TradeOrder CheckSignal()
|
|
|
|
|
{
|
|
|
|
|
TradeOrder ord; ord.strategy_name = Name();
|
|
|
|
|
|
|
|
|
|
// Strong consensus required
|
|
|
|
|
if(m_bullish_score >= m_min_score_threshold)
|
|
|
|
|
{
|
|
|
|
|
ord.action = ACTION_BUY;
|
|
|
|
|
ord.order_type = ORDER_TYPE_BUY;
|
|
|
|
|
ord.stop_loss = m_close0 - 40 * _Point;
|
|
|
|
|
ord.take_profit = m_close0 + 120 * _Point;
|
|
|
|
|
ord.trailing_enabled = true;
|
|
|
|
|
ord.trailing_type = TRAIL_FIXED_POINTS;
|
|
|
|
|
ord.trail_activation_points = 20;
|
|
|
|
|
ord.trail_distance_points = 15;
|
|
|
|
|
ord.trail_step_points = 5;
|
|
|
|
|
return ord;
|
|
|
|
|
}
|
|
|
|
|
else if(m_bearish_score >= m_min_score_threshold)
|
|
|
|
|
{
|
|
|
|
|
ord.action = ACTION_SELL;
|
|
|
|
|
ord.order_type = ORDER_TYPE_SELL;
|
|
|
|
|
ord.stop_loss = m_close0 + 40 * _Point;
|
|
|
|
|
ord.take_profit = m_close0 - 120 * _Point;
|
|
|
|
|
ord.trailing_enabled = true;
|
|
|
|
|
ord.trailing_type = TRAIL_FIXED_POINTS;
|
|
|
|
|
ord.trail_activation_points = 20;
|
|
|
|
|
ord.trail_distance_points = 15;
|
|
|
|
|
ord.trail_step_points = 5;
|
|
|
|
|
return ord;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ord;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void ExportFeatures(CFeaturesKB* kb, const datetime ts)
|
|
|
|
|
{
|
|
|
|
|
if(CheckPointer(kb)==POINTER_INVALID) return;
|
|
|
|
|
(*kb).WriteKV(ts, m_symbol, Name(), "rsi", m_rsi);
|
|
|
|
|
(*kb).WriteKV(ts, m_symbol, Name(), "macd_main", m_macd_main);
|
|
|
|
|
(*kb).WriteKV(ts, m_symbol, Name(), "macd_signal", m_macd_signal);
|
|
|
|
|
(*kb).WriteKV(ts, m_symbol, Name(), "stoch_k", m_stoch_k);
|
|
|
|
|
(*kb).WriteKV(ts, m_symbol, Name(), "stoch_d", m_stoch_d);
|
|
|
|
|
(*kb).WriteKV(ts, m_symbol, Name(), "cci", m_cci);
|
|
|
|
|
(*kb).WriteKV(ts, m_symbol, Name(), "williams", m_williams);
|
|
|
|
|
(*kb).WriteKV(ts, m_symbol, Name(), "momentum", m_momentum);
|
|
|
|
|
(*kb).WriteKV(ts, m_symbol, Name(), "roc", m_roc);
|
|
|
|
|
(*kb).WriteKV(ts, m_symbol, Name(), "bullish_score", m_bullish_score);
|
|
|
|
|
(*kb).WriteKV(ts, m_symbol, Name(), "bearish_score", m_bearish_score);
|
|
|
|
|
}
|
|
|
|
|
};
|