One or more event-logs can be replayed to simulate how a client strategy would behave.

Event Flow#

The simulator allows for user-specified latency expectations, possibly different expectations for market data and order management.

In the above chart, left-to-right, we have a typical flow of events

  • Market data (from exchange)

  • Order action (from strategy)

  • Order ack (from exchange)

  • Market data (from exchange)

  • Order update (from exchange)

However, there is actually no reason to simulate using an artificial “exchange time”. It is trivial to shift the exchange time line to match our receive time. Like this

With the notation

  • L1 = Order Management Latency + Market Data Latency

  • L2 = Order Management Latency - Market Data latency

Working in the space of receive time allows for certain optimizations.


In order to guarantee corret time-ordering, buffers must be used:

The matching engine will multiplex both inbound and outbound queues to guarantee correct time-ordering.


Event-logs are captured by receive time (system clock, monotonic) allowing for an almost identical replay as would have been seen during live trading.


Correct time-ordering is guaranteed when using a single event-log!

However, when multiplexing several event-logs, there is a small possibility for re-ordering (as compared to live trading) due to strategies listening to multiple inbound streams during live trading. Client processing of these streams could happen in a different order than the receive times captured by the gateways.


So why not use a realtime clock?

The reason is that the system clock is monotonic, consistent across CPU cores, and provides a high degree of accuracy. Two features that are very useful when we later want to multiplex several event-logs.

The realtime clock is not very accurate and, worse, is not guaranteed to be monotonic. We may very well observe the realtime clock stalling or even reversing time. In other words, when the realtime clock is being adjusted, it is no longer possible to accurately multiplex several event-logs.

Order Matching#

The default implementation of roq::Matcher supports conservative order matching.

  • Order is filled when the limit price cross the opposite side of the order book. For example, a buy order with a limit price of 10 will be filled if (1) the market best ask is 10, or less, when the order is placed or (2) the market best ask becomes 10, or less, at a later time.