WebSocket API
Hypercall 期权交易的实时数据流。
请查看 交互式 WebSocket API 参考文档,获得更好的浏览体验,包含实时示例和 schema 详情。
下载 AsyncAPI 规范 以供程序化使用。
连接
连接至 wss://HOST/ws:
端点:
- 生产环境:
wss://api.hypercall.xyz/ws - 本地:
ws://localhost:3000/ws
测试网已临时禁用,直到 Hypercall 获取更多测试网 HYPE。
钱包身份识别
若要在需要身份验证的频道(订单、成交、投资组合)上接收数据,请在连接后通过发送 Authenticate 消息来识别您的钱包:
{"type": "Authenticate", "wallet": "0x1234..."}
服务器返回确认响应:
{"type": "Authenticated", "wallet": "0x1234..."}
收到 Authenticated 后,您即可订阅需要身份验证的频道。如果钱包地址无效,服务器会返回一条 Error 消息,且连接保持打开。
为向后兼容,?wallet= 查询参数仍受支持,但已弃用,并将在未来版本中移除。请优先使用上述基于消息的方式。
连接活性
服务器强制执行 WebSocket 心跳机制:
- 每 20 秒发送一个
Ping控制帧 - 期望在 60 秒内收到匹配的
Pong - 如果客户端停止应答,则以关闭码
1008和原因pong timeout关闭连接
浏览器的 WebSocket 实现会自动处理 ping/pong。许多 Rust WebSocket 库,包括 tungstenite 和 tokio-tungstenite,也会为您处理控制帧的 ping/pong。在添加手动 Pong 处理之前,请查阅您所用客户端库的文档。自定义或原始套接字实现必须以 Pong 回复 Ping 帧。
慢消费者恢复
如果某个 /ws 连接无法在配置的消息、编码字节、队列存活时长或套接字写入安全上限内排空待发送数据,服务器将关闭该连接。当连接仍能接受关闭帧时,服务器会使用关闭码 1008 和一段紧凑的 JSON 原因:
{"error":"slow_consumer","class":"ordered_public","cause":"message_age","recovery":"snapshot_resubscribe"}
原因字段如下:
| 字段 | 含义 |
|---|---|
class | 帧越过安全边界的投递类别。 |
cause | message_limit、byte_limit、message_age 或 write_timeout。 |
recovery | 所需的后续操作,例如 resubscribe、snapshot_resubscribe、portfolio_refetch 或 rest_reconcile。 |
在任何断开连接之后,请重新连接,在需要时再次识别钱包,重新订阅,并在处理新事件之前对当前状态进行核对。有序的公共频道需要重新获取快照。私有事件频道需要通过权威的 REST 接口进行核对,因为游标回放功能尚不可用。完全停滞的连接可能在读取关闭原因之前就已终止,因此客户端对于非正常关闭也必须使用此恢复流程。
请为高速率的公共市场数据与需要身份验证的命令或私有流使用各自独立的连接。投递类别决定指标与恢复行为,但同一连接上的各帧仍共享一条有序的套接字写入路径。因此,停滞的公共写入可能会延迟该连接上后续的私有帧,直到写入截止时间将其关闭。
订阅频道
发送一条 JSON 消息以进行订阅:
{"type": "Subscribe", "channel": "orderbook"}
取消订阅:
{"type": "Unsubscribe", "channel": "orderbook"}
您将收到一条确认消息:
{"type": "Subscribed", "channel": "orderbook"}
标的过滤
order_updates 和 fills 频道支持一个可选的 symbols 过滤器。提供后,服务器仅发送其标的资产匹配指定标的之一的消息。
{"type": "Subscribe", "channel": "order_updates", "symbols": ["BTC"]}
既接受裸标的("BTC"),也接受完整合约名称("BTC-20260131-100000-C")。若要添加更多标的,请再发送一条 Subscribe。若要移除特定标的:
{"type": "Unsubscribe", "channel": "order_updates", "symbols": ["BTC"]}
未指定 symbols 时,将转发您钱包的所有更新。
期权链过滤
options_chain 频道支持按标的资产、到期日和期权类型进行过滤:
{
"type": "Subscribe",
"channel": "options_chain",
"symbols": ["BTC-20260131-100000-C"],
"expiry": "2026-01-31",
"option_type": "call"
}
| 过滤器 | 取值 | 默认值 |
|---|---|---|
symbols | 完整合约标的的数组(例如 ["BTC-20260131-100000-C"]) | 所有合约 |
expiry | 日期字符串 "YYYY-MM-DD" | 所有到期日 |
option_type | "call"、"put",或省略以表示两者 | 两者 |
可用频道
| 频道 | 需要身份验证 | 描述 |
|---|---|---|
orderbook | 否 | 所有标的的 L2 订单簿更新 |
trades | 否 | 公共成交流 |
market_updates | 否 | 市场挂牌变动(创建/删除/到期) |
options_chain | 否 | 增量期权链更新(可按标的、到期日、期权类型过滤) |
index_prices | 否 | 所有标的资产的实时现货/指数价格 |
indicative_market_data | 否 | 白名单报价方数据流。尚未普遍可用 |
order_updates | 是 | 您的订单状态变动(可按标的过滤) |
fills | 是 | 您的成交(可按标的过滤) |
portfolio | 是 | 您的持仓与余额更新 |
liquidation | 是 | 您的强制平仓状态变动 |
competition | 是 | 您的竞赛盈亏汇总、排名和最终统计数据 |
competition_engagement | 是 | 排名变动、与下一名的差距,以及最终排名 |
rfq | 是 | RFQ 报价、状态更新和成交通知 |
消息类型
下单(需身份验证)
通过 WebSocket 命令路径下单。
{
"type": "PlaceOrder",
"wallet": "0x1234...",
"symbol": "BTC-20260131-100000-C",
"side": "Buy",
"size": "1",
"price": "100",
"tif": "gtc",
"route": "book_only",
"client_id": "my-order-1",
"nonce": 1000,
"signature": "0x..."
}
| 字段 | 类型 | 描述 |
|---|---|---|
wallet | string | 拥有该订单的钱包地址 |
symbol | string | 期权标的 |
side | string | "Buy" 或 "Sell" |
size | string | 合约规模,须与签名值完全一致 |
price | string | 限价,须与签名值完全一致 |
tif | string | 可选的有效期,默认为 "gtc" |
route | string | 可选的路由。对于路由感知的 WebSocket 订单,请使用 "book_only"。省略路由在至少 2026 年 7 月 4 日之前仍受接受。 |
client_id | string | 可选的客户端订单 ID |
nonce | integer | 唯一的签名 nonce |
signature | string | EIP-712 PlaceOrder 签名 |
WebSocket PlaceOrder 目前直接分发至订单簿。route="best_execution" 和 route="rfq_only" 在 WebSocket 上会被拒绝,因为此路径尚未运行 RPI/RFQ 路由。对于 best_execution,请使用 POST /order。
订单簿更新
某个标的的 L2 订单簿快照/更新。
{
"type": "OrderbookUpdate",
"symbol": "BTC-20260131-100000-C",
"bids": [["95000.5", "10.5"], ["94999.0", "25.0"]],
"asks": [["95001.0", "8.0"], ["95002.5", "15.0"]],
"timestamp": 1737331200000
}
| 字段 | 类型 | 描述 |
|---|---|---|
symbol | string | 期权标的 |
bids | array | 买价档位,格式为 [price, size] 元组,size 以人类可读的合约数计 |
asks | array | 卖价档位,格式为 [price, size] 元组,size 以人类可读的合约数计 |
timestamp | integer | Unix 时间戳(毫秒) |
成交
公共成交事件。
{
"type": "Trade",
"symbol": "BTC-20260131-100000-C",
"price": "0.0523",
"size": "5.0",
"side": "buy",
"timestamp": 1737331200000
}
| 字段 | 类型 | 描述 |
|---|---|---|
symbol | string | 期权标的 |
price | string | 以美元计的成交价 |
size | string | 以合约数计的成交规模 |
side | string | 主动方(buy 或 sell) |
timestamp | integer | Unix 时间戳(毫秒) |
成交(需身份验证)
您的成交通知。
{
"type": "Fill",
"order_id": 12345,
"fill_id": 67890,
"symbol": "BTC-20260131-100000-C",
"side": "buy",
"price": "0.0523",
"size": "5.0",
"timestamp": 1737331200000,
"wallet_address": "0x1234...abcd",
"fee": "0",
"trade_id": 99999,
"is_taker": true
}
| 字段 | 类型 | 说明 |
|---|---|---|
order_id | integer | 您的订单 ID |
fill_id | integer | 成交 ID |
symbol | string | 期权代码 |
side | string | 交易方向(buy 或 sell) |
price | string | 成交价格(美元) |
size | string | 成交数量(合约张数) |
timestamp | integer | Unix 时间戳(毫秒) |
wallet_address | string | 您的钱包地址 |
fee | string | 收取的交易费用。在启动场所费用停用期间返回 0 |
trade_id | integer | 唯一交易 ID |
is_taker | boolean | 您是否为吃单方 |
builder_code_address | string? | 构建者代码钱包(如有) |
builder_code_fee | string? | 构建者代码费用。在启动场所费用停用期间返回 null |
投资组合更新(需认证)
针对持仓、余额、保证金及希腊字母指标的投资组合流更新。
希腊字母指标更新示例:
{
"type": "PortfolioUpdate",
"timestamp": 1737331200000,
"per_leg": [
{
"symbol": "BTC-20260131-100000-C",
"quantity": "2.0",
"delta": 0.91,
"gamma": 0.003,
"theta": -0.12,
"vega": 0.44,
"iv": 0.63
}
],
"aggregate": {
"delta": 0.91,
"gamma": 0.003,
"theta": -0.12,
"vega": 0.44,
"iv": 0.63
}
}
对于空投资组合,希腊字母指标更新采用:
per_leg: []aggregate: null
竞赛盈亏摘要(需认证)
用于页眉/页脚盈亏显示的竞赛流更新。
{
"type": "CompetitionPnlSummary",
"wallet_address": "0x1234...abcd",
"lifetime_realized_pnl": "1250.50",
"active_competition": {
"competition_id": 7,
"competition_name": "Spring Sprint",
"competition_state": "active",
"rank": 12,
"pnl": "420.25",
"volume": "25000",
"efficiency": "0.01681",
"medal": null
},
"timestamp": 1737331200000
}
当没有正在进行的竞赛时,active_competition 为 null。
订单更新(需认证)
订单状态变更通知。
{
"type": "OrderUpdate",
"order_id": 12345,
"client_order_id": "my-order-1",
"status": "filled",
"filled_size": "10.0",
"remaining_size": "0",
"avg_fill_price": "0.0523"
}
市场更新
市场挂牌变更。
市场已创建:
{
"type": "MarketUpdate",
"action": "Created",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1737331200000
}
市场已到期:
{
"type": "MarketUpdate",
"action": "Expired",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1738281600000
}
持仓到期(需认证)
当您的持仓在到期时结算时的通知。
{
"type": "PositionExpired",
"wallet_address": "0x1234...abcd",
"symbol": "BTC-20260131-100000-C",
"position_size": "10.0",
"settlement_price": "105000",
"settlement_value": "500.0",
"timestamp": 1738281600000
}
强制平仓状态变更(需认证)
您账户的强制平仓状态变更。
{
"type": "LiquidationStateChange",
"wallet_address": "0x1234...abcd",
"previous_state": "Normal",
"new_state": "Warning",
"equity": "10000.0",
"mm_required": "9500.0",
"shortfall": "0",
"auction_id": null,
"timestamp": 1737331200000
}
| 状态 | 说明 |
|---|---|
Normal | 账户状况健康 |
Warning | 接近追加保证金通知 |
Liquidating | 强制平仓拍卖进行中 |
指数价格更新
所有标的资产的批量现货/指数价格。
{
"type": "IndexPriceUpdate",
"prices": [
{"underlying": "BTC", "price": "97250.50"},
{"underlying": "ETH", "price": "3200.00"},
{"underlying": "HYPE", "price": "28.50"}
],
"timestamp": 1737331200000
}
| 字段 | 类型 | 说明 |
|---|---|---|
prices | array | 每个跟踪标的资产的 {underlying, price} 条目数组 |
prices[].underlying | string | 标的资产代码(例如 "BTC"、"ETH") |
prices[].price | string | 当前现货/指数价格(美元) |
timestamp | integer | Unix 时间戳(毫秒) |
指示性市场数据
来自已注册报价提供方的白名单报价提供方流,包含聚合的最优买价/卖价。此频道尚未普遍开放。除非 Hypercall 已为您的集成启用报价提供方流传输,否则请使用 REST 市场数据以及经认证的订单/成交/投资组合频道。
{
"type": "IndicativeMarketData",
"instrument": "BTC-20260131-100000-C",
"best_bid": "0.0520",
"best_ask": "0.0530",
"indicative_bid_size": "50.0",
"indicative_ask_size": "25.0",
"num_providers": 3,
"timestamp": 1737331200000
}
| 字段 | 类型 | 说明 |
|---|---|---|
instrument | string | 期权代码 |
best_bid | string | 可选的最优聚合买价 |
best_ask | string | 可选的最优聚合卖价 |
bid_iv | number | 可选的最优买价隐含波动率 |
ask_iv | number | 可选的最优卖价隐含波动率 |
indicative_bid_size | string | 可选的各提供方买单总量 |
indicative_ask_size | string | 可选的各提供方卖单总量 |
num_providers | integer | 活跃报价提供方数量 |
timestamp | integer | Unix 时间戳(毫秒) |
竞赛排名变更(需认证)
当您在正在进行的竞赛中的排名发生变化时的通知。
{
"type": "CompetitionRankChange",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"from_rank": 15,
"to_rank": 12,
"delta_places": 3,
"pnl": "420.25",
"timestamp": 1737331200000
}
竞赛差距更新(需认证)
与您上方下一名次之间的距离。
{
"type": "CompetitionGapUpdate",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"rank": 12,
"next_rank": 11,
"gap_metric_value": "50.00",
"timestamp": 1737331200000
}
竞赛最终排名(需认证)
在竞赛结束时发送,包含您的最终成绩。
{
"type": "CompetitionFinalStanding",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"rank": 12,
"pnl": "420.25",
"volume": "25000",
"efficiency": "0.01681",
"medal": null,
"timestamp": 1737331200000
}
RFQ 报价(需认证)
针对您提交的 RFQ 所收到的报价。
{
"type": "RfqQuotes",
"rfq_id": "550e8400-e29b-41d4-a716-446655440000",
"quotes": [
{
"quote_id": "660e8400-e29b-41d4-a716-446655440001",
"net_premium": "52.30",
"expires_at": 1737331225000
}
],
"status": "quoted",
"taker_wallet": "0x1234...abcd"
}
RFQ 状态更新(需认证)
您所提交的 RFQ 的状态变更。
{
"type": "RfqStatusUpdate",
"rfq_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "executed",
"taker_wallet": "0x1234...abcd"
}
错误
服务器错误消息。
{
"type": "Error",
"message": "Invalid channel: foobar"
}
认证
认证频道在连接后需要发送一条钱包身份识别消息:
{"type": "Authenticate", "wallet": "0x1234567890abcdef..."}
认证频道上的消息经过筛选,仅显示您钱包的数据。WebSocket 连接无需签名。
示例:Python 客户端
import asyncio
import websockets
import json
async def main():
uri = "wss://api.hypercall.xyz/ws"
async with websockets.connect(uri) as ws:
# Identify the wallet before subscribing to authenticated channels.
await ws.send(json.dumps({
"type": "Authenticate",
"wallet": "0xYourWallet"
}))
# Subscribe to orderbook
await ws.send(json.dumps({
"type": "Subscribe",
"channel": "orderbook"
}))
# Subscribe to fills for BTC only
await ws.send(json.dumps({
"type": "Subscribe",
"channel": "fills",
"symbols": ["BTC"]
}))
# Listen for messages
async for message in ws:
data = json.loads(message)
print(f"Received: {data['type']}")
asyncio.run(main())
示例:TypeScript 客户端
const ws = new WebSocket("wss://api.hypercall.xyz/ws");
ws.onopen = () => {
ws.send(JSON.stringify({ type: "Authenticate", wallet: "0xYourWallet" }));
// Subscribe to channels
ws.send(JSON.stringify({ type: "Subscribe", channel: "orderbook" }));
// Subscribe to order updates filtered to BTC
ws.send(JSON.stringify({
type: "Subscribe",
channel: "order_updates",
symbols: ["BTC"],
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(`Received: ${msg.type}`);
if (msg.type === "OrderbookUpdate") {
console.log(`${msg.symbol}: ${msg.bids.length} bids, ${msg.asks.length} asks`);
}
};