Tradovate API

Gli ordini bracket (OSO/OCO) dell'API Tradovate falliscono

La sua entrata viene eseguita su ES o NQ e lo stop-loss o il take-profit non compare mai. Ecco cosa significano davvero il 200 OK, il 404 e il rifiuto 'Wrong OCO combination', e come correggere ciascuno di essi.

Verificato dal Trading Systems Team di PickMyTrade Ultimo aggiornamento
· Lettura di 8 minuti
Risposta di un ordine bracket dell'API Tradovate che mostra HTTP 200 OK con failureReason e failureText nel corpo

La sua automazione invia un ordine bracket dell'API Tradovate, l'entrata viene eseguita su ES o NQ, e poi… nulla. Niente stop-loss, niente take-profit. Ora si trova a un tick sbagliato da una posizione priva di protezione, e il suo log riporta che l'ordine è stato “inviato correttamente”. Questa è la trappola. Nel 2026 l'errore classico non è più una schermata rossa di errore, ma uno stato HTTP 200 OK che nasconde un failureReason e un failureText nel corpo, oppure una chiamata a orderStrategy che torna come un semplice 404. Le varianti più comuni: un 404 (undocumented) da startOrderStrategy, un errore di parsing Invalid JSON, un rifiuto Wrong OCO combination, e il più insidioso, un'esecuzione parziale silenziosa in cui sopravvive solo l'entrata. Ecco cosa significa davvero ciascun errore, come correggere i problemi di endpoint e di campo che li causano, e come PickMyTrade impedisce che un'esecuzione priva di protezione arrivi mai al suo conto.

Checklist rapida per gli ordini bracket (OSO/OCO) che falliscono

  • Legga il corpo della risposta, non solo il codice HTTP. Tradovate le restituisce 200 OK anche quando l'ordine è già morto in partenza. La verità si trova in failureReason / failureText.
  • Confermi l'endpoint. Usi order/placeOSO per un'entrata che invia gambe di stop/target, order/placeOCO per due uscite collegate, e orderStrategy/startOrderStrategy per un bracket lato server.
  • Invii entrambi i campi account. Servono sia l'accountId numerico (da account/list) sia il nome account accountSpec. Se ne manca uno, o non corrispondono, otterrà Access is denied.
  • Serializzi JSON reale. Invii un corpo JSON (json= in Python requests), non un dict grezzo, altrimenti otterrà Invalid JSON: expected '{'.
  • Usi orderStrategyTypeId: 2. È l'unico valore valido. Un 1 le procura un 404 (undocumented).
  • Tenga pronto un fallback. Se l'endpoint di strategia continua a fallire, piazzi l'entrata, poi alleghi uno stop/target placeOCO non appena è aperta la posizione.

Cosa significano «Wrong OCO Combination» e gli errori 404

Tradovate offre diversi modi per inviare ordini protetti, e ciascuno fallisce a modo suo. Un bracket è un ordine di entrata più due gambe figlie, uno stop protettivo e un obiettivo di profitto, dove l'esecuzione o l'annullamento di una figlia annulla l'altra. Sull'API REST lo si costruisce con order/placeOSO (One-Sends-Other): un ordine padre porta oggetti bracket1 e bracket2 che si attivano solo dopo l'esecuzione del padre. order/placeOCO (One-Cancels-Other) collega due ordini in modo che l'esecuzione di uno annulli l'altro, comodo per agganciare uno stop e un target a una posizione già detenuta.

La parte confusa: questi endpoint restituiscono allegramente 200 OK pur rifiutando comunque l'ordine. Tradovate segnala gli errori di logica di business all'interno del corpo della risposta, non nello stato HTTP. Quindi un payload che raggiunge il server in modo pulito può comunque tornare con {"failureReason": "InvalidPrice", "failureText": "Wrong OCO combination"}, il che significa che i livelli di prezzo o l'abbinamento di tipi d'ordine scelti non formano un OCO valido. Uno stop e un limite posti sul lato sbagliato del mercato bastano a provocarlo. Consideri qualsiasi corpo contenente failureReason come un rifiuto, punto, indipendentemente da ciò che dice la riga di stato.

L'endpoint orderStrategy/startOrderStrategy è tutta un'altra bestia. Esegue una strategia bracket lato server, l'equivalente API di una strategia ATM, ed è molto più esigente riguardo al proprio payload. Se invia l'orderStrategyTypeId sbagliato, o lo chiama via REST semplice quando si aspetta un frame WebSocket, ottiene un 404 (undocumented) poco utile. Sembra una rotta mancante, ma in realtà è una richiesta rifiutata.

Principali cause di fallimento degli ordini bracket dell'API Tradovate

1. Ha controllato solo lo stato HTTP, non il corpo

Questa è la trappola numero uno. Il suo client vede 200 OK, registra “ordine inviato” e prosegue, ma l'entrata è stata rifiutata, oppure è passato solo l'ordine padre. Analizzi ogni risposta OSO/OCO alla ricerca di failureReason e failureText prima di considerare il bracket attivo.

2. orderStrategyTypeId errato su startOrderStrategy

Molti provano con orderStrategyTypeId: 1 e ottengono solo un 404 (undocumented) per il disturbo. Esiste un solo valore valido, ed è 2. Qualsiasi altro valore viene rifiutato prima ancora che la strategia venga costruita.

Richiesta startOrderStrategy dell'API Tradovate con il campo orderStrategyTypeId evidenziato e impostato su 2

3. Chiamare startOrderStrategy via REST invece che via WebSocket

Anche con l'id di tipo corretto, questo endpoint non è affidabile via HTTP REST semplice. È costruito per funzionare su un WebSocket, e funziona in modo affidabile quando lo si pilota in quel modo. Una chiamata REST che continua a restituire 404 spesso ha successo, invariata, nel momento in cui la si invia come frame WebSocket.

4. JSON malformato o un dict grezzo invece di un corpo JSON

Un errore comune di placeOCO è Invalid JSON: expected '{', offset: 0x00000075. Ciò accade quando la richiesta invia un dizionario codificato come form invece di una stringa JSON serializzata, in Python, ad esempio passando data=payload invece di json=payload (o dimenticando json.dumps()). Il server non vede mai JSON valido, quindi scarta l'intero bracket.

5. accountSpec mancante, accountId errato o combinazione di prezzo illegale

Gli endpoint bracket richiedono sia l'accountId numerico (ricavato da account/list) sia la stringa accountSpec (il nome del suo account). Ometta uno dei due e otterrà Access is denied. Separatamente, placeOCO e placeOSO controllano che le due gambe formino una combinazione legale, uno stop e un limite quotati sul lato sbagliato del mercato tornano come Wrong OCO combination. I bracket con entrata Market aggiungono un'ulteriore complicazione: poiché l'API richiede livelli di prezzo concreti per le gambe figlie, generalmente non è possibile agganciare un TP/SL relativo in tick a una semplice entrata Market tramite placeOSO. O calcola lei stesso i livelli di prezzo, oppure lascia che sia il motore di strategia a gestire gli scostamenti.

Come correggere gli ordini bracket dell'API Tradovate: passo dopo passo

Correggere la trappola «200 OK ma nessuna gamba»

  • Dopo ogni chiamata a placeOSO / placeOCO / startOrderStrategy, analizzi il corpo JSON.
  • Verifichi la presenza di una chiave failureReason. Se c'è, tratti l'ordine come rifiutato e legga failureText per la causa.
  • Consideri il bracket attivo solo quando ha gli ID ordine confermati sia per il padre sia per entrambe le gambe figlie, esegua polling su order/list oppure si iscriva agli eventi ordine via WebSocket.
  • Registri il corpo completo, non solo il codice di stato, in modo che le esecuzioni parziali compaiano nella sua traccia di audit.

Correggere i 404 di startOrderStrategy

  • Imposti orderStrategyTypeId su 2, l'unico valore accettato.
  • Invii sia accountId sia accountSpec, oltre a symbol, action e l'oggetto params (con la sua entryVersion e i brackets).
  • Invii la richiesta come frame WebSocket anziché come POST REST. Questo endpoint è progettato per funzionare via WebSocket, e il formato di frame atteso è ben documentato.
  • Riprovi lo stesso payload tramite il socket prima di presumere che il suo JSON sia malformato, il 404 è di solito un problema di trasporto, non di schema.
Payload placeOSO dell'API Tradovate che mostra le gambe bracket1 stop-loss e bracket2 take-profit con accountId e accountSpec

Correggere Invalid JSON e Wrong OCO combination

  • Serializzi il payload come JSON. In Python requests, usi requests.post(url, headers=..., json=payload), mai data=payload con un dict.
  • Confermi che l'header Content-Type: application/json sia impostato.
  • Per placeOCO, controlli la geometria delle due gambe: lo stop e il limite devono trovarsi su lati opposti e validi rispetto al prezzo attuale, in base alla direzione della posizione. Se vede Wrong OCO combination, inverta la gamba sul lato sbagliato.
  • Per un'entrata Market, attenda l'esecuzione e alleghi uno stop/target placeOCO alla posizione risultante, oppure passi a startOrderStrategy, che accetta scostamenti relativi.

Il fallback affidabile: entrata separata + OCO

Quando un bracket nativo semplicemente non collabora, disaccoppi l'entrata dalle uscite. Piazzi l'ordine di entrata da solo con order/placeOrder, confermi l'esecuzione, quindi invii un placeOCO che abbina lo stop protettivo all'obiettivo di profitto sulla posizione ormai aperta. È un giro di andata e ritorno in più, ma aggira completamente l'endpoint di strategia e le dà un controllo esplicito su ogni gamba.

Flusso di fallback dell'API Tradovate: un ordine di entrata eseguito seguito da un placeOCO che allega le gambe di stop e target

Tabella di risoluzione dei problemi

Errore Significato Soluzione
200 OK con failureReason nel corpoOrdine rifiutato a livello di business logic nonostante uno stato HTTP pulitoAnalizzi il corpo; non si fidi mai solo del codice di stato
404 (undocumented) su startOrderStrategyorderStrategyTypeId errato, oppure REST usato dove è previsto WebSocketImposti orderStrategyTypeId: 2 e invii via WebSocket
Invalid JSON: expected '{', offset: 0x...È stato inviato un dict grezzo / corpo form invece di JSON serializzatoInvii un corpo JSON (json= in requests) o applichi prima json.dumps()
failureReason: InvalidPrice, failureText: Wrong OCO combinationLe due gambe OCO non formano un abbinamento prezzo/tipo validoRiquoti in modo che stop e limite siano su lati opposti validi
Access is deniedaccountId o accountSpec mancante o erratoInvii l'accountId numerico da account/list insieme al nome accountSpec
L'entrata viene eseguita, nessuno stop/target appareLe gambe figlie sono state rifiutate silenziosamente mentre il padre è stato accettatoConfermi tutti e tre gli ID ordine, oppure ripieghi su entrata + placeOCO

Come previene tutto questo PickMyTrade

Costruire manualmente i payload OSO/OCO significa farsi carico di ciascuna delle modalità di errore sopra descritte. PickMyTrade si posiziona tra i suoi alert TradingView e Tradovate e gestisce per lei l'idraulica del bracket:

  • Gestione bracket e OCO, allega correttamente le gambe di stop-loss e take-profit, così un'entrata non resta mai priva di protezione.
  • Validazione delle risposte, ispeziona l'intera risposta dell'ordine, non solo lo stato HTTP, e fa emergere i rifiuti reali invece di un falso “successo”.
  • Filtri di entitlement e rischio, rispetta lo stato dell'accordo dati del suo account e i limiti della prop firm prima che un ordine venga instradato.
  • Instradamento sicuro rispetto ai rate limit, distanzia il flusso di ordini così che le gambe del bracket non urtino i tetti di richiesta.
  • Sincronizzazione multi-account, replica lo stesso bracket protetto su ogni account collegato.

Faccia trading senza rifiuti

Avvii la sua prova gratuita di 5 giorni, colleghi oggi stesso i suoi alert e lasci che PickMyTrade agganci correttamente stop-loss e take-profit ogni volta.

Avvii la sua prova gratuita di 5 giorni

Domande frequenti

Usi order/placeOSO quando una singola entrata deve inviare uno stop e un target come bracket1 e bracket2. Usi order/placeOCO per collegare due ordini di uscita in modo che l'esecuzione di uno annulli l'altro. Usi orderStrategy/startOrderStrategy per una strategia bracket lato server con scostamenti relativi.

Tradovate segnala i rifiuti di business logic all'interno del corpo della risposta, non nello stato HTTP. Analizzi il corpo alla ricerca di failureReason e failureText, e consideri il bracket attivo solo quando ha gli ID ordine confermati per il padre ed entrambe le gambe figlie.

È un rifiuto InvalidPrice che significa che le sue due gambe OCO non formano un abbinamento legale, tipicamente lo stop e il limite sono quotati sul lato sbagliato del mercato rispetto alla direzione della posizione. Riquoti la gamba incriminata.

Quasi sempre un orderStrategyTypeId errato (deve essere 2) oppure una chiamata REST dove Tradovate si aspetta un frame WebSocket. Corregga l'id di tipo e reinvii via WebSocket.

Sta inviando un dizionario grezzo o un corpo codificato come form. Serializzi prima il payload in JSON, in Python requests, passi json=payload invece di data=payload.

Non direttamente, placeOSO si aspetta livelli di prezzo concreti per le sue gambe figlie. O calcoli lei stesso i prezzi esatti prima dell'invio, attenda l'esecuzione e alleghi un placeOCO, oppure usi startOrderStrategy, che accetta scostamenti relativi.

Disaccoppi il flusso. Piazzi l'entrata con order/placeOrder, confermi l'esecuzione, quindi invii un placeOCO che abbina stop e target alla posizione aperta. Evita completamente l'endpoint di strategia.

Sì. Gli endpoint bracket si aspettano l'accountId numerico da account/list e il nome account accountSpec come stringa. Omettere uno dei due restituisce Access is denied.

Questa guida ha scopo esclusivamente educativo e informativo e non costituisce consulenza finanziaria, di investimento o di trading. Il trading di futures e altri prodotti a leva comporta un rischio sostanziale di perdita e non è adatto a ogni investitore. PickMyTrade è una piattaforma di automazione indipendente di terze parti e non è affiliata, sostenuta o sponsorizzata da Tradovate, Inc. o Bookmap. 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 nella documentazione ufficiale della piattaforma prima di agire.