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

indicator that draws up / down arrows

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

    indicator that draws up / down arrows

    good day to everyone,


    i have been trying to create an indicator that would draw an arrow below the low of every bar as long as two moving averages are increasing, and an arrow above the high of the bar if the two moving averages are decreasing. if neither is the case, it shouldn't plot anything.

    i'm having trouble getting the indicator to evaluate for multiple conditions and haven't been able to find a command for - no plot - either. if anyone knows how to get this simple idea to work i would greatly appreciate it. thanks.


    Code:
    [INDENT][INDENT]IsOverlay                                         = true;
    DisplayInDataBox                             = true;
    DrawOnPricePanel                            = true;
    DrawHorizontalGridLines                    = true;
    DrawVerticalGridLines                        = true;
    PaintPriceMarkers                             = true;
    ScaleJustification                            = NinjaTrader.Gui.Chart.ScaleJustification.Right;
    [/INDENT][/INDENT]//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;
                    Pesma                    = 30;
                    Peema                    = 30;
                    Dtau                    = 8;
                    Dtad                    = 8;
                    AddPlot(new Stroke(Brushes.DarkBlue, 2), PlotStyle.TriangleUp, "Iup");
                    AddPlot(new Stroke(Brushes.DarkRed, 2), PlotStyle.TriangleDown, "Ido");
                }
                else if (State == State.Configure)
                {
                }
            }
    
            protected override void OnBarUpdate()
            {
                
                
                double smav    = SMA(Pesma)[0];
                double emav    = EMA(Peema)[0];
                
                Smas[0] = smav;
                Emas[0] = emav;
                
                Plots[0].Width = 4;
                Plots[1].Width = 4;
                
                
                
                if (  (Smas[0]) > (Smas[1]) && (Emas[0]) > (Emas[1])  )
                {
                    Draw.ArrowUp(this, "iup", true, 0, Low[1] - (Dtau * TickSize), Brushes.DarkBlue);
                
                
                }
            
                else if (  (Smas[0]) < (Smas[1]) && (Emas[0]) < (Emas[1])  )
                {
                    Draw.ArrowUp(this, "ido", true, 0, High[1] + (Dttad * TickSize), Brushes.DarkRed);
                
                
                }
                
                else
                {
                - ¿ No plot ? -
                
                }
    Last edited by rtwave; 01-15-2018, 02:30 PM.

    #2
    Hello rtwave,

    When you mention you are having trouble getting the script to evaluate multiple conditions, can you clarify this?

    Currently you have an else if. The second condition set will only be evaluated if the first condition set evaluates as false.
    Are you wanting these to be evaluated separately, allowing the second set to be evaluated even if the first set evaluates as true?
    If so, do not use the else if and instead use an else.

    Are you asking why the condition sets are evaluating as false?
    If so, add prints to the script to find the values of the variables used in the conditions.
    Below is a link to a forum post that demonstrates using prints to understand behavior.


    The plots are appearing because they are always be set on every bar.
    Originally posted by rtwave View Post
    Smas[0] = smav;
    Emas[0] = emav;
    If you do not want the plot to appear. Don't set it.
    Code:
    // within the scope of the class
    private SMA SMA1;
    private EMA EMA1;
    
    // within OnStateChange()
    else if (State == State.SetDefaults)
    {
    AddPlot(new Stroke(Brushes.DarkBlue, 2), PlotStyle.Line, "Smas");
    AddPlot(new Stroke(Brushes.DarkRed, 2), PlotStyle.Line, "Emas");
    }
    else if (State == State.DataLoaded)
    {
    SMA1 = SMA(30);
    EMA1 = EMA(30);
    }
    
    // within OnBarUpdate()
    if ( (SMA1[0] > SMA1[1] && EMA1[0] > EMA1[1]) || (SMA1[0] < SMA1[1] && EMA1[0] < EMA1[1])
    {
    Smas[0] = SMA1[0];
    Emas[0] = EMA1[0];
    }
    
    if (SMA1[0] > SMA1[1] && EMA1[0] > EMA1[1])
    Draw.ArrowUp(this, "iup", true, 0, Low[1] - (Dtau * TickSize), Brushes.DarkBlue);
    
    else if (SMA1[0] > SMA1[1] && EMA1[0] > EMA1[1])
    Draw.ArrowUp(this, "ido", true, 0, High[1] + (Dttad * TickSize), Brushes.DarkRed);
    
    // within the scope of the class
    [Browsable(false)]
    [XmlIgnore]
    public Series<double> Smas
    {
    	get { return [B]Values[0][/B]; }
    }
    
    [Browsable(false)]
    [XmlIgnore]
    public Series<double> Emas
    {
    	get { return [B]Values[1][/B]; }
    }

    I'm not quite clear what the plots are attempting to achieve. These were set to PlotStyle.Triangle. This means whenever Values[0] and Values[1] have a bar set, the plot will appear as a string of triangles from the current bar to the previous bar. Then there are even more triangles drawn on top of these as drawing objects that appear when conditions are true..

    Below I am providing a link to a forum post with helpful information about getting started making NinjaScript Strategies and Indicators.
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      Chelsea,



      thanks.


      i have a number of indicators and strategies for another platform that i have been to develop over a number of years. these are mostly simple things, and given that ninjatrader is a more powerful platform, and it performs far better, and also very relevantly, that commissions and costs are lower with nt, it is that i have been trying to convert some of these simple instruments into nt8. i have found out that this can be a challenging enterprise at times for someone who is not a programmer.


      in this case the simple indicator i have in mind is shown in the images attached. i quickly put together two different versions, one which plots gray circles only below the bars for which the two moving averages are increasing and white circles only above the bars when the two averages are decreasing. an analogous format paints the entire bars gray or white depending on the corresponding case. in either case, it is not necessary to plot the moving averages, they would just be used for the appropriate calculations.





      the code looks like this:


      Code:
      
      emav = xaverage( price, emap ) ;
      smav = average ( price, smap ) ;
      
      
      
      mmv = minmove/pricescale ;
      offs = average ( high[1]-low[1], 7000);
      
      if emav > emav[1] and smav > smav[1] then begin
      
      plot1(low[1] - (dm * mmv * offs), "dsm");
      
      end
      else if emav < emav[1] and smav < smav[1] then begin
      
      plot2(high[1] + (dm * mmv * offs), "dsm");
      
      end
      else
      noplot( 1 ) ;
      the issues i'm having with nt8 have to do with the && condition (even when i had managed to make it work acceptably on nt7) and the third or default condition after - if - and - else if - (no plot).

      in this particular case i think it could be possible to create an indicator that plotted triangles (or arrows, or circles, or squares or whatever) when the two moving averages point in the same direction by creating two separate - if - conditions as you did in the code you posted. however, i would like to know if a general structure like the one i posted above could be created for nt8, where two mutually exclusive conditions are evaluated and if neither is true then the code reverts to a default option as i might use it for other indicators and strategies.


      i also have some other questions:

      - ¿is it possible to create some indicator in nt8 like the one on the second image i posted that painted bars in a chart according to user defined conditions?

      - in this line you posted:

      if ( (SMA1[0] > SMA1[1] && EMA1[0] > EMA1[1]) || (SMA1[0] < SMA1[1] && EMA1[0] < EMA1[1])

      ¿what does the - || - mean, and why would the second part be necessary?



      very well, thanks, regards.
      Attached Files
      Last edited by rtwave; 01-17-2018, 11:02 PM.

      Comment


        #4
        Rtwave,

        I built an indicator that draws arrows on each bar my conditions are true. Here is how I have my arrow plot setup to draw an arrow a certain amount of ticks above/below on each bar my conditions are true:

        Draw.ArrowUp(this, @"GreenArrowUp"+CurrentBar, false, 0, (Low[0] + (-2 * TickSize)) , Brushes.Lime);
        This example plots an arrow up 2 ticks below the low of the bar. Also, Ninjatrader 7 did this for you, but Ninjatrader 8 does not. "+CurrentBar" must be added to your logic or an arrow will only be plotted on the last high and low. With +CurrentBar added, the indicator will draw an arrow on every bar where the conditions are true.

        Also, are you sure you need an else if? I use:
        if(this is this on last bar[1] && this is this on current bar{0})

        Draw arrow

        I'd imagine that should be all you would need since an arrow won't be drawn if the conditions are not true.


        Chris
        Last edited by chrisca; 01-16-2018, 10:16 AM.

        Comment


          #5
          Hello rtwave,

          I think there may be differences in terminology from the other platform.

          When you mention plot, as in:

          plot1(low[1] - (dm * mmv * offs), "dsm");

          You are saying that this will draw a single drawing object on that bar and does not create a line connecting the set points, is this correct?

          For NinjaTrader this would be a drawing object.

          A plot in NinjaTrader is a line (or string of triangles or dashes) that connect the current bar to the previous bar.
          As an example of a plot in NinjaTrader add the SMA indicator to the chart. The line that appears represents the current SMA value for the bar. This will rise and fall as a curved line connecting the bars together.

          Is my understanding of how you are using the word plot correct?
          (In that you are expecting a single object on a bar and you are not expecting a line?)

          (I don't think you are actually wanting plots in your script.. I think you are wanting to draw a drawing object when the sma and ema are rising together or falling together)


          The || symbol means OR while the && means AND.

          if (1 == 1 && 1 == 2) <-- this will evaluate as false as 1 does not equal two and both conditions must be true as they are joined with an AND

          if (1== 1 || 1 == 2) <-- this will evaluate as true as 1 does equal 1, and the conditions are joined with an OR (meaning either condition can be true).

          Below is a publicly available link to a 3rd party educational site on if statements.
          Encode branching logic with if, else-if and else. Evaluate conditions to true or false.



          With the condition set
          if ( (SMA1[0] > SMA1[1] && EMA1[0] > EMA1[1]) || (SMA1[0] < SMA1[1] && EMA1[0] < EMA1[1])

          This states
          if the sma on the current bar is greater than the sma on the preivous bar and the ema on the current bar is also greater than the ema on the previous bar,
          OR if the sma on the current bar is less than the sma on the previosu bar and the ema on the current bar is also less than the ema on the current bar,
          then set the line plot on this bar to connect with the previous bar,
          otherwise if the sma and ema are not rising or falling together, then do nothing and do not set a line plot value to connect with the previous bar.

          With the drawing objects, you wouldn't need an else to trigger something when you want no drawing object. If you want nothing to happen, then don't trigger any actions such as drawing a drawing object.
          Last edited by NinjaTrader_ChelseaB; 01-16-2018, 03:02 PM.
          Chelsea B.NinjaTrader Customer Service

          Comment


            #6
            Chelsea and Chris,



            thanks.


            i now get the difference between plots and drawing objects in nt. i wouldn't mind using either of them on this indicator as long as visual markings were placed only in the correct bars and in the correct locations as have been defined.

            below i post the latest version of code i have for this indicator, it does compile correctly but it doesn't plot anything. i tried a number of minor modifications; if + if, if + else if, and the +CurrentBar addition Chris kindly suggested and the code will compile every time but the indicator won't plot anything in any case.


            this is a really simple idea for an indicator, which uses very basic inputs to create a very basic signalling system, so i have no idea what could still be wrong. any assistance would be greatly appreciated. thanks.


            Code:
                Calculate                                    = Calculate.OnBarClose;
                            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;
                            Pesma                    = 30;
                            Peema                    = 30;
                            Dtau                    = 8;
                            Dtad                    = 8;
                            
                        }
                        else if (State == State.Configure)
                        {
                        }
                    }
            
                    protected override void OnBarUpdate()
                    {
                        
                        
                        double smav    = SMA(Pesma)[0];
                        double emav    = EMA(Peema)[0];
                        
                        Smas[0] = smav;
                        Emas[0] = emav;
                        
                        Plots[0].Width = 5;
                        Plots[1].Width = 5;
                        
                        
                        if (CurrentBar < 1) return;
                        
                        
                        if (  Smas[0] > Smas[1] && Emas[0] > Emas[1]  )
                        {
                            Draw.ArrowUp(this, "iup", true, 0, Low[1] - (Dtau * TickSize), Brushes.Gray);
                        
                        
                        }
                    
                        else if (  Smas[0] < Smas[1] && Emas[0] < Emas[1]  )
                        {
                            Draw.ArrowDown(this, "ido", true, 0, High[1] + (Dtad * TickSize), Brushes.White);
                        
                        
                        }
                        
            #region Properties
                    
                    [Browsable(false)]
                    [XmlIgnore]
                    public Series<double> Smas
                    {
                        get { return Values[0]; }
                    }
            
                    [Browsable(false)]
                    [XmlIgnore]
                    public Series<double> Emas
                    {
                        get { return Values[1]; }
                    }

            Comment


              #7
              Rtwave,

              Just a though, but have you tried using an if statement instead of else if to plot the other arrows? I am wondering if that section of code is causing the indicator to not plot.

              Chris

              Comment


                #8
                Chris,


                indeed i tried using all the variations possible, including if and if for both conditions, as well as if and else if, but even when the code compiles in all cases nothing is plotted in the end.

                the if, else if, else structure could become necessary for other indicators so i will keep trying to make this basic indicator work and also understand the proper way to use these commands.

                Comment


                  #9
                  the following is a strategy for nt7 that i got from this post at morbidly obese mike's forum:


                  private void GoLong() { SetStopLoss("target1", CalculationMode.Price, Close[0] - (Stop*TickSize), false); SetProfitTarget("target1", CalculationMode.Price, Close[0] + ((Target1+Target2+Target3)*TickSize)); EnterLong("target1"); } private void ManageOrders() { if (Position.MarketPosition == MarketPosition.Long) { if (High[0] > Position.AvgPrice + ((Target1+Target2+Target3)*TickSize)) SetStopLoss("target1", CalculationMode.Price, Position.AvgPrice &#8230;



                  this code compiles and seems to work without problem in nt7. transcribing this strategy from the post to nt7 was practically the first time i ever worked with ninjascript and helped me get started with converting the code i have for other platforms into ninjatrader. i will now try to adapt this strategy to nt8, and from my experience so far, it won't be the easiest thing in the world.


                  anyway, it is precisely a small variation of the fragment with the conditions to enter long and short from this strategy that i'm trying to transform into a visual signalling system that uses arrows (or triangles, or diamonds or whatever) to alert when these conditions are true. commands like &&, if, else if, else and others work perfectly in nt7, so it is really perplexing how in nt8 they will compile but won't produce the same results.



                  Code:
                  [INDENT]ManageOrders();
                  [/INDENT]
                              
                              if (Position.MarketPosition != MarketPosition.Flat) return;
                              
                              
                              if (Rising(smav) && Rising(emav) && Rising(hmav))
                                  GoLong();
                              
                              
                              else if (Falling(smav) && Falling(emav) && Falling(hmav))
                                  GoShort();
                  morbidly obese mike's sample strategy in full:


                  Code:
                  #region Variables
                          
                          // User defined variables (add any user defined variables below)
                                  
                          private int smalength = 120;
                          private int emalength = 120;
                          private int hmalength = 120;
                          
                          private int target1 = 12;
                          private int target2 = 12;
                          private int target3 = 12;
                          
                          private int stop = 12;
                          
                          private bool be2 = false;
                          private bool be3 = false;
                          
                          
                          #endregion
                  
                          /// <summary>
                          /// This method is used to configure the strategy and is called once before any strategy method is called.
                          /// </summary>
                          protected override void Initialize()
                          {
                              CalculateOnBarClose = true;
                              EntryHandling = EntryHandling.UniqueEntries;
                          }
                  
                          private void GoLong()
                          {    
                              SetStopLoss("target1", CalculationMode.Price, Close[0] - (Stop*TickSize), false);
                              SetStopLoss("target2", CalculationMode.Price, Close[0] - (Stop*TickSize), false);
                              SetStopLoss("target3", CalculationMode.Price, Close[0] - (Stop*TickSize), false);
                              
                              
                              SetProfitTarget("target1", CalculationMode.Price, Close[0] + (Target1*TickSize));
                              SetProfitTarget("target2", CalculationMode.Price, Close[0] + ((Target1+Target2)*TickSize));
                              SetProfitTarget("target3", CalculationMode.Price, Close[0] + ((Target1+Target2+Target3)*TickSize));
                              
                              EnterLong("target1");
                              EnterLong("target2");
                              EnterLong("target3");
                          }
                          
                          
                          private void GoShort()
                          {    
                              SetStopLoss("target1", CalculationMode.Price, Close[0] + (Stop*TickSize), false);
                              SetStopLoss("target2", CalculationMode.Price, Close[0] + (Stop*TickSize), false);
                              SetStopLoss("target3", CalculationMode.Price, Close[0] + (Stop*TickSize), false);
                              
                              
                              SetProfitTarget("target1", CalculationMode.Price, Close[0] - (Target1*TickSize));
                              SetProfitTarget("target2", CalculationMode.Price, Close[0] - ((Target1+Target2)*TickSize));
                              SetProfitTarget("target3", CalculationMode.Price, Close[0] - ((Target1+Target2+Target3)*TickSize));
                              
                              EnterShort("target1");
                              EnterShort("target2");
                              EnterShort("target3");
                          }
                          
                          private void ManageOrders()
                          {    
                              if (Position.MarketPosition == MarketPosition.Long)
                                  
                                  {
                                      
                                      if (BE2 && High[0] > Position.AvgPrice + (Target1*TickSize))
                                      SetStopLoss("target2", CalculationMode.Price, Position.AvgPrice, false);
                              
                          
                                      if (BE3 && High[0] > Position.AvgPrice + ((Target1+Target2)*TickSize))
                                      SetStopLoss("target3", CalculationMode.Price, Position.AvgPrice, false);
                                      
                                  }
                                  
                                  
                              if (Position.MarketPosition == MarketPosition.Short)
                                  
                                  {
                                      
                                      if (BE2 && Low[0] < Position.AvgPrice - (Target1*TickSize))
                                      SetStopLoss("target2", CalculationMode.Price, Position.AvgPrice, false);
                              
                          
                                      if (BE3 && Low[0] < Position.AvgPrice - ((Target1+Target2)*TickSize))
                                      SetStopLoss("target3", CalculationMode.Price, Position.AvgPrice, false);
                                      
                                  }
                          
                          }
                          protected override void OnBarUpdate()
                          {
                              EntryHandling = EntryHandling.UniqueEntries;
                          
                              SMA        smav = SMA(smalength);
                              EMA        emav = EMA(emalength);
                              HMA        hmav = HMA(hmalength);
                              
                              
                              ManageOrders();
                              
                              
                              if (Position.MarketPosition != MarketPosition.Flat) return;
                              
                              
                              if (Rising(smav) && Rising(emav) && Rising(hmav))
                                  GoLong();
                              
                              
                              else if (Falling(smav) && Falling(emav) && Falling(hmav))
                                  GoShort();
                              
                              
                          }

                  Comment


                    #10
                    Hello rtwave,

                    I recommend using prints to understand the behavior of your strategy that is calling ManageOrders() and GoLong().

                    Print all values for all variables that are used in the conditions for the action you are expecting.

                    Below is a link to a post that details.


                    Your post #6 includes 'return Values[0];' in the declaration.

                    Values is a collection of data series for plots. Anytime you call AddPlot() in an indicator this adds a series to the Values collection.

                    Values[0] would be the first plot. Values[1] would be the second plot.

                    However, your script does not have plots added with AddPlot(). These are empty and are not holding values.

                    Are you trying to show the EMA and SMA on the chart?

                    If so, use AddPlot() for each of these.

                    Also, you are attempting to call 1 bar ago. This means the script needs to wait for at least 2 bars to exist or you will be calling for a index that doesn't exist and this will cause an error to appear in the Log tab of the Control Center.

                    Attached is your code added to a script with AddPlot() added twice so that Values[0] and Values[1] exist.

                    Also attached is a screenshot showing the drawing object is visible.
                    Attached Files
                    Chelsea B.NinjaTrader Customer Service

                    Comment


                      #11
                      Chelsea,



                      thanks. there is some progress to report.


                      i have tried the code you kindly posted. it does generate two arrows in the last correct location for each condition. once i added +CurrentBar to the command lined, as Chris kindly suggested before, i do get the kind of signals i'm looking for in every bar for which the conditions are true.





                      however, if i get rid of the plots for the sma and ema (by deleting the AddPlot(Brushes.White, "sma"); AddPlot(Brushes.White, "ema"); lines), the arrows will not be plotted either. i think that the plots for the moving averages are redundant once i have the arrows in the chart, and i would prefer to have only the drawing objects. ¿is there any way to have nt8 only create the drawing tools markers without having to also plot every indicator i might use to for the conditions?


                      thanks again.

                      Comment


                        #12
                        Hello rtwave,

                        The code you have was redundant and I left it this way. I was only demonstrating that the logic for your conditions does draw arrows.

                        The plots are the lines.
                        The drawing objects are the triangles.

                        This where I think we have a disconnect on what plots are.

                        Your plots are being set to the value of an indicator. These are being drawn as lines on the chart.

                        Your conditions are checking your plots. If you remove the plots, you remove the input for conditions.

                        Instead, why not reference the indicators directly and stop referencing the plots?
                        Code:
                        // in the scope of the indicator class
                        private SMA mySMA;
                        private EMA myEMA;
                        
                        // in OnStateChange when state is State.DataLoaded
                        mySMA = SMA(Pesma);
                        myEMA = EMA(Peema);
                        
                        // in OnBarUpdate
                        if (mySMA[0] > mySMA[1] && myEMA[0] > myEMA[1])
                        Last edited by NinjaTrader_ChelseaB; 01-18-2018, 08:26 AM.
                        Chelsea B.NinjaTrader Customer Service

                        Comment


                          #13
                          mission accomplished. in the end i was able to put together an indicator that would only draw arrows according to the behavior of two moving averages without plotting anything else.



                          i used the same structure as this sample indicator below and worked my way from there to get the indicator i had in mind.

                          Indicator: Multi-Colored Plots.




                          what i had to do was define the values for an sma and an ema as two series and then nt8 was able to make operations with them without having to have plotted these lines. i think i will be using an identical structure whenever i want to use the values of an indicator without having it plotted in the chart. now i will be doing some tests to find out whether this is also the case when coding an strategy.


                          - i still have a question, i have managed to create an indicator that uses drawing objects as visual signals ¿is it possible to create a similar nt indicator that instead painted the bars or any region of a chart according to user defined conditions like the one in the images i shared before?


                          thanks to all, regards.

                          Comment


                            #14
                            Hello,

                            Thank you for the reply.

                            You could use the BackBrush, BarBrush or a Region tool to shade a region, is this what you are asking?





                            I look forward to being of further assistance.
                            JesseNinjaTrader Customer Service

                            Comment


                              #15
                              Jesse and everyone else,


                              thanks.


                              the barbrush command works perfectly for what i had in mind.



                              thanks again.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by maybeimnotrader, Today, 05:46 PM
                              0 responses
                              6 views
                              0 likes
                              Last Post maybeimnotrader  
                              Started by quantismo, Today, 05:13 PM
                              0 responses
                              6 views
                              0 likes
                              Last Post quantismo  
                              Started by AttiM, 02-14-2024, 05:20 PM
                              8 responses
                              166 views
                              0 likes
                              Last Post jeronymite  
                              Started by cre8able, Today, 04:22 PM
                              0 responses
                              8 views
                              0 likes
                              Last Post cre8able  
                              Started by RichStudent, Today, 04:21 PM
                              0 responses
                              5 views
                              0 likes
                              Last Post RichStudent  
                              Working...
                              X