sifting/io
Developer Tutorials
7 min readSiftingIO Team

Building a Multi-Asset Market Data Stack: What Enterprise Teams Actually Need

What enterprise teams need from a multi-asset market data API: normalized schemas, real-time plus historical, filings, on-chain data, FIX and SDK delivery.

Building a Multi-Asset Market Data Stack: What Enterprise Teams Actually Need

How many vendors does it take to run one multi-asset market data stack? Ask a team operating a research platform or a brokerage backend and the honest answer is usually five or six: one provider for US stock prices, another for forex, another for crypto, a fundamentals and SEC filings service, a node provider or indexer for on-chain data, and sometimes a separate feed handler for anything that streams. Each one solved a real problem when it was added. The sum is an architecture problem, and it compounds.

Why multi-vendor market data stacks become difficult to maintain#

The direct costs are easy to list: six schemas, six credential systems, six client libraries, six rate-limit models, six status pages, six invoices. The indirect costs do the damage. One vendor timestamps in epoch seconds, another in exchange-local ISO strings, so every join in your warehouse starts with a conversion layer somebody has to maintain. One paginates by page number, another by opaque cursor, and the backfill jobs can't share code. Error handling diverges too: a 429 from one vendor carries a Retry-After header, another just closes the socket.

Then there is the organizational overhead. Every contract has its own licensing terms, renewal date, security review, and data processing agreement. When a bad print reaches production, the first hour of the incident goes to figuring out which of six feeds produced it. And each vendor's schema changes on its own schedule, which turns maintenance into a permanent migration backlog.

Why normalization across asset classes matters#

Any application that spans asset classes hits the same wall: the interesting queries are cross-asset, but the data arrives in per-vendor shapes. A portfolio tracker valuing stocks alongside crypto and FX, or a risk job netting exposure across currencies, spends most of its code translating formats.

A unified market data layer removes that translation work at the source. SiftingIO exposes US stocks, forex, crypto, and commodities through endpoint families grouped by purpose instead of asset class: /v1/hist/{class}/{symbol}/bars for historical OHLCV, /v1/last/quote/{venue}/{symbol} for live snapshots. Symbols follow one convention (AAPL, EURUSD, BTCUSD, XAUUSD), timestamps are RFC 3339 UTC for dates and epoch milliseconds for ticks, pagination is cursor-based everywhere, and one API key covers all of it. The consolidated price itself is a weighted median across multiple independent venues, so a single venue printing a stale or thin quote doesn't silently distort downstream systems.

Combining real-time and historical infrastructure#

Most platforms need both a deep historical store and a live feed, and the failure mode of sourcing them separately is that the two disagree: different symbols, different bar boundaries, different adjustment policies. Backfill and stream should come from the same source so the last historical bar and the first live tick line up.

The pull side is plain REST:

# daily bars (heavy endpoints require gzip)
curl --compressed -H "X-API-Key: $SIFTING_KEY" \
  "https://api.sifting.io/v1/hist/stocks/AAPL/bars?interval=1d"

# current best bid/ask
curl -H "X-API-Key: $SIFTING_KEY" \
  "https://api.sifting.io/v1/last/quote/forex/EURUSD"

The same AAPL and EURUSD identifiers work on the streaming side, so reconciliation between the warehouse and the live cache stops being a mapping table.

Going beyond prices: filings, fundamentals and corporate data#

Price feeds answer what an instrument is worth right now. Research platforms, compliance teams, and AI systems also need what the company said, and that usually means yet another vendor. A unified layer should treat company fundamentals as a first-class domain: SEC filings by form type and date, full filing-section text (business, risk factors, MD&A), XBRL financials queryable by concept and period, standard ratios, Form 4 insider transactions, 13F institutional holdings, and an economic calendar, all under /v1/fnd/* with the same key and conventions as the price endpoints. A year-over-year risk-factors diff, for example, becomes a single GET with no document pipeline behind it.

On-chain and DEX data is a market data domain of its own#

On-chain markets don't map cleanly onto the equities model. Instruments are pools rather than listings, liquidity is pool TVL, and the same pair trades on several chains at different prices. Teams typically cover this with node infrastructure and custom indexers, which is a data engineering project in itself.

Treating DEX and DeFi data as part of the market data layer collapses that project into API calls: on-chain swap activity and pool TVL across Ethereum, Base, Arbitrum, and Polygon, wallet portfolio lookups, and streaming with chain-scoped symbols such as eth:WETH-USDC. The benefit is architectural: on-chain prices arrive in the same normalized frames as everything else, so a dashboard or risk job doesn't care that the underlying venue is a smart contract.

REST, WebSocket, and FIX: matching delivery to the workload#

Delivery matters as much as coverage. Batch research and backfills fit REST. Live dashboards, alerting, and tick consumers fit WebSocket: connect to wss://stream.sifting.io/ws/v1?key=$SIFTING_KEY, then send

{ "op": "subscribe", "product": "cex", "symbols": ["BTCUSD", "ETHUSD"] }

The server acknowledges, replays the last cached value per symbol, then pushes live ticks.

Institutions with existing FIX plants have a third path. The FIX API delivers market data (no order entry) over FIX 4.4 from datacenters in Tokyo, New York, and London, using standard MarketDataRequest and snapshot-plus-incremental semantics. A bank or broker can plug consolidated crypto, FX, and commodities pricing into session infrastructure it already operates.

Above the wire protocols sit the integration surfaces teams staff around: official Go, Python, and JavaScript SDKs generated from the same specs, an MCP server that gives AI agents the same data, and connectors for n8n and Supabase when the consumer is a workflow or an app database instead of a codebase.

What enterprise evaluation looks like after the technical fit#

Once the endpoints check out, the questions change. Throughput: are quotas sufficient for production, and observable? Every response carries X-RateLimit-Limit and X-RateLimit-Remaining, so you can plan capacity from measurements instead of guesses. Availability: uptime SLAs run to 99.9 percent with service credits on upper tiers and 99.95 percent on enterprise agreements (these are uptime figures, distinct from any claim about data content). Security: multiple API keys per account for environment separation, and IP allowlisting on upper tiers. The procurement items that kill timelines in multi-vendor stacks (licensing review, DPA and MSA, invoicing terms, named support) happen once instead of six times, and enterprise plans add custom quotas, Net-30/60 billing, and a dedicated account manager.

A reference architecture for a multi-asset financial data platform#

A workable consolidated design has four layers. Ingestion: scheduled REST jobs backfill /v1/hist/* bars and /v1/fnd/* fundamentals into the warehouse, while a small pool of WebSocket consumers writes live ticks to a message bus. Storage: bars and fundamentals land in Postgres or object storage keyed by the provider's symbols, and the latest tick per symbol lives in an in-memory cache. Serving: internal services read one schema, whatever the asset class. Consumption: research notebooks, dashboards, alerting, and AI agents all draw from the same store, and the consolidated price doubles as a validation reference for whatever execution venues the business uses, a cross-check rather than an execution feed.

The property that keeps this simple is that normalization happened upstream. There's no per-vendor adapter layer to maintain, one credential to rotate, one contract to renew.

Common pitfalls when consolidating#

Three gotchas come up in nearly every migration. First, the heavy endpoints (historical bars, XBRL financials, the cross-sectional screener) require gzip and return 406 gzip_required without it; curl needs --compressed, and some HTTP clients don't negotiate gzip by default. Second, the WebSocket server closes any connection idle for 90 seconds, so consumers must send a ping at least every 60 seconds and, on reconnect, expect the cached replay frame per symbol and deduplicate it. Third, the streaming product codes are not the REST path slugs: you subscribe on the WebSocket with product: "cex" for crypto and product: "fx" for FX, but the REST paths spell those same venues crypto and forex. A consolidation layer that reuses one slug across both transports will hit rejected subscriptions until it maps the two naming schemes.

Endpoint-level detail for every family mentioned here is in the API documentation.

Keep reading

Related posts

Building a Multi-Asset Market Data Stack: What Enterprise Teams Actually Need · SiftingIO