#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 public enum TimeFrame { Seconds, Minutes, Hours } //This namespace holds Indicators in this folder and is required. Do not change it. namespace NinjaTrader.NinjaScript.Indicators { public class OpeningRange : Indicator { private double OpeningRangeHigh; private double OpeningRangeLow; private int OpeningRangeInSeconds; protected override void OnStateChange() { if (State == State.SetDefaults) { Description = @"Plots the user-defined opening range"; Name = "Opening Range"; Calculate = Calculate.OnPriceChange; IsOverlay = true; 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; OpeningRangeLength = 30; OpeningRangeTimeFrame = TimeFrame.Minutes; OpeningRangeHighStroke = new Stroke(Brushes.Yellow, DashStyleHelper.Solid, 3); OpeningRangeLowStroke = new Stroke(Brushes.Yellow, DashStyleHelper.Solid, 3); AddPlot(Brushes.Transparent, "ORH"); AddPlot(Brushes.Transparent, "ORL"); } else if (State == State.Configure) { OpeningRangeHigh = 0.0; OpeningRangeLow = 0.0; if (OpeningRangeTimeFrame == TimeFrame.Seconds) { AddDataSeries(Data.BarsPeriodType.Second, 1); OpeningRangeInSeconds = OpeningRangeLength; } else if (OpeningRangeTimeFrame == TimeFrame.Hours) { AddDataSeries(Data.BarsPeriodType.Minute, 30); OpeningRangeInSeconds = OpeningRangeLength * 60 * 60; } else { AddDataSeries(Data.BarsPeriodType.Minute, 1); OpeningRangeInSeconds = OpeningRangeLength * 60; } } } protected override void OnBarUpdate() { // Converting time to UTC in order to simplify opening range calculation. DateTime now = Times[BarsInProgress][0].ToUniversalTime(); DateTime marketOpen = now.Date.AddHours(14).AddMinutes(30); DateTime marketClose = now.Date.AddHours(21); if (now > marketClose) { OpeningRangeHigh = 0.0; OpeningRangeLow = 0.0; } if (BarsInProgress == 0) { ORH[0] = OpeningRangeHigh; ORL[0] = OpeningRangeLow; return; } if (now > marketOpen && now <= marketOpen.AddSeconds(OpeningRangeInSeconds)) { // TODO: The OR would ideally start on the first candle of the market session. // As it is, the OR begins plotting on the candle just prior to open. if (Highs[1][0] > OpeningRangeHigh || OpeningRangeHigh == 0.0) { RemoveDrawObject("ORH@" + OpeningRangeHigh); OpeningRangeHigh = Highs[1][0]; Draw.Line(this, "ORH@" + OpeningRangeHigh, true, marketOpen.ToLocalTime(), OpeningRangeHigh, marketClose.ToLocalTime(), OpeningRangeHigh, OpeningRangeHighStroke.Brush, OpeningRangeHighStroke.DashStyleHelper, (int)OpeningRangeHighStroke.Width); } if (Lows[1][0] < OpeningRangeLow || OpeningRangeLow == 0.0) { RemoveDrawObject("ORL@" + OpeningRangeLow); OpeningRangeLow = Lows[1][0]; Draw.Line(this, "ORL@" + OpeningRangeLow, true, marketOpen.ToLocalTime(), OpeningRangeLow, marketClose.ToLocalTime(), OpeningRangeLow, OpeningRangeLowStroke.Brush, OpeningRangeLowStroke.DashStyleHelper, (int)OpeningRangeLowStroke.Width); } } } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name="Length", Description="Length of opening range", Order=1, GroupName="Parameters")] public int OpeningRangeLength { get; set; } [NinjaScriptProperty] [Display(Name="Time Frame", Description="Time frame on which opening range is being calculated", Order=2, GroupName="Parameters")] public TimeFrame OpeningRangeTimeFrame { get; set; } [NinjaScriptProperty] [Display(Name = "Opening Range High", Description = "Opening range high line drawn on chart", Order = 3, GroupName = "Parameters")] public Stroke OpeningRangeHighStroke { get; set; } [NinjaScriptProperty] [Display(Name = "Opening Range Low", Description = "Opening range low line drawn on chart", Order = 4, GroupName = "Parameters")] public Stroke OpeningRangeLowStroke { get; set; } [Browsable(false)] [XmlIgnore] public Series ORH { get { return Values[0]; } } [Browsable(false)] [XmlIgnore] public Series ORL { get { return Values[1]; } } } } #region NinjaScript generated code. Neither change nor remove. namespace NinjaTrader.NinjaScript.Indicators { public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase { private OpeningRange[] cacheOpeningRange; public OpeningRange OpeningRange(int openingRangeLength, TimeFrame openingRangeTimeFrame, Stroke openingRangeHighStroke, Stroke openingRangeLowStroke) { return OpeningRange(Input, openingRangeLength, openingRangeTimeFrame, openingRangeHighStroke, openingRangeLowStroke); } public OpeningRange OpeningRange(ISeries input, int openingRangeLength, TimeFrame openingRangeTimeFrame, Stroke openingRangeHighStroke, Stroke openingRangeLowStroke) { if (cacheOpeningRange != null) for (int idx = 0; idx < cacheOpeningRange.Length; idx++) if (cacheOpeningRange[idx] != null && cacheOpeningRange[idx].OpeningRangeLength == openingRangeLength && cacheOpeningRange[idx].OpeningRangeTimeFrame == openingRangeTimeFrame && cacheOpeningRange[idx].OpeningRangeHighStroke == openingRangeHighStroke && cacheOpeningRange[idx].OpeningRangeLowStroke == openingRangeLowStroke && cacheOpeningRange[idx].EqualsInput(input)) return cacheOpeningRange[idx]; return CacheIndicator(new OpeningRange(){ OpeningRangeLength = openingRangeLength, OpeningRangeTimeFrame = openingRangeTimeFrame, OpeningRangeHighStroke = openingRangeHighStroke, OpeningRangeLowStroke = openingRangeLowStroke }, input, ref cacheOpeningRange); } } } namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns { public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase { public Indicators.OpeningRange OpeningRange(int openingRangeLength, TimeFrame openingRangeTimeFrame, Stroke openingRangeHighStroke, Stroke openingRangeLowStroke) { return indicator.OpeningRange(Input, openingRangeLength, openingRangeTimeFrame, openingRangeHighStroke, openingRangeLowStroke); } public Indicators.OpeningRange OpeningRange(ISeries input , int openingRangeLength, TimeFrame openingRangeTimeFrame, Stroke openingRangeHighStroke, Stroke openingRangeLowStroke) { return indicator.OpeningRange(input, openingRangeLength, openingRangeTimeFrame, openingRangeHighStroke, openingRangeLowStroke); } } } namespace NinjaTrader.NinjaScript.Strategies { public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase { public Indicators.OpeningRange OpeningRange(int openingRangeLength, TimeFrame openingRangeTimeFrame, Stroke openingRangeHighStroke, Stroke openingRangeLowStroke) { return indicator.OpeningRange(Input, openingRangeLength, openingRangeTimeFrame, openingRangeHighStroke, openingRangeLowStroke); } public Indicators.OpeningRange OpeningRange(ISeries input , int openingRangeLength, TimeFrame openingRangeTimeFrame, Stroke openingRangeHighStroke, Stroke openingRangeLowStroke) { return indicator.OpeningRange(input, openingRangeLength, openingRangeTimeFrame, openingRangeHighStroke, openingRangeLowStroke); } } } #endregion