#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 namespace NinjaTrader.NinjaScript.Indicators { /// /// The Daily Factor Indicator was created by Andrea Unger (Stocks and Commodities Jun 2023 pgs 26-31), and this is a new volatility indicator /// that compares the body, which is the absolute difference between the previous open and previous close, and the range which is the difference /// between the previous high and previous low. The indicator is calculated by dividing the body and range to determine the volatility for the /// previous bar. This indicator will range between 0 and 1. Values closer to 1 mean very high volatility, and values closer to 0 mean very low /// volatility. I have introduced an EMA to decide buy or sell signals and colors. Darker colors mean the indicator is /// above the threshold level, and lighter colors mean the indicator is below the threshold level. Colors are shades of green when the price is /// above the moving average and shades of red when the price is below the moving average. Feel free to try out your own threshold level and /// general buy and sell signals. /// public class DFI : Indicator { private EMA ema; private Stroke hLine; protected override void OnStateChange() { if (State == State.SetDefaults) { Description = @"Daily Factor (Strategy by @cheatcountry) NT8 v1.2 by @fercho"; Name = "DFI"; Calculate = Calculate.OnBarClose; IsOverlay = false; DrawOnPricePanel = false; IsSuspendedWhileInactive = true; ScaleJustification = NinjaTrader.Gui.Chart.ScaleJustification.Right; ///Define input parameters DFLevel = 0.70; AllowRepainting = false; AllowBarColorChange = true; AddPlot(Brushes.Red, "Daily Factor"); hLine = new Stroke(Brushes.DarkCyan, DashStyleHelper.DashDot, 1); AddLine(hLine,DFLevel,"DFLevel"); } else if (State == State.DataLoaded) { ema = EMA(Close,14); } } protected override void OnBarUpdate() { if (CurrentBar < 1) return; // Calculate Daily Factor DF[0] = High[1] != Low[1] ? Math.Abs(Open[1] - Close[1])/(High[1] - Low[1]) : 0; ///Determine signal int sig = 0; if (DF[0] >= DFLevel && Close[0] >= ema[0]) sig = 2; else if (DF[0] >= DFLevel && Close[0] < ema[0]) sig = -2; else if (Close[0] >= ema[0]) sig = 1; else if (Close[0] < ema[0]) sig = -1; ///Set bar color if enabled if (AllowBarColorChange) { if (sig > 1) PlotBrushes[0][0] = Brushes.Green; else if (sig > 0) PlotBrushes[0][0] = Brushes.Lime; else if (sig < -1) PlotBrushes[0][0] = Brushes.Maroon; else if (sig < 0) PlotBrushes[0][0] = Brushes.Red; else PlotBrushes[0][0] = Brushes.Transparent; } } #region Properties [Browsable(false)] [XmlIgnore()] public Series DF { get { return Values[0]; } } [NinjaScriptProperty] [Range(0, 1)] [Display(Name = "Daily Factor Threshold Level", Order = 0, GroupName = "Parameters")] public double DFLevel { get; set; } [NinjaScriptProperty] [Display(Name = "Allow Repainting?", Order = 1, GroupName = "Parameters")] public bool AllowRepainting { get; set; } [NinjaScriptProperty] [Display(Name = "Allow Bar Color Change?", Order = 2, GroupName = "Parameters")] public bool AllowBarColorChange { get; set; } #endregion } } #region NinjaScript generated code. Neither change nor remove. namespace NinjaTrader.NinjaScript.Indicators { public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase { private DFI[] cacheDFI; public DFI DFI(double dFLevel, bool allowRepainting, bool allowBarColorChange) { return DFI(Input, dFLevel, allowRepainting, allowBarColorChange); } public DFI DFI(ISeries input, double dFLevel, bool allowRepainting, bool allowBarColorChange) { if (cacheDFI != null) for (int idx = 0; idx < cacheDFI.Length; idx++) if (cacheDFI[idx] != null && cacheDFI[idx].DFLevel == dFLevel && cacheDFI[idx].AllowRepainting == allowRepainting && cacheDFI[idx].AllowBarColorChange == allowBarColorChange && cacheDFI[idx].EqualsInput(input)) return cacheDFI[idx]; return CacheIndicator(new DFI(){ DFLevel = dFLevel, AllowRepainting = allowRepainting, AllowBarColorChange = allowBarColorChange }, input, ref cacheDFI); } } } namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns { public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase { public Indicators.DFI DFI(double dFLevel, bool allowRepainting, bool allowBarColorChange) { return indicator.DFI(Input, dFLevel, allowRepainting, allowBarColorChange); } public Indicators.DFI DFI(ISeries input , double dFLevel, bool allowRepainting, bool allowBarColorChange) { return indicator.DFI(input, dFLevel, allowRepainting, allowBarColorChange); } } } namespace NinjaTrader.NinjaScript.Strategies { public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase { public Indicators.DFI DFI(double dFLevel, bool allowRepainting, bool allowBarColorChange) { return indicator.DFI(Input, dFLevel, allowRepainting, allowBarColorChange); } public Indicators.DFI DFI(ISeries input , double dFLevel, bool allowRepainting, bool allowBarColorChange) { return indicator.DFI(input, dFLevel, allowRepainting, allowBarColorChange); } } } #endregion