Learn / Exchange APIs

Symbol filters and minimum order sizes

Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs before acting on a number.

An order that is arithmetically correct can still be rejected, because exchanges enforce per-symbol constraints on price and quantity before an order reaches the matching engine. The rejection does not say “your size is not a valid increment” — it says the request was rejected.

On Binance that is -1013 INVALID_MESSAGE, documented as “the request is rejected by the API” for orders that fail a filter or placement check. Unhelpful on its own, and entirely predictable once you know the filters exist.

The filters

They vary in name by venue, but the categories are consistent.

Minimum notional. The order’s total value must exceed a floor. A correctly sized position on a small account can fall below it — this is the filter that most often surprises people, because the quantity looks fine.

Lot size / step size. Quantity must be a multiple of a step. 0.0837 may have to become 0.083. Not a rounding preference — the exchange rejects the unrounded value.

Price tick size. Prices must be multiples of a tick. A stop computed from a chart level frequently is not.

Min / max quantity. Absolute bounds per order.

Percent price. Limit prices too far from the current market are rejected, which catches conditional orders placed well away from price.

Max number of open orders per symbol.

On Binance these live in GET /api/v3/exchangeInfo, per symbol. They change without notice, and they differ between testnet and production — a recurring source of “it worked in testing”.

Why this breaks position sizing

The position size calculator produces:

position size = (balance × risk %) ÷ |entry − stop|

That is a real number. Exchanges do not accept real numbers — they accept multiples of a step size, above a notional floor.

So every computed size has to be reconciled with the filters, and the direction you round matters:

  • Round down and you risk slightly less than intended. Safe.
  • Round up and you risk slightly more than intended. Not safe, and it compounds if the habit is systematic.

Always round quantity down. The error is then always in the direction of less risk.

The nastier case: if rounding down puts the order below minimum notional, you have a genuine conflict. The correct resolution is not to round up to the minimum — that silently exceeds your risk budget. It is to recognise that this trade cannot be taken at this risk level on this account, and skip it.

That is an uncomfortable conclusion and it is the right one. An account small enough that minimum notional forces oversizing is an account where the stop distance or the instrument needs to change.

Precision, and the floating-point trap

Quantity and price precision are specified per symbol, and sending more decimal places than allowed is a rejection.

Worse, floating-point arithmetic produces values like 0.30000000000000004 from operations that should give 0.3. Send that where three decimals are allowed and it is rejected — for a reason invisible in your own logs, because your logging probably prints 0.3.

Two defences: do sizing arithmetic in a decimal type rather than a float, and log the exact string you are sending, not the parsed value.

A sizing routine that survives contact

  1. Compute the ideal size from risk and stop distance.
  2. Fetch the symbol’s filters — and cache them, since exchangeInfo is not free against a weight-based rate limit.
  3. Round quantity down to the step size.
  4. Check minimum notional. If it fails, skip the trade rather than rounding up.
  5. Round price to tick size — for a stop, round in the direction that makes the stop tighter, not wider.
  6. Format to the allowed precision as a string.
  7. Submit.

Step 4 is the one that requires discipline, and step 5 is the one people get backwards.

Why testnet does not catch it

Testnet symbol lists and filters do not mirror production. A symbol may not exist live; minimum notionals differ; step sizes differ.

So “it worked on testnet” carries no information about filters specifically. Verify against production exchangeInfo before going live — see Binance testnet API keys.

For AI-assisted setups

This is a good example of why a model’s output needs validation rather than trust. A model asked for a position size returns a plausible number to several decimal places. It has no knowledge of the symbol’s step size, and no reason to suspect one exists.

The correct architecture is to treat the model’s size as an input to the sizing routine above, not as the order quantity. Filters are exactly the kind of deterministic constraint that belongs in code, for the same reason risk limits do.

FAQ

What does Binance error -1013 mean?

INVALID_MESSAGE — the order was rejected before reaching the matching engine, most often because it failed a per-symbol filter: below minimum notional, not a multiple of the step size, a price off the tick, or outside the permitted percent-price band. Check the symbol’s entry in GET /api/v3/exchangeInfo.

Why is my order below the minimum size?

Because the notional value — quantity times price — is below the symbol’s floor, which is a per-symbol constraint rather than a global one. On a small account with a tight risk budget this happens legitimately. The correct response is to skip the trade rather than increasing size to meet the minimum, since that exceeds the risk you decided on.

Should I round position size up or down?

Down, always. Rounding down risks slightly less than intended; rounding up risks slightly more, and if it becomes habitual the error accumulates in the dangerous direction. If rounding down puts the order below minimum notional, that is information about the trade rather than a rounding problem.

Why did my order work on testnet but fail live?

Testnet symbol lists and filters do not mirror production — symbols may not exist, and minimum notionals and step sizes differ. Filters are one of the categories testnet specifically cannot validate, so check production exchangeInfo for the symbol before the first live order.