The FIX session layer specification calls for the SendingTime(52) of the FIX engines involved in a FIX session to be synchronized. The specification is not specific but suggests two minutes. However, two minutes is about the same as a calendar month in terms of electronic trading.
What are people using for the tolerance in terms of time difference between your FIX engine and your counterparty’s FIX engine?
Keep in mind that messages can be potentially significantly delayed due to dropped packets and buffering at various places in the IO stack before being processed. If you care about latency you don’t even parse SendingTime.
@rigtorp you can agree with your counterparty to reject messages that have been delayed for a certain time. You can only determine the delay if you synchronise your clocks. If you do not parse SendingTime(52) then you cannot offer such a feature to your counterparty.
Note that the FIX Engine can only reject such messages in general as it is supposed to be unaware of the business logic. For example, the session layer should not be configured to reject only delayed order handling messages. That functionality should be left to the application layer using TransactTime(60) instead.
1 Like
Synchronization should be done using NTP, PTP, PPS, White Rabbit etc.
In the context of electonic trading you never ever want to reject any messages, it would be super dangerous in cases like for example the flash crash. The algo needs to take into account market data and order entry delays and adjust quoting widths and hedging strategy accordingly. It would be useful to have a optional “AcceptDeadline” tag on new order so that client can control on a per order basis what the exchange should do with delayed orders, but that is partially available already with “do not cross” handling instructions.
When using FIX tag-value encoding it’s too expensive to parse the timestamps so they are usually ignored client side, only exchange side uses them (there are of course tricks to speed up the parsing, but it’s not valuable enough to usually bother). That applies to both software and FPGA. This is of course solved by using SBE or the proprietary binary protocols.
Even aside from the tag value timestamp parsing problem, the cost of retrieving system time for every message is significant. FIXP does not use sending time (or any other modification of application messages) for this reason.
Actually you get the local time stamp for free by NIC hardware timestamping.
I don’t see SendingTime as very useful. A transaction generating client needs to be able to provide backpressure when TCP buffers are full and/or number of outstanding requests are too large. Having the exchange reject delayed messages at session layer doesn’t seem useful and in fact seems quite dangerous. For exchange to client messages the point is moot, exchange needs to buffer messages for the duration of the session.
There is already a tag for an “AcceptDeadline”, i.e. TimeInForce=6 (GTD) and ExpireTime(126) set to the desired value. UTCTimestamp can go down to any level of precision.
There is a use case from an exchange perspective to reject messages on the session layer. This is about a throttle mechanism to protect the exchange gateways and matching engines from rogue applications. FIX added support for this with EP116 (https://www.fixtrading.org/packages/ep116/). It allows to define rules for a throttle to kick in (e.g. inbound rate, outstanding requests) and actions to take when it does (e.g. queue, reject). It can be limited to specific FIX message types. See ThrottleParamsGrp component for further details. Order handling messages provide ThrottleInst(1685) allowing the submitter of an order to control what should happen to an individual order if it becomes subject to throttling. Hence throttling spans both session and application layer.
I meant “AcceptDeadline” as a way to prevent a DAY/GTC order from hitting the book if the book had substantially changed. Post only instruction is good enough.
Yes providing back pressure throughout the system is very important. If back pressure through maximum queue depth and/or throttles are implemented I don’t see the need for SendingTime based rejections.