Inviare e ricevere messaggi¶
Introduzione ¶
Questo articolo serve come introduzione all'uso dell'API FIX per chiunque sia interessato a interagire con Spotware cServer utilizzando FIX.
In questo articolo, useremo un esempio in C# per descrivere in dettaglio i principi di come costruire un messaggio FIX, inviarlo al server e ricevere la risposta. Questo esempio non è in alcun modo un'applicazione a prova di proiettile ed è stato mantenuto il più semplice possibile per consentire ai programmatori di comprendere facilmente il concetto di utilizzo dei messaggi API FIX.
Per stabilire e mantenere una comunicazione adeguata con il server e una gestione corretta delle risposte, sono necessarie funzionalità aggiuntive, che sono state omesse per semplicità e chiarezza. Tratteremo questi argomenti in articoli futuri.
Esempio di codice ¶
Puoi trovare l'esempio di codice discusso in questo articolo nel nostro repository GitHub
Panoramica della comunicazione FIX ¶
Un messaggio FIX è semplicemente una stringa composta da set di tag numerici e valori separati da una barra verticale (|). Ogni tag rappresenta un campo diverso per il quale è consentito un certo set di valori. Di seguito puoi vedere un esempio di messaggio FIX che richiede l'autenticazione dal server.
8=FIX.4.4|9=126|35=A|49=theBroker.12345|56=CSERVER|34=1|52=20170117- 08:03:04|57=TRADE|50=any_string|98=0|108=30|141=Y|553=12345|554=passw0rd!|10=131|
Come puoi vedere, il modello ripetibile presente in ogni messaggio FIX è:
Tag=Value|Tag=Value|Tag=Value|...
A seconda dello scopo di ciascun messaggio, ogni volta è richiesto un set diverso di tag e valori. I tag e i valori richiesti per ciascun messaggio sono descritti in dettaglio nelle Regole di Ingaggio del motore FIX di cTrader (controlla sempre le regole di ingaggio più recenti).
In modo simile, le risposte vengono inviate dal server. Di seguito puoi vedere la risposta del server per il messaggio sopra.
8=FIX.4.4|9=106|35=A|34=1|49=CSERVER|50=TRADE|52=20170117- 08:03:04.509|56=theBroker.12345|57=any_string|98=0|108=30|141=Y|10=066|
I passaggi coinvolti nel processo di comunicazione con un server FIX sono i seguenti:
-
Costruire un messaggio FIX
-
Trasmettere un messaggio FIX
-
Ricevere un messaggio FIX
-
Analizzare un messaggio FIX
Un messaggio FIX grezzo non è un formato molto leggibile poiché è stato progettato pensando all'efficienza piuttosto che alla comprensibilità. Pertanto, per ogni applicazione software ci sarà sempre un processo di traduzione delle informazioni fornite nel rispettivo messaggio FIX.
Nella nostra applicazione di esempio C# abbiamo creato una classe per gestire la costruzione dei messaggi, nonché funzioni per creare messaggi FIX basati sulle informazioni pertinenti.
Dopo che i messaggi sono stati costruiti, vengono trasmessi tra un server e un client su Internet tramite socket di rete. Quando i messaggi vengono ricevuti, devono essere analizzati per essere presentati in un formato leggibile.
In questo articolo tratteremo il processo di costruzione, trasmissione e ricezione della risposta. Tratteremo l'analisi in un articolo futuro.
Costruire un messaggio FIX ¶
Struttura del messaggio ¶
Nella nostra applicazione di esempio abbiamo creato una classe responsabile della creazione di messaggi FIX. La classe si chiama MessageConstructor e può essere trovata nel progetto FIX API Library.
Il MessageConstructor viene inizializzato con i seguenti parametri:
-
Host(*)– l'indirizzo dove si trova il nostro cServer. -
Username(*)– il numero di conto -
Password(*)– la password -
SenderCompID(*)– viene fornito nel modulo API FIX di cTrader. È nel formato -
SenderSubID*– è la seconda parte di SenderCompID -
TargetCompID(*)– viene fornito nel modulo API FIX di cTrader (di solito è cServer)
Puoi trovare queste informazioni nel tuo modulo API FIX di cTrader.
Dopo aver inizializzato un MessageConstructor siamo pronti a costruire messaggi API FIX.
Tutti i messaggi vengono costruiti in modo simile. Di seguito è riportato un esempio di codice per la costruzione di un messaggio Logon.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | |
Puoi vedere che prima costruiamo la parte del corpo, poi la passiamo alla funzione header e infine passiamo entrambe le parti nella funzione trailer. Queste 3 parti sono dettagliate di seguito.
Il processo di costruzione del messaggio è semplicemente l'aggiunta dei tag, valori e separatori richiesti in una stringa.
Corpo ¶
Per prima cosa inizieremo descrivendo la costruzione del body, poiché il body del messaggio deve essere creato per primo. Possiamo vedere un esempio sopra (creazione del messaggio Logon).
Iniziamo inizializzando una classe StringBuilder e aggiungiamo i tag uno per uno in base agli input della funzione. In base al tipo di messaggio, il body deve essere composto da diversi set di tag, alcuni dei quali obbligatori e altri facoltativi.
Puoi trovare la struttura di ogni messaggio nelle nostre Rules of Engagement (/FIX).
Quindi creiamo un header per un messaggio Logon e vi aggiungiamo il body del messaggio. Infine, utilizzando la stringa headerAndBody generiamo il trailer. Di seguito, vedremo come costruire un header e un trailer.
Header ¶
L'header è la prima parte del messaggio FIX ed è composto dai seguenti campi (uguali per tutti i messaggi):
BeginString– la stringa iniziale definisce la versione del protocollo FIX e nel nostro caso è fissata a FIX4.4.BodyLength– la lunghezza del body indica la lunghezza del messaggio in caratteri, escludendo i campiBeginString,BodyLengthe trailer.MsgType– in questo campo definiamo il tipo di messaggio, in modo che il destinatario sappia come analizzare il body.SenderCompID– qui impostiamo ilSenderCompID.TargetCompID– questo è il destinatario del nostro messaggio. Nel nostro caso, sarà sempre cServer.SenderSubID– il login del trader.MsgSeqNum– questo è il numero di sequenza del messaggio. Deve essere incrementato per ogni messaggio inviato nella stessa sessione.Sending Time– l'ora di trasmissione del messaggio.
Di seguito puoi vedere la funzione ConstructHeader, responsabile della costruzione degli header.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
Trailer ¶
Il trailer è semplicemente un tag contenente il checksum del resto del messaggio.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Messaggi di sistema ¶
Il nostro esempio contiene funzioni che restituiscono i seguenti messaggi di sistema:
- Heartbeat:
MessageConstructor.HeartbeatMessage() - Test request:
MessageConstructor.TestRequestMessage() - Logon:
MessageConstructor.LogonMessage() - Logout:
MessageConstructor.LogoutMessage() - Resend request:
MessageConstructor.ResendMessage() - Reject:
MessageConstructor.RejectMessage() - Sequence reset:
MessageConstructor.SequenceResetMessage()
Messaggi applicativi ¶
Il nostro esempio contiene funzioni che restituiscono i seguenti messaggi di sistema:
- Market data request:
MessageConstructor.HeartbeatMessage() - Market data snapshot/full refresh:
MessageConstructor.MarketDataSnapshotMessage() - Market data incremental refresh:
MessageConstructor.MarketDataIncrementalRefreshMessage() - New order single:
MessageConstructor.NewOrderSingleMessage() - Order status request:
MessageConstructor.OrderStatusRequest() - Execution report:
MessageConstructor.ExecutionReport() - Business message reject:
MessageConstructor.BusinessMessageReject() - Request for positions:
MessageConstructor.RequestForPositions() - Position report:
MessageConstructor.PositionReport()
nvia un messaggio e ricevi una risposta ¶
Per inviare un messaggio FIX a cServer devi prima stabilire una connessione con il server. Puoi farlo creando un TcpClient. Nel nostro caso creiamo due client, poiché i messaggi di quotazione dei prezzi e i messaggi di trading sono gestiti da porte diverse sul server.
Quindi, dobbiamo ottenere i due stream su cui verranno inviati i messaggi. Questo processo avviene nel costruttore del form come mostrato di seguito:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Nel costruttore, inizializziamo anche una classe MessageConstructor che verrà utilizzata per generare i messaggi.
Successivamente, per inviare i messaggi, abbiamo creato due funzioni diverse, SendPriceMessage() e SendTradeMessage(). Ognuna prende il messaggio FIX come input e quindi chiama la funzione SendMessage() con il messaggio e il rispettivo stream come input.
La funzione SendMessage() funziona come segue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
I passaggi dettagliati sono i seguenti:
- Codificare il messaggio in un array di byte.
- Scrivere l'array di byte sullo stream.
- Leggere la risposta dallo stream.
- Incrementare il numero di sequenza del messaggio.
- Codificare il messaggio in una stringa.
La funzione dovrebbe restituire il messaggio FIX inviato dal server.
Come puoi immaginare, non puoi mostrare un messaggio FIX grezzo all'utente, quindi dovrebbe essere sviluppato un passaggio aggiuntivo di analisi del messaggio in arrivo.
Conclusione ¶
Questa applicazione è una breve dimostrazione su come comunicare con cServer utilizzando messaggi FIX. È solo un esempio che illustra i concetti del protocollo FIX e non è in alcun modo un motore FIX completo. Se desideri evitare di costruire il tuo motore FIX, potresti considerare l'utilizzo di uno dei motori FIX di terze parti disponibili.
Nota
Questo articolo è aggiornato al 03/02/2017 ed è stato sviluppato tenendo conto del motore FIX di cTrader, Rules of Engagement v2.9.1.