diff --git a/indicators/ADR.cs b/indicators/ADR.cs new file mode 100644 index 0000000..5808ed4 --- /dev/null +++ b/indicators/ADR.cs @@ -0,0 +1,199 @@ +#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; +using NinjaTrader.Gui.PropertiesTest; +#endregion + +//This namespace holds Indicators in this folder and is required. Do not change it. +namespace NinjaTrader.NinjaScript.Indicators +{ + public class DailyRange + { + public DateTime Date { get; set; } + public double UpperLevel { get; set; } + public double LowerLevel { get; set; } + } + + public class ADR : Indicator + { + private const int PrimaryBars = 0; + private const int DailyBars = 1; + + private TimeSpan SessionOpen; + private TimeSpan SessionClose; + + private List DailyRanges = new List(); + + protected override void OnStateChange() + { + if (State == State.SetDefaults) + { + Description = @"Average Daily Range (ADR)"; + Name = "ADR"; + Calculate = Calculate.OnBarClose; + IsOverlay = true; + DrawOnPricePanel = true; + ScaleJustification = ScaleJustification.Right; + IsSuspendedWhileInactive = false; + + RangePeriod = 5; + ADRHighStroke = new Stroke(Brushes.Yellow, 3); + ADRLowStroke = new Stroke(Brushes.Yellow, 3); + } + else if (State == State.Configure) + { + AddDataSeries(Instrument.FullName, new BarsPeriod { BarsPeriodType = BarsPeriodType.Day, Value = 1 }, + RangePeriod + 5, Bars.TradingHours.Name, Bars.IsResetOnNewTradingDay); + } + else if (State == State.DataLoaded) + { + SessionIterator chartSession = new SessionIterator(BarsArray[PrimaryBars]); + SessionOpen = chartSession.GetTradingDayBeginLocal(chartSession.ActualTradingDayExchange).TimeOfDay; + SessionClose = chartSession.GetTradingDayEndLocal(chartSession.ActualTradingDayExchange).TimeOfDay; + } + else if (State == State.Historical) + { + SetZOrder(-1); // Display behind bars on chart. + } + } + + protected override void OnBarUpdate() + { + if (DailyBars != BarsInProgress || CurrentBar < RangePeriod) + return; + + double totalRange = 0; + for (int i = 0; i < RangePeriod; i++) + { + totalRange += Highs[DailyBars][i] - Lows[DailyBars][i]; + } + double averageRange = totalRange / RangePeriod; + + DailyRanges.Add(new DailyRange + { + Date = Time[0].Date.AddDays(1), + UpperLevel = Closes[DailyBars][0] + (averageRange / 2), + LowerLevel = Closes[DailyBars][0] - (averageRange / 2), + }); + } + + protected override void OnRender(ChartControl chartControl, ChartScale chartScale) + { + base.OnRender(chartControl, chartScale); + + foreach (var Range in DailyRanges) + { + int startX = ChartControl.GetXByTime(Range.Date.AddDays(-1).Add(SessionOpen)); + int endX = ChartControl.GetXByTime(Range.Date.Add(SessionClose)); + + DrawHorizontalLine(startX, endX, chartScale.GetYByValue(Range.UpperLevel), ADRHighStroke); + DrawHorizontalLine(startX, endX, chartScale.GetYByValue(Range.LowerLevel), ADRLowStroke); + } + } + + private void DrawHorizontalLine(int startX, int endX, int y, Stroke stroke) + { + SharpDX.Direct2D1.Brush dxBrush = stroke.Brush.ToDxBrush(RenderTarget); + RenderTarget.DrawLine( + new SharpDX.Vector2(startX, y), + new SharpDX.Vector2(endX, y), + dxBrush, stroke.Width, stroke.StrokeStyle + ); + dxBrush.Dispose(); + } + + public override string DisplayName + { + get { return Name; } + } + + [NinjaScriptProperty] + [Range(1, int.MaxValue)] + [Display(Name = "Range Period", GroupName = "Average Daily Range", Order = 1)] + public int RangePeriod + { get; set; } + + [NinjaScriptProperty] + [Display(Name = "ADR High", Order = 2, GroupName = "Average Daily Range")] + public Stroke ADRHighStroke { get; set; } + + [NinjaScriptProperty] + [Display(Name = "ADR Low", Order = 3, GroupName = "Average Daily Range")] + public Stroke ADRLowStroke { get; set; } + } +} + +#region NinjaScript generated code. Neither change nor remove. + +namespace NinjaTrader.NinjaScript.Indicators +{ + public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase + { + private ADR[] cacheADR; + public ADR ADR(int rangePeriod, Stroke aDRHighStroke, Stroke aDRLowStroke) + { + return ADR(Input, rangePeriod, aDRHighStroke, aDRLowStroke); + } + + public ADR ADR(ISeries input, int rangePeriod, Stroke aDRHighStroke, Stroke aDRLowStroke) + { + if (cacheADR != null) + for (int idx = 0; idx < cacheADR.Length; idx++) + if (cacheADR[idx] != null && cacheADR[idx].RangePeriod == rangePeriod && cacheADR[idx].ADRHighStroke == aDRHighStroke && cacheADR[idx].ADRLowStroke == aDRLowStroke && cacheADR[idx].EqualsInput(input)) + return cacheADR[idx]; + return CacheIndicator(new ADR(){ RangePeriod = rangePeriod, ADRHighStroke = aDRHighStroke, ADRLowStroke = aDRLowStroke }, input, ref cacheADR); + } + } +} + +namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns +{ + public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase + { + public Indicators.ADR ADR(int rangePeriod, Stroke aDRHighStroke, Stroke aDRLowStroke) + { + return indicator.ADR(Input, rangePeriod, aDRHighStroke, aDRLowStroke); + } + + public Indicators.ADR ADR(ISeries input , int rangePeriod, Stroke aDRHighStroke, Stroke aDRLowStroke) + { + return indicator.ADR(input, rangePeriod, aDRHighStroke, aDRLowStroke); + } + } +} + +namespace NinjaTrader.NinjaScript.Strategies +{ + public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase + { + public Indicators.ADR ADR(int rangePeriod, Stroke aDRHighStroke, Stroke aDRLowStroke) + { + return indicator.ADR(Input, rangePeriod, aDRHighStroke, aDRLowStroke); + } + + public Indicators.ADR ADR(ISeries input , int rangePeriod, Stroke aDRHighStroke, Stroke aDRLowStroke) + { + return indicator.ADR(input, rangePeriod, aDRHighStroke, aDRLowStroke); + } + } +} + +#endregion