spread_bps vs vs_mid_bps: reading FX quotes in basis points
Modan's rate responses carry two numbers in basis points that look alike and mean different things. One tells you how a provider compares with its peers; the other tells you how far the market as a whole sits from a neutral reference. Confusing them produces confident, wrong conclusions.
Updated 2 Sep 2026 · 5 min read · by Modan
A basis point
One basis point (bp) is one hundredth of one percent: 100 bps = 1%. FX is quoted in basis points because the differences that matter are small in percentage terms and large in money terms. On a transfer of 10,000 units, a 50 bps difference is 50 units.
spread_bps: distance from the best of its kind
spread_bps is how far a provider's rate sits below the best rate of the same rate_type on that corridor at that moment. The best quote of each kind carries 0.0; everyone else of that kind carries a positive number. It is computed within a rate type on purpose: a retail quote is measured against the best retail quote, an interbank print against the best interbank print, and an official reference is never in the comparison.
Suppose the best retail quote on a corridor is 1,900 and another provider quotes 1,881. Its spread is (1,900 − 1,881) ÷ 1,900 × 10,000 ≈ 100 bps. The number says nothing about whether 1,900 itself is a good price — only that this provider is about 1% behind the leader.
spread_bps = (best_rate_of_same_type − rate) / best_rate_of_same_type × 10,000 0.0 = best of its kind; a corridor with two rate types carries two zeros
vs_mid_bps: distance from an independent reference
vs_mid_bps is how far a rate sits from an independent mid-market reference that Modan sources separately from every provider and refreshes hourly. It is signed: negative means the quote is below the mid (the customer receives less than the reference implies), positive means above. Because the reference is not a provider, this number is the one that answers "is this market expensive right now?".
The mid is crossed through USD from the reference feed, so any fiat pair the feed quotes on both legs has one; a crossed mid is timestamped with its staler leg, never the fresher one. Stablecoins are the exception: no fiat reference feed quotes USDT or USDC, so on those corridors vs_mid_bps is omitted rather than estimated. The mid_source field in every response names the feed.
Which one to use
- Choosing a provider for a transfer: sort by
spread_bpswithin executable quotes, then check the fee — or let the convert endpoint compute the net amount per provider. - Benchmarking a desk, a bank or a whole corridor: use
vs_mid_bps. It is the only measure anchored outside the providers themselves. - Reading market structure: the gap between the best and the worst executable quote (the *Dispersion* tile on every corridor page) shows how fragmented pricing is on that corridor right now.
Where the numbers appear
Both fields are on every provider entry returned by /rates, /convert, the fetch-* endpoints and the MCP tools, and both columns are on every corridor page. The same definitions apply everywhere; the API documentation has the field-by-field reference.
Frequently asked questions
- Can spread_bps be negative?
- No. It measures distance below the best rate of the same kind, so the best quote of each rate type carries 0.0 and every other quote of that type carries a positive number.
- Why does one corridor show several 0.0 spreads?
- Because spread is measured within a rate type. A corridor with retail quotes, an interbank print and an official reference has a best of each kind, and each best carries 0.0. Only executable kinds compete for the Best tag.
- Is vs_mid_bps the provider's fee?
- No. It is the distance between the quoted rate and an independent mid-market reference. A provider's explicit fee is a separate field; the convert endpoint combines rate and fee into the net amount delivered.