Markets: A Rigorous Course

Exercise · m05_kyle.py

Kyle (1985) and Glosten-Milgrom (1985)

Kyle, one period. v ~ N(p0, sigma_v^2) is the liquidation value, known only to the insider. Noise traders submit u ~ N(0, sigma_u^2), independent of v. The insider submits x = beta (v - p0). The market maker sees only total order flow y = x + u and sets p = p0 + lam y = E[v | y].

Proposition 5.3: lam = sigma_v / (2 sigma_u), beta = sigma_u / sigma_v, insider expected profit sigma_v sigma_u / 2, Var(v | y) = sigma_v^2 / 2.

Glosten-Milgrom, one trade. v in {v_low, v_high}, P(v_high) = theta. A fraction mu of arriving traders is informed (buys iff v = v_high, else sells); the others buy or sell with probability 1/2 each. A competitive dealer quotes ask = E[v | buy] and bid = E[v | sell] (Proposition 5.2).

Check: cd exercises && .venv/bin/python -m pytest modules/M05-intraday-execution/tests

Tests (6)

  • test_equilibrium_closed_form
  • test_lambda_recovered_by_regression
  • test_profits_and_information
  • test_insider_best_response
  • test_glosten_milgrom
  • test_glosten_milgrom_zero_profit

Theory: M05 notes. Run with Ctrl/⌘+Enter.

not run yet

Not saved: sign up to keep your code
"""Exercise 5.2: Kyle (1985) and Glosten-Milgrom (1985) (notes.md §5.3-5.4).

Kyle, one period. v ~ N(p0, sigma_v^2) is the liquidation value, known only
to the insider. Noise traders submit u ~ N(0, sigma_u^2), independent of v.
The insider submits x = beta (v - p0). The market maker sees only total
order flow y = x + u and sets p = p0 + lam y = E[v | y].

Proposition 5.3: lam = sigma_v / (2 sigma_u), beta = sigma_u / sigma_v,
insider expected profit sigma_v sigma_u / 2, Var(v | y) = sigma_v^2 / 2.

Glosten-Milgrom, one trade. v in {v_low, v_high}, P(v_high) = theta. A
fraction mu of arriving traders is informed (buys iff v = v_high, else
sells); the others buy or sell with probability 1/2 each. A competitive
dealer quotes ask = E[v | buy] and bid = E[v | sell] (Proposition 5.2).

Check:
    cd exercises && .venv/bin/python -m pytest modules/M05-intraday-execution/tests
"""

from __future__ import annotations

import numpy as np  # noqa: F401


def kyle_equilibrium(sigma_v: float, sigma_u: float) -> dict:
    """Return {"lam", "beta", "insider_profit", "posterior_var"} from Proposition 5.3."""
    raise NotImplementedError


def simulate_kyle(p0: float, sigma_v: float, sigma_u: float, n: int, seed: int = 0, beta: float | None = None, lam: float | None = None) -> dict:
    """Simulate n independent one-period games.

    rng = np.random.default_rng(seed); draw Z1 then Z2 as two length-n standard
    normal arrays; v = p0 + sigma_v Z1; u = sigma_u Z2; x = beta (v - p0);
    y = x + u; p = p0 + lam y. beta and lam default to the equilibrium values
    when None (use them to test off-equilibrium strategies).

    Return a dict with numpy arrays "v", "u", "x", "y", "p" and
    "profit" = (v - p) * x, the insider's realised profit per game.
    """
    raise NotImplementedError


def estimate_lambda(v: np.ndarray, y: np.ndarray) -> float:
    """OLS slope, with intercept, of v on y: sum (y - ybar)(v - vbar) / sum (y - ybar)^2.

    In data, v is the price after the information has come out, so this is the
    empirical price-impact regression of later price on signed order flow.
    """
    raise NotImplementedError


def glosten_milgrom_quotes(v_high: float, v_low: float, theta: float, mu: float) -> tuple[float, float]:
    """(bid, ask) = (E[v | sell], E[v | buy]) by Bayes' rule (Proposition 5.2)."""
    raise NotImplementedError


def simulate_gm_dealer_pnl(v_high: float, v_low: float, theta: float, mu: float, n: int, seed: int = 0) -> tuple[float, float]:
    """Simulate n independent single-trade rounds at the Glosten-Milgrom quotes.

    Each round: draw v (v_high w.p. theta), draw informed (w.p. mu); an informed
    trader buys iff v = v_high; an uninformed one buys w.p. 1/2. The dealer's
    P&L is ask - v on a buy and v - bid on a sell.

    Return (mean P&L, standard error of the mean). Zero-profit quotes give a
    mean indistinguishable from 0.
    """
    raise NotImplementedError

No runs yet

The stub's functions raise NotImplementedError until you write them. Fill in one, press Run tests, and watch its tests turn green.

Reference solution

Available after your first run, with an account approved for code runs.

Create a free account

Reading is open to everyone. An account keeps your progress, answers, notes and code drafts, and gives you the study plan, the journals and the simulator. Running code needs an account approved for it.