// MOVING AVERAGE CONVERGENCE/DIVERGENCE (MACD) OSCILLATOR public static IEnumerable <MacdResult> GetMacd(IEnumerable <Quote> history, int fastPeriod = 12, int slowPeriod = 26, int signalPeriod = 9) { // clean quotes history = Cleaners.PrepareHistory(history); // check parameters ValidateMacd(history, fastPeriod, slowPeriod, signalPeriod); // initialize List <Quote> historyList = history.ToList(); List <EmaResult> emaFast = GetEma(history, fastPeriod).ToList(); List <EmaResult> emaSlow = GetEma(history, slowPeriod).ToList(); List <BasicData> emaDiff = new List <BasicData>(); List <MacdResult> results = new List <MacdResult>(); for (int i = 0; i < historyList.Count; i++) { Quote h = historyList[i]; EmaResult df = emaFast[i]; EmaResult ds = emaSlow[i]; 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 { Index = h.Index - slowPeriod + 1, Date = h.Date, Value = macd }; emaDiff.Add(diff); } results.Add(result); } // add signal and histogram to result List <EmaResult> emaSignal = CalcEma(emaDiff, signalPeriod).ToList(); foreach (MacdResult r in results.Where(x => x.Index >= slowPeriod)) { EmaResult ds = emaSignal[r.Index - slowPeriod]; r.Signal = ds.Ema; r.Histogram = r.Macd - r.Signal; } 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) { // clean quotes history = Cleaners.PrepareHistory(history); // check parameters ValidateMacd(history, fastPeriod, slowPeriod, signalPeriod); // 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); }
// MOVING AVERAGE CONVERGENCE/DIVERGENCE (MACD) OSCILLATOR /// <include file='./info.xml' path='indicator/*' /> /// public static IEnumerable <MacdResult> GetMacd <TQuote>( IEnumerable <TQuote> history, int fastPeriod = 12, int slowPeriod = 26, int signalPeriod = 9) where TQuote : IQuote { // convert history to basic format List <BasicData> bdList = history.ConvertToBasic("C"); // check parameter arguments ValidateMacd(history, fastPeriod, slowPeriod, signalPeriod); // initialize List <EmaResult> emaFast = CalcEma(bdList, fastPeriod).ToList(); List <EmaResult> emaSlow = CalcEma(bdList, slowPeriod).ToList(); int size = bdList.Count; List <BasicData> emaDiff = new List <BasicData>(); List <MacdResult> results = new List <MacdResult>(size); // roll through history for (int i = 0; i < size; i++) { BasicData h = bdList[i]; EmaResult df = emaFast[i]; EmaResult ds = emaSlow[i]; MacdResult result = new MacdResult { 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, Value = macd }; emaDiff.Add(diff); } results.Add(result); } // add signal and histogram to result List <EmaResult> emaSignal = CalcEma(emaDiff, signalPeriod).ToList(); for (int d = slowPeriod - 1; d < size; d++) { MacdResult r = results[d]; EmaResult ds = emaSignal[d + 1 - slowPeriod]; r.Signal = ds.Ema; r.Histogram = r.Macd - r.Signal; } 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) { // clean quotes history = Cleaners.PrepareHistory(history); // check for exceptions if (slowPeriod <= fastPeriod) { throw new BadParameterException("Fast period must be smaller than the slow period."); } int qtyHistory = history.Count(); int minHistory = 2 * slowPeriod + signalPeriod; if (qtyHistory < minHistory) { throw new BadHistoryException("Insufficient history provided for MACD. " + string.Format("You provided {0} periods of history when {1} is required. " + "Since this uses a smoothing technique, " + "we recommend you use at least 250 data points prior to the intended " + "usage date for maximum precision.", qtyHistory, minHistory)); } // initialize IEnumerable <EmaResult> emaFast = GetEma(history, fastPeriod); IEnumerable <EmaResult> emaSlow = GetEma(history, slowPeriod); List <Quote> emaDiff = new List <Quote>(); 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 Quote diff = new Quote { Date = h.Date, Index = h.Index - slowPeriod, Close = macd }; emaDiff.Add(diff); } results.Add(result); } IEnumerable <EmaResult> emaSignal = GetEma(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) ? true : false; r.IsDiverging = (Math.Abs((decimal)r.Macd - (decimal)r.Signal) > Math.Abs((decimal)prevMacd - (decimal)prevSignal)) ? true : false; } // store for next iteration prevMacd = r.Macd; prevSignal = r.Signal; } return(results); }
// MOVING AVERAGE CONVERGENCE/DIVERGENCE (MACD) OSCILLATOR public static IEnumerable <MacdResult> GetMacd <TQuote>( IEnumerable <TQuote> history, int fastPeriod = 12, int slowPeriod = 26, int signalPeriod = 9) where TQuote : IQuote { // clean quotes List <TQuote> historyList = history.Sort(); // check parameters ValidateMacd(history, fastPeriod, slowPeriod, signalPeriod); // initialize List <EmaResult> emaFast = GetEma(history, fastPeriod).ToList(); List <EmaResult> emaSlow = GetEma(history, slowPeriod).ToList(); List <BasicData> emaDiff = new List <BasicData>(); List <MacdResult> results = new List <MacdResult>(); for (int i = 0; i < historyList.Count; i++) { TQuote h = historyList[i]; EmaResult df = emaFast[i]; EmaResult ds = emaSlow[i]; MacdResult result = new MacdResult { 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, Value = macd }; emaDiff.Add(diff); } results.Add(result); } // add signal and histogram to result List <EmaResult> emaSignal = CalcEma(emaDiff, signalPeriod).ToList(); for (int d = slowPeriod - 1; d < results.Count; d++) { MacdResult r = results[d]; EmaResult ds = emaSignal[d + 1 - slowPeriod]; r.Signal = ds.Ema; r.Histogram = r.Macd - r.Signal; } return(results); }