// DOUBLE EXPONENTIAL MOVING AVERAGE public static IEnumerable <EmaResult> GetDoubleEma(IEnumerable <Quote> history, int lookbackPeriod) { // convert history to basic format IEnumerable <BasicData> bd = Cleaners.ConvertHistoryToBasic(history, "C"); // initialize List <EmaResult> results = new List <EmaResult>(); IEnumerable <EmaResult> emaN = CalcEma(bd, lookbackPeriod); List <BasicData> bd2 = emaN .Where(x => x.Ema != null) .Select(x => new BasicData { Index = null, Date = x.Date, Value = (decimal)x.Ema }) .ToList(); // note: ToList seems to be required when changing data IEnumerable <EmaResult> emaN2 = CalcEma(bd2, lookbackPeriod); // compose final results foreach (EmaResult h in emaN) { EmaResult result = new EmaResult { Index = h.Index, Date = h.Date }; if (h.Index >= 2 * lookbackPeriod) { EmaResult emaEma = emaN2.Where(x => x.Index == h.Index - lookbackPeriod + 1).FirstOrDefault(); result.Ema = 2 * h.Ema - emaEma.Ema; } results.Add(result); } return(results); }
// MOVING AVERAGE CONVERGENCE/DIVERGENCE (MACD) OSCILLATOR public static IEnumerable <MacdResult> GetMacd(IEnumerable <Quote> history, int fastPeriod = 12, int slowPeriod = 26, int signalPeriod = 9) { // initialize IEnumerable <EmaResult> emaFast = GetEma(history, fastPeriod); IEnumerable <EmaResult> emaSlow = GetEma(history, slowPeriod); List <BasicData> emaDiff = new List <BasicData>(); List <MacdResult> results = new List <MacdResult>(); foreach (Quote h in history) { EmaResult df = emaFast.Where(x => x.Date == h.Date).FirstOrDefault(); EmaResult ds = emaSlow.Where(x => x.Date == h.Date).FirstOrDefault(); MacdResult result = new MacdResult { Index = (int)h.Index, Date = h.Date }; if (df?.Ema != null && ds?.Ema != null) { decimal macd = (decimal)df.Ema - (decimal)ds.Ema; result.Macd = macd; // temp data for interim EMA of macd BasicData diff = new BasicData { Date = h.Date, Index = h.Index - slowPeriod, Value = macd }; emaDiff.Add(diff); } results.Add(result); } IEnumerable <EmaResult> emaSignal = CalcEma(emaDiff, signalPeriod); decimal?prevMacd = null; decimal?prevSignal = null; // add signal, histogram to result foreach (MacdResult r in results) { EmaResult ds = emaSignal.Where(x => x.Date == r.Date).FirstOrDefault(); if (ds?.Ema == null) { continue; } r.Signal = ds.Ema; r.Histogram = r.Macd - r.Signal; // trend and divergence if (prevMacd != null && prevSignal != null) { r.IsBullish = (r.Macd > r.Signal); r.IsDiverging = (Math.Abs((decimal)r.Macd - (decimal)r.Signal) > Math.Abs((decimal)prevMacd - (decimal)prevSignal)); } // store for next iteration prevMacd = r.Macd; prevSignal = r.Signal; } return(results); }