I used the D programming language to implement the High Frequency Trading (HFT) platform. I was quite satisfied with the experience and decided to share how I came to this. This path was thorny.
In 2008 on Amazon I came across a book called “Learn to Tango with D”… This piqued my curiosity and decided to study D in more detail. This led me to Digital Mars and Walter Bright. I first heard about Walter when I heard about Zortech C ++, the first native C ++ compiler… His work has had a huge impact on my path to learning C ++. Therefore, I immediately became interested in the language only because he was its author, and was glad to know that he, together with Andrei Alexandrescu, was working on the second version. However, I decided to wait for them to move further on the new version before diving into the project.
In 2010 I bought Andrey’s book “The D Programming Language”as soon as it was published and started reading. At that time I was working at BNP Paribasusing C ++ to optimize my HFT platform, so high performance dominated my thoughts. When I saw that the classes in D are reference types, and their functions are virtual by default, I was disappointed. I didn’t understand how this could be useful for low latency programming. At the time, I was too busy with my work to delve deeper into the study, so I put the book and the language aside.
In 2014, I began to prepare for a new endeavor. As part of this, I started working on a new input handler framework (Feed-Handler) in C ++ using its own long-supported C ++ library of low-level components useful in high-performance, low-latency applications. Andrey’s book caught my eye again, and I decided to look at it again.
This time I finished reading the book to the end and realized that my initial impression was wrong. I found that I liked D’s metaprogramming capabilities and its support for functional programming. By the end of the book, I was ready to give D.
I started by porting my C ++ library and input handler to D. It was easy. I use very little inheritance in my C ++ code, preferring composition and concrete classes (Concrete class). I have found myself to be quite productive with structs, templates and mixins (mixin) D. In doing so, I closely followed the performance indicators. When D turned out to give the same performance as my C ++ code, I was bought with giblets. I found D to be much more elegant, cleaner, more readable, and easier to maintain. I switched to D and didn’t look back anymore.
My goal was to develop a complete HFT system using D. The system had to consist of various subsystems:
Feed-Handler Framework: Receives market data from exchanges; creates journals for all securities; publishes updates for other subsystems.
Strategies Framework: Receives market data updates from Input Processor 1; facilitates communication with the order management system, clause 3; allows you to connect to it strategies that make decisions about trading stocks.
Order Management System: interacts with the exchange and the strategy system, clause 2; maintains a database of orders.
Signal Generator: receives market data updates from input data processors clause 1; generates various signals in the form of indicator values, stock price predictions, etc .; sends various signals to the strategies of item 2.
In the end, I found a new data structure and better design for my input handler. I developed the new version entirely in D. This implementation makes significant use of templates. I like the templating syntax in D, and in general I find the error messages more comprehensible than the complex error messages I’m used to in C ++. I needed to get down to assembler for some x86 specific instructions, and in D it was easy to do.
Later I needed to work with configuration files. I prefer to write my config files in Lua, a lightweight scripting language that can be easily integrated into a program as an extension through its C API. For this, I found a D Lua binding called DerelictLua. Using, again, D’s metaprogramming tools, I have developed a very simple and practical way to interact with Lua through DerelictLua. Editor’s note: DerelictLua has been deprecated since then; new projects should use it successor, bindbc-lua…
The Bats exchange input processor works with 31 parallel channels, so it is more efficient to use multithreading. For this, I decided not to use the multithreading facilities provided by Phobos. I felt like I needed more control in such a low latency environment, especially the ability to bind each thread to a specific core. I preferred to use the pthreads library and its work with affinity. Due to the C ABI compatibility in D, it was very straight forward.
I work on FreeBSD. For my communication needs, I use kernel functions for queues and sockets. The same functionality is available on macOS, my preferred development platform. D didn’t stop me from using these APIs on macOS or FreeBSD. It was as easy as using the C queue kernel functions.
A few notes on issues and limitations:
I ran into a compiler error once. I found a workaround so it didn’t become a blocking factor. I was able to reproduce it with a few lines of code and contacted community D. They solved the problem and made a fix to a later version of the compiler.
I have not used a garbage collector (GC) in D. However, this is not an attack on D or its GC. On a low latency system like this, even using malloc and free can get expensive, so I’m not going to risk using a non-deterministic system with unpredictable latency. Instead, I used my library to handle memory allocation / deallocation via free lists, with preallocation of memory. As a consequence, I also gave up on using the D standard library.
I needed to work with fixed-size ASCII strings that do not have a NUL terminator, but are padded with trailing spaces instead. Without the standard library, it was easier for me to work with them in C style using pointers.
I was the only developer on this project, but I completed it successfully in a relatively short time. Much credit goes to D for its productivity, readability, and ease of modification.
A few explanations from the author from the comments (ed.):
Neither IDE nor debugger was used.
I used Sublime Text which had a D plugin for indentation and syntax highlighting.
Used terminal and build system DUB and dmd and ldc2 as compilers.
For this kind of applications with a huge amount of data and multithreading, a debugger can be useful, but most often problems can be found using logs.
In D, generating logs is very easy, just use writeln and a structure and everything works. In C ++, you need to write a function like dump () by hand.
From time to time I tried using lldb as a debugger, but I used it infrequently, only occasionally.
No database as no databases are suitable for this type of low latency application.
All the required databases are created in place and are in memory, mostly hash tables.
There is only asynchronous archiving of messages between OMS and the exchange, just in case something goes wrong, we can create the required system state and continue working.