#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 SharpDX.Direct2D1; #endregion //This namespace holds Drawing tools in this folder and is required. Do not change it. namespace NinjaTrader.NinjaScript.DrawingTools { public class AnchoredVWAP : DrawingTool { private const string ANCHOR_ICON = "\u2693"; private const double MOUSE_PROXIMITY = 15; public ChartAnchor Anchor { get; set; } public override IEnumerable Anchors { get { return new[] { Anchor }; } } private List VWAPVectors; protected override void OnStateChange() { if (State == State.SetDefaults) { Description = @"Anchors a VWAP to the specified bar on the chart"; Name = "Anchored VWAP"; DrawingState = DrawingState.Building; AnchorBar = 0; Stroke = new Stroke(Brushes.Yellow, 2f); if (Anchor == null) Anchor = new ChartAnchor { DisplayName = "Anchored VWAP", DrawingTool = this }; } else if (State == State.Terminated) { Dispose(); } } public override object Icon { get { return ANCHOR_ICON; } } public override Cursor GetCursor(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale, Point point) { switch (DrawingState) { case DrawingState.Building: return Cursors.Pen; case DrawingState.Editing: ChartAnchor closestAnchor = GetClosestAnchor(chartControl, chartPanel, chartScale, MOUSE_PROXIMITY, point); return Anchor == closestAnchor ? Cursors.SizeWE : null; case DrawingState.Moving: return Cursors.SizeWE; default: return null; } } public override Point[] GetSelectionPoints(ChartControl chartControl, ChartScale chartScale) { ChartPanel chartPanel = chartControl.ChartPanels[chartScale.PanelIndex]; return new[] { Anchor.GetPoint(chartControl, chartPanel, chartScale, false) }; } public override void OnBarsChanged() { } public override void OnCalculateMinMax() { } public override void OnMouseDown(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale, ChartAnchor dataPoint) { switch (DrawingState) { case DrawingState.Building: AnchorBar = (int)dataPoint.SlotIndex; DrawingState = DrawingState.Normal; IsSelected = false; break; case DrawingState.Editing: Point point = dataPoint.GetPoint(chartControl, chartPanel, chartScale); ChartAnchor closestAnchor = GetClosestAnchor(chartControl, chartPanel, chartScale, MOUSE_PROXIMITY, point); if (Anchor == closestAnchor) DrawingState = DrawingState.Moving; else { DrawingState = DrawingState.Normal; IsSelected = false; } break; case DrawingState.Normal: DrawingState = DrawingState.Editing; IsSelected = true; break; default: break; } } public override void OnMouseMove(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale, ChartAnchor dataPoint) { switch (DrawingState) { case DrawingState.Moving: AnchorBar = (int)dataPoint.SlotIndex; break; default: break; } } public override void OnMouseUp(ChartControl chartControl, ChartPanel chartPanel, ChartScale chartScale, ChartAnchor dataPoint) { switch (DrawingState) { case DrawingState.Moving: DrawingState = DrawingState.Editing; break; default: break; } } public override void OnRender(ChartControl chartControl, ChartScale chartScale) { UpdateVWAP(chartControl, chartScale); AntialiasMode originalAntialiasMode = RenderTarget.AntialiasMode; RenderTarget.AntialiasMode = AntialiasMode.PerPrimitive; SharpDX.Direct2D1.PathGeometry VWAPGeometry = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory); GeometrySink VWAPGeometrySink = VWAPGeometry.Open(); VWAPGeometrySink.BeginFigure(VWAPVectors.First(), FigureBegin.Hollow); VWAPGeometrySink.AddLines(VWAPVectors.ToArray()); VWAPGeometrySink.EndFigure(FigureEnd.Open); VWAPGeometrySink.Close(); RenderTarget.DrawGeometry(VWAPGeometry, Stroke.Brush.ToDxBrush(RenderTarget), Stroke.Width); VWAPGeometry.Dispose(); RenderTarget.AntialiasMode = originalAntialiasMode; } private void UpdateVWAP(ChartControl chartControl, ChartScale chartScale) { VWAPVectors = new List(); Bars bars = chartControl.BarsArray[0].Bars; double totalVolume = 0; double volumeWeightedPrice = 0; for (int i = AnchorBar; i < bars.Count; i++) { double volume = bars.GetVolume(i); double price = (bars.GetOpen(i) + bars.GetHigh(i) + bars.GetLow(i) + bars.GetClose(i)) / 4; totalVolume += volume; volumeWeightedPrice += price * volume; int x = chartControl.GetXByBarIndex(chartControl.BarsArray[0], i); int y = chartScale.GetYByValue(volumeWeightedPrice / totalVolume); VWAPVectors.Add(new SharpDX.Vector2(x, y)); if (i == AnchorBar) Anchor = CreateAnchor(new Point(x, y), chartControl, chartScale); } } [Display(ResourceType = typeof(Custom.Resource), GroupName = "Anchored VWAP", Name = "Anchor Bar", Order = 1)] public int AnchorBar { get; set; } [Display(ResourceType = typeof(Custom.Resource), GroupName = "Anchored VWAP", Name = "AVWAP", Order = 2)] public Stroke Stroke { get; set; } } }