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

MTF + Swing + Draw.Ray + CrossAbove

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

    MTF + Swing + Draw.Ray + CrossAbove



    Hi Everyone,

    We have found a great topic to be discussed : Rays from swing points in a MTF strategy.

    The main idea is to define the 2 (or 3 last) Rays from the 3 (or 4) last swingpoints,
    (High rays AND Low rays, unlike the Trendlines indicator which plots only one or the other),
    Then these last rays would be Crossed or not, and be used for comparison conditions.
    (let's keep in mind that the sample is meant to be applied on any primary series, that is why nothing is inside if (BarsInProgress == 0))

    Instead of adapting the Trendlines indicator wich includes alerts and plots only one side, and overall seems too complex for our use,
    We decided to copy and adapt the syntax from this thread :
    https://ninjatrader.com/support/foru...highs-and-lows
    Because we only need the last few swing points, without the full TrendRay and TrendQueue classes, we defined one by one those points.

    The attached sample illustrates how to define these last swing points and create rays from them.
    It is a very close variation of the thread's piece of code.


    Now begins the interesting part with just a few of many interogations :

    -Would there be a shorter/more efficient way to write this "high and low points definition" ? (we don't need more points)
    Is there a part from this code that would be better placed somewhere else in the script ?

    -Even if we are in if (BarsInProgress == 1) and the dots show a synchronization between the series, the rays seen from higher chart series than [0] and [1] DO NOT synch.
    We can see all that in the attached picture. (the swing indic is applied on the chart to see the last swing points)
    Should we not see all rays (regardless of which primary it's applied on) passing by the swing points (squares) of series[1] ?
    Why not in this case ?

    -Also, when trying to instantiate this newly created ray S1UpTrendRay1 (line 121 and line 129), we get the cs1503 error.
    https://ninjatrader.com/support/help...t8/?cs1503.htm. This was not enough hint for me to adapt to a drawing object.
    What exactly should we do with S1UpTrendRay1 drawing object in order to make it comparable and compile the script ? (like tried with && (CrossAbove(Closes[1], S1UpTrendRay1, 1) == true ) )


    Would anyone care to study swing points rays with us ?
    These are 3 topics which could have their own thread. Should we divide them into 3 threads ?
    Attached Files
    Last edited by Amedeus; 07-10-2021, 04:30 PM.

    #2
    Hey again,

    this is only about the 3rd point :

    if we are attempting to evaluate an eventual cross of a Draw.Ray object, is there no other later choice than use OnRender() method in a similar way than as it's used in the Trendline indicator ?
    implying AddPlots and other references to chart events ?

    if we still are attempting to evaluate an eventual cross of a Draw.Ray object, is there no other prior choice than create a Series<T> like suggested here ?https://ninjatrader.com/support/foru...29#post1134629

    are private class TrendRay and private class TrendQueue : Queue<TrendRay>, from the Trendline indicator, BOTH custom Series<T> ?

    if a custom a Series<T> is created to store the numerical values for each bar, of where a virtual ray would be (joining swing points) , could the use of OnRender() and other chart event or plots references be avoided ?
    Such a custom Series would just be a library of double values(?). Those double values, if plotted, would align perfectly on each bar with a Draw.Ray object whose DashStyle were to be Dot, right?
    Would such a custom series not be the simplest way, in terms of machine calculation, to evaluate a cross (of the virtual ray joining any chosen swing points)



    I'am trying to be very careful with the choice of words, if a question is asked somehow wrongly, it means a more major aspect of ninjascript or coding is not percieved well enough already.
    Last edited by Amedeus; 07-11-2021, 10:17 AM.

    Comment


      #3
      Hello Amedeus,

      "Would there be a shorter/more efficient way to write this "high and low points definition" ?"

      The swings are in the plots which are retrieved with barsAgo values. There wouldn't be a more efficient way (or another way) of getting those plot values.

      "Even if we are in if (BarsInProgress == 1) and the dots show a synchronization between the series, the rays seen from higher chart series than [0] and [1] DO NOT synch."

      Drawing objects plot on the primary series. Whatever bar or price is chosen, would have to be in relation to the primary series only.

      "Also, when trying to instantiate this newly created ray S1UpTrendRay1 (line 121 and line 129), we get the cs1503 error."

      What is the line of code causing the error? What is the full error message? Is S1UpTrendRay1 a series?

      A cross of a drawing object should be detected in OnBarUpdate().


      "if we still are attempting to evaluate an eventual cross of a Draw.Ray object, is there no other prior choice than create a Series<T> like suggested here ?"

      That depends, what is crossing the ray? The Close is a series? Is this what is crossing the ray?

      Plots would be synchronized with the primary series unless explicitly set to another series, however anything visual on the chart is still in relation to the primary series.
      Chelsea B.NinjaTrader Customer Service

      Comment


        #4

        Hey Chelsea, thank you very much,

        "The swings are in the plots which are retrieved with barsAgo values. "

        Does this implies that any found swing point - from a swing indicator applied to Series[1] for example - would have a different X anchor if applied on another primary Price Series ?
        Because the found swing point is obtained from a visual plot ?
        Basically a Swing indicator applied to BarsArray[1] in the script, if applied to any other Primary would calculate the primary swing points anyway ? because of its (Swing) nature to calculate from plots ?
        For example : if our sample is applied to Series[2], Swing1High1 double will have the right Y value, but cannot have its original X Bar (from Series[1]) position ?
        This should lead to conclude that it is not possible to use any Swing calculation from a secondary series (except for Y values). Is this right ?




        "What is the line of code causing the error? What is the full error message? Is S1UpTrendRay1 a series?"

        This is the initial ray
        Draw.Ray(this, "S1UpTrendRay1", true, Swing1HighBarsAgo2, Swing1High2, Swing1HighBarsAgo1, Swing1High1, Brushes.Black, DashStyleHelper.Dash, 2);

        This is the line that caused all the following compiling errors :
        (CrossAbove(Closes[1], S1UpTrendRay1, 1) == true )

        This is the 1st compiling error
        The name 'S1UpTrendRay1' does not exist in the current context, https://ninjatrader.com/support/help...t8/?cs0103.htm
        We understood from the message that S1UpTrendRay1 needs to be declared (instantiated?)

        This is how we tried to "instantiate" S1UpTrendRay1 in order for it to be crossable (or just compilable at 1st).
        Ray S1UpTrendRay1 = Draw.Ray(this, "S1UpTrendRay1", true, Swing1HighBarsAgo2, Swing1High2, Swing1HighBarsAgo1, Swing1High1, Brushes.Black, DashStyleHelper.Dash, 2);

        the compiling error message then became :
        The best overloaded method match for 'NinjaTrader.NinjaScript.NinjaScriptBase.CrossAbov e(NinjaTrader.NinjaScript.ISeries<double>, NinjaTrader.NinjaScript.ISeries<double>, int)' has some invalid arguments
        Argument 2 : Cannot implicitly convert type 'NinjaTrader.NinjaScript.DrawingTools.Ray' to 'NinjaTrader.NinjaScript.ISeries<double>'

        S1UpTrendRay1 is just a Draw object for now, not a Series.
        A Draw object that would have been compared against Closes[1], very likely also moving averages or other indicators (not necessarily plotted at all).
        S1UpTrendRay1 would have siblings in the other secondary series, Swings and comparisons stay within their own series though : no intend of comparing between series.



        "however anything visual on the chart is still in relation to the primary series."
        Yes, this is what i believed to understand, and why I'd lean to use something like Paul's YAxisProjectionOfLine, but it also is derived from a Plot/Draw object.
        Or this is also why a series, with doubles who would be projections of a given slope from 2 given swing points, would be a nice alternative regarding avoiding "anything visual".


        "Plots would be synchronized with the primary series unless explicitly set to another series"
        If this applies to the Swing indicator, it's been set as follow in DataLoaded:
        Swing1 = Swing(Closes[1], 7);
        if this is not "explicitly set to another series", how could we make Swing1High1 from the following line to be well defined (X,Y) point regardless of the primary ?
        int Swing1HighBarsAgo1 = Swing1.SwingHighBar(0, 1, 250); if(Swing1HighBarsAgo1 < 0 || CurrentBars[1] <= Swing1HighBarsAgo1) return; double Swing1High1 = Swing1.SwingHigh[Swing1HighBarsAgo1];

        Comment


          #5
          Hello Amedeus,

          The errors will have a line number and specifics. You can click on a compile error and hold Ctrl + c to copy the error, and Ctrl + v to paste this in a reply. Same with the Log tab of the Control Center.

          You can also take a screenshot.
          To send a screenshot with Windows 7 or newer I would recommend using the Windows Snipping Tool.
          Click here for instructions

          Alternatively to send a screenshot press Alt + PRINT SCREEN to take a screenshot of the selected window. Then go to Start--> Accessories--> Paint, and press CTRL + V to paste the image. Lastly, save as a jpeg file and send the file as an attachment.
          Click here for detailed instruction

          So the line of code in question is:
          if CrossAbove(Closes[1], S1UpTrendRay1, 1) == true)

          S1UpTrendRay1 is not series or a double. Its a ray. This cannot be used with CrossAbove or CrossBelow.

          You can supply a series and a series, or a series and a double. You cannot supply a drawing object.

          CrossAbove(ISeries<double> series1, ISeries<double > series2, int lookBackPeriod)
          CrossAbove(ISeries<double> series1, double value, int lookBackPeriod)


          Below is a link to the help guide on CrossAbove().
          https://ninjatrader.com/support/help...crossabove.htm


          Detecting something crossing a ray would require custom code. This was suggested in Post #3.
          https://ninjatrader.com/support/foru...663#post828663


          "if this is not "explicitly set to another series", how could we make Swing1High1 from the following line to be well defined (X,Y) point regardless of the primary ?"

          For a chart, the primary series is in control of the slots on the chart. If it is important that the indicator has to be added with AddChartIndicator(), whatever series used for that indicator should be the primary series.

          "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)"


          Custom rendering this in a custom version of the indicator by adding the secondary series directly to the indicator (and strategy) with AddDataSeries() then attempting to estimate distances for that secondary series in OnRender() may be possible but would be extremely complex.

          It might be easier to just add a second primary series to the data series window, and manually add the indicator to that input series.

          That could be saved in a chart template.
          Last edited by NinjaTrader_ChelseaB; 07-12-2021, 10:56 AM.
          Chelsea B.NinjaTrader Customer Service

          Comment


            #6

            Hey Chelsea, thank you very much,

            So there is no work around if someone wants to apply a MTF with a Swing calculation : it has to be applied on a primary of the same period as the Swing input...
            I assume this goes for MIN and MAX too.

            Eventually, if this someone wants to have a look at this same MTF from another scale using the value from an indicator calculating BarsAgo of one specific price series period,
            he/she could overlay the desired price series with the one of the Swing, like you just suggested at the end.
            This trick would limit the stretch in abilities of the chart display, we'll try to avoid this.

            Another trick, to have a look at this same MTF from another scale, would be to just very sadly give up the idea of a MTF that can be applied on all scales. Apply it only on the dataseries required by the AddChartIndicator.
            And draw IsGlobal arrows or triangles at the exact entry coordinates. We wanted to avoid the addition of such Draw objects, but it looks to be the best way now...
            We publish here now the syntax of such a condition :
            if ( Position.MarketPosition != MarketPosition.Flat && BarsSinceEntryExecution(1,"",0) == 0 )
            { Draw.TriangleUp(this, @"PositionEntryPoint" + Convert.ToString(CurrentBars[0]), true, 0, Y, true , ""); }
            In this sentence, Y could be referenced as the Y value of the EnterLimit order,an indicator most likely, maybe a Draw object.
            Would you have a clue of a syntax directly referencing the Entry price instead of the Y value of the indicator/drawing at the time ?


            Now that this structural aspect has been "solved", We'll come back soon regarding the slope that we were originally trying to create.

            Comment


              #7
              Hello Amedeus,

              For calculations you can use a secondary series. This only applies to visual purposes for rendering on a chart, not for calculations used internally in the script that are not rendered. The chart has visual bars on it. Those visual bars control the slots. If you are not concerned with visually rending objects then none of this would apply.
              MIN and MAX return the lowest and highest value for the supplied series, and yes they work fine for secondary series. MIN and MAX are not plotted indicators and are not rendered.

              Unfortunately, I am not understanding your issue or your workaround. Can you use less words to specifically state what is specifically not working as you expect?

              Where you mention: "Would you have a clue of a syntax directly referencing the Entry price instead of the Y value of the indicator/drawing at the time ?"

              By "Entry price" are you asking for the <Order>.AverageFillPrice?
              https://ninjatrader.com/support/help.../nt8/order.htm

              Are you asking how to find the y intercept along a line?
              Last edited by NinjaTrader_ChelseaB; 07-13-2021, 07:56 AM.
              Chelsea B.NinjaTrader Customer Service

              Comment


                #8

                Hey Chelsea, thanks a lot,

                This should be relatively quick and easy, so Ill'start with TriangleUp and do the "workaround" reply just after (relatively quick too, no worries).

                let's say we want a TriangleUp on the one exact spot of the entry marker on the chart.
                we would have an EnterLongLimit marker and then a TriangleUp when the condition is met :

                if (CrossAbove(Closes[1], Swing1High1) == true )
                {
                EnterLongLimit(Convert.ToInt32(DefaultQuantity), KC1.Midline[0], "");
                if ( Position.MarketPosition != MarketPosition.Flat && BarsSinceEntryExecution(1,"",0) == 0 )
                { Draw.TriangleUp(this, @"PositionEntryPoint" + Convert.ToString(CurrentBars[0]), true, 0, KC1.Midline[0], true , ""); }
                }

                But the strategy enters a little above or below the indicator for some reason. See in the attached picture : triangles and markers are not exactly overlaying one another.

                **

                this allows us to have an accurate X coordinate :
                if ( Position.MarketPosition != MarketPosition.Flat && BarsSinceEntryExecution(1,"",0) == 0 )

                And I was hoping to have a correct Y coordinate via the "double y" parameter :
                { Draw.TriangleUp(this, @"PositionEntryPoint" + Convert.ToString(CurrentBars[0]), true, 0, double y, true , ""); }
                That's why the question about the fill price.
                It is indeed a fill price reference that I was asking. Not an average though.

                **

                when inserting <Order>.AverageFillPrice in that spot, prompt says :
                An object reference is required for the nonstatic field, method, or property 'NinjaTrader.Cbi.Order.AverageFillPrice.get'

                I then tried with execution.Price, appeared the followin compile error :
                The name 'identifier' does not exist in the current context

                I'll be back with the simply put "workaround" thing.
                Attached Files
                Last edited by Amedeus; 07-13-2021, 10:33 AM.

                Comment


                  #9

                  Hey Chelsea,

                  The strategy must be able to be overlooked on any frame. (from 1 tick to 10K tick period or whatever)
                  The backtesting can be done on one frame only.
                  The entries and exits must be checkable on any frame.
                  The strategy's calculations will consider multiple indicators of multiple frames.
                  There will not be calculations between frames (Indic1 vs Indic2, or Closes[1] vs Indic2, that won't happen).

                  The visuals are not important at all. (I actually rather have the slope made of doubles, than the visible Draw.Object)
                  The strategy must be as simple as possible, structure wise and calculation wise, and some of the previous principles kinda favor this allready.

                  If the strategy were to be ran on a naked chart (whatever period), we'd only see the execution markers.
                  Excluding all conditions from beeing placed in BarsInProgress[0] was a way of not considering the primary.

                  **

                  If indeed the strategy can call Swing1High1 because AddDataSeries1 = Primary0, and cannot call Swing2High1 because AddDataSeries2 != Primary0, (Swing2High1 is the last high Swing of AddDataSeries2)
                  then the strategy cannot be applied on a chart dataseries other than the Swing input.
                  Is this correct ?

                  If the strategy is applied on a 100K tick chart, can it work with a Swing whose input is AddDataSeries(Data.BarsPeriodType.Tick, 90) ?

                  We dont care about the visuals, we are just interested in where the swing points are, in order to make slope that will be crossed or not.
                  The slope itself as a visual thing, we DO NOT care.
                  There will be no Addplots in this thing. Lightest the better.
                  (This is also why we instantly discard the excessive use of OnRender() previously for example. Even if we don't really tried to understand it in depth, it is plot related)
                  The tradability, backtestability, we DO care.

                  If the strategy can ask (Swing2 = Swing(Closes[2], 7) to tell where Swing2High1 is, then allright.
                  Last edited by Amedeus; 07-13-2021, 10:53 AM.

                  Comment


                    #10
                    Hello Amedeus,

                    A specific order is filling at an unexpected price?

                    An indicator is producing an unexpected value?
                    Chelsea B.NinjaTrader Customer Service

                    Comment


                      #11
                      Hey Chelsea, thanks,

                      Yes a specific order is filling at an unexpected price.
                      Would you have a clue as of why my order is filling at un enexpected price ? and what we can do about it ? either to the strategy or the expectation.


                      "An indicator is producing an unexpected value?"
                      Regarding the swing indicator, I'am not really in a state of expecting something, but more in a testing state with intend of forming later good expectations.

                      Were the followings not simple questions as asked ? :

                      If the strategy is applied on a 100K tick chart, can it work with a Swing whose input is AddDataSeries(Data.BarsPeriodType.Tick, 90) ?
                      Can the strategy ask (Swing2 = Swing(Closes[2], 7) to tell where Swing2High1 is ?
                      then the strategy cannot be applied on a chart dataseries other than the Swing input ?

                      Now I got one more :
                      MIN and MAX are not plotted indicators but Swing is ?

                      Was it possible to present what the workaround consists in, without the simple conditions mentioned last post ?
                      Last edited by Amedeus; 07-13-2021, 12:18 PM.

                      Comment


                        #12
                        Hello Amedeus,

                        Ok, an order is filling at an unexpected price. Is the script using 1 tick intra-bar granularity for accurate order fills? Is this real-time order historical or being compared between the two?

                        If the strategy is applied on a 100K tick chart, can it work with a Swing whose input is AddDataSeries(Data.BarsPeriodType.Tick, 90) ?
                        An indicator can use a secondary series for the input series (but cannot be added with AddChartIndicator()). An indicator can directly add a secondary series for a calculations (and can be added to a chart with AddChartIndicator()).
                        Can the strategy ask (Swing2 = Swing(Closes[2], 7) to tell where Swing2High1 is ?
                        This would be comparing to an indicator instance and not a specific plot or plot value. If Swing2 is an indicator instance they can be compared. Swing2High1 is a variable. Are you asking how to print the value of a variable?
                        Are you asking how to find the previous swing high?
                        https://ninjatrader.com/support/foru...12#post1085012

                        then the strategy cannot be applied on a chart dataseries other than the Swing input ?
                        The strategy can be applied to any data series. If you want to add the indicator to the chart with AddChartIndicator() the primary series should be the chart series and should be the series of the indicator.

                        MIN and MAX are not plotted indicators but Swing is ?
                        Correct. Try adding MIN directly to a chart from the chart indicators menu. Try adding the Swing indicator to a chart.
                        Chelsea B.NinjaTrader Customer Service

                        Comment


                          #13
                          Hey Chelsea, thanks,


                          "Is the script using 1 tick intra-bar granularity for accurate order fills? Is this real-time order historical or being compared between the two?"
                          No intra-bar granularity, but there is no need here : the chart is of the same dataseries than BarsInProgress1 (where the order is in the script).
                          I'd say it is compared between the two : applied on a real time chart with one month worth of data.
                          There is a better picture attached to illustrate, with the indicator plot this time.


                          "An indicator can use a secondary series for the input series (but cannot be added with AddChartIndicator()).
                          An indicator can directly add a secondary series for a calculations (and can be added to a chart with AddChartIndicator())."
                          " If you want to add the indicator to the chart with AddChartIndicator() the primary series should be the chart series and should be the series of the indicator."
                          Nowhere in the sample is written AddChartIndicator(), why does it sound like it has been ? or could have been without my consent somehow.
                          We are avoiding chart referneces and plot references.

                          If we add the corresponding dataseries to a copy of the Swing indicator, like suggested post#5, the strategy would be able to find Swing2High1, the variable.
                          If yes, the strategy should also be able to find Swing2High1 or Swing1High1 if applied on any frame. Correct ?
                          If so, I'll certainly look into it once we are able to put an arrow on an execution marker, and draw a proper slope from 2 swing points with no trick in the input dataseries.


                          " Try adding MIN directly to a chart from the chart indicators menu. Try adding the Swing indicator to a chart."
                          I did allready, a few times even. I provide attached a recent picture of what that gives us.

                          Here are the lines from their code :
                          AddPlot(Brushes.DarkCyan, NinjaTrader.Custom.Resource.NinjaScriptIndicatorNa meMAX);
                          AddPlot(new Stroke(Brushes.DarkCyan, 2), PlotStyle.Dot, NinjaTrader.Custom.Resource.SwingHigh);
                          AddPlot(new Stroke(Brushes.Goldenrod, 2), PlotStyle.Dot, NinjaTrader.Custom.Resource.SwingLow);
                          If plotted means having "A collection of Plot objects", we can see in the code than MAX only has one plot, not a collection, that's what makes the difference ?
                          On the chart indicator menu however, we can't see that, can we ? we can choose dashstyles and all... see the attached picture. They look plotted.
                          Attached Files

                          Comment


                            #14
                            Hey Chelsea and everyone,

                            Unless I'm missing something, this seems to work well and as expected.

                            Here attached is the sample of the strategy detecting crossaboves of the projections of the last high swings rays.
                            And a picture of those events.

                            Absolutely wonderful what NS can do...
                            Attached Files
                            Last edited by Amedeus; 07-14-2021, 07:52 AM.

                            Comment


                              #15
                              Hey Chelsea

                              Still with our swingSlope sample,
                              this (attachments) is where we're at, regarding the TriangleUps overlaying the price marker :

                              in order to use Order or Execution references like suggested post#7,
                              we added protected override void OnOrderUpdate() and protected override void OnExecutionUpdate()

                              now we can see where execution.Price and limitPrice are.

                              is this normal that triangles are all 1 bar before ?
                              would one good print tell us why ?

                              the goal here anyway is to have one triangle over each long entry.
                              Attached Files
                              Last edited by Amedeus; 07-14-2021, 11:02 AM.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by cre8able, Today, 03:20 PM
                              0 responses
                              5 views
                              0 likes
                              Last Post cre8able  
                              Started by Fran888, 02-16-2024, 10:48 AM
                              3 responses
                              47 views
                              0 likes
                              Last Post Sam2515
                              by Sam2515
                               
                              Started by martin70, 03-24-2023, 04:58 AM
                              15 responses
                              114 views
                              0 likes
                              Last Post NinjaTrader_Jesse  
                              Started by The_Sec, Today, 02:29 PM
                              1 response
                              7 views
                              0 likes
                              Last Post NinjaTrader_Jesse  
                              Started by jeronymite, 04-12-2024, 04:26 PM
                              2 responses
                              31 views
                              0 likes
                              Last Post NinjaTrader_BrandonH  
                              Working...
                              X