Real-time streaming
WebSocket clients for market data (stocks, crypto, options, news) and a trading
stream (order/account updates). Both authenticate automatically, reconnect with
backoff, dispatch their current subscriptions after reconnect authentication,
and ping/pong. The API is a typed EventEmitter: register listeners, then
connect().
const stocks = alpaca.marketData.stockStream({ feed: "iex" });
stocks.onBar((bar) => console.log(bar));
stocks.onError((msg) => console.error("stream error:", msg));
stocks.onConnect(() => stocks.subscribeForBars(["AAPL", "MSFT"]));
stocks.connect();
const updates = alpaca.trading.stream();
updates.onTradeUpdate((u) => console.log(u.event, u.order.symbol));
updates.onConnect(() => updates.subscribeTradeUpdates());
updates.connect();
Available streams
All five factories return a stream sharing the lifecycle below:
| Factory | Stream | Data |
|---|---|---|
alpaca.trading.stream() | TradingStream | Order/account updates (JSON) |
alpaca.marketData.stockStream() | StockDataStream | US-equity bars/trades/quotes (msgpack) |
alpaca.marketData.cryptoStream() | CryptoDataStream | Crypto market data (msgpack) |
alpaca.marketData.optionStream() | OptionDataStream | Options market data (msgpack) |
alpaca.marketData.newsStream() | NewsStream | Real-time news headlines |
Timestamp precision
Market-data stream events expose two timestamp fields:
timestamp: Date— millisecond precision, convenient for most uses.timestampRaw?: string— the full RFC-3339 nanosecond timestamp, e.g."2024-01-02T03:04:05.678099211Z".
The market-data stream is msgpack, whose default decoder truncates timestamps to
milliseconds. The SDK installs a custom decoder so timestampRaw keeps every
digit Alpaca sends. (This applies to the market-data channels — trades, quotes,
bars, statuses, LULDs, imbalances, corrections, cancel-errors, and orderbooks.)
Trade-id precision
Trade ids are 64-bit integers, which can exceed JavaScript's safe integer range
(2^53). The same custom decoder reads them losslessly, so id-bearing events
expose an exact string alongside the convenient (best-effort) number:
- Trades —
id: numberandidRaw?: string. - Cancel-errors —
id: numberandidRaw?: string. - Corrections —
originalId/correctedId(numbers) andoriginalIdRaw?/correctedIdRaw?(strings). - News —
id: numberandidRaw?: string.
Use idRaw whenever you compare, store, or key on an id; id remains for
display and small values. Other numeric fields (sizes, volumes, counts) stay a
plain number.
The REST canonical trade accessors (getStockTrades/getCryptoTrades) expose
the same idRaw, so ids you backfill over REST match the ones you receive live
— see Trade-id precision in the
market-data guide.
Shared lifecycle
Every stream exposes:
- Awaitable authentication —
whenAuthenticated()resolves with a typedStreamAuthResult(never rejects);waitForAuthentication(timeoutMs?)returns aboolean. Failures carry aSTREAM_AUTH_STATUS(server_rejectedwith the servercode,closed,timeout). - Reconnect lifecycle —
onReconnecting((attempt) => …)(1-based) andonReconnected(() => …)after re-authentication and re-subscription dispatch, distinct from the firstonConnect. This event does not promise a server subscription acknowledgement. - A custom
urlon any stream to route through a proxy/gateway, plus acallbackExecutorto offload listener work — a throwing listener is isolated and can never break the stream.
const result = await stocks.whenAuthenticated();
if (!result.authenticated) {
console.error(`auth failed: ${result.status} ${result.code ?? ""}`);
}
Connection safety
Lifecycle callbacks, messages, keepalive timers, and reconnect work are scoped
to the socket generation that created them, so a stale socket cannot mutate a
new connection. Ping timers start only after the socket is open. A manual
disconnect() suppresses reconnect and emits the disconnect lifecycle exactly
once.
Malformed frames, decode failures, and event-mapper failures are caught and
reported through onError / CLIENT_ERROR without escaping the socket callback
or crashing the process. The trading protocol's action: "error" frames use
the same error channel. Listener/callback-executor failures are isolated too.
Crypto and news streams have no sandbox endpoint: pass an explicit url to point
them elsewhere, otherwise sandbox: true throws.
stockStream also exposes subscribeForImbalances([...]) / onImbalance(...).
This channel is equities-only and sparse — Alpaca emits imbalance messages mainly
during limit-up/limit-down halts, so long quiet periods are expected even while
subscribed.
Common options
In addition to feed/paper/sandbox: reconnect, maxReconnectAttempts
(UNLIMITED_RECONNECT_ATTEMPTS to retry forever), backoff,
initialReconnectMs, maxReconnectMs, reconnectJitter, pingIntervalMs,
pongWaitMs, url, and callbackExecutor.