Live data from Hacker News

Fintech engineering mistakes (2022)

startupwin.kelsus.com

51–60 of 112 posts

Re: Fintech engineering mistakes (2022)

#51
post #21

I’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…

> — Use TIMESTAMPTZ. Always. When you’re using JSON to pass around datetime data, Use ISO8601 date and time with offset info, always. e.g. "transactionDate": "2023‐06‐28T15:55:22.511Z"

> Use ISO8601 date and time with offset info, always.

I think that's just sufficient for all use cases everywhere. I've been a software engineer for almost 25 years and, of all the universal truths I've encountered, implicit and unintended changes to datetime offset are the ones I've seen at every single job.

Re: Fintech engineering mistakes (2022)

#52
post #51

Earlier quoted context omitted.

> — Use TIMESTAMPTZ. Always. When you’re using JSON to pass around datetime data, Use ISO8601 date and time with offset info, always. e.g. "transactionDate": "2023‐06‐28T15:55:22.511Z"

> Use ISO8601 date and time with offset info, always. I think that's just sufficient for all use cases everywhere. I've been a software engineer for almost 25 years and, of all the universal truths I've encountered, implicit and unintended changes to datetime offset are the ones I've seen at every single job.

As I put in another comment, your class library might have a type that is equivalent to ISO 8601 data, indeed is convertible to and from it, but is a binary representation at runtime compatible with other types in the language.

So this technically isn't ISO8601, and certainly isn't "ISO8601 in a string", which is an _interchange format_ between application with potentially very different runtimes. I don't really recommend treating ISO8601 dates as mere strings, unless you intend to pass them through without even looking at the contents.

I refer to https://learn.microsoft.com/en-us/dotnet/api/system.datetime...

Use types that support ISO8601 with an offset, always.

The docs even say that, even if many are not aware:

> consider DateTimeOffset as the default date and time type for application development.

https://learn.microsoft.com/en-us/dotnet/standard/datetime/c...

Re: Fintech engineering mistakes (2022)

#53
I'm surprised the article doesn't explain how float numbers are stored in memory according to IEEE that's the main reason you don't use them to represent money.

If you are an engineer who doesn't know what a mantissa is, stop two minutes for a cool ride https://lashewi.medium.com/storing-currency-values-and-float...

Re: Fintech engineering mistakes (2022)

#54
post #2

You 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.

It's sufficient for quantitative finance and trading but not for accounting. For financial engineering and modeling it doesn't matter if results are a few fractions of a cent off as long as your profit margins/model tolerances are greater than the error, because your broker/bank/exchange will keep track of the exact values in your account. But if you are building a bank/broker/exchange, then tracking it precisely enough for GAAP is now your problem.

Re: Fintech engineering mistakes (2022)

#55
post #21

I’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…

"— 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.)."

I'd go a step further and prefix the strings with an ISO currency code ... to stop someone from just feeding it into their languages int to float converter and assuming that's ok. Only custom built (hopefully safe) converters will work.

Re: Fintech engineering mistakes (2022)

#56
post #45

Earlier quoted context omitted.

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 have worked at banks and fintechs for the past 30 years and honestly have never used anything but a doubles for money with no issues (and a simpler code base.) I understand the sentiment and the potential issues, but it's really kind of domain dependent.

Is storing $1.05 really that much simpler than storing something as 105? Use a long to store money, pretty easy.

Re: Fintech engineering mistakes (2022)

#57
post #55
post #21

I’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…

"— 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.)." I'd go a step further and prefix the strings with an ISO currency code ... to stop someone from just feeding it into their languages…

Ergh, I get what you're trying to prevent, but this actively breaks those custom safe parsers we build, and now you have to do some additional active parsing. Please don't do this, just set contractual expectations in your API.

Re: Fintech engineering mistakes (2022)

#58
Have built a fintech startup here in Germany ten years ago. The article mentions lots of important things. Here‘s another one:

Time synchronization. It is incredibly important in fintech applications for a number of reasons:

1. *Transaction Ordering:* Financial transactions often need to be processed in the order they were initiated. This is especially crucial in high-frequency trading where trades are often made in milliseconds or microseconds. A small difference in timing could potentially lead to substantial financial gains or losses. Therefore, accurate time synchronization ensures fairness and order in the execution of these transactions.

2. *Security:* Accurate timekeeping helps in maintaining security. For instance, time-based one-time passwords (TOTPs) are widely used in two-factor authentication systems. These passwords are valid only for a short period of time and rely on synchronized clocks on the server and client side.

3. *Audit Trails and Dispute Resolution:* Timestamping transactions can help create a precise audit trail, which is critical for detecting and investigating fraudulent activities. In case of any dispute, a detailed and accurate transaction history backed by synchronized time can help resolve the issue.

4. *Distributed Systems:* In distributed systems, time synchronization is important to ensure data consistency. Many financial systems are distributed over different geographical locations, and transactions need to be coordinated between these systems in an orderly fashion. This requires all servers to have their clocks synchronized.

I am sure there are even more fields where this is relevant.

Re: Fintech engineering mistakes (2022)

#59
post #51

Earlier quoted context omitted.

> — Use TIMESTAMPTZ. Always. When you’re using JSON to pass around datetime data, Use ISO8601 date and time with offset info, always. e.g. "transactionDate": "2023‐06‐28T15:55:22.511Z"

> Use ISO8601 date and time with offset info, always. I think that's just sufficient for all use cases everywhere. I've been a software engineer for almost 25 years and, of all the universal truths I've encountered, implicit and unintended changes to datetime offset are the ones I've seen at every single job.

> I think [ISO8601 date and time with offset info is] sufficient for all use cases everywhere.

TLDR: Also, which timezone is used (not quite the same as offset) really does matter--UTC is great but you can't use it everywhere.

________

One of my favorite simple examples of this "here be dragons" for the new developer: Any system that schedules a future calendar-event.

Such events are typically pegged, implicitly if not explicitly, to a particular timezone or geographic context. For example: "The company's Virtual Summit will occur on November 2nd at 1PM Elbonian Xtremesunshine Time, hosted out of our central Elbonian headquarters."

In that scenario, it is impossible to know for sure how many seconds-from-now it will happen until the moment actually happens! "2023-11-02 13:00:00 EXT" is actually a contract or spec for recognizing a future condition, one that will shift if/when the relevant nation/province/city simply declares their clocks shall be set differently.

So if the Elbonian government alters their daylight-savings switchover to occur earlier on 11-01 instead of 11-06, then the summit just moved. Even if you scheduled everything UTC all along... Well, now the summit is overlapping lunchtime for everyone in Elbonia, so it moved from their perspective.

Re: Fintech engineering mistakes (2022)

#60
post #13

Earlier 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…

> Can you confidently say that $100>¥10 in an offline environment?

Money is never converted. It is exchanged. Trying to solve this is like trying to solve the question "Is "100 USD" > "1 LAPTOP".

When you turn 100 USD into 90 EUR, you didn't convert it. You exchanged it. You bought EUR, at a price given to you by someone or something exchanging it. This could be a bank, a well-established currency office, or some dude on the street. There is no real difference between all three of those: The third party gave you a price, and now has more USD and less EUR, whereas you have more EUR and less USD.

There are various entities publishing standardized average rates which are calculated after the day closes, based on a variety of datapoints they have access to. Those are often used in eg. accounting, to establish the "real" value of something you bought in a currency you don't often use, but it's not true conversion.

If you have, as a datatype, a currency becoming another, there is ALWAYS a "rate" attached to this. So the question "$100>¥10" you asked above requires more data, it should be "$100>¥10 @ 144.28". ANYTHING else is a terrible leaky abstraction. Don't do it. Source your rates automatically from a single source if you like, but make it explicit.

Anyway, a "Money" object really is just this: A precise decimal object, with an ISO currency code. The latter simply being a short string among an included, limited set.

Post reply on HN