Esta página fue traducida automáticamente. El original en inglés es la versión canónica. Leer en inglés
Saltar al contenido principal

WebSocket API

Streaming de datos en tiempo real para el trading de opciones de Hypercall.

Referencia interactiva

Consulte la Referencia interactiva de la WebSocket API para disfrutar de una mejor experiencia de navegación con ejemplos en vivo y detalles de esquema.

Especificación legible por máquina

Descargue la especificación AsyncAPI para uso programático.

Conexión

Conéctese a wss://HOST/ws:

Endpoints:

  • Producción: wss://api.hypercall.xyz/ws
  • Local: ws://localhost:3000/ws
Estado de testnet

Testnet está temporalmente deshabilitada hasta que Hypercall adquiera más HYPE de testnet.

Identificación de wallet

Para recibir datos en canales autenticados (órdenes, fills, portfolio), identifique su wallet después de conectarse enviando un mensaje Authenticate:

{"type": "Authenticate", "wallet": "0x1234..."}

El servidor responde con una confirmación:

{"type": "Authenticated", "wallet": "0x1234..."}

Tras recibir Authenticated, puede suscribirse a canales autenticados. Si la dirección de la wallet no es válida, el servidor responde con un mensaje Error y la conexión permanece abierta.

Obsoleto: autenticación por parámetro de consulta

El parámetro de consulta ?wallet= todavía se admite por compatibilidad con versiones anteriores, pero está obsoleto y se eliminará en una versión futura. Prefiera el enfoque basado en mensajes descrito arriba.

Vitalidad de la conexión

El servidor aplica un heartbeat de WebSocket:

  • Envía un frame de control Ping cada 20 segundos
  • Espera un Pong correspondiente dentro de un plazo de 60 segundos
  • Cierra la conexión con el código de cierre 1008 y el motivo pong timeout si el cliente deja de responder

Las implementaciones de WebSocket de los navegadores gestionan ping/pong automáticamente. Muchas bibliotecas de websocket de Rust, incluidas tungstenite y tokio-tungstenite, también gestionan el ping/pong de frames de control por usted. Consulte la documentación de la biblioteca de su cliente antes de agregar un manejo manual de Pong. Las implementaciones personalizadas o de socket sin procesar deben responder a los frames Ping con Pong.

Recuperación de consumidor lento

El servidor cierra una conexión /ws que no puede drenar los datos salientes dentro del límite de seguridad configurado de mensajes, bytes codificados, antigüedad de cola o escritura de socket. Cuando la conexión todavía puede aceptar un frame de cierre, el servidor usa el código 1008 y un motivo JSON compacto:

{"error":"slow_consumer","class":"ordered_public","cause":"message_age","recovery":"snapshot_resubscribe"}

Los campos del motivo son:

CampoSignificado
classClase de entrega cuyo frame cruzó el límite de seguridad.
causemessage_limit, byte_limit, message_age o write_timeout.
recoveryPróxima acción requerida, como resubscribe, snapshot_resubscribe, portfolio_refetch o rest_reconcile.

Después de cualquier desconexión, vuelva a conectarse, identifique la wallet de nuevo cuando sea necesario, vuelva a suscribirse y reconcilie el estado actual antes de procesar nuevos eventos. Los canales públicos ordenados requieren un snapshot nuevo. Los canales de eventos privados requieren reconciliación a través de la superficie REST autoritativa, ya que la reproducción por cursor aún no está disponible. Una conexión totalmente estancada puede terminar antes de poder leer el motivo de cierre, por lo que los clientes deben usar este flujo de recuperación también para un cierre no limpio.

Use conexiones separadas para datos de mercado públicos de alta frecuencia y para comandos autenticados o streams privados. Las clases de entrega seleccionan las métricas y el comportamiento de recuperación, pero los frames de una conexión siguen compartiendo una única ruta ordenada de escritura de socket. Una escritura pública estancada puede, por lo tanto, retrasar frames privados posteriores en esa misma conexión hasta que el plazo de escritura la cierre.

Suscripción a canales

Envíe un mensaje JSON para suscribirse:

{"type": "Subscribe", "channel": "orderbook"}

Para cancelar la suscripción:

{"type": "Unsubscribe", "channel": "orderbook"}

Recibirá una confirmación:

{"type": "Subscribed", "channel": "orderbook"}

Filtrado por símbolo

Los canales order_updates y fills admiten un filtro opcional symbols. Cuando se proporciona, el servidor solo envía los mensajes cuyo activo subyacente coincide con uno de los símbolos especificados.

{"type": "Subscribe", "channel": "order_updates", "symbols": ["BTC"]}

Se aceptan tanto activos subyacentes simples ("BTC") como nombres completos de instrumento ("BTC-20260131-100000-C"). Para agregar más símbolos, envíe otro Subscribe. Para eliminar símbolos específicos:

{"type": "Unsubscribe", "channel": "order_updates", "symbols": ["BTC"]}

Cuando no se especifica ningún symbols, se reenvían todas las actualizaciones de su wallet.

Filtrado de la cadena de opciones

El canal options_chain admite el filtrado por símbolos de activo subyacente, fecha de vencimiento y tipo de opción:

{
"type": "Subscribe",
"channel": "options_chain",
"symbols": ["BTC-20260131-100000-C"],
"expiry": "2026-01-31",
"option_type": "call"
}
FiltroValoresPredeterminado
symbolsArray de símbolos completos de instrumento (p. ej., ["BTC-20260131-100000-C"])Todos los instrumentos
expiryCadena de fecha "YYYY-MM-DD"Todos los vencimientos
option_type"call", "put", u omitir para ambosAmbos

Canales disponibles

CanalRequiere autenticaciónDescripción
orderbookNoActualizaciones del libro de órdenes L2 para todos los símbolos
tradesNoFeed público de operaciones
market_updatesNoCambios en el listado de mercados (creado/eliminado/vencido)
options_chainNoActualizaciones incrementales de la cadena de opciones (filtrable por symbols, expiry, option_type)
index_pricesNoPrecios spot/de índice en tiempo real para todos los activos subyacentes
indicative_market_dataNoStream de proveedores de cotizaciones en lista de permitidos. Aún no disponible de forma general
order_updatesCambios de estado de sus órdenes (filtrable por símbolo)
fillsSus fills de operaciones (filtrable por símbolo)
portfolioActualizaciones de sus posiciones y saldos
liquidationCambios en su estado de liquidación
competitionResumen de su P&L de competición, ranking y estadísticas finales
competition_engagementCambios de ranking, diferencia con el siguiente puesto y clasificación final
rfqCotizaciones RFQ, actualizaciones de estado y notificaciones de fills

Tipos de mensaje

Colocar orden (autenticado)

Coloque una orden a través de la ruta de comandos de 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..."
}
CampoTipoDescripción
walletstringDirección de wallet propietaria de la orden
symbolstringSímbolo de la opción
sidestring"Buy" o "Sell"
sizestringTamaño del contrato, coincidiendo exactamente con el valor firmado
pricestringPrecio límite, coincidiendo exactamente con el valor firmado
tifstringTime-in-force opcional, por defecto "gtc"
routestringRuta opcional. Use "book_only" para órdenes WebSocket con reconocimiento de ruta. Una ruta omitida sigue aceptándose al menos hasta el 4 de julio de 2026.
client_idstringID de orden de cliente opcional
nonceintegerNonce de firma único
signaturestringFirma EIP-712 PlaceOrder

Actualmente, PlaceOrder de WebSocket despacha directamente al libro de órdenes. route="best_execution" y route="rfq_only" se rechazan en WebSocket porque esta ruta aún no ejecuta el enrutamiento RPI/RFQ. Use POST /order para best_execution.

Actualización del libro de órdenes

Snapshot/actualización del libro de órdenes L2 para un símbolo.

{
"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
}
CampoTipoDescripción
symbolstringSímbolo de la opción
bidsarrayNiveles de bid como tuplas [price, size], el tamaño se expresa en contratos legibles por humanos
asksarrayNiveles de ask como tuplas [price, size], el tamaño se expresa en contratos legibles por humanos
timestampintegerTimestamp Unix (milisegundos)

Operación

Evento público de operación.

{
"type": "Trade",
"symbol": "BTC-20260131-100000-C",
"price": "0.0523",
"size": "5.0",
"side": "buy",
"timestamp": 1737331200000
}
CampoTipoDescripción
symbolstringSímbolo de la opción
pricestringPrecio de la operación en USD
sizestringTamaño de la operación en contratos
sidestringLado agresor (buy o sell)
timestampintegerTimestamp Unix (milisegundos)

Fill (autenticado)

Notificación de su fill de operación.

{
"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
}
CampoTipoDescripción
order_idintegerEl ID de su orden
fill_idintegerID del fill
symbolstringSímbolo de la opción
sidestringLado de la operación (buy o sell)
pricestringPrecio del fill en USD
sizestringTamaño del fill en contratos
timestampintegerTimestamp Unix (milisegundos)
wallet_addressstringLa dirección de su wallet
feestringComisión de trading cobrada. Devuelve 0 mientras las comisiones del venue de lanzamiento estén deshabilitadas
trade_idintegerID único de la operación
is_takerbooleanSi usted fue el taker
builder_code_addressstring?Wallet del builder code (si corresponde)
builder_code_feestring?Comisión del builder code. Devuelve null mientras las comisiones del venue de lanzamiento estén deshabilitadas

Actualización de portafolio (autenticado)

Actualización del stream de portafolio para posiciones, saldos, margen y Greeks.

Ejemplo de actualización de Greeks:

{
"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
}
}

Para portafolios vacíos, las actualizaciones de Greeks usan:

  • per_leg: []
  • aggregate: null

Resumen de PnL de competencia (autenticado)

Actualización del stream de competencia para mostrar el PnL en el encabezado/pie de página.

{
"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
}

Cuando no hay una competencia activa, active_competition es null.

Actualización de orden (autenticado)

Notificación de cambio de estado de una orden.

{
"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"
}

Actualización de mercado

Cambios en el listado de mercados.

Mercado creado:

{
"type": "MarketUpdate",
"action": "Created",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1737331200000
}

Mercado vencido:

{
"type": "MarketUpdate",
"action": "Expired",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1738281600000
}

Posición vencida (autenticado)

Notificación cuando su posición se liquida al vencimiento.

{
"type": "PositionExpired",
"wallet_address": "0x1234...abcd",
"symbol": "BTC-20260131-100000-C",
"position_size": "10.0",
"settlement_price": "105000",
"settlement_value": "500.0",
"timestamp": 1738281600000
}

Cambio de estado de liquidación (autenticado)

Cambio en el estado de liquidación de su cuenta.

{
"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
}
EstadoDescripción
NormalLa cuenta está saludable
WarningSe aproxima a un margin call
LiquidatingSubasta de liquidación activa

Actualización de precio índice

Precios spot/índice agrupados para todos los activos subyacentes.

{
"type": "IndexPriceUpdate",
"prices": [
{"underlying": "BTC", "price": "97250.50"},
{"underlying": "ETH", "price": "3200.00"},
{"underlying": "HYPE", "price": "28.50"}
],
"timestamp": 1737331200000
}
CampoTipoDescripción
pricesarrayArray de entradas {underlying, price} para cada activo subyacente rastreado
prices[].underlyingstringSímbolo del activo subyacente (p. ej., "BTC", "ETH")
prices[].pricestringPrecio spot/índice actual en USD
timestampintegerTimestamp Unix (milisegundos)

Datos de mercado indicativos

Stream de proveedores de cotizaciones en lista de acceso permitido con el mejor bid/ask agregado de los proveedores de cotizaciones registrados. Este canal aún no está disponible de forma general. Use los datos de mercado REST y los canales autenticados de orden/fill/portafolio a menos que Hypercall haya habilitado el streaming de proveedores de cotizaciones para su integración.

{
"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
}
CampoTipoDescripción
instrumentstringSímbolo de la opción
best_bidstringMejor precio bid agregado (opcional)
best_askstringMejor precio ask agregado (opcional)
bid_ivnumberVolatilidad implícita del mejor bid (opcional)
ask_ivnumberVolatilidad implícita del mejor ask (opcional)
indicative_bid_sizestringTamaño total del bid entre proveedores (opcional)
indicative_ask_sizestringTamaño total del ask entre proveedores (opcional)
num_providersintegerNúmero de proveedores de cotizaciones activos
timestampintegerTimestamp Unix (milisegundos)

Cambio de rango en competencia (autenticado)

Notificación cuando su rango cambia en una competencia activa.

{
"type": "CompetitionRankChange",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"from_rank": 15,
"to_rank": 12,
"delta_places": 3,
"pnl": "420.25",
"timestamp": 1737331200000
}

Actualización de diferencia en competencia (autenticado)

Distancia hasta el siguiente rango por encima de usted.

{
"type": "CompetitionGapUpdate",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"rank": 12,
"next_rank": 11,
"gap_metric_value": "50.00",
"timestamp": 1737331200000
}

Clasificación final de competencia (autenticado)

Se envía cuando una competencia termina con sus resultados finales.

{
"type": "CompetitionFinalStanding",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"rank": 12,
"pnl": "420.25",
"volume": "25000",
"efficiency": "0.01681",
"medal": null,
"timestamp": 1737331200000
}

Cotizaciones RFQ (autenticado)

Cotizaciones recibidas en respuesta a su envío de 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"
}

Actualización de estado de RFQ (autenticado)

Cambio de estado de un RFQ que usted envió.

{
"type": "RfqStatusUpdate",
"rfq_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "executed",
"taker_wallet": "0x1234...abcd"
}

Error

Mensaje de error del servidor.

{
"type": "Error",
"message": "Invalid channel: foobar"
}

Autenticación

Los canales autenticados requieren un mensaje de identificación de wallet después de conectarse:

{"type": "Authenticate", "wallet": "0x1234567890abcdef..."}

Los mensajes en canales autenticados se filtran para mostrar únicamente los datos de su wallet. No se requiere firma para las conexiones WebSocket.

Ejemplo: Cliente 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())

Ejemplo: Cliente 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`);
}
};