Choose a matching model: FIFO, pro-rata, hybrid¶
flox's queue simulator decides how an incoming trade at a price level gets distributed across resting limit orders. The default is FIFO — the order at the front of the queue eats first. Real venues do not all behave that way.
| Venue family | Real matching | Closest model |
|---|---|---|
| Most spot crypto, US equities | Price-time FIFO | tob / full |
| Options exchanges (CME, Eurex) | Pure pro-rata | pro_rata |
| Some hybrid futures / fee tiers | FIFO top-N, pro-rata | pro_rata_with_fifo |
| CME Globex options (TOP-PRO-LMM) | Top fixed share + pro-rata tail | top_pro_lmm |
| ICE options size-pro-rata | Pure pro-rata weighted by priority | pro_rata_with_priority |
A pro-rata venue splits the trade across every resting order at the level, weighted by order size. The front of the queue carries no advantage — a 100-lot at the back gets the same proportional share as the 100-lot at the front. Backtesting a market-maker strategy on a pro-rata venue with the FIFO model overstates fills for big orders and understates them for small ones.
pro_rata_with_fifo is the hybrid: the first N orders consume the
trade in FIFO order, and only the remainder is distributed pro-rata
across the rest. Several exchanges use this scheme to reward queue
priority while still preserving size-weighted matching for the bulk
of the book.
Configure¶
The setter is on SimulatedExecutor. Set the model once at
strategy startup; switching mid-run is allowed but only affects
orders submitted after the call.
A worked example (Python):
"""Switch a SimulatedExecutor between FIFO, pure pro-rata, and hybrid matching."""
import flox_py as flox
exec = flox.SimulatedExecutor()
# Pure pro-rata: every order at the level shares the trade by size.
exec.set_queue_model("pro_rata", depth=4)
# Hybrid: first 3 orders consume the trade FIFO, rest split pro-rata.
exec.set_queue_model("pro_rata_with_fifo", depth=4)
exec.set_queue_fifo_top_n(3)
# Back to default FIFO at the top of book.
exec.set_queue_model("tob", depth=1)
print("queue model setters ok")
TOP-PRO-LMM (CME Globex options)¶
The order at the front of the queue receives a fixed share of every incoming trade (capped by its remaining), and the rest of the trade distributes pro-rata across the tail. LMM (Lead Market Maker) orders in the tail carry a bonus multiplier.
exec.set_queue_model("top_pro_lmm", depth=4)
exec.set_top_priority_share(0.40) # TOP gets 40% of each trade
exec.set_lmm_orders([order_id_a, order_id_b])
exec.set_lmm_bonus_multiplier(1.5) # LMM bonus
# Optional per-order multiplier on top of LMM bonus:
exec.set_order_priority_multiplier(order_id_a, 1.25)
If the LMM list is empty, the tail distributes as pure pro-rata weighted by the per-order priority multiplier (default 1.0).
PRO_RATA_WITH_PRIORITY (ICE options)¶
Every order at the level gets an effective weight of
remaining × priorityMultiplier. Used to model ICE-style options
matching where pinned MM agreements carry a static priority
multiplier (e.g. 1.5) on top of raw size.
What the simulator guarantees¶
- Pro-rata distribution is rounded down to the nearest raw unit, so the sum of fills never exceeds the trade quantity.
- A trade larger than the level total fills only the level total — no overshoot.
- An empty
fifoTopN(zero or larger than the level depth) makespro_rata_with_fifobehave identically to purepro_rata. - The
setFifoTopNvalue persists acrossset_queue_modelcalls; reset it explicitly when switching back to a pure FIFO mode.
When the model matters¶
Match the model to the venue you intend to trade. A bad choice can push a backtest's hit rate off by 20–40% on the same tape:
- A maker strategy that posts size deep in the book looks profitable on FIFO (it rarely fills) but takes adverse fills on pro-rata.
- A queue-jumping strategy that posts small orders at the front loses most of its edge on pro-rata venues — its priority is worth less.
Treat the matching model as a first-class venue parameter alongside fees, latency, and tick size.