---
title: "The Almgren–Chriss Framework"
book: "Microstructure and Execution"
subject: quant
language: en
chapter: 14
exercises: 8
source: https://one-course.com/books/quant/10/en/chapter/14-the-almgrenchriss-framework
---

# Chapter 14 — The Almgren–Chriss Framework

A trader must sell a million shares by the close. Selling them all now pays the impact; selling them evenly carries the price risk all day. Between the two lies a curve of schedules, and choosing a point on it is choosing a risk aversion. This chapter sets the problem as Almgren and Chriss did, solves it in closed form, draws the frontier, and then runs the schedules in the simulated market to see what the model gets right and what it misses.

## 14.1 Parent orders, child orders and a trajectory

**Definition 14.1 (Parent order, child order).**

A *parent order* is an instruction to trade a quantity over a period, given to a trader or an algorithm; the *child orders* are the orders actually sent to venues to execute it.

**Definition 14.2 (Trading trajectory).**

A *trading trajectory* is the quantity $x(t)$ still to be traded at each time $t$ of the execution window $[0,T]$, from $x(0)=X$ to $x(T)=0$; its trading rate is $v(t)=-\dot x(t)$.

The [parent order](#def-mx-the-almgren-chriss-framework-parent) is a metaorder (chapter 11) seen from the inside. A schedule chooses the trajectory; child-order placement (chapter 17) and routing (chapter 18) decide how each slice is traded. Bertsimas and Lo (1998) posed the choice as a dynamic programme minimising the expected cost; Almgren and Chriss (2001) added the risk.

## 14.2 Costs: impact and risk

**Definition 14.3 (Almgren–Chriss model).**

In the *Almgren–Chriss model* the price moves by a permanent impact $\gamma$ per share traded and a random walk of volatility $\sigma$, and each trade pays a temporary impact $\eta v$ per share at rate $v$. Selling $X$ along $x(t)$ costs, against the arrival price,

$$
\E[C]=\tfrac12\gamma X^2+\eta\int_0^Tv(t)^2\,dt,\qquad \operatorname{Var}[C]=\sigma^2\int_0^Tx(t)^2\,dt.
$$

**Definition 14.4 (Execution risk).**

*Execution risk* is the variance (or standard deviation) of an execution’s cost that comes from the price moving while the position is still held: $\sigma^2\int x^2\,dt$ here.

The permanent term does not depend on the schedule. The temporary term is smallest for trading as slowly as possible, evenly over the whole window; the risk is smallest for trading at once. A risk-averse trader minimises $\E[C]+\lambda\operatorname{Var}[C]$ (mean–variance, One Quant Book 7, chapter 25), with the risk aversion $\lambda$ in units of one over money.

## 14.3 The optimal trajectory in closed form

**Proposition 14.5 (Almgren–Chriss trajectory).**

The trajectory that minimises $\E[C]+\lambda\operatorname{Var}[C]$ is

$$
x(t)=X\,\frac{\sinh\bigl(\kappa(T-t)\bigr)}{\sinh(\kappa T)},\qquad \kappa=\sqrt{\frac{\lambda\sigma^2}{\eta}}.
$$

**Proof.** The objective is $\int_0^T(\eta\dot x^2+\lambda\sigma^2x^2)\,dt$ plus a constant. Its Euler–Lagrange equation is $\eta\ddot x=\lambda\sigma^2x$, whose solutions are combinations of $e^{\pm\kappa t}$; the boundary conditions $x(0)=X$, $x(T)=0$ select the ratio of hyperbolic sines. (This is also the value function route of One Quant Book 4, chapter 9, for a linear-quadratic problem.) ∎

**Definition 14.6 (Urgency).**

The *urgency* of an execution is $\kappa$, or the dimensionless $\kappa T$: zero for a straight line (time-weighted), large for a trajectory that sells most of the order early. Its inverse is the execution’s natural time scale.

On $n$ intervals of length $\tau$ the discrete optimum has the same form with $\tilde\kappa$ given by $\cosh(\tilde\kappa\tau)=1+\lambda\sigma^2\tau^2/(2\eta)$, which `firm.acexec.discrete` implements with the cost and variance of any discrete schedule.

```python
def discrete(x_total: float, horizon: float, n: int, eta: float, sigma: float,
             lam: float) -> np.ndarray:
    tau = horizon / n
    t = np.arange(n + 1) * tau
    if lam == 0:
        return x_total * (1 - t / horizon)
    kt = math.acosh(1 + lam * sigma**2 * tau**2 / (2 * eta)) / tau
    return x_total * np.sinh(kt * (horizon - t)) / np.sinh(kt * horizon)


def cost_var(holdings, horizon: float, gamma: float, eta: float,
             sigma: float) -> tuple[float, float]:
    x = np.asarray(holdings, float)
    tau = horizon / (len(x) - 1)
    trades = -np.diff(x)
    cost = 0.5 * gamma * x[0] ** 2 + eta * float(np.sum(trades**2)) / tau
    var = sigma**2 * tau * float(np.sum(x[1:] ** 2))
    return cost, var
```

***Listing 14.1.** The discrete Almgren–Chriss trajectory and the expected cost and variance of a schedule. code/firm/acexec/firm_acexec.py*

The chapter’s block: a stock at USD 50 trading 10 million shares a day with 2% daily volatility, so $\sigma=1$ dollar per share per square root of a day; selling 1 million by the close. The temporary impact is linearised from chapter 11’s square-root law at 10% participation, $\eta=0.8\times0.02\times\sqrt{0.1}\times50/(0.1\times10^7)=2.53\times10^{-7}$ dollars per share per share a day; no permanent impact. With $\lambda=10^{-6}$ per dollar, $\kappa=1.99$ per day. The optimal schedule on one-minute intervals expects to cost USD 300 000 (30 cents a share, 60 basis points) with a standard deviation of USD 470 000, a certainty equivalent $\E+\lambda\operatorname{Var}$ of USD 521 000, and sells 95% of the order in 5.9 of the 6.5 hours ([Figure 14.1](#fig-mx-the-almgren-chriss-framework-frontier), left).

## 14.4 The efficient trading frontier

**Definition 14.7 (Efficient trading frontier).**

The *efficient trading frontier* is the set of (risk, expected cost) pairs of the optimal trajectories as the risk aversion varies: no schedule has both lower risk and lower expected cost than a point on it.

The straight line is the frontier’s end with the least expected cost: USD 253 000 with a standard deviation of USD 576 000 and a certainty equivalent of USD 585 000 at $\lambda=10^{-6}$. What does getting the [urgency](#def-mx-the-almgren-chriss-framework-urgency) wrong cost? A schedule twice too patient ($\kappa/2$) expects USD 258 000 with a standard deviation of 542 000, a certainty equivalent of 551 000, 5.8% worse than the optimum; one twice too hurried ($2\kappa$) expects 506 000 with 352 000, a certainty equivalent of 630 000, 20.9% worse. The frontier is flat near its optimum and steep toward hurry: erring on the side of patience is cheaper.

![Selling 1 million shares by the close. Left: optimal trajectories for several urgencies (per day). Right: the efficient frontier, with the optimum for =10-6, the time-weighted schedule, and schedules twice too patient and twice too hurried. Data: mx_ac.block_study, fig_ac.py.](https://one-course.com/images/onecourse/chapters/quant-10/mx-the-almgren-chriss-framework/fig-8f24a1e05110.svg)

***Figure 14.1.** Selling 1 million shares by the close. Left: optimal trajectories for several urgencies (per day). Right: the efficient frontier, with the optimum for $\lambda=10^{-6}$, the time-weighted schedule, and schedules twice too patient and twice too hurried. Data: `mx_ac.block_study`, `fig_ac.py`.*

## 14.5 Calibration and limits

The model has three inputs, and each is an estimate. The execution agent of `mx_ac` runs a scheduler in `firm.agentmkt`’s market: it sells 20 000 shares over 30 minutes in 30 slices, each down to the scheduler’s target, for urgencies $\kappa T$ of 0, 2 and 6, on eight sessions each. The scheduler interface of `firm.acexec` (target holdings at given times) is the one chapters 15, 16 and 28 implement.

```python
class ScheduleAgent(Agent):
    name = "exec"

    def __init__(self, scheduler, start_ns: int, interval_ns: int, n: int):
        self.s, self.start, self.dt, self.n = scheduler, start_ns, interval_ns, n
        self.sold = 0

    def on_start(self, ctx):
        for j in range(self.n):
            ctx.set_timer(self.start + j * self.dt - ctx.now_ns, j)

    def on_timer(self, ctx, j):
        target = float(self.s.targets([(j + 1) / self.n])[0])
        q = int(round((self.s.x - target - self.sold) / 100)) * 100
        if q > 0:
            ctx.send(Order(side="S", qty=q, price=0, tif="I"))
            self.sold += q
```

***Listing 14.2.** An execution agent: at each interval it sells down to the scheduler’s target. code/microstructure/14-the-almgren-chriss-framework/python/mx_ac.py*

The realised shortfall per share ([Figure 14.2](#fig-mx-the-almgren-chriss-framework-sim)) is 5.2 ticks for the straight line (standard error 2.8), 5.3 (2.3) for $\kappa T=2$ and 7.4 (1.3) for $\kappa T=6$, with standard deviations across sessions of 8.0, 6.5 and 3.8: faster schedules cost more on average and vary less, as the model says. Calibrated on the same runs, the temporary impact is $\eta=0.11$ ticks per share per share a second (from each slice’s cost against its size) and $\sigma=0.69$ ticks per root second (from one-minute mid changes), and the model predicts means of 1.2, 1.4 and 3.6 ticks and standard deviations of 16.4, 13.2 and 7.6. It gets the ordering right and the levels wrong in two ways. The mean is too low because each slice’s slippage misses the impact that builds up across slices: the gap implies a permanent impact of about $4\times10^{-4}$ ticks per share, the $\gamma$ set to zero here. The standard deviation is too high because the market mean-reverts: its fundamentalists pull the price back, so thirty minutes’ variance is less than thirty times one minute’s. Almgren (2003) extended the model to non-linear impact and to risk that grows with trading; chapter 15 lets the schedule react to the market.

![Almgren–Chriss schedules executed in the simulated market (eight sessions each) against the model calibrated on the same runs. The model orders the schedules correctly; it misses the impact that accumulates across slices and the market’s mean reversion. Data: mx_ac.sim_study.](https://one-course.com/images/onecourse/chapters/quant-10/mx-the-almgren-chriss-framework/fig-aabc8c59798d.svg)

***Figure 14.2.** Almgren–Chriss schedules executed in the simulated market (eight sessions each) against the model calibrated on the same runs. The model orders the schedules correctly; it misses the impact that accumulates across slices and the market’s mean reversion. Data: `mx_ac.sim_study`.*

## 14.6 Tutorial: liquidating a block by the close

**Goal.** Solve the Almgren–Chriss problem for a block, draw its frontier, and test the schedules in the simulated market. **End state:** Figures [14.1](#fig-mx-the-almgren-chriss-framework-frontier) and [14.2](#fig-mx-the-almgren-chriss-framework-sim).

1. **Model.** `firm_acexec.kappa` , `trajectory` , `discrete` , `cost_var` , `frontier` , `time_to` .
2. **Block.** `mx_ac.block_study(lam)` : the optimum, the time-weighted schedule and the two mistakes.
3. **Simulation.** `ScheduleAgent(ACScheduler(Q, 1, kT), …)` in `firm_agentmkt.session` ; `sim_study()` for three urgencies and eight seeds, with the calibration.
4. **Draw.** `fig_ac.py` .

**What to change next.** Add the permanent impact implied by the simulation to the model and recompute its means; calibrate $\sigma$ at the execution’s horizon instead of one minute.

## 14.7 Build: the execution schedule

**Purpose.** The reference schedule of the firm’s execution: the benchmark that chapters 15 and 16 improve on, the scheduler interface their algorithms and chapter 28’s implement, and the pre-trade cost and risk estimates of chapter 19.

**Interface.** `kappa(eta, sigma, lam)`, `trajectory(X, T, kappa, t)`, `discrete(X, T, n, eta, sigma, lam)`, `cost_var(holdings, T, gamma, eta, sigma)`, `frontier(…, lams)`, `time_to(share, kappa, T)`; `Scheduler.targets(times)`, `ACScheduler`, `LinearScheduler`.

**Rules.** Holdings are the quantity still to trade; the discrete [urgency](#def-mx-the-almgren-chriss-framework-urgency) from $\cosh(\tilde\kappa\tau)$; costs against the arrival price; $\eta$ per unit of trading rate in the caller’s time unit.

**Acceptance tests.** `code/firm/acexec/tests/`: discrete and continuous trajectories agree on a fine grid; cost and variance of a straight line by hand; the frontier’s costs rise and variances fall with $\lambda$; the time to 95% equals $\ln 20/\kappa$ on a long horizon; the schedulers’ targets.

**Stretch.** Non-linear temporary impact (Almgren, 2003); a portfolio version with a covariance matrix; calibration from `firm.impactfit`.

Sources and further reading

- D. Bertsimas and A. W. Lo, “Optimal control of execution costs”, *Journal of Financial Markets* 1(1), 1998.
- R. Almgren and N. Chriss, “Optimal execution of portfolio transactions”, *Journal of Risk* 3(2), 2001.
- R. Almgren, “Optimal execution with nonlinear impact functions and trading-enhanced risk”, *Applied Mathematical Finance* 10(1), 2003.

## 14.8 Exercises

**Exercise 14.1 ★.**

With $\eta=2.53\times10^{-7}$ dollars per share per share a day, $\sigma=1$ dollar per share per root day and $\lambda=10^{-6}$ per dollar, compute $\kappa$.

**Solution of Exercise 14.1.**

$\kappa=\sqrt{10^{-6}\times1/2.53\times10^{-7}}=\sqrt{3.95}=1.99$ per day.

**Exercise 14.2 ★.**

Compute the expected cost and standard deviation of selling 1 million shares in a straight line over one day with these parameters and no permanent impact.

**Solution of Exercise 14.2.**

$\E=\eta X^2/T=2.53\times10^{-7}\times10^{12}=253\,000$ dollars; $\operatorname{Var}=\sigma^2X^2T/3$, a standard deviation of $10^6/\sqrt3=577\,000$ dollars (576 000 on one-minute intervals).

**Exercise 14.3 ★.**

How long does the optimal schedule take to sell 95% of the order, and what is the formula when the window is long?

**Solution of Exercise 14.3.**

5.9 of the 6.5 hours. On a long window $x(t)\approx Xe^{-\kappa t}$, so 95% is sold at $\ln20/\kappa$.

**Exercise 14.4 ★★.**

Why does a schedule twice too hurried lose more certainty equivalent (20.9%) than one twice too patient (5.8%)?

**Solution of Exercise 14.4.**

The temporary cost grows like $\kappa$ (trading faster costs more per share on every share), while the risk saved by hurrying is small once the order is already sold early; being patient adds risk slowly because the variance is bounded by the straight line’s.

**Exercise 14.5 ★★.**

Why does the model calibrated from slice slippage predict too low a mean shortfall in the simulation?

**Solution of Exercise 14.5.**

Each slice’s slippage measures only the book it consumed; the impact of earlier slices that has not decayed raises the prices later slices pay, a permanent (or slowly decaying) impact the model’s $\gamma=0$ leaves out.

**Exercise 14.6 ★★.**

Why does it predict too high a standard deviation?

**Solution of Exercise 14.6.**

$\sigma$ was estimated from one-minute changes and scaled as if prices were a random walk; the market mean-reverts (its fundamentalists pull the price back), so the variance over thirty minutes is less than thirty times the one-minute variance.

**Exercise 14.7 ★★★.**

*Coding.* From the simulated and model means, infer the permanent impact $\gamma$ that would close the gap for $\kappa T=0$ and for $\kappa T=6$. Are the two estimates consistent?

**Solution of Exercise 14.7.**

The mean gap is $\gamma Q/2$: $2\times(5.2-1.2)/20\,000=4.0\times10^{-4}$ ticks a share for $\kappa T=0$ and $2\times(7.4-3.6)/20\,000=3.8\times10^{-4}$ for $\kappa T=6$: consistent, as a schedule-independent permanent term should be.

**Exercise 14.8 ★★★.**

*Find the flaw.* “A time-weighted schedule has no risk because it trades the same amount every minute.”

**Solution of Exercise 14.8.**

Its trades are certain; its cost is not: it holds the position the longest, and the price moves while it does. Its risk is the largest on the frontier, a standard deviation of USD 576 000 for the block.

## 14.9 Problem: Liquidating a Block by the Close

**Problem 14.1.**

Weekend problem — liquidating a block by the close

A portfolio manager must sell 1 million shares of a 50-dollar stock by the close and asks the desk for a schedule, its expected cost and its risk.

**Part I — The model.**

1. Define parent and [child orders](#def-mx-the-almgren-chriss-framework-parent) and a [trading trajectory](#def-mx-the-almgren-chriss-framework-trajectory) .
2. Write the Almgren–Chriss expected cost and variance.
3. Why does the permanent term not depend on the schedule?
4. Derive the optimal trajectory.

**Part II — The block.**

5. How is $\eta$ linearised from the square-root law, and what is it here?
6. Give $\kappa$ , the expected cost, the standard deviation and the certainty equivalent at $\lambda=10^{-6}$ .
7. When is 95% of the order sold?
8. Give the straight line’s cost, risk and certainty equivalent.

**Part III — The frontier.**

9. Define the [efficient trading frontier](#def-mx-the-almgren-chriss-framework-frontier) .
10. Give the cost, risk and certainty equivalent of the schedules twice too patient and twice too hurried.
11. Which mistake is cheaper, and why?
12. What does the risk aversion mean for the manager?

**Part IV — Calibration and the verdict.**

13. Describe the simulated test.
14. Give the realised means and standard deviations.
15. Give the model’s calibrated parameters and predictions.
16. Explain the gaps.
17. What permanent impact closes the mean gap?
18. State the *named result* : the optimal trading horizon, expected cost and standard deviation for a given risk aversion, and the extra cost of a schedule that is twice too patient or twice too hurried.
19. What would you tell the manager about the numbers’ reliability?
20. In one sentence: what does the frontier add to a cost estimate?

**Solution of Problem 14.1.**

**1.** See the definitions. **2.** $\E=\tfrac12\gamma X^2+\eta\int v^2$, $\operatorname{Var}=\sigma^2\int x^2$. **3.** Every share sold moves the price by $\gamma$ whenever it is sold; the total is $\tfrac12\gamma X^2$. **4.** Euler–Lagrange: $\eta\ddot x=\lambda\sigma^2x$ with $x(0)=X$, $x(T)=0$. **5.** At 10% participation the square-root law gives $0.8\sigma\sqrt{0.1}$ of the price; dividing by the rate gives $\eta=2.53\times10^{-7}$ dollars per share per share a day. **6.** $\kappa=1.99$ per day; USD 300 000, 470 000 and 521 000. **7.** After 5.9 hours. **8.** USD 253 000, 576 000 and 585 000. **9.** The (risk, cost) pairs of optimal schedules over all risk aversions. **10.** Patient: 258 000, 542 000, 551 000 (+5.8%); hurried: 506 000, 352 000, 630 000 (+20.9%). **11.** Patience: the frontier is flat around the optimum toward lower [urgency](#def-mx-the-almgren-chriss-framework-urgency) and steep toward higher. **12.** How many dollars of expected cost the manager would pay to remove a dollar squared of variance: a statement about how much the day’s price risk matters to the fund. **13.** 20 000 shares over 30 minutes in 30 slices at urgencies 0, 2 and 6, eight sessions each. **14.** Means 5.2, 5.3 and 7.4 ticks; standard deviations 8.0, 6.5 and 3.8. **15.** $\eta=0.11$, $\sigma=0.69$; means 1.2, 1.4, 3.6 and standard deviations 16.4, 13.2, 7.6. **16.** Accumulating impact across slices (a permanent part) and mean reversion of the price. **17.** About $4\times10^{-4}$ ticks a share. **18.** *Named result*: with $\lambda=10^{-6}$ the optimal schedule sells 95% in 5.9 hours, expects USD 300 000 with a standard deviation of 470 000; a schedule twice too patient costs 5.8% more certainty equivalent and one twice too hurried 20.9% more. **19.** The ranking of schedules is reliable; the levels depend on calibrations that the simulation shows can be off by a factor of three. **20.** The risk that comes with each cost, and so the choice of how much cost to pay to reduce it.

## 14.10 Interview questions

**Interview question 14.1 ★ trader, researcher.**

Explain the trade-off in optimal execution and the shape of the Almgren–Chriss trajectory.

**Solution of Interview question 14.1.**

Trading fast pays temporary impact; trading slowly bears price risk. The optimum front-loads the order: $x(t)=X\sinh(\kappa(T-t))/\sinh(\kappa T)$, a straight line when risk does not matter and an exponential decay when it matters a lot.

*What the interviewer is looking for: The trade-off; the sinh shape; limits.*

**Interview question 14.2 ★★ researcher.**

Derive the Almgren–Chriss trajectory from its objective.

**Solution of Interview question 14.2.**

Minimise $\int(\eta\dot x^2+\lambda\sigma^2x^2)dt$; Euler–Lagrange $\eta\ddot x=\lambda\sigma^2x$; boundary conditions give the sinh ratio.

*What the interviewer is looking for: Calculus of variations; boundary conditions.*

**Interview question 14.3 ★★ trader.**

Your client doubles its risk aversion. What happens to the schedule, the expected cost and the risk?

**Solution of Interview question 14.3.**

$\kappa$ grows by $\sqrt2$: the schedule front-loads more, the expected cost rises and the risk falls; the client moves along the frontier toward hurry.

*What the interviewer is looking for: Direction of each change; the square root.*

**Interview question 14.4 ★★ researcher.**

How would you calibrate the temporary and permanent impact of the model?

**Solution of Interview question 14.4.**

Temporary: regress each slice’s slippage against the mid on its trading rate; permanent: the drift of the price over the whole execution beyond the temporary part, or the price after completion; both on many orders, with the square-root law as a check.

*What the interviewer is looking for: Slice-level and order-level estimates; sample size.*

**Interview question 14.5 ★★ developer.**

Design a scheduler interface that different execution algorithms can share. What does it take and return?

**Solution of Interview question 14.5.**

Given the order and the market state, return target holdings at requested times (and a way to update them as the market changes); the child-order layer trades toward the targets. Keep it stateless or explicit about state so schedules can be tested offline.

*What the interviewer is looking for: Targets over time; separation from placement.*

**Interview question 14.6 ★★★ researcher.**

What does the [Almgren–Chriss model](#def-mx-the-almgren-chriss-framework-ac) leave out, and which of these matters most for a liquid stock?

**Solution of Interview question 14.6.**

Non-linear and transient impact, intraday volume and volatility patterns, signals, spread and fees, and adaptation to the market. For a liquid stock the volume pattern and transient impact usually matter most.

*What the interviewer is looking for: A list; a prioritisation with a reason.*
