Skip to content

Why prices are 15-minute delayed

This is the most important page on this docs site to read before you build with oneapi.finance. The 15-minute delay is not a bug, a feature flag, or a limitation we plan to remove later. It is a deliberate, structural choice. This page explains why, what it actually means, and how to architect around it.

The short version

US consolidated equity quotes (NBBO, last sale, depth) are licensed by the exchanges that produce them, redistributed through the Securities Information Processors (CTA/UTP for tape A and B/C, UTP for NASDAQ-listed). Any vendor that pushes those quotes to third parties pays:

  • Exchange direct-feed fees for each feed they consume (NYSE, NASDAQ, BATS, IEX direct).
  • SIP redistribution fees for each business or end-user receiving the consolidated tape.
  • Per-user device fees when the tape is shown to humans (called “non-pro” at $1–$3 per user per month and “pro” at $20–$140 per user per month, both audited annually).
  • Reporting and audit overhead of explaining all of the above to the exchanges every quarter.

Realistic floor for a small commercial redistributor is roughly $9,500 per month before any infrastructure cost. That math does not work for a flat €19/month plan with bursty hobbyist traffic.

The standard exchange fee schedules are public:

What “15-minute delayed” actually means

Most exchanges allow free redistribution of their data after a 15-minute delay, in line with the SIPs’ delayed-data carve-out. Concretely:

  • A trade that prints at T = 14:30:00 ET is free to redistribute publicly starting at T + 00:15:00. We pull it at that point or shortly after.
  • During market hours, our quote freshness for liquid US tickers is typically 15-25 minutes behind the tape.
  • Outside market hours, our last quote is the closing print. It does not move again until the next session opens.
  • For non-US markets, the delay can be smaller (the LSE allows 15 minutes, Euronext allows 15 minutes, XETR allows 15 minutes). It can also be larger for venues that mandate end-of-day-only redistribution (some emerging markets).

Where the delay lives in the response

Every quote response carries enough information to reason about freshness:

{
"quote": {
"symbol": "AAPL",
"price": 175.43,
"timestamp": "2026-05-04T19:45:00Z",
"meta": {
"source": "yahoo_query1",
"fetched_at": "2026-05-04T20:00:14Z"
}
}
}
  • timestamp is the as-of time of the price tick, in UTC.
  • meta.fetched_at is when our worker pulled the data from the upstream.

The age of the quote is now() - timestamp. The age of our cache is now() - meta.fetched_at. They differ because (a) the upstream is itself delayed, and (b) we may have served from our own cache. Both are exposed so your code can decide.

A defensive snippet:

from datetime import datetime, timezone
def quote_age_seconds(quote) -> float:
ts = datetime.fromisoformat(quote["timestamp"].replace("Z", "+00:00"))
return (datetime.now(timezone.utc) - ts).total_seconds()

Use cases that fit a delayed feed

A 15-minute delay is fine for:

  • Personal portfolio trackers, watchlists, and net-worth dashboards.
  • Research tools, screeners, and backtesting harnesses.
  • Educational sites and financial blogs.
  • News-driven price-change alerts (the user already knew about the news five minutes ago).
  • Any analytical workflow where the unit of decision is “today” or longer.

Use cases that do not fit

You should choose a different vendor if you are:

  • Quoting trades to clients in real time (you need NBBO).
  • Running a market-making or HFT strategy.
  • Operating a regulated brokerage front-end that displays “last price” to retail traders.
  • Calibrating an options-pricing model that prices off live underlyings.

Reasonable real-time alternatives include Polygon.io, Databento, or going direct to the exchanges. Expect the floor to be in the four or low-five figures per month.

We do not invent prices

We do not synthesize, smooth, or interpolate prices to mask the delay. If our upstream is silent, the most recent good tick stays as price and timestamp does not advance. If you compare two consecutive responses and timestamp is identical, no new data has arrived. This is by design — making up prices to feel fresher would be the worst possible behavior for a financial API.

What we may add later

Real-time tier — at a price commensurate with the licensing — is on the roadmap, but only if and when we find a customer base that genuinely needs it and the licensing economics work. The free and Indie tiers will always remain delayed-by-default; this is a positioning choice, not a temporary one.

What’s next