Track Topic
: rss

Topic: Ticks size

posts 1–20 of 25 newer >
Page 1 · 2
?
50 posts

Hi,

I am writting a function to do tick rounding in bf and although i have found a way to do it, the implementation just makes me feel a little dirty.  It is easy to take a valid tick i.e. 2.02 and get the next i.e. 2.04. But to know that 2.005 should be 2.0 and not 2.02 is not so simple. (i think).

Ok so the current implementation has a look up table (yeah i know) of all possible ticks. If you have a number, find the nearst two ticks, then working out which of the two is closer is simple. This procedure is O(log2N) using a binary search. The time sucks as the look up table is about 400 values and the search which is log2(400) is about 8-9. It works, but its crap.

is there a O(1) solution to this? Go team...

?
62 posts

Rather than have a table of all tick values, I guess it would be more efficient to have a table of increments i.e. the gap between ticks:

 

if($price<100) $tick=5;
            if($price<50) $tick=2;
            if($price<30) $tick=1;
            if($price<20) $tick=0.5;
            if($price<10) $tick=0.2;
            if($price<6) $tick=0.1;
            if($price<4) $tick=0.05;
            if($price<3) $tick=0.02;
            if($price<2) $tick=0.01;

?
62 posts

Oops - managed to post that half-way through writing it.

Anyway, have a table of increments, and then round to the nearest increment:

tick=round(unroundedprice / increment) * increment

Not o(1), but it increases with the number of different increments (9 for Betfair), not the number of different ticks

?
128 posts
I used to use a function like JPL's and then decided to use it to populate a lookup table. The way i found fastest was to make the table an array of integers and then convert back to double or float after looking up the value. Having spent about 5 or 6 hours profiling various methods, the end result was that i saved something like 100ms on 1,000,000 odds conversions. When was te last time you did THAT many? The major bottle neck is, and always will be, the internet speeds. Having said that, it's not particularly difficult to break the 20x a sec limits...
?
50 posts

Thats how i generate the table in the first place.

Lets run with this though as it was also the last inteligent thought I had also. So if you know that you have a price 2.005 then you get from the increments that the tick size is 0.02. but then what? you can't add or subtract it, otherwise you get 1.985 or 2.025. The only other thing i can think of is rounding it up by 2dp then doing some sort of integer arithmetic based on the tick size using mod to work out the delta from the nearest tick and then adding or subtracting it and rounding it back. 

Ill try coding that up and see what happens. 

?
62 posts

As per my previous post, surely you just have to divide by the tick size; round to the nearest integer; and then multiply by the tick size.

Taking your example of 2.005, we divide by 0.02 to get 100.25, round to 100, and multiply by 0.02 to get 2.00.

 (I think this only works if the tick sizes are of the form 1/N where N is an integer, but they all are, so that's fine).

?
50 posts

ok i posted that before seeing the rest of jpls post. Interesting. Thanks.

?
128 posts
Probably obvious but just to clarify what i said...

Lets say you're calculating the mean odds between back and lay:
Back          Lay
3.20           3.30

Convert the odds to integers when you convert from strings to numbers, which gives us:
Back          Lay
320            330

Calculate the mean:
(320 + 330) / 2 = 325

That's our lookup table index number. The array will return 325 because it is already a qualifying increment. With standard rounding, Index 322 wil return 320, Index's 323, 324, 325, 326 and 327 will all return 325. Index 328 will return 330, etc, etc. What i also did was make the array 3D which gave me 3 options: "standard rounding", "always round down" and "always round up". It also makes life easy when you're trading "back odds + 1tick", etc because all you have to do is modify the index before you do the lookup.
?
128 posts
Guess who's the slowest typer. LOL

Personally, i'd never HAVE  to worry about 2.005 because i never worked beyond 2 decimal places. But even if i did, 2.005 would become 200 or 201 by my methods, depending which way you specify the rounding.
?
50 posts
but if you specify your rounding like that dont you have an epic lookup table? i.e. 1000 * 100 in size 
?
50 posts

Thanks you two for all the help, you've provided some good food for thought. I think ive improved on both your techniques though. See what you think.
So i did it using the mod way, which i think is better a) fast since it doesnt us a look up table b) allows a greater level of accuracy than jpl's method.

Basically the problem with jpls method is that 3.0 is rarely 3.0 but 2.999999999999999999999 (thanks IEEE) which works when (int)(2.99999 * 100.0) = 299 which will get you 3.0. However if you have 3.02499999 which should be 3.025, if you mult by 100 and floor it you get 302 which will round to 3.00 and not 3.05.

3.0265 --> 3.00  // wrong
3.0298 --> 3.00
3.0331 --> 3.05

So use round instead of floor i hear you cry. Well you get a different problem at the other end 2.9868 should round to 2.98 but 298.68 rounds to 299 which gives you 3.00

2.9835 --> 2.98 
2.9868 --> 3.00 // wrong
2.9901 --> 3.00

So where is the solution? Well you just need to do it with floor and look at an extra decimal place i.e. scale up by 1000 not 100 and then do the floor and integer calc.

Here is the code anyways. (It assumes you use jpl's lookup table for tick size)

public double roundToNearestTick(double value) {
        final double scaleup = 1000.0 ;
        int iValue = (int)(value * scaleup);
        int tickSize = (int) (getTickSize(value) * scaleup);

        int remainder = iValue % tickSize;
        if (remainder < (tickSize / 2.0)) return ((iValue - remainder) / scaleup);
        else return ((iValue + (tickSize - remainder)) / scaleup);
}

Rounding is a bitch.

?
62 posts

blackmagic - probably I'm missing something, but seems to me a lot of your rounding problems are self-created from deciding to round to 2 or 3 d.p. unncessarily.  What's wrong with:

public double roundToNearestTick(double value) {
        double tickSize = getTickSize(value);
        return (double)(round(value/tickSize)) * tickSize;
}

Apologies for any language mangling - not a Java programmer.

?
128 posts
Strangely enough, i just dug out my old code and was indeed using x1000 and not x100.

But as i said, you're only saving micro seconds. Code execution time is zero in comparison to internet lag...
?
62 posts

In summary, my view (which may be wrong of course) is that you don't need to round explicitly to 2 or 3 d.p. because rounding to the nearest tick will do that automatically.  If you try to round to 2 or 3 d.p first and then round to the nearest tick you'll get horrible errors (as blackmagic found it).  But if you keep it simple and just round to the nearest tick everything is very easy.

?
91 posts

mmmm, I've just been playing with my own code (that I've been using for 2 years), I just rewrote it a few times (trying to get round-up, round-down, and nearest. Did a few experiments and the outcomes were scary... Even a rewrite that seemed functionally identical gave different results. Dodgy ground indeed.

?
50 posts

JPL I think is still a problem if you truncate/round to 2-3d.p. If you are rounding or truncating to 2 or 3dp then you are loosing some digits that you need to do the tick rounding properly. If you look closely at the examples i gave you can see fence post errors you get for each of the round/truncate methods.

?
62 posts

blackmagic - we may end up having to agree to differ on this one.

You flagged up 2.9868 as one that might round to 3.00 if rounded carelessly.  But if you just divide by the tick size, round and then multiply again it works:

2.9868 / 0.02 = 149.34, rounded to 149

149 * 0.02 = 2.98 (correct)

?
50 posts

touche my freind, touche...

unfortunatly

?
50 posts

touche my freind, touche...

unfortunatly

that
?
50 posts

touche my freind, touche...

unfortunatly

posts 1–20 of 25 newer >
Page 1 · 2

This Topic Is Locked To Guest Posts

It's been a while since this topic was active, if you'd like to get it going again, please post as a registered member

join now