私の実装。.h:
#pragma once
#include <deque>
class MovingAverage
{
public:
MovingAverage(int length);
~MovingAverage(void);
void Add(double val);
void Modify(double value);
double Value;
std::deque<double> _candlesExceptNewest;
private:
MovingAverage(MovingAverage& rhs):
_length(rhs._length)
{
printf("MovingAverage copy-constructor mustn't be executed, exiting.");
exit(0);
}
const int _length;
int addCounter;
static const int RECALCULATE_VALUE_MASK;
double _sumExceptNewest;
double NewestCandleMedian() {
return (_newestCandleMin + _newestCandleMax) / 2;
}
void RecalculateValue();
double _newestCandleMin;
double _newestCandleMax;
};
.cpp:
#include "MovingAverage.h"
#include "CommonsNative.h"
const int MovingAverage::RECALCULATE_VALUE_MASK = 1024 - 1;
MovingAverage::MovingAverage(int length):
Value(quiet_NaN),
_length(length),
addCounter(0)
{
if (length < 20) {
std::cout << "Warning, MA is very short, less than 20! length = "
<< length << std::endl;
}
}
MovingAverage::~MovingAverage(void)
{
}
void MovingAverage::Add(double val)
{
++addCounter;
if (addCounter & RECALCULATE_VALUE_MASK) {
_sumExceptNewest = 0;
for (double val : _candlesExceptNewest)
{
_sumExceptNewest += val;
}
}
auto curQueueSize = _candlesExceptNewest.size();
if (curQueueSize == 0) {
_newestCandleMax = _newestCandleMin = val;
}
_sumExceptNewest += NewestCandleMedian();
_candlesExceptNewest.push_back(NewestCandleMedian());
if (curQueueSize == _length) {
_sumExceptNewest -= _candlesExceptNewest.front();
_candlesExceptNewest.pop_front();
}
_newestCandleMax = _newestCandleMin = val;
RecalculateValue();
}
void MovingAverage::RecalculateValue()
{
Value = (_sumExceptNewest + NewestCandleMedian())/(_candlesExceptNewest.size() + 1);
}
void MovingAverage::Modify(double val)
{
if (_candlesExceptNewest.size() == 0) {
Add(val);
} else {
if (val > _newestCandleMax) {
_newestCandleMax = val;
}
if (val < _newestCandleMin) {
_newestCandleMin = val;
}
}
}