Durante mis años trabajando como sysadmin, desarrollador, e investigador en Ifitec, tuve que (obviamente), hacer muchos proyectos, pero solo dos me dieron dolores de cabeza por la poca documentación que había para introducirse.
El primero, fuero Oracle, en específico, su motor de Bases de Datos. Es monolítico, lo cual hace que la instalación, sea igual de ingente. Y el segundo, fue el motor de mensajería para transacciones financieras, QuickFIX, por su escasa documentación inicial, y prácticamente su carencia de “Hello Worlds!”.
Pero obviamente, si todo fuese tan fácil, no existrían los desafíos, asique puse manos a la obra, y aquí les dejo mis “traspies” con QuickFIX para que no les pase lo mismo que a mi 😀
Introducción a FIX y QuickFIX
FIX, es la especificación del Protocolo para transacciones financieras “Financial Information eXchange”, o FIX. Participan en su elaboración un gran número de stakeholders, interesados en hacerla cada día mas completa, y abierta. Fue concebida en el 1992, y su misión es “To improve the global trading process by defining, managing and promoting an open protocol for real-time, electronic communication between industry participants, while complementing industry standards.” (Mas información sobre FIX aquí, NOTA: si quieres obtener acceso al sitio completo, debe registrarte)
A pesar de que la especificación del protocola es abiertas, sus implementaciones no tienen la obligación de serlo (ya se libre – como libre en cerveza-, o codigo abierto), y la mayoría son especificaciones comerciales. Aquí es donde entra en el cuadro QuickFIX.
QuickFIX, es una implementación de código abierto de FIX. Actualmente soporta hasta la versión 4.4 de la especificación FIX, y es bastante robusto. Tiene implementaciones para Java, C++, Ruby y Python.
Usando QuickFIX
La licencia de QuickFIX no es una de las tradicionales open-source, pero sigue su espíritu, permitiendo la modificación y redistribución del código, siempre y cuando se conserve su autoría original, se reconozca a sus autores en los softwares derivados, y el nombre QuickFIX, no puede ser usado sin consultar antes a sus dueños.
Del FAQ de QuickFIX, es bastante importante tener en consideración los siguientes puntos:
- Â Las horas de todos los computadores envueltos en transacciones FIX deben estar sincronizadas, de preferencia, usando un servidor NTP común.
- Quickfix esta programado en C++ y hace uso de excepciones. Compilar tus proyectos con la opción “-fexceptions”.
Arquitectura de FIX
QuickFIX, más allá de ser una implementación de un protocolo, es también un motor de mensajería. Esto delega gran parte del control sobre la transmisión, a QuickFIX. Es por esto, que hay que conocer la arquitectura antes de poder usarlo.
FIX en si, divide todos sus mensajes en dos tipos, Session y Application. Asimismo, el motor QuickFIX divide su funcionamiento entre estas dos capas.
- Sesión: esta capa esta encargada de manejar cosas como login, logout, recuperación de mensajes, heartbeats, peticiones de test, peticiones de reenvio, rechazos, reseteos de secuencia (gap fills), entre otros. La mayoría de estos mensajes se usan de forma automática, pero siempre pueden ser modificados, o enviados bajo petición del programador.
- Aplicación: Dado que FIX maneja información de trade para stock market y futures market, los mensajes de la capa de aplicación estarán en la linea de enviar una orden, obtener una confirmación (fill), cambiar una orden, entre otros. Estos mensajes nunca son generador de forma automática por el motor QuickFIX, el programador debe controlar el flujo de mensajes en esta aplicación de forma total.
Si desea un buen resumen de la estructura y funcionamiento de FIX y Quickfix, referirse a este link. (una breve y muy intuitiva introducción a FIX, por DevChix).
Conceptos de FIX
- Contra parte: El otro lado de la conexión. Si se esta trabajando en el cliente, la contraparte será el servidor, y vice-versa.
- Mensaje: Mensaje que se envía una contra parte a otra. Existen dos tipos:
- Aplicación: Mensaje generados por la aplicación (que en si, es lo que realmente se programa, es decir, la información financiera)
- Administrativos: Mensajes generados por el Engine Quickfix para control de la conexión, la mayoría son mensajes de Sesión.
- Sesiones: Las sesiones existen mientras exista la aplicación, y pueden ser definidas como un canal de comunicación entre dos contrapartes. Estas existen incluso si no hay contra parte que escuche o este conectada. Al momento de ser creada una sesión, puedes enviar mensajes. Si no hay contraparte activa, los mensajes serán enviados al momento en que una conexión sea establecida por la contra parte (un cliente conectado).
- Iniciador: En cada sesión, existe, un iniciador, una de las contraparte debe iniciar la sesión. Esto se debe a que QuickFIX esta implementado sobre TCP/IP, por ende, una de las contrapartes debe intentar contactar a otro “servidor”
- Aceptador: El aceptador actúa como listener en TCP/IP, normalmente también es el servidor central de transacciones financieras. Esta contraparte escucha la red en un socket, esperando conexiones entrantes de sus contrapartes “iniciadoras”.
Mensajes FIX al descubierto
Este es un ejemplo de un mensaje FIX
Send(12/06/2006-10:23:43.175)|8=FIX.4.2|9=00060|35=0|49=Alex|56=orders|34=99|52=20041206-10:23:43.175|10=080|
Un mensaje esta compuesto de varios tags ( Ej: 8=FIX.4.2| ). Este tag, esta compuesto de:
- ID del Tag: Un número que identifica a que corresponde el tag. (ej: 8). Es muy importante entender estos números. Por ejemplo, el número 43, indica que es un valor de secuencia de mensajes.
- =: Signo igual (ej: =)
- valor: Dependiendo del id de tag, el valor puede cambiar (ej: FIX.4.2)
- delimitador: Indica el fin del tag. (ej: |)
Dado que ya sabemos como esta compuesto un mensaje, podemos analizarlos. La especificación 4.4 de FIX posee cerca de 900 tags, y cada mensaje tiene especificado cuales de estos tags son obligatorios, opcionales, o prohibidos para ese mensaje. Pero todo deben tener los siguientes dos tags, que son universales.
- 34: Número de secuencia (permite la sincronización entre contrapartes)
- 35: Tipo de mensaje (permite identificar el mensaje, y darle un sentido a los datos que trae).
El tipo de mensaje permite saber que comunica ese mensaje, algunos casos son:
- 0: Heartbeat(usado para mantener vivas –keepalive– las comunicaciones)
- A: Logon (es usado para iniciar las sesiones, permite identificar y autenticar)
- 5: Logout
- B: News (Noticia)
- S: Quote (Para registrar en tiempo real los bid & ask)
- y otros…
FIXimate 4.4, es una presentación mas amigable de la especificación de FIX 4.4 (que es XML), ordenada por mensajes o tags. Cuando programes, ten siempre un navegador abierto con esta página.
Instalación y Compilación de las fuentes
En Fedora (cuando comence, era Fedora 7), es necesario tener instalados lo siguientes paquetes:
- mysql-devel
- libxml2
- libxml2-devel
- gcc
- gcc-c++
- glibc-devel
- make
- python
- python-devel
- ruby
- ruby-devel
Utiliza el siguiente comando de yum para instalarlos:
yum install mysql-devel libxml2 gcc gcc-c++ glibc-devel make python python-devel ruby ruby-devel
Luego, debes descargar la ultima versión desde esta dirección y descomprimirla:
cd /tmp
wget http://ufpr.dl.sourceforge.net/sourceforge/quickfix/quickfix-1.12.4.tar.gz
tar xvfz quickfix-1.12.4.tar.gz
Luego, ingresa al directorio quickfix y crea los scripts makefile con la siguiente configuración:
./configure --with-python=/usr/include/python2.4/ --with-ruby --with-mysql=/usr
Nota: La opción de mysql esta incorrecta apropósito. Si no se especifica así, el Makefile construido no es capaz de encontrar las cabeceras de desarrollo de MySQL.Luego, compilamos QuickFIX. Es normal cuando se compila el soporte para Python, el computador deje de responder (esto sucede cuando el computador tiene poca RAM)… (y si… el computador completo deja de responder 🙁 ).
make
Una vez que termina de compilar, instalamos las bibliotecas quickfix en nuestro sistema. Esto debe ejecutarse como usuario root.
su -
cd /tmp/quickfix
make install
¡Y listo!, ya tienes QuickFIX en tu sistema.
NOTA: Los siguientes pasos de la instalación solo deben realizarse si se utilizará el soporte de MySQL.
Ahora se deben crear la BD y tablas de QuickFIX en MySQL. Para eso, QuickFIX proporciona un script, el cual se modificara ligeramente.
cd /tmp/quickfix/src/sql/mysql
Edita el archivo ”’create.sh”’. Este archivo tiene una solo linea, que ahora deberá ser:
mysql -u root -p --execute="source mysql.sql";
Esto permite autenticar con password de forma interactiva. Ejecuta ahora el script, e ingresa la password del usuario ”’root”’ de mysql.
./create.sh
Explicación sobre el funcionamiento de QuickFIX
QuickFIX en si posee una arquitectura cliente(s)/servidor(es). Y su implementación se basa en TCP/IP. La biblioteca de QuickFIX se encarga de crear las conexiones, y de auto-configurarse (a partir de un archivo). Como programador, solo es necesario preocuparse de crear un archivo de configuración y los mensajes a enviar.
Toda aplicación de QuickFIX, debe tener un archivo de configuración, el cual define el tipo de conexión, el puerto, si el puerto sera reutilizado, cuando inician y finalizan las sesiones, entre otros parámetros.
[DEFAULT]
ConnectionType=acceptor
SocketAcceptPort=5001
SocketReuseAddress=Y
StartTime=00:00:00
EndTime=00:00:00
[SESSION]
BeginString=FIX.4.4
SenderCompID=EXECUTOR
TargetCompID=CLIENT1
FileStorePath=store
DataDictionary=spec/FIX44.xml
Cada sección SESSION del archivo de configuración, puede especificar el DataDictionary a usar, el cual, es el DTD del protocolo FIX (la especificación formal del lenguaje). Se usa para validar los mensajes entrantes y salientes. Estos, debe estar en la ruta especificada. Los archivos spec se pueden encontrar junto con las fuentes de QuickFIX.
Las aplicaciones QuickFIX deben tener un conjunto de clases instanciadas, para poder funcionar como motor de mensajes, entre ellas podemos encontrar los Logger, Initiators, Acceptors. Todos estos actúan por separado.
Para poder enviar y recibir mensajes, se debe implementar la interfaz Application. Los métodos de esta interfaz serán llamados cuando ocurran los eventos a los cuales hacen referencia.
namespace FIX{
class Application{
public:
virtual ~Application() {};
virtual void onCreate( const SessionID& ) = 0;
virtual void onLogon( const SessionID& ) = 0;
virtual void onLogout( const SessionID& ) = 0;
virtual void toAdmin( Message&, const SessionID& ) = 0;
virtual void toApp( Message&, const SessionID& )
throw( DoNotSend ) = 0;
virtual void fromAdmin( const Message&, const SessionID& )
throw( FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon ) = 0;
virtual void fromApp( const Message&, const SessionID& )
throw( FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType ) = 0;
};
}
Método | Observaciones |
---|---|
~Application | Destructor que se encarga de limpiar el objeto |
onCreate | Esta función es llamada cuando se establece una sesión |
onLogon | Esta función es llamada cuando una contraparte envía un mensaje de tipo Logon (A). Por defecto, acepta toda conexión entrante. Es posible utilizar esta función para crear autenticación simple, o basada en sistemas de autententicación centralizadas. |
onLogout | Notifica cuando una sesión FIX ya no esta en linea, o cuando se recibe un mensaje de Logout (5). Posibles causes de ser llamada esta función son: un logout válido, problemas en la conexión, o terminación forzada de la conexión |
toAdmin | Notifica cuando el Engine QuickFIX enviará un mensaje administrativo a la contra parte. Algo interesante, es que la referencia que es pasada del mensaje no es constante. Es decir, se puede modificar el mensaje. |
toApp | Función de callback que se llama cuando se envía un mensaje de aplicación. La referencia al mensaje no es constante. Arrojar una excepción ”DoNotSend”, hace que el engine QuickFIX no envie este mensaje. |
fromAdmin | Notifica cuando llega al engine QuickFIX un mensaje administrativo de su contra parte |
fromApp | Es prácticamente el núcleo de una aplicación quickfix. Por ejemplo, en el caso de un sistema OMS (Order Management System), el lado del servidor recibe a través de esta función, las peticiones de nuevas ordenes. En cambio, por el lado del cliente, esta función dará permitirá recibir las confirmaciones de una orden emitida (o rechazo). La excepción ”FieldNotFound” permite decir a la contraparte que faltaron campos en el mensaje, esta excepción es tirada automáticamente por la clase Message. La excepción ”UnsupportedMessageType” permite indicar a la contra parte que no se posible procesar ese tipo de mensaje. La excepción ”IncorrectTagValue” permite indicar que un campo tiene un valor o rango no soportado. |
Compilación de Programas en C++
Para compilar con QuickFIX:
g++ -fexceptions -finline-functions -lquickfix -lpthread -lxml2 -lz -L/usr/local/lib Application.cpp main.cpp
- –fexceptions -Â Para el soporte de exceptions
- -finline-functions – Que las funciones sean compiladas inline.
- -lquickfix – Que incluya la libreria de quickfix al compilar.
- -lpthread – Que incluya la libreria de threads.
- -lxml2 – Que incluya al compilar, la libreria ”’xml2”’, para parsing de xml.
- -lz – Que incluya al compilar, la libreria ”’z”’, para compresión.
- -L/usr/local/lib – Que incluya en la ruta de librerias, este directorio
Para facilitar la compilación, usaremos ”’Makefile”’. Un archivo makefile como el siguiente, permite compilar una aplicación en quickfix:
CC = g++
CXXFLAGS = -fexceptions -finline-functions -lquickfix -lpthread -lxml2 -lz -L/usr/local/lib
all: executor
executor: Application.o
clean:
rm -rf *.o executor
Conclusiones
A pesar de que no se toco el tema de diseño y arquitectura, existe un trabajo en las referencias (Exploring FM Software Architecture), el cual trata sobre este tema, y posee análisis sobre características deseadas, consideraciones y recomendaciones para el diseño y arquitectura de software para Mercados Financieros.
Espero haber cumplido como introducción a QuickFIX. Pronto pondré un Hello World! de QuickFIX. Porfavor, dejen comentarios, para saber si interesa el tema. Saludos!!
Referencias
- Sitio del Protocolo FIX
- Sitio de Quickfix
- Sitio de descargas de Quickfix
- Documentación de Quickfix
- Listas de Correo de Quickfix
- Licencia de Quickfix
- FAQ de Quickfix
- FIX Protocol – DevChix
- Exploring FM Software Architecture
- FIXimate 4.4
… la especificación del protocola es abiertas …
/protocolo/
… se conserve su autorpia original …
/autoria/
… conocer la arquictectura antes …
/arquitectura/
… peticiones de reencio, rechazos, …
/reenvio/
… [etc] ….
Instálate un corrector ortográfico en Español a tu navegador! 😛
Éste RNT no puede aparecer sino que para decir las cosas malas de algo… aunque las crÃticas sean constructivas, un “Está bueno” nunca está demás!!!
Wenas arturo!
Tiempo q no pasaba por tu blog…
Podrias ponerte un par de etiquetas para acortar los posts… no conviene para lectura en celular ni PC’s pajeros… <!–pagebreak algo asi era 😛
Saludos, nos vemos la otra semana!
Hola como estás? Existe alguna forma que me pueda contactar con vos para hacerte unas preguntas?
Hola, mil gracias por la información me ha servido mucho.
Saludos desde Mexico
De Nada!!!, saludos también para ti!
Gracias por la info!
PD: Para RNT…
RNT=invesil…haber si corregÃs esta
Saludos muy buena informacion como parte introductoria, de verdad estaba perdido y me orientaste por el buen camino 🙂
Muy buen post!!! Tengo una consulta. Al momento de enviar un mensaje de log on como hago para que aparezcan en el los tag 50 (SenderSubId) y 57 (targetSubId). Es que a la compañia que me conecto, debo enviarle esta informacion. Ya tengo el valor de los parametros. Solo me falta enviarselos en el mensage de log on (35=A) Mi pregunta es. ¿Como hago? En el config? Como lo defino?
Gracias
Hola, me ha ayudado mucho el post.Cometas en la ultima linea que ibas a hacer algun articulo mas, lo has hecho ya?
Muchas gracias.
Gracias Juan,
Pero la verdad, es que lo iba a hacer en la medida que hubiese interes, pero ya han pasado anios en que trabajara en FIX. Me siento un poco oxidado como para hacer otro post sobre el tema.
Saludos!!
Hola Arturo, quiza podriamos escribir algo del FIX protocol para .net por lo facil y rapido, excelente, mil gracias
Alguien tiene ejemplos de alguna implementacion de QuickFIX para .NET?. Estoy comenzando a ver el tema y la verdad estoy un poco perdido. Agradecere cualquier tipo de ayuda!. Saludos.
oye , yo est0y intentandolo hacer desde net, pero no me funciona, me dice q datadictinary no reconocido,.. q sera? ,,, te agradeceria mucho si me puedes orientar.
hola amigo espero que te encuentres bien, bueno el post esta muy interesante y la verdad felicitaciones de ante mano, te agradezco, pero la verdad tengo una duda si tengo un quickfix, como server como lo hago que se ejecute siempre, o este esperando peticiones siempre?? saludos.
Hola Alexander.
Lamentablemente ya no trabajo con Quickfix, asique te respondere de lo que recuerdo (puede que este equivocado, o que las cosas hayan cambiado con el tiempo).
Mira este ejemplo, es uno de los mas basicos que pude encontrar:
http://www.quickfixengine.org/quickfix/doc/html/application.html
Aqui se usa la Clase “Acceptor”, la cual se le indica a traves del comando “start” que comience a aceptar conexiones. Mientras no se llame al metodo “stop”, la clase seguira aceptando conexiones.
En este ejemplo, se usa un ciclo while para dejarle esperando infinitamente por conecciones, lo cual es suficiente para un ejemplo, o una aplicacion muy basica.
La alternativa mas “elegante”, seria que usaras hebras. La idea seria encapsular la Clase Acceptor en una clase, que inicia una hebra a traves de uno de sus metodo. Este metodo tendra el mismo ciclo infinito con las llamadas a start y stop antes y despues del ciclo.
A traves de un metodo publico, provees una interfaz para detener el ciclo. acuerdate de usar mutex para el acceso al booleano, si no, tendras problemas de concurrencia.
Si encuentro alguno de los servidores que programe, te envio un ejemplo de codigo.
Saludos!!
Hola Alexander.
Lamentablemente ya no trabajo con Quickfix, asique te responderé de lo que recuerdo (puede que este equivocado, o que las cosas hayan cambiado con el tiempo).
Mira este ejemplo, es uno de los mas básicos que pude encontrar:
http://www.quickfixengine.org/quickfix/doc/html/application.html
Aquà se usa la Clase “Acceptor”, la cual se le indica a través del comando “start” que comience a aceptar conexiones. Mientras no se llame al método “stop”, la clase seguirá aceptando conexiones.
En este ejemplo, se usa un ciclo while para dejarle esperando infinitamente por conexiones, lo cual es suficiente para un ejemplo, o una aplicación muy básica.
La alternativa mas “elegante”, seria que usaras hebras. La idea seria encapsular la Clase Acceptor en una clase, que inicia una hebra a través de uno de sus método. Este método tendrá el mismo ciclo infinito con las llamadas a start y stop antes y después del ciclo.
A través de un método publico, provees una interfaz para detener el ciclo. acuérdate de usar mutex para el acceso al booleano, si no, tendrás problemas de concurrencia.
Si encuentro alguno de los servidores que programe, te envÃo un ejemplo de código.
Saludos!!
lalalala