Skip to main content

Live streaming

/v2/stream is a WebSocket endpoint for the trading day under way. It carries new rows and live bars, with history-to-live handoff.

wss://data.cyberun.cloud/v2/stream
Sec-WebSocket-Protocol: veinmesh.v2
Authorization: Bearer vmk_...

The key needs the live permission, the book_snapshot kind and a book depth. See API keys for permissions.

Subscribe​

Send a JSON message:

{"op": "subscribe", "id": "rb", "symbols": ["SHFE.rb2701"], "dataset": "book.snapshot"}
  • id is yours; it identifies the subscription on this connection.
  • symbols are public symbols or instrument_ids.
  • dataset is book.snapshot.
  • Add bars to receive bars instead of rows; its keys are the same as /v2/bars (type, interval, anchor, adjust, transform).
  • Add from for history-to-live handoff: the last resume_token, or an RFC 3339 instant on the current day.
  • fields limits row fields; the common fields are always sent.
  • numbers is string (default) or float.

The server answers:

{"type": "subscribed", "id": "rb", "catalog_version": "..."}

Send {"op":"unsubscribe","id":"rb"} to stop one subscription, or {"op":"ping"} to check that the connection is alive.

A subscription belongs to one market. Its trading day, zone and calendar are that market's. If you need symbols from two markets, open two subscriptions.

Messages​

Rows. Every new row arrives with the same shape as /v2/data:

{"type": "data", "id": "rb", "rows": [{"ts": "...", "last": "3061", "...": "..."}],
"resume_token": "..."}

With from, the rows you missed are sent first, then live rows.

Bars. With bars, the server sends every bar of the day so far, then the current bar on each change with complete: false, and once more with complete: true when it closes. A continuous contract follows the contract of the day; live bars are not back-adjusted. The contract field says which contract the bar used.

Heartbeat. {"type":"heartbeat","ts":"..."} arrives periodically.

Error. {"type":"error","id":"rb","problem":{...}}, with the same problem shape as HTTP. A slow client whose bounded queue overflows receives resync_required and the connection closes; rows are never dropped silently.

Resume and reconnect​

Each row or bar message carries a resume_token. After a disconnect, subscribe again with "from": "<resume_token>"; the server sends what you missed, then live messages, without duplicates.

  • A token is valid for a limited time; older tokens answer version_unavailable (410); use an RFC 3339 instant instead.
  • Reconnect with the last token you processed, not the last one you received, so your processing stays at-least-once.
  • If a key is revoked, the connection receives an error and closes.

Limits​

One connection holds a limited number of subscriptions and symbols; exceeding either answers 429 resource_exhausted. The numbers are in Limits.

Python​

for message in client.stream("SHFE.rb2701"):
for row in message.rows:
print(row["ts"], row["last"])

client.stream(..., bars={"interval": 60}) yields bars. The SDK reconnects after a disconnect and continues from the last row it received. It needs the websockets extra. See Python SDK.