Skip to content

Connection security

Crypto API decimal precision: preserve the intended value

A clean-looking 0.28 request can begin as an intended 0.29 order. Trace decimal values through parsing, arithmetic, normalization and serialization.

Ivory precision comb slots guide a pale lime ribbon while an ivory ribbon bends out of alignment on a dark surface.
Illustration for connection security; examples in this article are educational.

Crypto API decimal precision means preserving the intended price, quantity and fee values while parsing, calculating and serializing a request. Keep decimal strings intact at the boundary, use decimal arithmetic or an exact scaled-integer representation, and apply the instrument's increment rules separately. Formatting a binary floating-point result to look tidy does not prove the submitted value is correct.

A precision error can change an order even when the final request looks plausible. The most useful diagnostic is a trace from the original text to the exact submitted text, with every conversion and rounding decision visible. This guide develops that trace using fictional values; it does not claim that KLINEO implements the example pipeline.

Three questions hidden inside “precision”

First ask whether the program preserved the number it received. Binary floating point approximates many decimal fractions, including 0.1. Displaying fewer digits can conceal the approximation without changing the stored value. This is a representation property, explained in Python's floating-point tutorial, rather than evidence that an exchange has returned bad data.

Then ask whether the number belongs to the instrument's permitted grid. Binance Spot defines separate price and quantity filters: its documented checks include price modulo tick size and quantity modulo step size being zero. Those are increment rules, not simply a count of decimal places. See the Binance Spot filter definitions.

Finally ask what the field means. An exact decimal in the wrong unit remains wrong. Bybit's V5 place-order documentation specifies qty and price as strings, but also describes product-dependent quantity units and a marketUnit choice for spot market orders. The Bybit request-field reference is evidence for that API, not a universal contract for every venue. Resolve the market and unit with the symbol and contract identifier guide before applying any scale.

The one-step error that survives a clean-looking request

Assume a fictional spot order requests 0.29 base units, with a quantity increment of 0.01 base units and a limit price of 12.35 quote units. The intended quantity already lies on the grid: 0.29 divided by 0.01 is exactly 29 in decimal arithmetic.

Now consider a JavaScript implementation that parses both fields as ordinary Number values, divides quantity by increment, floors the result and multiplies back. Running Math.floor(0.29 / 0.01) * 0.01 produces 0.28 in this worked check. The division evaluates to 28.999999999999996, so flooring removes a whole permitted step.

Trace pointDecimal-preserving pathBinary floating-point path in this example
Source quantity text"0.2900""0.2900"
Increment text"0.01""0.01"
Quantity divided by incrementExactly 2928.999999999999996
Floor to whole steps2928
Submitted quantity text"0.29""0.28"
Limit notional at 12.353.5815 quote units3.4580 quote units

The difference is 0.01 base units and 0.1235 quote units. Every value is hypothetical; these are not current instrument settings or expected returns. Both final quantities fit the invented increment, so checking only the final grid would miss the unintended change.

This is why “the exchange accepted it” is an incomplete correctness test. Acceptance cannot show that the application's transformations preserved the authorized quantity. Adding an arbitrary tiny constant before flooring may hide this fixture while creating different behavior near another boundary. Define the arithmetic and rounding policy explicitly.

Preserve text before choosing a numeric representation

For a field documented as a decimal string, retain its original text and parse directly into the chosen exact representation. Converting text to a binary float first and then constructing a decimal preserves the intermediate float's value, including its approximation. Python's decimal arithmetic documentation demonstrates that distinction between construction from strings and from floats.

Two common designs are decimal arithmetic with a defined precision and rounding context, or integers measured in a specified smallest unit. For the fictional quantity above, a scale of 100 represents 0.29 as integer 29 and 0.01 as integer 1. The scale belongs to the field and instrument; it cannot be copied blindly to a price, fee or different contract.

Neither design eliminates limits. Decimal arithmetic needs sufficient working precision, and non-terminating division still needs a policy. Fixed-width integers can overflow; scaled integers also need a defined treatment when division leaves a remainder. Keep those conditions visible as validation outcomes rather than silently truncating them.

A string is only a container. Validate the endpoint's allowed grammar and the field's semantics: missing text, non-finite values, negative quantities and unsupported exponent notation must not slip through just because a parser accepts them. Whether zero is valid depends on the particular field and API operation.

Normalization needs its own decision record

An increment of 0.05 allows 0.25 and 0.30, but not 0.29, even though all three have two decimal places. If a candidate fails the grid, preserving it exactly has succeeded at representation and exposed a separate problem.

Record the original candidate, rule snapshot, selected rounding policy, normalized candidate and reason for the change. Redo dependent calculations on the normalized values. Lowering a price or quantity can alter order behavior; raising one can exceed the original commitment. A generic round-to-nearest function has no knowledge of that intent.

This article stops at preserving values and making transformations explicit. The exchange order minimums worksheet handles the different question of whether any valid quantity can fit a budget and the venue's minimums. Exact arithmetic cannot make an infeasible order feasible.

For AI-generated proposals, the same boundary belongs outside the model. The structured output validation guide explains why parseable fields still require independent numerical and policy checks.

A reusable round-trip worksheet

Test one field through every component that touches it, including the database, queue, SDK and serializer. The following fixtures are proposed engineering checks, not reports of KLINEO test coverage.

FixtureEvidence to captureExpected decision
"0.2900" with increment "0.01"Original, parsed value, step count, submitted textPreserve numerical value 0.29 without losing a step
"0.29" with increment "0.05"Exact remainder and configured normalization policyReject or create an explicitly revised candidate
Very small positive amountText before and after every transportDo not collapse to zero or unsupported notation
Fee with more places than the UI showsRaw fee and accounting valueKeep accounting detail; round only the display as intended
Missing, non-finite or prohibited signed inputParser result and validation reasonStop before request serialization

Numerical round-trip equality does not require identical spelling: "0.2900" and "0.29" denote the same decimal value. Preserve original text for provenance while defining separately what the endpoint accepts on submission. Avoid sending locale formatting such as grouped thousands separators merely because it looks correct in a report.

Precision also matters on the return path. Sum execution and fee values with their asset units attached, and keep display rounding out of the accounting ledger. Exact sums over an incomplete history are still incomplete; the API pagination and history guide addresses retrieving the records being summed.

When a discrepancy appears, find the first boundary where the numerical value or unit changed. That gives a concrete repair target: parsing, calculation, normalization, persistence or serialization. A polished final number alone cannot provide that evidence.

Prepared with AI assistance on 23 October 2026 under the editorial policy. Official API and language documentation supplied the factual basis; the JavaScript failure case and decimal worksheet were checked locally. No live order was placed.

Keep the context with the example.

Each worked example is illustrative, with its sources and assumptions in the article. Read our editorial standards for authorship, verification and corrections.