#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 { [CategoryOrder("Bollinger Bands", 1)] [CategoryOrder("Plots", 2)] public class PercentB : Indicator { private Bollinger BollingerBands; protected override void OnStateChange() { if (State == State.SetDefaults) { Description = @"Measures price in relation to the upper and lower Bollinger Bands"; Name = "%B"; Calculate = Calculate.OnBarClose; IsOverlay = false; DisplayInDataBox = true; DrawOnPricePanel = false; DrawHorizontalGridLines = false; DrawVerticalGridLines = false; PaintPriceMarkers = false; ScaleJustification = ScaleJustification.Right; IsSuspendedWhileInactive = true; Period = 20; StandardDeviations = 2.0; UpperLevel = 1.0; LowerLevel = 0.0; UpperLevelStroke = new Stroke(Brushes.LimeGreen, 3); LowerLevelStroke = new Stroke(Brushes.Red, 3); AddPlot(new Stroke(Brushes.Yellow, 2), PlotStyle.Line, "%B"); } else if (State == State.Configure) { BollingerBands = Bollinger(StandardDeviations, Period); AddLine(UpperLevelStroke, UpperLevel, "Upper Level"); AddLine(LowerLevelStroke, LowerLevel, "Lower Level"); } } protected override void OnBarUpdate() { if (CurrentBar < Period) return; double upperBand = BollingerBands.Upper[0]; double lowerBand = BollingerBands.Lower[0]; Value[0] = (Close[0] - lowerBand) / (upperBand - lowerBand); } public override string DisplayName { get { return Name; } } #region Properties [Browsable(true)] [Range(1, int.MaxValue)] [NinjaScriptProperty] [Display(ResourceType = typeof(Custom.Resource), Name = "Moving Average Period", GroupName = "Bollinger Bands", Order = 1)] public int Period { get; set; } [Browsable(true)] [Range(0.1, double.MaxValue)] [NinjaScriptProperty] [Display(ResourceType = typeof(Custom.Resource), Name = "Standard Deviations", GroupName = "Bollinger Bands", Order = 2)] public double StandardDeviations { get; set; } [NinjaScriptProperty] [Range(double.MinValue, double.MaxValue)] [Display(Name = "Upper Level", GroupName = "Plots", Order = 2)] public double UpperLevel { get; set; } [NinjaScriptProperty] [Display(Name = "Upper Level Stroke", GroupName = "Plots", Order = 3)] public Stroke UpperLevelStroke { get; set; } [NinjaScriptProperty] [Range(double.MinValue, double.MaxValue)] [Display(Name = "Lower Level", GroupName = "Plots", Order = 4)] public double LowerLevel { get; set; } [NinjaScriptProperty] [Display(Name = "Lower Level Stroke", GroupName = "Plots", Order = 5)] public Stroke LowerLevelStroke { get; set; } #endregion } } #region NinjaScript generated code. Neither change nor remove. namespace NinjaTrader.NinjaScript.Indicators { public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase { private PercentB[] cachePercentB; public PercentB PercentB(int period, double standardDeviations, double upperLevel, Stroke upperLevelStroke, double lowerLevel, Stroke lowerLevelStroke) { return PercentB(Input, period, standardDeviations, upperLevel, upperLevelStroke, lowerLevel, lowerLevelStroke); } public PercentB PercentB(ISeries input, int period, double standardDeviations, double upperLevel, Stroke upperLevelStroke, double lowerLevel, Stroke lowerLevelStroke) { if (cachePercentB != null) for (int idx = 0; idx < cachePercentB.Length; idx++) if (cachePercentB[idx] != null && cachePercentB[idx].Period == period && cachePercentB[idx].StandardDeviations == standardDeviations && cachePercentB[idx].UpperLevel == upperLevel && cachePercentB[idx].UpperLevelStroke == upperLevelStroke && cachePercentB[idx].LowerLevel == lowerLevel && cachePercentB[idx].LowerLevelStroke == lowerLevelStroke && cachePercentB[idx].EqualsInput(input)) return cachePercentB[idx]; return CacheIndicator(new PercentB(){ Period = period, StandardDeviations = standardDeviations, UpperLevel = upperLevel, UpperLevelStroke = upperLevelStroke, LowerLevel = lowerLevel, LowerLevelStroke = lowerLevelStroke }, input, ref cachePercentB); } } } namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns { public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase { public Indicators.PercentB PercentB(int period, double standardDeviations, double upperLevel, Stroke upperLevelStroke, double lowerLevel, Stroke lowerLevelStroke) { return indicator.PercentB(Input, period, standardDeviations, upperLevel, upperLevelStroke, lowerLevel, lowerLevelStroke); } public Indicators.PercentB PercentB(ISeries input , int period, double standardDeviations, double upperLevel, Stroke upperLevelStroke, double lowerLevel, Stroke lowerLevelStroke) { return indicator.PercentB(input, period, standardDeviations, upperLevel, upperLevelStroke, lowerLevel, lowerLevelStroke); } } } namespace NinjaTrader.NinjaScript.Strategies { public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase { public Indicators.PercentB PercentB(int period, double standardDeviations, double upperLevel, Stroke upperLevelStroke, double lowerLevel, Stroke lowerLevelStroke) { return indicator.PercentB(Input, period, standardDeviations, upperLevel, upperLevelStroke, lowerLevel, lowerLevelStroke); } public Indicators.PercentB PercentB(ISeries input , int period, double standardDeviations, double upperLevel, Stroke upperLevelStroke, double lowerLevel, Stroke lowerLevelStroke) { return indicator.PercentB(input, period, standardDeviations, upperLevel, upperLevelStroke, lowerLevel, lowerLevelStroke); } } } #endregion