---
title: "Queue-Reactive Models and Large-Tick Assets"
book: "Market Making and High-Frequency Trading"
subject: quant
language: en
chapter: 5
exercises: 8
source: https://one-course.com/books/quant/11/en/chapter/5-queue-reactive-models-and-large-tick-assets
---

# Chapter 5 — Queue-Reactive Models and Large-Tick Assets

On a stock whose spread is one tick nearly all day, every market maker quotes the same two prices. What separates them is where they stand in the queue, and when they leave it. On this chapter’s simulated stock the spread is one tick 96% of the time. A one-lot quoter that always joins the best queues earns 0.03 ticks a share over the ten seconds after its fills; one that joins only the side whose queue is at least 30% of the two, and leaves when that share falls, earns 0.39 on a third of the volume. The same join rule without the exit loses 0.12. Leaving is the part that pays.

## 5.1 The large-tick regime

One Quant Book 10, chapter 6 classifies instruments by their relative tick size: in a *large-tick asset* the spread is almost always one tick and the best queues are long, in a *small-tick asset* the spread spans many ticks and queues are short. The distinction decides what a market maker controls. In a small-tick asset the quote’s distance from the mid is a continuous choice, the depth of chapter 3. In a large-tick asset the price is fixed by the tick grid and the only choices are to be in a best queue or not, and where in it.

Book 7’s simulated stock is large-tick. Over an hour, its spread is one tick 96.3% of the time and the median best queue holds 17 lots of 100 shares. Chapter 3’s exploring quoter found no fill at all a tick behind the best price. Everything a market maker earns there, it earns in the two best queues.

## 5.2 Queue-reactive intensities

**Definition 5.1 (Queue-reactive model).**

A *queue-reactive model* describes each best queue of a book as a birth–death process whose rates depend on the queue’s current size $q$: limit orders join its back at rate $\lambda^L(q)$, cancellations remove resting orders at rate $\lambda^C(q)$, market orders remove orders from its front at rate $\lambda^M(q)$. When a queue empties the price moves by one tick and new queues are drawn from a regeneration distribution.

Huang, Lehalle and Rosenbaum introduced the model on real order-book data: between changes of a reference price the book is a Markov queueing system whose intensities depend only on its current state. It is the birth–death chain of One Quant Book 4, chapter 8, with rates read off the data instead of assumed constant, as in Cont, Stoikov and Talreja’s earlier model.

**Method 5.2 (Estimating the intensities).**

Replay the order-by-order messages. For each message, note the size of each best queue just before it and the time since the previous message; credit that time to the size. Count the lots added to, cancelled from and executed against each best queue at each size. The intensity at size $q$ is the count divided by the time spent at $q$; pool the two sides if the book is symmetric.

[Figure 5.1](#fig-hf-queue-reactive-models-and-large-tick-assets-intensities) shows the estimate on one simulated hour. Cancellations grow with the queue, from 0.34 lots a second at one lot to about 1.5 at ten, because each resting order cancels at its own rate; market orders reach small queues more often than large ones (0.55 a second at two lots, about 0.3 at fifteen). Limit orders arrive at 1.3 to 2.3 lots a second, with no trend in the size.

![Queue-reactive intensities of the best queues of the simulated stock, pooled over bid and ask, by the queue’s size just before each event; one simulated hour. Data: firm.qreactive.estimate on firm.tape.](https://one-course.com/images/onecourse/chapters/quant-11/hf-queue-reactive-models-and-large-tick-assets/fig-f2ba362d9501.svg)

***Figure 5.1.** Queue-reactive intensities of the best queues of the simulated stock, pooled over bid and ask, by the queue’s size just before each event; one simulated hour. Data: `firm.qreactive.estimate` on `firm.tape`.*

## 5.3 The value of a place in the queue

One Quant Book 10, chapter 6 defines the *queue value* of a resting order: what the order is expected to earn from its current place until it is filled or cancelled. Moallemi and Yuan split it into a static part, the spread earned against adverse selection costs that grow with the position in the queue, and a dynamic part, the option to leave later; for some large-tick stocks they found it of the same order as the spread.

The fitted [queue-reactive model](#def-hf-queue-reactive-models-and-large-tick-assets-qr) computes it by simulation. Put one lot of ours in the bid queue with $n$ lots ahead; the bid queue holds $Q^b$ lots in all and the ask queue $Q^a$. Market sells take the bid from the front, cancellations hit the other orders at random, limit orders join the back. The order is filled when a market sell reaches it; it is abandoned, worth zero, if the ask queue empties first (the price moves up, away from it) or after sixty seconds. After a fill the mid is followed for ten seconds, each emptied queue moving it by a tick, and the order is marked there: half a tick plus the mid’s move ([Listing 5.1](#lst-hf-queue-reactive-models-and-large-tick-assets-mc)).

![Value of one lot resting in the bid queue, at its front and at its back, in the fitted queue-reactive model, by the bid queue’s size, for a short and a long ask queue: expected P&L per share marked ten seconds after the fill (zero if not filled within sixty seconds or if the ask queue empties first); 4 000 simulated paths per point. Data: hf_queues.values.](https://one-course.com/images/onecourse/chapters/quant-11/hf-queue-reactive-models-and-large-tick-assets/fig-1abdcc705b89.svg)

***Figure 5.2.** Value of one lot resting in the bid queue, at its front and at its back, in the fitted [queue-reactive model](#def-hf-queue-reactive-models-and-large-tick-assets-qr), by the bid queue’s size, for a short and a long ask queue: expected P&L per share marked ten seconds after the fill (zero if not filled within sixty seconds or if the ask queue empties first); 4 000 simulated paths per point. Data: `hf_queues.values`.*

Three regularities show in [Figure 5.2](#fig-hf-queue-reactive-models-and-large-tick-assets-values). The front is worth more than the back when our queue is long: at ten lots with a short ask queue, 0.60 against 0.32 ticks. When our queue is short and the other long, front and back are worth little and almost the same (0.12 at two lots against twenty): a fill is nearly certain because the queue is about to be eaten, and the price follows. When the other queue is short, a back order risks never being filled, because the price moves away first.

**Remark 5.3 (What the model cannot see).**

Every value in the figure is positive, yet chapter 1’s quoter, always in these queues, lost its spread to adverse selection. The fitted model knows only queue sizes. In the simulated market, as in real ones, some market orders come from traders who know where the efficient price is, and they arrive when the quotes are stale. A [queue-reactive model](#def-hf-queue-reactive-models-and-large-tick-assets-qr) captures the mechanical race for the front; the information in the flow must be measured on one’s own fills, by mark-outs, and added to it (chapter 6).

## 5.4 When to join and when to leave

**Definition 5.4 (Queue-join rule, queue-exit rule).**

A *queue-join rule* decides whether to place an order at the back of a best queue, given the state of the book; a *queue-exit rule* decides whether to cancel an order already resting, given the state of the book and the order’s place in its queue.

The two rules are different decisions: joining forfeits nothing, leaving forfeits the place. The chapter’s rules use one number, the share of our side’s best queue in the two best queues, counting others’ orders only, $s^b=Q^b/(Q^b+Q^a)$ for the bid (and $1-s^b$ for the ask). The model says a side whose share is small is about to be eaten: fills there are nearly certain and followed by an adverse move. A one-lot quoter joins a side only when its share is at least $\theta$; the exit rule then either stays, leaves when the share falls below $\theta$, or leaves unless fewer than two lots are ahead ([Listing 5.2](#lst-hf-queue-reactive-models-and-large-tick-assets-quoter)). On six simulated sessions of twenty minutes:

| rule ($\theta=0.3$) | shares | ten-second mark-out | ten-second edge | P&L (sd) |
| --- | --- | --- | --- | --- |
|  | a session | (ticks a share) | ($ a session) | ($ a session) |
| always join | 11 167 | 0.026 | 2.92 | 5.33 (63.67) |
| join, then stay | 6 900 | $-0.117$ | $-8.08$ | $-32.00$ (68.41) |
| join and leave | 3 400 | 0.392 | 13.33 | $-6.50$ (23.82) |
| join, leave unless at the front | 4 450 | 0.032 | 1.42 | $-26.50$ (63.22) |

The ten-second mark-out, spread capture less the adverse move over ten seconds, is the fill’s edge; times the shares, it is the session’s edge. By that measure the exit rule is what works. Joining on a favourable share and then staying is worse than always joining: the orders that stay are exactly those whose side turned against them, and they are the ones that get filled. Leaving when the share falls quadruples the edge on a third of the volume. Keeping orders near the front, the natural refinement, gives most of the gain back, as the model predicted: when the other side is about to take the queue, being first means being filled first. The P&L column, which also marks the inventory to the end of each session, is too noisy over six sessions to rank the rules.

[Figure 5.3](#fig-hf-queue-reactive-models-and-large-tick-assets-sweep) varies $\theta$ for the join-and-leave rule. The mark-out per share rises with the threshold up to 0.4; the edge per session peaks at 0.3, where the quoter still trades enough.

![The join-and-leave rule on six simulated sessions of twenty minutes: ten-second edge a session and ten-second mark-out per share filled, against the threshold (=0 is always joining). Data: hf_queues.sweep.](https://one-course.com/images/onecourse/chapters/quant-11/hf-queue-reactive-models-and-large-tick-assets/fig-93f13051b6c3.svg)

***Figure 5.3.** The join-and-leave rule on six simulated sessions of twenty minutes: ten-second edge a session and ten-second mark-out per share filled, against the threshold $\theta$ ($\theta=0$ is always joining). Data: `hf_queues.sweep`.*

## 5.5 Tutorial: pricing a place in the queue

**Goal.** Estimate the queue-reactive intensities of a large-tick book, value a place in its queue, and test join and exit rules in the market. **End state:** Figures [5.1](#fig-hf-queue-reactive-models-and-large-tick-assets-intensities), [5.2](#fig-hf-queue-reactive-models-and-large-tick-assets-values) and [5.3](#fig-hf-queue-reactive-models-and-large-tick-assets-sweep) and the table.

1. **Estimate** with `firm.qreactive.estimate(msgs, top, lot, qmax)` on one simulated hour ( [Method 5.2](#met-hf-queue-reactive-models-and-large-tick-assets-estimate) ).
2. **Value the queue** with `order_value`: all states and paths advance together, one event each per step. The bid side’s events are the heart of it. `# bid side events add_b = e == 0 qb[i[add_b]] += 1 behind[i[add_b & wi]] += 1 can = (e == 1 ) & (qb[i] > 0 ) ci = i[can] others = np.maximum(qb[ci] - alive[ci].astype(int ), 1 ) pick_ahead = alive[ci] & (rng.random(len (ci)) * others < ahead[ci]) ahead[ci[pick_ahead]] -= 1 behind[ci[alive[ci] & ~pick_ahead]] = np.maximum(behind[ci[alive[ci] & ~pick_ahead]] - 1 , 0 ) qb[ci] -= 1 mkt = (e == 2 ) & (qb[i] > 0 ) mi = i[mkt] hit_us = alive[mi] & (ahead[mi] == 0 ) ahead[mi[alive[mi] & ~hit_us]] -= 1 qb[mi] -= 1 f = mi[hit_us] alive[f], filled[f], marking[f], tf[f] = False , True , True , t[f]` **Listing 5.1.** Our order in the bid queue: joins behind it, cancellations ahead of it, market orders from the front. code/firm/qreactive/firm_qreactive.py
3. **Rules as a Quoter.** The harness gives the quoter its order’s place in the queue (`ctx.ahead`), as an order-by-order feed would; the quoter reads the others’ queues from `ctx.external`. `def on_market (self , ctx, t, top): x = ctx.external(top) qb, qa = max (int (x[" bid_qty " ]), 0 ), max (int (x[" ask_qty " ]), 0 ) share = {1 : qb / (qb + qa) if qb + qa else 0.5 } share[-1 ] = 1.0 - share[1 ] best = {1 : int (x[" bid " ]), -1 : int (x[" ask " ])} room = {1 : ctx.position < self .limit * LOT, -1 : ctx.position > -self .limit * LOT} want = {s: share[s] >= self .theta and room[s] for s in (1 , -1 )} for cid, w in ctx.working().items(): if w.price != best[w.side] or want[w.side] or not room[w.side]: continue a = ctx.ahead(cid) if self .mode == " stay " or (self .mode == " front " and a is not None and a < self .front * LOT): want[w.side] = True` **Listing 5.2.** Join a side on its share of the best queues; stay, leave, or leave unless at the front. code/hft/05-queue-reactive-models-and-large-tick-assets/python/hf_queues.py
4. **Compare** with `compare()` and `sweep()` on sessions never used for estimation.

**What to change next.** Add the imbalance of the next level; let the threshold depend on the place in the queue, using the model’s value.

## 5.6 Build: the queue-reactive engine

**Purpose.** Queue-reactive intensities from any order-by-order stream, and the value of an order’s place in its queue, for join and exit decisions.

**Interface.** `estimate(msgs, top, lot, qmax, n_open) -> {q, L, C, M, time, regen}`; `QRModel(L, C, M, regen)`; `order_value(model, ahead, same, opp, H, tmax, paths, seed) -> {fill, value, adverse}`; `value_table`. In `firm.mmharness`, `ctx.ahead(cid)` for Quoters that set `wants_queue_position`.

**Rules.** Events are counted in lots, one lot per event. Estimation and evaluation never use the same sessions. Values are per share, in ticks, marked at the mid a fixed horizon after the fill.

**Acceptance tests.** `code/firm/qreactive/tests/`: intensities and time in state by hand on a four-message stream; no fill without market orders; the front fills more often than the back; table shapes. `code/firm/mmharness/tests/`: an order’s place in its queue never moves back.

**Stretch.** Intensities that depend on both queues (the full model); an information term fitted to mark-outs; run on `firm.exchsim`’s feed.

Sources and further reading

- W. Huang, C.-A. Lehalle and M. Rosenbaum, “Simulating and analyzing order book data: the queue-reactive model”, *Journal of the American Statistical Association* 110(509), 2015.
- C. C. Moallemi and K. Yuan, “A model for queue position valuation in a limit order book”, working paper, 2016.
- R. Cont, S. Stoikov and R. Talreja, “A stochastic model for order book dynamics”, *Operations Research* 58(3), 2010.
- K. Dayri and M. Rosenbaum, “Large tick assets: implicit spread and optimal tick size”, *Market Microstructure and Liquidity* 1(1), 2015.

## 5.7 Exercises

**Exercise 5.1 ★.**

A best queue spent 200 seconds at 4 lots; in that time 290 lots were cancelled from it. Estimate $\lambda^C(4)$.

**Solution of Exercise 5.1.**

$290/200=1.45$ lots a second.

**Exercise 5.2 ★.**

The bid queue holds 3 lots of others’ orders and the ask queue 12. What is the bid’s share, and does the chapter’s rule with $\theta=0.3$ join the bid? The ask?

**Solution of Exercise 5.2.**

$s^b=3/15=0.2$: below 0.3, so it does not join the bid; the ask’s share is 0.8, so it joins the ask.

**Exercise 5.3 ★.**

A quoter’s fills earned 0.392 ticks a share after ten seconds on 3 400 shares a session. With a one-cent tick, what is its ten-second edge a session?

**Solution of Exercise 5.3.**

$0.392\times3\,400\times\$0.01=\$13.33$.

**Exercise 5.4 ★★.**

Why can a place at the back of a queue be worth more when the opposite queue is long than when it is short?

**Solution of Exercise 5.4.**

A short opposite queue empties soon, and the price then moves away from the resting order before it is reached: the order is left unfilled. With a long opposite queue the price is unlikely to move away, so even the back is eventually filled.

**Exercise 5.5 ★★.**

Explain why joining on a favourable share and then staying did worse than always joining.

**Solution of Exercise 5.5.**

Joining on a favourable share selects good states only at the moment of joining. Orders that stay are then filled mostly after the share has turned against them, when their queue is being eaten ahead of a price move: the rule keeps precisely the orders whose fills are adverse ($-0.117$ ticks a share against 0.026 for always joining).

**Exercise 5.6 ★★.**

From [Figure 5.3](#fig-hf-queue-reactive-models-and-large-tick-assets-sweep), why does the edge per session peak at a lower threshold than the mark-out per share?

**Solution of Exercise 5.6.**

A higher threshold keeps only the best states, so each fill is better, but it quotes less often and fills fewer shares; the edge per session is the product, which peaks at 0.3 ($13.33) while the mark-out per share peaks at 0.4 (0.484).

**Exercise 5.7 ★★★.**

*Coding.* With the fitted model, compute the value, fill probability and adverse move of one lot at the front of a bid queue of 10 lots when the ask queue holds 2 (`order_value(model(), 0, 10, 2, paths=4000, seed=6)`).

**Solution of Exercise 5.7.**

Fill probability 0.825, value 0.594 ticks a share, adverse move $-0.22$: after its fills the mid moves in its favour on average, because the short ask queue tends to empty and the price to rise.

**Exercise 5.8 ★★★.**

*Find the flaw.* “The [queue-reactive model](#def-hf-queue-reactive-models-and-large-tick-assets-qr) says every place in our queues is worth at least a tenth of a tick, so we should always quote.”

**Solution of Exercise 5.8.**

The model has no informed flow: its only adverse selection is mechanical. The simulated market’s informed traders make fills worse exactly when queues are being eaten, which the model’s values do not include; chapter 1’s quoter, always in the queues, lost its spread. Measure mark-outs of one’s own fills and quote only where they are positive.

## 5.8 Problem: Front of the Line

**Problem 5.1.**

Weekend problem — front of the line

A market maker in a one-tick stock must decide, message by message, which queues to be in.

**Part I — The regime.**

1. What distinguishes a large-tick asset, and what can a market maker control there?
2. Give the simulated stock’s one-tick share and median best queue.
3. Why did chapter 3’s exploring quoter get no fill behind the touch?

**Part II — The model.**

4. Define the [queue-reactive model](#def-hf-queue-reactive-models-and-large-tick-assets-qr) .
5. Describe the estimation and give the fitted intensities’ shapes.
6. Why do cancellations grow with the queue in this market?
7. Describe the simulation that values a place in the queue, and its payoff.

**Part III — The value of a place.**

8. Give the front and back values at 10 lots against 2, and at 2 lots against 20.
9. Why is the front not worth more than the back when our queue is short and the other long?
10. Why are all the model’s values positive, and what does that omit?

**Part IV — Rules in the market.**

11. Define the [queue-join rule](#def-hf-queue-reactive-models-and-large-tick-assets-rules) and the [queue-exit rule](#def-hf-queue-reactive-models-and-large-tick-assets-rules) .
12. State the *named result* : the ten-second mark-out per share of always joining, joining and staying, and joining and leaving, and the value of the front against the back of a ten-lot queue in the model.
13. Why is the P&L column not used to rank the rules?
14. Why did keeping orders at the front give the gain back?
15. Which threshold maximises the edge per session, and why not the mark-out?
16. How many messages does each rule send, compared with always joining, and why?
17. How would you add an information term to the model?
18. What would change on a venue that allocates pro rata?
19. How would the rules behave on a small-tick asset?
20. In one sentence: what matters more in a one-tick book, joining well or leaving well?

**Solution of Problem 5.1.**

1. A spread almost always one tick with long best queues; the market maker controls which queues to be in and when to leave them, not the price.
2. One tick 96.3% of the time; median best queue 17 lots.
3. Market orders here are too small to exhaust a best queue, so the next price is almost never reached.
4. See [Definition 5.1](#def-hf-queue-reactive-models-and-large-tick-assets-qr) .
5. [Method 5.2](#met-hf-queue-reactive-models-and-large-tick-assets-estimate) ; limit orders between 1.3 and 2.3 lots a second with no trend, cancellations rising from 0.34 to about 1.5, market orders falling from 0.55 to about 0.3.
6. Each resting order cancels at its own rate, so a longer queue loses lots faster.
7. One lot in the bid queue with $n$ ahead; joins, cancellations and market orders at the fitted rates; filled when reached, abandoned if the ask empties or after 60 seconds; after a fill, marked at the mid ten seconds later: $0.5$ tick plus the mid’s move.
8. 0.60 (front) and 0.32 (back) at 10 against 2; 0.12 for both at 2 against 20.
9. The queue is about to be eaten: every place is filled, followed by the price move.
10. The model has no informed flow; the information in the flow is omitted.
11. See [Definition 5.4](#def-hf-queue-reactive-models-and-large-tick-assets-rules) .
12. Always joining 0.026, joining and staying $-0.117$ , joining and leaving 0.392 ticks a share; in the model, the front of a ten-lot queue against a two-lot ask is worth 0.60 ticks and the back 0.32.
13. It marks each session’s end inventory, whose moves are large against the rules’ differences over six sessions.
14. When the other side is about to take the queue, the front is filled first and the move follows.
15. 0.3 for the edge per session; the mark-out keeps rising to 0.4 because stricter rules keep better but fewer fills.
16. Always 365, stay 245, leave 468, leave unless at the front 448: leaving means cancelling and rejoining as the book moves.
17. Fit the fills’ mark-out, by state, to the book’s features at the fill and add it to the payoff, or add informed market orders whose rate depends on a hidden efficient price.
18. Under pro-rata allocation the place in the queue does not matter, size does (chapter 15); leaving costs no place.
19. The spread is several ticks, so the choice of price reappears (chapters 3–4) and queues are short; the rules matter less.
20. Leaving well.

## 5.9 Interview questions

**Interview question 5.1 ★ trader.**

You are first in a long bid queue in a one-tick stock. The ask queue has just shrunk to one lot. What do you do?

**Solution of Interview question 5.1.**

The ask is about to empty and the price to move up: a bid at the front will probably be filled well, and the move follows in its favour. Stay; the danger is the reverse, a short bid queue.

*What the interviewer is looking for: reading the other side’s queue, and that the front is not always safe.*

**Interview question 5.2 ★★ researcher.**

How would you estimate how much a place at the front of the queue is worth, from your own data?

**Solution of Interview question 5.2.**

Record each order’s place at every event and its outcome (fill, mark-out at a horizon, or cancellation); estimate the expected mark-out and fill probability by place and by the queues’ sizes, out of sample; the difference between places is the queue value.

*What the interviewer is looking for: outcomes conditioned on place, and selection bias of which orders stay.*

**Interview question 5.3 ★★ researcher.**

Why do fill probability and adverse selection move together along a queue?

**Solution of Interview question 5.3.**

An order far back is reached only when most of the queue has been eaten, which is when the price is about to move through it: higher fill probability late in a queue’s life comes with worse fills.

*What the interviewer is looking for: the conditional nature of late fills.*

**Interview question 5.4 ★★ developer.**

How does a market maker know how many shares are ahead of its order, and what breaks the estimate?

**Solution of Interview question 5.4.**

From an order-by-order feed: at its acknowledgement the order joins behind every order resting at its price; each execution or cancellation of an order ahead moves it forward. Hidden orders, lost or reordered packets and venue-specific priority rules (size changes, replaces) break the count.

*What the interviewer is looking for: order-by-order tracking and its failure modes.*

**Interview question 5.5 ★★ trader.**

A colleague proposes to cancel and re-enter your orders every second to follow the book. What does that cost in a one-tick stock?

**Solution of Interview question 5.5.**

Every cancel and re-entry sends the order to the back of the queue: in a one-tick stock the place is most of the order’s value, so churning gives it away, besides adding messages.

*What the interviewer is looking for: priority lost on replace.*

**Interview question 5.6 ★★★ researcher.**

Each resting order cancels at rate $\nu$ and market orders arrive at rate $\mu$. An order has $n$ orders ahead of it. What is the probability that the next event among those ahead is a market order, and what is the expected time until all $n$ are gone?

**Solution of Interview question 5.6.**

With $k$ ahead the events among them occur at rate $\mu+k\nu$; the next is a market order with probability $\mu/(\mu+n\nu)$. Each event removes one order ahead, so the expected time until none is left is $\sum_{k=1}^n1/(\mu+k\nu)$.

*What the interviewer is looking for: competing exponential clocks and summing the stages.*
