private static List <ConnorsRsiResult> CalcConnorsRsiBaseline( List <BasicData> bdList, int rsiPeriod, int rankPeriod) { // initialize List <RsiResult> rsiResults = CalcRsi(bdList, rsiPeriod).ToList(); int size = bdList.Count; List <ConnorsRsiResult> results = new List <ConnorsRsiResult>(size); decimal?[] gain = new decimal?[size]; decimal?lastClose = null; decimal streak = 0; // compose interim results for (int i = 0; i < size; i++) { BasicData h = bdList[i]; int index = i + 1; ConnorsRsiResult result = new ConnorsRsiResult { 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 gain[i] = (lastClose == 0) ? null : (decimal)((lastClose <= 0) ? null : (h.Value - lastClose) / lastClose); results.Add(result); if (index > rankPeriod) { int qty = 0; for (int p = index - rankPeriod - 1; p < index; p++) { if (gain[p] < gain[i]) { qty++; } } result.PercentRank = 100m * qty / rankPeriod; } lastClose = h.Value; } 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 IEnumerable <BasicData> bd = Cleaners.ConvertHistoryToBasic(history, "C"); // check parameters ValidateConnorsRsi(bd, rsiPeriod, streakPeriod, rankPeriod); // initialize List <ConnorsRsiResult> results = new List <ConnorsRsiResult>(); IEnumerable <RsiResult> rsiResults = CalcRsi(bd, rsiPeriod); int startPeriod = Math.Max(rsiPeriod, Math.Max(streakPeriod, rankPeriod)) + 2; decimal?lastClose = null; decimal streak = 0; // compose interim results foreach (BasicData h in bd) { ConnorsRsiResult result = new ConnorsRsiResult { Index = (int)h.Index, Date = h.Date, RsiClose = rsiResults.Where(x => x.Index == h.Index).FirstOrDefault().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) { IEnumerable <ConnorsRsiResult> period = results .Where(x => x.Index >= (h.Index - rankPeriod) && x.Index < h.Index); result.PercentRank = (decimal)100 * 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); }