Skip to content

docs(0237): the RFP float-vs-decimal-string answer, recorded - #287

Merged
karczuRF merged 1 commit into
developfrom
docs/0237_rfp-float-vs-string-answer
Sep 4, 2026
Merged

docs(0237): the RFP float-vs-decimal-string answer, recorded#287
karczuRF merged 1 commit into
developfrom
docs/0237_rfp-float-vs-string-answer

Conversation

@karczuRF

@karczuRF karczuRF commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

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 (the X-Cache wording, 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 toFloat64 returned a close below its own low by 1.343e-11 at BTC 1h — a malformed candle by the low <= open,close <= high rule every charting library assumes. The mechanism is named there: float64 carries ~15-16 significant digits against the 19 a five-figure price at Decimal(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 close of 5e-14, five ticks above the Decimal(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

  • The answer covers every Decimal-valued field, not just the one the RFP names — vwap_24h, volume_24h_usd, the sources values, every OHLCV O/H/L/C. Answering only about price_usd would invite the same question again.
  • The deviation is strictly more capable than the literal wording. A consumer who wants a float can parseFloat our 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

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".
@karczuRF
karczuRF merged commit 9ca2729 into develop Sep 4, 2026
3 checks passed
@karczuRF
karczuRF deleted the docs/0237_rfp-float-vs-string-answer branch September 4, 2026 12:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant