Les endpoints fill/position de l'API Tradovate ne renvoient aucune donnée
Vos ordres passent sans problème, mais le prix d'exécution ou la taille de la position ouverte revient vide. Deux des trois causes sont des problèmes de format d'appel que vous pouvez corriger en quelques minutes, l'une est une particularité de timing à intégrer dans votre conception.
Vos ordres passent sans problème. Puis vous demandez à l'API la seule chose dont vous avez vraiment besoin, le prix d'exécution ou la taille de la position ouverte, et elle ne vous renvoie rien. Un tableau vide. Un null. Un 200 OK tout propre avec [] dans le corps. Trois appels font trébucher presque tout le monde ici : fill/list (ou fill/items) revient vide, order/item fonctionne mais n'a pas de prix d'exécution, et position/find?name=... ne trouve jamais votre position. Deux de ces cas sont des problèmes de format d'appel que vous pouvez corriger en quelques minutes. Un est une particularité de timing avec laquelle il faut composer dans votre conception. Et dans une petite proportion des cas, c'est vraiment Tradovate qui renvoie des données de façon peu fiable, auquel cas la bonne démarche est de recouper plusieurs endpoints et de le signaler au support. Séparons les trois cas.
Liste de vérification rapide
- Interrogez pendant la session. REST ne montre que la journée de trading en cours. Après la clôture du marché, la session est archivée et les anciens appels renvoient un résultat vide.
- Arrêtez d'utiliser
/findsur les positions. L'entité Position n'a pas de champname, doncposition/find?name=MNQZ5ne correspondra jamais. Recherchez les positions parcontractId. - Le prix d'exécution n'est pas sur l'ordre. Lisez-le dans le champ
pricedu fill, pas dansorder/item. - Faites correspondre l'endpoint au paramètre.
/item?id=prend un id ;/items?ids=prend une liste ;/listn'en prend aucun. Les paramètres sont en minuscules. - Vérifiez l'hôte et le token. Un token demo sur un hôte live, ou un token expiré, renvoie un résultat vide ou non autorisé avant même qu'un problème de données ne s'applique.
- Si les bons appels reviennent toujours vides pendant une session live avec une activité connue, capturez la requête et la réponse et signalez-le au support.
Ce que signifie vraiment "renvoie None"
Il y a une distinction importante derrière ces échecs, et elle change la façon de les corriger. Un 200 OK avec un tableau vide signifie que l'appel a été accepté, authentifié et compris, le serveur n'avait simplement aucune donnée à vous donner avec ces paramètres. Ce n'est presque jamais un bug de Tradovate ; c'est un décalage de portée ou de timing de votre côté. Un 404, en revanche, signifie que l'enregistrement précis demandé n'est pas accessible pour le moment, ce qui est courant sur une recherche item?id= après le basculement de la session. Et un 401 signifie que le serveur n'est même pas allé assez loin pour chercher des données. Donc avant de conclure que « l'endpoint est cassé », vérifiez lequel de ces trois codes vous obtenez réellement. Cela pointe directement vers la cause.
Pourquoi les appels fill, order et position reviennent vides
1. REST ne montre que la session en cours
C'est la cause principale, et elle piège ceux qui testent après la clôture. Tradovate archive la session de chaque journée à la clôture du marché. Une fois cela fait, les endpoints de requête REST, fill/list, order/list, fillPair/list, cashBalanceLog/list et consorts, ne voient plus que les enregistrements de la session en cours. Demandez les fills d'hier et vous obtenez un 200 avec un tableau vide ; demandez un ordre archivé précis via order/item?id= et vous pouvez obtenir un 404. Rien ne cloche dans votre authentification ou votre syntaxe. Les données ne sont simplement plus dans le cache en direct. L'indice ici, c'est que le même appel exact fonctionnait très bien une heure plus tôt pendant la session et revient vide maintenant.
La solution comporte deux volets. Pour l'activité en direct, exécutez vos requêtes dans la même session que celle où les trades ont eu lieu. Pour tout ce qui est historique, le rapprochement de fin de journée, un journal de P&L, un journal des trades, utilisez la Reporting API sur rpt-live.tradovateapi.com (ou rpt-demo.tradovateapi.com pour le demo), conçue pour servir des données archivées par plage de dates. Les endpoints de trading génériques ne le sont pas.

2. /find ne fonctionne que sur les entités avec un champ name
Essayer de localiser une position ouverte avec position/find?name=MNQZ5 échouera à chaque fois, et non parce que votre position est manquante. L'opération /find n'est définie que pour les entités qui portent un champ name. Les contrats en ont un. Les produits en ont un. L'entité Position n'en a pas, donc une recherche par nom sur celle-ci ne renvoie rien, quoi que vous passiez. Les positions sont indexées par contractId, un entier, et non par la chaîne de symbole que vous voyez sur votre graphique.
Procédez donc en deux étapes. Résolvez d'abord le symbole en id de contrat : contract/find?name=MNQZ5 renvoie l'objet contract, y compris son id numérique. (Pour une correspondance partielle ou anticipée, contract/suggest?t=MNQ&l=10 renvoie des candidats.) Récupérez ensuite vos positions avec position/list, ou position/deps?masterid={accountId} pour un compte précis, et filtrez les résultats là où contractId correspond à l'id que vous venez de rechercher. Lisez netPos pour la taille signée. C'est la position que vous cherchiez à « trouver ».

3. L'objet order ne porte pas le prix d'exécution
Celui-ci est vraiment contre-intuitif. order/item?id= renvoie l'ordre, son statut, son sens, sa quantité, son type d'ordre, ses horodatages. Ce qu'il ne renvoie pas, c'est le prix auquel vous avez été exécuté, car un ordre et son exécution sont deux enregistrements distincts. Le prix d'exécution se trouve sur l'entité fill, dans son champ price. Un ordre peut produire plusieurs fills à des prix différents, ce qui explique précisément pourquoi ce nombre ne peut pas tenir comme valeur unique sur l'ordre.
Pour obtenir le prix d'exécution d'un ordre, allez voir les fills. Chaque fill référence son ordre parent via un champ orderId et son instrument via contractId, et porte price, qty, action (Buy/Sell) et un timestamp. Récupérez fill/list pour la session et faites correspondre l'orderId qui vous intéresse, ou chargez directement les fills dépendants de l'ordre. Pour le temps réel, la source la plus propre est les événements executionReport / fill sur le WebSocket, qui arrivent à l'instant même où une exécution a lieu. Si vous avez besoin du P&L réalisé plutôt que des prix de fill bruts, fillPair/list vous donne les paires buy/sell appariées.
4. Bon endpoint, mauvais paramètre
Les endpoints de requête de Tradovate suivent une forme stricte, sensible à la casse, et les mélanger produit des résultats vides ou des erreurs qui ressemblent à des problèmes de données. Le schéma est : /item?id=123 pour un enregistrement unique, /items?ids=1,2,3 pour plusieurs, /list pour tout ce qui est dans le périmètre sans paramètres, /deps?masterid=123 pour les dépendants d'un parent, et /ldeps?masterids=1,2 pour plusieurs parents. Un appel comme fill/items?Id=XXX enfreint silencieusement deux règles à la fois, il utilise l'endpoint au pluriel /items (qui attend ids=) avec un paramètre Id singulier et en majuscule que le serveur ne reconnaît pas. Basculez soit vers fill/item?id=XXX pour un enregistrement, soit vers fill/items?ids=XXX pour une liste, et gardez le paramètre en minuscules.
Comment recouper les endpoints étape par étape
Quand un appel fill, order ou position revient vide, exécutez cette séquence avant de supposer que la plateforme est en cause. Elle isole la cause en quelques minutes.
Écartez l'authentification
Lancez un appel authentifié trivial comme account/list. Un 401 ici signifie que le problème vient de votre token ou de votre hôte, pas des endpoints fill/position, corrigez cela d'abord.
Confirmez l'environnement
Assurez-vous que l'hôte que vous appelez (demo vs. live) correspond au token avec lequel vous vous êtes authentifié. Un token valide pointant vers le mauvais environnement ne renvoie aucune donnée.
Confirmez qu'il y a de l'activité pendant cette session
Si vous testez après la clôture du marché, il se peut qu'il n'y ait vraiment rien dans le cache en direct. Reproduisez pendant une session active avec une position ouverte connue ou un fill récent.
Résolvez le symbole
Lancez contract/find?name=YOURSYMBOL et notez l'id numérique. Chaque filtre de position et de fill se base là-dessus, pas sur le texte du symbole.
Comparez trois vues
Récupérez order/list, fill/list et position/list pour le même compte et recoupez-les par contractId et orderId. Si l'ordre apparaît comme exécuté mais qu'aucun fill correspondant n'apparaît, c'est l'écart qui mérite d'être escaladé.

Tableau de dépannage
| Symptôme | Cause probable | Correction |
|---|---|---|
| fill/list renvoie 200 + [] après la clôture | Session archivée ; REST ne sert que la journée en cours | Interrogez pendant la session ; utilisez la Reporting API pour l'historique |
| position/find?name= toujours vide | Position n'a pas de champ name | Résolvez symbole → contractId, puis filtrez position/list |
| order/item fonctionne mais pas de prix d'exécution | Le prix se trouve sur le fill, pas sur l'ordre | Lisez le prix depuis le fill correspondant (par orderId) |
| order/item?id= renvoie 404 | Enregistrement archivé après la clôture du marché | Interrogez pendant la session ou récupérez-le via la Reporting API |
| /items?Id= renvoie vide ou des erreurs | Mauvaise forme d'endpoint/paramètre | Utilisez /item?id= (un) ou /items?ids= (liste), en minuscules |
| Tous les bons appels vides pendant une session live | Problème de fiabilité possible côté plateforme | Capturez la requête/réponse et signalez-le au support |
Le schéma fiable : synchroniser une fois, puis streamer
Interroger REST encore et encore pour savoir « ma position est-elle déjà à jour ? » est la façon fragile de faire les choses, et c'est une grande raison pour laquelle les gens voient des réponses obsolètes ou vides, on attrape l'endpoint entre deux mises à jour. Le schéma vers lequel Tradovate lui-même oriente les développeurs est différent : s'abonner, ne pas sonder.
Ouvrez le WebSocket de trading et envoyez un user/syncrequest. En réponse, vous obtenez un instantané consolidé unique, comptes, positions, ordres, fills, soldes de trésorerie, le tout. À partir de là, le socket vous transmet chaque changement au fur et à mesure : un nouveau fill, une mise à jour de position, un mouvement de solde. Vous gardez un modèle local synchronisé à partir de ces événements au lieu de réinterroger REST. Pour le volet historique, les trades déjà archivés hors de la session en direct, faites le backfill initial via la Reporting API, puis passez le relais au WebSocket pour tout ce qui suit. Cette combinaison est ce qui maintient la vue d'un bot sur les fills et les positions à la fois complète et à jour.
Quand le signaler au support
La plupart du temps, ces réponses vides remontent à l'une des quatre causes ci-dessus, et vous pouvez les corriger sans l'aide de personne. Mais il existe un sous-ensemble réel où le bon appel, effectué pendant une session active, contre un compte avec une activité confirmée, ne renvoie toujours rien, ou un ordre apparaît comme exécuté alors qu'aucun enregistrement de fill n'apparaît jamais. Ce n'est pas quelque chose que vous pouvez contourner par du code, et cela vaut la peine de le signaler. Lorsque vous le faites, incluez l'endpoint exact et la chaîne de requête, l'id de compte, l'horodatage UTC, si vous étiez en demo ou en live, et le corps de réponse 200 brut montrant le résultat vide. Un rapport ainsi recoupé est traité bien plus rapidement que « l'API ne fonctionne pas ».
Où PickMyTrade s'intègre
Assembler la recherche de contrats, la correspondance des fills, les requêtes tenant compte de la session et une boucle de synchronisation WebSocket représente beaucoup de code à écrire et à maintenir juste pour connaître votre prix d'exécution et votre taille ouverte. PickMyTrade se place entre TradingView et Tradovate et gère cette couche pour vous :
- Suivi en direct des positions et des fills, la connexion reste synchronisée avec l'état de votre compte, vous n'interrogez donc pas des endpoints qui reviennent vides entre les mises à jour.
- Gestion des symboles bien faite, la résolution des contrats et le rollover sont gérés en coulisses, vous ne faites donc jamais correspondre le mauvais id.
- Exécution sécurisée par session, les ordres sont routés et confirmés sans que vous ayez à gérer manuellement les fenêtres de données archivées ou en direct.
- Aucun code de token ou de WebSocket, l'authentification, le renouvellement et le flux de synchronisation sont pris en charge, vos alertes atteignent donc simplement Tradovate et s'exécutent.
Automatisez sans vous battre avec l'API
Démarrez votre essai gratuit et automatisez Tradovate sans vous battre avec l'API.
Démarrez votre essai gratuit de 5 joursQuestions fréquentes
Les endpoints REST de liste et d'élément n'exposent que la session de trading en cours. Une fois la session archivée à la clôture du marché, les appels pour une activité plus ancienne renvoient un 200 OK avec un tableau vide (ou un 404 sur une recherche d'élément). Interrogez pendant la même session que celle où les fills ont eu lieu, et utilisez la Reporting API pour tout ce qui est historique.
L'objet order porte l'état de l'ordre, pas les détails d'exécution. Le prix d'exécution moyen ou par lot se trouve dans le champ price de l'entité fill. Récupérez les fills pour cet order id, via fill/list ou l'endpoint de dépendance des fills, et lisez price à cet endroit, ou écoutez l'événement executionReport sur le WebSocket.
L'opération /find ne fonctionne que sur les entités qui ont un champ name. L'entité Position n'a pas de champ name, donc une recherche par nom renvoie toujours un résultat vide, quelle que soit votre position ouverte. Les positions sont indexées par contractId. Résolvez d'abord le symbole en id de contrat avec contract/find?name=MNQZ5, puis faites correspondre cet id avec position/list.
Les contrats ont bien un champ name, donc contract/find?name=MNQZ5 renvoie l'objet contract, y compris son id numérique. Pour des correspondances partielles, utilisez contract/suggest?t=MNQ&l=10. Prenez ce contractId et utilisez-le pour filtrer positions et fills, puisque les deux référencent le contrat par id plutôt que par le texte du symbole.
Ne sondez pas REST en boucle. Ouvrez le WebSocket de trading et envoyez user/syncrequest pour obtenir un instantané unique des comptes, positions, ordres, fills et soldes de trésorerie, puis laissez le socket diffuser chaque mise à jour à partir de là. Utilisez la Reporting API pour le backfill historique initial.
Ce guide est fourni à des fins éducatives et informatives uniquement et ne constitue pas un conseil financier, d'investissement ou de trading. Le trading de futures et d'autres produits à effet de levier comporte un risque de perte substantiel 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 celle-ci. Tous les noms, logos et marques associés sont la propriété de leurs détenteurs respectifs. Les fonctionnalités et les étapes de la plateforme évoluent avec le temps, confirmez donc toujours la procédure actuelle dans la plateforme et la documentation officielles de Tradovate avant d'agir.