ClOrdID

Imported from previous forum

[ original email was from jim whitehead - jwhitehead@latentzero.com ]
One things that i’ve seen come a couple of times is concern raised over the length of ClOrdIDs, my understanding has always been that the FPL spec has never a detailed a size limit but does enforce requirement for uniqueness.

Apart from some systems having a hardcoded limit is anyone aware of any performance impacts coming from ‘large’ ClOrdIDs?

[ original email was from John Prewett - jprewett@lavatrading.com ]
> One things that i’ve seen come a couple of times is concern raised over

the length of ClOrdIDs, my understanding has always been that the FPL
spec has never a detailed a size limit but does enforce requirement for
uniqueness.

Apart from some systems having a hardcoded limit is anyone aware of any
performance impacts coming from ‘large’ ClOrdIDs?

Hi Jim,

I like this question and many things follow on from it from a performance perspective. I think this is certainly a topic that should be added to the white paper (thanks).

Several issues arise from large ClOrdIDs from a performance perspective:

  1. When you receive an order-related request, you should(must?) validate that the ClOrdID being used has not been used before. This would require a comparison of the submitted ClOrdID against the collection of previously submitted ClOrdIDs. The longer the ClOrdID, the slower the comparison.

  2. When you receive a CancelRequest, StatusRequest or CancelRreplaceRequest, you have to compare the submitted OrigClOrdID with a collection of ClOrdIDs to find the one being referenced. Similar situation to #1. The longer the ClOrdID, the slower the comparison.

  3. The larger the ClOrdIDs are, the more memory is consumed by the collection of ClOrdIDs. Now this does assume you are holding your collection in memory. If you aren’t, you have a very simple performance improvement that can be made.

  4. One of the ways to allow for almost limitless ClOrdID lengths is to use a string class to encapsulate the data. This is a very simple implementation which has a performance downside as many string class implementations require a heap allocation to allocate string data space. If you put a (fairly liberal) maximum ClOrdID length, you can avoid unnecessary (expensive) heap allocations. Here at Lava, we specify that submitters must limit their ClOrdIDs to 40 characters. We feel this is a reasonable compromise between performance and flexibility.

There are many optimizations that can be made to your collections of ClOrdIDs.

Some implementations only maintain a collection of “active” ClOrdIDs. This helps reduce collection memory. Depending on the collection technology, reducing the number of items in the collection can also speed the lookup. The cost of this is removing an item when is becomes no longer active. This implementation decision has few downsides. A submitter can “get away with” a duplicate ClOrdID provided that it uniquely identifies an active order. The only issue that arises is if the submitter intended the request against an inactive order instead of an active one, both of which happened to use the same ClOrdID. This could be more of an issue where the submitter wants to increase the OrderQty on an inactive order, which is legal in FIX terms. Also an OrderStatusRequest becomes somewhat ambiguous.

Some implementations place the onus of ClOrdID uniqueness completely upon the submitter. Anomalies that arise as a result of submitting duplicate ClOrdIDs are the risk that is taken. Personally, I believe this approach for order processing is difficult to justify as many other things are validated, why not this one?

The most extreme limitation we have to deal with one venue that limits the ClOrdID to 7 characters. I feel this overly restrictive and put other performance burdens upon the submitter.

A further topic that arises from all this is creation of unique ClOrdIDs from the perspective of the submitter. You may have multiple processes or threads sharing a single session. How do you allocate unique ClOrdIDs in an efficient manner?

At Lava, we tend to use simple numeric ClOrdIDs. Each process or thread that shares a FIX session uses a numeric allocator. We tend to define numeric ranges for each thread prior to session startup so that there is no possible overlap. It is difficult to have multiple allocators, each with sufficient range to handle their possible requirements when the venue enforces the ClOrdID to be 7 characters. For multiple threads sharing one numeric allocator, you might want to think of some type of “lock free” implementation instead of putting as mutex or exclusive lock around the numeric allocator. So the performance of the ClOrdID allocator becomes important when it must be shared between multiple processes or threads.

Thanks.

JohnP

We also use a numeric ClOrdID. Further more, we use a Base64 like encoding method to further reduce the length of the ClOrdID.

private const string QWBase64 = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”;
public static string PackNumber(int number)
{
if (number < 0)
throw new ArgumentException(“Input number must be non-negative.”);
StringBuilder sb = new StringBuilder();
while (true)
{
int curIndex = number % 64;
sb.Append(QWBase64[curIndex]);
number /= 64;
if (number == 0)
break;
}
return sb.ToString();
}

public static int UnpackNumber(string s)
{
int buffer = 0;
for (int i = s.Length - 1; i >= 0; i–)
{
buffer *= 64;
int curIndex;
char c = s[i];
if (c >= ‘A’ && c <= ‘Z’)
curIndex = c - ‘A’;
else if (c >= ‘a’ && c <= ‘z’)
curIndex = c - ‘a’ + 26;
else if (c >= ‘0’ && c <= ‘9’)
curIndex = c - ‘0’ + 52;
else if (c == ‘+’)
curIndex = 62;
else if (c == ‘/’)
curIndex = 63;
else
throw new FormatException(“FIXOrderManagerUtility.UnpackNumber”);
buffer += curIndex;
}
return buffer;
}

One things that i’ve seen come a couple of times is concern raised
over the length of ClOrdIDs, my understanding has always been that the
FPL spec has never a detailed a size limit but does enforce
requirement for uniqueness.

Apart from some systems having a hardcoded limit is anyone aware of
any performance impacts coming from ‘large’ ClOrdIDs?

Hi Jim,

I like this question and many things follow on from it from a
performance perspective. I think this is certainly a topic that should
be added to the white paper (thanks).

Several issues arise from large ClOrdIDs from a performance perspective:

  1. When you receive an order-related request, you should(must?)
    validate that the ClOrdID being used has not been used before. This
    would require a comparison of the submitted ClOrdID against the
    collection of previously submitted ClOrdIDs. The longer the ClOrdID,
    the slower the comparison.

  2. When you receive a CancelRequest, StatusRequest or
    CancelRreplaceRequest, you have to compare the submitted OrigClOrdID
    with a collection of ClOrdIDs to find the one being referenced.
    Similar situation to #1. The longer the ClOrdID, the slower the
    comparison.

  3. The larger the ClOrdIDs are, the more memory is consumed by the
    collection of ClOrdIDs. Now this does assume you are holding your
    collection in memory. If you aren’t, you have a very simple
    performance improvement that can be made.

  4. One of the ways to allow for almost limitless ClOrdID lengths is to
    use a string class to encapsulate the data. This is a very simple
    implementation which has a performance downside as many string class
    implementations require a heap allocation to allocate string data space.
    If you put a (fairly liberal) maximum ClOrdID length, you can avoid
    unnecessary (expensive) heap allocations. Here at Lava, we specify that
    submitters must limit their ClOrdIDs to 40 characters. We feel this is a
    reasonable compromise between performance and flexibility.

There are many optimizations that can be made to your collections
of ClOrdIDs.

Some implementations only maintain a collection of “active” ClOrdIDs.
This helps reduce collection memory. Depending on the collection
technology, reducing the number of items in the collection can also
speed the lookup. The cost of this is removing an item when is becomes
no longer active. This implementation decision has few downsides. A
submitter can “get away with” a duplicate ClOrdID provided that it
uniquely identifies an active order. The only issue that arises is if
the submitter intended the request against an inactive order instead of
an active one, both of which happened to use the same ClOrdID. This
could be more of an issue where the submitter wants to increase the
OrderQty on an inactive order, which is legal in FIX terms. Also an
OrderStatusRequest becomes somewhat ambiguous.

Some implementations place the onus of ClOrdID uniqueness completely
upon the submitter. Anomalies that arise as a result of submitting
duplicate ClOrdIDs are the risk that is taken. Personally, I believe
this approach for order processing is difficult to justify as many other
things are validated, why not this one?

The most extreme limitation we have to deal with one venue that limits
the ClOrdID to 7 characters. I feel this overly restrictive and put
other performance burdens upon the submitter.

A further topic that arises from all this is creation of unique ClOrdIDs
from the perspective of the submitter. You may have multiple processes
or threads sharing a single session. How do you allocate unique ClOrdIDs
in an efficient manner?

At Lava, we tend to use simple numeric ClOrdIDs. Each process or thread
that shares a FIX session uses a numeric allocator. We tend to define
numeric ranges for each thread prior to session startup so that there is
no possible overlap. It is difficult to have multiple allocators, each
with sufficient range to handle their possible requirements when the
venue enforces the ClOrdID to be 7 characters. For multiple threads
sharing one numeric allocator, you might want to think of some type of
“lock free” implementation instead of putting as mutex or exclusive lock
around the numeric allocator. So the performance of the ClOrdID
allocator becomes important when it must be shared between multiple
processes or threads.

Thanks.

JohnP

Also, in our FIX Order Gateway, we use the MsgSeqNum of the incoming order message to generate the ClOrdID of the down stream order. In that case it is extremely easy to perform a reverse translation of ClOrdID from the down stream execution report.

We also use a numeric ClOrdID. Further more, we use a Base64 like
encoding method to further reduce the length of the ClOrdID.

private const string QWBase64 =
“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”;
public static string PackNumber(int number) { if (number < 0) throw new
ArgumentException(“Input number must be non-negative.”); StringBuilder
sb = new StringBuilder(); while (true) { int curIndex = number % 64;
sb.Append(QWBase64[curIndex]); number /= 64; if (number == 0) break; }
return sb.ToString(); }

public static int UnpackNumber(string s) { int buffer = 0; for (int i =
s.Length - 1; i >= 0; i–) { buffer *= 64; int curIndex; char c = s[i];
if (c >= ‘A’ && c <= ‘Z’) curIndex = c - ‘A’; else if (c >= ‘a’ && c <=
‘z’) curIndex = c - ‘a’ + 26; else if (c >= ‘0’ && c <= ‘9’) curIndex =
c - ‘0’ + 52; else if (c == ‘+’) curIndex = 62; else if (c == ‘/’)
curIndex = 63; else throw new
FormatException(“FIXOrderManagerUtility.UnpackNumber”); buffer +=
curIndex; } return buffer; }

One things that i’ve seen come a couple of times is concern raised
over the length of ClOrdIDs, my understanding has always been that
the FPL spec has never a detailed a size limit but does enforce
requirement for uniqueness.

Apart from some systems having a hardcoded limit is anyone aware of
any performance impacts coming from ‘large’ ClOrdIDs?

Hi Jim,

I like this question and many things follow on from it from a
performance perspective. I think this is certainly a topic that should
be added to the white paper (thanks).

Several issues arise from large ClOrdIDs from a performance
perspective:

  1. When you receive an order-related request, you should(must?)
    validate that the ClOrdID being used has not been used before.
    This would require a comparison of the submitted ClOrdID against
    the collection of previously submitted ClOrdIDs. The longer the
    ClOrdID, the slower the comparison.

  2. When you receive a CancelRequest, StatusRequest or
    CancelRreplaceRequest, you have to compare the submitted
    OrigClOrdID with a collection of ClOrdIDs to find the one being
    referenced. Similar situation to #1. The longer the ClOrdID, the
    slower the comparison.

  3. The larger the ClOrdIDs are, the more memory is consumed by the
    collection of ClOrdIDs. Now this does assume you are holding your
    collection in memory. If you aren’t, you have a very simple
    performance improvement that can be made.

  4. One of the ways to allow for almost limitless ClOrdID lengths is to
    use a string class to encapsulate the data. This is a very simple
    implementation which has a performance downside as many string
    class implementations require a heap allocation to allocate string
    data space. If you put a (fairly liberal) maximum ClOrdID length,
    you can avoid unnecessary (expensive) heap allocations. Here at
    Lava, we specify that submitters must limit their ClOrdIDs to 40
    characters. We feel this is a reasonable compromise between
    performance and flexibility.

There are many optimizations that can be made to your collections of
ClOrdIDs.

Some implementations only maintain a collection of “active” ClOrdIDs.
This helps reduce collection memory. Depending on the collection
technology, reducing the number of items in the collection can also
speed the lookup. The cost of this is removing an item when is becomes
no longer active. This implementation decision has few downsides. A
submitter can “get away with” a duplicate ClOrdID provided that it
uniquely identifies an active order. The only issue that arises is if
the submitter intended the request against an inactive order instead
of an active one, both of which happened to use the same ClOrdID. This
could be more of an issue where the submitter wants to increase the
OrderQty on an inactive order, which is legal in FIX terms. Also an
OrderStatusRequest becomes somewhat ambiguous.

Some implementations place the onus of ClOrdID uniqueness completely
upon the submitter. Anomalies that arise as a result of submitting
duplicate ClOrdIDs are the risk that is taken. Personally, I believe
this approach for order processing is difficult to justify as many
other things are validated, why not this one?

The most extreme limitation we have to deal with one venue that limits
the ClOrdID to 7 characters. I feel this overly restrictive and put
other performance burdens upon the submitter.

A further topic that arises from all this is creation of unique
ClOrdIDs from the perspective of the submitter. You may have multiple
processes or threads sharing a single session. How do you allocate
unique ClOrdIDs in an efficient manner?

At Lava, we tend to use simple numeric ClOrdIDs. Each process or
thread that shares a FIX session uses a numeric allocator. We tend to
define numeric ranges for each thread prior to session startup so that
there is no possible overlap. It is difficult to have multiple
allocators, each with sufficient range to handle their possible
requirements when the venue enforces the ClOrdID to be 7 characters.
For multiple threads sharing one numeric allocator, you might want to
think of some type of “lock free” implementation instead of putting as
mutex or exclusive lock around the numeric allocator. So the
performance of the ClOrdID allocator becomes important when it must be
shared between multiple processes or threads.

Thanks.

JohnP

The method I use is to find unique IDs for Orders (37) is

SenderCompID + “-” + ClOrdID

or

SenderCompID + “-” + SenderSubID + “-” + ClOrdID

depending on connection

This is what I use as Orders database table key.

Also, in our FIX Order Gateway, we use the MsgSeqNum of the incoming
order message to generate the ClOrdID of the down stream order. In that
case it is extremely easy to perform a reverse translation of ClOrdID
from the down stream execution report.

We also use a numeric ClOrdID. Further more, we use a Base64 like
encoding method to further reduce the length of the ClOrdID.

private const string QWBase64 =
“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”;
public static string PackNumber(int number) { if (number < 0) throw
new ArgumentException(“Input number must be non-negative.”);
StringBuilder sb = new StringBuilder(); while (true) { int curIndex =
number % 64; sb.Append(QWBase64[curIndex]); number /= 64; if (number
== 0) break; } return sb.ToString(); }

public static int UnpackNumber(string s) { int buffer = 0; for
(int i =
s.Length - 1; i >= 0; i–) { buffer *= 64; int curIndex; char c =
s[i]; if (c >= ‘A’ && c <= ‘Z’) curIndex = c - ‘A’; else if (c >=
‘a’ && c <= ‘z’) curIndex = c - ‘a’ + 26; else if (c >= ‘0’ && c <=
‘9’) curIndex = c - ‘0’ + 52; else if (c == ‘+’) curIndex = 62; else
if (c == ‘/’) curIndex = 63; else throw new
FormatException(“FIXOrderManagerUtility.UnpackNumber”); buffer +=
curIndex; } return buffer; }

One things that i’ve seen come a couple of times is concern raised
over the length of ClOrdIDs, my understanding has always been that
the FPL spec has never a detailed a size limit but does enforce
requirement for uniqueness.

Apart from some systems having a hardcoded limit is anyone aware
of any performance impacts coming from ‘large’ ClOrdIDs?

Hi Jim,

I like this question and many things follow on from it from a
performance perspective. I think this is certainly a topic that
should be added to the white paper (thanks).

Several issues arise from large ClOrdIDs from a performance
perspective:

  1. When you receive an order-related request, you should(must?)
    validate that the ClOrdID being used has not been used before.
    This would require a comparison of the submitted ClOrdID against
    the collection of previously submitted ClOrdIDs. The longer the
    ClOrdID, the slower the comparison.

  2. When you receive a CancelRequest, StatusRequest or
    CancelRreplaceRequest, you have to compare the submitted
    OrigClOrdID with a collection of ClOrdIDs to find the one being
    referenced. Similar situation to #1. The longer the ClOrdID, the
    slower the comparison.

  3. The larger the ClOrdIDs are, the more memory is consumed by the
    collection of ClOrdIDs. Now this does assume you are holding
    your collection in memory. If you aren’t, you have a very simple
    performance improvement that can be made.

  4. One of the ways to allow for almost limitless ClOrdID lengths is
    to use a string class to encapsulate the data. This is a very
    simple implementation which has a performance downside as many
    string class implementations require a heap allocation to
    allocate string data space. If you put a (fairly liberal) maximum
    ClOrdID length, you can avoid unnecessary (expensive) heap
    allocations. Here at Lava, we specify that submitters must limit
    their ClOrdIDs to 40 characters. We feel this is a reasonable
    compromise between performance and flexibility.

There are many optimizations that can be made to your collections of
ClOrdIDs.

Some implementations only maintain a collection of “active”
ClOrdIDs. This helps reduce collection memory. Depending on the
collection technology, reducing the number of items in the
collection can also speed the lookup. The cost of this is removing
an item when is becomes no longer active. This implementation
decision has few downsides. A submitter can “get away with” a
duplicate ClOrdID provided that it uniquely identifies an active
order. The only issue that arises is if the submitter intended the
request against an inactive order instead of an active one, both of
which happened to use the same ClOrdID. This could be more of an
issue where the submitter wants to increase the OrderQty on an
inactive order, which is legal in FIX terms. Also an
OrderStatusRequest becomes somewhat ambiguous.

Some implementations place the onus of ClOrdID uniqueness completely
upon the submitter. Anomalies that arise as a result of submitting
duplicate ClOrdIDs are the risk that is taken. Personally, I believe
this approach for order processing is difficult to justify as many
other things are validated, why not this one?

The most extreme limitation we have to deal with one venue that
limits the ClOrdID to 7 characters. I feel this overly restrictive
and put other performance burdens upon the submitter.

A further topic that arises from all this is creation of unique
ClOrdIDs from the perspective of the submitter. You may have
multiple processes or threads sharing a single session. How do you
allocate unique ClOrdIDs in an efficient manner?

At Lava, we tend to use simple numeric ClOrdIDs. Each process or
thread that shares a FIX session uses a numeric allocator. We tend
to define numeric ranges for each thread prior to session startup so
that there is no possible overlap. It is difficult to have multiple
allocators, each with sufficient range to handle their possible
requirements when the venue enforces the ClOrdID to be 7 characters.
For multiple threads sharing one numeric allocator, you might want
to think of some type of “lock free” implementation instead of
putting as mutex or exclusive lock around the numeric allocator. So
the performance of the ClOrdID allocator becomes important when it
must be shared between multiple processes or threads.

Thanks.

JohnP

I would like to add an aspect relevant in exchange environments to this. The scope of uniqueness is typically smaller than the session or the exchange participant for an exchange to enforce uniqueness when receiving orders. It would create an unnecessary bottleneck to keep track of uniqueness across one of these two criteria. Exchanges maintain separate order books for matching of individual instruments. That is where the order needs to go and that is where uniqueness counts. In terms of performance, you can simply take an optimistic approach and try to add a new order. If you do not get a duplicate key you are fine, otherwise raise an exception. This is much faster than looking up a given ClOrdID value in some separate pool of previously received ClOrdIDs.

Thus, the architecture of your trading system determines the scope of your uniqueness as an exchange. The user can make it unique across all of his orders if that is easier for him, the exchange will typically not require such a global uniqueness across instruments as it achieves better performance with a more local uniqueness.

Regards,
Hanno.

One things that i’ve seen come a couple of times is concern raised
over the length of ClOrdIDs, my understanding has always been that the
FPL spec has never a detailed a size limit but does enforce
requirement for uniqueness.

Apart from some systems having a hardcoded limit is anyone aware of
any performance impacts coming from ‘large’ ClOrdIDs?

Hi Jim,

I like this question and many things follow on from it from a
performance perspective. I think this is certainly a topic that should
be added to the white paper (thanks).

Several issues arise from large ClOrdIDs from a performance perspective:

  1. When you receive an order-related request, you should(must?)
    validate that the ClOrdID being used has not been used before. This
    would require a comparison of the submitted ClOrdID against the
    collection of previously submitted ClOrdIDs. The longer the ClOrdID,
    the slower the comparison.

  2. When you receive a CancelRequest, StatusRequest or
    CancelRreplaceRequest, you have to compare the submitted OrigClOrdID
    with a collection of ClOrdIDs to find the one being referenced.
    Similar situation to #1. The longer the ClOrdID, the slower the
    comparison.

  3. The larger the ClOrdIDs are, the more memory is consumed by the
    collection of ClOrdIDs. Now this does assume you are holding your
    collection in memory. If you aren’t, you have a very simple
    performance improvement that can be made.

  4. One of the ways to allow for almost limitless ClOrdID lengths is to
    use a string class to encapsulate the data. This is a very simple
    implementation which has a performance downside as many string class
    implementations require a heap allocation to allocate string data space.
    If you put a (fairly liberal) maximum ClOrdID length, you can avoid
    unnecessary (expensive) heap allocations. Here at Lava, we specify that
    submitters must limit their ClOrdIDs to 40 characters. We feel this is a
    reasonable compromise between performance and flexibility.

There are many optimizations that can be made to your collections
of ClOrdIDs.

Some implementations only maintain a collection of “active” ClOrdIDs.
This helps reduce collection memory. Depending on the collection
technology, reducing the number of items in the collection can also
speed the lookup. The cost of this is removing an item when is becomes
no longer active. This implementation decision has few downsides. A
submitter can “get away with” a duplicate ClOrdID provided that it
uniquely identifies an active order. The only issue that arises is if
the submitter intended the request against an inactive order instead of
an active one, both of which happened to use the same ClOrdID. This
could be more of an issue where the submitter wants to increase the
OrderQty on an inactive order, which is legal in FIX terms. Also an
OrderStatusRequest becomes somewhat ambiguous.

Some implementations place the onus of ClOrdID uniqueness completely
upon the submitter. Anomalies that arise as a result of submitting
duplicate ClOrdIDs are the risk that is taken. Personally, I believe
this approach for order processing is difficult to justify as many other
things are validated, why not this one?

The most extreme limitation we have to deal with one venue that limits
the ClOrdID to 7 characters. I feel this overly restrictive and put
other performance burdens upon the submitter.

A further topic that arises from all this is creation of unique ClOrdIDs
from the perspective of the submitter. You may have multiple processes
or threads sharing a single session. How do you allocate unique ClOrdIDs
in an efficient manner?

At Lava, we tend to use simple numeric ClOrdIDs. Each process or thread
that shares a FIX session uses a numeric allocator. We tend to define
numeric ranges for each thread prior to session startup so that there is
no possible overlap. It is difficult to have multiple allocators, each
with sufficient range to handle their possible requirements when the
venue enforces the ClOrdID to be 7 characters. For multiple threads
sharing one numeric allocator, you might want to think of some type of
“lock free” implementation instead of putting as mutex or exclusive lock
around the numeric allocator. So the performance of the ClOrdID
allocator becomes important when it must be shared between multiple
processes or threads.

Thanks.

JohnP