Streaming funding rates
Perpetual-futures funding rates update on each exchange's settlement cycle (typically every 1, 4, or 8 hours). Polling REST works, but for live dashboards or alerts you want a push stream. DataMaxi+ exposes a single multiplexed WebSocket that emits a normalised funding-rate message every time any subscribed venue settles or republishes.
By the end of this tutorial you'll have a Python script that subscribes to multiple (symbol, exchange) pairs and prints an alert when the rate crosses a threshold.
Prerequisites
- An API key — see How to get an API key.
- Python 3.8+ with the
websocketslibrary:
pip install websockets
1. Inspect the endpoint
The funding-rate stream lives at:
wss://api.datamaxiplus.com/ws/v1/funding-rate
Auth is the same X-DTMX-APIKEY header you use for REST, passed during the WS upgrade.
Full payload schema and field descriptions are in the Funding Rate WS reference. The compact payload format optimises bandwidth — every field is a single letter:
| Key | Meaning | Example |
|---|---|---|
f | Funding rate | 0.0001 |
i | Settlement interval (h) | 8 |
e | Exchange | binance |
s | Symbol | BTC-USDT |
b | Base | BTC |
q | Quote | USDT |
d | Settlement timestamp ms | 1733616000000 |
p | Processed-at ms | 1733616060000 |
2. Connect and subscribe
import asyncio
import json
import os
import websockets
DTMX_KEY = os.environ["DTMX_API_KEY"]
URL = "wss://api.datamaxiplus.com/ws/v1/funding-rate"
SUBSCRIPTIONS = [
"BTC-USDT@binance",
"BTC-USDT@bybit",
"ETH-USDT@binance",
]
async def main():
async with websockets.connect(
URL,
additional_headers={"X-DTMX-APIKEY": DTMX_KEY},
) as ws:
await ws.send(json.dumps({
"method": "SUBSCRIBE",
"params": SUBSCRIPTIONS,
"id": 1,
}))
async for raw in ws:
msg = json.loads(raw)
handle(msg)
def handle(msg):
print(msg)
asyncio.run(main())
The subscribe message identifies symbols with a {base}-{quote}@{exchange} format. The id is echoed back in the ack so you can correlate responses to requests.
3. Decode and alert
Now expand handle() to filter out subscription acks (which lack the f field) and fire an alert when funding crosses a threshold — say, |funding rate| > 0.05% (5 basis points).
THRESHOLD = 0.0005 # 0.05%
def handle(msg):
if "f" not in msg:
# subscription ack, error, or non-data frame
return
rate = msg["f"]
if abs(rate) < THRESHOLD:
return
direction = "LONGS PAY" if rate > 0 else "SHORTS PAY"
print(
f"[{msg['e']:>10}] {msg['s']:<12} "
f"{rate * 100:+.4f}% ({direction}, every {msg['i']}h)"
)
Sample output:
[ binance] BTC-USDT +0.0100% (LONGS PAY, every 8h)
[ bybit] BTC-USDT -0.0080% (SHORTS PAY, every 8h)
[ binance] ETH-USDT +0.0125% (LONGS PAY, every 8h)
4. Hand off to a real sink
Printing is the demo. In production you'd send the alert somewhere durable — Slack, Telegram, PagerDuty, your own queue. Drop a function call into handle():
import httpx
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]
def send_slack(text):
httpx.post(SLACK_WEBHOOK, json={"text": text})
Or, if you're building a strategy, push the message onto a queue and consume from your strategy worker.
Operational notes
▸ Reconnect. WebSocket connections drop — network blips, server restarts, deploys. Wrap the connect() call in a backoff loop and re-send your SUBSCRIBE after every reconnect.
▸ Backpressure. If your handler is slow, the OS receive buffer fills and the server may drop you. Push messages onto an asyncio.Queue and process in a separate task if your handler does network I/O.
▸ One stream, many symbols. A single connection can carry many subscriptions. Don't open one socket per symbol — you'll hit connection limits and waste resources.
▸ Symbol discovery. Available (symbol, exchange) pairs are listed at /api/v1/funding-rate/symbols. Hit it on startup to validate your subscription list.
Next steps
- Building an arbitrage bot — use funding rates as a signal.
- WebSocket reference — full streaming catalog.
- Premium / spread strategies — turn signals into trades.