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

New to NT7. Strategy Dev of PPO?

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

    New to NT7. Strategy Dev of PPO?

    Hi all,
    I'm hoping I'm not asking plainly obvious questions, but I've been playing around with the strategy wizard and fumbling around with the code and having little success in creating a strategy that essentially uses modified EMA input values for entering positions on crossovers. I'm working on a strategy which enters long of the PPO line crossing above the signal, and vice versa.

    Is there a simple way of taking the existing PPO code included in NT7's library, modifying the existing default values and going from there?

    J.

    #2
    Hello blacksheepesq,

    Thanks for your post and welcome to the forums!

    Yes, you could open the indicator and copy its code and then paste it into the strategy however you can accomplish your strategy in the wizard without the need to do that.

    When you have an indicator with multiple plot lines you need to identify which line you want to use and that is done by the "plot" selection of the indicator in the wizard. I've attached a screenshot of the wizard settings needed to take an action when the PPO line crosses above the smoothed line. The red rectangles show the selections I made.

    For the action I've added plotting blue dots a few ticks below the low of the bar where the cross occurs to help verify that the strategy sees the cross action, please see the 2nd screenshot.

    edit: added clarifying text in the last paragraph.
    Attached Files
    Last edited by NinjaTrader_PaulH; 11-23-2016, 07:30 AM.
    Paul H.NinjaTrader Customer Service

    Comment


      #3
      Paul,
      You certainly pointed me in the right direction. I was able to start constructing a strategy that focused on longs in the ES.

      I don't suppose you know if there's a way to program the logic so that I can start managing trades when the PPO slope flattens out? Since the PPO is a built in indicator, I would probably have to muck around with the actual script in order to achieve this goal...

      Thank again for the help so far.

      Comment


        #4
        Hello blacksheepesq,

        Thanks for your reply.

        You might look at and test with using the Slope in the strategy wizard found under the Misc category.

        You may want to review the helpguide's wizard screens to learn more about the use of the strategy wizard. Here are some helpful links:

        http://ninjatrader.com/support/helpG...on_builder.htm
        http://ninjatrader.com/support/helpG...gy_actions.htm

        In addition you may want to review these strategy wizard videos:
        https://www.youtube.com/watch?v=FmBi...D7105&index=10

        While geared towards alerting, this video shows another use of the strategy wizard: https://www.youtube.com/watch?v=vt0s...A140D7&index=6
        Paul H.NinjaTrader Customer Service

        Comment


          #5
          Help creating indicator from scratch

          So far wonderful help, I have the slop indicator on the schedule for this weekend!

          I'm attempting to create an indicator to be plotted on a panel below price data, but have run into a few problems. I've included the code below sans the automatically generated NT7 script at the bottom. I hope it's all clear.

          I get a variety of error messages

          // This namespace holds all indicators and is required. Do not change it.
          namespace NinjaTrader.Indicator
          {
          /// <summary>
          /// Enter the description of your new custom indicator here
          /// </summary>
          [Description("Enter the description of your new custom indicator here")]
          public class WToscillator : Indicator
          {
          #region Variables
          // Wizard generated variables
          private int channelLength = 10; // Default setting for ChannelLength
          private int averageLength = 21; // Default setting for AverageLength
          // User defined variables (add any user defined variables below)
          #endregion

          /// <summary>
          /// This method is used to configure the indicator and is called once before any bar data is loaded.
          /// </summary>
          protected override void Initialize()
          {
          Add(new Line(Color.Red, 60, "ExtremeOverbought"));
          Add(new Line(Color.Green, 53, "Overbought"));
          Add(new Line(Color.Green, -53, "Oversold"));
          Add(new Line(Color.Red, -60, "ExtremeOversold"));

          // Add(new Plot(Color.FromKnownColor(KnownColor.Red), PlotStyle.Line, "ExtremeOverbought"));
          // Add(new Plot(Color.FromKnownColor(KnownColor.Lime), PlotStyle.Line, "Overbought"));
          // Add(new Plot(Color.FromKnownColor(KnownColor.Lime), PlotStyle.Line, "Oversold"));
          // Add(new Plot(Color.FromKnownColor(KnownColor.Red), PlotStyle.Line, "ExtremeOversold"));
          Overlay = false;
          }

          /// <summary>
          /// Called on each bar update event (incoming tick)
          /// </summary>
          protected override void OnBarUpdate()
          {
          // Use this method for calculating your indicator values. Assign a value to each
          // plot below by replacing 'Close[0]' with your own formula.
          ExtremeOverbought.Set(Close[0]);
          Overbought.Set(Close[0]);
          Oversold.Set(Close[0]);
          ExtremeOversold.Set(Close[0]);

          //Introduce typical bar price.
          double barTypicalPrice = Typical[0];

          //Introduce esa variable.
          double esa = EMA(barTypicalPrice, channelLength)[0];

          //Introduce d
          double d = EMA(Math.Abs(barTypicalPrice - esa), channelLength);

          //Introduce "choppiness index"
          double ci = (barTypicalPrice - esa)/(0.015*d);

          double tci = EMA(ci, averageLength)[0];

          //Define the oscillator lines...
          double wt1 = tci;
          double wt2 = SMA(wt1, 4);

          }

          #region Properties
          [Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove
          [XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove
          public DataSeries ExtremeOverbought
          {
          get { return Values[0]; }
          }

          [Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove
          [XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove
          public DataSeries Overbought
          {
          get { return Values[1]; }
          }

          [Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove
          [XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove
          public DataSeries Oversold
          {
          get { return Values[2]; }
          }

          [Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove
          [XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove
          public DataSeries ExtremeOversold
          {
          get { return Values[3]; }
          }

          [Description("Channel Length")]
          [GridCategory("Parameters")]
          public int ChannelLength
          {
          get { return channelLength; }
          set { channelLength = Math.Max(1, value); }
          }

          [Description("AverageLength")]
          [GridCategory("Parameters")]
          public int AverageLength
          {
          get { return averageLength; }
          set { averageLength = Math.Max(1, value); }
          }
          #endregion
          }
          }


          I am getting a series of error messages that I have not been able to decipher.

          Argument '1' cannot convert from 'double' to 'NinjaTrader.Data.IDataSeries" applying to lines where I declare and initialize the variables esa, d, tci and wt2. For the same lines I'm also getting a "the best overloaded method match for NinjaTrader.Indicator.Indicator.EMA(NinjaTrader.Da ta.IDataSeries, int)' has some invalid arguments" error message---SMA for the wt2 for obvious reasons.

          Newbie here, am I completely going about the syntax the wrong way? Thanks again.

          Comment


            #6
            Hello blacksheepesq,

            Thanks for your post.

            It looks like the issue is that you are trying to get EMA of a double value and the EMA requires a data series as its input. The syntax is EMA(dataseries, Period). http://ninjatrader.com/support/helpG...onential_e.htm

            You may want to review the helpguide on creating a dataseries that you can use in the EMA(), here is a link to that section: http://ninjatrader.com/support/helpG...ries_class.htm
            Paul H.NinjaTrader Customer Service

            Comment


              #7
              Ah, you are right...I will review this tonight and let you know how I progressed...

              Comment


                #8
                Nope, I decided to start from scratch by creating a dataseries in the in Variables region, tried compiling the basic code and got an error:

                "Type.Ninjatrader.Indicator.WTOversion2 already defines a member 'Initialize' with the same parameter types".

                The error takes place right on the initialize() line of code: " protected override void Initialize()"

                Compiler error code 'CS0111'.

                Frankly, I don't get it because I didn't touch the initialize() method.

                #region Using declarations
                using System;
                using System.ComponentModel;
                using System.Diagnostics;
                using System.Drawing;
                using System.Drawing.Drawing2D;
                using System.Xml.Serialization;
                using NinjaTrader.Cbi;
                using NinjaTrader.Data;
                using NinjaTrader.Gui.Chart;
                #endregion

                // This namespace holds all indicators and is required. Do not change it.
                namespace NinjaTrader.Indicator
                {
                /// <summary>
                /// Enter the description of your new custom indicator here
                /// </summary>
                [Description("Enter the description of your new custom indicator here")]
                public class WTOversion2 : Indicator
                {
                #region Variables
                // Wizard generated variables
                // User defined variables (add any user defined variables below)


                // Create a DataSeries object and assign it to the variable
                protected override void Initialize()
                {
                myDataSeries = new DataSeries(this); // "this" refers to the indicator, or strategy
                // itself. This syncs the DataSeries object
                // to historical data bars
                }
                #endregion
                /// <summary>
                /// This method is used to configure the indicator and is called once before any bar data is loaded.
                /// </summary>
                protected override void Initialize()
                {
                Add(new Line(Color.Red, 60, "ExtremeOverbought"));
                Add(new Line(Color.Green, 53, "Overbought"));
                Add(new Line(Color.Green, -53, "Oversold"));
                Add(new Line(Color.Red, -60, "ExtremeOversold"));
                //Add(new Plot(Color.FromKnownColor(KnownColor.Chartreuse), PlotStyle.Line, "WTFast"));
                //Add(new Plot(Color.FromKnownColor(KnownColor.Red), PlotStyle.Line, "Signal"));
                Overlay = false;
                }

                /// <summary>
                /// Called on each bar update event (incoming tick)
                /// </summary>
                protected override void OnBarUpdate()
                {

                // Calculate the range of the current bar and set the value
                myDataSeries.Set(Typical[0]);

                //Calculate the typical price
                double bar_typical = Typical[0];

                //Keep working from here.


                double esa = EMA(bar_typical, 10);

                // Use this method for calculating your indicator values. Assign a value to each
                // plot below by replacing 'Close[0]' with your own formula.
                WTFast.Set(Close[0]);
                Signal.Set(Close[0]);
                }

                #region Properties
                [Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove
                [XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove
                public DataSeries WTFast
                {
                get { return Values[0]; }
                }

                [Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove
                [XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove
                public DataSeries Signal
                {
                get { return Values[1]; }
                }

                #endregion
                }
                }

                Comment


                  #9
                  Hello blacksheepesq,

                  Thanks for your reply.

                  Sometimes starting fresh is a good idea!

                  The error code relates to the added initialize() in your code, I would remove the section:

                  // Create a DataSeries object and assign it to the variable
                  protected override void Initialize()
                  {
                  myDataSeries = new DataSeries(this); // "this" refers to the indicator, or strategy
                  // itself. This syncs the DataSeries object
                  // to historical data bars
                  }


                  and in its place (in the Region variables) add:

                  private DataSeries myDataSeries; // Define a DataSeries variable

                  In the existing initialize() section, below the line Overlay = false; I would add:

                  myDataSeries = new DataSeries(this); // "this" refers to the indicator, or strategy

                  Those changes will properly set up adding the dataseries.


                  Looking at the rest of your code you will also have issues with:

                  double esa = EMA(bar_typical, 10); because bar_typical is not a dataseries but is a double as you defined it here: double bar_typical = Typical[0];

                  I may be jumping ahead here as I am not sure what you are trying to accomplish but if you want the current value of a 10 period EMA of the Typical price then you would contract a line like:

                  double esa = EMA(Typical, 10)[0];

                  Typical is already a dataseries that you can use. the index [0] means to get the current value of the 10 period EMA.

                  So if all you need to is the typical price type data series then you do not need to add another dataseries unless you are trying to do something else.

                  Hope this helps.
                  Paul H.NinjaTrader Customer Service

                  Comment


                    #10
                    Thank you for your prompt reply,
                    I suspected that ‘Typical’ was already a dataseries already built into NTS, but I had read the forums and erroneously came to believe that I needed to create a whole new dataseries. You are right – all I need is the typical price of a 10 period EMA.
                    Next, I’d like to take the absolute value of difference between the typical price and that EMA over ten periods, and take that ema and assign it to a variable.
                    Basically, little by little, I’m trying to build up the following basic logic into NTS for strategy development. This behaves like an RSI. I'm glad to see that I don't have to create a whole new dataseries, and hlc3 appears to coincide with the 'Typical' method in NTS. Looks like I have a weekend project.

                    n1 = 10 // 10 periods
                    n2 = 21 // 21 periods

                    avprice = hlc3
                    esa = ema(ap, n1)
                    d = ema(abs(ap - esa), n1)
                    chop_index = (ap - esa) / (0.015 * d)
                    tci = ema(ci, n2)

                    wt1 = tci
                    wt2 = sma(wt1,4)

                    Comment


                      #11
                      Tried again with no avail. I'm still getting errors trying to convert an IDataseries input into a double. Frankly, I guess I'm not seeing why that would be an issue, even based on the syntax because EMA can take in a literal number as an input! And that can be a double!

                      This is driving me nuts. I'm busy with my other work and I've spent the entire weekend trying to bumble around with the tutorials and the guide. I could really use some help here....


                      //ap = hlc3
                      //esa = ema(ap, n1)
                      //d = ema(abs(ap - esa), n1)
                      //ci = (ap - esa) / (0.015 * d)
                      //tci = ema(ci, n2)

                      double ap = Typical[0];
                      double esa = EMA(Typical,ChannelLength)[0];
                      double d = EMA(Math.Abs(Typical[10] - esa))[0]; // really need to watch my code here.
                      double ci = (ap - esa) / (0.015 * d);
                      double tci = EMA(ci, AverageLength);

                      wt1 = tci;
                      wt2 = sma(wt1,4);

                      I'll plot the wt1 and the wt2 lines on the chart. at least I've figured out that the code for that has to be inputted into the Initialize() method.

                      For the HLC3 section I've even tried forgoing the whole Typical() route entirely (since I can't seem to get that working) and tried the following:

                      double ap = (High[0] + Low[0] + Close[0])/3;
                      double esa = EMA(ap, ChannelLength)[0];

                      No dice. Oh, I declared and initialized channelLength in the variable section.

                      Comment


                        #12
                        Hello blacksheepesq,

                        Thanks for your reply.

                        This statement: double tci = EMA(ci, AverageLength); will fail because the statement is trying to assign an entire dataseries to a singular variable which is a double. If you are wanting the current value of the dataseries then you would add the index [0] to select the latest value. So the correct syntax would be double tci = EMA(ci, AverageLength)[0];

                        This statement: wt2 = sma(wt1,4); is the same issue of trying to assign an entire dataseries to a single variable and the solution is the same: wt2 = sma(wt1,4)[0];

                        This statement: double d = EMA(Math.Abs(Typical[10] - esa))[0]; has a lot going on. While the index[0] is the correct way to get the current value of the dataseries, I am unsure of what you are trying to accomplish with Math.Abs(Typical[10] - esa) The statement as written would be the absolute value of the typical price 10 bars ago minus the value of esa. The result then would be used to specify the "period" of the EMA of the default price type which would be the Close value. However the period needs to be an integer value and the statement would resolve to a double causing an error of unable to convert from double to int.

                        This statement: double esa = EMA(ap, ChannelLength)[0]; would fail because ap is defined in the previous statement as a singular value and needs to be a dataseries. I would advise to use: double esa = EMA(Typical, ChannelLength)[0]; assuming that ChannelLength is an integer.
                        Paul H.NinjaTrader Customer Service

                        Comment


                          #13
                          So, here's my code in the Initiliaze() method of my indicator...

                          /// <summary>
                          /// This method is used to configure the indicator and is called once before any bar data is loaded.
                          /// </summary>
                          protected override void Initialize()
                          {

                          // Add(new Line(System.Drawing.Color.Red, 60, "ExtremeOverbought"));
                          // Add(new Line(System.Drawing.Color.Green, 53, "Overbought"));
                          // Add(new Line(System.Drawing.Color.Green, -53, "Oversold"));
                          // Add(new Line(System.Drawing.Color.Red, -60, "ExtremeOversold"));

                          40 //double ap = (High[0] + Low[0] + Close[0]) / 3; //
                          41 double esa = EMA(Typical, ChannelLength)[0];
                          42 double d = EMA(Math.Abs(Typical - esa))[0];
                          43 double ci = (Typical - esa) / (0.015 * d);
                          44 double tci = EMA(ci, AverageLength)[0];
                          45
                          46 double wt1 = tci;
                          47 double wt2 = SMA(wt1, 4)[0];
                          //
                          // Overlay = false;
                          // CalculateOnBarClose = true;
                          }


                          ....And here are the following compiler error messages....

                          Indicator\JonsCustomStrategy.cs Argument '1': cannot convert from 'double' to 'NinjaTrader.Data.IDataSeries' NT1503 - click for info 44 21

                          Indicator\JonsCustomStrategy.cs Argument '1': cannot convert from 'double' to 'NinjaTrader.Data.IDataSeries' NT1503 - click for info 47 21

                          Indicator\JonsCustomStrategy.cs Operator '-' cannot be applied to operands of type 'NinjaTrader.Data.IDataSeries' and 'double' NT0019 - click for info 42 28

                          Indicator\JonsCustomStrategy.cs Operator '-' cannot be applied to operands of type 'NinjaTrader.Data.IDataSeries' and 'double' NT0019 - click for info 43 17

                          Indicator\JonsCustomStrategy.cs The best overloaded method match for 'NinjaTrader.Indicator.Indicator.EMA(NinjaTrader.D ata.IDataSeries, int)' has some invalid arguments CS1502 - click for info 44 17

                          Indicator\JonsCustomStrategy.cs The best overloaded method match for 'NinjaTrader.Indicator.Indicator.SMA(NinjaTrader.D ata.IDataSeries, int)' has some invalid arguments CS1502 - click for info 47 17


                          I can't help but feel that the solution is painfully obvious. I am aware that certain methods must take a dataseries or Idataseries for the first parameter. I'm just trying to get the EMA of the typical price of the instrument for 10 (or user defined) periods back. I presume that "double esa = EMA(Typical, ChannelLength)[0];" should be no problem.

                          I'm not really understanding why line 42 should be a problem though -- and I have a hunch it's syntax. You mean to say that the difference between 'Typical' and 'esa' isn't allowed because esa would be at this point defined as a double??

                          And then there's the issue of the variable 'ci'....am I REQUIRED to create a data series to hold that data?? That seems very clumsy. But if I must do it, perhaps you can walk me through that process. I can't find an example in the scripts that come with NT7.

                          Many thanks.

                          Comment


                            #14
                            Hello blacksheepesq,

                            Thanks for your reply.

                            Please remove lines 40 - 47 from the Initialize() method and place them in the OnBarUpdate() method.
                            Initialize() is called before bars are loaded and trying access bar data there will cause errors.

                            Line 44 will not work as you cannot get the EMA of a double value, it must be a dataseries.

                            line 42: "I'm not really understanding why line 42 should be a problem though -- and I have a hunch it's syntax. You mean to say that the difference between 'Typical' and 'esa' isn't allowed because esa would be at this point defined as a double??" - Correct, both esa and Typical are double and this difference will resolve to a double value, the EMA is requiring that an integer value be specified for the period.
                            Paul H.NinjaTrader Customer Service

                            Comment


                              #15
                              Decided to tackle this a little more tonight by creating a DataSeries object -- or at least attempt to. Here's the code I have so far. Still have errors (of course!)

                              protected override void Initialize()
                              {
                              myDataSeries = new DataSeries(this); //'this' refers to this indicator and syncs the DataSeries object to historical data bars

                              Add(new Line(System.Drawing.Color.Red, 60, "ExtremeOverbought"));
                              Add(new Line(System.Drawing.Color.Green, 53, "Overbought"));
                              Add(new Line(System.Drawing.Color.Green, -53, "Oversold"));
                              Add(new Line(System.Drawing.Color.Red, -60, "ExtremeOversold"));

                              Add(new Plot(Color.FromKnownColor(KnownColor.Cyan), PlotStyle.Line, "Plot0")); // Set Plot0 values in the OnBarUpdate() method section below
                              Overlay = false;
                              CalculateOnBarClose = true;
                              }

                              /// <summary>
                              /// Called on each bar update event (incoming tick)
                              /// </summary>
                              protected override void OnBarUpdate()
                              {
                              myDataSeries.set(Typical)[0];
                              //double ap = (High[0] + Low[0] + Close[0]) / 3; //
                              double esa = EMA(myDataSeries, ChannelLength)[0];
                              double d = EMA(Math.Abs(myDataSeries - esa))[0];
                              double ci = (myDataSeries - esa) / (0.015 * d);
                              double tci = EMA(ci, AverageLength)[0];

                              double wt1 = tci;
                              double wt2 = SMA(wt1, 4)[0];



                              This is the code within the NinjaTrader.Indicator namespace and the Properties section in the code. I have a parade of errors that frankly don't make any sense to me since I diligently followed the instructions according to the NinjaTrader manual.

                              If someone over there at Customer SErvice can take the above code and plug it in their compilers, maybe someone can explain to me what the error codes are trying to tell me?

                              J.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by trilliantrader, 04-18-2024, 08:16 AM
                              5 responses
                              22 views
                              0 likes
                              Last Post trilliantrader  
                              Started by Davidtowleii, Today, 12:15 AM
                              0 responses
                              3 views
                              0 likes
                              Last Post Davidtowleii  
                              Started by guillembm, Yesterday, 11:25 AM
                              2 responses
                              9 views
                              0 likes
                              Last Post guillembm  
                              Started by junkone, 04-21-2024, 07:17 AM
                              9 responses
                              69 views
                              0 likes
                              Last Post jeronymite  
                              Started by mgco4you, Yesterday, 09:46 PM
                              1 response
                              13 views
                              0 likes
                              Last Post NinjaTrader_Manfred  
                              Working...
                              X