//+------------------------------------------------------------------+ //| CMAOnRingBuffer.mqh | //| Copyright 2012, Konstantin Gruzdev | //| https://login.mql5.com/ru/users/Lizar | //| Revision 30 Nov 2012 | //+------------------------------------------------------------------+ #property copyright "Copyright 2012, Konstantin Gruzdev" #property link "https://login.mql5.com/ru/users/Lizar" //--- Class for working with the ring buffer of data: #include //+------------------------------------------------------------------+ //| Class CMAOnRingBuffer | //| Appointment: class is designed to calculate a moving averages | //| using the class for working with the ring | //| buffer. | //| Link: http://www.mql5.com/ru/code/1342 | //+------------------------------------------------------------------+ class CMAOnRingBuffer :public CArrayRing { private: CArrayRing *m_array_in; // ring buffer for input data int m_ma_period; // number of elements to analyze ENUM_MA_METHOD m_ma_method; // MA calculation method bool m_as_series; // true, if the indexing as in time series double m_k1,m_k2; double m_LK[]; string m_name; // indicator name int m_bars_required; // number of elements required to calculate int m_start; // index of element to start the calculation int m_index; // current element index public: CMAOnRingBuffer() {} ~CMAOnRingBuffer(); //--- initialization method: bool Init(int ma_period=14,ENUM_MA_METHOD ma_method=MODE_SMA, int size_buffer=256, bool as_series=false); //--- basic methods: int MainOnArray(const int rates_total, const int prev_calculated,const double &array[]); double MainOnValue(const int rates_total, const int prev_calculated, const int begin, const double value, const int index); //--- methods to get access to private data: int BarsRequired() { return(m_bars_required); } string Name() { return(m_name); } string MAMethod() { return(MethodToString(m_ma_method)); } int MAPeriod() { return(m_ma_period); } //--- returns the value of element with the specified index: double operator [](const int index) const { return(At(index)); } private: //--- methods of calculation based on the array of input data: void SMAOnArray (const int rates_total, const int prev_calculated, const double &array[]); void EMAOnArray (const int rates_total, const int prev_calculated, const double &array[]); void LWMAOnArray(const int rates_total, const int prev_calculated, const double &array[]); //--- methods to calculate the sequential values ??of the indicator elements: double SMAOnValue (const int prev_calculated, const int begin, const double value, const int index); double EMAOnValue (const int prev_calculated, const int begin, const double value, const int index); double LWMAOnValue(const int prev_calculated, const int begin, const double value, const int index); //--- auxiliary methods: int Begin(const int rates_total,const double &array[]); bool FillArrayIn(const int prev_calculated, const double value); string MethodToString(ENUM_MA_METHOD method); }; //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ void CMAOnRingBuffer:: ~CMAOnRingBuffer() { if(CheckPointer(m_array_in)!=POINTER_INVALID) delete m_array_in; } //+------------------------------------------------------------------+ //| Indicator on array | //+------------------------------------------------------------------+ int CMAOnRingBuffer:: MainOnArray(const int rates_total,const int prev_calculated,const double &array[]) { //--- save as_series flags bool as_series=ArrayGetAsSeries(array); if(as_series) ArraySetAsSeries(array,false); //--- main calculation: switch(m_ma_method) { case MODE_SMA: SMAOnArray(rates_total,prev_calculated,array); break; case MODE_EMA: case MODE_SMMA: EMAOnArray(rates_total,prev_calculated,array); break; case MODE_LWMA: LWMAOnArray(rates_total,prev_calculated,array); break; } //--- restore as_series flags if(as_series) ArraySetAsSeries(array,true); //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| Indicator on value | //+------------------------------------------------------------------+ double CMAOnRingBuffer:: MainOnValue(const int rates_total, const int prev_calculated, const int begin, const double value, const int index) { //--- check as_series flags: if(m_as_series) m_index=rates_total-1-index; else m_index=index; //--- check begin: if(m_indexm_start-m_ma_period;i--) sum+=array[i]; Last(sum/m_ma_period); } //--- number of bars was changed: else { m_start=prev_calculated-1; Last(At(1)-(array[m_start-m_ma_period]-array[m_start])/m_ma_period); } //--- main loop for(int i=m_start+1;i