// EXPONENTIAL MOVING AVERAGE public static IEnumerable <EmaResult> GetEma(IEnumerable <Quote> history, int lookbackPeriod) { // convert history to basic format IEnumerable <BasicData> bd = Cleaners.ConvertHistoryToBasic(history, "C"); // calculate return(CalcEma(bd, lookbackPeriod)); }
// RELATIVE STRENGTH INDEX public static IEnumerable <RsiResult> GetRsi(IEnumerable <Quote> history, int lookbackPeriod = 14) { // convert history to basic format List <BasicData> bd = Cleaners.ConvertHistoryToBasic(history, "C"); // calculate return(CalcRsi(bd, lookbackPeriod)); }
// STANDARD DEVIATION public static IEnumerable <StdDevResult> GetStdDev(IEnumerable <Quote> history, int lookbackPeriod) { // convert to basic data IEnumerable <BasicData> bd = Cleaners.ConvertHistoryToBasic(history, "C"); // calculate return(CalcStdDev(bd, lookbackPeriod)); }
// TRIPLE EXPONENTIAL MOVING AVERAGE public static IEnumerable <EmaResult> GetTripleEma <TQuote>( IEnumerable <TQuote> history, int lookbackPeriod) where TQuote : IQuote { // convert history to basic format List <BasicData> bdList = Cleaners.ConvertHistoryToBasic(history, "C"); // validate parameters ValidateTema(bdList, lookbackPeriod); // initialize List <EmaResult> results = new List <EmaResult>(bdList.Count); List <EmaResult> emaN1 = CalcEma(bdList, lookbackPeriod).ToList(); List <BasicData> bd2 = emaN1 .Where(x => x.Ema != null) .Select(x => new BasicData { Date = x.Date, Value = (decimal)x.Ema }) .ToList(); List <EmaResult> emaN2 = CalcEma(bd2, lookbackPeriod).ToList(); List <BasicData> bd3 = emaN2 .Where(x => x.Ema != null) .Select(x => new BasicData { Date = x.Date, Value = (decimal)x.Ema }) .ToList(); List <EmaResult> emaN3 = CalcEma(bd3, lookbackPeriod).ToList(); // compose final results for (int i = 0; i < emaN1.Count; i++) { EmaResult e1 = emaN1[i]; int index = i + 1; EmaResult result = new EmaResult { Date = e1.Date }; if (index >= 3 * lookbackPeriod - 2) { EmaResult e2 = emaN2[index - lookbackPeriod]; EmaResult e3 = emaN3[index - 2 * lookbackPeriod + 1]; result.Ema = 3 * e1.Ema - 3 * e2.Ema + e3.Ema; } results.Add(result); } return(results); }
// EXPONENTIAL MOVING AVERAGE public static IEnumerable <EmaResult> GetEma <TQuote>( IEnumerable <TQuote> history, int lookbackPeriod) where TQuote : IQuote { // convert history to basic format List <BasicData> bdList = Cleaners.ConvertHistoryToBasic(history, "C"); // calculate return(CalcEma(bdList, lookbackPeriod)); }
// STANDARD DEVIATION public static IEnumerable <StdDevResult> GetStdDev <TQuote>( IEnumerable <TQuote> history, int lookbackPeriod, int?smaPeriod = null) where TQuote : IQuote { // convert to basic data List <BasicData> bd = Cleaners.ConvertHistoryToBasic(history, "C"); // calculate return(CalcStdDev(bd, lookbackPeriod, smaPeriod)); }
// DOUBLE EXPONENTIAL MOVING AVERAGE public static IEnumerable <EmaResult> GetDoubleEma <TQuote>( IEnumerable <TQuote> history, int lookbackPeriod) where TQuote : IQuote { // convert history to basic format List <BasicData> bd = Cleaners.ConvertHistoryToBasic(history, "C"); // validate parameters ValidateDema(bd, lookbackPeriod); // initialize List <EmaResult> results = new List <EmaResult>(); List <EmaResult> emaN = CalcEma(bd, lookbackPeriod).ToList(); List <BasicData> bd2 = emaN .Where(x => x.Ema != null) .Select(x => new BasicData { Date = x.Date, Value = (decimal)x.Ema }) .ToList(); // note: ToList seems to be required when changing data List <EmaResult> emaN2 = CalcEma(bd2, lookbackPeriod).ToList(); // compose final results for (int i = 0; i < emaN.Count; i++) { EmaResult e1 = emaN[i]; int index = i + 1; EmaResult result = new EmaResult { Date = e1.Date }; if (index >= 2 * lookbackPeriod - 1) { EmaResult e2 = emaN2[index - lookbackPeriod]; result.Ema = 2 * e1.Ema - e2.Ema; } results.Add(result); } return(results); }
// CONNORS RSI public static IEnumerable <ConnorsRsiResult> GetConnorsRsi <TQuote>( IEnumerable <TQuote> history, int rsiPeriod = 3, int streakPeriod = 2, int rankPeriod = 100) where TQuote : IQuote { // convert history to basic format List <BasicData> bd = Cleaners.ConvertHistoryToBasic(history, "C").ToList(); // check parameters ValidateConnorsRsi(bd, rsiPeriod, streakPeriod, rankPeriod); // initialize List <ConnorsRsiResult> results = CalcConnorsRsiBaseline(bd, rsiPeriod, rankPeriod); int startPeriod = Math.Max(rsiPeriod, Math.Max(streakPeriod, rankPeriod)) + 2; // RSI of streak List <BasicData> bdStreak = results .Where(x => x.Streak != null) .Select(x => new BasicData { Date = x.Date, Value = (decimal)x.Streak }) .ToList(); List <RsiResult> rsiStreakResults = CalcRsi(bdStreak, streakPeriod).ToList(); // compose final results for (int p = streakPeriod + 2; p < results.Count; p++) { ConnorsRsiResult r = results[p]; RsiResult k = rsiStreakResults[p - 1]; r.RsiStreak = k.Rsi; if (p + 1 >= startPeriod) { r.ConnorsRsi = (r.RsiClose + r.RsiStreak + r.PercentRank) / 3; } } return(results); }
// 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"); // validate parameters ValidateDema(bd, lookbackPeriod); // 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 <TQuote>( IEnumerable <TQuote> history, int fastPeriod = 12, int slowPeriod = 26, int signalPeriod = 9) where TQuote : IQuote { // convert history to basic format List <BasicData> bdList = Cleaners.ConvertHistoryToBasic(history, "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); }
// TRIPLE EMA OSCILLATOR (TRIX) public static IEnumerable <TrixResult> GetTrix <TQuote>( IEnumerable <TQuote> history, int lookbackPeriod, int?signalPeriod = null) where TQuote : IQuote { // convert history to basic format List <BasicData> bdList = Cleaners.ConvertHistoryToBasic(history, "C"); // validate parameters ValidateTrix(bdList, lookbackPeriod); // initialize List <TrixResult> results = new List <TrixResult>(bdList.Count); decimal? lastEma = null; List <EmaResult> emaN1 = CalcEma(bdList, lookbackPeriod).ToList(); List <BasicData> bd2 = emaN1 .Where(x => x.Ema != null) .Select(x => new BasicData { Date = x.Date, Value = (decimal)x.Ema }) .ToList(); List <EmaResult> emaN2 = CalcEma(bd2, lookbackPeriod).ToList(); List <BasicData> bd3 = emaN2 .Where(x => x.Ema != null) .Select(x => new BasicData { Date = x.Date, Value = (decimal)x.Ema }) .ToList(); List <EmaResult> emaN3 = CalcEma(bd3, lookbackPeriod).ToList(); // compose final results for (int i = 0; i < emaN1.Count; i++) { EmaResult e1 = emaN1[i]; int index = i + 1; TrixResult result = new TrixResult { Date = e1.Date }; results.Add(result); if (index >= 3 * lookbackPeriod - 2) { EmaResult e2 = emaN2[index - lookbackPeriod]; EmaResult e3 = emaN3[index - 2 * lookbackPeriod + 1]; result.Ema3 = e3.Ema; if (lastEma != null && lastEma != 0) { result.Trix = 100 * (e3.Ema - lastEma) / lastEma; } lastEma = e3.Ema; // optional SMA signal GetTrixSignal(signalPeriod, index, lookbackPeriod, results); } } return(results); }
// CONNORS RSI public static IEnumerable <ConnorsRsiResult> GetConnorsRsi( IEnumerable <Quote> history, int rsiPeriod = 3, int streakPeriod = 2, int rankPeriod = 100) { // convert history to basic format List <BasicData> bd = Cleaners.ConvertHistoryToBasic(history, "C").ToList(); // check parameters ValidateConnorsRsi(bd, rsiPeriod, streakPeriod, rankPeriod); // initialize List <ConnorsRsiResult> results = new List <ConnorsRsiResult>(); List <RsiResult> rsiResults = CalcRsi(bd, rsiPeriod).ToList(); int startPeriod = Math.Max(rsiPeriod, Math.Max(streakPeriod, rankPeriod)) + 2; decimal?lastClose = null; decimal streak = 0; // compose interim results for (int i = 0; i < bd.Count; i++) { BasicData h = bd[i]; ConnorsRsiResult result = new ConnorsRsiResult { Index = (int)h.Index, Date = h.Date, RsiClose = rsiResults[i].Rsi }; // bypass for first record if (lastClose == null) { lastClose = h.Value; results.Add(result); continue; } // streak of up or down if (h.Value == lastClose) { streak = 0; } else if (h.Value > lastClose) { if (streak >= 0) { streak++; } else { streak = 1; } } else // h.Value < lastClose { if (streak <= 0) { streak--; } else { streak = -1; } } result.Streak = streak; // percentile rank result.PeriodGain = (decimal)((lastClose <= 0) ? null : (h.Value - lastClose) / lastClose); if (h.Index > rankPeriod) { List <ConnorsRsiResult> period = results .Where(x => x.Index >= (h.Index - rankPeriod) && x.Index < h.Index) .ToList(); result.PercentRank = 100m * period .Where(x => x.PeriodGain < result.PeriodGain) .Count() / rankPeriod; } results.Add(result); lastClose = h.Value; } // RSI of streak List <BasicData> bdStreak = results .Where(x => x.Streak != null) .Select(x => new BasicData { Index = null, Date = x.Date, Value = (decimal)x.Streak }) .ToList(); IEnumerable <RsiResult> rsiStreakResults = CalcRsi(bdStreak, streakPeriod); // compose final results foreach (ConnorsRsiResult r in results.Where(x => x.Index >= streakPeriod + 2)) { r.RsiStreak = rsiStreakResults .Where(x => x.Index == r.Index - 1) .FirstOrDefault() .Rsi; if (r.Index >= startPeriod) { r.ConnorsRsi = (r.RsiClose + r.RsiStreak + r.PercentRank) / 3; } } return(results); }
// TRIPLE EMA OSCILLATOR (TRIX) public static IEnumerable <TrixResult> GetTrix( IEnumerable <Quote> history, int lookbackPeriod, int?signalPeriod = null) { // convert history to basic format IEnumerable <BasicData> bd = Cleaners.ConvertHistoryToBasic(history, "C"); // validate parameters ValidateTrix(bd, lookbackPeriod); // initialize List <TrixResult> results = new List <TrixResult>(); decimal? lastEma = null; List <EmaResult> emaN1 = CalcEma(bd, lookbackPeriod).ToList(); List <BasicData> bd2 = emaN1 .Where(x => x.Ema != null) .Select(x => new BasicData { Index = null, Date = x.Date, Value = (decimal)x.Ema }) .ToList(); List <EmaResult> emaN2 = CalcEma(bd2, lookbackPeriod).ToList(); List <BasicData> bd3 = emaN2 .Where(x => x.Ema != null) .Select(x => new BasicData { Index = null, Date = x.Date, Value = (decimal)x.Ema }) .ToList(); List <EmaResult> emaN3 = CalcEma(bd3, lookbackPeriod).ToList(); // compose final results for (int i = 0; i < emaN1.Count; i++) { EmaResult e1 = emaN1[i]; TrixResult result = new TrixResult { Index = e1.Index, Date = e1.Date }; results.Add(result); if (e1.Index >= 3 * lookbackPeriod - 2) { EmaResult e2 = emaN2[e1.Index - lookbackPeriod]; EmaResult e3 = emaN3[e2.Index - lookbackPeriod]; result.Ema3 = e3.Ema; if (lastEma != null && lastEma != 0) { result.Trix = 100 * (e3.Ema - lastEma) / lastEma; } lastEma = e3.Ema; // optional SMA if (signalPeriod != null && e1.Index >= 3 * lookbackPeriod - 2 + signalPeriod) { decimal sumSma = 0m; for (int p = e1.Index - (int)signalPeriod; p < e1.Index; p++) { sumSma += (decimal)results[p].Trix; } result.Signal = sumSma / signalPeriod; } } } return(results); }