Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

Avoid removing of objects drawn by indicator when user change timeframe of chart

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

    Avoid removing of objects drawn by indicator when user change timeframe of chart

    Hello
    I have written a tool (indicator) that helps user to draw some objects on chart, so objects are drawn by indicator, I want objects remain on chart when user changes timeframe of chart from upper toolbar, or even if user decide to remove indicator from chart, is this possible?

    Click image for larger version

Name:	image.png
Views:	42
Size:	44.7 KB
ID:	1296924

    #2
    Hello tidicofx,

    Thank you for your post.

    Drawing objects drawn by an indicator will still appear on the chart even after changing the timeframe, although since the scale has been changed they may appear smaller/bigger.

    This sample script below demonstrates using drawing objects. When testing out this script by changing the timeframe, I am still able to see the drawing objects on the chart.



    Unfortunately, it would not be possible to keep the drawing objects on the chart if you remove the indicator they were drawn by. Removing the indicator will also cause any drawing objects it created to be removed from the chart as well.

    Please let us know if you have any further questions.
    Gaby V.NinjaTrader Customer Service

    Comment


      #3
      hello, thank you for your reply
      i have tested again
      here is a line drawn by indicator
      Click image for larger version

Name:	image.png
Views:	31
Size:	32.4 KB
ID:	1297048
      then i switch to M10
      Click image for larger version

Name:	image.png
Views:	20
Size:	31.1 KB
ID:	1297049​line is gone
      even when i switch back to M15, line is not there
      Click image for larger version

Name:	image.png
Views:	19
Size:	32.0 KB
ID:	1297050​maybe I set something wrong in indicator code?
      here is indicator code
      Code:
              private string pid = "PS_";
              private SimpleFont myFont;
              private bool isFirstRun=true;
              private double pointSize=1;
              private int digits=0;
              private double ask=0, bid=0;
              private bool isCliked = false;
              private int selectedCandleIdx = -1;
              private Key priceToDraw = Key.N;
      
              protected override void OnStateChange()
              {
                  if (State == State.SetDefaults)
                  {
                      Description                                    = @"DrawHorizontalRay";
                      Name                                        = "DrawHorizontalRay";
                      Calculate                                    = Calculate.OnEachTick;
                      IsOverlay                                    = true;
                      DisplayInDataBox                            = false;
                      DrawOnPricePanel                            = true;
                      DrawHorizontalGridLines                        = true;
                      DrawVerticalGridLines                        = true;
                      PaintPriceMarkers                            = true;
                      AllowRemovalOfDrawObjects                     = 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;
                      
                      LineColor                    = Brushes.Red;
                      LineStyle                    = DashStyleHelper.Solid;
                      LineWidth                    = 2;
                      myFont                        = new SimpleFont("Arial", 12);
                  }
                  else if (State == State.DataLoaded)
                  {
                      if (ChartPanel!=null) ChartPanel.KeyDown+=new System.Windows.Input.KeyEventHandler(OnKeyDown);
                      if (ChartPanel!=null) ChartPanel.MouseDown+=new System.Windows.Input.MouseButtonEventHandler(OnMouseDown);
                  }
                  else if (State == State.Terminated)
                  {
                      if (ChartPanel!=null) ChartPanel.KeyDown-=new System.Windows.Input.KeyEventHandler(OnKeyDown);
                      if (ChartPanel!=null) ChartPanel.MouseDown-=new System.Windows.Input.MouseButtonEventHandler(OnMouseDown);
                  }
              }
      
              protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
              {
                  if (isCliked)
                  {
                      isCliked=false;
                      int x = chartControl.MouseDownPoint.X.ConvertToHorizontalPixels(chartControl.PresentationSource);
                      int y = chartControl.MouseDownPoint.Y.ConvertToVerticalPixels(chartControl.PresentationSource);
                      int barIdx = ChartBars.GetBarIdxByX(chartControl, x);
                      double price = chartScale.GetValueByY((float)y);
                      double high=Bars.GetHigh(barIdx);
                      double low=Bars.GetLow(barIdx);
                      if (price>=low && price<=high)
                      {
                          selectedCandleIdx=barIdx;
                          priceToDraw=0;
                          DateTime dt=Bars.GetTime(barIdx);
                          Draw.TextFixed(this, "Hint", dt.ToString()+" is selected, Press O,H,L,C to draw line", TextPosition.TopLeft);
                          ForceRefresh();
                      }
                      else if (selectedCandleIdx!=-1)
                      {
                          selectedCandleIdx=-1;
                          Draw.TextFixed(this, "Hint", "", TextPosition.TopLeft);
                          ForceRefresh();
                      }
                  }
                  if (priceToDraw!=Key.N && selectedCandleIdx!=-1)
                  {
                      DateTime dt=Bars.GetTime(selectedCandleIdx);
                      double price=0;
                      if (priceToDraw==Key.O) price=Bars.GetOpen(selectedCandleIdx);
                      if (priceToDraw==Key.H) price=Bars.GetHigh(selectedCandleIdx);
                      if (priceToDraw==Key.L) price=Bars.GetLow(selectedCandleIdx);
                      if (priceToDraw==Key.C) price=Bars.GetClose(selectedCandleIdx);
                      //Draw.Ray(this, pid+dt.ToString()+"_"+priceToDraw.ToString(), false, dt, price, dt.AddDays(1), price, LineColor, LineStyle, LineWidth);
                      Draw.Line(this, pid+dt.ToString()+"_"+priceToDraw.ToString(), false, dt, price, dt.AddDays(30), price, LineColor, LineStyle, LineWidth);
                      priceToDraw=Key.N;
                      ForceRefresh();
                  }
              }
              
              protected override void OnBarUpdate()
              {
                  //Add your custom indicator logic here.
                  if (isFirstRun && CurrentBar>=10)
                  {
                      isFirstRun=false;
                      digits=GetDidgits();
                      pointSize=GetPoint();
                      //Draw.TextFixed(this, "Test", digits.ToString()+", "+pointSize.ToString(), TextPosition.BottomLeft);
                  }
                  ask=GetCurrentAsk(); bid=GetCurrentBid();
              }
              
              public void OnKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
              {
                  if (e.Key==Key.O || e.Key==Key.H || e.Key==Key.L || e.Key==Key.C)
                  {
                      e.Handled = true;
                      priceToDraw = e.Key;
                      ForceRefresh();
                  }
              }
              
              public void OnMouseDown(object sender, System.Windows.Input.MouseEventArgs e)
              {  
                  if (e.LeftButton==MouseButtonState.Pressed)
                  {
                      isCliked = true;
                      ForceRefresh();
                  }
              }
      ​

      Comment


        #4
        Hello tidicofx,

        Thank you for your response.

        It looks like you are using drawing objects from OnRender. OnRender is used for custom rendering shapes and lines, I would not suggest creating Drawing objects from OnRender. Drawing tools should be used from OnBarUpdate().

        If you draw a line from OnBarUpdate(), are you still seeing this behavior occur?

        I look forward to your response.
        Gaby V.NinjaTrader Customer Service

        Comment


          #5
          Originally posted by NinjaTrader_Gaby View Post
          Hello tidicofx,

          Thank you for your response.

          It looks like you are using drawing objects from OnRender. OnRender is used for custom rendering shapes and lines, I would not suggest creating Drawing objects from OnRender. Drawing tools should be used from OnBarUpdate().

          If you draw a line from OnBarUpdate(), are you still seeing this behavior occur?

          I look forward to your response.
          ok, I think I made confusion writing code into OnRender
          I have updated code to make more sense of what I am doing
          user clicks on a candle, then press one of Keys O,H,L,C and indicator draws line from selected candle HOLC, very simple example
          here is code
          Code:
                  private string pid = "PS_";
                  private SimpleFont myFont;
                  private bool isFirstRun=true;
                  private double pointSize=1;
                  private int digits=0;
                  private double ask=0, bid=0;
                  private bool isCliked = false;
                  private int selectedCandleIdx = -1;
          
                  private double myChartMin;
                  private double myChartMax;
          
                  protected override void OnStateChange()
                  {
                      if (State == State.SetDefaults)
                      {
                          Description                                    = @"DrawHorizontalRay";
                          Name                                        = "DrawHorizontalRay";
                          Calculate                                    = Calculate.OnEachTick;
                          IsOverlay                                    = true;
                          DisplayInDataBox                            = false;
                          DrawOnPricePanel                            = true;
                          DrawHorizontalGridLines                        = true;
                          DrawVerticalGridLines                        = true;
                          PaintPriceMarkers                            = true;
                          AllowRemovalOfDrawObjects                     = 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;
                          
                          LineColor                    = Brushes.Red;
                          LineStyle                    = DashStyleHelper.Solid;
                          LineWidth                    = 2;
                          myFont                        = new SimpleFont("Arial", 12);
                          myChartMax                    = 0;
                          myChartMin                    = 0;
                      }
                      else if (State == State.DataLoaded)
                      {
                          if (ChartPanel!=null) ChartPanel.KeyDown+=new System.Windows.Input.KeyEventHandler(OnKeyDown);
                          if (ChartPanel!=null) ChartPanel.MouseDown+=new System.Windows.Input.MouseButtonEventHandler(OnMouseDown);
                      }
                      else if (State == State.Terminated)
                      {
                          if (ChartPanel!=null) ChartPanel.KeyDown-=OnKeyDown;
                          if (ChartPanel!=null) ChartPanel.MouseDown-=OnMouseDown;
                      }
                  }
          
                  protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
                  {
                      myChartMax=chartScale.MaxValue;
                      myChartMin=chartScale.MinValue;
                  }
                  
                  public void OnKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
                  {
                      if (selectedCandleIdx!=-1)
                      if (e.Key==Key.O || e.Key==Key.H || e.Key==Key.L || e.Key==Key.C)
                      {
                          DateTime dt=Bars.GetTime(selectedCandleIdx);
                          double price=0;
                          if (e.Key==Key.O) price=Bars.GetOpen(selectedCandleIdx);
                          if (e.Key==Key.H) price=Bars.GetHigh(selectedCandleIdx);
                          if (e.Key==Key.L) price=Bars.GetLow(selectedCandleIdx);
                          if (e.Key==Key.C) price=Bars.GetClose(selectedCandleIdx);
                          Print(dt.ToString()+", "+price.ToString());
                          Draw.Line(this, pid+dt.ToString()+"_"+e.Key.ToString(), false, dt, price, dt.AddDays(30), price, LineColor, LineStyle, LineWidth);
                          e.Handled = true;
                          ForceRefresh();
                      }
                  }
                  
                  public void OnMouseDown(object sender, System.Windows.Input.MouseEventArgs e)
                  {  
                      if (e.LeftButton==MouseButtonState.Pressed && ChartControl!=null)
                      {
                          //Draw.TextFixed(this, "Test", myChartMax.ToString()+", "+myChartMin.ToString(), TextPosition.TopLeft);
                          int x = ChartControl.MouseDownPoint.X.ConvertToHorizontalPixels(ChartControl.PresentationSource);
                          int y = ChartControl.MouseDownPoint.Y.ConvertToVerticalPixels(ChartControl.PresentationSource);
                          int barIdx = ChartBars.GetBarIdxByX(ChartControl, x);
                          double price = GetPriceFromY(y);
                          double high=Bars.GetHigh(barIdx);
                          double low=Bars.GetLow(barIdx);
                          if (price>=low && price<=high)
                          {
                              selectedCandleIdx=barIdx;
                              Print(selectedCandleIdx.ToString());
                              DateTime dt=Bars.GetTime(barIdx);
                              Draw.TextFixed(this, "Hint", dt.ToString()+" is selected, Press O,H,L,C to draw line", TextPosition.TopLeft);
                              ForceRefresh();
                          }
                          else if (selectedCandleIdx!=-1)
                          {
                              selectedCandleIdx=-1;
                              Draw.TextFixed(this, "Hint", "", TextPosition.TopLeft);
                              ForceRefresh();
                          }
                      }
                  }
          
                  protected override void OnBarUpdate()
                  {
                      //Add your custom indicator logic here.
                  }
          
                  private double GetPriceFromY(int y)
                  {
                      if (myChartMax==0 || myChartMin==0 || ChartPanel==null) return (0);
                      return (myChartMax-y*1.0/ChartPanel.H*(myChartMax-myChartMin));
                  }
          ​
          still with this code when I change timeframe line is removing from chart

          Comment


            #6
            Hello tidicofx,

            Thank you for your response.

            This is because the drawing objects are only created when an onkeydown() or onmousedown() event happens in your script.

            When you change the timeframe or data series of the chart, the script is recalculated so the drawing objects disappear. When a drawing object is drawn from OnBarUpdate(), the script can redraw the drawing object based on historical data once the script is reloaded. However, since you are not drawing the objects from OnBarUpdate() they are not re-drawn.

            If you would like to have the objects redrawn whenever the script is reloaded/data series or time frame is changed, you can write the drawing object's time and prices to a text file when the script draws something, then reload that file when the script loads so it can then redraw them using OnBarUpdate().

            The sample scripts below demonstrate reading and writing to/from a text file:





            Please let me know if you have any further questions.
            Gaby V.NinjaTrader Customer Service

            Comment


              #7
              Originally posted by NinjaTrader_Gaby View Post
              Hello tidicofx,

              Thank you for your response.

              This is because the drawing objects are only created when an onkeydown() or onmousedown() event happens in your script.

              When you change the timeframe or data series of the chart, the script is recalculated so the drawing objects disappear. When a drawing object is drawn from OnBarUpdate(), the script can redraw the drawing object based on historical data once the script is reloaded. However, since you are not drawing the objects from OnBarUpdate() they are not re-drawn.

              If you would like to have the objects redrawn whenever the script is reloaded/data series or time frame is changed, you can write the drawing object's time and prices to a text file when the script draws something, then reload that file when the script loads so it can then redraw them using OnBarUpdate().

              The sample scripts below demonstrate reading and writing to/from a text file:





              Please let me know if you have any further questions.
              ok, so as far as I understand from your comments, objects will always remove when chart timeframe is changing, I have to track record of drawn objects and redraw them again
              this is despite manually drawn objects that remain on chart even when I change timeframe, that's a bit disappointing, hope in future releases of NT that can be considered as option to not remove drawings while indicator is not removed from chart

              Comment


                #8
                Hello,

                Yes, whenever you change the time frame, data series, or refresh historical data the script is recalculated/reloaded as well so any drawing objects drawn by the strategy will be removed.

                Since your drawing objects are outside of OnBarUpdate(), once the script is recalculated they can't be redrawn using historical data - they will only be redrawn when onkeydown() or onmousedown() event happens.

                While the indicator is technically not being removed from the chart (like manually removing it from the Indicators window), the script is being reloaded when you change the time frame which means everything in the script is going to be recalculated from scratch.

                Please let me know if you have any further questions.
                Gaby V.NinjaTrader Customer Service

                Comment


                  #9
                  Originally posted by NinjaTrader_Gaby View Post
                  Hello,

                  Yes, whenever you change the time frame, data series, or refresh historical data the script is recalculated/reloaded as well so any drawing objects drawn by the strategy will be removed.

                  Since your drawing objects are outside of OnBarUpdate(), once the script is recalculated they can't be redrawn using historical data - they will only be redrawn when onkeydown() or onmousedown() event happens.

                  While the indicator is technically not being removed from the chart (like manually removing it from the Indicators window), the script is being reloaded when you change the time frame which means everything in the script is going to be recalculated from scratch.

                  Please let me know if you have any further questions.
                  it's clear now, thanks

                  Comment

                  Latest Posts

                  Collapse

                  Topics Statistics Last Post
                  Started by fx.practic, 10-15-2013, 12:53 AM
                  5 responses
                  5,404 views
                  0 likes
                  Last Post Bidder
                  by Bidder
                   
                  Started by Shai Samuel, 07-02-2022, 02:46 PM
                  4 responses
                  95 views
                  0 likes
                  Last Post Bidder
                  by Bidder
                   
                  Started by DJ888, Yesterday, 10:57 PM
                  0 responses
                  8 views
                  0 likes
                  Last Post DJ888
                  by DJ888
                   
                  Started by MacDad, 02-25-2024, 11:48 PM
                  7 responses
                  159 views
                  0 likes
                  Last Post loganjarosz123  
                  Started by Belfortbucks, Yesterday, 09:29 PM
                  0 responses
                  8 views
                  0 likes
                  Last Post Belfortbucks  
                  Working...
                  X