Files
2025-02-07 19:15:50 +03:30

83 lines
6.9 KiB
Plaintext

//+------------------------------------------------------------------+
//| RingBuffer.mqh |
//| Copyright 2016, Vasiliy Sokolov. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Vasiliy Sokolov."
#property link "http://www.mql5.com"
#include "RiBuffDbl.mqh"
//+------------------------------------------------------------------+
//| Calculate the exponential moving average in the ring buffer |
//+------------------------------------------------------------------+
class CRiEMA : public CRiBuffDbl
{
private:
double m_prev_ema; // Previous EMA value
double m_last_value; // Last price value
double m_smoth_factor; // Smoothing factor
bool m_calc_first_v; // Flag indicating the first value calculation
double CalcEma(); // Direct average calculation
protected:
virtual void OnAddValue(double value);
virtual void OnChangeValue(int index, double del_value, double new_value);
virtual void OnSetMaxTotal(int max_total);
public:
CRiEMA(void);
double EMA(void);
};
//+------------------------------------------------------------------+
//| Subscribe to value adding/changing notifications |
//+------------------------------------------------------------------+
CRiEMA::CRiEMA(void) : m_prev_ema(EMPTY_VALUE), m_last_value(EMPTY_VALUE),
m_calc_first_v(false)
{
}
//+------------------------------------------------------------------+
//| Calculate smoothing factor according to MetaQuotes EMA equation |
//+------------------------------------------------------------------+
void CRiEMA::OnSetMaxTotal(int max_total)
{
m_smoth_factor = 2.0/(1.0+max_total);
}
//+------------------------------------------------------------------+
//| Increase the total sum |
//+------------------------------------------------------------------+
void CRiEMA::OnAddValue(double value)
{
//Calculate the previous EMA value
if(m_prev_ema != EMPTY_VALUE)
m_prev_ema = CalcEma();
//Save the current price
m_last_value = value;
}
//+------------------------------------------------------------------+
//| Correct EMA |
//+------------------------------------------------------------------+
void CRiEMA::OnChangeValue(int index,double del_value,double new_value)
{
if(index != GetMaxTotal()-1)
return;
m_last_value = new_value;
}
//+------------------------------------------------------------------+
//| Direct EMA calculation |
//+------------------------------------------------------------------+
double CRiEMA::CalcEma(void)
{
double value = m_last_value*m_smoth_factor+m_prev_ema*(1.0-m_smoth_factor);
return value;
}
//+------------------------------------------------------------------+
//| Get the simple moving average |
//+------------------------------------------------------------------+
double CRiEMA::EMA(void)
{
if(m_calc_first_v)
return CalcEma();
else
{
m_prev_ema = m_last_value;
m_calc_first_v = true;
}
return m_prev_ema;
}