From 82ed1266ec43969a38dcfab7f221292f64cef981 Mon Sep 17 00:00:00 2001 From: moshferatu Date: Mon, 12 Aug 2024 08:31:52 -0700 Subject: [PATCH] Add ConnorsRSI indicator, credit to Larry Connors' Buy the Fear, Sell the Greed --- indicators/ConnorsRSI.cs | 172 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 indicators/ConnorsRSI.cs diff --git a/indicators/ConnorsRSI.cs b/indicators/ConnorsRSI.cs new file mode 100644 index 0000000..76aa47d --- /dev/null +++ b/indicators/ConnorsRSI.cs @@ -0,0 +1,172 @@ +#region Using declarations +using NinjaTrader.Gui; +using NinjaTrader.Gui.Chart; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Windows.Media; +#endregion + +namespace NinjaTrader.NinjaScript.Indicators +{ + public class ConnorsRSI : Indicator + { + private RSI rsi; + private RSI streakRsi; + + private Series streak; + private Series returns; + + protected override void OnStateChange() + { + if (State == State.SetDefaults) + { + Description = @"Credit to Larry Connors"; + Name = "ConnorsRSI"; + Calculate = Calculate.OnBarClose; + IsOverlay = false; + DisplayInDataBox = true; + DrawOnPricePanel = true; + DrawHorizontalGridLines = true; + DrawVerticalGridLines = true; + PaintPriceMarkers = true; + ScaleJustification = ScaleJustification.Right; + IsSuspendedWhileInactive = true; + + RSIPeriod = 3; + RSISmoothing = 1; + StreakRSIPeriod = 2; + StreakRSISmoothing = 1; + PercentRankPeriod = 100; + + AddPlot(new Stroke(Brushes.Yellow, 3), PlotStyle.Line, "ConnorsRSI"); + } + else if (State == State.DataLoaded) + { + rsi = RSI(RSIPeriod, RSISmoothing); + + streak = new Series(this); + streakRsi = RSI(streak, StreakRSIPeriod, StreakRSISmoothing); + + returns = new Series(this); + } + } + + protected override void OnBarUpdate() + { + if (CurrentBar < Math.Max(RSIPeriod, Math.Max(StreakRSIPeriod, PercentRankPeriod))) + return; + + if (Close[0] > Close[1]) + { + if (streak[1] > 0) + streak[0] = streak[1] + 1; + else + streak[0] = 1; + } + else if (Close[0] < Close[1]) + { + if (streak[1] < 0) + streak[0] = streak[1] - 1; + else + streak[0] = -1; + } + else + streak[0] = 0; + + returns[0] = (Close[0] - Close[1]) / Close[1]; + + List dailyReturns = new List(); + for (int i = PercentRankPeriod; i > 0; i--) + dailyReturns.Add(returns[i]); + + int rank = dailyReturns.Count(x => x < returns[0]); + double percentRank = (double)rank / PercentRankPeriod * 100; + + Value[0] = (rsi[0] + streakRsi[0] + percentRank) / 3; + } + + public override string DisplayName + { + get { return Name; } + } + + [NinjaScriptProperty] + [Display(Name = "RSI Period", GroupName = "ConnorsRSI", Order = 1)] + public int RSIPeriod { get; set; } + + [NinjaScriptProperty] + [Display(Name = "RSI Smoothing", GroupName = "ConnorsRSI", Order = 2)] + public int RSISmoothing { get; set; } + + [NinjaScriptProperty] + [Display(Name = "Streak RSI Period", GroupName = "ConnorsRSI", Order = 3)] + public int StreakRSIPeriod { get; set; } + + [NinjaScriptProperty] + [Display(Name = "Streak RSI Smoothing", GroupName = "ConnorsRSI", Order = 4)] + public int StreakRSISmoothing { get; set; } + + [NinjaScriptProperty] + [Display(Name = "Percent Rank Period", GroupName = "ConnorsRSI", Order = 5)] + public int PercentRankPeriod { get; set; } + } +} + +#region NinjaScript generated code. Neither change nor remove. + +namespace NinjaTrader.NinjaScript.Indicators +{ + public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase + { + private ConnorsRSI[] cacheConnorsRSI; + public ConnorsRSI ConnorsRSI(int rSIPeriod, int rSISmoothing, int streakRSIPeriod, int streakRSISmoothing, int percentRankPeriod) + { + return ConnorsRSI(Input, rSIPeriod, rSISmoothing, streakRSIPeriod, streakRSISmoothing, percentRankPeriod); + } + + public ConnorsRSI ConnorsRSI(ISeries input, int rSIPeriod, int rSISmoothing, int streakRSIPeriod, int streakRSISmoothing, int percentRankPeriod) + { + if (cacheConnorsRSI != null) + for (int idx = 0; idx < cacheConnorsRSI.Length; idx++) + if (cacheConnorsRSI[idx] != null && cacheConnorsRSI[idx].RSIPeriod == rSIPeriod && cacheConnorsRSI[idx].RSISmoothing == rSISmoothing && cacheConnorsRSI[idx].StreakRSIPeriod == streakRSIPeriod && cacheConnorsRSI[idx].StreakRSISmoothing == streakRSISmoothing && cacheConnorsRSI[idx].PercentRankPeriod == percentRankPeriod && cacheConnorsRSI[idx].EqualsInput(input)) + return cacheConnorsRSI[idx]; + return CacheIndicator(new ConnorsRSI(){ RSIPeriod = rSIPeriod, RSISmoothing = rSISmoothing, StreakRSIPeriod = streakRSIPeriod, StreakRSISmoothing = streakRSISmoothing, PercentRankPeriod = percentRankPeriod }, input, ref cacheConnorsRSI); + } + } +} + +namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns +{ + public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase + { + public Indicators.ConnorsRSI ConnorsRSI(int rSIPeriod, int rSISmoothing, int streakRSIPeriod, int streakRSISmoothing, int percentRankPeriod) + { + return indicator.ConnorsRSI(Input, rSIPeriod, rSISmoothing, streakRSIPeriod, streakRSISmoothing, percentRankPeriod); + } + + public Indicators.ConnorsRSI ConnorsRSI(ISeries input , int rSIPeriod, int rSISmoothing, int streakRSIPeriod, int streakRSISmoothing, int percentRankPeriod) + { + return indicator.ConnorsRSI(input, rSIPeriod, rSISmoothing, streakRSIPeriod, streakRSISmoothing, percentRankPeriod); + } + } +} + +namespace NinjaTrader.NinjaScript.Strategies +{ + public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase + { + public Indicators.ConnorsRSI ConnorsRSI(int rSIPeriod, int rSISmoothing, int streakRSIPeriod, int streakRSISmoothing, int percentRankPeriod) + { + return indicator.ConnorsRSI(Input, rSIPeriod, rSISmoothing, streakRSIPeriod, streakRSISmoothing, percentRankPeriod); + } + + public Indicators.ConnorsRSI ConnorsRSI(ISeries input , int rSIPeriod, int rSISmoothing, int streakRSIPeriod, int streakRSISmoothing, int percentRankPeriod) + { + return indicator.ConnorsRSI(input, rSIPeriod, rSISmoothing, streakRSIPeriod, streakRSISmoothing, percentRankPeriod); + } + } +} + +#endregion