Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Use of SharpDX to Draw Line

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Use of SharpDX to Draw Line

    Dear Support,

    Here is an example situatuion: I can draw a line based on certain conditions using the default Draw.Line() to either show the last drawn line or all historical lies drawn by simply adding "+CurrentBar" to string tag as show below
    Code:
    Draw.Line(NinjaScriptBase owner, string tag, ....) to show only the last line drawn
    Draw.Line(NinjaScriptBase owner, string tag + CurrentBar, ....) to show all historical lines drawn
    Here is the question: I want to use SharpDX rendering of the lines for resource efficiency. However, I want to have an option to render only the last line rendered or all the historical lines rendered. Is that possible in SharpDX? If so, how such an option is coded in SharpDX to allow switching between rendering all historical lins or only the last redered line? An example would be appreciated.

    Many thanks.

    Tags: SharDX, Draw.Line

    #2
    Hello aligator,

    The OnRender override would just render the commands you pass in that override, there is no concept of all or some objects, its what you specifically code to render that shows up.

    If you wanted to have a single object you would have a single line of code in OnRender to render a single line, if you wanted multiple lines you would repeat that for each line. You would have to make conditions if you wanted to render differently based on user input.

    You would have to come up with a way to store the prices where the line start and end up be and then reference those prices from OnRender to be used for rendering the lines. You can see the ZigZag indicator for an example of storing data in a plot and later reusing that from OnRender to custom render the data.




    Comment


      #3
      Code:
      
              protected override void OnRender(Gui.Chart.ChartControl chartControl, Gui.Chart.ChartScale chartScale)
              {
                  if (Bars == null || chartControl == null || startIndex == int.MinValue)
                      return;
      
                  IsValidDataPointAt(Bars.Count - 1 - (Calculate == NinjaTrader.NinjaScript.Calculate.OnBarClose ? 1 : 0)); // Make sure indicator is calculated until last (existing) bar
                  int preDiff = 1;
                  for (int i = ChartBars.FromIndex - 1; i >= 0; i--)
                  {
                      if (i - Displacement < startIndex || i - Displacement > Bars.Count - 1 - (Calculate == NinjaTrader.NinjaScript.Calculate.OnBarClose ? 1 : 0))
                          break;
      
                      bool isHigh    = zigZagHighZigZags.IsValidDataPointAt(i - Displacement);
                      bool isLow    = zigZagLowZigZags.IsValidDataPointAt(i - Displacement);
      
                      if (isHigh || isLow)
                          break;
      
                      preDiff++;
                  }
      
                  preDiff -= (Displacement < 0 ? Displacement : 0 - Displacement);
      
                  int postDiff = 0;
                  for (int i = ChartBars.ToIndex; i <= zigZagHighZigZags.Count; i++)
                  {
                      if (i - Displacement < startIndex || i - Displacement > Bars.Count - 1 - (Calculate == NinjaTrader.NinjaScript.Calculate.OnBarClose ? 1 : 0))
                          break;
      
                      bool isHigh    = zigZagHighZigZags.IsValidDataPointAt(i - Displacement);
                      bool isLow    = zigZagLowZigZags.IsValidDataPointAt(i - Displacement);
      
                      if (isHigh || isLow)
                          break;
      
                      postDiff++;
                  }
      
                  postDiff += (Displacement < 0 ? 0 - Displacement : Displacement);
      
                  int        lastIdx        = -1;
                  double    lastValue    = -1;
                  SharpDX.Direct2D1.PathGeometry    g        = null;
                  SharpDX.Direct2D1.GeometrySink    sink    = null;
      
                  for (int idx = ChartBars.FromIndex - preDiff; idx <= ChartBars.ToIndex + postDiff; idx++)
                  {
                      if (idx < startIndex || idx > Bars.Count - (Calculate == NinjaTrader.NinjaScript.Calculate.OnBarClose ? 2 : 1) || idx < Math.Max(BarsRequiredToPlot - Displacement, Displacement))
                          continue;
      
                      bool isHigh    = zigZagHighZigZags.IsValidDataPointAt(idx);
                      bool isLow    = zigZagLowZigZags.IsValidDataPointAt(idx);
      
                      if (!isHigh && !isLow)
                          continue;
                      
                      double value = isHigh ? zigZagHighZigZags.GetValueAt(idx) : zigZagLowZigZags.GetValueAt(idx);
                      
                      if (lastIdx >= startIndex)
                      {
                          float x1    = (chartControl.BarSpacingType == BarSpacingType.TimeBased || chartControl.BarSpacingType == BarSpacingType.EquidistantMulti && idx + Displacement >= ChartBars.Count
                              ? chartControl.GetXByTime(ChartBars.GetTimeByBarIdx(chartControl, idx + Displacement))
                              : chartControl.GetXByBarIndex(ChartBars, idx + Displacement));
                          float y1    = chartScale.GetYByValue(value);
      
                          if (sink == null)
                          {
                              float x0    = (chartControl.BarSpacingType == BarSpacingType.TimeBased || chartControl.BarSpacingType == BarSpacingType.EquidistantMulti && lastIdx + Displacement >= ChartBars.Count
                              ? chartControl.GetXByTime(ChartBars.GetTimeByBarIdx(chartControl, lastIdx + Displacement))
                              : chartControl.GetXByBarIndex(ChartBars, lastIdx + Displacement));
                              float y0    = chartScale.GetYByValue(lastValue);
                              g            = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory);
                              sink        = g.Open();
                              sink.BeginFigure(new SharpDX.Vector2(x0, y0), SharpDX.Direct2D1.FigureBegin.Hollow);
                          }
                          sink.AddLine(new SharpDX.Vector2(x1, y1));
                      }
      
                      // Save as previous point
                      lastIdx        = idx;
                      lastValue    = value;
                  }
      
                  if (sink != null)
                  {
                      sink.EndFigure(SharpDX.Direct2D1.FigureEnd.Open);
                      sink.Close();
                  }
      
                  if (g != null)
                  {
                      var oldAntiAliasMode = RenderTarget.AntialiasMode;
                      RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive;
                      RenderTarget.DrawGeometry(g, Plots[0].BrushDX, Plots[0].Width, Plots[0].StrokeStyle);
                      RenderTarget.AntialiasMode = oldAntiAliasMode;
                      g.Dispose();
                      RemoveDrawObject("NinjaScriptInfo");
                  }
                  else
                      Draw.TextFixed(this, "NinjaScriptInfo", NinjaTrader.Custom.Resource.ZigZagDeviationValueError, TextPosition.BottomRight);
              }
              #endregion​
      Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
      Last edited by PaulMohn; 08-03-2024, 04:55 AM.

      Comment


        #5
        Code:
        
                protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
                {
                    if (Bars == null || ChartControl == null || Bars.Instrument == null || !IsVisible)
                    {
                        return;
                    }
        
                    try
                    {
                        int cbti = ChartBars.ToIndex;
                        int cbfi = ChartBars.FromIndex;
        
        
                        SharpDX.Direct2D1.Brush brushBarDX = Brushes.Gray.ToDxBrush(RenderTarget);
                        SharpDX.Direct2D1.Brush brushOutlineDX = Brushes.Black.ToDxBrush(RenderTarget);
        
                        SharpDX.Direct2D1.Brush brushZeroDX = Lines[0].BrushDX;
                        SharpDX.Direct2D1.StrokeStyle lzSS = Lines[0].StrokeStyle;
                        float zeroLineY = chartScale.GetYByValue(0);
                        RenderTarget.DrawLine(new SharpDX.Vector2(ChartPanel.X, zeroLineY), new SharpDX.Vector2(ChartPanel.W, zeroLineY), brushZeroDX, 1f, lzSS);
        
                        float width = (float) Math.Max(2, ChartBars.Properties.ChartStyle.BarWidth*2);
        
                        for (int idx = cbfi; idx <= cbti; idx++)
                        {
                            double opValue = deltaOpenSeries.GetValueAt(idx);
                            double hiValue = deltaHighSeries.GetValueAt(idx);
                            double loValue = deltaLowSeries.GetValueAt(idx);
                            double clValue = Values[1].GetValueAt(idx);
        
                            double clValue1 = idx > 0 ? Values[1].GetValueAt(idx - 1) : clValue;
                            double opValue1 = idx > 0 ? deltaOpenSeries.GetValueAt(idx - 1) : opValue;
        
                            float yOpen = chartScale.GetYByValue(opValue);
                            float yHi = chartScale.GetYByValue(hiValue);
                            float yLo = chartScale.GetYByValue(loValue);
                            float yClose = chartScale.GetYByValue(clValue);
        
                            var height = (int) Math.Abs(yOpen - yClose);
                            var top = (opValue > clValue ? yOpen : yClose);
                            var bottom = (opValue < clValue ? yOpen : yClose);
                            float xCenter = chartControl.GetXByBarIndex(ChartBars, idx);
                            float xPosition = xCenter - (float) (width/2);
        
        
                            SharpDX.RectangleF rect = new SharpDX.RectangleF(xPosition, top, width, height);
        
                            if (deltaColorSeries.GetValueAt(idx) == 1)
                            {
                                brushBarDX = BarUpBrush.ToDxBrush(RenderTarget);
                                brushOutlineDX = OutlineUpBrush.ToDxBrush(RenderTarget);
                            }
                            else if (deltaColorSeries.GetValueAt(idx) == -1)
                            {
                                brushBarDX = BarDnBrush.ToDxBrush(RenderTarget);
                                brushOutlineDX = OutlineDnBrush.ToDxBrush(RenderTarget);
                            }
                            else
                            {
                                brushBarDX = Brushes.Gray.ToDxBrush(RenderTarget);
                                brushOutlineDX = Brushes.Gray.ToDxBrush(RenderTarget);
                            }
                          
                            RenderTarget.FillRectangle(rect, brushBarDX);
                            RenderTarget.DrawRectangle(rect, brushOutlineDX);
                            RenderTarget.DrawLine(new SharpDX.Vector2(xCenter, yHi), new SharpDX.Vector2(xCenter, top), brushOutlineDX, 1f);
                            RenderTarget.DrawLine(new SharpDX.Vector2(xCenter, yLo), new SharpDX.Vector2(xCenter, bottom), brushOutlineDX, 1f);
                        }
        
                        brushBarDX.Dispose();
                        brushOutlineDX.Dispose();
                        brushZeroDX.Dispose();
                        lzSS.Dispose();
        
                        if (DeltaGaplessEmaType != GaplessEmaTypeEnum.None)
                        {
                            //Avg path
                            SharpDX.Direct2D1.PathGeometry lineGeometryAvg = new SharpDX.Direct2D1.PathGeometry(Core.Globals.D2DFactory);
        
                            SharpDX.Direct2D1.GeometrySink sinkAvg = lineGeometryAvg.Open();
        
                            sinkAvg.BeginFigure(new SharpDX.Vector2(chartControl.GetXByBarIndex(ChartBars, cbfi), chartScale.GetYByValue(Values[0].GetValueAt(cbfi))), SharpDX.Direct2D1.FigureBegin.Filled);
        
                            for (int idx = cbfi; idx <= cbti; idx++)
                            {
                                double indyValue = Values[0].GetValueAt(idx);
        
                                float avgY = chartScale.GetYByValue(indyValue);
                                float x = chartControl.GetXByBarIndex(ChartBars, idx);
        
                                sinkAvg.AddLine(new SharpDX.Vector2(x, avgY));
                            }
        
                            SharpDX.Direct2D1.Brush avgBrush = Plots[0].BrushDX;
                            SharpDX.Direct2D1.StrokeStyle avgStrokeStyle = Plots[0].StrokeStyle;
                            float strokeWidthAvg = Plots[0].Width;
        
                            //Avg path plot
                            sinkAvg.EndFigure(SharpDX.Direct2D1.FigureEnd.Open);
                            sinkAvg.Close();
                            RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive;
                            RenderTarget.DrawGeometry(lineGeometryAvg, avgBrush, strokeWidthAvg, avgStrokeStyle);
                            RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.Aliased; //
                            lineGeometryAvg.Dispose();
                            avgBrush.Dispose();
        
                            avgStrokeStyle.Dispose();
                        }
                    }
                    catch (Exception ex)
                    {
                        Print("DeltaV3 exception at OnRender() at line 586:" + ex);
                    }
                }​
        trasformare un indicatore Ninja in codice per PRT Forums &#8250; ProRealTime forum Italiano &#8250; Supporto ProBuilder &#8250; trasformare un indicatore Ninja in codice per PRT This topic has 7 replies, 2 voices, and was last updated 6 years ago by Gianco. Viewing 8 posts - 1 through 8 (of 8 total) 05/28/2018 at 10:50 AM [&#8230;]

        Comment


          #6
          Code:
          protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
                  {
                      // Set text to chart label color and font
                      TextFormat    textFormat            = chartControl.Properties.LabelFont.ToDirectWriteTextFormat();
          
                      // Loop through each Plot Values on the chart
                      for (int seriesCount = 0; seriesCount < Values.Length; seriesCount++)
                      {
                          double    y                    = -1;
                          double    startX                = -1;
                          double    endX                = -1;
                          int        firstBarIdxToPaint    = -1;
                          int        firstBarPainted        = ChartBars.FromIndex;
                          int        lastBarPainted        = ChartBars.ToIndex;
                          Plot    plot                = Plots[seriesCount];
          
                          for (int i = newSessionBarIdxArr.Count - 1; i >= 0; i--)
                          {
                              int prevSessionBreakIdx = newSessionBarIdxArr[i];
                              if (prevSessionBreakIdx <= lastBarPainted)
                              {
                                  firstBarIdxToPaint = prevSessionBreakIdx;
                                  break;
                              }
                          }
          
                          // Loop through visble bars to render plot values
                          for (int idx = lastBarPainted; idx >= Math.Max(firstBarPainted, lastBarPainted - width); idx--)
                          {
                              if (idx < firstBarIdxToPaint)
                                  break;
          
                              startX        = chartControl.GetXByBarIndex(ChartBars, idx);
                              endX        = chartControl.GetXByBarIndex(ChartBars, lastBarPainted);
                              double val    = Values[seriesCount].GetValueAt(idx);
                              y            = chartScale.GetYByValue(val);
                          }
          
                          // Draw pivot lines
                          Point startPoint    = new Point(startX, y);
                          Point endPoint        = new Point(endX, y);
                          RenderTarget.DrawLine(startPoint.ToVector2(), endPoint.ToVector2(), plot.BrushDX, plot.Width, plot.StrokeStyle);
          
                          // Draw pivot text
                          TextLayout textLayout = new TextLayout(Globals.DirectWriteFactory, plot.Name, textFormat, ChartPanel.W, textFormat.FontSize);
                          RenderTarget.DrawTextLayout(startPoint.ToVector2(), textLayout, plot.BrushDX);
                          textLayout.Dispose();
                      }
                      textFormat.Dispose();
                  }​

          Comment


            #7
            ChartStyle Input parameters access from Chart right click Data Series / Ctrl+F

            Code:
            #region Using declarations
            using NinjaTrader.Data;
            using NinjaTrader.Gui.Chart;
            using SharpDX;
            using SharpDX.Direct2D1;
            using System;
            
            //added
            using System.ComponentModel;
            using System.ComponentModel.DataAnnotations;
            using System.Xml.Serialization;
            using NinjaTrader.Gui;
            
            #endregion​
            Code:
            
                    public override void OnRender(ChartControl chartControl, ChartScale chartScale, ChartBars chartBars)
                    {
                        Bars            bars            = chartBars.Bars;
                        float            barWidth        = GetBarPaintWidth(BarWidthUI);
                        Vector2            point0            = new Vector2();
                        Vector2            point1            = new Vector2();
                        RectangleF        rect            = new RectangleF();
            
                        SharpDX.Direct2D1.StrokeStyleProperties ssPropsWick = new SharpDX.Direct2D1.StrokeStyleProperties();
                        ssPropsWick.DashStyle                                = DashStyleWick;
                        SharpDX.Direct2D1.StrokeStyle styleWick             = new SharpDX.Direct2D1.StrokeStyle(RenderTarget.Factory, ssPropsWick);
                        SharpDX.Direct2D1.AntialiasMode oldAntialiasMode    = RenderTarget.AntialiasMode;
                        RenderTarget.AntialiasMode                            = SharpDX.Direct2D1.AntialiasMode.Aliased;
                        
                        for (int idx = chartBars.FromIndex; idx <= chartBars.ToIndex; idx++)
                        {
                            Brush        overriddenBarBrush        = chartControl.GetBarOverrideBrush(chartBars, idx);
                            Brush        overriddenOutlineBrush    = chartControl.GetCandleOutlineOverrideBrush(chartBars, idx);
                            Brush        upOutBrushDX            = UpOutBrush.ToDxBrush(RenderTarget);
                            Brush        dnOutBrushDX            = DnOutBrush.ToDxBrush(RenderTarget);
                            Brush        dojiBrushDX                = DojiBrush.ToDxBrush(RenderTarget);
                            Brush upOutBrushWickDX = UpOutBrushWick.ToDxBrush(RenderTarget);
                            Brush dnOutBrushWickDX = DnOutBrushWick.ToDxBrush(RenderTarget);
                            Brush dojiBrushWickDX = DojiBrushWick.ToDxBrush(RenderTarget);
                            
                            Brush upOutBrushWickDX1 = UpOutBrushWick1.ToDxBrush(RenderTarget);
                            Brush dnOutBrushWickDX1 = DnOutBrushWick1.ToDxBrush(RenderTarget);
            
            
                            double        closeValue                = bars.GetClose(idx);
                            float        closeY                    = chartScale.GetYByValue(closeValue);
                            float        highY                    = chartScale.GetYByValue(bars.GetHigh(idx));
                            float        lowY                    = chartScale.GetYByValue(bars.GetLow(idx));
                            double        openValue                = bars.GetOpen(idx);
                            float        openY                    = chartScale.GetYByValue(openValue);
                            float        x                        = chartControl.GetXByBarIndex(chartBars, idx);
            
                            
                            if (Math.Abs(openY - closeY) < 0.0000001)
                            {
                                // Doji Line
                                point0.X = x - barWidth * 0.5f;
                                point0.Y = closeY;
                                point1.X = x + barWidth * 0.5f;
                                point1.Y = closeY;
            
                                TransformBrush(overriddenOutlineBrush ?? dojiBrushDX, new RectangleF(point0.X, point0.Y - WidthOutline, barWidth, WidthOutline));
                                RenderTarget.DrawLine(point0, point1, overriddenOutlineBrush ?? dojiBrushDX, WidthOutline);
                            }
                            else
                            {
                                // Candle
                                Brush brush    = closeValue >= openValue ? UpBrushDX : DownBrushDX;
                                brush.Opacity    = Opacity * 0.01f;
                                rect.X        = x - barWidth * 0.5f + 0.5f;
                                rect.Y        = Math.Min(closeY, openY);
                                rect.Width    = barWidth - 1;
                                rect.Height    = Math.Max(openY, closeY) - Math.Min(closeY, openY);
                                TransformBrush(overriddenBarBrush ?? brush, rect);
                                TransformBrush(overriddenOutlineBrush ?? (closeValue > openValue ? upOutBrushDX : dnOutBrushDX), rect);
                                RenderTarget.FillRectangle(rect, overriddenBarBrush ?? brush);
                                RenderTarget.DrawRectangle(rect, overriddenOutlineBrush ?? (closeValue > openValue ? upOutBrushDX : dnOutBrushDX), WidthOutline);
            
                            }
            
                            // Up Bar Upper Wick
                            if (highY < Math.Min(openY, closeY))
                            {
                                point0.X = x;
                                point0.Y = highY;
                                point1.X = x;
                                point1.Y = Math.Min(openY, closeY);
                                TransformBrush(overriddenOutlineBrush ?? (closeValue == openValue ? dojiBrushWickDX : closeValue > openValue ? upOutBrushWickDX : dnOutBrushWickDX), new RectangleF(point0.X - WidthWick, point0.Y, WidthWick, point1.Y - point0.Y));
                                RenderTarget.DrawLine(point0, point1, overriddenOutlineBrush ?? (closeValue == openValue ? dojiBrushWickDX : closeValue > openValue ? upOutBrushWickDX : dnOutBrushWickDX), WidthWick, styleWick);
                            }
                            
                            // Up Bar Lower Wick
                            if (highY < Math.Min(openY, closeY))
                            {
                                point0.X = x;
                                point0.Y = highY;
                                point1.X = x;
                                point1.Y = Math.Min(openY, closeY);
                                TransformBrush(overriddenOutlineBrush ?? (closeValue == openValue ? dojiBrushWickDX : closeValue > openValue ? upOutBrushWickDX1 : dnOutBrushWickDX1), new RectangleF(point0.X - WidthWick, point0.Y, WidthWick, point1.Y - point0.Y));
                                RenderTarget.DrawLine(point0, point1, overriddenOutlineBrush ?? (closeValue == openValue ? dojiBrushWickDX : closeValue > openValue ? upOutBrushWickDX1 : dnOutBrushWickDX1), WidthWick, styleWick);
                            }
            
                            // Down Bar Upper Wick
                            if (lowY > Math.Max(openY, closeY))
                            {
                                point0.X = x;
                                point0.Y = lowY;
                                point1.X = x;
                                point1.Y = Math.Max(openY, closeY);
                                TransformBrush(overriddenOutlineBrush ?? (closeValue == openValue ? dojiBrushWickDX : closeValue > openValue ? upOutBrushWickDX : dnOutBrushWickDX), new RectangleF(point1.X - WidthWick, point1.Y, WidthWick, point0.Y - point1.Y));
                                RenderTarget.DrawLine(point0, point1, overriddenOutlineBrush ?? (closeValue == openValue ? dojiBrushWickDX : closeValue > openValue ? upOutBrushWickDX : dnOutBrushWickDX), WidthWick, styleWick);
                            }
            
                            // Down Bar Lower Wick
                            if (lowY > Math.Max(openY, closeY))
                            {
                                point0.X = x;
                                point0.Y = lowY;
                                point1.X = x;
                                point1.Y = Math.Max(openY, closeY);
                                TransformBrush(overriddenOutlineBrush ?? (closeValue == openValue ? dojiBrushWickDX : closeValue > openValue ? upOutBrushWickDX1 : dnOutBrushWickDX1), new RectangleF(point1.X - WidthWick, point1.Y, WidthWick, point0.Y - point1.Y));
                                RenderTarget.DrawLine(point0, point1, overriddenOutlineBrush ?? (closeValue == openValue ? dojiBrushWickDX : closeValue > openValue ? upOutBrushWickDX1 : dnOutBrushWickDX1), WidthWick, styleWick);
                            }
                            
                            upOutBrushDX.Dispose();
                            dnOutBrushDX.Dispose();
                            dojiBrushDX.Dispose();
                            upOutBrushWickDX.Dispose();
                            dnOutBrushWickDX.Dispose();
                            dojiBrushWickDX.Dispose();
                            
                            upOutBrushWickDX1.Dispose();
                            dnOutBrushWickDX1.Dispose();
                        }
                        styleWick.Dispose();
                        RenderTarget.AntialiasMode = oldAntialiasMode;
            
                    }​
            Last edited by PaulMohn; 08-03-2024, 09:01 AM.

            Comment


              #8
              Thank you PaulMohn for your posts. I am not quite sure what am i looking at since there is no explanations. Are you responding to my question in past #1? Are you posting the code for the ZigZag indicator using Sharp DX?

              I am not familiar with SharpDX but I know it is much faster with less resources used. Unfortunately, NinjaTrader_Jesse did not quite answer my question in post #1.

              I simply asked: If I have an indicator designed to just draw one line on a chart when certain conditions are met. I need an option to show only the last line drawn or the historical lines drawn by the same indicator (I am only interested in the last line drawn. But sometimes, I need to see where the same line was drawn in past history). I asked if that can be programmed in SharpDX.

              As an example, I would love to see the ZigZagUTC to be written in SharpDX. It will be a huge improvement since it can be very useful to develop code for price Action patterns. Note that the recent version of PAS incdicator (NexusFi.com) is much faster after it was re-written in SharpDX. The problem is the default zigzag indicator it used is not a true ZIgZag since does not follow the rule that every high point must be followed by a low point and so on.

              Cheer!
              Attached Files

              Comment


                #9
                Hello aligator,

                I simply asked: If I have an indicator designed to just draw one line on a chart when certain conditions are met. I need an option to show only the last line drawn or the historical lines drawn by the same indicator (I am only interested in the last line drawn. But sometimes, I need to see where the same line was drawn in past history). I asked if that can be programmed in SharpDX.
                I am sorry that you had further questions about your post that were not answered, in the future please make sure that you follow up if you are unsure of an answer provided so that we can get you a more complete answer. The details I provided in post 2 do answer the concern that you had though, there is no concept of past objects when using OnRender. OnRender does not work like drawing objects where you can have multiple unique objects drawn based on a tag name. If you wanted to draw 1 line you would have a single line of code in OnRender RenderTarget.DrawLine() that draws that 1 line based on values you have collected. If you need clarification please provide some details on how we can assist.

                The script you attached is using drawing objects, you could limit that to the last drawn values by using a non unique tag name for the lines. Each time you call Draw.Line it will just update the existing line on the chart. Right now it uses lastlobar.ToString() as the string, you could use something like "MyLine" instead to make it non unique. In regard to seeing that as sharpdx instead that is something you could do if you wanted, that is not something our support could do for you. If any users wanted to make that modification and post the result they can certainly do that.
                Last edited by NinjaTrader_Jesse; 08-05-2024, 09:22 AM.

                Comment


                  #10
                  Hello aligator ,

                  Might be helpful for your case:

                  Code:
                  #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 SharpDX;
                  using SharpDX.Direct2D1;
                  using SharpDX.DirectWrite;
                  #endregion
                  
                  //This namespace holds Indicators in this folder and is required. Do not change it.
                  namespace NinjaTrader.NinjaScript.Indicators
                  {
                      public class _OnRenderPlot : Indicator
                      {
                          int cBar;
                          double cHigh;
                          
                          protected override void OnStateChange()
                          {
                              if (State == State.SetDefaults)
                              {
                                  Description                                    = @"Enter the description for your new custom Indicator here.";
                                  Name                                        = "_OnRenderPlot";
                                  Calculate                                    = Calculate.OnEachTick;
                                  IsOverlay                                    = true;
                                  DisplayInDataBox                            = true;
                                  DrawOnPricePanel                            = true;
                                  DrawHorizontalGridLines                        = true;
                                  DrawVerticalGridLines                        = true;
                                  PaintPriceMarkers                            = true;
                                  ScaleJustification                            = NinjaTrader.Gui.Chart.ScaleJustification.Right;
                                  //Disable this property if your indicator requires custom values that cumulate with each new market data event.
                                  //See Help Guide for additional information.
                                  IsSuspendedWhileInactive                    = true;
                                  
                                   // Adds a blue Dash-Line style plot with 5pixel width and 70% opacity
                                  AddPlot(new Stroke(Brushes.Cyan, DashStyleHelper.Dash, 5, 70), PlotStyle.Hash, "MyPlot1");
                              }
                              else if (State == State.Configure)
                              {
                              }
                          }
                  
                          protected override void OnBarUpdate()
                          {        
                              if (CurrentBar <21) return;
                              
                              if (Open[0] < Close[0])
                              {
                                  cBar = CurrentBar;
                                  cHigh = High[0];
                                  MyPlot1[0] = cHigh;
                              }
                              else
                              {
                                  //MyPlot1[0] = double.NaN;
                              }
                                  
                              if ((CurrentBar - cBar) < 4)
                              {
                                  MyPlot1[0] = cHigh;
                              }
                          }
                          
                          protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
                          {
                              base.OnRender(chartControl, chartScale);
                              
                              
                              SharpDX.Direct2D1.StrokeStyleProperties ssPropsWick = new SharpDX.Direct2D1.StrokeStyleProperties();
                              ssPropsWick.DashStyle                                = DashStyleSolidLine;
                              SharpDX.Direct2D1.StrokeStyle solidLine             = new SharpDX.Direct2D1.StrokeStyle(RenderTarget.Factory, ssPropsWick);
                              SharpDX.Direct2D1.AntialiasMode oldAntialiasMode    = RenderTarget.AntialiasMode;
                              RenderTarget.AntialiasMode                            = SharpDX.Direct2D1.AntialiasMode.Aliased;
                              
                              // get the starting and ending bars from what is rendered on the chart
                              float startX = chartControl.GetXByBarIndex(ChartBars, ChartBars.FromIndex);
                              float endX = chartControl.GetXByBarIndex(ChartBars, ChartBars.ToIndex);
                  
                              // Loop through each Plot Values on the chart
                              for (int seriesCount = 0; seriesCount < Values.Length; seriesCount++)
                              {
                                  // get the value at the last bar on the chart (if it has been set)
                                  if (Values[seriesCount].IsValidDataPointAt(ChartBars.ToIndex))
                                  {
                                      double plotValue = cHigh;
                  
                                      // convert the plot value to the charts "Y" axis point
                                      float chartScaleYValue = chartScale.GetYByValue(plotValue);
                  
                                      // calculate the x and y values for the line to start and end
                                      SharpDX.Vector2 startPoint = new SharpDX.Vector2(startX, chartScaleYValue);
                                      SharpDX.Vector2 endPoint = new SharpDX.Vector2(endX, chartScaleYValue);
                  
                                      // draw a line between the start and end point at each plot using the plots SharpDX Brush color and style
                                      RenderTarget.DrawLine(startPoint, endPoint, Plots[seriesCount].BrushDX,
                                        Plots[seriesCount].Width, solidLine);
                                  }
                              }
                              solidLine.Dispose();
                              RenderTarget.AntialiasMode = oldAntialiasMode;
                          }
                                
                          #region Properties
                          
                              [Browsable(false)]
                              [XmlIgnore]
                              public Series<double> MyPlot1
                              {
                                get { return Values[0]; }
                              }
                          
                          [NinjaScriptProperty]
                          [Display(Name="DashStyle Solid Line", Description="DashStyle Solid Line.", Order=0, GroupName="Plots Lines")]
                          public SharpDX.Direct2D1.DashStyle DashStyleSolidLine
                          { get; set; }
                              
                          #endregion
                      }
                  }
                  
                  #region NinjaScript generated code. Neither change nor remove.
                  
                  namespace NinjaTrader.NinjaScript.Indicators
                  {
                      public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
                      {
                          private _OnRenderPlot[] cache_OnRenderPlot;
                          public _OnRenderPlot _OnRenderPlot(SharpDX.Direct2D1.DashStyle dashStyleSolidLine)
                          {
                              return _OnRenderPlot(Input, dashStyleSolidLine);
                          }
                  
                          public _OnRenderPlot _OnRenderPlot(ISeries<double> input, SharpDX.Direct2D1.DashStyle dashStyleSolidLine)
                          {
                              if (cache_OnRenderPlot != null)
                                  for (int idx = 0; idx < cache_OnRenderPlot.Length; idx++)
                                      if (cache_OnRenderPlot[idx] != null && cache_OnRenderPlot[idx].DashStyleSolidLine == dashStyleSolidLine && cache_OnRenderPlot[idx].EqualsInput(input))
                                          return cache_OnRenderPlot[idx];
                              return CacheIndicator<_OnRenderPlot>(new _OnRenderPlot(){ DashStyleSolidLine = dashStyleSolidLine }, input, ref cache_OnRenderPlot);
                          }
                      }
                  }
                  
                  namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
                  {
                      public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
                      {
                          public Indicators._OnRenderPlot _OnRenderPlot(SharpDX.Direct2D1.DashStyle dashStyleSolidLine)
                          {
                              return indicator._OnRenderPlot(Input, dashStyleSolidLine);
                          }
                  
                          public Indicators._OnRenderPlot _OnRenderPlot(ISeries<double> input , SharpDX.Direct2D1.DashStyle dashStyleSolidLine)
                          {
                              return indicator._OnRenderPlot(input, dashStyleSolidLine);
                          }
                      }
                  }
                  
                  namespace NinjaTrader.NinjaScript.Strategies
                  {
                      public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
                      {
                          public Indicators._OnRenderPlot _OnRenderPlot(SharpDX.Direct2D1.DashStyle dashStyleSolidLine)
                          {
                              return indicator._OnRenderPlot(Input, dashStyleSolidLine);
                          }
                  
                          public Indicators._OnRenderPlot _OnRenderPlot(ISeries<double> input , SharpDX.Direct2D1.DashStyle dashStyleSolidLine)
                          {
                              return indicator._OnRenderPlot(input, dashStyleSolidLine);
                          }
                      }
                  }
                  
                  #endregion
                  
                  ​
                  It captures and returns cHigh (latest value) the last double value from the plot.

                  Problems / solutions:

                  SharpDX examples compilation.
                  Lacking documentation.
                  Scattered documentation/SharpDX indicators samples.
                  Ninjatrader User Guide.
                  Insightful help from support.

                  Comment


                    #11
                    Code:
                    protected override void OnRender(ChartControl chartControl,
                                                     ChartScale chartScale)
                    {
                        base.OnRender(chartControl, chartScale);
                    // loop through only the rendered bars on the chart
                        for (int barIndex = ChartBars.FromIndex; barIndex <=
                                ChartBars.ToIndex; barIndex++)
                        {
                    // get the time stamp at the selected bar index value
                            DateTime timeValue = Bars.GetSessionEndTime(barIndex);
                            Print("Bar #" + barIndex + " time stamp is " +
                                  timeValue);
                        }
                    }​

                    Comment


                      #12
                      Hello PaulMohn,

                      I am not certain what is happening but you are posting many message here with no description of why, please avoid this going forward and combine your thoughts into one reply and provide some detail about the code you are posting.I have temporarily removed the additional posts, if you want to provide a few different examples for the original poster please edit your post # 11 to contain those samples with descriptions of why you are posting them

                      Comment


                        #13
                        NinjaTrader_Brett
                        NinjaTrader_ChelseaB

                        Would you double check the reason given by NinjaTrader_Jesse to remove previous posts?
                        The reason is erroneous (i.e. none of the previous posts were duplicates).

                        The new reason-s given by NinjaTrader_Jesse are wrong and unmotivated.

                        Last edited by PaulMohn; 08-05-2024, 09:44 AM.

                        Comment


                          #14
                          Hello PaulMohn,

                          Please refer to post #12 for the explanation. Please avoid spamming the forum with many posts, if you want to help that is always great but please do not post many posts over and over. If you need to add additional detail click the Edit button on your existing post to add other content.

                          Please also make sure to include descriptions of what the code does and how that is relevant to the original post, it has already been mentioned in post 8 that there is a gap here so posting more code with no specific details on how that will solve the original question will likely just lead to more questions

                          Comment


                            #15
                            Originally posted by PaulMohn View Post
                            NinjaTrader_Brett
                            NinjaTrader_ChelseaB

                            Would you double check the reason given by NinjaTrader_Jesse to remove previous posts?
                            The reason is erroneous (i.e. none of the previous posts were duplicates).

                            The new reason-s given by NinjaTrader_Jesse are wrong and unmotivated.
                            __________

                            bis. .

                            Comment

                            Latest Posts

                            Collapse

                            Topics Statistics Last Post
                            Started by Geovanny Suaza, 02-11-2026, 06:32 PM
                            0 responses
                            556 views
                            0 likes
                            Last Post Geovanny Suaza  
                            Started by Geovanny Suaza, 02-11-2026, 05:51 PM
                            0 responses
                            324 views
                            1 like
                            Last Post Geovanny Suaza  
                            Started by Mindset, 02-09-2026, 11:44 AM
                            0 responses
                            101 views
                            0 likes
                            Last Post Mindset
                            by Mindset
                             
                            Started by Geovanny Suaza, 02-02-2026, 12:30 PM
                            0 responses
                            545 views
                            1 like
                            Last Post Geovanny Suaza  
                            Started by RFrosty, 01-28-2026, 06:49 PM
                            0 responses
                            547 views
                            1 like
                            Last Post RFrosty
                            by RFrosty
                             
                            Working...
                            X