#region Using declarations using NinjaTrader.Cbi; using NinjaTrader.Data; using NinjaTrader.Gui; using NinjaTrader.NinjaScript.MarketAnalyzerColumns; using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Windows.Media; #endregion namespace NinjaTrader.NinjaScript.Indicators { public class VWAP : Indicator { private static int CHART_BARS = 0; private static int TICK_BARS = 1; private double TotalVolume; private double VolumeWeightedPrice; private double TotalVolumeTick; private double VolumeWeightedPriceTick; private double VWAPTick; protected override void OnStateChange() { if (State == State.SetDefaults) { Description = "Volume Weighted Average Price (VWAP)"; Name = "VWAP"; Calculate = Calculate.OnBarClose; IsOverlay = true; DisplayInDataBox = true; DrawOnPricePanel = true; ScaleJustification = Gui.Chart.ScaleJustification.Right; IsSuspendedWhileInactive = true; BarsRequiredToPlot = 0; Precision = VWAPPrecision.Chart; Price = VWAPPrice.OHLC; AddPlot(new Stroke(Brushes.Yellow, DashStyleHelper.Solid, 3), PlotStyle.Line, "VWAP"); } else if (State == State.Configure) { ClearOutputWindow(); if (Precision == VWAPPrecision.Tick) { AddDataSeries(Instrument.FullName, new BarsPeriod { BarsPeriodType = BarsPeriodType.Tick, Value = 1 }, Bars.TradingHours.Name); } } else if (State == State.DataLoaded) { ResetVWAP(); } } private double GetPrice(int bars) { switch (Price) { case VWAPPrice.Open: return Opens[bars][0]; case VWAPPrice.High: return Highs[bars][0]; case VWAPPrice.Low: return Lows[bars][0]; case VWAPPrice.Close: return Closes[bars][0]; case VWAPPrice.HL: return (Highs[bars][0] + Lows[bars][0]) / 2; case VWAPPrice.HLC: return (Highs[bars][0] + Lows[bars][0] + Closes[bars][0]) / 3; case VWAPPrice.OHLC: default: return (Opens[bars][0] + Highs[bars][0] + Lows[bars][0] + Closes[bars][0]) / 4; } } private void ResetVWAP() { TotalVolume = 0; VolumeWeightedPrice = 0; TotalVolumeTick = 0; VolumeWeightedPriceTick = 0; VWAPTick = 0; } protected override void OnBarUpdate() { if (Bars.IsFirstBarOfSession && IsFirstTickOfBar) { ResetVWAP(); // Prevent visible jumps in VWAP when a new session begins. PlotBrushes[0][0] = Brushes.Transparent; } if (CHART_BARS == BarsInProgress) { if (Precision == VWAPPrecision.Tick) { Value[0] = VWAPTick; } else if (Calculate == Calculate.OnBarClose || IsFirstTickOfBar) { TotalVolume += Volume[0]; VolumeWeightedPrice += Volume[0] * GetPrice(CHART_BARS); Value[0] = VolumeWeightedPrice / TotalVolume; } else { Value[0] = (VolumeWeightedPrice + (Volume[0] * GetPrice(CHART_BARS))) / (TotalVolume + Volume[0]); } } else if (TICK_BARS == BarsInProgress) { TotalVolumeTick += Volumes[TICK_BARS][0]; VolumeWeightedPriceTick += Volumes[TICK_BARS][0] * GetPrice(TICK_BARS); VWAPTick = VolumeWeightedPriceTick / TotalVolumeTick; } } public override string DisplayName { get { return Name; } } #region Properties [TypeConverter(typeof(VWAPPrecisionConverter))] [PropertyEditor("NinjaTrader.Gui.Tools.StringStandardValuesEditorKey")] [Display(Name = "Precision", Description = "Precision with which VWAP is calculated", Order = 1, GroupName = "VWAP")] public VWAPPrecision Precision { get; set; } [TypeConverter(typeof(VWAPPriceConverter))] [PropertyEditor("NinjaTrader.Gui.Tools.StringStandardValuesEditorKey")] [Display(Name = "Average Price", Description = "How the average price of the bar is calculated", Order = 2, GroupName = "VWAP")] public VWAPPrice Price { get; set; } #endregion } } public enum VWAPPrecision { Chart, Tick } public enum VWAPPrice { Open, High, Low, Close, HL, HLC, OHLC } public class VWAPPrecisionConverter : TypeConverter { private const string CHART = "Chart Period"; private const string TICK = "Tick"; public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) { List values = new List() { CHART, TICK }; return new StandardValuesCollection(values); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { switch (value.ToString()) { case CHART: return VWAPPrecision.Chart; case TICK: return VWAPPrecision.Tick; } return VWAPPrecision.Chart; } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { VWAPPrecision enumValue = (VWAPPrecision)Enum.Parse(typeof(VWAPPrecision), value.ToString()); switch (enumValue) { case VWAPPrecision.Chart: return CHART; case VWAPPrecision.Tick: return TICK; } return CHART; } public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return true; } public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { return true; } public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) { return true; } public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { return true; } } public class VWAPPriceConverter : TypeConverter { private const string OPEN = "Open"; private const string HIGH = "High"; private const string LOW = "Low"; private const string CLOSE = "Close"; private const string HIGH_LOW = "(High + Low) / 2"; private const string HIGH_LOW_CLOSE = "(High + Low + Close) / 3"; private const string OPEN_HIGH_LOW_CLOSE = "(Open + High + Low + Close) / 4"; public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) { List values = new List() { OPEN, HIGH, LOW, CLOSE, HIGH_LOW, HIGH_LOW_CLOSE, OPEN_HIGH_LOW_CLOSE }; return new StandardValuesCollection(values); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { switch (value.ToString()) { case OPEN: return VWAPPrice.Open; case HIGH: return VWAPPrice.High; case LOW: return VWAPPrice.Low; case CLOSE: return VWAPPrice.Close; case HIGH_LOW: return VWAPPrice.HL; case HIGH_LOW_CLOSE: return VWAPPrice.HLC; case OPEN_HIGH_LOW_CLOSE: return VWAPPrice.OHLC; } return VWAPPrice.OHLC; } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { VWAPPrice enumValue = (VWAPPrice)Enum.Parse(typeof(VWAPPrice), value.ToString()); switch (enumValue) { case VWAPPrice.Open: return OPEN; case VWAPPrice.High: return HIGH; case VWAPPrice.Low: return LOW; case VWAPPrice.Close: return CLOSE; case VWAPPrice.HL: return HIGH_LOW; case VWAPPrice.HLC: return HIGH_LOW_CLOSE; case VWAPPrice.OHLC: return OPEN_HIGH_LOW_CLOSE; } return OPEN_HIGH_LOW_CLOSE; } public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return true; } public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { return true; } public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) { return true; } public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { return true; } } #region NinjaScript generated code. Neither change nor remove. namespace NinjaTrader.NinjaScript.Indicators { public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase { private VWAP[] cacheVWAP; public VWAP VWAP() { return VWAP(Input); } public VWAP VWAP(ISeries input) { if (cacheVWAP != null) for (int idx = 0; idx < cacheVWAP.Length; idx++) if (cacheVWAP[idx] != null && cacheVWAP[idx].EqualsInput(input)) return cacheVWAP[idx]; return CacheIndicator(new VWAP(), input, ref cacheVWAP); } } } namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns { public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase { public Indicators.VWAP VWAP() { return indicator.VWAP(Input); } public Indicators.VWAP VWAP(ISeries input ) { return indicator.VWAP(input); } } } namespace NinjaTrader.NinjaScript.Strategies { public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase { public Indicators.VWAP VWAP() { return indicator.VWAP(Input); } public Indicators.VWAP VWAP(ISeries input ) { return indicator.VWAP(input); } } } #endregion