//+------------------------------------------------------------------+ //| CutlerRSI_Engine.mqh | //| Core calculation engine for all Cutler's RSI-based indicators.| //| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" #include //+==================================================================+ //| | //| CLASS 1: CCutlerRSI_Engine (Base Class) | //| | //+==================================================================+ class CCutlerRSI_Engine { protected: int m_rsi_period; int m_ma_period; ENUM_MA_METHOD m_ma_method; double m_price[]; virtual bool PreparePriceSeries(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], ENUM_APPLIED_PRICE price_type); public: CCutlerRSI_Engine(void) {}; virtual ~CCutlerRSI_Engine(void) {}; bool Init(int rsi_p, int ma_p, ENUM_MA_METHOD ma_m); void Calculate(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], ENUM_APPLIED_PRICE price_type, double &rsi_buffer[], double &signal_buffer[]); int GetPeriodRSI(void) const { return m_rsi_period; } int GetPeriodMA(void) const { return m_ma_period; } }; //+------------------------------------------------------------------+ //| CCutlerRSI_Engine: Initialization | //+------------------------------------------------------------------+ bool CCutlerRSI_Engine::Init(int rsi_p, int ma_p, ENUM_MA_METHOD ma_m) { m_rsi_period = (rsi_p < 1) ? 1 : rsi_p; m_ma_period = (ma_p < 1) ? 1 : ma_p; m_ma_method = ma_m; return true; } //+------------------------------------------------------------------+ //| CCutlerRSI_Engine: Main Calculation Method (Shared Logic) | //+------------------------------------------------------------------+ void CCutlerRSI_Engine::Calculate(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], ENUM_APPLIED_PRICE price_type, double &rsi_buffer[], double &signal_buffer[]) { if(rates_total <= m_rsi_period) return; if(!PreparePriceSeries(rates_total, open, high, low, close, price_type)) return; double sum_pos = 0, sum_neg = 0; for(int i = 1; i < rates_total; i++) { double diff = m_price[i] - m_price[i-1]; sum_pos += (diff > 0) ? diff : 0; sum_neg += (diff < 0) ? -diff : 0; if(i > m_rsi_period) { double old_diff = m_price[i - m_rsi_period] - m_price[i - m_rsi_period - 1]; sum_pos -= (old_diff > 0) ? old_diff : 0; sum_neg -= (old_diff < 0) ? -old_diff : 0; } if(i >= m_rsi_period) { if(sum_pos + sum_neg > 0) { double rs = sum_pos / sum_neg; rsi_buffer[i] = 100.0 - (100.0 / (1.0 + rs)); } else { rsi_buffer[i] = 100.0; } } } int ma_start_pos = m_rsi_period + m_ma_period - 1; for(int i = ma_start_pos; i < rates_total; i++) { switch(m_ma_method) { case MODE_EMA: case MODE_SMMA: if(i == ma_start_pos) { double sum=0; for(int j=0; j0) signal_buffer[i]=lwma_sum/weight_sum;} break; default: {double sum=0; for(int j=0; j