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

Using Dictionary in indicator

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

    Using Dictionary in indicator

    Hello,
    I'm starting on a new course for me: Dictionaries.
    I'm getting an error that, "the given key was not present in the dictionary". I have verified through Print() that the valleysRising.Key does have value, but for some reason around the 25th bar I get the error. Here is my code.
    Code:
     #region Variables
            B1StochDir2                stochDirection;
            B1HourGlass               hourGlass;
            B1PVStoch                  stochPV;
    
            protected                     Dictionary<int, ValleysRising> valleys;
    
            #endregion
    
            protected override void Initialize()
            {
                Overlay                  = true;
                BarsRequired        = 15;
            }
            protected override void OnStartUp()
            {
                stochDirection              = B1StochDir2(3, 5, 2);
                hourGlass                    = B1HourGlass(14, 14, 7, 15, 3);
                stochPV                       = B1PVStoch(3, 5, 2);        
            }
    
            protected override void OnBarUpdate()
            {
                if(CurrentBar < BarsRequired) return;
    
                var valleysRising     = new ValleysRising(){Key = 1};
    
                valleys    = new Dictionary<int, ValleysRising>();
    
                for (int x = 0; x <= 3; x++){
                    if(stochPV.StochValley[x] != -1){
                        valleysRising.BarNumber      = CurrentBar;
                        valleysRising.Value                = stochPV.StochValley[x];
                        valleys.Add(valleysRising.Key, valleysRising);
                        break;
                    }    
                }
                Print(CurrentBar);
                Print(valleysRising.Key);
                Print("");
    
                ValleysRising valleysCheck     =    valleys[1];    
            }
    
            #region Properties
    
            #endregion
        }
        public class ValleysRising
        {
            public int           Key                {get; set;}        
            public int           BarNumber    {get; set;}
            public double    Value             {get; set;}
    
            public ValleysRising(){
    
        }
      }
    Would someone mind taking a look at this?

    #2
    Hello CaptainAmericaXX,

    What line is line of code causing the error?

    Is it the 'stochPV.StochValley[x]' that has the invalid key?

    Is it valleys[1]?

    Use prints on different lines in the script to see where the code is stopping with an error.
    https://ninjatrader.com/support/foru...121#post791121


    Also, below I am including a sample script that uses a dictionary.
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      Originally posted by CaptainAmericaXX View Post
      Hello,
      I'm starting on a new course for me: Dictionaries.
      I'm getting an error that, "the given key was not present in the dictionary". I have verified through Print() that the valleysRising.Key does have value, but for some reason around the 25th bar I get the error. Here is my code.
      Code:
      #region Variables
      B1StochDir2 stochDirection;
      B1HourGlass hourGlass;
      B1PVStoch stochPV;
      
      protected Dictionary<int, ValleysRising> valleys;
      
      #endregion
      
      protected override void Initialize()
      {
      Overlay = true;
      BarsRequired = 15;
      }
      protected override void OnStartUp()
      {
      stochDirection = B1StochDir2(3, 5, 2);
      hourGlass = B1HourGlass(14, 14, 7, 15, 3);
      stochPV = B1PVStoch(3, 5, 2);
      }
      
      protected override void OnBarUpdate()
      {
      if(CurrentBar < BarsRequired) return;
      
      [COLOR=#FF0000]var valleysRising = new ValleysRising(){Key = 1};
      
      valleys = new Dictionary<int, ValleysRising>();[/COLOR]
      
      for (int x = 0; x <= 3; x++){
      if(stochPV.StochValley[x] != -1){
      valleysRising.BarNumber = CurrentBar;
      valleysRising.Value = stochPV.StochValley[x];
      valleys.Add(valleysRising.Key, valleysRising);
      break;
      }
      }
      Print(CurrentBar);
      Print(valleysRising.Key);
      Print("");
      
      ValleysRising valleysCheck = valleys[1];
      }
      
      #region Properties
      
      #endregion
      }
      public class ValleysRising
      {
      public int Key {get; set;}
      public int BarNumber {get; set;}
      public double Value {get; set;}
      
      public ValleysRising(){
      
      }
      }
      Would someone mind taking a look at this?
      The text that I have marked in red means that you are recreating those two object on every pass of OBU. Why?

      It does mean though that if your for loop runs less than 2 times in a pass, there will be only one value in valleys. i.e., valleys[1] would not exist.

      Comment


        #4
        Thank you both for your help.
        Chelsea_B, as koganam discovered, the issue was in my for loop index. I'm currently trying to understand why this would cause an error. Do you happen to have a dictionary sample script for NT7? I'm still way old school.

        koganam,
        The text that I have marked in red means that you are recreating those two object on every pass of OBU. Why?
        I chuckle whenever someone asks me why I did something some way. The answer always is, "I don't know. I thought it would work." I thought there would be an issue every time OBU updated, but I didn't know another way to do it. If you could show me the proper way to initialize the dictionary I would be grateful.

        Comment


          #5
          Originally posted by CaptainAmericaXX View Post
          Thank you both for your help.
          Chelsea_B, as koganam discovered, the issue was in my for loop index. I'm currently trying to understand why this would cause an error. Do you happen to have a dictionary sample script for NT7? I'm still way old school.

          koganam,

          I chuckle whenever someone asks me why I did something some way. The answer always is, "I don't know. I thought it would work." I thought there would be an issue every time OBU updated, but I didn't know another way to do it. If you could show me the proper way to initialize the dictionary I would be grateful.
          1. Given what appears to be the logic, I would say just declare/initialize both of those as class variables, instead of local variables in OBU.
          2. Check the count of any collection before you access the indexed value, and act as necessary, even if it means throwing an exception.
          Last edited by koganam; 06-26-2019, 02:21 PM.

          Comment


            #6
            The first line marked in red should stay where it is.
            This is because valleysRising is the object being added to the dictionary,
            so each time you want to Add valleysRising to the valleys dictionary, it should
            be a new ValleysRising object.

            The second line marked in red should be moved to OnStartUp.
            This is because valleys is the dictionary, and it only needs to instantiated
            one time, so move it out of OnBarUpdate and into OnStartUp. It is already
            a protected class variable, so that part is fine.

            The class ValleysRising has a data member named Key, which is probably not
            necessary -- since if your Key is just an integer which is always incrementing,
            then a List is probably better than Dictionary. But, in your code, I see you are
            not incrementing Key, but it stays the value of '1' for every valleysRising object
            added to the Dictionary. Why not eliminate the 'Key' data member and just use
            the 'BarNumber' data member as the dictionary key? After all, BarNumber is
            unique for every bar, because you assign it the value of CurrentBar.

            You have other problems, too. The valleysCheck variable is assigned the
            reference from valleys[1], but that is not the correct way to access a dictionary.
            And, for whatever you're trying to do, valleys[1] is the 2nd item and won't exist
            if valleys only has 1 item in it. That is, valleys[0] is the first item, not valleys[1].

            I think for your particular use case above, a Dictionary is probably poor choice,
            as it unnecessarily complicates things. I'd recommend the use of a List instead.

            But, if your desire is to learn, throw in a few reading assignments for your self,
            there are many all across the internet. For example,

            https://www.google.com/search?q=c%23...tionary+values
            https://www.tutorialsteacher.com/csh...arp-dictionary

            Hang in there!

            Comment


              #7
              Thanks for all the help. I followed bltdavid's advice and changed the Dictionary for a List.
              I was hoping that by using a Dictionary/List that I would be able to save all specified past values in memory. What I'm getting now is a new, updated value every time OBU is called which really is nothing better that creating a variable. My ignorance of Lists and how the OnBarUpdate() works is limiting my ability to obtain my desired result.
              I'm trying to capture the values of what I call "valleys" in which an indicator comes to a visual bottom point. I wanted to then compare those past valleys against new valleys as they're created. What I'm trying to create is a collection that shows, for instance, bars 5, 10, 13, 20, with values of 22, 30, 50, 90 etc.
              The logic for getting the "valley" is sound, but I can't save more than one value at a time. Can anyone give me an idea of how to do this?
              Thanks

              Comment


                #8
                Originally posted by CaptainAmericaXX View Post
                Thanks for all the help. I followed bltdavid's advice and changed the Dictionary for a List.
                I was hoping that by using a Dictionary/List that I would be able to save all specified past values in memory. What I'm getting now is a new, updated value every time OBU is called which really is nothing better that creating a variable. My ignorance of Lists and how the OnBarUpdate() works is limiting my ability to obtain my desired result.
                I'm trying to capture the values of what I call "valleys" in which an indicator comes to a visual bottom point. I wanted to then compare those past valleys against new valleys as they're created. What I'm trying to create is a collection that shows, for instance, bars 5, 10, 13, 20, with values of 22, 30, 50, 90 etc.
                The logic for getting the "valley" is sound, but I can't save more than one value at a time. Can anyone give me an idea of how to do this?
                Thanks
                In that case, a better design is to use a struct (or a class, but a class is rather heavy weight for such a simple case) to hold your paired values. Then you can populate and put the structs in a List. That way you can query the list by index to find particular offset valleys (like the 3rd most recent valley etc.), and you can also iterate through the list by index to find either/both of the bar index and value of the corresponding valley (e.g., how many valleys ago was the one that occurred on bar 15?).
                Last edited by koganam; 06-29-2019, 11:47 AM. Reason: Corrected sentence structure.

                Comment

                Latest Posts

                Collapse

                Topics Statistics Last Post
                Started by DJ888, 04-16-2024, 06:09 PM
                4 responses
                12 views
                0 likes
                Last Post DJ888
                by DJ888
                 
                Started by terofs, Today, 04:18 PM
                0 responses
                5 views
                0 likes
                Last Post terofs
                by terofs
                 
                Started by nandhumca, Today, 03:41 PM
                0 responses
                5 views
                0 likes
                Last Post nandhumca  
                Started by The_Sec, Today, 03:37 PM
                0 responses
                3 views
                0 likes
                Last Post The_Sec
                by The_Sec
                 
                Started by GwFutures1988, Today, 02:48 PM
                1 response
                9 views
                0 likes
                Last Post NinjaTrader_Clayton  
                Working...
                X