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

Forex tickSize

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

    Forex tickSize

    Hello! Running into something strange. I'm missing something but cannot put my finger on it.

    Code:
     for (double i = today.low; i <= today.high; i += TickSize) { //TODAY = CANDLESTICK. In other words I'm just looping through the high[0] to the low[0] and incrementing by the ticksize
    
    if (i == 1.20909) {
    Print("yes");
    Print(CurrentBar);
    Print(i);
    }
    if (CurrentBar == 2627) { //this bar includes the price of 1.20909 * see picture
    Print("Bar");
    Print(i);
    }
    
    }

    What is puzzling is that the bar 2627 does include the price of 1.20909 which is shown in this picture. Because it does, I would also expect the first condition to be true and give its print outs. It does not.

    Click image for larger version

Name:	2021-04-28 15_29_14-NinjaScript Output.png
Views:	182
Size:	41.6 KB
ID:	1153829


    #2
    Hello Jaboo,

    Thank you for your post.

    Could you provide a screenshot of your settings for the DataSeries of the chart you're running this on? I'd like to test but want to make sure we're testing over the same data.

    Thanks in advance; I look forward to assisting you further.
    Kate W.NinjaTrader Customer Service

    Comment


      #3
      Click image for larger version

Name:	2021-04-28 16_30_37-Chart - EURUSD.png
Views:	174
Size:	32.9 KB
ID:	1153839

      Comment


        #4
        Hello Jaboo,

        Thank you for your reply.

        I've been able to reproduce this on my end. I suspect it has to do with an issue with floating point arithmetic. There's some suggestions in the help guide that may be helpful:



        It's the end of my work day currently, but I'll see if I can work up an example in the morning.

        Thanks in advance; I look forward to assisting you further.
        Kate W.NinjaTrader Customer Service

        Comment


          #5
          Thanks Kate. Will take a look at the documentation you provided.

          For more context on what I'm trying to achieve; Every "tick price" i maps to an object in a dictionary. As I loop I pull the object for that price and do some processing. What appears to be happening is that sometimes the price can be 1.20909 and other times be 1.209099999. This would be two separate objects in my dictionary which would lead to undesirable results.

          If I need to do some pre processing to the value before I pull it from the dictionary I'm happy to do that. I'm just not sure where to start......

          Thanks!

          Comment


            #6
            Hello jaboo,

            Thank you for your reply.

            I've been able to do some further testing this morning and was able to get your example code working by using this inside the loop, so I can confirm it's a floating point arithmetic issue:

            Code:
            if((Math.Abs(i - 1.20909) < 0.000001))
            {
            Print("yes");
            Print(CurrentBar);
            Print(i);
            }
            
            if (CurrentBar == 2627)
            {
            //this bar includes the price of 1.20909 * see picture
            Print("Bar 2627");
            Print(i);
            }
            If you use this do you see the prints you'd expect?

            Thanks in advance; I look forward to assisting you further.
            Kate W.NinjaTrader Customer Service

            Comment


              #7
              it does. but still not sure how to solve my problem. I'm not sure how to get it so the price is always the same. Should I round the number? This way I always pick up 1.20909 from my dictionary and never 1.209099999?

              Comment


                #8
                Hi jaboo,

                The link Kate provided above does have a few answers on how to address the issue.

                A possible quick and dirty pragmatic approach.

                Personally, sometimes when I am doing quick assessment work and want to work out of deep granularity issues or just want to get better visibility of granularity various plots on a chart I ...
                • at the open of the code block multiply each value by 10,000 (or a bigger number if 10k was not big enough)
                • execute my algorithmic work
                • if I need to address concerns similar to those addressed by "approximate compare" I might add or subtract .0001 to one or multiple values I am trying to compare.
                • then if I need to carry a value forward at the original granularity multiply the result by .0001
                • continue on with my work ...

                HedgePlay
                Last edited by hedgeplay; 04-29-2021, 09:58 AM.

                Comment


                  #9
                  thank you for the replies. Admittedly I do not understand your suggestions.

                  Code:
                  dictionary<double> dict
                  
                  
                  for (double i = today.low; i <= today.high; i += TickSize)
                  
                  if(does not contain key)
                  dict.add(i) //assume here it has the price of 1.20909
                  
                  
                  ....... 100 bars later
                  
                  
                  for (double i = today.low; i <= today.high; i += TickSize)
                  
                  if(dict contains i) //assume here that i = 1.20909999999999999
                  
                  print(found key)
                  I do not understand how to access that print statement. because i will not always match what is in the dictionary. or even worse, during my first for loop I might add 1.2099999 one time and again might add 1.20999999999999999 another time. the only price I care about, in the case of forex pair, is the tick price ie 1.20909.


                  Comment


                    #10
                    Look to Kate to provide better informed answers.

                    I am not user I fully understand exactly what you are trying do and the issues that need to be addressed .. however here is my quick take on a reply.


                    TLDR; Create "Lowest common Denominator Buckets" and mask down or cast down to reduce granularity of the more detailed inputs to fit the common bucket size.


                    I will just share from software engineering and architecture experience on very large global mission-critical systems that most common industry solution I have seen to matching numbers like 1.20999999999999999 .. 1.20909. is to identify the lightest, least places below the decimal you need to need the data to retain and "mask" each value prior to loading it into the dictionary to this less granular 'standard' format you will use.


                    For example tick transaction time could be easily captured down to the 100 nanosecond level and look something like this.. note the lack of zeros at the end.


                    Time[0].Tick = 6375472610277376213

                    But some system designer decided that level of granularity is not needed so time is not captured at that level or when captured is masked before saved to reduce the grain to a more manageable level. So at least the CQG Continumm data is send to us at this grain instead.

                    Note the four zeros at the end where further detail was not captured originally or masked off before being saved to reduce the complexity.

                    637547261027730000


                    A concept example to study ... From memory, I think the NT8 devs might have done something similar when using when using time time data series charts so your looks against previous Bars by Time are more likely to return the correct bar when submitting for the bar index number by time.

                    "masking" (consistent removal of a number of digits or characters) is a more common approach than 'rounding'


                    Update: An Addition .. if trading cyrpto or across different brokers or something where possibly more grain is needed than the lowest common denominator then sometimes you might need to add zeros to the simplest data inputs so you can keep the absolute minimum number of places on the more complex inputs.


                    Gotta go.. have work to do.

                    Best of Luck!

                    HedgePlay
                    .
                    Last edited by hedgeplay; 04-29-2021, 02:19 PM.

                    Comment


                      #11
                      Thank you HedgePlay

                      this seemed to have worked

                      Code:
                      String value = String.Format("{0:N5}", i);
                      i = Convert.ToDouble(value);

                      Comment


                        #12
                        Cool!

                        Glad to see you found a simple solution.

                        HedgePlay

                        Comment

                        Latest Posts

                        Collapse

                        Topics Statistics Last Post
                        Started by Brevo, Today, 01:45 AM
                        0 responses
                        6 views
                        0 likes
                        Last Post Brevo
                        by Brevo
                         
                        Started by aussugardefender, Today, 01:07 AM
                        0 responses
                        3 views
                        0 likes
                        Last Post aussugardefender  
                        Started by pvincent, 06-23-2022, 12:53 PM
                        14 responses
                        242 views
                        0 likes
                        Last Post Nyman
                        by Nyman
                         
                        Started by TraderG23, 12-08-2023, 07:56 AM
                        9 responses
                        384 views
                        1 like
                        Last Post Gavini
                        by Gavini
                         
                        Started by oviejo, Today, 12:28 AM
                        0 responses
                        6 views
                        0 likes
                        Last Post oviejo
                        by oviejo
                         
                        Working...
                        X