Take the 2-minute tour ×
Quantitative Finance Stack Exchange is a question and answer site for finance professionals and academics. It's 100% free, no registration required.

In my firm we are beginning a new OMS (Order Management System) project and there is a debate whether we use Quickfix or we go for a professional fix engine? Because there is a common doubt that QuickFix is not enough fast and obviously we will not get any technical support. I heard that in BOVESPA it has been used for a while. They are changing it with a paid one now. Well that is enough for me. If they use it I can use it.

Should I choose a professional one over QuickFix? Is it not good enough?

share|improve this question
add comment

11 Answers

up vote 14 down vote accepted

In order to answer your question (for you) you would need something to compare to. You would need numbers to know if it is slower/faster, how much, and if it will impact your system overall. Also knowing your performance goals could narrow down the options.

My advice is to take a look at your overall architecture of the sytem you have or intend to build. To just look at QuickFIX is rather meaningless without the whole chain involved in processing information and reacting to it. As an example, say QuickFIX is 100 times faster than some part (in the chain of processing) you have or build. Now, replacing QuickFIX with another part which is 100 times faster than QuickFIX would not change anything because you're still held back by the slowest point. And remember that network hops are usually very expensive compared to in-memory processing of data.

If you for some reason cannot compare different candidates against each other, why not start with e.g. QuickFIX, but make the system in such a way that it can be replaced with something faster later on.

Generally speaking, QuickFIX is not the fastest option, but the key point is that it might not have to be. If performance is very critical and one has resources, you usually end up buying something or building something yourself. Drawbacks here are having resources like time, money and skilled people.

To answer your question better one would need to know other aspects as well, like available resources (money, time, skill), overall system overview, performance expectations and other factors that limit decisions. E.g. if money is not a limiting factor, just find the fastest option and buy it.

share|improve this answer
1  
+1. I like this answer! –  olaker Mar 10 '11 at 13:12
add comment

I work in a big hedge fund and our DMA is entirely based on quickfixj with hundreds of trades a day and thousands of fills.

Quickfixj sits at the end of the OMS connecting to various counterparties and is in use since 2009, I think. Number of orders vary, possibly 150-450 a day, obviously with a lot more fills coming back than that number. Latency from an order entering the OMS to the fix message being sent is perhaps 150ms -- we are not aiming to be low latency at all though.

Using quickfixj is absolutely pain free.

share|improve this answer
    
Welcome to quant.SE! Can you elaborate a bit on your usage of QuickFixJ? How many orders per day? Do you measure order to accept latency? Some informative stats about your usage would be very interesting. –  Louis Marascio Sep 10 '11 at 12:19
1  
Quickfixj sits at the end of the OMS connecting to various counterparties and is in use since 2009, I think. Number of orders vary, possibly 150-450 a day, obviously with a lot more fills coming back than that number. Latency from an order entering the OMS to the fix message being sent is perhaps 150ms -- we are not aiming to be low latency at all though. Using quickfixj is absolutely pain free. –  jk3000 Sep 10 '11 at 15:58
    
Thanks for the additional data! Can you edit you answer and include it there? That way it won't be missed if folks aren't reading comments. I'm out of votes right now, but will up vote you in a few hours. –  Louis Marascio Sep 10 '11 at 16:00
    
Number of orders vary, possibly 150-450 a day. To put things into perspective, a market maker may send 1500--4500 orders per second. –  chrisaycock Sep 10 '11 at 22:53
add comment

How fast do you need? Have you measured round-trip times from the exchange and determined that you need a better solution?

I wouldn't call QuickFix quick; it has a lot of unnecessary overhead (temporary objects, temporary strings, nested functions, etc). But I've used it in projects before without too much trouble.

It is definitely possible to make a much faster FIX engine from scratch. You can use inlined accessors, call writev() instead of concatenating strings, etc. Then there's the standard's requirements, like replaying old FIX messages or handling multiple values per one key. It's a ton of work to do something like that correctly, so you'll need to evaluate just how much pain you're willing to go through.

I haven't used any of the commercial off-the-self engines; hopefully someone else can chime-in with a specific recommendation there. Ideally the cost of that will be a fraction of doing it in-house.

share|improve this answer
1  
Care to elaborate on "But I've used it in projects before without too much trouble."? I'm also curious on what optimization level you had the compiler at whilst using QuickFix. –  bruce.banner Feb 19 '11 at 13:53
add comment

Forget about BOVESPA nobody in Brazil is really doing anything that relies on speed and stability. I can say that from my personal experience. I would say that depending on your demands QuickFIX can be as good as FIX.

share|improve this answer
add comment

Quickfix derivative with a large number of optimizations, much faster than the current release, especially for short messages. Includes sample application that measures latency over the loopback interface.

https://github.com/akorobka/quickfix/tree/quickerfix

Summary of the improvements

There are several things that have an adverse impact on the performance of the current reference implementation.

Most of them have to do with a large amount of redundant object copying, implicit type conversions and small block memory allocations. These changes try to reduce these as much as possible through a redesign of the field object, use of more efficient field containers (Boost, Google Sparsehash) with a custom pool allocator, and streamlined Tx/Rx pipelines.

Other changes are basically brute force optimizations using more efficient serialization/deserialization code, each contributing 0-20% to the total speedup.

Extensions

Each field type defines a nested Pack type that can be used for in-place field construction when adding a field to the message,

msg.setField( FIX::ClOrdID::Pack( "4" ) );

Double field constructors get an optional bool argument that specifies whether the value should be rounded.

msg.setField( FIX::DoubleField( field, value, precision, true ) );
msg.setField( FIX::Price( value, precision, true ) );
msg.setField( FIX::Price::Pack( value, precision, true ) );

share|improve this answer
    
Thanks, I like it. Did you make use of move semantics of C++11 ? –  ali_bahoo Nov 7 '13 at 21:01
    
It's still C++03 only. –  Alexander Korobka Nov 20 '13 at 19:07
add comment

Bovespa is starting to release the new trade platform; take a look for yourself.

The BM&FBOVESPA PUMA Trading System will incorporate all of the functionalities that currently exist in the BM&FBOVESPA trading systems. Its trading speed will be less than a millisecond. In addition, the new platform will allow trading on the following markets: equities in the cash market, futures, options on futures and on actuals, spot US dollar, federal government bonds, private fixed-income securities, and spot commodities.

IMHO, quickfix needs to be patched/improved in order to handle such latency. (:

share|improve this answer
add comment

We use internally optimized version of Quickfix. It gives us ~30 microsecond latency. Commercial products, like Onix or RapidAdvantage FIX will give you twice less.

share|improve this answer
    
ty for numbers! –  user5462 Jun 4 '13 at 2:50
add comment

Compared to commercial offerings, Quickfix isn't that bad - considering you can pay $10000's for the very best ULL engines.

I have conducted side by side testing of Quickfix and Fix8 measuring encode/decode latency for NewOrderSingle(D) messages, see here.

share|improve this answer
    
I noticed a typo in your tables. "Average µs/msg" should read "Average s/msg". –  kristine Jan 29 '13 at 10:41
    
Thanks for spotting that. –  dakka Jan 29 '13 at 11:58
    
You're welcome. Thank you very much for compiling those results. –  kristine Jan 29 '13 at 12:13
add comment

Most of the answers here are pretty correct. However, when talking about performance we use to forget the foundation of all this: The programmin language and platform.

I will summarize it like this: Need high-performance? Go for C (C++ in this case, since there is no pure C version of QuickFix). Choosing QuickFixJ, QuickFix .NET or any other implementation won't never be as fast as a pure C implementation of the FIX Protocol.

I am working on it by the way, and surprised that nobody did before (mainly for the HFT business)

Happy New Year!

share|improve this answer
    
absolutely agree, I'd say, if you want to make ultra low latency solution forget about design rules. Code should be very straightforward. And C is a better solution for this. E.g. just for comparison: I have a FIX parser written in C with some tricks in memory management and it takes about 1 microsecond for parsing-checking-encoding back for 1 ExecutionReport message. QuickFIX solution do only encoding for > 10 microseconds. –  dmitryme Feb 15 at 14:55
add comment

I have not tested QuickFIX performance but I thought I'd share performance numbers from two open source FIX engines I have written.

Libtrading, a FIX engine written in C, has 16 μs round-trip time for NewOrderSingle-ExecutionReport ping-pong test. The test is being run on a 2-way 2.7GHz Sandy Bridge i7 CPU running Fedora 19 with Linux 3.11.6 with both client and server running on the same machine. The numbers include time spent in the Linux TCP/IP stack which is around 5 μs RTT on the machine. This translates to roughly 6 μs overhead per FIX message.

Falcon, an experimental FIX engine written in Java, has 23 μs round-trip time for similar test where the server is actually provided by libtrading. This is around 9 μs per-message overhead which is 50% more than the C FIX engine.

share|improve this answer
add comment

I ran the performance test code included in QuickFix C++ and got the results below. As far as I can tell, this looks excellent. And I am running a commodity home desktop not a high-end trading server used by big shops. The build was done with VS 2012 at full optimization.

G:\projects\quickfix\test\release\pt>pt.exe -p 15000 -c 1000000

Converting integers to strings:

num: 1000000, seconds: 0.016, num_per_second: 6.25e+007

Converting strings to integers:

num: 1000000, seconds: 0, num_per_second: 1.#INF

Converting doubles to strings:

num: 1000000, seconds: 0.5, num_per_second: 2e+006

Converting strings to doubles:

num: 1000000, seconds: 0.219, num_per_second: 4.56621e+006

Creating Heartbeat messages:

num: 1000000, seconds: 0.75, num_per_second: 1.33333e+006

Identifying message types:

num: 1000000, seconds: 0.062, num_per_second: 1.6129e+007

Serializing Heartbeat messages to strings:

num: 1000000, seconds: 0.516, num_per_second: 1.93798e+006

Serializing Heartbeat messages from strings:

num: 1000000, seconds: 1.094, num_per_second: 914077

Creating NewOrderSingle messages:

num: 1000000, seconds: 2.312, num_per_second: 432526

Serializing NewOrderSingle messages to strings:

num: 1000000, seconds: 0.75, num_per_second: 1.33333e+006

Serializing NewOrderSingle messages from strings:

num: 1000000, seconds: 3.188, num_per_second: 313676

Creating QuoteRequest messages:

num: 1000000, seconds: 41.547, num_per_second: 24069.1

Serializing QuoteRequest messages to strings:

num: 1000000, seconds: 3.734, num_per_second: 267809

Serializing QuoteRequest messages from strings:

num: 1000000, seconds: 26.672, num_per_second: 37492.5

Reading fields from QuoteRequest message:

num: 1000000, seconds: 15.89, num_per_second: 62932.7

Storing NewOrderSingle messages:

num: 1000000, seconds: 3.485, num_per_second: 286944

Validating NewOrderSingle messages with no data dictionary:

num: 1000000, seconds: 0.11, num_per_second: 9.09091e+006

Validating NewOrderSingle messages with data dictionary:

G:\projects\quickfix\test\release\pt>

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.