Market Data Vendors
These are examples, not shipped integrations. Each shows how one vendor's data model maps onto the chart contracts so you can adapt the pattern to whichever provider you have a contract with. Endpoints, schema names, and pricing change — confirm the current details against the vendor's own documentation before building.
The shape is always the same: the vendor client lives in your gateway, and the chart sees only normalized SDK types.
Choosing between them
| Databento | Alpaca | Massive | |
|---|---|---|---|
| Positioning | Normalized venue-native data, including full order book | Broker with a bundled market data API | Multi-asset market data API |
| Asset classes | Equities, futures, options across many venues | US equities, crypto, options | Stocks, options, forex, crypto |
| Order book | Yes, including full book by order | Top of book | Quote-level |
| History depth | Deep tick and book history | Bars, trades, quotes | Bars, trades, quotes, plus bulk flat files |
| Execution included | No | Yes, same account | No |
| Best fit | Order-flow surfaces, book replay, research-grade history | Getting a chart and a broker running from one vendor | Broad multi-asset coverage without venue-level detail |
If your product shows the depth ladder, liquidity heatmap, or footprint, you need genuine book data. A top-of-book feed cannot render those surfaces honestly, and synthesizing depth from quotes produces a chart that looks right and is wrong.
Databento
Databento publishes venue data under one normalized model, with identical
schemas for historical and live. That property matters here: one normalizer
serves both loadBars and subscribeRealTimeBars.
Schemas to SDK contracts
| Schema | Contains | Maps to |
|---|---|---|
ohlcv-1s, ohlcv-1m, ohlcv-1h, ohlcv-1d | Aggregate bars | loadBars, subscribeRealTimeBars |
trades | Every trade print | getTimeAndSales, subscribeTimeAndSales, and bar aggregation |
tbbo | Trades with the book at the time of trade | Tape with aggressor inference |
mbp-1 | Top of book | getQuotes, subscribeQuotes |
mbp-10 | Ten levels per side | getDepth, subscribeDepth |
mbo | Full book, order by order | getBookHistory, book replay |
definition | Instrument reference data | resolveSymbol, searchSymbols, price increments |
statistics, status | Session statistics and venue state | Session and market status surfaces |
Conversions
Two conversions are mandatory and easy to miss:
- Timestamps are UTC nanoseconds. The chart takes Unix milliseconds.
- Prices are fixed-precision integers scaled by 1e-9. The chart takes floats in display units.
const bar = {
time: Number(record.ts_event / 1_000_000n),
open: Number(record.open) / 1e9,
high: Number(record.high) / 1e9,
low: Number(record.low) / 1e9,
close: Number(record.close) / 1e9,
volume: Number(record.volume),
};
Do this once, in the gateway. A scaling error that reaches the browser is indistinguishable from a market move.
Instrument identity is per-dataset and per-venue rather than a bare ticker, so
resolve it from the definition schema and keep your own map from the ticker
users type to the vendor's instrument id. That map belongs in
SdkSymbolInfo.ticker and canonicalSymbol.
Alpaca
Alpaca is a broker whose market data API is separate from its trading API, so it can serve both contracts — but the two have independent credentials, tiers, and limits.
Transports
| Purpose | Endpoint |
|---|---|
| REST market data | https://data.alpaca.markets/v2/... |
| WebSocket, IEX feed | wss://stream.data.alpaca.markets/v2/iex |
| WebSocket, SIP feed | wss://stream.data.alpaca.markets/v2/sip |
| Sandbox WebSocket | wss://stream.data.sandbox.alpaca.markets/v2/... |
REST calls authenticate with the APCA-API-KEY-ID and APCA-API-SECRET-KEY
headers. The stream authenticates in-band, then subscribes:
{ "action": "auth", "key": "YOUR_KEY", "secret": "YOUR_SECRET" }
{ "action": "subscribe", "bars": ["AAPL"], "trades": ["AAPL"], "quotes": ["AAPL"] }
Stream messages are compact. Bars arrive as "b" with S symbol, o, h,
l, c, v, vw volume-weighted price, n trade count, and t timestamp.
Trades arrive as "t" with S, p price, s size, x exchange, c
conditions, z tape, and i trade id. Expand these into SDK shapes in the
gateway rather than teaching the chart a vendor's field names.
The feed distinction
The free Basic tier serves IEX only — a single venue, roughly a few percent of consolidated volume. Charts built on IEX show real trades but not the consolidated market, so bars and volume differ from any other terminal the trader compares against. SIP is the consolidated feed and requires a paid plan. Decide this before users see a chart, because the difference is visible and gets reported as a data bug.
Alpaca also publishes updatedBars, which correct a previously delivered bar.
Route those to the same replace-by-timestamp path as a normal live bar; the
chart replaces a bar whose time already exists.
Massive
Massive covers stocks, options, forex, and crypto over REST and WebSocket, with bulk historical delivered as flat files. Its US equity coverage spans the major exchanges plus dark pools, FINRA facilities, and OTC.
The integration split that works well here:
- Flat files for backfill. Load history into your own store once, then serve
loadBarsfrom that store rather than paying per-request latency on every scroll. - REST for gap filling and on-demand ranges the store does not yet cover.
- WebSocket for the developing bar and the tape.
That pattern is not Massive-specific — it is the right architecture for any vendor that sells both bulk history and a live stream, and it is what makes scroll-back on a chart feel instant.
Licensing
Vendor licensing constrains architecture more than any technical detail on this page.
- Display versus non-display use is priced separately by most venues, and a chart is display use.
- Redistribution — showing a vendor's data to anyone who is not the licensee — usually requires a separate agreement. A chart you build for your own desk and a chart you offer to clients are different licenses even with identical code.
- Per-seat counting is typically per user, not per connection, which is one reason the gateway deduplicates upstream subscriptions.
- Delayed and end-of-day data carry lighter obligations. If the product does not need real time, saying so early saves real money.
Enforce entitlements at the gateway, and make an entitlement failure a typed error rather than an empty result. See Build the data gateway.
Next steps
- Market data types — the contract each vendor schema has to satisfy.
- Interactive Brokers — a broker-supplied data example.
- TradeZero — what to do when the broker publishes no data at all.