137 lines
2.9 KiB
MQL5
137 lines
2.9 KiB
MQL5
|
|
/**
|
||
|
|
* @file SMMA - Concrete Streaming Smoothed Moving Average indicator using synchronized time-series events and smoothed averaging.
|
||
|
|
* @deps IndicatorBase.mqh, BarSeriesBuffer.mqh, SmoothedAverage.mqh
|
||
|
|
* @state Stateful (Orchestrates time-series buffers and recursive smoothed average calculations across ticks)
|
||
|
|
* @io Source struct pricing tick -> Updates smoothed average and underlying time buffers | Request offset index -> Returns historical SMMA double value
|
||
|
|
* @note AI-assisted code. Independently review and test in a demo environment before live production trading.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifndef __SMMA_MQH__
|
||
|
|
#define __SMMA_MQH__
|
||
|
|
|
||
|
|
#include "IndicatorBase.mqh"
|
||
|
|
#include "..\\Algorithms\\SmoothedAverage.mqh"
|
||
|
|
#include "..\\Storage\\BarSeriesBuffer.mqh"
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
class SMMA : public IndicatorBase
|
||
|
|
{
|
||
|
|
private:
|
||
|
|
|
||
|
|
int m_period;
|
||
|
|
double m_alpha;
|
||
|
|
CBarSeriesBuffer m_input;
|
||
|
|
CBarSeriesBuffer m_main;
|
||
|
|
|
||
|
|
public:
|
||
|
|
|
||
|
|
static const int MAIN;
|
||
|
|
|
||
|
|
SMMA()
|
||
|
|
{
|
||
|
|
m_period = 0;
|
||
|
|
m_alpha = 0.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
~SMMA()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
void SetParameters(const int period)
|
||
|
|
{
|
||
|
|
m_period = period;
|
||
|
|
}
|
||
|
|
|
||
|
|
virtual bool Init()
|
||
|
|
{
|
||
|
|
if(m_period <= 0)
|
||
|
|
return(false);
|
||
|
|
|
||
|
|
if(m_maxBarsBack == 0)
|
||
|
|
m_maxBarsBack = m_period;
|
||
|
|
|
||
|
|
if(m_maxBarsBack <= 0)
|
||
|
|
return(false);
|
||
|
|
|
||
|
|
m_alpha = 1.0 / m_period;
|
||
|
|
|
||
|
|
if(!m_input.Init(m_period))
|
||
|
|
return(false);
|
||
|
|
|
||
|
|
if(!m_main.Init(m_maxBarsBack))
|
||
|
|
return(false);
|
||
|
|
|
||
|
|
return(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
virtual void Reset()
|
||
|
|
{
|
||
|
|
m_input.Reset();
|
||
|
|
m_main.Reset();
|
||
|
|
}
|
||
|
|
|
||
|
|
virtual void DeInit()
|
||
|
|
{
|
||
|
|
Reset();
|
||
|
|
}
|
||
|
|
|
||
|
|
virtual void Update(const Source &src)
|
||
|
|
{
|
||
|
|
ESeriesEvent event = m_input.Update(src.time, src.value);
|
||
|
|
|
||
|
|
double result = src.value;
|
||
|
|
|
||
|
|
switch(event)
|
||
|
|
{
|
||
|
|
case SERIES_FIRST_SAMPLE:
|
||
|
|
break;
|
||
|
|
|
||
|
|
case SERIES_APPEND:
|
||
|
|
{
|
||
|
|
double previous;
|
||
|
|
|
||
|
|
if(m_main.At(0, previous))
|
||
|
|
result = SmoothedAverage(src.value, previous, m_alpha);
|
||
|
|
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
case SERIES_REPLACE_LAST:
|
||
|
|
{
|
||
|
|
double previous;
|
||
|
|
|
||
|
|
if(m_main.At(1, previous))
|
||
|
|
result = SmoothedAverage(src.value, previous, m_alpha);
|
||
|
|
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
case SERIES_RESET:
|
||
|
|
m_main.Reset();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
m_main.Update(src.time, result);
|
||
|
|
}
|
||
|
|
|
||
|
|
virtual double GetValue(const int index,
|
||
|
|
const int lineIndex = 0) const
|
||
|
|
{
|
||
|
|
if(lineIndex != MAIN)
|
||
|
|
return(m_errorValue);
|
||
|
|
|
||
|
|
double value;
|
||
|
|
|
||
|
|
if(!m_main.At(index, value))
|
||
|
|
return(m_errorValue);
|
||
|
|
|
||
|
|
return(value);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
const int SMMA::MAIN = 0;
|
||
|
|
|
||
|
|
#endif // __SMMA_MQH__
|
||
|
|
//+------------------------------------------------------------------+
|