Skip to main content

What you’ll build

In this tutorial, you will:
  1. open a realtime connection with ddx-python,
  2. subscribe to ORDER_BOOK_L2 and MARK_PRICE,
  3. attach callback handlers,
  4. inspect live state from the client,
  5. stop cleanly after receiving updates.

Prerequisites

  • A working ddx-python installation.
  • A config file with webserver_url, ws_url, rpc_url, contract_deployment, and private_key.
  • Basic familiarity with the client setup from Getting Started with ddx-python.

Step 1: Open the client context

Use the same async client pattern as the Python onboarding tutorial:
async with DerivaDEXClient(
    base_url=config["webserver_url"],
    ws_url=config["ws_url"],
    rpc_url=config["rpc_url"],
    contract_deployment=config["contract_deployment"],
    private_key=config["private_key"],
) as client:
    ...
The realtime connection is established when the context enters.

Step 2: Define one callback per feed

The WebSocket example uses separate handlers for order-book and mark-price updates:
def handle_order_book(contents):
    print("order book:", contents)

def handle_mark_price(contents):
    print("mark price:", contents)
Keep the handlers simple at first so you can verify subscription flow before adding trading logic.

Step 3: Build the feed subscriptions

Create FeedWithParams objects for the feeds you want:
from ddx.realtime_client.models import (
    Feed,
    FeedWithParams,
    MarkPriceParams,
    OrderBookL2Filter,
    OrderBookL2Params,
)

feeds = [
    (
        FeedWithParams(
            feed=Feed.ORDER_BOOK_L2,
            params=OrderBookL2Params(
                order_book_l2_filters=[
                    OrderBookL2Filter(symbol="ETHP", aggregation=0.1)
                ]
            ),
        ),
        handle_order_book,
    ),
    (
        FeedWithParams(
            feed=Feed.MARK_PRICE,
            params=MarkPriceParams(symbols=["ETHP"]),
        ),
        handle_mark_price,
    ),
]

Step 4: Subscribe and start receiving updates

Register the feeds with the realtime client:
await client.ws.subscribe_feeds(feeds)
After subscription:
  1. acknowledgements are matched to the client’s outstanding requests,
  2. incoming feed payloads are decoded into typed models,
  3. your callbacks run whenever matching updates arrive.

Step 5: Read cached live state

The example periodically reads cached state from the realtime client:
current_price = client.ws.mark_price("ETHP")
if current_price is not None:
    print("current price:", current_price)
This gives you a simple way to confirm the stream is updating without building a larger queue consumer first.

Step 6: Handle shutdown and reconnect expectations

The example installs signal handlers and keeps a running flag so the loop can exit cleanly. While it is running, note two things:
  1. the realtime client keeps active subscriptions and attempts to restore them after reconnect,
  2. your callbacks must still tolerate dropped connections, delayed updates, and resubscription flow.
For trading or account-state flows, combine WebSocket updates with REST bootstrap rather than treating the WebSocket as the only state source.

Step 7: Extend the subscription set carefully

Once the basic market-data path works, add more feeds one at a time:
  1. ORDER_UPDATE for order outcomes,
  2. STRATEGY_UPDATE for collateral and position effects,
  3. TRADER_UPDATE for trader-level balance and profile events.
Keep feed expansion incremental so you can verify callback behavior and update ordering before you attach decision logic.

Next routes

Last modified on April 13, 2026