NinjaTrader - Double Smoothed Stochastics
Jun 12, 2023

I do not guarantee the accuracy of this indicator. Use at your own demise.


namespace NinjaTrader.NinjaScript.Indicators
{
	public class DSS : Indicator
	{
		private MIN minLow;
		private MAX maxHigh;
		private Series<double> p0, p1;

		protected override void OnStateChange()
		{
			if (State == State.SetDefaults)
			{
				Description									= @"Double Smoothed Stochastics";
				Name										= "DSS";
				Calculate									= Calculate.OnEachTick;
				IsOverlay									= false;
				DisplayInDataBox							= true;
				DrawOnPricePanel							= true;
				DrawHorizontalGridLines						= true;
				DrawVerticalGridLines						= true;
				PaintPriceMarkers							= true;
				ScaleJustification							= NinjaTrader.Gui.Chart.ScaleJustification.Right;
				//Disable this property if your indicator requires custom values that cumulate with each new market data event. 
				//See Help Guide for additional information.
				IsSuspendedWhileInactive					= true;
				
				Length = 10;
				rLength = 9;
				sLength = 5;
				
				AddPlot(new Stroke(Brushes.Orange, 3), PlotStyle.Line, "DSS");
				AddLine(new Gui.Stroke(Brushes.Red, Gui.DashStyleHelper.Dash, 3), 80, NinjaTrader.Custom.Resource.NinjaScriptIndicatorUpper);
				AddLine(new Gui.Stroke(Brushes.DodgerBlue, Gui.DashStyleHelper.Dash, 2), 50, NinjaTrader.Custom.Resource.NinjaScriptIndicatorZeroLine);
				AddLine(new Gui.Stroke(Brushes.Red, Gui.DashStyleHelper.Dash, 3), 20, NinjaTrader.Custom.Resource.NinjaScriptIndicatorLower);
			}
			else if (State == State.Configure)
			{
				p0 = new Series<double>(this);
				p1 = new Series<double>(this);
				maxHigh	= MAX(High, Length);
				minLow	= MIN(Low, Length);
			}
		}

		protected override void OnBarUpdate()
		{
			p0[0] = maxHigh[0] - minLow[0];
			double div = EMA(EMA(p0, sLength), rLength)[0];
			
			p1[0] = Close[0] - minLow[0];
			var ema = EMA(EMA(p1, sLength), rLength);
			
			if (div == 0)
				K[0] = 0;
			else
				K[0] = 100 * ema[0] / div;
		}
		
		#region Properties
		[Browsable(false)]	// this line prevents the data series from being displayed in the indicator properties dialog, do not remove
		[XmlIgnore()]		// this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove
		public Series<double> K
		{
			get { return Values[0]; }
		}

		[Range(1, int.MaxValue), NinjaScriptProperty]
		[Display(ResourceType = typeof(Custom.Resource), Name = "Length", GroupName = "NinjaScriptParameters", Order = 0)]
		public int Length
		{ get; set; }
		
		[Range(1, int.MaxValue), NinjaScriptProperty]
		[Display(ResourceType = typeof(Custom.Resource), Name = "rLength", GroupName = "NinjaScriptParameters", Order = 1)]
		public int rLength
		{ get; set; }
		
		[Range(1, int.MaxValue), NinjaScriptProperty]
		[Display(ResourceType = typeof(Custom.Resource), Name = "sLength", GroupName = "NinjaScriptParameters", Order = 2)]
		public int sLength
		{ get; set; }
		#endregion
	}
}
Comments