Le WebSocket Tradovate se ferme exactement au bout de 5 minutes
Le socket diffuse parfaitement pendant 300 secondes, puis tombe sans erreur ni avertissement. Voici ce qui le ferme réellement, la cadence de heartbeat qui le prolonge et le schéma de reconnexion qui fait de la coupure un non-événement.
On This Page
- Ce que signifie « le WebSocket se ferme exactement au bout de 5 minutes »
- Principales causes de la fermeture du WebSocket à 5 minutes en 2026
- 1. Trames de heartbeat tardives ou totalement absentes
- 2. Bridage des minuteurs du navigateur (setInterval / setTimeout)
- 3. Délai d'inactivité ou de session côté serveur
- 4. Envoi sur un socket qui n'est pas OPEN (readyState 0)
- 5. Expiration du jeton et connexions de longue durée
- Comment corriger la fermeture du WebSocket à 5 minutes : pas à pas
- Solution 1 : envoyer une trame de heartbeat environ toutes les 2,5 secondes
- Solution 2 : remplacer setInterval par une vérification d'horodatage ou un Web Worker
- Solution 3 : protéger chaque envoi par une vérification de readyState
- Solution 4 : ajouter une logique de reconnexion, de réautorisation et de réabonnement
- Tableau de dépannage
- Évitez cela avec PickMyTrade
Quand vous automatisez des valeurs rapides comme ES ou NQ, peu de choses font plus mal qu'un WebSocket Tradovate qui meurt sur un minuteur. Vous vous connectez, autorisez, vous abonnez aux données de marché, et tout se diffuse à merveille, jusqu'à 300 secondes pile, quand le socket tombe sans erreur, sans motif de fermeture, sans avertissement. C'est chaque fois la même histoire : la connexion se ferme exactement au bout de 5 minutes, même quand vos heartbeats semblent partir correctement. Deux erreurs liées accompagnent généralement ce phénomène, une exception WebSocket is not open: readyState 0 (CONNECTING) quand votre code écrit sur un socket à moitié ouvert, et un simple code de fermeture 1006 (fermeture anormale) de la part du pair distant. Voici ce que signifie réellement la fermeture à 5 minutes en 2026, les vraies causes derrière, et le schéma exact heartbeat plus reconnexion qui maintient la connexion en vie, ainsi que la façon dont PickMyTrade gère cette tuyauterie pour vous afin qu'un socket tombé ne vous coûte jamais une exécution.
Liste de contrôle rapide pour la fermeture du WebSocket à 5 minutes
- Envoyez un heartbeat environ toutes les 2,5 secondes, une trame dont le texte est un tableau JSON vide,
[]. Sautez-le, et Tradovate ferme le socket pour inactivité. - Ne vous fiez pas à setInterval dans un onglet de navigateur, les onglets en arrière-plan sont bridés, votre heartbeat dépasse 2,5 s et le serveur raccroche.
- Envoyez vos propres heartbeats, une fois que les données en temps réel circulent, le serveur cesse d'en envoyer ; le client doit donc entretenir le rythme.
- Protégez chaque envoi par une vérification de readyState, n'écrivez que lorsque le socket est OPEN (1), jamais tant qu'il est encore CONNECTING (0).
- Journalisez l'événement de fermeture,
ws.addEventListener('close', e => console.log(e))révèle le code (souvent 1006) et l'éventuel motif. - Partez du principe que des coupures se produiront et reconnectez-vous, encapsulez le socket pour qu'une fermeture réautorise et réabonne automatiquement.
Ce que signifie « le WebSocket se ferme exactement au bout de 5 minutes »
L'API temps réel de Tradovate est une connexion WebSocket : vous l'ouvrez, envoyez une trame d'autorisation, puis vous abonnez aux données et événements qui vous intéressent. Pour que cette connexion reste ouverte, le client est chargé d'envoyer des heartbeats, de petites trames de keep-alive, à cadence fixe. Cessez de les envoyer et Tradovate considère le socket comme inactif, puis le ferme côté serveur.
Si l'échec tombe si souvent sur la marque nette des 5 minutes, c'est que les délais d'expiration le long du chemin réseau, le serveur, un répartiteur de charge ou un proxy intermédiaire, ont tendance à être appliqués sur des chiffres ronds. La connexion se coupe exactement toutes les 5 minutes (300 secondes) sans message, et, fait révélateur, sans heartbeats, la coupure survient plutôt au bout d'environ 2 minutes. Les heartbeats prolongent donc la vie du socket, mais un heartbeat en retard ou manquant, ou un minuteur d'inactivité indépendant quelque part sur le chemin, peut encore le guillotiner à 300 secondes. Il n'existe pas de cause racine publiée pour le cas exact des 5 minutes ; la réponse d'ingénierie durable n'est donc pas d'empêcher chaque fermeture, mais d'y survivre.
Les deux messages d'erreur que vous verrez sont des symptômes du même problème sous-jacent. WebSocket is not open: readyState 0 (CONNECTING) signifie que votre code a tenté un send() avant la fin du handshake, ce qui arrive souvent dans une fonction de heartbeat qui se déclenche en pleine reconnexion. Le code de fermeture 1006 est la façon dont le navigateur ou la bibliothèque dit “la connexion est tombée de manière anormale”, sans handshake de fermeture propre, exactement ce que vous obtenez quand un minuteur d'inactivité côté serveur coupe la ligne.
Principales causes de la fermeture du WebSocket à 5 minutes en 2026
1. Trames de heartbeat tardives ou totalement absentes
C'est la cause numéro un. Tradovate attend une trame de heartbeat, de contenu texte [], environ toutes les 2,5 secondes pour prouver que le client est vivant. Manquez cette fenêtre et le serveur lance le compte à rebours de fermeture. Et voici le piège : dès que vous diffusez des cotations en temps réel, le serveur Tradovate cesse d'envoyer ses propres heartbeats, vous ne pouvez donc pas compter sur le trafic intégré de la connexion pour la maintenir ouverte. Votre client doit envoyer la trame de crochets vides à son propre rythme.
2. Bridage des minuteurs du navigateur (setInterval / setTimeout)
Si vous planifiez les heartbeats avec setInterval() ou setTimeout() dans un navigateur, vous êtes à la merci de la priorité de l'onglet. Quand l'onglet perd le focus, Chrome (et la plupart des navigateurs) abaisse la priorité de ces minuteurs, si bien qu'un intervalle de “2,5 secondes” peut discrètement s'étirer sur plusieurs secondes. Le heartbeat dépasse l'échéance et le socket se ferme, souvent autour de la marque des 5 minutes, une fois assez de retard accumulé.
3. Délai d'inactivité ou de session côté serveur
Même un heartbeat parfaitement cadencé ne peut pas annuler un délai d'expiration appliqué en amont. Un proxy, une passerelle ou la session Tradovate elle-même peut plafonner la durée d'inactivité ou la durée totale de connexion, ce qui explique pourquoi la fermeture tombe sur cette frontière suspecte de 300 secondes. Comme cela échappe à votre contrôle, la solution est la reconnexion, pas la prévention.
4. Envoi sur un socket qui n'est pas OPEN (readyState 0)
Un WebSocket a quatre états : CONNECTING (0), OPEN (1), CLOSING (2) et CLOSED (3). Si votre boucle de heartbeat ou votre code d'ordres appelle send() alors que le socket est encore à readyState 0, vous obtenez WebSocket is not open: readyState 0 (CONNECTING) et, souvent, un message “Disconnected from Tradovate Market WebSocket” juste derrière. C'est ce qui frappe le plus fort juste après une coupure, quand votre reconnexion a lancé un nouveau socket qui n'a pas encore terminé son handshake.
5. Expiration du jeton et connexions de longue durée
Un jeton d'accès Tradovate a une durée de vie limitée, et ces connexions ne sont pas conçues pour vivre éternellement ; maintenez un même socket ouvert très longtemps (plus d'une journée) et il a tendance à tomber. Si votre jeton expire en pleine session ou si la connexion vieillit, le socket se ferme et toute réautorisation avec l'ancien jeton échoue. La durée de vie des jetons varie et évolue avec le temps ; confirmez donc les valeurs actuelles dans la documentation API de Tradovate et renouvelez de façon proactive plutôt que d'attendre un échec.
Comment corriger la fermeture du WebSocket à 5 minutes : pas à pas
Solution 1 : envoyer une trame de heartbeat environ toutes les 2,5 secondes
Le heartbeat est le fondement. À une cadence d'environ 2,5 secondes, envoyez une trame dont le texte est un tableau JSON vide :
Démarrez la routine de keep-alive
Une fois le socket ouvert et l'autorisation effectuée, démarrez une routine de keep-alive.
Envoyez la trame de crochets vides
À chaque tick, appelez ws.send('[]'), la trame de crochets vides est le heartbeat de Tradovate.
Gardez l'intervalle sous 2,5 s
Gardez l'intervalle confortablement sous la limite (2,5 secondes est la cible ; un peu plus souvent est plus sûr qu'un peu moins).
Ne comptez jamais sur des pings du serveur
Ne supposez jamais que le serveur vous pingera, une fois que les données commencent à être diffusées, il ne le fera pas.
Solution 2 : remplacer setInterval par une vérification d'horodatage ou un Web Worker
Comme les minuteurs du navigateur sont bridés, ne vous appuyez pas sur setInterval seul, que l'onglet soit au premier plan ou en arrière-plan. Deux alternatives éprouvées :
- Heartbeats pilotés par horodatage. Enregistrez un horodatage (
new Date()) chaque fois que vous recevez un message. Comparez-le à la dernière fois où vous avez envoyé un heartbeat ; si plus de 2500 ms se sont écoulées, envoyez[]immédiatement. Cela réagit au trafic réel plutôt qu'à un minuteur que le navigateur peut priver de ressources. - Déplacez le minuteur hors du thread principal. Exécutez le heartbeat dans un Web Worker, ou exécutez toute la connexion comme un service Node.js. Les deux contournent entièrement le bridage des onglets du navigateur, un processus Node n'est pas du tout soumis à la pénalité des onglets en arrière-plan.
Solution 3 : protéger chaque envoi par une vérification de readyState
Supprimez l'erreur readyState 0 en n'écrivant jamais sur un socket qui n'est pas ouvert :
Vérifiez readyState avant chaque envoi
Avant chaque send(), heartbeat ou ordre, vérifiez if (ws.readyState === WebSocket.OPEN) (c'est l'état 1).
Sautez et laissez la logique de reconnexion prendre le relais
S'il est encore CONNECTING (0) ou déjà CLOSING/CLOSED, sautez l'envoi et laissez votre logique de reconnexion prendre le relais.
Attachez des écouteurs pour toutes les transitions d'état
Attachez des écouteurs pour open, message, error et close afin que les transitions d'état soient explicites, et journalisez l'objet de l'événement close pour capturer le code et le motif.
Solution 4 : ajouter une logique de reconnexion, de réautorisation et de réabonnement
Comme certaines fermetures à 5 minutes sont imposées en amont et ne peuvent pas être évitées, traitez chaque coupure comme une erreur récupérable et reconstruisez automatiquement :
Encapsulez le socket
Encapsulez le socket dans une classe ou une fonction qui possède son cycle de vie, de sorte qu'un seul endroit soit responsable de sa création et de sa destruction.
Reconnectez-vous à la fermeture
À la fermeture, reconnectez-vous, ouvrez un nouveau socket plutôt que d'essayer de ranimer le mort.
Réautorisez le nouveau socket
Réautorisez le nouveau socket avec un jeton valide (régénérez le jeton avant son expiration pour qu'un jeton neuf soit toujours prêt).
Réabonnez-vous à tout
Réabonnez-vous à tout ce que vous aviez, renvoyez votre user/syncrequest et réabonnez-vous à chaque flux de données de marché, car un nouveau socket démarre sans abonnements.
Attendez OPEN avant d'envoyer
Attendez OPEN avant d'envoyer quoi que ce soit sur le nouveau socket, et ajoutez un court backoff pour qu'une connexion instable ne martèle pas le serveur.
Tableau de dépannage
| Erreur / signal | Ce que cela signifie | Solution |
|---|---|---|
| Le socket se ferme à exactement 300 s | Un délai d'inactivité ou de session sur le chemin a coupé la connexion | Envoyer des heartbeats toutes les ~2,5 s et se reconnecter automatiquement à la fermeture |
| Coupures au bout de ~2 minutes | Aucun heartbeat n'est envoyé | Démarrer un keep-alive qui envoie la trame [] à une cadence de 2,5 s |
| WebSocket is not open: readyState 0 (CONNECTING) | Le code a appelé send() avant la fin du handshake | N'envoyer que lorsque readyState === OPEN (1) ; sinon sauter |
| Code de fermeture 1006 | Fermeture anormale sans handshake propre | Se reconnecter à la fermeture, réautoriser et réabonner |
| « Disconnected from Tradovate Market WebSocket » | Le socket est tombé en plein flux | Reconstruire le socket et restaurer vos abonnements |
| Heartbeats corrects mais onglet inactif | Le navigateur a bridé setInterval/setTimeout | Utiliser des heartbeats basés sur des horodatages ou un Web Worker / Node.js |
| Coupure après une très longue durée de fonctionnement | Jeton expiré ou connexion vieillie | Renouveler le jeton avant son expiration et se reconnecter selon un calendrier |
Évitez cela avec PickMyTrade
PickMyTrade se place entre vos alertes TradingView et Tradovate et exécute la couche WebSocket comme un service géré côté serveur, de sorte que la fermeture à 5 minutes est traitée avant même de vous atteindre :
- Heartbeats gérés, envoie la trame de keep-alive à une cadence fiable côté serveur, sans onglet de navigateur pour brider le minuteur.
- Auto-Reconnect & Re-Auth, détecte un socket tombé, en ouvre un nouveau, réautorise avec un jeton valide et se réabonne automatiquement.
- Garde-fous d'état de connexion, ne transmet que lorsque le socket est réellement ouvert, éliminant les erreurs d'envoi readyState 0.
- Multi-Account Sync, maintient le flux de chaque compte connecté en bonne santé afin qu'une seule reconnexion ne laisse jamais un compte à la traîne.
Tradez sans rejet
Commencez votre essai gratuit de 7 jours, reliez vos alertes dès aujourd'hui et tradez sans rejet.
Commencez votre essai gratuit de 7 joursQuestions fréquentes
Le socket est fermé par un délai d'inactivité ou de session sur le chemin de connexion, qui se déclenche souvent sur des chiffres ronds comme 300 secondes. L'envoi de heartbeats prolonge la connexion, mais si un heartbeat prend du retard ou si un minuteur en amont se déclenche malgré tout, le socket tombe quand même. La solution fiable consiste à combiner heartbeats et reconnexion automatique.
Environ toutes les 2,5 secondes. Le heartbeat est une trame dont le texte est un tableau JSON vide, []. Envoyer un peu plus souvent que toutes les 2,5 secondes est plus sûr que de risquer une trame tardive.
Juste [], un tableau JSON vide envoyé comme texte du message WebSocket. C'est cette trame de crochets vides que Tradovate lit comme un keep-alive.
Votre code a appelé send() alors que le socket était encore en cours de handshake (état 0), pas encore OPEN (état 1). Vérifiez readyState avant chaque envoi et sautez l'écriture jusqu'à ce que le socket indique OPEN, en laissant d'abord votre logique de reconnexion se terminer.
Pas une fois que les données en temps réel sont diffusées. Le serveur cesse d'envoyer des heartbeats après le début du flux de données ; le client doit donc envoyer les siens à la cadence de 2,5 secondes. Vous ne pouvez pas compter sur le trafic du serveur pour maintenir la connexion ouverte.
Les navigateurs brident setInterval et setTimeout dans les onglets inactifs, ce qui étire votre heartbeat de 2,5 secondes au-delà de la limite. Utilisez des heartbeats basés sur des horodatages liés aux messages reçus, ou exécutez la connexion dans un Web Worker ou un processus Node.js pour éviter entièrement le bridage des onglets.
Le code 1006 est une fermeture anormale sans handshake de fermeture propre, généralement une connexion perdue ou un délai d'expiration côté serveur. N'essayez pas d'empêcher chaque 1006 ; encapsulez le socket, reconnectez-vous à la fermeture, réautorisez avec un jeton neuf et réabonnez-vous à vos flux.
Ce guide est fourni à des fins exclusivement éducatives et informatives et ne constitue pas un conseil financier, d'investissement ou de trading. Le trading de contrats à terme et d'autres produits à effet de levier comporte un risque de perte important et ne convient pas à tous les investisseurs. PickMyTrade est une plateforme d'automatisation tierce indépendante et n'est ni affiliée à Tradovate, Inc., ni approuvée ou parrainée par cette dernière. « Tradovate » ainsi que tous les noms, logos et marques associés sont la propriété de leurs détenteurs respectifs. Les fonctionnalités de la plateforme et les étapes évoluent avec le temps ; confirmez donc toujours la procédure en vigueur dans la plateforme et la documentation officielles de Tradovate avant d'agir.