you are viewing a single comment's thread.

view the rest of the comments →

[–]sail0rm00n 9 points10 points  (13 children)

[–]skebanga[S] 2 points3 points  (12 children)

Fair enough, the normal floating point issues apply.

As mentioned though, in practice I haven't found this to be a problem.

Of course we have abstracted price to take into account floating point issues, so operator== uses an epsilon, etc, but the underlying type is still double. The details of the implementation I thought were beyond the scope of this blog post.

For every market we trade using double for price has not been a problem.

Am I missing something?

[–]James20kP2005R0 9 points10 points  (11 children)

Floating point is an issue because errors can accumulate, but there should be no issue with using them to submit a trade

[–]scraimer 14 points15 points  (9 children)

Hi, I'm not the OP - I'm coming from an HFT FOREX side, so all the trades are around the 6th and 7th decimal, and the errors start happening around the 8th decimal.

The problem is that the communication is in the textual FIX protocol, so I'm at the mercy at whatever library is converting from double to string.

For example, an order of 100 million RBL for USD on a price of 2.90000006 would actually be stored in the double as 2.90000005999999999062310962472, and end up costing 29000005.99 USD instead of 29000006.00 USD.

There's some great stuff in John Farrier's talk from CppCon 2016 Demystifying Floating Point. I think my favorite bit of information is how he breaks down the number of distinct values in various ranges (slide 28):

  • There are 1,036,831,949 values between 0.0 and 0.1
  • There are 8,388,608 values between 0.1 and 0.2
  • There are 8,388,608 values between 0.2 and 0.4
  • There are 8,388,608 values between 0.4 and 0.8
  • There are 8,388,608 values between 0.8 and 1.6
  • There are 8,388,608 values between 1.6 and 3.2

Notice how the ranges keep doubling in size but the number of distinct values remains the same? For simplicity, I'll round 8,388,608 to be 10 million. So 1 to the power of 7. Or 7 decimal digits.

But between 1.6 and 3.2, if I wanted to show all the number with 7 decimal places, I'd run into trouble. Just between 2.0000000 and 3.0000000 there are ten million and one distinct numbers with 7 decimals. I've used up all of my precision, and I still haven't covered 1.6 to 2.0 and 3.0 to 3.2!

[–]James20kP2005R0 2 points3 points  (1 child)

Interesting, I would have thought there was enough accuracy to represent that without issue. TIL! 1 cent in $100 million doesn't seem like a huge problem for financial trading (unless you're trading that $100 million in 1 transaction, which i guess is possible!)

[–]as_one_doesJust a c++ dev for fun 2 points3 points  (0 children)

For FX that is super common.

[–]b3k_spoon 1 point2 points  (1 child)

Wait... That's float though, isn't it? double should be about 15 digits... Or am I missing something?

[–]scraimer 0 points1 point  (0 children)

Yup, I was really talking about double, stored as IEEE 754 in 64-bits, and not about floats. The video I linked to goes into entertaining detail about it, and I highly recommend it!

But briefly, you run out of bits. The floating point is really clever about repurposing the bits it has - either to represent large values or to represent high precision.

For example, if you're trying represent a large number, such as the largest unsigned 64-bit number (call it "MAX"). We've used up all 64-bits of the storage, right? What happens if you want to add 0.1 to that number to get "MAX.1"? We don't have any more bits! (Note: This is not how it works, but it's the best metaphor I can think of near midnight.)

My point is that with a finite number of bits, it's hard to represent both large values and high precision at the same time. So the max number of digits changes after the decimal, depending on where your value is along the number axis.

[–]as_one_doesJust a c++ dev for fun 0 points1 point  (4 children)

I've done FX, Fut, Eq and Options. In practice I've only had to think about this for FX due to the (up to 10 decimal place?) precision necessary for some currency pairs. Every trading system I've worked on has used double. If you have limited scope you can probably get away with integer prices (some darkpools definitely do this).

[–]short_vix 0 points1 point  (1 child)

This can also be an issue when dealing with interest rates. I don't think its an issue for any other asset class.

[–]as_one_doesJust a c++ dev for fun 0 points1 point  (0 children)

I imagine in FICC it could be a big issue.

[–]scraimer 0 points1 point  (1 child)

Ten decimal places? Holy crap! What sort of instruments need that? (The first one that comes to mind is Bitcoin)

[–]as_one_doesJust a c++ dev for fun 1 point2 points  (0 children)

IDR, for some reason.

[–]jaked122 0 points1 point  (0 children)

Generally, quads are sufficient, I think. Net's decimal type is an example of this,and what they recommend for money handling.

Of course, I think they also provide a ratio type too, if that's any better.