A response can arrive quickly and still contain an old price. To display a quote honestly, track when the market observation occurred, when your application received it, and what your application knows about the instrument’s session. These are separate facts.
Keep three clocks separate
The quote field lp_time describes the last-price timestamp in Unix seconds. Your client can also record a receive timestamp. A streaming message may carry an envelope timestamp in milliseconds, but that timestamp should not replace the market observation time inside the quote.
For example, an observation at 14:30:00 UTC received at 14:30:04 UTC is four seconds old at receipt. That difference is not a measurement of API network latency: it also includes any time between the underlying observation and delivery. To measure request duration, use a monotonic client timer around the HTTP request and record it separately.
Classify a quote without inventing freshness
This helper operates on an already validated quote object and a caller-defined threshold. The threshold is your product policy, not a provider SLA. Both inputs use seconds; convert to JavaScript milliseconds only when formatting a date.
function classifyQuote(quote, nowSeconds, maxAgeSeconds) {
if (!Number.isFinite(maxAgeSeconds) || maxAgeSeconds < 0) {
throw new Error("Choose a non-negative freshness threshold");
}
if (!Number.isFinite(quote?.lp)) return "unavailable";
if (!Number.isFinite(quote?.lp_time) || quote.lp_time <= 0) {
return "timestamp-unknown";
}
const age = nowSeconds - quote.lp_time;
if (age < 0) return "clock-mismatch";
return age > maxAgeSeconds ? "older-than-policy" : "within-policy";
}
within-policy deliberately says only that the timestamp meets your selected age threshold. It does not establish that the instrument has exchange-authorized real-time delivery. Confirm coverage and delivery characteristics separately for the symbols you need.
Account for sessions and missing fields
An old last-trade time outside market hours can be expected. The same age during an active session may warrant investigation. Session information such as current_session, when available, helps provide context, but does not replace a verified market calendar or prove that the market is open right now. Trading halts and illiquid instruments can also explain a lack of new trades.
Treat an absent price, a missing currency and an unknown timestamp as explicit states. Do not fill them with zero, USD or the current time. If you display a previous value during an outage, keep its original timestamp and label it as the last known observation.
Preserve degraded and partial results
A quote response may be successful while carrying degraded: true. Keep that flag alongside the value so downstream consumers can apply their own policy. In a batch, inspect both the envelope and individual result. In a stream, a subscription acknowledgement proves that a subscription was accepted; it is not a new quote.
A quote update may not include every field your UI needs. Merge only fields actually present for the same instrument, and keep a distinction between a field that was omitted and one explicitly supplied as unavailable. Avoid comparing prices across different currencies or exchange listings as if they were the same instrument.
Make the state visible
A compact quote row can show price, currency, exchange-qualified symbol, market time and a freshness label. Put receive time and request duration in diagnostics. Test at least a current observation, missing timestamp, future timestamp, closed-session observation and degraded result before using the row in a dashboard.
This separates a data-quality decision from a transport decision. A stream can reduce polling work, but simply using a streaming connection does not guarantee fresh or complete data.