DEV Community

James Tao
James Tao

Posted on

Handling Order‑Book Level Changes When Pulling Snapshots From Crypto Asset APIs

Intro

For a group FinTech course project, I built a cloud‑hosted crypto‑asset analysis prototype. One core task was consuming order‑book snapshots from a crypto API to calculate liquidity metrics, extract order‑book features, and feed data into simulation strategy backtesting.

When I first built the prototype, I had a very simple mental model: an order‑book snapshot is just a static snapshot of bid/ask prices at a single point in time. Whenever I fetched a new snapshot, I would fully overwrite my local cache.

Once I started feeding real‑time streaming data into the system, I realised this approach has critical flaws. The value of order‑book data isn’t limited to static price values. Dynamic events — new orders, cancellations, and volume shifts across price levels — are where most of the analytical insight lives.

If you only persist discrete snapshots, you only get isolated time slices. You lose the full lifecycle of changes for every price tier. This introduces bias when evaluating short‑term liquidity. That was one of the biggest gotchas I hit during lab development.

Core requirements for order‑book processing

From debugging and iteration, I landed on two key requirements for our implementation:

  1. The local order‑book must stay synchronised with exchange state to guarantee valid feature calculations and strategy simulation outputs.
  2. Beyond reading point‑in‑time snapshots, the system needs to track incremental price‑level changes. We need to retain order addition and cancellation events for later backtesting and review.

Simply fetching snapshots and overwriting local state will not meet these requirements. You need to implement incremental update logic for your local order book.

Real‑world pitfalls you might miss

Exchange order‑books are continuously changing. Volume fluctuates on every price level, and some tiers disappear entirely after order cancellations. If you overwrite your local copy on every snapshot arrival, you can view the latest state but discard all intermediate change history.

Running WebSocket streams in cloud environments also reveals subtle issues that rarely show up in small local test cases:

  1. Out‑of‑order messages: Network jitter can cause stale delayed messages to arrive after newer payloads. Without timestamp validation, old data can corrupt current order‑book levels.
  2. Price precision mismatches: Different trading pairs use different decimal places. Without normalisation logic, identical prices can be misinterpreted as separate price tiers.
  3. State drift after reconnection: When WebSocket connections drop and reconnect, incremental event streams get interrupted. Incremental updates alone cannot fix misalignment between local state and the real exchange order‑book.

These bugs can silently corrupt liquidity metrics and order‑book features in production‑style analytical pipelines.

Solution: Incrementally maintain your in‑memory order‑book

The core idea is straightforward: keep an order‑book structure in memory, keyed by price. Apply incoming market events incrementally instead of replacing the full dataset with each snapshot.

  • If the incoming volume value is 0: interpret this as an order cancellation, remove that price level locally.
  • If volume is non‑zero: update the volume for the given price. Insert a new price level if it does not already exist.

This pattern properly handles new price‑level creation, volume updates, and order cancellations.

For lab validation, I subscribed to real‑time order‑book streams via AllTick API and wired incremental updates to incoming WebSocket messages.

import websocket
import json

def on_message(ws, message):
    data = json.loads(message)
    symbol = data.get("symbol")
    price = data.get("price")
    volume = data.get("volume")
    print("alltick", symbol, price, volume)

if __name__ == "__main__":
    ws_app = websocket.WebSocketApp("wss://api.alltick.co/ws", on_message=on_message)
    ws_app.run_forever()
Enter fullscreen mode Exit fullscreen mode

⚠️ Note: This is minimal demo code for learning. For assignments or prototypes, implement these improvements:

  • Attach timestamps to each message to filter delayed, out‑of‑order events
  • Normalise price decimal precision
  • After every reconnection, fetch a full order‑book snapshot before resuming incremental consumption to resolve state drift

Choose your persistence strategy based on use‑case:

  • Save periodic full snapshots if you only need to inspect the current market state.
  • Persist individual level‑change event streams if you want to analyse liquidity evolution over time.

Key takeaways

Working with crypto asset APIs taught me that fetching order‑book snapshots is not the final goal. The real challenge is keeping your local order‑book continuously synchronised with live market conditions.

Order‑book analysis is about far more than latest trade prices. The rhythm of volume changes across price tiers delivers most of the meaningful signals. Solid synchronisation logic builds a reliable foundation for liquidity measurement, feature engineering, and strategy simulation.

Discuss 👇

Have you built order‑book processing pipelines using crypto asset APIs?
Have you dealt with state drift, parsing mistakes or data corruption caused by network behaviour? Share your debugging lessons in the comments.

Top comments (0)