C++ price type to properly deal with rounding error?

Discussion in 'App Development' started by kmiklas, May 17, 2017.

  1. kmiklas

    kmiklas

    Hey All,

    What type is considered is "best practice" for price representation in C++?

    I'm building an order book, and have run into the rounding error gremlin.

    The problem is ubiquitous, but in this example, I'm using a double to both represent a price point, and also as a key in the bid/ask queues. Rounding error is causing the key lookup to be empty. Example: here I am simply trying to print L2 book data +/- 10 price points above/below market price. Using a loop and an increment of $0.01 (penny pricing), I try to index bid[12.78]. Due to rounding error, I get bid[12.78000000000000001], which maps to nothing. :mad:

    Any recommendations on how to represent price type? I'm not sure what direction to head here. I've heard:

    1. Internally represent prices as integers, and convert to doubles only when necessary.
    2. Represent the whole number and decimal part of numbers as integers. This seems like a lot of work.
    3. Use the Intel scientific library.

    This is pretty much driving me crazy, so any help is appreciated.

    What is the best practice for price representation in C++?

    Thank you.

    [​IMG]
     
    Last edited: May 17, 2017
  2. 2rosy

    2rosy

    thats not a rounding error its floating point issues.
     
    kmiklas likes this.
  3. southall

    southall

    You call yourself a 'Quantitative Software Engineer' in your signature, yet you get stuck with a trivial issue like this?
     
    kmiklas likes this.
  4. Simples

    Simples

    Depends on your usage of those numbers. Have you created bounded contexts and done some DDD (domain driven design)? From experience you should know when you'd want to use floats, and when not to. You don't need to use the same formats everywhere, though if it's fast and convenient enough, you might prefer to.

    Design for future changes and adaptability - which means less is more: less configuration, less dynamic logic, easier to rewrite sections, clear context boundaries, possibility for optimizations in critical inner loops.

    Can't imagine even one place to use floats in an exchange, except a really funky one. Issues like this is why software / DBMS often come with clear specifications on their datatypes and their limitations, with fully documented errorcodes on their violations. Trying to support anything or everything, quickly becomes both expensive and confusing, while limitations can lend itself to clear APIs and perhaps some internal optimizations.
     
    kmiklas likes this.
  5. Have you tried rounding to two decimals before submitting the float? The rounding step should be the very last step, with no other calculations or modifications performed afterwards.
     
  6. You're right straight-up float and double types exhibit rounding problems with some numbers.
    Have you looked at any fixed point libraries? There are plenty to choose from for C++, including Boost.Multiprecision.
    BTW if you're not already using Boost I suggest you consider it. One nice thing is you don't have to totally Boost-ify your application. You can cherry pick the features you want, many of which are purely header-based templates.
     
    Trader13 and kmiklas like this.
  7. dartmus

    dartmus

    Last edited: May 18, 2017
  8. kmiklas

    kmiklas

    Thanks for your replies everyone. This is one of those problems that seems trivial on the surface, but there's a lot of "gotchas." We all know that if the price is wrong because of machine error and number representation, somebody is going to hurt! I want to do this properly, and get it right the first time.

    I've Googled, posted on forums, and asked around, but can't seem to get a conclusive answer. The concern here is rounding/floating point arithmetic error. The following seem to be viable options:

    1. float, double, or long double (with supporting rounding functions)
    2. int, long, (or some size_t) and cast to decimal type at the last minute
    3. Boost multiprecision library
    4. Intel mathematical library
    5. Store the whole number and decimal parts as separate ints! (or size_t)

    Hmmmm..... #1 seems to be the leader of the pack, but I'm more inclined to go with #2. Whole numbers mathematics have no risk of rounding error, floating point issues, and can easily be casted when sending to output.
     
  9. Turveyd

    Turveyd

    FPI are a nitemare, computers shouldnt go wrong but they do and it sucks.

    Convert to a String get the left 8characters convert to number, store as string if need be, slower for database searchs ofcourse.
     
    kmiklas likes this.
  10. Simples

    Simples

    Your problem is the above. "Getting it right the first time" depends on what usage you need. If you need to sort numbers, maybe int64 will be OK for you, given some limitations. Or maybe int64 + last int64 for exponent part (forgoing unlimited precision and numerical range)?

    What limitations can you live with? If you want to be completely unbounded, these problems will keep popping up at every turn, which is why serious software vendors design with sane limitations in the first place.

    By using C++ and some STL/Boost libraries, maybe you can template away from the problem, but do you really really need to?

    The huge difference here is that businesses focus on the businessproblems, while you take on this not as a business, but for exploration and research, with a technical focus.
     
    #10     May 18, 2017
    kmiklas likes this.