using System; using System.Linq; namespace QuanTAlib { public class Mma : AbstractBase { private readonly int _period; private readonly CircularBuffer _buffer; private double _lastMma; public Mma(int period) : base() { if (period < 2) { throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 2."); } _period = period; _buffer = new CircularBuffer(period); Name = "Mma"; WarmupPeriod = period; Init(); } public Mma(object source, int period) : this(period) { var pubEvent = source.GetType().GetEvent("Pub"); pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); } public override void Init() { base.Init(); _lastMma = 0; _buffer.Clear(); } protected override void ManageState(bool isNew) { if (isNew) { _index++; } } protected override double Calculation() { ManageState(Input.IsNew); _buffer.Add(Input.Value, Input.IsNew); if (_index >= _period) { double T = _buffer.Sum(); double S = CalculateWeightedSum(); _lastMma = (T / _period) + (6 * S) / ((_period + 1) * _period); } else { // Use simple average until we have enough data points _lastMma = _buffer.Average(); } IsHot = _index >= _period; return _lastMma; } private double CalculateWeightedSum() { double sum = 0; for (int i = 0; i < _period; i++) { double weight = (_period - (2 * i + 1)) / 2.0; sum += weight * _buffer[^(i + 1)]; } return sum; } } }