Hffix
Financial Information Exchange Protocol C++ Library
Install / Use
/learn @jamesdbrock/HffixREADME
High Frequency FIX — C++ Library for Financial Information Exchange Protocol {#mainpage}
Introduction
The High Frequency FIX Parser library is an open source implementation of <a href="https://www.fixtrading.org/standards/">tagvalue FIX (classic FIX)</a> intended for use by developers of high frequency, low latency financial software. The purpose of the library is to do fast, efficient encoding and decoding of FIX in place, at the location of the I/O buffer. The library does not use intermediate message objects, and it does no memory allocation on the free store (the “heap”).
hffix library is not certified by any industry-leading committees. It is not an “engine.” It is not an “adaptor.” It has no threading, no I/O, no object-oriented subtyping. It is just a superfast parser and serializer in plain modern generic-iterator-style C++98.
Hello, FIX! Quick Start
The main repository is at https://github.com/jamesdbrock/hffix
fixprint
To see an example of the library in action, enter these four commands at your shell prompt. This example uses the fixprint utility which comes with the hffix library. The result will be a colorized and pretty-printed FIX 5.0 test data set.
git clone https://github.com/jamesdbrock/hffix.git
cd hffix
make fixprint
util/bin/fixprint --color < test/data/fix.5.0.set.2 | less -R
Usage
The library is header-only, so there is nothing to link. To use the hffix.hpp library for C++ FIX development, place the two header files in your include path and #include <hffix.hpp>.
hffix/include/hffix.hpphffix/include/hffix_fields.hpp
Documentation
Full Doxygen is on the internet at https://jamesdbrock.github.io/hffix
To build the Doxygen html documentation in the doc/html directory and view it:
git clone https://github.com/jamesdbrock/hffix.git
cd hffix
make doc
xdg-open doc/html/index.html
Library Design
High Frequency FIX Parser tries to follow the <a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md">C++ Core Guidelines</a> and the <a href="http://www.boost.org/development/requirements.html">Boost Library Requirements and Guidelines</a>. It is modern platform-independent header-only C++98 and depends only on the C++ Standard Library. It is patterned after the C++ Standard Template Library, and it models each FIX message with Container and Iterator concepts. It employs compile-time generic templates but does not employ object-oriented inheritance.
Speed
The design criteria for High Frequency FIX Parser are based on our experience passing messages to various FIX hosts for high frequency quantitative trading at <a href="http://www.t3live.com">T3 Trading Group, LLC</a>. These design criteria follow from the observation that the latency of a trading system depends on the following list of considerations, in descending order of importance.
- Network architecture. Most of the latency will be in the network between us and our peer, outside of our control. We should do everything we can to exert some control over the network to shorten our path.
- Operating System I/O syscall usage. We should be very careful about which syscalls we're using to do network I/O. Perhaps use an OS bypass NIC.
- Operating System thread usage. We should be running a single pinned operating system thread per core with a multiplexed event loop like Boost Asio or libuv for waiting on I/O events.
- Userspace runtime memory usage. Memory allocations can trigger a page fault and a syscall. Complicated object-oriented designs with lots of pointer indirections lead to cache misses and branch prediction failures.
- Userspace algorithms. This is the easiest stuff to measure and the most fun to discuss, so a lot of attention is focused here, but it's only important if we get all the other considerations right first.
The hffix library assumes that the library user will want to make their own choices about considerations 2 and 3, and the hffix library focuses on providing good answers for consideration 4. It does this by using only stack memory and I/O buffer memory, and never allocating on the free store.
In contrast, the popular alternative QuickFix library forces the user to use the QuickFix solution to considerations 2 and 3 for threads and sockets, and most of QuickFix's choices about threads and sockets are not great. QuickFix also has an inefficient object-oriented design for consideration 4.
See also <a href="https://www.youtube.com/watch?v=NH1Tta7purM">CppCon 2017: Carl Cook “When a Microsecond Is an Eternity: High Performance Trading Systems in C++”</a>
Specs Included
All of the Financial Information Exchange (FIX) protocol specification versions supported by the library are bundled into the the distribution, in the fixspec directory. As a convenience for the developer, the High Frequency FIX Parser library includes a program which parses the FIX protocol specification documents and generates the include/hffix_fields.hpp file. That file hffix::tag enums and an hffix::dictionary_init_field function which allows fields to be referred to by name instead of number during both compile-time and run-time.
Platforms
The library is platform-independent C++98, and is tested on Linux with gcc and clang on Github Actions.
License
The main High Frequency FIX Parser Library is distributed under the open source FreeBSD License, also known as the Simplified BSD License.
Some extra components are under the Boost Software License.
Included FIX specs are copyright FIX Protocol, Limited.
Features
Serial Message Field Access
For reading FIX messages, High Frequency FIX Parser presents an STL-style <a href="https://en.cppreference.com/w/cpp/named_req/ForwardIterator">immutable Forward Iterator</a> interface. Writing fields is done serially with an interface similar to an STL-style <a href="https://en.cppreference.com/w/cpp/named_req/SequenceContainer">Back Insertion Sequence Container</a>. Reading and writing are done directly on the I/O buffer, without any intermediate objects.
The disadvantage of this implementation is that the message API provides serial access to fields, not random access. Of course, when we're writing a message, random access isn't important, just write out the fields in order. When we're reading a message, it's easy enough to pretend that we have random access by using iterator algorithms like std::find. A convenience algorithm hffix::message_reader::find_with_hint is provided by this library for efficiently reading fields when you know approximately what field order to expect. See the examples below for how this works out in practice.
The advantage is that this enables the High Frequency FIX Parser library to completely avoid free store memory allocation.
The library performs all memory allocation on the stack, and the library never requires developers using the library to allocate anything on the free store with new or malloc.
Field values in the FIX protocol are always encoded on the wire as ASCII, and High Frequency FIX Parser exposes field values to the developer as iterator range char const* begin(), char const* end(). High Frequency FIX Parser also provides a complete set of conversion functions to native C++ types for ints, decimal floats, dates and times, et cetera — see documentation for hffix::message_writer and hffix::field_value.
Exceptions
Some functions in this library may throw std::logic_error if a precondition is not met by the programmer, so you can usually prevent the library from throwing exceptions by meeting the precondition. All methods, functions, constructors, and destructors provide the No-Throw exception guarantee unless they are documented to throw exceptions, in which case they provide the Basic exception guarantee. See documentation for details.
Thread Safety
High Frequency FIX Parser is not thread-aware at all and has no threads, mutexes, locks, or atomic operations.
All const methods of the hffix::message_reader are safe for concurrent calls.
The hffix::message_writer is not safe for concurrent calls.
hffix::message_reader and hffix::message_writer have no storage of their own, they read and write fields directly on an I/O buffer. The developer must guarantee that the buffer endures while fields are being read or written.
FIX Sessions
Managing sessions requires making choices about sockets and threads. High Frequency FIX Parser does not manage sessions. It is intended for developers who want a FIX parser with which to build a session manager for a high-performance trading system that already has a socket and threading architecture.
FIX has transport-layer features mixed in with the messages, and most FIX hosts have various quirks in the way they employ the administrative messages. To manage a FIX session your application will need to match the the transport-layer and administrative features of the other FIX host. High Frequency FIX Parser has the flexibility to express any subset or proprietary superset of FIX.
See also FIX Session-level Test Cases and Expected Behaviors
Numerics
No native floating-point numeric types (double, float) are employed by the library.
ASCII-encoded decimal numbers are represented by integral mantissa and exponent.
See hffix::message_writer::push_back_decimal() and hffix::field_value::as_decimal().
As with every FIX data type, the High Frequency FIX library user has the option to serialize
and deserialize numeric fields themself rather than use these methods.
Encryption
High Frequency FIX Parser su
