diff --git a/Include/MyIncludes/MFI_Calculator.mqh b/Include/MyIncludes/MFI_Calculator.mqh index 2eba7ca..ad5e16b 100644 --- a/Include/MyIncludes/MFI_Calculator.mqh +++ b/Include/MyIncludes/MFI_Calculator.mqh @@ -1,174 +1,203 @@ //+------------------------------------------------------------------+ //| MFI_Calculator.mqh | //| Calculation engine for Standard and Heikin Ashi MFI. | +//| VERSION 2.00: Optimized for incremental calculation. | //| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" #include +#include //+==================================================================+ -//| | //| CLASS 1: CMFICalculator (Base Class) | -//| | //+==================================================================+ class CMFICalculator { protected: - int m_mfi_period, m_ma_period; - ENUM_MA_METHOD m_ma_method; + int m_mfi_period; ENUM_APPLIED_VOLUME m_volume_type; - double m_typical_price[]; - //--- CORRECTED: Added 'open' to signature - virtual bool PreparePriceSeries(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[]); + //--- Engine for Signal Line + CMovingAverageCalculator m_signal_engine; + + //--- Persistent Buffers for Incremental Calculation + double m_typical_price[]; + double m_pos_mf[]; // Positive Money Flow + double m_neg_mf[]; // Negative Money Flow + double m_mfi_buffer[]; + + //--- Updated: Accepts start_index + virtual bool PreparePriceSeries(int rates_total, int start_index, const double &open[], const double &high[], const double &low[], const double &close[]); public: CMFICalculator(void) {}; virtual ~CMFICalculator(void) {}; - bool Init(int mfi_p, int ma_p, ENUM_MA_METHOD ma_m, ENUM_APPLIED_VOLUME vol_t); - //--- CORRECTED: Added 'open' to signature - void Calculate(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], + //--- Init now takes ENUM_MA_TYPE + bool Init(int mfi_p, int ma_p, ENUM_MA_TYPE ma_m, ENUM_APPLIED_VOLUME vol_t); + + //--- Updated: Accepts prev_calculated + void Calculate(int rates_total, int prev_calculated, const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], double &mfi_buffer[], double &signal_buffer[]); }; //+------------------------------------------------------------------+ -//| CMFICalculator: Initialization | +//| Init | //+------------------------------------------------------------------+ -bool CMFICalculator::Init(int mfi_p, int ma_p, ENUM_MA_METHOD ma_m, ENUM_APPLIED_VOLUME vol_t) +bool CMFICalculator::Init(int mfi_p, int ma_p, ENUM_MA_TYPE ma_m, ENUM_APPLIED_VOLUME vol_t) { m_mfi_period = (mfi_p < 1) ? 1 : mfi_p; - m_ma_period = (ma_p < 1) ? 1 : ma_p; - m_ma_method = ma_m; m_volume_type = vol_t; + +// Initialize Signal Engine + if(!m_signal_engine.Init(ma_p, ma_m)) + return false; + return true; } //+------------------------------------------------------------------+ -//| CMFICalculator: Main Calculation Method (Shared Logic) | +//| Main Calculation (Optimized) | //+------------------------------------------------------------------+ -void CMFICalculator::Calculate(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], +void CMFICalculator::Calculate(int rates_total, int prev_calculated, const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], double &mfi_buffer[], double &signal_buffer[]) { - if(rates_total <= m_mfi_period + m_ma_period) - return; -//--- CORRECTED: Pass 'open' to PreparePriceSeries - if(!PreparePriceSeries(rates_total, open, high, low, close)) + if(rates_total <= m_mfi_period) return; - double pos_mf[], neg_mf[]; - ArrayResize(pos_mf, rates_total); - ArrayResize(neg_mf, rates_total); +//--- 1. Determine Start Index + int start_index; + if(prev_calculated == 0) + start_index = 0; + else + start_index = prev_calculated - 1; - for(int i=1; i m_typical_price[i-1]) - pos_mf[i] = raw_mf; + { + m_pos_mf[i] = raw_mf; + m_neg_mf[i] = 0; + } else if(m_typical_price[i] < m_typical_price[i-1]) - neg_mf[i] = raw_mf; - } - - double sum_pos = 0, sum_neg = 0; - for(int i = 1; i < rates_total; i++) - { - sum_pos += pos_mf[i]; - sum_neg += neg_mf[i]; - if(i > m_mfi_period) - { - sum_pos -= pos_mf[i - m_mfi_period]; - sum_neg -= neg_mf[i - m_mfi_period]; - } - if(i >= m_mfi_period) - { - if(sum_neg > 0) { - double ratio = sum_pos / sum_neg; - mfi_buffer[i] = 100.0 - (100.0 / (1.0 + ratio)); + m_pos_mf[i] = 0; + m_neg_mf[i] = raw_mf; } else - mfi_buffer[i] = 100.0; - } + { + m_pos_mf[i] = 0; + m_neg_mf[i] = 0; + } } - int ma_start_pos = m_mfi_period + m_ma_period - 1; - for(int i = ma_start_pos; i < rates_total; i++) +//--- 5. Calculate MFI (Incremental Sliding Window) + int loop_start_mfi = MathMax(m_mfi_period, start_index); + +// If full recalc, we need to handle the first value specially or just loop + if(prev_calculated == 0) { - 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 0) + { + double ratio = sum_pos / sum_neg; + m_mfi_buffer[i] = 100.0 - (100.0 / (1.0 + ratio)); + } + else + m_mfi_buffer[i] = 100.0; + } + +//--- 6. Calculate Signal Line (Using Engine) +// MFI is valid from index: m_mfi_period + int mfi_offset = m_mfi_period; + m_signal_engine.CalculateOnArray(rates_total, prev_calculated, m_mfi_buffer, signal_buffer, mfi_offset); + +//--- 7. Copy MFI to Output + ArrayCopy(mfi_buffer, m_mfi_buffer, 0, 0, rates_total); } //+------------------------------------------------------------------+ -//| CMFICalculator: Prepares the standard source price series. | +//| Prepare Price (Standard - Optimized) | //+------------------------------------------------------------------+ -bool CMFICalculator::PreparePriceSeries(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[]) +bool CMFICalculator::PreparePriceSeries(int rates_total, int start_index, const double &open[], const double &high[], const double &low[], const double &close[]) { - ArrayResize(m_typical_price, rates_total); - for(int i=0; i