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

Last ten bars all closed below MA

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

    Last ten bars all closed below MA

    I am trying to come up with the elegant code to test if recent number of bars all closed below Moving Average. Not sure how do I structure a loop to achieve just that.

    Here's what I currently have

    Code:
                if (
                       Close[9] < EMA20[9]
                    && Close[8] < EMA20[8]
                    && Close[7] < EMA20[7]
                    && Close[6] < EMA20[6]
                    && Close[5] < EMA20[5]
                    && Close[4] < EMA20[4]
                    && Close[3] < EMA20[3]
                    && Close[2] < EMA20[2]
                    && Close[1] < EMA20[1]
                   )​
    xcoder
    NinjaTrader Ecosystem Vendor - EMS

    #2
    Try this,

    Code:
    public bool IsSeriesBelow(ISeries<double> s1, ISeries<double> s2, int startBarsAgo, int lookback)
    {
        int found = 0;
    
        for (int barsAgo = startBarsAgo, cnt = 0; cnt < lookback; ++cnt, ++barsAgo)
            if (s1[barsAgo] < s2[barsAgo])
                ++found;
    
        return found > 0 && found == lookback;
    }
    To replace the exact code in OP's question, use like this,

    Code:
    if (IsSeriesBelow(Close, EMA20, 1, 9))
        Print("All elements below");
    To test last 10 bars, use like this,

    Code:
    if (IsSeriesBelow(Close, EMA20, 0, 10))
        Print("Last 10 elements are all below");
    -=o=-

    startBarsAgo is the first bars ago index to start, which is usually 0.
    This argument value should never be negative.

    lookback is count of bars to check, and should always be > 0.
    (That's why found > 0 is part of the return statement, it helps
    guard against lookback being 0, which will probably be a
    common mistake, and should probably be explicitly made
    invalid.)

    -=o=-

    How to do that?
    How to make lookback equal to 0 'explicitly invalid'?

    You could add some guard code at the top for startBarsAgo < 0
    and lookback < 1 and throw an ArgumentException if these
    guard checks fail -- which I'll leave as an exercise for the reader.

    With these guard checks, you wouldn't need the found > 0 in the
    return statement.

    Enjoy!



    PS: Caveat emptor -- this code was invented as I typed it, and
    has not been tested.

    PPS: I like this function, and will probably add it to my library. The
    analogous IsSeriesAbove should be an easy exercise for the
    reader.



    Comment


      #3
      Thank you, Dave.

      I was actually thinking of just creating a function like your first example but I suspected there must be some built in tool like "IsSeriesBelow" you've introduced me to. Somehow I missed it skimming thought documentation. Just starting out writing code for trading system and I have one rhetorical and one technical questions.

      1. I have tried many things so far to create a universal price action based system that would work on any timeframe, instrument and market conditions. So far, everything I wrote was inconsistent at best making money some days and loosing bunch later and making it back again. I test them all on ES last 3 months of data. The main obstacle is that I have to close futures positions overnight and there only one day to make it. Well maybe I could reopen everything next day but then I suspect my commissions would be though the roof.

      So the question is "is such system even possible?". How do you approach the business logic to create a system. Only focusing on specific instrument and timeframe? Or maybe only run it during certain market hours?

      2. Therefore the technical question. How do you get time programmatically without bringing in 3rd party indicators? I've used bar count that I liked but I don't favor the idea of having my code dependency like that. I'd rather have it all packed in and not relying on user installing extra stuff. Plus counting bars since open would be different for different timeframes. Maybe there is a better way? Let's say I want to only run my system for the first two hours after regular market opened, how do I get that window?

      And finally, I understand that guarding system itself against looking back to bars that haven't been loaded yet is already set like this ...

      Code:
              protected override void OnBarUpdate()
              {
                  if (BarsInProgress != 0)
                      return;
      
                  if (CurrentBars[0] < 11)
                      return;​
      of if we're guarding against user entering negative value that is also protected when we create input variable by setting min value. Maybe I've missed the point?
      xcoder
      NinjaTrader Ecosystem Vendor - EMS

      Comment


        #4
        Originally posted by Xcoder View Post
        1. I have tried many things so far to create a universal price action based system that would work on any timeframe, instrument and market conditions.
        So the question is "is such system even possible?". How do you approach the business logic to create a system. Only focusing on specific instrument and timeframe? Or maybe only run it during certain market hours?
        You're asking me?
        Like, I would know?

        Lol, I would venture to say the holy grail you seek doesn't
        exist. Traders who specialize in CL may not give a rat's
        patooty about GC, and vice versa -- markets have distinct
        personalities based upon the underlying commodity being
        traded and the personalities of the people/organizations
        doing the trading. My point is, the description you used,
        with words like 'universal' and 'any instrument' -- well,
        good luck with that.

        Ask 10 different people and you'd probably get 10 different
        answers. Ask 10 different very successful traders and you'd
        probably find 10 different ways of trading. And, I would surmise,
        if you find 10 successful traders using the same system, they will
        all be using it differently enough that they all didn't take the same
        trades.

        In my opinion, you should specialize in one or two instruments,
        develop or learn a manual way of trading those instruments,
        and only after you have manually traded them profitably, only
        then should you try to automate your manual strategy.

        Not all manual strategies are automatable -- but most are,
        since they all tend to boil down to some kind of pattern
        recognition across one or more charts, using one or more
        time frames.

        Just my 2˘.



        EDIT:
        I mean, I know you said 'price action', but price action is the
        the result of traders making trades -- and traders make trades
        because they're reacting to something -- whether it be news,
        divergences, price movement -- there are hundreds of different
        variables, combined in hundreds of different ways. The auction
        is where the chaos of thousands of buyers and sellers come to
        meet -- but you know all this -- my point is, some patterns
        may stand out on some days, but not others, it depends on
        all those hundreds of variables ... so you have to learn when
        not to trade, which I think is just as important as knowing when
        to trade.

        You need to build a good trading plan -- all this means is that
        you have written down everything you need to do in order to
        be successful -- trading plans could be as simple as 3x5
        cards, or complex spreadsheets, or sticky notes on your
        monitor, or laminated rule sheets, or whatever -- it's simply
        a matter of what your mind needs -- you've got to obey your
        trading rules -- a trading plan (in whatever form) creates
        guard rails to mentally keep you in your lane.
        Last edited by bltdavid; 11-04-2023, 02:12 PM.

        Comment


          #5
          Originally posted by Xcoder View Post
          2. Therefore the technical question. How do you get time programmatically without bringing in 3rd party indicators? I've used bar count that I liked but I don't favor the idea of having my code dependency like that. I'd rather have it all packed in and not relying on user installing extra stuff. Plus counting bars since open would be different for different timeframes. Maybe there is a better way? Let's say I want to only run my system for the first two hours after regular market opened, how do I get that window?
          Are you just asking for how to setup start and stop
          times for a strategy?

          Check out my code in the post here.

          Comment


            #6
            Originally posted by Xcoder View Post
            And finally, I understand that guarding system itself against looking back to bars that haven't been loaded yet is already set like this ...

            Code:
            protected override void OnBarUpdate()
            {
            if (BarsInProgress != 0)
            return;
            
            if (CurrentBars[0] < 11)
            return;​
            of if we're guarding against user entering negative value that is also protected when we create input variable by setting min value. Maybe I've missed the point?
            The term 'guard code' is a generic term I use to describe the
            code checks you do to protect your code from running under
            conditions which would cause errors. Guard code can occur
            anywhere in your code -- top, middle, bottom. Many times
            you find guard code all over the place and you may not even
            realize that that code is guarding something.

            The classic 'guard code' example is making sure you don't divide
            by zero,

            Code:
            if (b != 0)
                c = a / b;
            else
                Print("Houston, we have a problem");
            Guard code helps make your code robust.

            The examples you show are common guard code situations
            typically needed at the top of OnBarUpdate.

            For methods with arguments, many times you see guard
            code added to check the validity of the argument values.

            Here is IsSeriesBelow with fully developed guard code for
            all 4 arguments -- yikes, I agree, it's a bit much,

            Code:
            public bool IsSeriesBelow(ISeries<double> s1, ISeries<double> s2, int startBarsAgo, int lookback)
            {
                if (s1 == null || s2 == null)
                    throw new ArgumentException("Series cannot be null");
            
                if (startBarsAgo < 0)
                    throw new ArgumentException("startBarsAgo cannot be negative");
            
                if (lookback < 1)
                    throw new ArgumentException("lookback cannot be zero or negative");
            
            ​    if (CurrentBar < startBarsAgo+lookback)
                    throw new ArgumentException("Not enough bars");
            
                int found = 0;
            
                for (int barsAgo = startBarsAgo, cnt = 0; cnt < lookback; ++cnt, ++barsAgo)
                    if (s1[barsAgo] < s2[barsAgo])
                        ++found;
            
                return found == lookback;
            }​
            See how the guard code throws an exception if the arguments are invalid?

            This much guard code is probably way overkill, esp for a personal library,
            but can be more or less common in professional or commercial coding
            environments.

            How you use guard code is up to you, it really depends upon the intended
            audience and how much 'hand-holding' you feel is needed.

            For my personal library, I sometimes check for bad arguments, but I don't
            check every thing possible, and I don't do it for every method, lower level
            methods typically have no guards at all, since it's expected that the calling
            code some where above it has already sanitized the arguments.

            For this method, my standard practice is to drop all the guard code except
            for the check for lookback < 1, because the rest of the guards are
            checking things I simply never do, so they are a bit useless for my habits.

            Therefore, I tend to use this approach,

            Code:
            public bool IsSeriesBelow(ISeries<double> s1, ISeries<double> s2, int startBarsAgo, int lookback)
            {
                if (lookback < 1)
                    throw new ArgumentException("lookback cannot be zero or negative");
            
                int found = 0;
            
                for (int barsAgo = startBarsAgo, cnt = 0; cnt < lookback; ++cnt, ++barsAgo)
                    if (s1[barsAgo] < s2[barsAgo])
                        ++found;
            
                return found == lookback;
            }​
            That means, in the return, if found is zero, it will never be equal to lookback,
            and the method returns false, as intended. How do I know? Because there
            is guard code there at the top, which is crucial to how the return statement
            is always guaranteed to work even when found is zero.

            Remember, guard code can occur anywhere, at any time. You add it whenever
            and wherever it is prudent, to protect the operation of the code that will soon be
            executed. You commonly see it at the top of methods, and it's often used to
            validate arguments or other variables before the method starts doing it's thing.

            Guard code is sometimes required, but can also be a form of in-code
            documentation, providing guard rails (pun?) to catch programmer mistakes,
            esp newbie programmers not familiar with the code.

            The purpose of guard code, ultimately, is to prevent code execution using
            defective data, ie, guard code is there to prevent bugs.

            Make sense?

            Last edited by bltdavid; 11-04-2023, 03:50 PM. Reason: typo

            Comment


              #7
              Originally posted by Xcoder View Post
              if we're guarding against user entering negative value that is also protected when we create input variable by setting min value. Maybe I've missed the point?
              Yes, you missed the point. Sorta.

              That's great that your lookback property is
              being validated by a 'min' value, but how does
              the IsSeriesBelow method know that you've
              done that?

              Arguments passed to methods may have been
              validated multiple times before being passed to
              a low level function like IsSeriesBelow.

              It's not a big deal that values get checked and
              validated and sanitized many different ways at
              many different levels -- remember, many times
              these layers of code are independent of each
              other. It's quite common to see lots of code
              overlap when validating arguments at various
              layers -- esp independent layers.

              In the case of IsSeriesBelow ...

              Think about it this way: startBarsAgo can be
              zero, that's ok -- but lookback cannot be zero,
              it's a logic error in the programmer's brain to think
              of zero as valid (at least in the case of this particular
              method).

              But the problem is, many times zero is already
              valid for so many other things that people may
              just assume it's also valid for lookback. So, our
              guard code helps to fight programmer bias, too.

              So, for our little IsSeriesBelow, we try to catch
              those biases (er, I mean, lazy assumptions) and
              throw an exception.

              I know it's a bit subjective, but ultimately guard code
              is there to prevent bugs, that is, to prevent code
              execution using faulty data.

              Just my 2˘.

              Last edited by bltdavid; 11-04-2023, 03:53 PM. Reason: typo

              Comment


                #8
                Thanks bltdavid​ a.k.a. Dave Lots of good insight right here.

                So, in regards of time window I am thinking of calling Time[0] that I believe returns current candle time in string format which it was on exchange (Eastern for CME and NYSE)? Then I'd convert that string into actual time string or object to figure out the time and do my math to say trade between 9:30 and 11:30 Eastern time. But I don't know if I overcomplicated things, maybe there a better way?

                looking for simple Boolean expression at the end like isTime after 09:30 and before 11:30 then do thing.
                xcoder
                NinjaTrader Ecosystem Vendor - EMS

                Comment


                  #9
                  For time windows, I use the code I mentioned in post 5 above.

                  Comment


                    #10
                    Hello Xcoder,

                    Thanks for your post.

                    Using loops would be considered C# education and falls outside the scope of support we are able to provide you with in the Support Department at NinjaTrader. We do not provide C# education in our support services.

                    You could consider doing a quick Google search for something like "Working with C# Loops" to find more information about creating loops in C#.

                    That said, bltdavid has also provided some great information regarding this topic. You could review that information and implement it in your script to accomplish your goal.

                    Note that IsSeriesBelow is not a documented NinjaScript specific method or property.

                    In regard to limiting actions to occur between a certain time, a Time Condition or Time Filter could be implemented in your script. The forum thread bltdavid shared in post # 5 demonstrates this.

                    See the 'How to create Time conditions' and 'How to create Time Filters' sections of this help guide page for more information: https://ninjatrader.com/support/help...on_builder.htm
                    Last edited by NinjaTrader_BrandonH; 11-05-2023, 04:02 PM.
                    Brandon H.NinjaTrader Customer Service

                    Comment


                      #11
                      thank you, Brandon
                      xcoder
                      NinjaTrader Ecosystem Vendor - EMS

                      Comment

                      Latest Posts

                      Collapse

                      Topics Statistics Last Post
                      Started by jxs_xrj, 01-12-2020, 09:49 AM
                      6 responses
                      3,290 views
                      1 like
                      Last Post jgualdronc  
                      Started by Touch-Ups, Today, 10:36 AM
                      0 responses
                      7 views
                      0 likes
                      Last Post Touch-Ups  
                      Started by geddyisodin, 04-25-2024, 05:20 AM
                      8 responses
                      61 views
                      0 likes
                      Last Post NinjaTrader_Gaby  
                      Started by Option Whisperer, Today, 09:55 AM
                      0 responses
                      8 views
                      0 likes
                      Last Post Option Whisperer  
                      Started by halgo_boulder, 04-20-2024, 08:44 AM
                      2 responses
                      24 views
                      0 likes
                      Last Post halgo_boulder  
                      Working...
                      X