/// <summary>Calculate the EMA</summary> private void Reset() { m_ema.Clear(); m_ema.Capacity = Instrument.Count; var ema = new EmaPt(Settings.WindowSize); foreach (var candle in Instrument) { // Candle data must be strictly ordered by timestamp because I'm using binary search Debug.Assert(candle.Timestamp >= ema.Timestamp); // Calculate the EMA value and save it ema.Add(candle.Close); ema.Timestamp = candle.Timestamp; m_ema.Add(ema); // Create the next EMA value ema = new EmaPt(ema); } // Invalidate the graphics Invalidate(); InvalidateChart(); }
/// <summary>Handle data added to the instrument</summary> protected override void HandleInstrumentDataChanged(object sender, DataEventArgs e) { // Check the data is for this instrument Debug.Assert(Instrument == e.Instrument); if (e.TimeFrame != Instrument.TimeFrame) { return; } // If this is a new candle, add to the EMA collection if (e.NewCandle) { var ema = m_ema.Count != 0 ? new EmaPt(m_ema.Back()) : new EmaPt(Settings.WindowSize); var prev = Instrument[-1]; ema.Timestamp = prev.Timestamp; ema.Add(prev.Close); m_ema.Add(ema); } // Otherwise, if this is an update to an existing candle, // recalculate the EMA for this candle and all following candles else if (e.Candle != null) { // Find the index of the corresponding EMA value var idx = m_ema.BinarySearch(x => x.Timestamp.CompareTo(e.Candle.Timestamp)); if (idx < 0) { idx = ~idx; } // Recalculate all EMA values from 'idx' forwards m_ema.Resize(idx); var prev = idx > 0 ? m_ema[idx - 1] : new EmaPt(Settings.WindowSize); for (; idx != Instrument.Count; ++idx) { var ema = new EmaPt(prev); var candle = Instrument[(uint)idx]; ema.Timestamp = candle.Timestamp; ema.Add(candle.Close); m_ema.Add(ema); prev = ema; } } }