Explainer

Bid-ask spread explained: bid, ask, mid price and spread in bps

Every quote is two prices. The gap between them is the cheapest signal of liquidity you will ever get, and most dashboards throw it away.

On this page
  1. Bid vs ask: two prices, one market
  2. The arithmetic: pips, cents and basis points
  3. How wide is normal?
  4. Why spreads widen at night and at the rollover
  5. NBBO: the best bid and offer across US venues
  6. Slippage: when the spread is not the whole cost
  7. Track the spread yourself in Python
  8. What the spread tells your code
  9. Questions

Key takeaways

  • The bid is the best price a buyer will pay, the ask is the best price a seller will accept, and the bid-ask spread is the gap between them.
  • Compare spreads in basis points (spread divided by mid price, times 10,000), not in raw price units, or a yen pair will always look wider than it is.
  • Spreads widen when fewer people are trading: pre-market and after-hours sessions, the daily forex rollover and the minutes around big releases.
  • Slippage is the extra cost when an order is bigger than the size shown at the best price and fills deeper in the book.
  • A zero, crossed or suddenly huge spread is a data-quality alarm. Check it before you chart or act on a quote.

The bid-ask spread is the difference between the highest price a buyer is willing to pay (the bid) and the lowest price a seller will accept (the ask). Open any quote from a market data API and you get both numbers. On a Monday morning in late September 2026, EURUSD quoted 1.136965 to sell and 1.137005 to buy: a spread of 0.00004, which forex traders call 0.4 pips.

That gap tells you how easy it is to trade at this moment, what a round trip costs before any fee, and whether the quote in front of you is healthy. This guide covers how to express the spread so markets can be compared, why it changes through the day, what NBBO and slippage mean, and how to track it in a few lines of Python.

Bid vs ask: two prices, one market

If you want to buy right now you pay the ask (also called the offer). If you want to sell right now you receive the bid. The mid price halfway between them is what most charts draw, but nobody actually trades at the mid. Every quote endpoint returns both sides and the size available at each:

A live forex quote from the REST API

{
  "symbol": "EURUSD",
  "bid": 1.136965,1
  "ask": 1.137005,2
  "bid_size": 85,3
  "ask_size": 61,
  "timestamp": 17905911140024
}
  1. bidBest price a buyer is offering. You sell here.
  2. askBest price a seller is asking. You buy here.
  3. bid_sizeSize available at the bid. Units depend on the market.
  4. timestampWhen the quote was observed, in Unix milliseconds (UTC).
Response of GET /forex/quote/EURUSD, captured on 2026-09-28 at 10:25 UTC. Spread 0.00004, or 0.4 pips.

A quote is not a trade. A quote is an offer that is still standing; a trade is a deal that already happened. The last trade price can sit anywhere inside, or briefly outside, the current bid and ask. The OHLC explainer shows how trades become the bars on a chart, and why a bar never tells you what the spread was.

The arithmetic: pips, cents and basis points

spread = ask − bidmid = (bid + ask) ÷ 2spread in bps = spread ÷ mid × 10,000

spread
The gap, in units of the quote currency.
mid
The midpoint most charts plot.
bps
Basis points: hundredths of a percent, comparable across markets.
EURUSD 1.136965 / 1.137005: spread 0.00004, mid 1.136985, spread 0.35 bps.

Forex traders usually quote spreads in pips. For most pairs a pip is the fourth decimal (0.0001); for yen pairs it is the second (0.01), because the yen trades at a much larger number per dollar. Our pip explainer has the full rule and a calculator. Stocks quote spreads in cents, and crypto in whatever the quote currency is.

None of those units compare across markets. Divide the spread by the mid and express it in basis points instead: one basis point is 0.01%, and a 2 bps spread costs the same fraction of a trade whether the instrument is priced at 1.13 or at 82,000. Here are five live quotes taken a few seconds apart:

InstrumentBidAskSpreadIn bps
EURUSD1.1369651.1370050.4 pips0.35
USDJPY157.0982157.10520.7 pips0.45
XAUUSD4,155.954,156.47$0.521.25
BTCUSD82,820.0082,820.01$0.010.001
US:KO (pre-market)88.1188.30$0.1921.54
REST quotes captured on Monday 2026-09-28 around 10:25 UTC. US stocks were in pre-market, which is why US:KO is so wide.

The last row is the interesting one. The same stock that trades a cent or two wide in the middle of a regular session was quoting 19 cents wide before the open: seventeen times wider than gold and sixty times wider than EURUSD in relative terms. Nothing was wrong with the data; there were simply very few people quoting it at 06:25 in New York. The after-hours and pre-market guide goes deeper on why.

How wide is normal?

There is no universal "good" spread. It depends on how many people trade the instrument and how much risk a market maker takes by standing in the middle. The most traded currency pairs and the largest stocks sit at a basis point or less; thinly traded shares, exotic currencies and small coins can be fifty times wider.

Typical spread in busy hours, basis points

  • EURUSD< 1
  • BTCUSD< 1
  • Large-cap US stock1 to 3
  • Gold (XAUUSD)1 to 3
  • USDTRY10 to 50
  • Small-cap stock20 to 100
Order-of-magnitude ranges during liquid hours, for intuition only. Measure your own instruments before relying on a number.

Why spreads widen at night and at the rollover

The same pair can be tight at 14:00 UTC and wide at 22:00 UTC. Liquidity follows people: when London and New York are both open, many banks and funds quote currencies and competition squeezes the spread. When only one region is awake, fewer quotes compete and the gap opens up. The forex market hours guide has a live session clock.

Forex sessions on a UTC clock

Sydney
Tokyo
LondonLondon
New YorkNew York

Hours in UTC

Late September hours (London and New York on summer time, Sydney on standard time). Each session shifts by an hour when its region changes clocks.

The widest moment of the forex day is usually the rollover at 17:00 New York time, when dealers settle positions and roll them to the next value date. For a few minutes liquidity thins out and spreads can jump to several times their daytime width. If your alerting fires on price moves, it will fire at the rollover for reasons that have nothing to do with the market.

EURUSD spread across a trading day

Illustrative shape of a normal day in UTC while New York is on summer time; not a measurement. The spike is the 17:00 New York rollover, 21:00 UTC.

Stocks follow the same logic on a different clock. Spreads are widest in the first minutes after the open, while the order book is still filling, and in pre-market and after-hours sessions. Crypto trades all week, so it has no open, but weekend nights are visibly thinner than weekday afternoons.

NBBO: the best bid and offer across US venues

A US stock trades on many venues at once, and each has its own best bid and ask. The national best bid and offer (NBBO) is the highest bid and the lowest ask across all of them. It is the reference brokers are measured against, and the tightest spread anyone can see for that stock at that instant.

  1. Venue A88.40 / 88.43
  2. Venue B88.41 / 88.44
  3. Venue C88.39 / 88.42
  4. NBBO88.41 / 88.42
Illustrative. The NBBO takes the best bid (88.41 on B) and the best ask (88.42 on C), so it is tighter than any single venue.

TickerLayer quotes are derived from aggregated sources rather than being the official NBBO, so we publish how close they come: the US stocks data quality benchmark compares our quotes with a consolidated US market reference, state for state, including the share of samples where our midpoint sits inside the NBBO.

Slippage: when the spread is not the whole cost

The spread is the cost of trading a small amount. The size fields tell you how small. The pre-market US:KO quote above showed 200 shares at the 88.30 ask. Buy 1,000 shares and the first 200 fill at the ask; the rest fill at worse prices deeper in the book. That difference between the price you expected and the average price you got is slippage.

Ask levelShares availableShares filledCost
88.30200200$17,660
88.34300300$26,502
88.39500500$44,195
Total1,000$88,357
Illustrative book behind a real pre-market quote. Average fill 88.357, which is 5.7 cents (6.5 bps) worse than the 88.30 ask and 15.2 cents worse than the mid.

Quote data does not show the levels behind the best price, but it tells you when to worry: when your order is several times the displayed size, or when the spread is already wide, expect to pay more than the ask.

Track the spread yourself in Python

You need a key and one endpoint. GET /{asset}/quote/{symbol} returns the current bid and ask for any asset class, with the same shape for forex, stocks, crypto, indices, ETFs and commodities. This script prints the spread in basis points for a few instruments:

spread.pyPython
import os
import requests

API = "https://api.tickerlayer.com"
HEADERS = {"x-api-key": os.environ["TICKERLAYER_API_KEY"]}


def spread_bps(asset: str, symbol: str) -> float:
    r = requests.get(f"{API}/{asset}/quote/{symbol}", headers=HEADERS, timeout=5)
    r.raise_for_status()
    q = r.json()
    bid, ask = float(q["bid"]), float(q["ask"])
    mid = (bid + ask) / 2
    return (ask - bid) / mid * 10_000


for asset, symbol in [
    ("forex", "EURUSD"),
    ("forex", "USDJPY"),
    ("commodities", "XAUUSD"),
    ("crypto", "BTCUSD"),
    ("stocks", "US:KO"),
]:
    print(f"{symbol:<8} {spread_bps(asset, symbol):7.2f} bps")
Output, 2026-09-28 10:25 UTC
EURUSD      0.35 bps
USDJPY      0.45 bps
XAUUSD      1.25 bps
BTCUSD      0.00 bps
US:KO      21.54 bps

Polling is fine for a spot check. To watch a spread change tick by tick, subscribe to the quote channel over WebSocket instead. Stream frames carry the same bid and ask, sent as strings on the forex, crypto and stocks channels, so convert them before doing arithmetic. The WebSocket market data guide walks through connecting, subscribing and reconnecting, and the exchange rate API guide covers forex quotes in depth.

What the spread tells your code

  • The cost of tradingCrossing the spread is a real cost. A strategy that makes 1 bp per trade on a 2 bps spread loses money before fees.
  • A liquidity gaugeA spread three times its usual width means the book is thin. Size down, or wait.
  • A quality checkZero, negative or absurd spreads point at a stale or broken quote. Drop it instead of plotting it.
  • A calmer alertAlert on the mid, but only when the spread is normal. Most false alarms happen when it is not.

The quality check deserves code of its own. A crossed quote (bid above ask) or a locked one (bid equal to ask) is not a price anyone can trade. It is usually a moment where the two sides were updated at slightly different times, and a reason to wait for the next update. The bad ticks guide extends this into a full stale-price and spike filter.

guard.pyPython
def usable(quote: dict, max_bps: float = 50.0) -> bool:
    bid, ask = float(quote["bid"]), float(quote["ask"])
    if bid <= 0 or ask <= 0 or ask <= bid:
        return False  # empty, crossed or locked
    mid = (bid + ask) / 2
    return (ask - bid) / mid * 10_000 <= max_bps

Do

  • Compare spreads in basis points across markets.
  • Keep bid and ask in storage; derive the mid.
  • Expect wider spreads before the open, overnight and at the rollover.
  • Filter crossed and locked quotes before charting.

Avoid

  • Comparing a yen pair and a euro pair in raw price units.
  • Backtesting on mid prices and ignoring the cost of crossing.
  • Firing price alerts during the daily rollover.
  • Assuming a large order fills at the ask.
Spread habits that save a production system from its most common false alarms.

Questions

What is a good bid-ask spread?

It depends on the instrument. Major currency pairs, large coins and the largest stocks trade at around one basis point or less in busy hours; small caps, exotic currencies and minor coins can be tens of basis points wide. Compare an instrument with its own history rather than with other markets.

Is it better to buy at the bid or the ask?

A market order to buy pays the ask and a market order to sell receives the bid. A limit order placed at the bid may get a better price, but it only fills if a seller comes to you.

Why does the spread widen at night?

Fewer participants are quoting, so less competition keeps prices close. In forex the widest point is usually the daily rollover at 17:00 New York time; in US stocks it is the pre-market and after-hours sessions.

What is the difference between spread and slippage?

The spread is the gap between the best bid and the best ask. Slippage is the extra cost when an order is larger than the size at the best price and fills at worse levels.

What is the mid price?

The average of the bid and the ask. Charts usually plot it, but nobody trades at it; buyers pay the ask and sellers receive the bid.

What does NBBO mean?

National best bid and offer: the highest bid and the lowest ask for a US stock across all trading venues at a given moment.

Keep reading

Ready to integrate?

Start with the free tier, explore the docs, and connect via REST or WebSocket in minutes.