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

Very Strange (Awckard) results when working with Lists.

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

    Very Strange (Awckard) results when working with Lists.

    I would like to have a list of the last 5 closed bars that were at the time of the last (CurrentBar%5 ==0). the code is quite simple but it does not deliver the results it should.

    Let me first post the code.
    Code:
    namespace NinjaTrader.NinjaScript.Indicators.TestIndicators
    {
        public class ListsAwckardnessIssues : Indicator
        {    
            private List<int>             list00, list01;
    
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                    Description                                    = @"dont undestand what wappens";
                    Name                                        = "ListsAwckardnessIssues";
                    Calculate                                    = Calculate.OnBarClose;
                    IsOverlay                                    = false;
                    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;
                }
                else if (State == State.Configure)
                {
                    list00 = new List<int>();
                    list01 = new List<int>();
                }
            }
    
            protected override void OnBarUpdate()
            {
                list00.Add(CurrentBar);
                Print("List of currentbars: List00 "+string.Join(", ",list00));    
                Print("List of currentbars: List01 "+string.Join(", ",list01));
                if (CurrentBar%5==0)
                    {
                    //    list01.Clear();
                        list01 = list00;
                        list00.Clear();
                        Print("");
                        Print("List01: "+string.Join(", ",list01));
                        Print("List00: "+string.Join(", ",list00));
    
                    }
    
            }
        }
    }​
    then let me post the results:

    Click image for larger version

Name:	image.png
Views:	158
Size:	10.8 KB
ID:	1253294
    and now let me post the results that I expected.
    Click image for larger version

Name:	image.png
Views:	124
Size:	23.2 KB
ID:	1253297

    Here is the indeator...
    [ATTACH]n1253296[/ATTACH]

    Please let me know what Am I doing wrong??

    Thank You
    FVJ


    Attached Files

    #2
    Yep, we need to fix your brain. This is a C# question, no NinjaScript
    is involved, except for a better understanding of CurrentBar, and the
    result of (0%5==0) when CurrentBar is zero.

    When these two statements execute, what do you think happens?

    1. list01 = list00;
    2. list00.Clear();​


    Statement 1 assignment means list01 is now referencing
    the same memory as
    list00, meaning they are both pointing
    to the exact same list. Ok, no problem, you probably got that.

    Thus, when statement 2 clears
    list00, well, list01 is referencing
    the same memory, so it effectively clears both lists (er, I mean it
    clears the one list they both point to).

    Statements 1 & 2 don't execute until you have 5 bars, and then it
    clears both lists -- ah, but wait -- what does your if statement below
    do when CurrentBar is zero?


    if (CurrentBar%5==0)

    Zero mod anything is always zero. Therefore, statement 1 & 2
    will execute on the very first bar, and then every time CurrentBar is
    evenly divisible by 5. Thus, on CurrentBar == 0, you are setting
    both variables to point to the same memory, and that's why you
    see the contents of list00 and list01 duplicated (because they are
    the same, since they reference the same object).

    Now, why you think in your expected results that either list should
    somehow become null -- that is also wrong -- walk through the
    code on paper, and convince yourself of that fact.

    For a final thought, you don't need to ask anyone here anything
    about this script -- you need to get into the habit of adding Print
    statements to your code and always test your assumptions.

    -=o=-

    Hmm ...
    In fact, I think your brain did not know that '0 % n == 0' is true
    for all 'n' -- but if you had been adding Print statements, you
    should have eventually thought to narrow the problem and test
    your basic assumption with something like this,


    Code:
    for (int i = 0; i < 200; i++)
        {
            // test modulus '%' operator
            if ((i % 10) == 0)
                Print("i = " + i);
        }
    Anyways, now ya know.

    Just my 2˘.

    Last edited by bltdavid; 05-26-2023, 10:20 PM. Reason: Added link to CurrentBar help page

    Comment


      #3
      Originally posted by efeuvejota01 View Post
      I would like to have a list of the last 5 closed bars that were at the time of the last (CurrentBar%5 ==0). the code is quite simple but it does not deliver the results it should.
      Try this code,

      Code:
        list00.Add(CurrentBar);
        if (list00.Count > 5)
            list00.RemoveAt(0);
      The list00 will always contain a list of the last 5 bars,
      no need to get all fancy with the '%' operator, and no
      need for the second list01 variable, and no need to
      call list00.Clear() either.

      The trick is to remove the element at list00[0], which
      is what RemoveAt(0) is doing, but only after the list is
      considered 'full'.



      Last edited by bltdavid; 05-26-2023, 10:19 PM. Reason: Added Link to RemoveAt

      Comment


        #4
        And, for anyone who is wondering ... this statement,

        if (CurrentBar%5==0)

        is exactly equivalent to this statement,

        if ((CurrentBar%5)==0)

        I mean, the extra interior parentheses may matter to the
        human eyes, but they do not matter to the compiler.

        Why?
        Because operator precedence says that the '%' operator
        binds tighter (aka, executes) before the '==' operator.

        In other words, when parentheses don't make it clear,
        it is operator precedence that determines the order of
        operations, and in programming speak, we say that
        "the '%' operator has higher precedence than the '=='
        operator".

        -=o=-

        Parentheses are used to override these normal rules
        of operator precedence -- but because they can also
        make the code clearer, many programmers (and many
        teachers) use/overuse them a lot.

        -=o=-

        Any good C# programmer should commit a fair amount
        of the operator precedence table to memory. Not a lot
        will do this, because they rely on parentheses instead.

        Why commit?
        When you write your own code, that's fine. But when
        reading the code of others, you may have to fall back
        on knowing operator precedence really well to really
        understand a hairy expression or two.

        Where do you see these hairy expressions?
        In school quizzes and exams, in job interviews, in prior
        existing code at work, in books and articles ... it's more
        common than you think.

        Just my 2˘.

        Last edited by bltdavid; 05-26-2023, 10:52 PM.

        Comment


          #5
          Hello efeuvejota01,

          Thanks for your post.

          bltdavid is correct. This is a C# education question and is not a NinjaScript-specific question so this would go beyond the support we would be able to provide you with in the Support department at NinjaTrader. Note that we do not provide C# programming education services in our Support department.

          Please refer to the advice shared by bltdavid regarding your inquiry. You could also consider doing a Google search for something like 'Working with Lists C#' to do further research about using C# Lists.

          Brandon H.NinjaTrader Customer Service

          Comment


            #6
            When you're doing this list01 = list00; I would suggest what you really want to do is this list01 = new List<int>(list00);.
            Bruce DeVault
            QuantKey Trading Vendor Services
            NinjaTrader Ecosystem Vendor - QuantKey

            Comment


              #7
              Thank you very much for your answers. (bltdavid ​ , NinjaTrader_BrandonH​, QuantKey_Bruce​)
              I was not aware of the lack of syntax of the core line in the script, so with the info in mind I searched online and came to the following syntax that worked pretty well
              Code:
              list01 = list00.Cast<int>().ToList();
              I will test the suggestion of QuantKey​_Bruce... in order to see all possibilities.
              Thanks again!!!
              FVJ

              The result I was looking for is the following
              Click image for larger version

Name:	image.png
Views:	111
Size:	13.5 KB
ID:	1253522

              Comment


                #8
                Originally posted by efeuvejota01 View Post
                list01 = list00.Cast<int>().ToList();
                Aren't list00 and list01 both type List<int>?
                I'm assuming they are, since post 1 defined them as such.

                Just curious, how well do you know C#?

                Ok, quick test:
                What is the difference between these 3 statements?

                1. list01 = new List<int>(list00);
                2. list01 = list00.ToList();
                3. list01 = list00.Cast<int>().ToList();

                Answer: Nothing. They all do the same thing, which is
                make list01 reference a completely new and separate
                list which is an exact duplicate of list00.

                But statement 3 is woeful, ugly, and pointless.
                Why? Because the Cast<int> is pointless when all
                list elements in both lists are already type int.

                -=o=-

                Why didn't you just take Bruce's advice?
                [His suggestion was fine, why did you ignore it?]

                What's with this Cast<int> solution you found?
                [Did you not understand Bruce's suggestion?]
                [Does Bruce's solution not work for you?]
                [Why do you think your Cast<int> solution is better?]

                I'm confused that you got perfectly sound advice
                but then chose to ignore it. What were your reasons?

                I'm not trying to be mean, you may have had your
                reasons, but from my vantage point, they don't look
                like particularly good reasons, which means I may
                not have the whole picture.

                Am I missing something?

                Last edited by bltdavid; 06-03-2023, 10:04 PM.

                Comment


                  #9
                  FYI My intuition is the cast approach probably could work but isn't exactly right, and I basically don't do it that way because it isn't as intuitive to me - since that's not the way I'm used to doing it, I didn't spend any time trying to figure out what's wrong with it and just suggested what I knew would work. Often, there are many ways to accomplish a goal, and I tend to zero in on the way that is the most readable and maintainable and isuitive for me to look at later and understand that it is intended to do. That having been said, my way is not the only way - it's just a way I understand and can explain easily without wasting resources blazing a new trail.
                  Bruce DeVault
                  QuantKey Trading Vendor Services
                  NinjaTrader Ecosystem Vendor - QuantKey

                  Comment


                    #10
                    Originally posted by QuantKey_Bruce View Post
                    FYI My intuition is the cast approach probably could work but isn't exactly right, and I basically don't do it that way because it isn't as intuitive to me - since that's not the way I'm used to doing it, I didn't spend any time trying to figure out what's wrong with it and just suggested what I knew would work. Often, there are many ways to accomplish a goal, and I tend to zero in on the way that is the most readable and maintainable and isuitive for me to look at later and understand that it is intended to do. That having been said, my way is not the only way - it's just a way I understand and can explain easily without wasting resources blazing a new trail.
                    The cast approach does work, but my point is the
                    casting is useless and completely superfluous. Why?
                    Because both lists are List<int> so the Cast method
                    is entirely and 100% pointless.

                    I was directing my comments at the OP, since they
                    ignored your sound suggestion, then went searching
                    on the internet, found the Cast<int> solution, and used
                    that instead, without understanding the uselessness
                    of that code, or the correctness of your suggestion.

                    I found that real curious, and suspect.

                    [Btw, I tend to use #2, since in my experience that is
                    the most common idiom for how to duplicate a list.]

                    Comment

                    Latest Posts

                    Collapse

                    Topics Statistics Last Post
                    Started by jxs_xrj, 01-12-2020, 09:49 AM
                    5 responses
                    3,289 views
                    1 like
                    Last Post jgualdronc  
                    Started by Touch-Ups, Today, 10:36 AM
                    0 responses
                    5 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
                    5 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