Intro
If you’ve built real‑time market data consumers using WebSocket‑based US stock APIs, you’ve probably run into one sneaky bug: out‑of‑order tick events.
Everything works great in local testing. Your script receives ticks, prices update smoothly. Once you connect to live trading feeds, strange behaviors emerge: prices roll backward, technical indicators break, and your trading logic fires unexpected signals.
Many developers immediately blame the API provider. In most cases, however, the problem comes from cross‑border network jitter, variable latency, and client‑side processing pressure reordering incoming packets.
In this article, I’ll cover:
- Why tick data arrives out‑of‑order in live environments
- Practical strategies for different business scenarios
- Working Python client‑side buffer implementation
- A layered ingestion architecture for timing‑sensitive workloads
These tips apply if you’re building market dashboards, backtesting pipelines, or experimenting with live quantitative strategies.
Why do ticks arrive in the wrong order?
Under local test conditions with small sample data, timing issues stay hidden. Once you subscribe to multiple stock symbols and ingest high‑frequency real‑time streams, network instability and parsing load can shuffle packet sequence.
Let’s take three sequential trades generated on an exchange:
| Tick ID | Event Timestamp | Trade Price |
|---|---|---|
| A | 10:00:01.001 | 185.20 |
| B | 10:00:01.005 | 185.25 |
| C | 10:00:01.009 | 185.18 |
✅ Expected sequence: A → B → C
⚠️ Real‑world possible sequence: A → C → B
⚠️ Important: Out‑of‑order delivery does not equal a broken API. Most timing drift occurs during transmission or from client‑side bottlenecks.
If you consume messages strictly by arrival order, you will face broken charts, false strategy triggers, and corrupted persisted datasets.
Core principle: Receiving a tick payload ≠ ready‑to‑process tick payload.
Do not use your local machine receive time as the market event time. Always trust the timestamp or sequence ID embedded inside the API response.
Simplified processing workflow for every incoming tick:
- Receive raw WebSocket message
- Parse/deserialize to tick object
- Extract original market‑event timestamp
- Compare against timestamp of last successfully processed tick
- Apply business rule: buffer / discard / replay
Example scenario:
Your application finishes processing tick with timestamp 10:00:01.009. A delayed tick arrives later with timestamp 10:00:01.005.
Do not treat it as fresh market data. Mark it as out‑of‑order and handle according to your business logic.
Strategy selection by use‑case
There is no universal solution. You must balance latency requirements and data integrity for your project.
📊 Live market dashboard
Millisecond‑level timing skew is acceptable. UI stability is higher priority than perfect chronological precision.
Skip heavy correction logic. Use a short buffering window: collect a small batch of events, sort by native event timestamp, then forward sorted data to frontend rendering.
💾 Persist raw tick data
Always store the original event_time returned by the API. Never rely only on your local receive timestamp.
event_time acts as your source‑of‑truth for data cleaning, backtesting and recomputation later. Also save local receive timestamp so you can calculate end‑to‑end latency.
📈 Quantitative strategy execution
Strict timing requirements. Validate chronological integrity before feeding ticks into your strategy engine.
Late‑arriving out‑of‑order ticks can create false trade signals and corrupt calculation results. Buffering and filtering logic are mandatory.
Client‑side buffer implementation (Python)
Below is runnable example for AllTick API WebSocket connection. We buffer incoming ticks in‑memory, sort them by timestamp, and release for business processing once threshold is reached.
💡 Note: buffer size
20is for demonstration only. Tune this value:
- Dashboards: larger buffer is acceptable
- Low‑latency trading: keep buffer small, balance delay vs out‑of‑order tolerance
import websocket
# In‑memory tick buffer
buffer = []
def on_message(ws, message):
tick = parse_tick(message)
buffer.append(tick)
# Sort buffer by market‑event timestamp
buffer.sort(key=lambda x: x["timestamp"])
# Pop earliest ordered tick for processing
while len(buffer) > 20:
tick = buffer.pop(0)
process_tick(tick)
ws = websocket.WebSocketApp(
"wss://api.alltick.co/stock/websocket",
on_message=on_message
)
ws.run_forever()
⚠️ Key takeaway: WebSocket guarantees message delivery, but it does NOT guarantee business‑level event ordering. Timestamp validation and out‑of‑order buffering belong to client‑side implementation.
Common gotcha: two different timestamp fields
Many new market‑data developers make this mistake: using local system time (time.time()) as the market execution time.
received_at = time.time()
received_at only captures when your program received the packet. It tells you nothing about when the trade actually happened on US exchanges.
✅ Recommended persistence pattern:
-
event_time: Authoritative market timestamp returned by API -
received_time: Local client timestamp when message arrived
Calculate end‑to‑end latency:
latency = received_time - event_time
When latency spikes occur, dual timestamps help you isolate issues: network link, upstream API service, or local application performance bottleneck.
Layered architecture for timing‑sensitive systems
For production‑grade projects where tick ordering matters, decouple market ingestion layer from downstream business logic. Prevent network‑caused timing noise from propagating through your whole stack.
Simplified data flow:
Raw WebSocket payload
↓
Market ingestion layer
↓
Timestamp / sequence‑number validation
↓
Short‑term buffering & chronological sorting
↓
Dispatch: data persistence / strategy computation / market‑data output
Benefits: Temporary network‑caused out‑of‑order events get corrected inside ingestion layer. Timing anomalies will not leak to every downstream component, greatly simplifying debugging.
Wrapping up
When consuming US stock tick APIs, the core challenge is not forcing messages to arrive in perfect order. You must keep three concepts separated:
- Packet arrival order
- Actual market‑event occurrence order
- Business‑processing order
With properly tuned buffering, timestamp validation and dual‑timestamp logging, you can mitigate most common real‑time feed bugs: price flickering, time rollbacks, misleading indicator outputs.
Even when working with mature market‑data services such as AllTick API, client‑side timing safeguards are still essential for stable production quant tooling.
💬 Discussion
Have you encountered out‑of‑order market data in your projects? What solutions or workarounds have you tried? Drop a comment below.

Top comments (0)