345 lines
11 KiB
C#
345 lines
11 KiB
C#
#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<string> values = new List<string>() { 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<string> values = new List<string>() { 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<double> 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<VWAP>(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<double> 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<double> input )
|
|
{
|
|
return indicator.VWAP(input);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|