#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 Volatility : Indicator { private List volatilities; private double currentVolatility; protected override void OnStateChange() { if (State == State.SetDefaults) { Description = @"Measures volatility based on the standard deviation of price over the defined period"; Name = "Volatility"; Calculate = Calculate.OnPriceChange; IsOverlay = false; DisplayInDataBox = true; DrawOnPricePanel = true; PaintPriceMarkers = true; ScaleJustification = ScaleJustification.Right; IsSuspendedWhileInactive = true; StdDevPeriod = 20; PctRankPeriod = 252; EMAPeriod = 100; AddPlot(new Stroke(Brushes.Yellow, DashStyleHelper.Solid, 3), PlotStyle.Line, "Volatility"); AddPlot(new Stroke(Brushes.Gray, DashStyleHelper.Solid, 3), PlotStyle.Line, "EMA"); } else if (State == State.DataLoaded) { volatilities = new List(); currentVolatility = double.MinValue; } } protected override void OnBarUpdate() { if (CurrentBar < StdDevPeriod) return; if (IsFirstTickOfBar && currentVolatility > double.MinValue) { volatilities.Add(currentVolatility); if (volatilities.Count > PctRankPeriod) volatilities.RemoveAt(0); } currentVolatility = StdDev(Close, StdDevPeriod)[0]; PercentRank[0] = CalculatePercentRank(volatilities, currentVolatility); Average[0] = EMA(Value, EMAPeriod)[0]; } private double CalculatePercentRank(List values, double currentValue) { if (values.Count == 0) return 0; int rank = values.Count(v => v <= currentValue); return (double)rank / values.Count * 100.0; } public override string DisplayName { get { return Name; } } [Browsable(false)] [XmlIgnore] public Series PercentRank { get { return Values[0]; } } [Browsable(false)] [XmlIgnore] public Series Average { get { return Values[1]; } } [Range(1, int.MaxValue), NinjaScriptProperty] [Display(Name = "Std Dev Period", Description = "Period for calculating the standard deviation of price", Order = 1, GroupName = "Volatility")] public int StdDevPeriod { get; set; } [Range(1, int.MaxValue), NinjaScriptProperty] [Display(Name = "Pct Rank Period", Description = "Period for calculating the percent rank of volatility", Order = 2, GroupName = "Volatility")] public int PctRankPeriod { get; set; } [Range(1, int.MaxValue), NinjaScriptProperty] [Display(Name = "EMA Period", Description = "Period for calculating the moving average of price", Order = 3, GroupName = "Volatility")] public int EMAPeriod { get; set; } } } #region NinjaScript generated code. Neither change nor remove. namespace NinjaTrader.NinjaScript.Indicators { public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase { private Volatility[] cacheVolatility; public Volatility Volatility(int stdDevPeriod, int pctRankPeriod, int eMAPeriod) { return Volatility(Input, stdDevPeriod, pctRankPeriod, eMAPeriod); } public Volatility Volatility(ISeries input, int stdDevPeriod, int pctRankPeriod, int eMAPeriod) { if (cacheVolatility != null) for (int idx = 0; idx < cacheVolatility.Length; idx++) if (cacheVolatility[idx] != null && cacheVolatility[idx].StdDevPeriod == stdDevPeriod && cacheVolatility[idx].PctRankPeriod == pctRankPeriod && cacheVolatility[idx].EMAPeriod == eMAPeriod && cacheVolatility[idx].EqualsInput(input)) return cacheVolatility[idx]; return CacheIndicator(new Volatility(){ StdDevPeriod = stdDevPeriod, PctRankPeriod = pctRankPeriod, EMAPeriod = eMAPeriod }, input, ref cacheVolatility); } } } namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns { public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase { public Indicators.Volatility Volatility(int stdDevPeriod, int pctRankPeriod, int eMAPeriod) { return indicator.Volatility(Input, stdDevPeriod, pctRankPeriod, eMAPeriod); } public Indicators.Volatility Volatility(ISeries input , int stdDevPeriod, int pctRankPeriod, int eMAPeriod) { return indicator.Volatility(input, stdDevPeriod, pctRankPeriod, eMAPeriod); } } } namespace NinjaTrader.NinjaScript.Strategies { public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase { public Indicators.Volatility Volatility(int stdDevPeriod, int pctRankPeriod, int eMAPeriod) { return indicator.Volatility(Input, stdDevPeriod, pctRankPeriod, eMAPeriod); } public Indicators.Volatility Volatility(ISeries input , int stdDevPeriod, int pctRankPeriod, int eMAPeriod) { return indicator.Volatility(input, stdDevPeriod, pctRankPeriod, eMAPeriod); } } } #endregion