El WebSocket de Tradovate se cierra exactamente a los 5 minutos
El socket transmite perfectamente durante 300 segundos y luego se cae sin error ni aviso. Esto es lo que realmente lo cierra, la cadencia de heartbeat que lo extiende y el patrón de reconexión que convierte la caída en algo irrelevante.
On This Page
- Qué significa «El WebSocket se cierra exactamente a los 5 minutos»
- Principales causas del cierre del WebSocket a los 5 minutos en 2026
- 1. Frames de heartbeat que llegan tarde o no llegan
- 2. Limitación de temporizadores del navegador (setInterval / setTimeout)
- 3. Tiempo de espera de inactividad o de sesión del lado del servidor
- 4. Enviar en un socket que no está OPEN (readyState 0)
- 5. Caducidad del token y conexiones de larga duración
- Cómo arreglar el cierre del WebSocket a los 5 minutos: paso a paso
- Solución 1: envíe un frame de heartbeat aproximadamente cada 2,5 segundos
- Solución 2: sustituya setInterval por una comprobación de marca de tiempo o un Web Worker
- Solución 3: proteja cada envío con una comprobación de readyState
- Solución 4: añada lógica de reconexión, reautorización y resuscripción
- Tabla de solución de problemas
- Evite esto con PickMyTrade
Cuando automatiza valores rápidos como ES o NQ, pocas cosas duelen más que un WebSocket de Tradovate que muere por un temporizador. Se conecta, autoriza, se suscribe a datos de mercado y todo fluye de maravilla, justo hasta los 300 segundos, cuando el socket se cae sin error, sin motivo de cierre, sin aviso. Es la misma historia cada vez: la conexión se cierra exactamente a los 5 minutos, incluso cuando sus heartbeats parecen dispararse correctamente. Normalmente aparecen dos errores relacionados, una excepción WebSocket is not open: readyState 0 (CONNECTING) cuando su código escribe en un socket medio abierto, y un simple código de cierre 1006 (cierre anormal) del extremo remoto. Esto es lo que significa realmente el cierre a los 5 minutos en 2026, las causas reales y el patrón exacto de heartbeat más reconexión que mantiene viva la conexión, además de cómo PickMyTrade ejecuta esta infraestructura por usted para que un socket caído nunca le cueste una ejecución.
Lista rápida para el cierre del WebSocket a los 5 minutos
- Envíe un heartbeat aproximadamente cada 2,5 segundos, un frame cuyo texto es un array JSON vacío,
[]. Si lo omite, Tradovate cierra el socket por inactividad. - No confíe en setInterval en una pestaña del navegador, las pestañas en segundo plano se limitan, su heartbeat se retrasa más de 2,5 s y el servidor cuelga.
- Envíe sus propios heartbeats, una vez que fluyen los datos en tiempo real, el servidor deja de enviarlos, así que el cliente tiene que mantener el ritmo.
- Proteja cada envío con una comprobación de readyState, escriba solo cuando el socket esté OPEN (1), nunca mientras siga en CONNECTING (0).
- Registre el evento de cierre,
ws.addEventListener('close', e => console.log(e))revela el código (a menudo 1006) y cualquier motivo. - Asuma que habrá caídas y reconecte, envuelva el socket para que un cierre vuelva a autorizar y a suscribirse automáticamente.
Qué significa «El WebSocket se cierra exactamente a los 5 minutos»
La API en tiempo real de Tradovate es una conexión WebSocket: la abre, envía un frame de autorización y luego se suscribe a los datos y eventos que le interesan. Para mantener abierta esa conexión, el cliente es responsable de enviar heartbeats, pequeños frames de keep-alive, con una cadencia fija. Si deja de enviarlos, Tradovate considera el socket inactivo y lo cierra desde el lado del servidor.
El motivo por el que el fallo cae con tanta frecuencia en la marca exacta de 5 minutos es que los tiempos de espera a lo largo de la ruta de red, el servidor, un balanceador de carga o un proxy intermedio, tienden a aplicarse en cifras redondas. La conexión se desconecta exactamente cada 5 minutos (300 segundos) sin mensaje y, significativamente, sin heartbeats la caída ocurre en cambio a los 2 minutos aproximadamente. Así que los heartbeats prolongan la vida del socket, pero un heartbeat retrasado o perdido, o un temporizador de inactividad independiente en algún punto de la ruta, aún puede guillotinarlo a los 300 segundos. No hay una causa raíz publicada para el caso exacto de 5 minutos, así que la respuesta de ingeniería duradera no es evitar cada cierre, sino sobrevivirlo.
Los dos mensajes de error que verá son síntomas del mismo problema de fondo. WebSocket is not open: readyState 0 (CONNECTING) significa que su código intentó send() antes de que terminara el handshake, algo habitual dentro de una función de heartbeat que se dispara en plena reconexión. El código de cierre 1006 es la forma que tienen el navegador o la biblioteca de decir “la conexión se cayó de forma anormal”, sin handshake de cierre limpio, exactamente lo que ocurre cuando un temporizador de inactividad del servidor corta la línea.
Principales causas del cierre del WebSocket a los 5 minutos en 2026
1. Frames de heartbeat que llegan tarde o no llegan
Esta es la causa número uno. Tradovate espera un frame de heartbeat, con contenido de texto [], aproximadamente cada 2,5 segundos para comprobar que el cliente está vivo. Si pierde esa ventana, el servidor inicia la cuenta atrás para cerrar. Y aquí está el problema: una vez que empieza a transmitir cotizaciones en tiempo real, el servidor de Tradovate deja de enviar sus propios heartbeats, así que no puede apoyarse en el tráfico integrado de la conexión para mantenerla abierta. Su cliente tiene que enviar el frame de corchetes vacíos según su propio calendario.
2. Limitación de temporizadores del navegador (setInterval / setTimeout)
Si programa heartbeats con setInterval() o setTimeout() en un navegador, queda a merced de la prioridad de la pestaña. Cuando la pestaña pierde el foco, Chrome (y la mayoría de los navegadores) reducen la prioridad de esos temporizadores, de modo que un intervalo de “2,5 segundos” puede estirarse sin avisar a varios segundos. El heartbeat se pasa del plazo y el socket se cierra, a menudo justo alrededor de la marca de 5 minutos, cuando se ha acumulado suficiente retraso.
3. Tiempo de espera de inactividad o de sesión del lado del servidor
Ni siquiera un heartbeat perfectamente espaciado puede anular un tiempo de espera aplicado aguas arriba. Un proxy, una pasarela o la propia sesión de Tradovate pueden limitar el tiempo de inactividad o la duración total de la conexión, por lo que el cierre cae en esa sospechosa frontera redonda de 300 segundos. Como esto escapa a su control, la solución es la reconexión, no la prevención.
4. Enviar en un socket que no está OPEN (readyState 0)
Un WebSocket tiene cuatro estados: CONNECTING (0), OPEN (1), CLOSING (2) y CLOSED (3). Si su bucle de heartbeat o su código de órdenes llama a send() mientras el socket aún está en readyState 0, obtiene WebSocket is not open: readyState 0 (CONNECTING) y, a menudo, un mensaje “Disconnected from Tradovate Market WebSocket” justo detrás. Esto duele más en el instante posterior a una caída, cuando su reconexión ha levantado un socket nuevo que aún no completó su handshake.
5. Caducidad del token y conexiones de larga duración
Un token de acceso de Tradovate tiene una vida limitada, y estas conexiones no están hechas para vivir para siempre; si mantiene un único socket abierto durante periodos muy largos (más de un día), tiende a caerse. Si su token caduca a mitad de sesión o la conexión envejece, el socket se cierra y cualquier reautorización con el token antiguo falla. La duración de los tokens varía y cambia con el tiempo, así que confirme los valores actuales en la documentación de la API de Tradovate y renueve de forma proactiva en lugar de esperar a un fallo.
Cómo arreglar el cierre del WebSocket a los 5 minutos: paso a paso
Solución 1: envíe un frame de heartbeat aproximadamente cada 2,5 segundos
El heartbeat es la base. Con una cadencia de aproximadamente cada 2,5 segundos, envíe un frame cuyo texto sea un array JSON vacío:
Inicie la rutina de keep-alive
Después de que el socket se abra y de haber autorizado, inicie una rutina de keep-alive.
Envíe el frame de corchetes vacíos
En cada tick, llame a ws.send('[]'), el frame de corchetes vacíos es el heartbeat de Tradovate.
Mantenga el intervalo por debajo de 2,5 s
Mantenga el intervalo cómodamente por debajo del límite (2,5 segundos es el objetivo; un poco más a menudo es más seguro que un poco menos).
Nunca asuma pings del servidor
Nunca dé por hecho que el servidor le hará ping, una vez que comienzan a transmitirse datos, no lo hará.
Solución 2: sustituya setInterval por una comprobación de marca de tiempo o un Web Worker
Como los temporizadores del navegador se limitan, no se apoye solo en setInterval, ni en una pestaña en primer plano ni en segundo plano. Dos alternativas probadas:
- Heartbeats guiados por marca de tiempo. Registre una marca de tiempo (
new Date()) cada vez que reciba un mensaje. Compárela con la última vez que envió un heartbeat; si han transcurrido más de 2500 ms, envíe[]ahora. Esto reacciona al tráfico real en lugar de a un temporizador que el navegador puede dejar sin recursos. - Saque el temporizador del hilo principal. Ejecute el heartbeat dentro de un Web Worker o ejecute toda la conexión como un servicio Node.js. Ambos evitan por completo la limitación de pestañas del navegador, un proceso de Node no está sujeto en absoluto a la penalización de las pestañas en segundo plano.
Solución 3: proteja cada envío con una comprobación de readyState
Elimine el error de readyState 0 no escribiendo nunca en un socket que no esté abierto:
Compruebe readyState antes de cada envío
Antes de cada send(), sea heartbeat u orden, compruebe if (ws.readyState === WebSocket.OPEN) (es decir, el estado 1).
Omita y deje que la lógica de reconexión se encargue
Si todavía está en CONNECTING (0) o ya en CLOSING/CLOSED, omita el envío y deje que su lógica de reconexión tome el relevo.
Adjunte listeners para todas las transiciones de estado
Adjunte listeners para open, message, error y close para que las transiciones de estado sean explícitas, y registre el objeto del evento close para capturar el código y el motivo.
Solución 4: añada lógica de reconexión, reautorización y resuscripción
Como algunos cierres a los 5 minutos se aplican aguas arriba y no se pueden evitar, trate cada caída como un error recuperable y reconstruya automáticamente:
Envuelva el socket
Envuelva el socket en una clase o función que posea su ciclo de vida, de modo que un único lugar sea responsable de crearlo y destruirlo.
Reconecte al cerrarse
Al cerrarse, reconecte, abra un socket nuevo en lugar de intentar revivir el muerto.
Vuelva a autorizar el nuevo socket
Vuelva a autorizar el nuevo socket con un token válido (regenere el token antes de que caduque para que siempre haya uno nuevo listo).
Vuelva a suscribirse a todo
Vuelva a suscribirse a todo lo que tenía, reenvíe su user/syncrequest y suscríbase de nuevo a cada feed de datos de mercado, porque un socket nuevo empieza sin suscripciones.
Espere a OPEN antes de enviar
Espere a OPEN antes de enviar nada en el nuevo socket y añada un breve backoff para que una conexión inestable no sature al servidor.
Tabla de solución de problemas
| Error / señal | Qué significa | Solución |
|---|---|---|
| El socket se cierra exactamente a los 300 s | Un tiempo de espera de inactividad o de sesión en la ruta cortó la conexión | Envíe heartbeats cada ~2,5 s y reconecte automáticamente al cerrarse |
| Se cae a los ~2 minutos | No se envía ningún heartbeat | Inicie un keep-alive que envíe el frame [] con cadencia de 2,5 s |
| WebSocket is not open: readyState 0 (CONNECTING) | El código llamó a send() antes de que terminara el handshake | Envíe solo cuando readyState === OPEN (1); omita en caso contrario |
| Código de cierre 1006 | Cierre anormal sin handshake limpio | Reconecte al cerrarse, vuelva a autorizar y vuelva a suscribirse |
| «Disconnected from Tradovate Market WebSocket» | El socket se cayó a mitad de flujo | Reconstruya el socket y restaure sus suscripciones |
| Heartbeats bien, pero la pestaña estaba inactiva | El navegador limitó setInterval/setTimeout | Use heartbeats basados en marcas de tiempo o un Web Worker / Node.js |
| Caída tras un tiempo de actividad muy largo | Token caducado o la conexión envejeció | Renueve el token antes de que caduque y reconecte según un calendario |
Evite esto con PickMyTrade
PickMyTrade se sitúa entre sus alertas de TradingView y Tradovate y ejecuta la capa de WebSocket como un servicio gestionado del lado del servidor, de modo que el cierre a los 5 minutos se gestiona antes de que llegue a usted:
- Heartbeats gestionados, envía el frame de keep-alive con una cadencia fiable del lado del servidor, sin pestaña de navegador que limite el temporizador.
- Auto-Reconnect & Re-Auth, detecta un socket caído, abre uno nuevo, vuelve a autorizar con un token válido y se resuscribe automáticamente.
- Protecciones de estado de conexión, solo transmite cuando el socket está realmente abierto, eliminando los errores de envío con readyState 0.
- Multi-Account Sync, mantiene sano el flujo de cada cuenta conectada para que una única reconexión nunca deje atrás a una cuenta.
Opere sin rechazos
Comience su prueba gratuita de 7 días, vincule sus alertas hoy y opere sin rechazos.
Comience su prueba gratuita de 7 díasPreguntas frecuentes
El socket se cierra por un tiempo de espera por inactividad o de sesión en la ruta de conexión, que suele dispararse en cifras redondas como 300 segundos. Enviar heartbeats prolonga la conexión, pero si un heartbeat se retrasa o salta un temporizador aguas arriba, el socket se cae de todos modos. La solución fiable es heartbeats más reconexión automática.
Aproximadamente cada 2,5 segundos. El heartbeat es un frame cuyo texto es un array JSON vacío, []. Enviar algo más a menudo que cada 2,5 segundos es más seguro que arriesgarse a un frame tardío.
Solo [], un array JSON vacío enviado como texto del mensaje WebSocket. Ese frame de corchetes vacíos es lo que Tradovate interpreta como keep-alive.
Su código llamó a send() mientras el socket aún estaba en el handshake (estado 0), todavía no OPEN (estado 1). Compruebe readyState antes de cada envío y omita la escritura hasta que el socket indique OPEN, dejando que su lógica de reconexión termine primero.
No una vez que se transmiten datos en tiempo real. El servidor deja de enviar heartbeats después de que comienza el flujo de datos, así que el cliente debe enviar los suyos en la cadencia de 2,5 segundos. No puede confiar en el tráfico del servidor para mantener abierta la conexión.
Los navegadores limitan setInterval y setTimeout en pestañas inactivas, estirando su heartbeat de 2,5 segundos por encima del límite. Use heartbeats basados en marcas de tiempo ligadas a los mensajes recibidos, o ejecute la conexión en un Web Worker o en un proceso de Node.js para evitar por completo la limitación de pestañas.
El código 1006 es un cierre anormal sin handshake de cierre limpio, normalmente una conexión caída o un tiempo de espera del servidor. No intente prevenir todos los 1006; envuelva el socket, reconecte al cerrarse, vuelva a autorizar con un token nuevo y vuelva a suscribirse a sus feeds.
Esta guía tiene fines exclusivamente educativos e informativos y no constituye asesoramiento financiero, de inversión ni de trading. Operar con futuros y otros productos apalancados conlleva un riesgo sustancial de pérdida y no es adecuado para todos los inversores. PickMyTrade es una plataforma de automatización independiente de terceros y no está afiliada, respaldada ni patrocinada por Tradovate, Inc. «Tradovate» y todos los nombres, logotipos y marcas relacionados son propiedad de sus respectivos titulares. Las funciones de la plataforma y los pasos cambian con el tiempo, por lo que debe confirmar siempre el proceso vigente en la plataforma y la documentación oficiales de Tradovate antes de actuar.