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 becauseClOrdID
can not be rewritten.The
BusinessMessageReject
message is sometimes used (instead ofExecutionReport
orOrderCanceReject
), typically when certain order attributes are unsupported by the exchange. This message does not even have aClOrdID
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 precedeOrderUpdate
.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.