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

Clarification on how AddDataSeries works

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

    Clarification on how AddDataSeries works

    I'm making sure I'm understanding this properly, since the tutorial states that once AddDataSeries is executed, that becomes "1" in the array, with 1 minute ALWAYS the default with 0.

    So.... if I have this start to my Configure,

    " else if (State == State.Configure)
    {
    smaFast = EMA(Fast);
    smaSlow = EMA(Slow);
    smaLarge = EMA(Large);

    smaFast.Plots[0].Brush = Brushes.Orange;
    smaSlow.Plots[0].Brush = Brushes.Green;
    smaLarge.Plots[0].Brush = Brushes.White;
    //Pivots
    //AddDataSeries(Data.BarsPeriodType.Day, 1);
    // AddDataSeries(Data.BarsPeriodType.Minute, 30);
    //My own timeframes. BarsInProgress 1 is 5 minutes, 2 is 15, 0 is always default 1 minute???
    AddDataSeries(Data.BarsPeriodType.Minute, 5);
    AddDataSeries(Data.BarsPeriodType.Minute, 15);"


    .... does that mean that per the tutorial example, If i do this:
    "(SMA(20)[0] > SMA(BarsArray[1], 20)[0])" - this will check the if the latest default of 1 minute is greater than HARD coded 5 minute?

    ... Or - how I understand it, since the script has been working as expected, if I do not mention BarsArray, it will take whatever the value I set the strategy to run in, so if I run it on a 5 minute time frame, THAT's the DEFAULT value of [0].

    Doing so, the above code would simply check the sma of 5 minute, versus explicit request to 5 minutes? It mentions that the default of [0] is 1 minute, but I've been running my code, and all values are properly at 5 minutes, even if I have no mention of "BarsArray" anywhere - if I'm doing a single time frame - since I set the strategy to run and backtest on 5 minute time frame in the software.

    Can someone clarify please?

    #2
    To follow up my own question, as to why I'm asking this.

    I then tried an indicator that is available in the community here that marks lower low, higher highs, etc.

    I want to use a 5 minute data for everything, but I would like to use 15 minute data for this specific indicator.

    Doing this gives me the same result (5 minute is added only), but no faults - do I need to modify the indicator in some way to accept multi-frame? I thought this was a built-in feature of NT8


    //I declare previously
    private NinjaPriceAction Ninja;
    private NinjaPriceAction Ninja2;

    //Then I "think" I'm initializing two time frames in the State == State.Configure) area
    Ninja = NinjaPriceAction(BarsArray[1],3,50,15);
    Ninja2 = NinjaPriceAction(BarsArray[2],3,50,15);
    AddChartIndicator(Ninja);
    AddChartIndicator(Ninja2);





    Here is the indicator below:
    =====================
    trunkated to fit

    //This namespace holds Indicators in this folder and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.Indicators
    {
    public class NinjaPriceAction : Indicator
    {
    private int barsback;
    public double prevhigh;
    public double prevlow;
    public double curhigh;
    public double curlow;
    private double offset;
    private double curATR;
    private double toffset;
    private ATR myATR;
    private Swing mySwing;
    private double tOffset;
    private int myBarUp, myBarDown;

    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    Description = @"Labels the swing points";
    Name = "NinjaPriceAction";
    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;
    Strength = 3;
    TextOffset = 3;
    LookBack = 50;
    DTBStrength = 15;
    TextFont = new NinjaTrader.Gui.Tools.SimpleFont("Arial", 12);
    DBcolor = Brushes.Gold;
    DTcolor = Brushes.Gold;
    HHcolor = Brushes.Green;
    HLcolor = Brushes.Green;
    LLcolor = Brushes.Red;
    LHcolor = Brushes.Red;
    }
    else if (State == State.DataLoaded)
    {
    myATR = ATR(14);
    mySwing = Swing(Strength);
    tOffset = TextOffset * TickSize;
    }
    }

    protected override void OnBarUpdate()
    {

    if (CurrentBar < LookBack + 1) return;

    barsback = mySwing.SwingHighBar(0,2,LookBack);

    if (barsback == -1)
    return;

    prevhigh = mySwing.SwingHigh[barsback];

    barsback = mySwing.SwingHighBar(0,1,LookBack);

    if (barsback == -1)
    return;

    curhigh = mySwing.SwingHigh[barsback];

    curATR = myATR[barsback];
    offset = curATR * DTBStrength / 100;

    if (curhigh < prevhigh + offset && curhigh > prevhigh - offset && CurrentBar - barsback != myBarUp)
    {
    myBarUp = CurrentBar - barsback;
    Draw.Text(this, "DT"+CurrentBar, true, "DT", barsback, High[barsback] + tOffset, 0, DTcolor,
    TextFont, TextAlignment.Center, Brushes.Transparent, Brushes.Transparent, 0);
    }
    else if (curhigh > prevhigh && CurrentBar - barsback != myBarUp)
    {
    myBarUp = CurrentBar - barsback;
    Draw.Text(this, "HH"+CurrentBar, true, "HH", barsback, High[barsback] + tOffset, 0, HHcolor,
    TextFont, TextAlignment.Center, Brushes.Transparent, Brushes.Transparent, 0);
    }
    else if (CurrentBar - barsback != myBarUp)
    {
    myBarUp = CurrentBar - barsback;
    Draw.Text(this, "LH"+CurrentBar, true, "LH",barsback, High[barsback] + tOffset, 0, LHcolor,
    TextFont, TextAlignment.Center, Brushes.Transparent, Brushes.Transparent, 0);
    }


    barsback = mySwing.SwingLowBar(0,2,LookBack);

    if (barsback == -1)
    return;

    prevlow = mySwing.SwingLow[barsback];

    barsback = mySwing.SwingLowBar(0,1,LookBack);

    if (barsback == -1)
    return;

    curlow = mySwing.SwingLow[barsback];

    curATR = myATR[barsback];
    offset = curATR * DTBStrength / 100;


    if (curlow > prevlow - offset && curlow < prevlow + offset && CurrentBar - barsback != myBarDown)
    {
    myBarDown = CurrentBar - barsback;
    Draw.Text(this, "DB"+CurrentBar, true, "DB", barsback, Low[barsback] - tOffset, 0, DBcolor,
    TextFont, TextAlignment.Center, Brushes.Transparent, Brushes.Transparent, 0);
    }
    else if (curlow < prevlow && CurrentBar - barsback != myBarDown)
    {
    myBarDown = CurrentBar - barsback;
    Draw.Text(this, "LL"+CurrentBar, true, "LL", barsback, Low[barsback] - tOffset, 0, LLcolor,
    TextFont, TextAlignment.Center, Brushes.Transparent, Brushes.Transparent, 0);
    //Print(curlow + " Here it freaking is, at this bar: " + CurrentBar);
    }
    else if (CurrentBar - barsback != myBarDown)
    {
    myBarDown = CurrentBar - barsback;
    Draw.Text(this, "HL"+CurrentBar, true, "HL", barsback, Low[barsback] - tOffset, 0, HLcolor,
    TextFont, TextAlignment.Center, Brushes.Transparent, Brushes.Transparent, 0);
    }
    }

    #region Properties

    [Browsable(false)]
    [XmlIgnore]
    public double CurLow
    {
    get { Update(); return curlow; }
    }

    [Browsable(false)]
    [XmlIgnore]
    public double PreviousLow
    {
    get { Update(); return prevlow; }
    }

    [Browsable(false)]
    [XmlIgnore]
    public double CurHigh
    {
    get { Update(); return curhigh; }
    }

    [Browsable(false)]
    [XmlIgnore]
    public double PreviousHigh
    {
    get { Update(); return prevhigh; }
    }


    [NinjaScriptProperty]
    [Range(1, int.MaxValue)]
    [Display(Name="Strength", Description="Swing strength, number of bars", Order=1, GroupName="Parameters")]
    public int Strength
    { get; set; }

    [Range(0, int.MaxValue)]
    [Display(Name="TextOffset", Description="Number of ticks to offset text from high/low", Order=2, GroupName="Parameters")]
    public int TextOffset
    { get; set; }

    [NinjaScriptProperty]
    [Range(1, int.MaxValue)]
    [Display(Name="LookBack", Description="Number of bars ago to check", Order=3, GroupName="Parameters")]
    public int LookBack
    { get; set; }

    [NinjaScriptProperty]
    [Range(1, int.MaxValue)]
    [Display(Name="DTBStrength", Order=4, GroupName="Parameters")]
    public int DTBStrength
    { get; set; }

    [Display(Name = "Font, size, type, style",
    Description = "select font, style, size to display on chart",
    GroupName = "Text",
    Order = 1)]
    public Gui.Tools.SimpleFont TextFont
    { get; set; }

    [XmlIgnore]
    [Display(Name="HH Color", Description="(text) Higher High color", Order=2, GroupName="Text")]
    public Brush HHcolor
    { get; set; }

    [Browsable(false)]
    public string HHcolorSerializable
    {
    get { return Serialize.BrushToString(HHcolor); }
    set { HHcolor = Serialize.StringToBrush(value); }
    }

    [XmlIgnore]
    [Display(Name="HL Color", Description="(text) Higher Low color", Order=3, GroupName="Text")]
    public Brush HLcolor
    { get; set; }

    [Browsable(false)]
    public string HLcolorSerializable
    {
    get { return Serialize.BrushToString(HLcolor); }
    set { HLcolor = Serialize.StringToBrush(value); }
    }

    [XmlIgnore]
    [Display(Name="DT Color", Description="(text) Double Top color", Order=6, GroupName="Text")]
    public Brush DTcolor
    { get; set; }

    [Browsable(false)]
    public string DTcolorSerializable
    {
    get { return Serialize.BrushToString(DTcolor); }
    set { DTcolor = Serialize.StringToBrush(value); }
    }

    [XmlIgnore]
    [Display(Name="LL Color", Description="(text) Lower Low color", Order=4, GroupName="Text")]
    public Brush LLcolor
    { get; set; }

    [Browsable(false)]
    public string LLcolorSerializable
    {
    get { return Serialize.BrushToString(LLcolor); }
    set { LLcolor = Serialize.StringToBrush(value); }
    }

    [XmlIgnore]
    [Display(Name="LH Color", Description="(text) Lower High color", Order=5, GroupName="Text")]
    public Brush LHcolor
    { get; set; }

    [Browsable(false)]
    public string LHcolorSerializable
    {
    get { return Serialize.BrushToString(LHcolor); }
    set { LHcolor = Serialize.StringToBrush(value); }
    }

    [XmlIgnore]
    [Display(Name="DB Color", Description="(text) Double Bottom color", Order=7, GroupName="Text")]
    public Brush DBcolor
    { get; set; }

    [Browsable(false)]
    public string DBcolorSerializable
    {
    get { return Serialize.BrushToString(DBcolor); }
    set { DBcolor = Serialize.StringToBrush(value); }
    }
    #endregion



    }
    }

    #region NinjaScript generated code. Neither change nor remove.

    namespace NinjaTrader.NinjaScript.Indicators
    {
    public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
    {
    private NinjaPriceAction[] cacheNinjaPriceAction;
    public NinjaPriceAction NinjaPriceAction(int strength, int lookBack, int dTBStrength)
    {
    return NinjaPriceAction(Input, strength, lookBack, dTBStrength);
    }

    public NinjaPriceAction NinjaPriceAction(ISeries<double> input, int strength, int lookBack, int dTBStrength)
    {
    if (cacheNinjaPriceAction != null)
    for (int idx = 0; idx < cacheNinjaPriceAction.Length; idx++)
    if (cacheNinjaPriceAction[idx] != null && cacheNinjaPriceAction[idx].Strength == strength && cacheNinjaPriceAction[idx].LookBack == lookBack && cacheNinjaPriceAction[idx].DTBStrength == dTBStrength && cacheNinjaPriceAction[idx].EqualsInput(input))
    return cacheNinjaPriceAction[idx];
    return CacheIndicator<NinjaPriceAction>(new NinjaPriceAction(){ Strength = strength, LookBack = lookBack, DTBStrength = dTBStrength }, input, ref cacheNinjaPriceAction);
    }
    }
    }

    namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
    {
    public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
    {
    public Indicators.NinjaPriceAction NinjaPriceAction(int strength, int lookBack, int dTBStrength)
    {
    return indicator.NinjaPriceAction(Input, strength, lookBack, dTBStrength);
    }

    public Indicators.NinjaPriceAction NinjaPriceAction(ISeries<double> input , int strength, int lookBack, int dTBStrength)
    {
    return indicator.NinjaPriceAction(input, strength, lookBack, dTBStrength);
    }
    }
    }

    namespace NinjaTrader.NinjaScript.Strategies
    {
    public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
    {
    public Indicators.NinjaPriceAction NinjaPriceAction(int strength, int lookBack, int dTBStrength)
    {
    return indicator.NinjaPriceAction(Input, strength, lookBack, dTBStrength);
    }

    public Indicators.NinjaPriceAction NinjaPriceAction(ISeries<double> input , int strength, int lookBack, int dTBStrength)
    {
    return indicator.NinjaPriceAction(input, strength, lookBack, dTBStrength);
    }
    }
    }

    #endregion

    Comment


      #3
      Any help would be appreciated...

      I'm using the example provided in the BarrsArray help forum of NT8:

      if (SMA(20)[0] > SMA(BarsArray[1], 20)[0])
      EnterLong();

      When checking out the SMA indicator, it does indeed have the same syntax for strategies:

      public Indicators.SMA SMA(ISeries<double> input , int period)
      {
      return indicator.SMA(input, period);
      }

      Clearly, the double input refers to the BarsArray. The same thing happens in my indicator:

      public Indicators.NinjaPriceAction NinjaPriceAction(ISeries<double> input , int strength, int lookBack, int dTBStrength)
      {
      return indicator.NinjaPriceAction(input, strength, lookBack, dTBStrength);
      }


      Is it just that it fails to DRAW multiple time frames? both "AddChartIndicator" lines draw the 5 minutes, not the 5 and the 15. Would the code act correctly when checking for logical solutions, like in the example that checks for 5 versus 15 minute SMA? And it's only the charting that is broken?

      Comment


        #4
        Hello lmatiukas,

        AddDataSeries adds data series to the BarsArray collection. BarsInProgress is the index of the BarsArray collection in the order the series are added after the primary series. The primary series (meaning the data series used for the chart or the Data Series section when testing a strategy without a chart), will always be the first series added to the BarsArray collection and will be BarsInProgress 0 and BarsArray[0]. If the chart is a 1 day chart, BarsArray[0] and when BarsInProgress is 0 this will be that 1 day series.

        The first added series will be BarsArray[1] and when BarsInProgress is 1. If you add a 1 minute series with AddDataSeries, that becomes BarsArray[1]. If you call AddDataSeries() again that becomes BarsArray[2].

        OnBarUpdate will be run for every bar update for every series. So sometimes this will be for BarsInProgress 0, sometimes it will be BarsInProgress 1, just depending on when that series has a bar update.

        Where you have inquired:
        "... does that mean that per the tutorial example, If i do this:
        "(SMA(20)[0] > SMA(BarsArray[1], 20)[0])" - this will check the if the latest default of 1 minute is greater than HARD coded 5 minute?"

        With the first SMA call, whatever series happens to be currently updating OnBarUpdate() will be used as the input series for the first SMA call SMA(20)[0] as no input series is specified. This will change series as each series updates OnBarUpdate(). If BarsInProgress at that moment is BarsInProgress 0, then the SMA will be for BarsArray[0] or the primary series. If BarsInProgress is 1 at that moment, then the SMA will be for the added series with AddDataSeries(). It changes as BarsInProgress changes.

        With the second SMA call SMA(BarsArray[1], 20)[0], this specifies the input series to always be the added series with AddDataSeries no matter what BarsInProgress is updating OnBarUpdate(). This is how you get information from a specific series when any other series is updating.

        Below is a link to the help guide on AddDataSeries(), BarsArray, BarsInProgress, OnBarUpdate(), and Closes.







        As a heads up, AddChartIndicator() cannot be used with an indicator that is not using the primary series as the input series, as these must be tied to the chart bars. The chart bars are the primary series so to use AddChartIndicator() the indicator must be using the primary series. You can still use the values from an indicator using an added series as the input series in a strategy, it just won't be visually automatically added to the chart with AddChartIndicator().

        From the help guide:
        "An indicator being added via AddChartIndicator() cannot use any additional data series hosted by the calling strategy, but can only use the strategy's primary data series. If you wish to use a different data series for the indicator's input, you can add the series in the indicator itself and explicitly reference it in the indicator code (please make sure though the hosting strategy has the same AddDataSeries() call included as well)"


        And a link to an example of this.



        As a tip, to export a NinjaTrader 8 NinjaScript so this can be shared and imported by the recipient, and to keep your forum posts short, do the following:
        1. Click Tools -> Export -> NinjaScript...
        2. Click the 'add' link -> check the box(es) for the script(s) and reference(s) you want to include
        3. Click the 'Export' button
        4. Enter a unique name for the file in the value for 'File name:'
        5. Choose a save location -> click Save
        6. Click OK to clear the export location message
        By default your exported file will be in the following location:
        • (My) Documents/NinjaTrader 8/bin/Custom/ExportNinjaScript/<export_file_name.zip>
        Below is a link to the help guide on Exporting NinjaScripts.
        http://ninjatrader.com/support/helpG...-us/export.htm
        Chelsea B.NinjaTrader Customer Service

        Comment


          #5
          got it!

          So basically the code will work as intended, it will simply not draw two different time frames on the chart.

          I was testing to see IF the code would work, by expecting two drawings, but this way works for me as well.

          Comment


            #6
            Hello lmatiukas,

            That is correct. Adding a series with AddDataSeries add the series internally to the script, and does not visually add the series to the chart. All drawing objects and plots will by synchronized with the primary series.
            Chelsea B.NinjaTrader Customer Service

            Comment

            Latest Posts

            Collapse

            Topics Statistics Last Post
            Started by Kaledus, Today, 01:29 PM
            3 responses
            9 views
            0 likes
            Last Post NinjaTrader_Jesse  
            Started by frankthearm, Yesterday, 09:08 AM
            14 responses
            47 views
            0 likes
            Last Post NinjaTrader_Clayton  
            Started by gentlebenthebear, Today, 01:30 AM
            2 responses
            13 views
            0 likes
            Last Post gentlebenthebear  
            Started by PaulMohn, Today, 12:36 PM
            2 responses
            17 views
            0 likes
            Last Post PaulMohn  
            Started by Conceptzx, 10-11-2022, 06:38 AM
            2 responses
            56 views
            0 likes
            Last Post PhillT
            by PhillT
             
            Working...
            X