Request Management#

Order actions are requests to change the state of an order. Each such request is identified and managed by an increasing version number. The gateways will cache all requests.

FIX#

If an exchange is fully FIX 4.4 compliant, it will support chaining by rewriting ClOrdID through OrigClOrdID. The ExecutionReport or OrderCancelReject messages will then include the requested ClOrdID which can in turn be used to correlate with the cached request.

However, even for exchanges offering FIX 4.4 connectivity, there are some complications that requires the use of heuristics to match with response a request

  • The OrderCancelReject may not contain a unique request id because ClOrdID can not be rewritten.

  • The BusinessMessageReject message is sometimes used (instead of ExecutionReport or OrderCanceReject), typically when certain order attributes are unsupported by the exchange. This message does not even have a ClOrdID and the only solution is then to cache request history by message sequence number.

REST / WebSocket#

Some exchanges offer a REST service for order actions and a WebSocket service to push order updates. This design introduces an inherent race condition between the two connections.

Request matching is required when an order update arrives from WebSocket before the matching response arrives from REST.

We are in luck if the exchange supports chaining (rewriting ClOrdID through OrigClOrdID).

Otherwise the only choice is to match on order attributes:

  • Has the order status changed to canceled? Then it’s probably an update correlating with a cancel request.

  • Has the limit price or order quantity changed? Then it’s probably an update correlating with a modify request.

  • Any update should match if there is a create order request.

Matching#

This is the situation

  • Having a request version or request id is the ideal situation, then we can match exactly.

  • For other cases, heuristics must be used to match a response or an order update to an outstanding request.

And we have these constraints

  • Correct time-ordering must be guaranteed, i.e. OrderAck must always precede OrderUpdate.

  • Duplication of OrderAck is not be allowed.

For heuristics, the logic includes

  • The first matching request wins, the assumption is that the exchange will not conflate requests.

  • It is possible to skip request version, the assumption is that requests can be lost.

  • If the order status is new, the request type must be create.

  • If the order status is canceled, the request type must be cancel.

  • There can be no matching on quantity or price when the requst status rejected.

  • If the order status is working and the request type could be create or modify, then the quantity and price must match the request.

Versioning#

Response and Updates#

The OrderAck message contains the version number of the requst.

The OrderUpdate message contains different version numbers useful for tracking outstanding requests as well as rejects.

  • max_request_version is the version number of the last received request.

  • max_response_version is the version number of the last received response (possibly matched through heuristics).

  • max_accepted_version is the version number of the last received response with a positively accepted status (i.e. not rejected and not failed due to network or timeout).

The implications

  • max_request_version > max_response_version means there are outstanding requests.

  • max_response_version > max_accepted_version means some requests may have been rejected.

Tracking rejects is very important for chaining.

Order Actions#

Only ModifyOrder and CancelOrder allows you to specify a version (CreateOrder implicitly use version 1).

The next available version number is automatically assigned if you do not specify a version number.

The validity of the version number is verified if you do specify a version number.

You can optionally specify a conditional_on_version for ModifyOrder and CancelOrder. This can be used by the gateway to shortcut certain scenarios: the gateway is allowed to auto-reject this request if it has seen a reject for the conditional_on_version request. The reason for having this option is to deal with a race condition and possibly better support FIX chaining.

Chaining#

Some protocols will allow pipelining and implicitly expect the exchange to deal with rejects in a consistent manner.

For example, a client sends two order modification requests. The second request is sent before having received a response for the first request.

Let’s assume the first request is rejected, then the question is what has to happen with the second request?

For example, FIX expects the second request to be auto-rejected because ClOrdID / OrigClOrdID chaining states the the previous request must have succeeded for this request to succeed.

This may or may not be supported by the exchange and a best-effort approach is therefore all that can be done! (See above comment around conditional_on_version, for example.)

If supported, the gateway must also remember to reset OrigClOrdID whenever a reject is received.

Assumptions#

  • It is not possible to guarantee correct FIX 4.4 chaining if the exchange does not support ClOrdID / OrigClOrdID.

  • Requests must be cached by FIX message sequence number, if the exchange uses the FIX BusinessMessageReject.

  • Heuristics is greedy and will try to match an update or a response to an outstanding request.

  • Heuristics can fail for some scenarios, e.g. trying to modify an order quantity or a limit price to the same values.