Tradovate API

Errore 404 sull'endpoint liquidatePosition dell'API Tradovate

Invia una richiesta POST all'endpoint liquidate aspettandosi una chiusura pulita, ma ottiene invece 404 Not Found. Nove volte su dieci si tratta di un percorso scritto con maiuscole/minuscole errate, dell'host sbagliato o del verbo HTTP sbagliato, non di un account o di un payload danneggiati.

Verificato dal Trading Systems Team di PickMyTrade Ultimo aggiornamento
· Lettura di 8 minuti
Client API Tradovate che mostra una risposta 404 Not Found su un POST a order/liquidateposition

Vuole chiudere una posizione da codice, quindi invia una richiesta POST all'endpoint liquidate aspettandosi una chiusura pulita. Invece il server restituisce 404 Not Found. Il suo token è valido, le altre chiamate di ordine funzionano, il JSON sembra perfetto, eppure proprio questa route si comporta come se non esistesse. È frustrante, perché sembra che l'endpoint sia rotto o mancante.

Non lo è. Un 404 è più circoscritto di quanto sembri: non riguarda il suo account, la sua posizione o il suo payload. Significa che l'URL esatto a cui ha inviato il POST non corrisponde a nessuna route sul server di Tradovate. Nove volte su dieci si tratta di una di queste tre cose: il percorso ha maiuscole/minuscole errate o è scritto male, sta puntando all'host sbagliato, oppure ha inviato il verbo HTTP sbagliato. Le escludiamo in ordine, per poi fissare la chiamata corretta e permetterle di chiudere la posizione in modo pulito.

Cosa le sta dicendo davvero un 404

Ogni errore HTTP indica un livello diverso, e confonderli porta a modificare la cosa sbagliata. Un 404 significa che il percorso non esiste. Un 401 significa che il percorso esiste ma non era autorizzato. Un 400 significa che percorso e autenticazione erano corretti ma il corpo della richiesta era malformato. Un 429 significa che sta raggiungendo il limite di frequenza delle richieste. Quindi, se ha davanti un 404 reale, smetta di modificare il corpo JSON: il server non è mai arrivato abbastanza avanti da occuparsene. Non è nemmeno riuscito a trovare la route.

Questo singolo fatto restringe molto la ricerca. Tutto ciò che produce un 404 si trova nella riga della richiesta: il metodo, l'host, il segmento di versione e la grafia del percorso. Verifichi questi quattro punti e l'errore sparirà.

Causa 1: il percorso ha maiuscole/minuscole errate o è scritto male

Questo è il grande classico, e coglie quasi tutti almeno una volta. I percorsi REST di Tradovate distinguono tra maiuscole e minuscole. L'operazione si scrive esattamente liquidatePosition, con la l minuscola e la P maiuscola in camelCase. Se la scrive in un altro modo, il router non ha nulla da far corrispondere e risponde con 404. Scrivere tutto in minuscolo è l'errore classico, di solito perché l'ha digitata a memoria o perché il suo framework ha normalizzato l'URL al posto suo.

Cosa ha inviato Risultato
/v1/order/liquidatePositionRoute corretta
/v1/order/liquidateposition404 Not Found
/v1/order/LiquidatePosition404 Not Found
/v1/order/liquidate_position404 Not Found
/v1/order/liquidate-position404 Not Found
Diagramma che scompone l'URL corretto di liquidatePosition di Tradovate in host, segmento di versione e percorso in camelCase

La soluzione è poco entusiasmante ma affidabile: copi il nome dell'operazione direttamente dal riferimento API e lo incolli, invece di ridigitarlo. Basta un solo carattere sbagliato nelle maiuscole/minuscole. Già che c'è, controlli che non ci sia una barra finale accidentale o un segmento duplicato come /order/order/liquidatePosition che un generatore di URL può introdurre di nascosto.

Causa 2: host sbagliato o segmento di versione mancante

L'URL completo ha quattro parti che devono essere tutte corrette: schema, host, il segmento di versione /v1 e il percorso. Mettendoli insieme si ottiene:

  • Demo/simulazione: https://demo.tradovateapi.com/v1/order/liquidatePosition
  • Live: https://live.tradovateapi.com/v1/order/liquidatePosition

Se omette /v1 otterrà un 404, perché alla radice dell'API non è collegata direttamente nessuna route /order/liquidatePosition. Un errore di battitura nell'host produce lo stesso risultato, oppure fa fallire del tutto la risoluzione DNS. E non si rivolga qui all'host dei dati di mercato: md.tradovateapi.com serve quotazioni, DOM e grafici, non operazioni sugli ordini, quindi anche un host md non instraderà una chiamata di liquidazione.

Vale la pena segnalare una sottigliezza: mescolare gli ambienti, un token demo contro l'host live, o viceversa, si manifesta più spesso come un 401 che come un 404, ma vale comunque la pena controllarlo una volta che il percorso è pulito. I nomi host vengono aggiornati di tanto in tanto, quindi confermi quelli attuali nella documentazione ufficiale per sviluppatori di Tradovate, invece di fidarsi di un URL copiato da un vecchio gist.

Causa 3: ha inviato il metodo HTTP sbagliato

L'operazione di liquidazione è solo POST. Se invia un GET, il server non ha alcun gestore GET per quel percorso, il che si manifesta come un errore di tipo non trovato o metodo non consentito, a seconda di come lo segnala il suo client. È facile caderci se sta testando incollando l'URL nella barra degli indirizzi del browser: quello è sempre un GET, quindi qui fallirà sempre.

Effettui un test con un vero POST da un client adeguato. Ha anche bisogno delle intestazioni corrette nella richiesta: Content-Type: application/json e Authorization: Bearer <yourAccessToken>. Un POST con il corpo nel posto sbagliato, o senza il content type JSON, può fallire in modi che sembrano un problema di routing anche quando il percorso è corretto.

Causa 4: singolare o plurale, qual è quello reale?

È qui che nasce buona parte della confusione del tipo “l'endpoint non esiste”. L'operazione canonica, per singola posizione, è la route al singolare /order/liquidatePosition. Accetta un accountId e un singolo contractId e chiude quell'unica posizione netta. È questa la route che troverà documentata, ed è quella che risponde in modo costante.

Alcune librerie client e frammenti di codice della community fanno riferimento a una variante plurale in stile batch che accetta un array positions invece di un singolo contratto. Se copia un esempio al plurale ma la sua destinazione espone solo la route al singolare, oppure presume che il singolare accetti un array, otterrà un 404 oppure invierà un corpo che l'endpoint ignorerà. In caso di dubbio, utilizzi per impostazione predefinita il singolare /order/liquidatePosition con accountId e contractId, e verifichi il nome esatto dell'operazione e la sua struttura rispetto al riferimento API live per la versione che sta chiamando. L'ortografia e la scelta tra singolare e plurale sono esattamente i due dettagli che producono silenziosamente un 404.

La chiamata corretta, campo per campo

Una volta che la riga della richiesta è corretta, il corpo è breve.

POST https://demo.tradovateapi.com/v1/order/liquidatePosition
{ "accountId": 12345, "contractId": 67890, "admin": false, "customTag50": "" }

Campo Cos'è
accountIdL'id numerico dell'account, non il nome o la specifica dell'account. Lo recuperi da /account/list.
contractIdL'id numerico del contratto che detiene, ottenuto da /position/list. Deve essere maggiore di zero.
adminUn booleano, e deve essere presente. Lo imposti su false a meno che il suo utente API non disponga realmente del permesso admin (vedere l'insidia più sotto).
customTag50Etichetta opzionale di massimo 50 caratteri che accompagna l'ordine. Una stringa vuota va bene.
Risposta JSON di position/list di Tradovate con i campi accountId e contractId evidenziati

I due id sono il punto in cui la maggior parte delle persone si blocca, quindi proceda con attenzione. Chiami /account/list e legga l'id dall'oggetto account con cui vuole operare. Chiami /position/list, e ogni posizione aperta le restituisce sia un accountId sia un contractId, insieme alla sua quantità netta. Copi esattamente questi numeri, l'endpoint lavora sulla coppia (accountId, contractId), non su un id di posizione o su una stringa simbolo.

Client API Tradovate che mostra un POST riuscito a order/liquidatePosition con una risposta 200

L'insidia dell'admin: un 401 nascosto dietro la sua soluzione

Questa insidia scatta proprio nel momento in cui si risolve il 404. Il campo admin è obbligatorio nel corpo, ma il valore che gli assegna è determinante. Impostando admin: true quando il suo utente API non è predisposto per l'accesso admin, la chiamata passa direttamente a 401 Unauthorized. Impostando admin: false la stessa richiesta va a buon fine. Quindi, a meno che non sappia che il suo utente ha privilegi admin, invii "admin": false. Se ha appena risolto un 404 e ora si trova davanti un 401 al tentativo immediatamente successivo, questa è quasi sempre la ragione, non il suo token, non l'id del suo account.

Cosa le offre l'endpoint, e cosa non offre

Vale la pena conoscere alcuni comportamenti prima di costruire qualcosa sopra questa chiamata:

  • Chiude l'intera posizione netta per quella coppia (accountId, contractId). Dietro le quinte inserisce un ordine di chiusura, il che significa che non verrà eseguito quando il mercato è chiuso: lo esegua durante l'orario di negoziazione dello strumento.
  • È una chiamata per contratto. Per chiudere tutto su un account, recuperi /position/list e cicli, lanciando una liquidatePosition per ogni contractId aperto. Su questa route non esiste un unico corpo “chiudi tutto l'account”.
  • È sicuro rispetto alle race condition. Se la posizione si è già chiusa tra il suo controllo e la chiamata, ad esempio perché uno stop è stato eseguito, ottiene un 200 pulito con un corpo vuoto invece di un errore. È voluto, ed è più sicuro che sintetizzare un ordine sul lato opposto, che potrebbe aprire accidentalmente una posizione inversa.
  • Non restituisce alcun orderId. Poiché nella risposta non è presente un id ordine, non può leggere direttamente il prezzo di esecuzione di chiusura. Se le serve quel prezzo per il P&L, effettui una riconciliazione con i report di esecuzione e fill (execution reports, fill pairs) o con il registro delle posizioni.

Una checklist rapida per risolvere il 404

Verifica Cosa confermare
Ortografia esattaliquidatePosition in camelCase, non minuscolo, non snake_case, non con trattini.
URL completoSchema + host + /v1 + /order/liquidatePosition, con il segmento di versione presente.
Host correttodemo.tradovateapi.com o live.tradovateapi.com, mai l'host md dei dati di mercato.
POST, non GETPOST con Content-Type: application/json e un token Bearer; niente test dalla barra degli indirizzi del browser.
Id numericiaccountId da /account/list, contractId da /position/list, entrambi maggiori di zero.
Valore di adminIncluda admin; lo imposti su false a meno che il suo utente non abbia il permesso admin, per evitare un successivo 401.

Dove si inserisce PickMyTrade

La maggior parte delle persone alle prese con questo 404 non vuole davvero diventare idraulici dell'API Tradovate, vuole una strategia che apra, gestisca e chiuda le posizioni senza dover sorvegliare costantemente endpoint, id e token. PickMyTrade instrada gli alert di TradingView verso Tradovate e può chiudere o liquidare le posizioni come parte di una strategia, così non deve costruire a mano le chiamate di liquidazione, inseguire gli id di account e contratto, né gestire i token.

  • Nessuna chiamata di liquidazione costruita a mano la sua strategia apre e chiude posizioni su Tradovate senza una sola richiesta API scritta a mano.
  • Risoluzione di account e contratto gestita gli id che mandano in crisi le chiamate dirette vengono risolti al suo posto.
  • Autenticazione gestita token e host vengono gestiti automaticamente, così un 401 nascosto dietro un 404 non diventa mai un suo problema.
  • Routing sicuro rispetto ai rate limit distribuisce il flusso di ordini in modo che nulla rimbalzi contro i limiti di richiesta di Tradovate.

Automatizzi l'intero flusso di ordini

Vuole che la sua strategia TradingView apra e chiuda posizioni su Tradovate senza scrivere a mano nemmeno una chiamata API? Scopra come PickMyTrade automatizza l'intero flusso di ordini.

Avvii la sua prova gratuita di 5 giorni

Domande frequenti

Un 404 significa che il percorso dell'URL non esiste esattamente come è stato inviato. La causa più comune è la distinzione tra maiuscole e minuscole: i percorsi REST di Tradovate sono case-sensitive, e l'operazione si scrive liquidatePosition con la P maiuscola. Invii un POST a /v1/order/liquidateposition tutto in minuscolo e otterrà 404 Not Found, perché quella route non è definita. Succede lo stesso se omette il segmento di versione /v1, punta all'host sbagliato, o invia un GET invece di un POST. Corregga prima il percorso, prima di toccare il corpo.

L'endpoint canonico, per singola posizione, è il singolare /order/liquidatePosition. Accetta un accountId numerico più un singolo contractId e chiude quell'unica posizione netta. Alcune librerie client e frammenti di codice fanno riferimento a una variante plurale in stile batch che accetta un array positions, quindi copiare un esempio al plurale su una route che serve solo il singolare (o viceversa) può causare un 404. In caso di dubbio, usi il singolare /order/liquidatePosition con accountId e contractId, e confermi il nome esatto dell'operazione rispetto al riferimento API live per la sua versione.

Entrambi sono id numerici, non nomi. Chiami /account/list per ottenere il campo id del suo account, e chiami /position/list per ottenere l'accountId e il contractId di ogni posizione aperta. Copi quei valori numerici direttamente nel corpo della richiesta. Il contractId deve essere maggiore di zero, e deve essere il contratto che sta effettivamente detenendo, non una radice di prodotto o una stringa simbolo.

Un 401 significa che la route esiste ma la richiesta non era autorizzata, il che è un problema diverso da un 404. Su questo endpoint, il fattore scatenante abituale è il campo admin. È obbligatorio nel corpo, ma se imposta admin su true quando il suo utente API non è predisposto per il permesso admin, la chiamata torna con 401 Unauthorized. Imposti admin su false e la richiesta va a buon fine. Quindi, se correggendo il percorso il suo 404 si è trasformato in un 401, imposti admin su false.

No. Una liquidazione riuscita restituisce un 200 pulito senza orderId, quindi non può leggere direttamente il prezzo di esecuzione di chiusura dalla risposta. È sicura rispetto alle race condition: se la posizione si è già chiusa, ottiene comunque un 200 con un corpo vuoto invece di un errore. Per ottenere il prezzo di chiusura ai fini del P&L, effettui una riconciliazione con i report di esecuzione e fill o con il registro delle posizioni, invece di aspettarsi un id ordine in risposta.

Sì. PickMyTrade instrada gli alert di TradingView verso Tradovate e può chiudere o liquidare le posizioni come parte di una strategia, così non deve costruire a mano le chiamate a liquidatePosition, inseguire le ricerche di accountId e contractId, né gestire i token da solo. È una scorciatoia per l'automazione, non un sostituto dell'API grezza quando ha bisogno specificamente di un controllo di basso livello.

Questa guida ha scopi esclusivamente educativi e informativi e non costituisce consulenza finanziaria, di investimento o di trading. Il trading di future e altri prodotti a leva comporta un rischio sostanziale di perdita e non è adatto a tutti gli investitori. PickMyTrade è una piattaforma di automazione indipendente di terze parti e non è affiliata a Tradovate, Inc., né approvata o sponsorizzata da quest'ultima. Tutti i nomi, i loghi e i marchi correlati sono di proprietà dei rispettivi titolari. Le funzionalità e i passaggi della piattaforma cambiano nel tempo, quindi confermi sempre il processo attuale sulla piattaforma e nella documentazione ufficiale di Tradovate prima di agire.