Python WebSocket: Reconnect & Heartbeats
Build a production-ready Python WebSocket client with market subscriptions, periodic heartbeats, exponential backoff, and automatic resubscription.
Core Takeaway · 30-Second Brief
A production-grade WebSocket market client requires four components: sending the subscription payload on connect, transmitting periodic application heartbeats, reconnecting with jittered exponential backoff on disconnect, and automatically resubscribing on every new connection.
01
Protocol Essentials
| Item | AllTick Specification |
|---|---|
| Equities WebSocket URL | wss://quote.alltick.co/quote-stock-b-ws-api?token=YOUR_TOKEN |
| Forex / Metals / Commodities URL | wss://quote.alltick.co/quote-b-ws-api?token=YOUR_TOKEN |
| Trade Subscription Command | cmd_id 22004 with data.symbol_list |
| Application Heartbeat | cmd_id 22000 sent every 10 seconds |
02
Complete Runnable Code
pip install websocketsimport asyncio, json, os, random, uuidimport websocketsWS_URL = "wss://quote.alltick.co/quote-stock-b-ws-api?token={token}"CMD_SUBSCRIBE_TRADE = 22004CMD_HEARTBEAT = 22000HEARTBEAT_SECONDS = 10CODES = ["700.HK", "AAPL.US"]def message(cmd_id: int, data: dict) -> str: return json.dumps({"cmd_id": cmd_id, "seq_id": 1, "trace": str(uuid.uuid4()), "data": data})async def heartbeat(ws): while True: await asyncio.sleep(HEARTBEAT_SECONDS) await ws.send(message(CMD_HEARTBEAT, {}))async def run_once(url: str): async with websockets.connect(url, ping_interval=None) as ws: await ws.send(message(CMD_SUBSCRIBE_TRADE, {"symbol_list": [{"code": c} for c in CODES]})) beat = asyncio.create_task(heartbeat(ws)) try: async for raw in ws: handle(json.loads(raw)) finally: beat.cancel()def handle(msg: dict): if msg.get("cmd_id") == CMD_HEARTBEAT + 1: return print(msg)async def main(): token = os.getenv("ALLTICK_API_TOKEN", "YOUR_API_TOKEN") url = WS_URL.format(token=token) delay = 1 while True: try: await run_once(url) delay = 1 except (websockets.WebSocketException, OSError) as exc: wait = min(delay, 60) + random.uniform(0, 1) print(f"Disconnected: {exc!r}, reconnecting in {wait:.1f}s") await asyncio.sleep(wait) delay *= 2if __name__ == "__main__": asyncio.run(main())03
Key Design Decisions
- Subscription runs inside run_once, guaranteeing automatic resubscription after every reconnect.
- Backoff starts at 1 second, doubles up to 60 seconds, and adds random jitter to prevent thundering herds.
- The heartbeat task is cancelled inside finally so it never writes to a closed socket.
- ping_interval=None disables protocol-level pings in favor of AllTick’s application-level cmd_id 22000 heartbeat.
- Heartbeat acknowledgments are filtered out in handle() to keep downstream consumers clean.
04
Production Hardening Checklist
Sources & Verification · 2026-10-13
Relevant endpoint, field, and exchange rules were checked against the primary specifications linked below.
Python examples passed ast.parse on Python 3.14.0. This checks syntax only; dependencies, runtime compatibility, and network responses were not tested.
Authenticated AllTick requests and production end-to-end tests were not run for this review. Record your token plan, library versions, market session, ret/trace, and observed results when reproducing these checks.
Primary specifications
Reproduce before deployment
- Send cmd_id 22000 every 10 seconds and inspect response 22001; the documented timeout is 30 seconds. Force disconnection and stop old heartbeat tasks before reconnecting.
- Resubscribe after recovery and check acknowledgement. Use jitter and a capped retry budget; avoid parallel reconnects exceeding token connection limits.