Quantitative Finance · Book 2 · Markets

Markets II: Rates, FX and Credit

Markets II: Rates, FX and Credit · Markets

30Market-Making Games

An interviewer points out of the window: make me a market on the number of windows in that building. You say 200 at 400. She says: I buy. You have just sold her windows at 400, and you have learned something: she thinks there are more than 400, or at least she is willing to bet so. Your next market should be higher. Trading firms train and test people with games like this because every market maker’s problem is in it: estimate a value you cannot see, quote around it wide enough to survive the people who know more, narrow enough to trade with the people who do not, and learn from every trade. This chapter plays the game seriously: how to make a market, how to update on trades, how adverse selection sets the width, and what firms say about the games they use.

30.1 Make me a market

Definition 30.1 (Make-me-a-market, width)

Make-me-a-market is a request to quote, on some uncertain quantity, a bid at which one will buy and an offer at which one will sell, for a stated size, before knowing which way the other party will trade. The width of the market is the offer minus the bid.

The language is that of an open-outcry pit, and Jane Street’s public guide to its trading interviews spells it out: “I’m 2 bid for 10” offers to buy 10 at 2; “I have 10 at 4” offers to sell; “2 at 4, 10 up” does both; the other side says “sold” to hit the bid or “take ’em” to lift the offer, and the order stands until it trades or its maker says “I’m out”. The guide’s advice for a contract paying the roll of a die, worth 3.5 on average, is to buy below and sell above the expected value, to weigh the worst loss against one’s capital, and to balance the chance of trading against the profit per trade; it suggests “3 at 4, 10 up”.

A market has a centre, the maker’s estimate of the value, and a width. The centre is a statistics problem; the width is an economic one. Quote too narrow and anyone who knows the value better trades against you when you are wrong; quote too wide and no one trades. The card game of this chapter makes both precise.

Definition 30.2 (Inventory)

A market maker’s inventory is the net position it holds from the trades done against its quotes, long after net buying and short after net selling.

30.2 Updating on trades

Definition 30.3 (Bayesian update)

A Bayesian update revises a probability distribution over an unknown value after an observation, in proportion to how likely the observation would be under each value: posterior ∝\propto prior ×\times likelihood.

The contract of the chapter’s game pays the sum of five cards dealt face down from a 52-card deck, aces 1 to kings 13. Before any trade the sum is worth 35 on average, with a standard deviation of 8.03, and it lies between 6 and 64 (Figure 30.1). Each round a trader arrives: with probability 0.2 an informed one, who knows the sum and buys if it is above the offer, sells if below the bid, and otherwise passes; otherwise an uninformed one, who trades on a random side with a probability that falls with the width, e−w/8e^{-w/8}, and otherwise passes.

Distribution of the sum of five cards dealt from a 52-card deck, aces counting 1 and kings 13: mean 35 (dashed), standard deviation 8.03, from 6 to 64. Exact, by counting. Data: the chapter’s tutorial.
Figure 30.1. Distribution of the sum of five cards dealt from a 52-card deck, aces counting 1 and kings 13: mean 35 (dashed), standard deviation 8.03, from 6 to 64. Exact, by counting. Data: the chapter’s tutorial.

Example 30.4 (The first trade)

The maker opens 30 at 40, a width of 10. An uninformed trader trades with probability e−10/8=0.29e^{-10/8} = 0.29. If someone buys at 40, it was an informed trader with probability 0.31; the maker’s expected value of the sum rises from 35 to 38.13, and its next market is centred there. After a sale at 30 it falls to 31.87; after a pass it stays at 35, since a pass is equally likely from a high or a low sum.

Over a game the maker’s centre drifts towards the true sum as trades reveal it (Figure 30.2); how fast depends on the share of informed traders and on the width, since a wide market filters out the informed trades that carry the information along with the uninformed ones that pay for the width.

One game at a width of 11.5: the maker’s expected value of the sum before each round, updated by Bayes’ rule after every trade and pass, against the true sum, 31. Early buys push the estimate up; the sales that follow bring it down towards the truth. The maker ends the game with a profit of 18.6. Data: the chapter’s tutorial, seeded.
Figure 30.2. One game at a width of 11.5: the maker’s expected value of the sum before each round, updated by Bayes’ rule after every trade and pass, against the true sum, 31. Early buys push the estimate up; the sales that follow bring it down towards the truth. The maker ends the game with a profit of 18.6. Data: the chapter’s tutorial, seeded.

30.3 Adverse selection around a table

The guide’s definition of adverse selection matches the one in One Quant Book 1, chapter 1: the trades you get to do are worse than they would appear, because someone else is selecting into the trade against you. Its practical form is a question to ask before every quote: conditional on this order being filled, what is the thing worth, and would I still want the trade? Glosten and Milgrom turned it into a model in 1985: a specialist facing informed and uninformed traders sets its bid and offer at the expected value conditional on a sale and on a purchase, and the presence of better-informed traders produces a positive spread even when the specialist is risk-neutral and makes zero expected profit.

Definition 30.5 (Winner’s curse)

The winner’s curse is the tendency of the winner of an auction among bidders with noisy estimates of a common value to have overestimated it: winning is itself evidence that one’s estimate was too high.

A market maker is always the winner of such an auction: its quote was the one someone chose to trade on. The width is the price of the curse, and the best width balances two effects (Figure 30.3). A wider market loses less to the informed, who trade only when the sum lies outside it, but trades less with the uninformed, who pay half the width each time.

Proposition 30.6 (Width against the table)

With no informed traders, the maker’s expected profit per round is w2e−w/λ\tfrac w2 e^{-w/\lambda} with patience λ\lambda, maximised at w=λw = \lambda. Informed traders make every width cost more and the narrowest widths cost most, since they trade only against quotes on the wrong side of the value; learning from trades lowers the loss to them, and so allows a narrower market.

Proof. An uninformed trader trades with probability e−w/λe^{-w/\lambda} and, the centre being the expected value, earns the maker w/2w/2 on average; the product is maximised at w=λw = \lambda. An informed trader’s expected cost to the maker is E[(V−a)++(b−V)+]E[(V - a)^+ + (b - V)^+], which falls as the quotes move apart; a better centre shrinks it for any width. ∎

Example 30.7 (The best width)

Over 2 000 seeded games of 20 rounds with a fifth of the traders informed, the maker who updates earns most, 16.4 per game, at a width of 11.5 points, against 14.1 at 8 points and 15.1 at 15. A maker who never updates does best wider, at 14 points, and earns only 12.0. Without informed traders the best width would be the patience, 8 points, earning about 29 a game (29.4 by the formula, 28.6 in the simulation).

The maker’s expected P&L per game of 20 rounds against the width of its market, for tables with 10, 20 and 30% informed traders, updating by Bayes’ rule, and for 20% without updating (dashed). Narrow markets are picked off; wide ones do not trade; the best width rises, and the profit falls, with the share of informed traders. 600 seeded games per point. Data: the chapter’s tutorial.
Figure 30.3. The maker’s expected P&L per game of 20 rounds against the width of its market, for tables with 10, 20 and 30% informed traders, updating by Bayes’ rule, and for 20% without updating (dashed). Narrow markets are picked off; wide ones do not trade; the best width rises, and the profit falls, with the share of informed traders. 600 seeded games per point. Data: the chapter’s tutorial.

30.4 The training games firms describe

Firms rarely publish their games, but some describe them. Jane Street’s guide sets practice markets: on the roll of a twenty-sided die, the maximum of three six-sided dice, a die with the option to reroll once, the temperature in an hour, and a million times a die roll, with the question of how one would feel if one’s bid were hit and the roll came up one. Its trading internship lists mock trading, in teams, on scenarios built by its traders, and classes that range from financial products to poker. The common thread is the chapter’s: the value is uncertain, the other players know different things, and every trade is information.

The games also teach inventory. A maker who has sold three times in a row is short, and if its sales were to informed traders the value is above where it sold. Shifting both quotes up, or skewing them, protects it, at the cost of trading less on one side; the card engine can be extended to do so.

30.5 Tutorial: the card-sum market

Goal. Compute the exact distribution of the card sum, play the market against a table of informed and uninformed bots with and without Bayesian updating, and find the width that maximises expected profit. End state: Figures 30.1, 30.2 and 30.3, Examples 30.4 and 30.7 and the numbers of the weekend problem.

  1. The deck and the update: the exact distribution of the sum, the table’s parameters, and Bayes’ rule after a trade or a pass.

    def card_sum_distribution(k: int, copies: int = 4, values: range = range(1, 14)) -> dict[int, float]:
        """Exact distribution of the sum of k cards drawn without replacement from the deck."""
        ways: dict[tuple[int, int], int] = {(0, 0): 1}                      # (cards, sum) -> count
        for v in values:
            nxt: dict[tuple[int, int], int] = {}
            for (n, s), w in ways.items():
                for j in range(min(copies, k - n) + 1):
                    key = (n + j, s + j * v)
                    nxt[key] = nxt.get(key, 0) + w * math.comb(copies, j)
            ways = nxt
        total = sum(w for (n, _), w in ways.items() if n == k)
        return {s: w / total for (n, s), w in sorted(ways.items()) if n == k}
    
    
    @dataclass(frozen=True)
    class Table:
        cards: int = 5
        rounds: int = 20
        informed: float = 0.2              # share of arriving traders who know the sum
        patience: float = 8.0              # uninformed traders' tolerance for width
    
    
    def mean(post: dict[int, float]) -> float:
        return sum(s * p for s, p in post.items())
    
    
    def update(post: dict[int, float], action: str, bid: float, ask: float, t: Table, width: float) -> dict[int, float]:
        """Posterior over the sum after observing `action` ('buy', 'sell' or 'pass') at these quotes."""
        q = math.exp(-width / t.patience)
        lik = {"buy": lambda s: t.informed * (s > ask) + (1 - t.informed) * q / 2,
               "sell": lambda s: t.informed * (s < bid) + (1 - t.informed) * q / 2,
               "pass": lambda s: t.informed * (bid <= s <= ask) + (1 - t.informed) * (1 - q)}[action]
        new = {s: p * lik(s) for s, p in post.items()}
        z = sum(new.values())
        return {s: p / z for s, p in new.items()} if z > 0 else post
    Listing 30.1. The card-sum distribution, the table, and the Bayesian update. code/firm/mmgame/firm_mmgame.py
  2. The game: dealing and playing one game.

    def deal(t: Table, rng: random.Random, prior: dict[int, float]) -> tuple[int, list[tuple[float, float, float]]]:
        """The sum and, for each round, the uniforms that decide who arrives, whether an uninformed
        trader trades and on which side; dealing once lets every width face the same table."""
        value = rng.choices(list(prior), list(prior.values()))[0]
        return value, [(rng.random(), rng.random(), rng.random()) for _ in range(t.rounds)]
    
    
    def play(width: float, t: Table, value: int, draws: list[tuple[float, float, float]], learn: bool = True,
             prior: dict[int, float] | None = None) -> tuple[float, list[float]]:
        """One game: (maker's P&L, the maker's mid before each round and at the end)."""
        prior = prior or card_sum_distribution(t.cards)
        post, pnl, mids = dict(prior), 0.0, []
        q = math.exp(-width / t.patience)
        for u_who, u_trade, u_side in draws:
            m = mean(post)
            mids.append(m)
            bid, ask = m - width / 2, m + width / 2
            if u_who < t.informed:
                action = "buy" if value > ask else "sell" if value < bid else "pass"
            else:
                action = ("buy" if u_side < 0.5 else "sell") if u_trade < q else "pass"
            if action == "buy":
                pnl += ask - value
            elif action == "sell":
                pnl += value - bid
            if learn:
                post = update(post, action, bid, ask, t, width)
        mids.append(mean(post))
        return pnl, mids
    Listing 30.2. Dealing and one game. code/firm/mmgame/firm_mmgame.py
  3. The widths: the expected P&L of each width against the same deals.

    def expected_pnl(widths: list[float], t: Table, games: int, seed: int,
                     learn: bool = True) -> list[tuple[float, float, float]]:
        """(width, mean P&L per game, standard error) for each width, every width facing the same
        seeded deals."""
        rng, prior = random.Random(seed), card_sum_distribution(t.cards)
        deals = [deal(t, rng, prior) for _ in range(games)]
        out = []
        for w in widths:
            xs = [play(w, t, v, d, learn, prior)[0] for v, d in deals]
            m = sum(xs) / games
            sd = math.sqrt(sum((x - m) ** 2 for x in xs) / (games - 1))
            out.append((w, m, sd / math.sqrt(games)))
        return out
    Listing 30.3. Expected P&L by width, over common deals. code/firm/mmgame/firm_mmgame.py
  4. Run mmgame_demo.first_trade(), mmgame_demo.problem() and fig_mmgame.py.

What to change next. Let the maker skew its quotes with its inventory, and find whether it earns more; then give each bot one of the five cards instead of the sum, so that every trader is partly informed, as around a real table.

30.6 Build: the market-making game engine

Purpose. The miniature firm trains its quoting logic, and its people, on games whose answers it can compute.

Interface. card_sum_distribution(k, copies, values); Table(cards, rounds, informed, patience); mean(post); update(post, action, bid, ask, table, width); deal(table, rng, prior); play(width, table, value, draws, learn, prior); expected_pnl(widths, table, games, seed, learn).

Rules. Five cards from one deck; one trader a round; informed traders trade only when the sum is outside the quotes; uninformed ones trade with probability e−w/λe^{-w/\lambda} on a random side; quotes centred on the maker’s current expected value; every width faces the same seeded deals.

Acceptance tests. code/firm/mmgame/tests/: the distribution sums to one with mean 35 and the right extremes; a buy raises and a sale lowers the estimate; without informed traders the profit matches the formula; updating beats not updating; games are reproducible.

Stretch. Inventory skew; several makers competing on width; traders with partial information (one card each); the Glosten–Milgrom zero-profit spread; a live version for people to play against the bots.

Sources and further reading

  • Jane Street, “Probability and markets guide”; trading internship page.
  • L. R. Glosten and P. R. Milgrom, “Bid, ask and transaction prices in a specialist market with heterogeneously informed traders”, Journal of Financial Economics 14 (1985).

30.7 Exercises

Exercise 30.1 ★

Make a market on the roll of a six-sided die, and explain your width.

Solution

Solution of Exercise 30.1.

Around the expected value, 3.5: for example “3 at 4, 10 up”. The value is known, so no one can be better informed; the width is a small profit for the risk of the roll and a width at which the other side still wants to trade.

Exercise 30.2 ★

You quote 200 at 400 on the number of windows and the interviewer buys. What do you do with your next market, and why?

Solution

Solution of Exercise 30.2.

Raise the market: the buyer may know better, and at least thought 400 was cheap. Move the centre up and perhaps widen, for example to 300 at 500, and think about why she bought: if she might have counted the windows, move a lot.

Exercise 30.3 ★

Why does a pass leave the maker’s estimate at 35 on the first round of the card game?

Solution

Solution of Exercise 30.3.

An informed trader passes when the sum is between 30 and 40, and an uninformed one passes with the same probability whatever the sum; the prior is symmetric about 35 and so is the set of sums that produce a pass, so the mean does not move. Later, when quotes are off-centre, a pass does move it.

Exercise 30.4 ★★

With no informed traders and patience 8, what width maximises the maker’s profit per round, and what does it earn over 20 rounds?

Solution

Solution of Exercise 30.4.

A width equal to the patience, 8 points: 4e−1=1.474e^{-1} = 1.47 a round, 29.4 over 20 rounds.

Exercise 30.5 ★★

In the first round at 30 at 40, what is the probability that a buyer is informed? Why is it so much higher than the 20% of informed traders at the table?

Solution

Solution of Exercise 30.5.

0.31. A quarter of the sums are above 40, so informed buyers are 5% of arrivals (0.2×0.250.2 \times 0.25); uninformed traders trade only 29% of the time at this width and buy half of that, 11.5% of arrivals (0.8×0.29/20.8 \times 0.29 / 2). The width filters the uninformed more than the informed, so a buy is informed more often than the table’s 20%.

Exercise 30.6 ★★

Explain the winner’s curse in a market maker’s terms.

Solution

Solution of Exercise 30.6.

The market maker’s quote is traded against precisely when someone thinks it is wrong in their favour; conditional on being filled, the value is worse than the maker thought. Quoting the unconditional estimate means losing on average to those who choose to trade.

Exercise 30.7 ★★★

Coding. With expected_pnl, find the best width for a table with 30% informed traders on the grid 8 to 15 in half points, over the same 2 000 seeded deals.

Solution

Solution of Exercise 30.7.

12.5 points, earning 13.8 a game: more informed traders push the best width up and the profit down (11.0 points and 20.6 with 10% informed).

Exercise 30.8 ★★★

Find the flaw. “I quote tight so I trade more: more trades means more spread earned.” Correct it.

Solution

Solution of Exercise 30.8.

More trades earn more spread from the uninformed, but a tight market is also traded whenever the informed know it is wrong, and those trades cost more than the spread earns. Below the best width, profit falls; at zero width the maker loses 22 a game in the chapter’s table.

30.8 Problem: The Card-Sum Market

Problem 30.1

Weekend problem — the width that pays

You make markets for 20 rounds on the sum of five cards dealt face down from a 52-card deck. Each round one trader comes: a fifth of the time one who knows the sum; otherwise one who trades on a random side with probability e−w/8e^{-w/8} at a width ww. You quote around your current expected value.

Part I — The contract.

  1. What are the mean, standard deviation and range of the sum?
  2. Why are the extremes 6 and 64 rather than 5 and 65?
  3. At a width of 10, how likely is an uninformed trader to trade?
  4. Quote your first market at width 10.
  5. What do you earn per round, on average, from an uninformed trader?

Part II — Learning.

  1. After a buy at 40, what is your new expected value? After a sale at 30?
  2. Why does a pass teach you nothing on the first round, but something later?
  3. In the chapter’s example game, how does your estimate move, and why does it first go the wrong way?
  4. What does updating earn you, at the best widths, against not updating?
  5. Why does the maker who does not update prefer a wider market?

Part III — The width.

  1. Find the best width and the expected P&L per game.
  2. What do widths of 8 and 15 earn?
  3. Without informed traders, what would the best width and profit be?
  4. How does the best width change with 10% and 30% informed traders?
  5. How likely does an uninformed trader trade at the best width?

Part IV — Judgement.

  1. How would you know, at a real table, what share of traders is informed?
  2. How should you adjust your quotes after three sales in a row?
  3. What does this game teach about quoting real securities?
  4. State the named result: the width that maximises expected P&L against this table, and that P&L.
  5. In one sentence: what does the width pay for?
Solution

Solution of Problem 30.1.

1. Mean 35, standard deviation 8.03, from 6 to 64. 2. A deck has four cards of each value: five aces or five kings are impossible. 3. e−10/8=0.29e^{-10/8} = 0.29. 4. 30 at 40. 5. Half the width when it trades: 0.29×5=1.430.29 \times 5 = 1.43 per round from an arriving uninformed trader. 6. 38.13 after a buy; 31.87 after a sale. 7. On the first round the quotes are symmetric around a symmetric prior; later the centre has moved, and a pass says the sum is probably inside the current quotes. 8. It rises from 35 to about 39 after early buys, then falls towards 31 as sales come in; the early buys were uninformed noise, or informed buys against a market still centred too low, and the maker cannot tell which. 9. 16.4 a game at 11.5 points against 12.0 at 14 points without updating. 10. Without learning its centre stays wrong, so it must keep more distance from the value to lose less to the informed. 11. 11.5 points, 16.4 a game. 12. 14.1 at 8 points and 15.1 at 15. 13. 8 points, about 29 a game. 14. 11.0 points with 10% informed (20.6 a game), 12.5 with 30% (13.8). 15. e−11.5/8=0.24e^{-11.5/8} = 0.24. 16. From the mark-outs of its fills: how far the value moves against it after trades, by counterparty and size; persistent adverse moves mean informed flow. 17. Raise the centre, since the buyers may know the value is higher, and consider skewing: a higher offer to sell less while short, a bid closer to buy back. 18. That the centre is an estimate to be revised with every trade, the width a price for adverse selection set against how much the uninformed will pay, and that learning from flow is worth as much as a wider spread. 19. Named result: the card-sum market: against a table with a fifth of the traders informed, a width of 11.5 points maximises the expected P&L, 16.4 a game. 20. It pays for the trades made with people who know more.

30.9 Interview questions

Interview question 30.1 ★ trader

Make me a market on the sum of two dice.

Solution

Solution of Interview question 30.1.

The sum has mean 7, from 2 to 12; with no one better informed, quote around 7, for example “6.5 at 7.5” for size, wider if the size is large relative to the risk one can take, and think about who would want to trade it.

What the interviewer is looking for: the centre, a reasoned width, and who is on the other side.

Interview question 30.2 ★ trader

I buy on your offer. What do you do now?

Solution

Solution of Interview question 30.2.

Ask why: the buyer may know more. Update the estimate upwards by an amount that depends on how likely the buyer is informed; move the market up, perhaps widen, and consider the inventory I now hold short.

What the interviewer is looking for: conditional expectation and inventory.

Interview question 30.3 ★★ trader, researcher

Why does a bid–ask spread exist even with no costs? Explain with a model.

Solution

Solution of Interview question 30.3.

Glosten and Milgrom: a risk-neutral maker facing informed and uninformed traders sets the offer at the expected value given a buy and the bid at the expected value given a sale; since buys are more likely when the value is high, the offer is above the bid even with zero costs and zero expected profit.

What the interviewer is looking for: conditional expectations on trade direction.

Interview question 30.4 ★★ trader

You are short three contracts after three sales. How do you move your market?

Solution

Solution of Interview question 30.4.

Move the market up, both because the sales may have been to informed buyers and because the short position is risk: raise the bid more than the offer to attract sellers and discourage buyers, until the inventory is back within limits.

What the interviewer is looking for: information and inventory both push the same way.

Interview question 30.5 ★★ researcher

How would you estimate the share of informed traders in a market from its trades?

Solution

Solution of Interview question 30.5.

From the relation between trades and subsequent price moves: estimate how much prices move after buys and sales (the permanent impact), or fit a Glosten–Milgrom or PIN-type model to the sequence of buys and sales and the spread; mark-outs by counterparty give a direct measure.

What the interviewer is looking for: price impact and mark-outs as evidence of information.

Interview question 30.6 ★★★ developer

Design a multi-player market-making game server for training, with bots and humans.

Solution

Solution of Interview question 30.6.

A server holding each game’s hidden state and order book, with a message protocol for quotes, trades and cancellations; bots as clients with the same interface as humans; time-stamped logs of everything for replay and scoring; rooms and scenarios defined as data; fairness checks on latency between players; post-game analytics of P&L, width and adverse selection.

What the interviewer is looking for: authoritative state, same interface for bots and humans, replay.

Terms defined in this chapter

See all 2333 terms in the glossary