docs(0237): the RFP float-vs-decimal-string answer, recorded - #287
Merged
Conversation
The RFP types Current Price as a float; we publish it — and every numeric field — as a decimal string, per the §3.3 precision design. The deviation was never written down, so it would have been improvised at review time. docs/scf/milestone-2-rfp-deviations.md now carries it, alongside the other two M2 deviations already decided: the X-Cache wording and USDC's exclusion from the backfill spot-check. Standalone rather than folded into 0128, which has not started — the same reasoning 0248 and 0122 settled. The argument does not rest on first principles. ADR 0011 records a measured production defect caused by exactly this: deriving through toFloat64 returned a close BELOW its own low by 1.343e-11 at BTC 1h, 0.92 of one float64 ulp, on a value carrying 19 significant digits against float64's 15-16. That was one internal conversion; publishing floats would impose it on every consumer, on every field. The affected assets are real — 7e-8 on RON, and a close of 5e-14 five ticks above the Decimal(38,14) floor — and 0120 already verified that the string form survives the JSON round-trip. Also states what the task's own wording did not: the answer covers every Decimal-valued field, not just the one the RFP names, and a consumer who wants a float can still parseFloat while the reverse is unrecoverable. The OpenAPI now says this on price_usd itself rather than only in the API-level blurb. Fixes one leftover from PR #283 in passing: the SdexStream schema description still said the archive walks the ledger history "in order".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The RFP's Asset Metadata Required list types the field as
Current Price (float USD). We publish it — and every numeric field — as a decimal string, per the §3.3 precision design. The deviation is almost certainly right; what was missing is a recorded answer, so it would have been improvised at review time rather than defended from evidence.New:
docs/scf/milestone-2-rfp-deviations.md, which also gathers the two M2 deviations already decided (theX-Cachewording, USDC's exclusion from the spot-check) so 0128 folds in one file rather than three. Standalone rather than written into 0128, which has not started — the same reasoning 0248 and 0122 settled.The argument does not rest on first principles
ADR 0011 records a measured production defect caused by exactly this. Deriving a candle's extremes through
toFloat64returned aclosebelow its ownlowby 1.343e-11 at BTC 1h — a malformed candle by thelow <= open,close <= highrule every charting library assumes. The mechanism is named there: float64 carries ~15-16 significant digits against the 19 a five-figure price atDecimal(38, 14)holds, and the gap was 0.92 of one float64 ulp. Rounding cannot fix it — a 14-decimal half-tick is 2,700× too small.That was one internal conversion. Publishing floats would impose it on every consumer, on every field, on every request.
The affected assets are real, not hypothetical: 7e-8 on RON (measured on prod during 0123) and a
closeof 5e-14, five ticks above theDecimal(38, 14)floor. Those are the long-tail assets the RFP asks us to cover, and a float round-trip destroys their low-order digits while still parsing and still looking plausible.And the alternative is already tested — 0120's conformance suite verified that
Decimal(38,14)strings parse everywhere and survive the JSON round-trip.Two things the task's own wording did not say
vwap_24h,volume_24h_usd, thesourcesvalues, every OHLCV O/H/L/C. Answering only aboutprice_usdwould invite the same question again.parseFloatour string and get exactly what the RFP's reading would have delivered. The reverse is not recoverable — had we published a float, no consumer could restore digits the serialisation had already destroyed.Also
price_usditself, not only in the API-level blurb.SdexStreamschema description still said the archive "walks the ledger history in order". It walks backward.