I'm trying to adapt Stochastics indicator in order to use it over another indicator (not price, not High and Low, just a value), so I've modified the original Stochastics code (just the three lines marked), but the indicator in real time fails; the top value, which should be 100, goes higher, to 140 for example, when I have the indicator running for some hours. EDIT: Just add that when top value goes to 140, bottom value is 40. It looks like values slide 40 to the top for some reason.
I'm pretty sure the code should be really simple, but I don't know exactly how to modify it to get just that, a stochastics over a series of values which have no High and Low but just a simple value.
Thanks in advance for any help.
MyStochastics code:
#region Using declarations using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Media; using System.Xml.Serialization; using NinjaTrader.Cbi; using NinjaTrader.Gui; using NinjaTrader.Gui.Chart; using NinjaTrader.Gui.SuperDom; using NinjaTrader.Gui.Tools; using NinjaTrader.Data; using NinjaTrader.NinjaScript; using NinjaTrader.Core.FloatingPoint; using NinjaTrader.NinjaScript.DrawingTools; #endregion // This namespace holds indicators in this folder and is required. Do not change it. namespace NinjaTrader.NinjaScript.Indicators { /// <summary> /// The Stochastic Oscillator is made up of two lines that oscillate between /// a vertical scale of 0 to 100. The %K is the main line and it is drawn as /// a solid line. The second is the %D line and is a moving average of %K. /// The %D line is drawn as a dotted line. Use as a buy/sell signal generator, /// buying when fast moves above slow and selling when fast moves below slow. /// </summary> public class MyStochastics : Indicator { private Series<double> den; private Series<double> fastK; private MIN min; private MAX max; private Series<double> nom; private SMA smaFastK; private SMA smaK; protected override void OnStateChange() { if (State == State.SetDefaults) { Description = NinjaTrader.Custom.Resource.NinjaScriptIndicatorDescriptionStochastics; Name = "MyStochastics"; IsSuspendedWhileInactive = true; PeriodD = 7; PeriodK = 14; Smooth = 3; AddPlot(Brushes.DodgerBlue, NinjaTrader.Custom.Resource.StochasticsD); AddPlot(Brushes.Goldenrod, NinjaTrader.Custom.Resource.StochasticsK); AddLine(Brushes.DarkCyan, 20, NinjaTrader.Custom.Resource.NinjaScriptIndicatorLower); AddLine(Brushes.DarkCyan, 80, NinjaTrader.Custom.Resource.NinjaScriptIndicatorUpper); } else if (State == State.Configure) { den = new Series<double>(this); nom = new Series<double>(this); fastK = new Series<double>(this); min = MIN(Input, PeriodK); // [B]<<<<<<<<<<<<<< MODIFIED LINE (Low => Input)[/B] max = MAX(Input, PeriodK); [B]// <<<<<<<<<<<<<< MODIFIED LINE (Max => Input)[/B] smaFastK = SMA(fastK, Smooth); smaK = SMA(K, PeriodD); } } protected override void OnBarUpdate() { double min0 = min[0]; nom[0] = Input[0] - min0; [B]// <<<<<<<<<<<<<<<<<<<<<<<<<<< MODIFIED LINE (Close[0] => Input[0])[/B] den[0] = max[0] - min0; if (den[0].ApproxCompare(0) == 0) fastK[0] = CurrentBar == 0 ? 50 : fastK[1]; else fastK[0] = Math.Min(100, Math.Max(0, 100 * nom[0] / den[0])); // Slow %K == Fast %D K[0] = smaFastK[0]; D[0] = smaK[0]; } #region Properties [Browsable(false)] [XmlIgnore()] public Series<double> D { get { return Values[0]; } } [Browsable(false)] [XmlIgnore()] public Series<double> K { get { return Values[1]; } } [Range(1, int.MaxValue), NinjaScriptProperty] [Display(ResourceType = typeof(Custom.Resource), Name = "PeriodD", GroupName = "NinjaScriptParameters", Order = 0)] public int PeriodD { get; set; } [Range(1, int.MaxValue), NinjaScriptProperty] [Display(ResourceType = typeof(Custom.Resource), Name = "PeriodK", GroupName = "NinjaScriptParameters", Order = 1)] public int PeriodK { get; set; } [Range(1, int.MaxValue), NinjaScriptProperty] [Display(ResourceType = typeof(Custom.Resource), Name = "Smooth", GroupName = "NinjaScriptParameters", Order = 2)] public int Smooth { get; set; } #endregion } } #region NinjaScript generated code. Neither change nor remove. namespace NinjaTrader.NinjaScript.Indicators { public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase { private MyStochastics[] cacheMyStochastics; public MyStochastics MyStochastics(int periodD, int periodK, int smooth) { return MyStochastics(Input, periodD, periodK, smooth); } public MyStochastics MyStochastics(ISeries<double> input, int periodD, int periodK, int smooth) { if (cacheMyStochastics != null) for (int idx = 0; idx < cacheMyStochastics.Length; idx++) if (cacheMyStochastics[idx] != null && cacheMyStochastics[idx].PeriodD == periodD && cacheMyStochastics[idx].PeriodK == periodK && cacheMyStochastics[idx].Smooth == smooth && cacheMyStochastics[idx].EqualsInput(input)) return cacheMyStochastics[idx]; return CacheIndicator<MyStochastics>(new MyStochastics(){ PeriodD = periodD, PeriodK = periodK, Smooth = smooth }, input, ref cacheMyStochastics); } } } namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns { public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase { public Indicators.MyStochastics MyStochastics(int periodD, int periodK, int smooth) { return indicator.MyStochastics(Input, periodD, periodK, smooth); } public Indicators.MyStochastics MyStochastics(ISeries<double> input , int periodD, int periodK, int smooth) { return indicator.MyStochastics(input, periodD, periodK, smooth); } } } namespace NinjaTrader.NinjaScript.Strategies { public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase { public Indicators.MyStochastics MyStochastics(int periodD, int periodK, int smooth) { return indicator.MyStochastics(Input, periodD, periodK, smooth); } public Indicators.MyStochastics MyStochastics(ISeries<double> input , int periodD, int periodK, int smooth) { return indicator.MyStochastics(input, periodD, periodK, smooth); } } } #endregion
Comment