83 lines
6.9 KiB
Plaintext
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;
|
|
} |