Shit, I wish I read this prior to my interviews at Cash App.
Fintech engineering mistakes (2022)
41–50 of 112 posts
Re: Fintech engineering mistakes (2022)
#42I’d also add: — If you’re using JSON to pass around monetary quantities (eg. from the frontend to the backend), put them in strings as opposed to the native number type. You never know what the serializers and deserializers across languages will do to your numbers (round them, truncate them etc.). — Start recording the currency of the transactions as early as possible. It can be a separate column in your table. — Use…
I'm generally not a fan of overloading fields, but we took the opportunity to add the currency code when we decided to encode monetary quantities in JSON as strings, e.g. "0.02USD". This has worked well, particularly because we use a money handling library that parses it unchanged.
But since this is not a human visible field, this is probably irrelevant, right?
Re: Fintech engineering mistakes (2022)
#43Earlier quoted context omitted.
It would be neat to have a fundamental "money" primitive alongside int, float, string, etc. It might not be simple to implement, though. Off the top of my head, * Can you confidently say that $100>¥10 in an offline environment? * You'd need to support different bases for splitting units to deal with eldritch values such as farthings. * Where is the line drawn? Is a Bitcoin a valid currency? A gold Krugerrand? A bundl…
"Can you confidently say that $100>¥10 in an offline environment?" A major problem money has is that it isn't a unit in the sense we usually take the term to mean. We expect, for instance, that translating one unit to another with a suitable level of precision should be translatable without loss back to the original unit, but that's not true for money, even ignoring transaction costs. If "US dollar" is a unit, it is…
Re: Fintech engineering mistakes (2022)
#44Earlier quoted context omitted.
I'm generally not a fan of overloading fields, but we took the opportunity to add the currency code when we decided to encode monetary quantities in JSON as strings, e.g. "0.02USD". This has worked well, particularly because we use a money handling library that parses it unchanged.
Do you always put the currency behind the number? I know some countries prefer the currency infront (e.g. USD), others behind (EUR). But since this is not a human visible field, this is probably irrelevant, right?
https://ux.stackexchange.com/questions/9105/international-cu...
So we put the ISO code at the end and ignore whitespace. But including a prefix sign as with `€1.234.567,89 EUR` would break it.
Re: Fintech engineering mistakes (2022)
#45This is a great little article, and I can't emphasize what a big deal #2 is.
Some folks will laugh at this advice. Others (like me) will cry because we know of multibillion-dollar fintechs that still struggle with this. The one I'm thinking of didn't even have cents for a long time. After a pretty heroic migration effort they added cents. And they did it properly. But within weeks folks were using floats all over the place for money, leading to flaky tests and all kinds of other errors.
I understand the sentiment and the potential issues, but it's really kind of domain dependent.
Re: Fintech engineering mistakes (2022)
#46Earlier quoted context omitted.
For example 16.10 is not exactly 16.10 in IEEE floating point. When you do enough operations, and depending on the order of operations, you can wind up several cents off. That sounds small, but can be enough to give your auditors heart-burn. COBOL does BCD arithmetic, (not really but at least conceptually), and it's penny accurate to 31 digits (as per the standard - implementations may have greater accuracy). Frankly…
It would be neat to have a fundamental "money" primitive alongside int, float, string, etc. It might not be simple to implement, though. Off the top of my head, * Can you confidently say that $100>¥10 in an offline environment? * You'd need to support different bases for splitting units to deal with eldritch values such as farthings. * Where is the line drawn? Is a Bitcoin a valid currency? A gold Krugerrand? A bundl…
At a bare minimum, it should be a reasonable fixed point type that correctly handles rounding and intermediate values. So a dollar amount like 123.45 times a rate like 0.3450 doesn't exceed 4 decimal places but intermediate values are extended so we get correct rounding. The destination should probably determine the number of places. That bare minimum wouldn't stop you from comparing yen to dollars, any more than a floating point representing mph stops you from comparing it to a value representing kph.
But there are times where we need to track prices to the nearest tenth or hundredth of a cent. So it should be extensible so that 123.456 dollars * 0.3450 winds up at a correct round/decimal places.
You also don't need always-on, real time currency conversion. You could have a conversion type, operator, or method that does safe conversion based on the value I give it. So if I estimate that Yen are about 130 to the dollar, I can just use that. If I happen to write an application that queries a data provider and can populate that in 'real time,' that's up to me.
If you really wanted, you could find a way to create new types that represent currencies that aren't part of the basic implementation. That might mean you need to specify some things like the representation for different locales, or the default number of digits.
Re: Fintech engineering mistakes (2022)
#47Earlier quoted context omitted.
I'm generally not a fan of overloading fields, but we took the opportunity to add the currency code when we decided to encode monetary quantities in JSON as strings, e.g. "0.02USD". This has worked well, particularly because we use a money handling library that parses it unchanged.
Do you always put the currency behind the number? I know some countries prefer the currency infront (e.g. USD), others behind (EUR). But since this is not a human visible field, this is probably irrelevant, right?
Re: Fintech engineering mistakes (2022)
#48Earlier quoted context omitted.
Do you always put the currency behind the number? I know some countries prefer the currency infront (e.g. USD), others behind (EUR). But since this is not a human visible field, this is probably irrelevant, right?
It’s probably fine, but this sort of thing is why transactionAmount and transactionCurrency are better when separated. Consider the case when you’re doing some reporting from your DB based on currency; do you really want to have to deal with one string that contains both or just do a simple WHERE clause?
Re: Fintech engineering mistakes (2022)
#49One more: Timezones Various platforms use: UTC, the user’s timezone as set in their dashboard, the user’s detected timezone, the timezone of the server that is generating the reports. Aggregating or reconciling data from different platforms can be a pain if the timezones aren’t clearly indicated. I’ve had bank statements that didn’t agree to CSV exports of the same data because the servers generating the two reports…
Haha yeah for the past tax year I I looked at my transaction history and it was missing some that I expected to be there. Turns out, the exchange (Gemini, for crypto) uses UTC, but the IRS docs always tell you that a cutoff is relative to your own time zone. The transactions were in the late evening on New Year's Eve, central US time, but that was already the next year by UTC, so any readout of "transactions for 2022…
Re: Fintech engineering mistakes (2022)
#50You can absolutely use doubles for money. Excel does it and so do many other financial tools. There are pros and cons but as long as you do rounding and comparisons correctly it works perfectly fine.
At least until you need to add things, at which point you need Kahan's algorithm.