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 existirí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 :D

Introducción a FIX y QuickFIX

FIX ProtocolFIX, 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.

QuickFIXQuickFIX, 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”.

FIX, de forma gráfica

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

Agradecimientos

  • A Renato (RNT), por recordarme que debo corregir las faltas de ortografía :P
  • A mis colegas de Ifitec, que ellos son ahora más expertos en FIX que yo :D