5 ms·
I glanced, and I found this handbook shallow and - in some areas - even bad advice. E.g. If I ever see a monetary value stored in something else than integers
by xlii 4mo ago
I glanced, and I found this handbook shallow and - in some areas - even bad advice.
E.g. If I ever see a monetary value stored in something else than integers I'm going to run away screaming (thank you Rust decimals represented as JSON floats). It's always integers unless you have a VERY good reason to do otherwise (though exported view can be in anything, even in weird bitcoded formats).
FX exchange. Resolution of FX isn't a point-in-time thing, things like buyer rate-in-time, seller rate-in-time, agreement, agreement tolerance, agreed upon resolution timestamp come in the effect.
Immutability - that's why you want to have event sourcing everywhere that touches money:
# Resolved stream
A -> B -> E
# Actual stream
A0 -> Edit(A0, A) -> B -> C -> D -> Rollback(B) -> E
Though in the end Fintech != Fintech. I worked at Fintech where money was treated like a baggage, and in other where money was a central point of everything.
- lxgr 4mo ago> thank you Rust decimals represented as JSON floats What do you mean? JSON doesn’t have floats, it has numbers, and how they’re used after being parsed is not part of the spec. > If I ever see a monetary value stored in something else than integers I'm going to run away screaming That’s good, then we’ll likely not be working on the same system :) I consider running from “amounts as integer” systems these days (but usually unfortunately can’t). In an idealized codebase that only seasoned financial programmers are allowed to touch, it can go well, but such a system is usually either overly exclusive or risks becoming brittle.
- lawlorino 4mo ago> I consider running from “amounts as integer” systems these days (but usually unfortunately can’t). In the context of Fintech, how do you otherwise resolve floating point rounding issues if not representing amounts with integers?
- lxgr 4mo agoNative decimal types, if your system has them. Many languages and databases used in financial contexts do.
- Maxatar 4mo agoBut native decimal libraries are almost always floating point. Do people not know what a floating point number is?
- lxgr 4mo agoThat’s alright, the important part here is that they’re decimal, not binary. You don’t want 0.1 + 0.2 to equal 0.300…004.
- Maxatar 4mo agoThere are pretty trivial ways to use binary floating point values that don't result in 0.1 + 0.2 producing 0.30000...4 and it saddens me when this topic comes up and people go to such extreme lengths to recreate a second hand buggy reimplementation of a subset of floating point numbers to do it.
- worik 4mo ago> There are pretty trivial ways to use binary floating point values that don't result in 0.1 + 0.2 producing 0.30000...4 Not across all architectures and operating systems there are not Listen to those who have done this. Use integers for finance.
- Maxatar 4mo agoYes across all architectures and OS's that use IEEE 754 floating points.
- FabHK 4mo agoWhat are those pretty trivial ways? And how are they better than storing 10 cents + 20 cents = 30 cents?
- simpsond 4mo agoAn integer for the value (scaled by number of decimals) and an integer value for the number of decimals. Different systems may use different values, even for the same currency or asset.
- Maxatar 4mo agoWhat exactly do you think a floating point number is?
- lxgr 4mo agoUsually that, but in binary, which causes lots of headaches for financial math.
- Maxatar 4mo agoFor those who don't understand what they're doing, yes. But those people end up having headaches and causing trouble no matter what.
- CyberDildonics 4mo agoSo all the people who write financial software and avoid floats don't know what they're doing? That's would end up being just about everyone. You should teach them, you know so much more than they do.
- dgunay 4mo agoAll of the data we control (in the database, in our apis, etc) is integer cents. When we have to interface with a system that represents money using JSON numbers as dollars.cents, we parse or serialize it into an arbitrary precision decimal type. Hasn't been much of a problem.
- morpheuskafka 4mo agoI'm sure there is something I don't know here, but how is working with integers "brittle"? The only issue I see is rounding down by default, not sure if that is even an issue or not. At any rate, it seems a lot less brittle than floats or bigdecimal style number classes.
- lxgr 4mo agoThe brittleness comes from the fact that the number of implied decimal digits per currency isn't always well-defined across all stakeholders and systems. If you're only working in a single currency, there's usually no issue.
- foresterre 4mo agoAs a general rule, you always include the currency code (EUR, SEK, USD etc.) and if possible also the amount of decimals, when using minor units. Currency codes can be found in ISO 4217.
- lxgr 4mo agoYes, definitely always include the number of digits, but at your system boundary you still have to pray that whoever you're working with isn't silently dropping that number and re-deriving it from their own, almost-4217-compliant currency database. Redundancy can be great, but it's not a panacea, since it's not guaranteed to be used in an optimal way.
- zdragnar 4mo ago> JSON doesn’t have floats, it has numbers, and how they’re used after being parsed is not part of the spec. I think that's the problem they were trying to describe. Without a formal spec, systems won't agree on how to handle floats. JS engines treat numbers as 53 bit signed floats, so passing a well defined decimal there through JSON means losing precision at the edges. Money stored in integers gets around the issue by simple virtue of not really needing more than 53 bits to accurately represent the values anyone is going to encounter. There are downsides like all the extra math or functions to handle doing the math everywhere money is manipulated or displayed, but this is the sort of thing where static typing is really helpful, and isn't too hard for juniors to understand that they should always use money functions to work with money data.
- dotancohen 4mo agoWith I need to represent monetary amounts through JSON, I encode it as a base 10 string and wrap it in quotes so that the JavaScript engines treat it as a string. Conversion back to int happens after the string has been parsed and validated. I do this with HTTP GET and POST form requests as well. In HTTP, everything is a string (even if that string is JSON).
- worik 4mo ago> JS engines treat numbers as 53 bit signed floats Please do not use Javascript for finance applications. Just do not do it Save it for user interface elements and dancing whizzimagigs, where it will do less harm.
- zdragnar 4mo agoExcel does the same thing, and has been used to track money for decades. Somehow, we're all still alive.
- lxgr 4mo agoFinancial applications need user interface elements too, and doing these poorly has caused quite some [1] harm in the past... [1] https://financialregulation.linklaters.com/post/102j8af/the-citi-fat-finger-fines-and-ui-design https://financialregulation.linklaters.com/post/102j8af/the-...
- dahart 4mo agoWhat are you referring to with the integers/floats comment? The article says clearly that the rule of thumb is not to use floats and that they’re “almost never” a good idea, that they cause unpredictable precision loss, and recommends integer or BigDecimal types in multiple places. Are you also talking about rationals? So what is the bad advice here, exactly? For FX, it seems like you’re reinforcing what the handbook says, that there’s no canonical rate. Aside from that, it’s talking about post-resolution records and you’re talking about how to resolve, no? That’s valid nuance of a separate goal, and it’s a fine goal of yours, but doesn’t seem like a demonstration of something missing or wrong. The article appears to make the very same point about immutability? What are you saying that’s different?
- solumos 4mo agoWith integers/floats, he's saying it's not opinionated enough. Anything other than integers with minor-unit precision, unless you have a very good reason, is a bad idea. So "floating point is almost a bad idea" doesn't go far enough, and the other alternatives are presented somewhat equally. The FX critique is saying that it's glossing over a lot of the complexity. I'd say the same is true for the treatment of DE ledgers, and it borders on bad advice (e.g. "Balance is never stored. It’s derived from the movements of money.")
- dahart 4mo ago> Anything other that integers with minor-unit precision, unless you have a very good reason, is a bad idea. The article clearly communicates this sentiment, no? What else needs to be said? How much further does it need to go, and why? It might be a mistake for either us or the handbook to be absolute or dogmatic about floats. It’s not a sin to mention that they exist, and it’s a fact that some people in fintech use them for some reasons that have a defensible engineering position and well considered tradeoffs. I’ve been on the side of assuming people don’t use floats for money and then been surprised when I bumped into people here on HN who report using floats in finance routinely. BTW, is your quote “almost a bad idea” a typo? There’s a world of difference between ‘almost a bad idea’ and ‘almost always a bad idea’. The actual words in the article, if we’re quoting the article, are: “almost never a good idea” in reference to using floating point types. > it’s glossing over a lot of the complexity. Of course it is, that’s a good thing. It’s not pretending to be a spec or rules, it’s an introduction and general principles. The article is already introducing new complexities that people outside of fintech might not be aware of. But do we really have to mention ALL complexity? The biggest problem with Wikipedia is that it’s overrun by nuance and complexity, so much that you often can’t read an article on a topic without already being an expert on that topic. This is why experts are often bad teachers. Being unable to gloss over some complexity is not good for learning and doesn’t make a good environment for newcomers. Let’s allow people to write for non-experts and make room for learning. We don’t have to avoid glossing over some of the complexity; it’s useful to get the general direction and gist correct while leaving out some of the detail. > it borders on bad advice Be specific. What’s wrong? Note that contributions are invited.
- skipants 4mo agoThat was the first thing that popped out and made me distrust the whole wiki; there's only One Right Way to store money (as integers[1], as you said) and it should have been explicit about that. You can also use fixed-point if whatever you're using supports it but it's still technically integers.
- m00x 4mo agoYou can't do everything you need with an integer. There are values you might want to display or calculate with that are smaller than cents. In some places you'll need things like BigDecimal, which are immune to floating point errors in most cases. It's also safe to return decimal values for displaying values.
- solomonb 4mo agoThe integer `1` can mean whatever you want, it doesn't need to be a cent. Haskell's `Fixed` type is a good example of this: https://hackage-content.haskell.org/package/base-4.22.0.0/docs/Data-Fixed.html#t:Fixed https://hackage-content.haskell.org/package/base-4.22.0.0/do... Its a wrapper around an `Integer` where you declare the scale in the type. So if you use `Fixed E2` as your type then `MkFixed 1` is 1 cent. If you did `Fixed E3` as your type then `MkFixed 1` is 0.1 cent. In both cases it is entirely an integer encoding.
- FabHK 4mo agoBut it's a good idea to keep those values distinct from actual money. You can't pay a fraction of a cent to anyone.
- fauigerzigerk 4mo agoBut the price of some unit of a commodity may well be expressed in smaller fractions to allow for small price changes. You could argue that a price is not really an amount that anyone can actually pay and that's true. But it seems complex and error prone to store unit prices and amounts using different scaling factors.
- m00x 4mo agoIf you're calculating stock gains, taxes, etc. You'll want to do it on BigDecimal on line items, then sum it up. Cents could lose precision leading to a large difference on millions of line items. If you're doing static payments or displaying a number, it doesn't matter if it's float amounts or integer cents since you're not doing any calculations anyway. Stripe uses cents mostly because it's the most foolproof way that won't cause massive issues as a public API.
- deleted 4mo ago[deleted]
- oddthink 4mo ago> E.g. If I ever see a monetary value stored in something else than integers I'm going to run away screaming (thank you Rust decimals represented as JSON floats). It's always integers unless you have a VERY good reason to do otherwise (though exported view can be in anything, even in weird bitcoded formats). That really overstates the issue. Whole domains of finance run just fine on doubles. If you're doing Monte Carlo options pricing over interest rate paths, and you're interested in the risk metrics, like durations, convexity, vega, and so on, no one cares what your rounding convention is. doubles are just fine, thank you. How are you going to force `exp(-rt)cashflow` to be an integer? Or the normal CDF? Yes, there are domains where ints make sense. But it's certainly not universal, you just need to make the right engineering choice.
- quibono 4mo agoI love how this sensible take is followed by a tornado of comments that boils down to "NEVER use floats JUST BECAUSE".
- worik 4mo agoNever use floats for financial calculations. Because hard won experience. "Floats" are simulations of Real Numbers, and Reals are uncountable. Not what you want for finance, where everything is counted.
- quibono 4mo agoI suggest reading the comment I was replying to since it contextualises the answer quite well. Hard to find absolutes in real life outside of thermodynamics.
- rnagulapalle 4mo ago[flagged]
- ViscountPenguin 4mo agoIt can be really frustrating viewing threads like this sometimes. I've not once seen an interest rate swap priced in anything other than float/double, and that's relatively simple even compared to some of the crazy instruments out there. Like, sure, probably don't use floats for everything, but what are the odds that your greeks are gonna be nicely expressable as simple rationals?
- sho 4mo ago> It's always integers unless you have a VERY good reason to do otherwise I don't really agree. This seems like one of those outdated "greybeard rules" which people love to cargo cult, but to me it just comes with its own set of trade-offs, like now you have to think about exponents everywhere and getting them wrong comes with orders-of-magnitude consequences. If you have a modern DB and your languages handle its decimals well then I'd use them. You can translate as needed for imports and exports, but the core of your system is always sound. Switch to the more basic formats if and only if there was some perf problem with decimals, which for most fintechs will be a VERY long time with modern DBs. What really pushes me towards decimals is the consequence of getting something wrong. Relying on comparing raw ints, with variable exponents baked in, can lead to catastrophic errors with multi-order-of-magnitude gaps if that implicit exponent isn't carried along correctly. It's a massive footgun always waiting to happen. Decimals avoid that whole class of problem. So the goal is to maximise the "safe" decimals as source of truth everywhere you can, and have very well-tested "in and out" paths for any producers or consumers with different representation preferences. To me, that's good system design. And when, not if, you're manually inspecting DB records to track down a bug, having everything normalized in a glanceable, obvious format like decimals will let you recognise errors faster and more intuitively. This goes extra for crypto, especially stablecoins, where one USD stablecoin might be exp-6 and another might be exp-9. And you're representing them in the same DB! Off by a factor of a thousand if you miss that exponent! Decimalize that immediately says I.
- deleted 4mo ago[deleted]
- advertum 4mo ago[flagged]