Overview
The WebSocketClient provides real-time streaming of orderbook updates and price data over a persistent WebSocket connection. It supports automatic reconnection and event-driven message handling via decorators.
Setup
from limitless_sdk.websocket import WebSocketClient, WebSocketConfig
config = WebSocketConfig(
url="wss://ws.limitless.exchange",
auto_reconnect=True,
reconnect_delay=5, # seconds between reconnection attempts
)
ws_client = WebSocketClient(config)
| Parameter | Type | Default | Description |
|---|
url | str | Required | WebSocket server URL |
auto_reconnect | bool | True | Automatically reconnect on disconnection |
reconnect_delay | float | 1.0 | Seconds to wait between reconnection attempts |
Event Handlers
Register handlers for specific events using the @ws_client.on() decorator:
@ws_client.on("connect")
async def on_connect():
print("Connected to WebSocket")
@ws_client.on("orderbookUpdate")
async def on_orderbook(data):
print("Orderbook update:", data)
@ws_client.on("newPriceData")
async def on_price(data):
print("Price update:", data)
Available Events
| Event | Payload | Auth | Description |
|---|
connect | None | — | Fired when the WebSocket connection is established |
orderbookUpdate | dict | Public | Orderbook changes (new bids/asks, removals) |
newPriceData | dict | Public | Latest price data for subscribed markets |
positions | dict | Authenticated | Your position changes (see Authenticated Subscriptions) |
orderEvent | dict | Authenticated | Your CLOB order lifecycle and settlement events |
Subscribing to Markets
After connecting, subscribe to specific markets to receive updates:
@ws_client.on("connect")
async def on_connect():
await ws_client.subscribe(
"subscribe_market_prices",
{"marketSlugs": ["btc-above-100k-march-2025"]},
)
print("Subscribed to market prices")
The subscribe() method takes two arguments:
| Parameter | Type | Description |
|---|
event | str | Subscription event name (e.g. "subscribe_market_prices") |
data | dict | Subscription parameters including marketSlugs |
You can subscribe to multiple markets at once by passing a list of slugs in marketSlugs.
Authenticated Subscriptions
The subscribe_positions and subscribe_order_events channels are per-account and require authentication. Pass hmac_credentials to the config — the SDK signs the WebSocket handshake automatically (no manual headers needed). This is the same flow as the TypeScript SDK; see Authentication to generate a token.
from limitless_sdk import HMACCredentials
from limitless_sdk.websocket import WebSocketClient, WebSocketConfig
config = WebSocketConfig(
url="wss://ws.limitless.exchange",
hmac_credentials=HMACCredentials(
token_id="your_token_id",
secret="your_token_secret", # base64-encoded secret from token creation
),
auto_reconnect=True,
)
ws_client = WebSocketClient(config)
Positions
Subscribe to real-time updates when your positions change:
@ws_client.on("connect")
async def on_connect():
await ws_client.subscribe(
"subscribe_positions",
{"marketSlugs": ["btc-above-100k-march-2025"]},
)
@ws_client.on("positions")
async def on_positions(data):
print("Position update:", data)
Order Events
Subscribe to your CLOB order lifecycle and settlement events. This channel is per-account and takes no payload:
@ws_client.on("connect")
async def on_connect():
await ws_client.subscribe("subscribe_order_events")
@ws_client.on("orderEvent")
async def on_order_event(event):
# Several event shapes arrive on the same `orderEvent` name — distinguish by source, then type
if event.get("source") == "OME":
print("Order state:", event.get("type"), event.get("orderId"), event.get("clientOrderId"))
else:
print("Settlement:", event.get("type"), event.get("orderId"), event.get("txHash"))
Authenticated subscribe() calls raise ValueError if no hmac_credentials is set. Auth failures surface on the exception event. See the WebSocket Events reference for the full orderEvent payload shapes (source OME vs SETTLEMENT, and type values).
Auto-Reconnect
When auto_reconnect is enabled (the default), the client automatically reconnects after a disconnection:
- The connection drops (network issue, server restart, etc.)
- The client waits
reconnect_delay seconds
- A new connection is established
- The
connect event fires again, so your subscription logic re-executes
Place your subscribe() calls inside the connect handler to ensure subscriptions are restored after every reconnection.
Complete Example
import asyncio
from limitless_sdk.websocket import WebSocketClient, WebSocketConfig
async def main():
config = WebSocketConfig(
url="wss://ws.limitless.exchange",
auto_reconnect=True,
reconnect_delay=5,
)
ws_client = WebSocketClient(config)
@ws_client.on("connect")
async def on_connect():
print("Connected")
await ws_client.subscribe(
"subscribe_market_prices",
{"marketSlugs": ["btc-above-100k-march-2025"]},
)
@ws_client.on("orderbookUpdate")
async def on_orderbook(data):
slug = data.get("marketSlug", "unknown")
bids = len(data.get("bids", []))
asks = len(data.get("asks", []))
print(f"[{slug}] Orderbook: {bids} bids, {asks} asks")
@ws_client.on("newPriceData")
async def on_price(data):
slug = data.get("marketSlug", "unknown")
price = data.get("price", "N/A")
print(f"[{slug}] Price: {price}")
# Connect, then keep the client alive to receive events
await ws_client.connect()
await asyncio.Event().wait() # runs until interrupted (Ctrl+C)
asyncio.run(main())
await ws_client.connect() returns once the connection is established — it does not block. Keep the event loop alive afterwards (e.g. await asyncio.Event().wait()), otherwise the program exits before any events arrive. Register your @ws_client.on(...) handlers and subscribe() inside the connect handler before calling connect().