Developer docs

WebSocket 实时推送

高级版专属:逐笔成交与报价实时推送,协议与 Polygon WebSocket 一致。

Advanced 套餐专属。连接地址 wss://marilux.dev/stocks,协议和 Polygon 官方 WebSocket 完全一致:连上先鉴权,鉴权成功后按需订阅,之后行情会持续推过来,直到你退订或断开。

1. 连接后会先收到:

[{"ev":"status","status":"connected","message":"Connected Successfully"}]

2. 发送鉴权消息:

{"action":"auth","params":"mh_live_your_key"}

成功返回 auth_success;套餐不是 Advanced、Key 已停用/过期、或超出套餐的并发连接数上限都会返回 auth_failed,原因见 message(连接数超限时会带上你的上限)。连接建立后须在 10 秒内鉴权成功,否则服务端会以关闭码 1008 断开连接,鉴权失败的连接同样会被断开,请修正原因后重新连接。

[{"ev":"status","status":"auth_success","message":"authenticated"}]

3. 订阅标的:params 是"事件类型.股票代码",逗号分隔可以一次订阅多个,事件类型 T=逐笔成交、Q=逐笔报价。

{"action":"subscribe","params":"T.AAPL,Q.AAPL,T.MSFT"}

订阅成功返回:

[{"ev":"status","status":"success","message":"subscribed to: T.AAPL,Q.AAPL"}]

订阅数超出套餐上限时,超出的部分会被拒绝,已订阅的部分不受影响,并额外收到一条错误消息列出未订阅的标的:

[{"ev":"status","status":"error","message":"已达到套餐订阅股票数上限(200 只),未订阅: T.MSFT"}]

4. 行情推送——数组形式,可能一次包含多条:

[{"ev":"T","sym":"AAPL","x":12,"i":"133121","p":334.8,"s":5,"c":[12,14,37,41],"t":1789775989256756500}]

订阅上限按股票数计算:同一只股票同时订阅成交(T.AAPL)和报价(Q.AAPL)只算 1 只。暂不支持通配符(*)订阅全市场。各档位上限:

  • 高级版体验:1 个连接,10 只股票
  • 高级版月付/季付:2 个连接,200 只股票
  • 高级版半年付:3 个连接,500 只股票
  • 高级版年付:5 个连接,500 只股票

断线重连:如果你的程序处理消息太慢、服务端待发送的数据积压超过 2MB,连接会以关闭码 1013 断开,以免拖累其他客户;服务器维护重启时连接也会断开。请务必实现自动重连,重连后重新发送 auth 和 subscribe。

退订用 {"action":"unsubscribe","params":"T.AAPL"}。不再需要某个标的记得退订,不退订不会额外收费,但会一直占着你套餐的订阅数配额。

Node.js 示例:

const ws = new WebSocket("wss://marilux.dev/stocks");
ws.onmessage = (event) => {
  const msgs = JSON.parse(event.data);
  for (const m of msgs) {
    if (m.status === "connected") ws.send(JSON.stringify({ action: "auth", params: "mh_live_your_key" }));
    if (m.status === "auth_success") ws.send(JSON.stringify({ action: "subscribe", params: "T.AAPL" }));
    if (m.ev === "T") console.log("成交:", m.sym, m.p, m.s);
  }
};

Python 示例:(pip install websockets)

import asyncio, json, websockets

async def main():
    async with websockets.connect("wss://marilux.dev/stocks") as ws:
        async for raw in ws:
            for m in json.loads(raw):
                if m.get("status") == "connected":
                    await ws.send(json.dumps({"action": "auth", "params": "mh_live_your_key"}))
                elif m.get("status") == "auth_success":
                    await ws.send(json.dumps({"action": "subscribe", "params": "T.AAPL"}))
                elif m.get("ev") == "T":
                    print("成交:", m["sym"], m["p"], m["s"])

asyncio.run(main())