Fresh row
Quote age is inside the alert threshold, spread percent is acceptable, and the row can trigger user-facing alerts.
State: fresh
A real-time workflow for initializing option dashboard rows with REST, keeping them fresh with WebSockets, backfilling missed quote windows, and explaining every alert.
Initialize rows with expirations, chain data, and contract snapshots; subscribe to quote and trade WebSocket messages; mark stale rows; backfill after reconnects; and include bid/ask, quote age, spread percent, Greeks, and reject reasons in each alert.
Initialization
REST first
Use expirations, chains, and snapshots to build stable rows before streaming updates arrive.
Live updates
WebSockets
Subscribe to quote and trade channels for exact OCC tickers that are visible or alert-eligible.
Reliability
Backfill
Use REST quote history after reconnects so alerts do not depend on a perfect stream.
State model
Start with Expirations, Options Chain API, and Option Contract Snapshot data so every row has a stable identity before live messages arrive. The row key should be the exact OCC ticker, not a display label assembled from strike and expiration text.
The initialized row should include underlying, expiration, strike, call/put side, DTE, moneyness, open interest, day volume, bid, ask, midpoint, implied volatility, Greeks, last trade, and snapshot timestamp. That lets the UI show useful context immediately and update the quote or trade fields independently.
Streaming
Use WebSockets for quote and trade updates, then keep Market Data Access Methods in mind for reconnect and REST backfill behavior. A stream update should patch the row, recalculate spread percent and quote age, and update freshness labels without losing the static contract metadata.
For alerting, combine quote freshness, spread percent, volume/open-interest pressure, trade condition, moneyness, and Greeks in the condition itself. A dashboard that says why an alert fired is more useful than a dashboard that only flashes a contract ticker.
Quote age is inside the alert threshold, spread percent is acceptable, and the row can trigger user-facing alerts.
State: fresh
No quote update arrived within the threshold, so the row remains visible but cannot trigger fresh-price alerts.
State: stale
The contract failed a no-bid, wide-spread, entitlement, or missing-data rule and should show a reject reason.
State: rejected
Operations
When the WebSocket reconnects, request Quotes for the missed window and apply the same freshness and spread checks used by live messages. This prevents duplicate alerts, missed exits, and false positives caused by a temporary network gap.
Each alert should store the OCC ticker, trigger timestamp, bid, ask, midpoint, spread percent, quote age, latest trade, volume, open interest, Greeks, alert rule, backfill status, entitlement state, and reject reason. That record turns a live dashboard into a reviewable research and operations system.
A reliable dashboard keeps static contract identity, live market updates, and backfill evidence separate.
| Phase | Data source | Dashboard behavior |
|---|---|---|
| Initialize | Expirations, chain, snapshot | Create rows with stable OCC tickers, DTE, moneyness, Greeks, IV, open interest, and latest quote context. |
| Stream | WebSocket quotes and trades | Patch bid, ask, last trade, size, timestamp, quote age, spread percent, and freshness labels. |
| Alert | Rule engine | Trigger only when quote quality, liquidity, moneyness, Greeks, and user thresholds all pass. |
| Recover | REST quote backfill | After reconnects, fill missed quote windows and prevent duplicate or stale alerts. |
| Review | Alert evidence store | Persist trigger timestamp, row state, fill context, rule version, and reject reason. |
API example
dashboard REST initialization and backfill
# Initialize the dashboard with REST so every row has contract metadata.
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.cutemarkets.com/v1/options/chain/QQQ/?expiration_date=2026-05-15&limit=250"
# Backfill the active alert window after reconnects or missed WebSocket messages.
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.cutemarkets.com/v1/options/quotes/O:QQQ260515C00450000/?timestamp.gte=2026-05-01T13:30:00Z×tamp.lt=2026-05-01T13:45:00Z"
# Drill into one contract when a user opens a dashboard row.
curl -H "Authorization: Bearer YOUR_API_KEY" "https://api.cutemarkets.com/v1/options/snapshot/QQQ/O:QQQ260515C00450000/"WebSocket subscription and stale-row handling
const API_KEY = process.env.CUTEMARKETS_API_KEY;
const state = new Map();
function markRow(ticker, patch) {
const previous = state.get(ticker) || {};
const next = { ...previous, ...patch, updatedAt: Date.now() };
const quote = next.quote || {};
const bid = Number(quote.bid_price || 0);
const ask = Number(quote.ask_price || 0);
const mid = bid > 0 && ask >= bid ? (bid + ask) / 2 : 0;
next.spreadPct = mid > 0 ? (ask - bid) / mid : Infinity;
next.freshness = Date.now() - next.updatedAt > 15000 ? "stale" : "fresh";
state.set(ticker, next);
}
function subscribe(tickers) {
const ws = new WebSocket("wss://api.cutemarkets.com/v1/ws/options/?apiKey=" + encodeURIComponent(API_KEY));
ws.addEventListener("open", () => {
for (const ticker of tickers) {
ws.send(JSON.stringify({ action: "subscribe", params: "Q." + ticker }));
ws.send(JSON.stringify({ action: "subscribe", params: "T." + ticker }));
}
});
ws.addEventListener("message", (event) => {
const message = JSON.parse(event.data);
if (message.ev === "Q") markRow(message.sym, { quote: message });
if (message.ev === "T") markRow(message.sym, { trade: message });
});
ws.addEventListener("close", () => {
setTimeout(() => backfillAndReconnect(tickers), 1000);
});
}
async function backfillAndReconnect(tickers) {
for (const ticker of tickers) {
await fetch("/api/options/backfill-quotes?ticker=" + encodeURIComponent(ticker));
}
subscribe(tickers);
}How to implement
Load listed expirations, chain rows, and contract snapshots so each dashboard row has a stable OCC ticker and metadata.
Open WebSocket subscriptions for quote and trade updates on visible, watchlisted, or alert-eligible contracts.
Update bid, ask, last trade, quote age, spread percent, freshness, and alert eligibility every time a message arrives.
On reconnect, request quote history for the missed interval before resuming alert evaluation.
Store the trigger rule, quote evidence, trade context, row state, entitlement status, and reject reason for later review.
Last verified
This guide was last reviewed on June 4, 2026. Date-sensitive market calendars, provider docs, and listed contracts can change, so production workflows should verify the live source before trading or publishing an automated answer.
No. Use REST for initialization and backfill, then WebSockets for low-latency quote and trade updates.
Keep the row visible but mark it stale and suppress fresh-price alerts until a new quote or validated backfill arrives.
Store the OCC ticker, trigger timestamp, bid, ask, spread percent, quote age, latest trade, volume, open interest, Greeks, rule version, and reject reason.
Related pages
Real-time options data API
Use live data and streaming updates for options dashboards.
WebSockets
Review the WebSocket subscription model for live market-data updates.
Live and delayed entitlements
Handle live, delayed, and quote-access states in production dashboards.
Real-time options system design
Plan ingestion, state, backfill, and alerting for real-time options systems.