private void OnBarsUpdate(object sender, BarsUpdateEventArgs e) { if (State == State.Active && SuperDom != null && SuperDom.IsConnected) { if (SuperDom.IsReloading) { OnPropertyChanged(); return; } BarsUpdateEventArgs barsUpdate = e; lock (barsSync) { int currentMaxIndex = barsUpdate.MaxIndex; for (int i = lastMaxIndex + 1; i <= currentMaxIndex; i++) { if (barsUpdate.BarsSeries.GetIsFirstBarOfSession(i)) { // If a new session starts, clear out the old values and start fresh LastVolumes.Clear(); } double ask = barsUpdate.BarsSeries.GetAsk(i); double bid = barsUpdate.BarsSeries.GetBid(i); double close = barsUpdate.BarsSeries.GetClose(i); long volume = barsUpdate.BarsSeries.GetVolume(i); if (Bidask == VolumeSide.ask && lastBid != bid && close <= bid) { lastBid = bid; long newVolume; LastVolumes.AddOrUpdate(bid, newVolume = 1, (price, oldVolume) => newVolume = oldVolume + 1); } if (Bidask == VolumeSide.bid && lastAsk != ask && close >= ask) { lastAsk = ask; long newVolume; LastVolumes.AddOrUpdate(ask, newVolume = 1, (price, oldVolume) => newVolume = oldVolume + 1); } } lastMaxIndex = barsUpdate.MaxIndex; if (!clearLoadingSent) { SuperDom.Dispatcher.InvokeAsync(() => SuperDom.ClearLoadingString()); clearLoadingSent = true; } } } }
protected override void OnRender(DrawingContext dc, double renderWidth) { // This may be true if the UI for a column hasn't been loaded yet (e.g., restoring multiple tabs from workspace won't load each tab until it's clicked by the user) if (gridPen == null) { if (UiWrapper != null && PresentationSource.FromVisual(UiWrapper) != null) { Matrix m = PresentationSource.FromVisual(UiWrapper).CompositionTarget.TransformToDevice; double dpiFactor = 1 / m.M11; gridPen = new Pen(Application.Current.TryFindResource("BorderThinBrush") as Brush, 1 * dpiFactor); halfPenWidth = gridPen.Thickness * 0.5; } } if (fontFamily != SuperDom.Font.Family || (SuperDom.Font.Italic && fontStyle != FontStyles.Italic) || (!SuperDom.Font.Italic && fontStyle == FontStyles.Italic) || (SuperDom.Font.Bold && fontWeight != FontWeights.Bold) || (!SuperDom.Font.Bold && fontWeight == FontWeights.Bold)) { // Only update this if something has changed fontFamily = SuperDom.Font.Family; fontStyle = SuperDom.Font.Italic ? FontStyles.Italic : FontStyles.Normal; fontWeight = SuperDom.Font.Bold ? FontWeights.Bold : FontWeights.Normal; typeFace = new Typeface(fontFamily, fontStyle, fontWeight, FontStretches.Normal); heightUpdateNeeded = true; } double verticalOffset = -gridPen.Thickness; lock (SuperDom.Rows) foreach (PriceRow row in SuperDom.Rows) { if (renderWidth - halfPenWidth >= 0) { // Draw cell Rect rect = new Rect(-halfPenWidth, verticalOffset, renderWidth - halfPenWidth, SuperDom.ActualRowHeight); // Create a guidelines set GuidelineSet guidelines = new GuidelineSet(); guidelines.GuidelinesX.Add(rect.Left + halfPenWidth); guidelines.GuidelinesX.Add(rect.Right + halfPenWidth); guidelines.GuidelinesY.Add(rect.Top + halfPenWidth); guidelines.GuidelinesY.Add(rect.Bottom + halfPenWidth); dc.PushGuidelineSet(guidelines); dc.DrawRectangle(BackColor, null, rect); dc.DrawLine(gridPen, new Point(-gridPen.Thickness, rect.Bottom), new Point(renderWidth - halfPenWidth, rect.Bottom)); dc.DrawLine(gridPen, new Point(rect.Right, verticalOffset), new Point(rect.Right, rect.Bottom)); //dc.Pop(); if (SuperDom.IsConnected && !SuperDom.IsReloading && State == NinjaTrader.NinjaScript.State.Active) { // Draw proportional volume bar long buyVolume = 0; long sellVolume = 0; long totalRowVolume = 0; long totalVolume = 0; if (LastVolumes.TryGetValue(row.Price, out totalRowVolume)) { totalVolume = totalLastVolume; } else { verticalOffset += SuperDom.ActualRowHeight; continue; } // Print volume value - remember to set MaxTextWidth so text doesn't spill into another column if (totalRowVolume > 0) { string volumeString = string.Empty; volumeString = totalRowVolume.ToString(Core.Globals.GeneralOptions.CurrentCulture); if (renderWidth - 6 > 0) { if (DisplayText || rect.Contains(Mouse.GetPosition(UiWrapper))) { FormattedText volumeText = new FormattedText(volumeString, Core.Globals.GeneralOptions.CurrentCulture, FlowDirection.LeftToRight, typeFace, SuperDom.Font.Size, ForeColor) { MaxLineCount = 1, MaxTextWidth = renderWidth - 6, Trimming = TextTrimming.CharacterEllipsis }; // Getting the text height is expensive, so only update it if something's changed if (heightUpdateNeeded) { textHeight = volumeText.Height; heightUpdateNeeded = false; } textPosition.Y = verticalOffset + (SuperDom.ActualRowHeight - textHeight) / 2; dc.DrawText(volumeText, textPosition); } } } verticalOffset += SuperDom.ActualRowHeight; } else { verticalOffset += SuperDom.ActualRowHeight; } dc.Pop(); } } }
protected override void OnStateChange() { if (State == State.SetDefaults) { Name = "Num Touches"; Buys = new ConcurrentDictionary <double, long>(); BackColor = Brushes.Transparent; BarColor = Application.Current.TryFindResource("brushVolumeColumnBackground") as Brush; BuyColor = Brushes.Green; DefaultWidth = 160; PreviousWidth = -1; DisplayText = true; ForeColor = Application.Current.TryFindResource("brushVolumeColumnForeground") as Brush; ImmutableBarColor = Application.Current.TryFindResource("immutableBrushVolumeColumnBackground") as Brush; ImmutableForeColor = Application.Current.TryFindResource("immutableBrushVolumeColumnForeground") as Brush; IsDataSeriesRequired = true; LastVolumes = new ConcurrentDictionary <double, long>(); SellColor = Brushes.Red; Sells = new ConcurrentDictionary <double, long>(); Bidask = VolumeSide.bid; } else if (State == State.Configure) { if (UiWrapper != null && PresentationSource.FromVisual(UiWrapper) != null) { Matrix m = PresentationSource.FromVisual(UiWrapper).CompositionTarget.TransformToDevice; double dpiFactor = 1 / m.M11; gridPen = new Pen(Application.Current.TryFindResource("BorderThinBrush") as Brush, 1 * dpiFactor); halfPenWidth = gridPen.Thickness * 0.5; } if (SuperDom.Instrument != null && SuperDom.IsConnected) { BarsPeriod bp = new BarsPeriod { MarketDataType = MarketDataType.Last, BarsPeriodType = BarsPeriodType.Tick, Value = 1 }; SuperDom.Dispatcher.InvokeAsync(() => SuperDom.SetLoadingString()); clearLoadingSent = false; if (BarsRequest != null) { BarsRequest.Update -= OnBarsUpdate; BarsRequest = null; } BarsRequest = new BarsRequest(SuperDom.Instrument, Cbi.Connection.PlaybackConnection != null ? Cbi.Connection.PlaybackConnection.Now : Core.Globals.Now, Cbi.Connection.PlaybackConnection != null ? Cbi.Connection.PlaybackConnection.Now : Core.Globals.Now); BarsRequest.BarsPeriod = bp; BarsRequest.TradingHours = (TradingHoursData == TradingHours.UseInstrumentSettings || TradingHours.Get(TradingHoursData) == null) ? SuperDom.Instrument.MasterInstrument.TradingHours : TradingHours.Get(TradingHoursData); BarsRequest.Update += OnBarsUpdate; BarsRequest.Request((request, errorCode, errorMessage) => { // Make sure this isn't a bars callback from another column instance if (request != BarsRequest) { return; } lastMaxIndex = 0; maxVolume = 0; totalBuyVolume = 0; totalLastVolume = 0; totalSellVolume = 0; Sells.Clear(); Buys.Clear(); LastVolumes.Clear(); if (State >= NinjaTrader.NinjaScript.State.Terminated) { return; } if (errorCode == Cbi.ErrorCode.UserAbort) { if (State <= NinjaTrader.NinjaScript.State.Terminated) { if (SuperDom != null && !clearLoadingSent) { SuperDom.Dispatcher.InvokeAsync(() => SuperDom.ClearLoadingString()); clearLoadingSent = true; } } request.Update -= OnBarsUpdate; request.Dispose(); request = null; return; } if (errorCode != Cbi.ErrorCode.NoError) { request.Update -= OnBarsUpdate; request.Dispose(); request = null; if (SuperDom != null && !clearLoadingSent) { SuperDom.Dispatcher.InvokeAsync(() => SuperDom.ClearLoadingString()); clearLoadingSent = true; } } else if (errorCode == Cbi.ErrorCode.NoError) { SessionIterator superDomSessionIt = new SessionIterator(request.Bars); bool isInclude60 = request.Bars.BarsType.IncludesEndTimeStamp(false); if (superDomSessionIt.IsInSession(Core.Globals.Now, isInclude60, request.Bars.BarsType.IsIntraday)) { for (int i = 0; i < request.Bars.Count; i++) { DateTime time = request.Bars.BarsSeries.GetTime(i); if ((isInclude60 && time <= superDomSessionIt.ActualSessionBegin) || (!isInclude60 && time < superDomSessionIt.ActualSessionBegin)) { continue; } double ask = request.Bars.BarsSeries.GetAsk(i); double bid = request.Bars.BarsSeries.GetBid(i); double close = request.Bars.BarsSeries.GetClose(i); long volume = request.Bars.BarsSeries.GetVolume(i); if (ask != double.MinValue && close >= ask) { Buys.AddOrUpdate(close, volume, (price, oldVolume) => oldVolume + volume); totalBuyVolume += volume; } else if (bid != double.MinValue && close <= bid) { Sells.AddOrUpdate(close, volume, (price, oldVolume) => oldVolume + volume); totalSellVolume += volume; } long newVolume; LastVolumes.AddOrUpdate(close, newVolume = volume, (price, oldVolume) => newVolume = 0); totalLastVolume += volume; if (newVolume > maxVolume) { maxVolume = newVolume; } } lastMaxIndex = request.Bars.Count - 1; // Repaint the column on the SuperDOM OnPropertyChanged(); } if (SuperDom != null && !clearLoadingSent) { SuperDom.Dispatcher.InvokeAsync(() => SuperDom.ClearLoadingString()); clearLoadingSent = true; } } }); } } else if (State == State.Active) { if (!DisplayText) { WeakEventManager <System.Windows.Controls.Panel, MouseEventArgs> .AddHandler(UiWrapper, "MouseMove", OnMouseMove); WeakEventManager <System.Windows.Controls.Panel, MouseEventArgs> .AddHandler(UiWrapper, "MouseEnter", OnMouseEnter); WeakEventManager <System.Windows.Controls.Panel, MouseEventArgs> .AddHandler(UiWrapper, "MouseLeave", OnMouseLeave); mouseEventsSubscribed = true; } } else if (State == State.Terminated) { if (BarsRequest != null) { BarsRequest.Update -= OnBarsUpdate; BarsRequest.Dispose(); } BarsRequest = null; if (SuperDom != null && !clearLoadingSent) { SuperDom.Dispatcher.InvokeAsync(() => SuperDom.ClearLoadingString()); clearLoadingSent = true; } if (!DisplayText && mouseEventsSubscribed) { WeakEventManager <System.Windows.Controls.Panel, MouseEventArgs> .RemoveHandler(UiWrapper, "MouseMove", OnMouseMove); WeakEventManager <System.Windows.Controls.Panel, MouseEventArgs> .RemoveHandler(UiWrapper, "MouseEnter", OnMouseEnter); WeakEventManager <System.Windows.Controls.Panel, MouseEventArgs> .RemoveHandler(UiWrapper, "MouseLeave", OnMouseLeave); mouseEventsSubscribed = false; } lastMaxIndex = 0; maxVolume = 0; totalBuyVolume = 0; totalLastVolume = 0; totalSellVolume = 0; Sells.Clear(); Buys.Clear(); LastVolumes.Clear(); } }
private void OnBarsUpdate(object sender, BarsUpdateEventArgs e) { if (State == State.Active && SuperDom != null && SuperDom.IsConnected) { if (SuperDom.IsReloading) { OnPropertyChanged(); return; } BarsUpdateEventArgs barsUpdate = e; lock (barsSync) { int currentMaxIndex = barsUpdate.MaxIndex; for (int i = lastMaxIndex + 1; i <= currentMaxIndex; i++) { if (barsUpdate.BarsSeries.GetIsFirstBarOfSession(i)) { // If a new session starts, clear out the old values and start fresh maxVolume = 0; totalBuyVolume = 0; totalLastVolume = 0; totalSellVolume = 0; Sells.Clear(); Buys.Clear(); LastVolumes.Clear(); } double ask = barsUpdate.BarsSeries.GetAsk(i); double bid = barsUpdate.BarsSeries.GetBid(i); double close = barsUpdate.BarsSeries.GetClose(i); long volume = barsUpdate.BarsSeries.GetVolume(i); if (ask != double.MinValue && close >= ask) { Buys.AddOrUpdate(close, volume, (price, oldVolume) => oldVolume + volume); totalBuyVolume += volume; } else if (bid != double.MinValue && close <= bid) { Sells.AddOrUpdate(close, volume, (price, oldVolume) => oldVolume + volume); totalSellVolume += volume; } long newVolume; LastVolumes.AddOrUpdate(close, newVolume = volume, (price, oldVolume) => newVolume = oldVolume + volume); totalLastVolume += volume; if (newVolume > maxVolume) { maxVolume = newVolume; } } lastMaxIndex = barsUpdate.MaxIndex; if (!clearLoadingSent) { SuperDom.Dispatcher.InvokeAsync(() => SuperDom.ClearLoadingString()); clearLoadingSent = true; } } } }