---
title: "Beyond Almgren–Chriss"
book: "Microstructure and Execution"
subject: quant
language: en
chapter: 15
exercises: 8
source: https://one-course.com/books/quant/10/en/chapter/15-beyond-almgrenchriss
---

# Chapter 15 — Beyond Almgren–Chriss

The Almgren–Chriss schedule does not look at the market while it trades. A trader who expects the price to fall in the next half-hour should sell faster; one whose impact decays should pause after a large trade; one whose market dries up at lunch should trade before it does. This chapter adds each of these to chapter 14’s block: a forecast, the price’s own moves, transient impact and random liquidity, and measures what each is worth.

## 15.1 Execution with a signal

**Definition 15.1 (Signal-adaptive schedule).**

A *signal-adaptive schedule* sets each interval’s trade from the holdings left and a forecast of the price’s drift, trading faster when the forecast is against the order (a seller expecting a fall) and slower when it is for it.

Let the price drift at a rate $\alpha_t$ that follows an Ornstein–Uhlenbeck process (One Quant Book 4, chapter 4) with a half-life and a stationary standard deviation, observed by the trader. On $n$ steps of length $\tau$, selling $u_k$ from holdings $x_k$, the expected cost is quadratic in the state $(x_k,\alpha_k)$ and the control:

$$
\min\ \E\sum_k\Bigl(\eta\frac{u_k^2}{\tau}+\lambda\sigma^2\tau x_k^2-\tau\,\alpha_kx_k\Bigr),\qquad x_{k+1}=x_k-u_k,\quad \alpha_{k+1}=\phi\,\alpha_k+\text{noise},
$$

with $x_n=0$ enforced by a large terminal penalty. A linear-quadratic problem has a linear optimal policy, $u_k=K_{k,1}x_k+K_{k,2}\alpha_k$, with gains from a backward Riccati recursion; without a signal it reproduces the Almgren–Chriss trajectory exactly. Cartea and Jaimungal (2016) built order flow into the same framework.

```python
def lqr_signal(n: int, tau: float, eta: float, sigma: float, lam: float, phi: float,
               terminal: float = 1e6):
    q = np.array([[lam * sigma**2 * tau, -tau / 2], [-tau / 2, 0.0]])
    r = eta / tau
    a = np.array([[1.0, 0.0], [0.0, phi]])
    b = np.array([[-1.0], [0.0]])
    p = np.array([[terminal, 0.0], [0.0, 0.0]])
    gains = []
    for _ in range(n):
        k = np.linalg.solve(r + b.T @ p @ b, b.T @ p @ a)          # u = -k z
        p = q + a.T @ p @ a - a.T @ p @ b @ k
        gains.append(-k.ravel())
    return gains[::-1]
```

***Listing 15.1.** The Riccati recursion of execution with a signal: gains on the holdings and on the forecast drift. code/firm/execcontrol/firm_execcontrol.py*

On the block of chapter 14 (1 million shares of a USD 50 stock over a day, in 78 five-minute steps, $\lambda=10^{-6}$), 1 500 simulated days with the same random numbers for both schedules give the saving in [Figure 15.1](#fig-mx-beyond-almgren-chriss-signal). A signal with a half-life of a twentieth of a day (about twenty minutes) and a standard deviation of USD 0.5 a day saves 0.19 basis points against Almgren–Chriss’s 61; one with a half-life of a day and USD 2 a day saves 41 of 66. The saving grows with the signal’s strength and more than linearly with its persistence: a forecast that lasts only a few steps cannot be acted on before it is gone. It also raises the cost’s variance (a standard deviation of 212 basis points against 173 for the strongest signal): the schedule takes risk to use the forecast.

![What a drift forecast saves the block’s execution, against its half-life, for three strengths (standard deviations of the drift): mean saving over 1 500 simulated days with common random numbers, and its standard error. Data: mx_beyond.signal_study.](https://one-course.com/images/onecourse/chapters/quant-10/mx-beyond-almgren-chriss/fig-ae2957d18bdc.svg)

***Figure 15.1.** What a drift forecast saves the block’s execution, against its half-life, for three strengths (standard deviations of the drift): mean saving over 1 500 simulated days with common random numbers, and its standard error. Data: `mx_beyond.signal_study`.*

## 15.2 Adaptive schedules

**Definition 15.2 (Adaptive execution, aggressive-in-the-money strategy).**

An *adaptive execution* changes its schedule with the price’s path during the order. An *aggressive-in-the-money strategy* trades faster when the price has moved in the order’s favour (up for a seller) and slower when it has moved against it.

Almgren–Chriss is static: its mean–variance optimum is computed once. Lorenz and Almgren (2011) showed that re-optimising as the price moves does better in the same mean–variance sense. The intuition: after a favourable move the order has gained money it can spend on impact to cut the remaining risk. The chapter’s rule recomputes the Almgren–Chriss trajectory from the current holdings at each step with [urgency](https://one-course.com/books/quant/10/en/chapter/14-the-almgrenchriss-framework#def-mx-the-almgren-chriss-framework-urgency) $\kappa_0e^{a\,\Delta p/(\sigma\sqrt T)}$.

```python
def aim(k0: float, a: float, sigma: float, horizon: float, n: int):
    """A policy u(k, x, alpha, dp): the Almgren-Chriss trajectory from the current holdings
    over the time left, with urgency k0 exp(a dp / (sigma sqrt(horizon)))."""
    tau = horizon / n

    def policy(k, x, alpha, dp):
        left = horizon - k * tau
        kk = k0 * math.exp(a * dp / (sigma * math.sqrt(horizon)))
        if kk * left < 1e-9:
            return x * tau / left
        if kk * left > 30:                           # the ratio of sinh without overflow
            return x * (1 - math.exp(-kk * tau))
        return x - x * math.sinh(kk * (left - tau)) / math.sinh(kk * left)
    return policy
```

***Listing 15.2.** An aggressive-in-the-money policy: the static trajectory re-solved from the current holdings with an urgency that grows with the gain so far. code/firm/execcontrol/firm_execcontrol.py*

With $\kappa_0T=2$ and 3 000 simulated days, the static schedule costs 60.9 basis points with a standard deviation of 90.5, a certainty equivalent of 101.9. The adaptive rule with $a=0.25$, 0.5, 1 and 2 costs 61.2, 62.2, 66.2 and 81.7 on average with standard deviations of 88.7, 86.4, 80.4 and 66.2, and certainty equivalents of 100.5, 99.4, 98.6 and 103.6: moderate adaptation improves the trade-off by up to 3.2%, strong adaptation overshoots.

![The aggressive-in-the-money rule for increasing adaptation a=0 (static), 0.25, 0.5, 1 and 2: it trades mean cost for lower risk, with the best certainty equivalent near a=1 at this risk aversion. 3 000 simulated days. Data: mx_beyond.aim_grid.](https://one-course.com/images/onecourse/chapters/quant-10/mx-beyond-almgren-chriss/fig-2a8eea0dc42a.svg)

***Figure 15.2.** The aggressive-in-the-money rule for increasing adaptation $a=0$ (static), 0.25, 0.5, 1 and 2: it trades mean cost for lower risk, with the best certainty equivalent near $a=1$ at this risk aversion. 3 000 simulated days. Data: `mx_beyond.aim_grid`.*

## 15.3 Transient impact and the optimal block

**Definition 15.3 (Bucket-shaped trajectory).**

A *bucket-shaped trajectory* trades a block at the start and another at the end with a slower constant rate between: the optimum when impact is transient.

With the exponential kernel of Obizhaeva and Wang (2013, chapter 12), resilience $\rho=10$ per day and 101 trades over the day, the time-weighted schedule costs 0.0893 (in units of the instantaneous impact of the whole order) and the optimum 0.0834, 6.6% less: it trades 0.0876 of the order in each end block, close to the formula’s $1/(\rho T+2)=0.0833$, and 0.0083 in each trade between. Selling everything at once would cost 0.5. The saving is modest because the kernel decays fast relative to the day; with slower resilience the blocks and the saving grow.

## 15.4 Stochastic liquidity

**Definition 15.4 (Stochastic liquidity).**

*Stochastic liquidity* lets the impact parameters themselves change at random during the execution, as volume and depth do, so that the cost of trading now depends on the state of the market now.

Almgren (2012) solved mean–variance execution when liquidity and volatility vary randomly, with strategies that adapt to the market’s quality. The chapter’s version has two regimes, normal and dry, the dry one with four times the temporary impact; the market stays normal with probability 0.9 per step and dry with 0.7; the policy on (holdings, regime) comes from Book 4’s `firm.dpsolve`. Halfway through the day with half the order left, it sells 60 000 shares in the next step when the market is normal and 20 000 when it is dry. Over 3 000 simulated days it costs 73.2 basis points against 91.5 for Almgren–Chriss, which ignores the regimes: 18.3 basis points saved (standard error 0.5), with a slightly lower standard deviation (89.6 against 94.6).

## 15.5 A control-theory template

The four problems share a template: a state (holdings, and whatever the market reveals), a control (the trade), a cost (impact now, risk and forecast drift later), and a solution method matched to the structure: a closed form for Almgren–Chriss, a Riccati recursion for linear-quadratic signals, a matrix inverse for transient impact, dynamic programming for regimes. Gatheral and Schied (2011) solved the geometric Brownian case in closed form under another risk criterion. Every solution returns a schedule in `firm.acexec`’s interface, so the child-order layer does not care which one produced it.

## 15.6 Tutorial: trading on a forecast

**Goal.** Add a signal, adaptation, transient impact and random liquidity to the block’s execution, and price each. **End state:** Figures [15.1](#fig-mx-beyond-almgren-chriss-signal) and [15.2](#fig-mx-beyond-almgren-chriss-aim) and the numbers of sections 2 to 4.

1. **Signal.** `firm_execcontrol.lqr_signal(n, tau, eta, sigma, lam, phi)` and `simulate(policy, …)` ; `mx_beyond.signal_study()` .
2. **Adaptation.** `aim(k0, a, sigma, T, n)` ; `aim_grid()` .
3. **Transient.** `transient_study(rho)` with `firm_propagator.optimal_liquidation` and `OWScheduler` .
4. **Liquidity.** `liquidity_dp(X, n, tau, eta, sigma, lam, stay)` and `liquidity_study()` ; draw with `fig_beyond.py` .

**What to change next.** Feed each schedule to chapter 14’s `ScheduleAgent` and run it in the simulated market on many sessions; estimate the signal’s drift with a Kalman filter instead of observing it.

## 15.7 Build: execution control

**Purpose.** The adaptive schedules behind the algorithms of chapters 16 and 28 and Book 12’s learned execution policies, as benchmarks with known optima.

**Interface.** `lqr_signal(n, tau, eta, sigma, lam, phi)`, `simulate(policy, X, n, tau, eta, sigma, phi, s_alpha, seed, paths)`, `OWScheduler(X, rho, T)`, `aim(k0, a, sigma, T, n)`, `liquidity_dp(X, n, tau, eta, sigma, lam, stay)`.

**Rules.** Sales are positive; the last step sells what is left; costs against the arrival price per share; common random numbers across policies; regime probabilities in tenths (the nodes of `firm.dpsolve`).

**Acceptance tests.** `code/firm/execcontrol/tests/`: the Riccati policy without a signal equals the discrete Almgren–Chriss trajectory; a signal lowers the mean cost; Obizhaeva–Wang’s blocks; the adaptive policy’s direction and its static limit; more selling when liquid.

**Stretch.** Kalman-filtered signals; stochastic volatility; transient impact with a signal.

Sources and further reading

- P. Lorenz and R. Almgren, “Mean–variance optimal adaptive execution”, *Applied Mathematical Finance* 18(5), 2011.
- J. Gatheral and A. Schied, “Optimal trade execution under geometric Brownian motion in the Almgren and Chriss framework”, *International Journal of Theoretical and Applied Finance* 14(3), 2011.
- R. Almgren, “Optimal trading with stochastic liquidity and volatility”, *SIAM Journal on Financial Mathematics* 3(1), 2012.
- A. A. Obizhaeva and J. Wang, “Optimal trading strategy and supply/demand dynamics”, *Journal of Financial Markets* 16(1), 2013.
- A. Cartea and S. Jaimungal, “Incorporating order-flow into optimal execution”, *Mathematics and Financial Economics* 10(3), 2016.

## 15.8 Exercises

**Exercise 15.1 ★.**

A signal has a half-life of 0.2 days. What is its persistence $\phi$ over a five-minute step of a 78-step day?

**Solution of Exercise 15.1.**

$\phi=e^{-\ln2\,(1/78)/0.2}=0.9565$.

**Exercise 15.2 ★.**

Why is the gain on the forecast drift negative in the Riccati policy for a seller (the policy sells less when the forecast drift is positive)?

**Solution of Exercise 15.2.**

The cost has the term $-\tau\alpha x$: holding shares while the drift is positive earns the drift, so a seller keeps more of the position when $\alpha>0$ and sells less; when $\alpha<0$ it sells faster.

**Exercise 15.3 ★.**

With resilience $\rho=10$ per day and a one-day window, what share of the order does the Obizhaeva–Wang optimum trade in each end block?

**Solution of Exercise 15.3.**

$1/(\rho T+2)=1/12=0.0833$ of the order in each block (0.0876 on the 101-trade grid).

**Exercise 15.4 ★★.**

Why does a signal with a short half-life save so little, even when it is strong?

**Solution of Exercise 15.4.**

Acting on a forecast means trading faster or slower than the schedule, which costs temporary impact; a forecast that decays within a few steps changes the price by little before it is gone, so there is little to capture for the impact spent: 0.19 basis points at a twentieth of a day and USD 0.5 a day, 3.0 even at USD 2.

**Exercise 15.5 ★★.**

Why does adaptation with $a=2$ do worse than the static schedule in certainty equivalent?

**Solution of Exercise 15.5.**

It changes speed so much after moves that it pays heavy impact in bursts: its mean cost rises to 81.7 basis points, more than the risk it removes is worth at this risk aversion (certainty equivalent 103.6 against 101.9).

**Exercise 15.6 ★★.**

What does the stochastic-liquidity policy do differently from Almgren–Chriss, and why does it save 18 basis points?

**Solution of Exercise 15.6.**

It trades more while the market is liquid and waits while it is dry (60 000 against 20 000 shares at mid-order), paying the dry regime’s quadruple impact less often; Almgren–Chriss trades on schedule whatever the regime.

**Exercise 15.7 ★★★.**

*Coding.* Run the signal study with the signal observed with noise (the policy sees $\alpha+\epsilon$ with $\epsilon$ of the same standard deviation as $\alpha$). How much of the saving survives, and why?

**Solution of Exercise 15.7.**

Acting on the noisy observation as if it were exact saves 8.3 basis points (standard error 2.0) instead of 41; weighting it by one half, its signal-to-total variance ratio (the Bayes estimate of $\alpha$), saves 20.3. Noise makes the policy trade on errors; shrinking the forecast recovers half the value.

**Exercise 15.8 ★★★.**

*Find the flaw.* “Our execution with the alpha signal saved 40 basis points in the backtest, so the signal is worth 40 basis points on every order.”

**Solution of Exercise 15.8.**

The saving depends on the signal’s strength and half-life relative to each order’s duration and size, it is measured on the backtest’s orders, and it assumes the signal is as good out of sample and observed without noise (exercise 7: noise cuts it from 41 to 8 basis points); and the schedule takes more risk. Value it per order type, out of sample, with the risk.

## 15.9 Problem: Trading on a Forecast

**Problem 15.1.**

Weekend problem — trading on a forecast

A research team gives the execution desk a drift forecast and asks what it is worth; the desk also wonders about adapting to prices and liquidity.

**Part I — The signal.**

1. Write the linear-quadratic problem and its state.
2. Why is the optimal policy linear, and how are its gains computed?
3. Check that without a signal it is Almgren–Chriss.
4. Give the saving for the three strengths at the three half-lives.

**Part II — Adaptation.**

5. Define an [aggressive-in-the-money strategy](#def-mx-beyond-almgren-chriss-adaptive) .
6. Give the static schedule’s cost, risk and certainty equivalent.
7. Give the adaptive rule’s for $a=0.25$ , 0.5, 1 and 2.
8. Why does moderate adaptation help?

**Part III — Transient impact and liquidity.**

9. Give the costs of the time-weighted and optimal schedules under the transient kernel and the size of the blocks.
10. Why is the saving small here?
11. Describe the two liquidity regimes and the policy’s trades in each.
12. Give the dynamic programme’s cost and saving.

**Part IV — The verdict.**

13. Rank the four extensions by what they saved here.
14. Which of them need data the desk may not have?
15. What does the signal do to the cost’s risk?
16. How would you test the signal’s value on real orders?
17. State the *named result* : the basis points an alpha signal saves an execution schedule, against the signal’s half-life and strength.
18. What minimum half-life makes a signal worth wiring into execution, on these numbers?
19. Which extension would you build first, and why?
20. In one sentence: what does looking at the market buy an execution?

**Solution of Problem 15.1.**

**1.** Minimise $\E\sum(\eta u^2/\tau+\lambda\sigma^2\tau x^2-\tau\alpha x)$; state $(x,\alpha)$. **2.** Quadratic cost and linear dynamics: the value function is quadratic, the policy linear; Riccati recursion backward. **3.** With $\phi=0$ and no drift the gains reproduce the discrete Almgren–Chriss trajectory. **4.** Half-life 0.05: 0.19, 0.75, 2.98; 0.2: 1.1, 4.5, 17.2; 1: 3.1, 11.5, 41.0 basis points for USD 0.5, 1 and 2 a day. **5.** Faster when the price has moved in the order’s favour. **6.** 60.9, 90.5, 101.9 basis points. **7.** Means 61.2, 62.2, 66.2, 81.7; deviations 88.7, 86.4, 80.4, 66.2; certainty equivalents 100.5, 99.4, 98.6, 103.6. **8.** After a gain, cutting the remaining risk is worth some impact; the static schedule cannot do it. **9.** 0.0893 and 0.0834; blocks of 0.0876 (formula 0.0833). **10.** Resilience of 10 a day makes impact decay fast compared with the day, so spreading evenly is nearly optimal. **11.** Normal and dry (four times the impact), staying 0.9 and 0.7; 60 000 against 20 000 shares at mid-order. **12.** 73.2 against 91.5 basis points: 18.3 saved. **13.** Signal (up to 41 for a strong, persistent one), liquidity (18), transient impact (6.6% of impact), adaptation (3.2% of the certainty equivalent). **14.** The signal and the liquidity regimes. **15.** It raises it: 212 against 173 basis points of standard deviation for the strongest signal. **16.** Split real orders by the signal’s value at arrival and compare schedules with and without it on matched orders, out of sample. **17.** *Named result*: on the block, a drift forecast with a half-life of a twentieth of a day saves 0.19 to 3.0 basis points for standard deviations of USD 0.5 to 2 a day, and one with a half-life of a day saves 3.1 to 41; the saving grows with strength and faster than linearly with persistence. **18.** About a fifth of a day (1 to 17 basis points) for these strengths; shorter signals are worth little. **19.** Liquidity regimes: an 18-basis-point saving from data the desk sees in real time. **20.** The chance to trade when trading is cheap and the price is on its side, at the cost of more risk.

## 15.10 Interview questions

**Interview question 15.1 ★ trader.**

You are selling and your alpha model says the stock will fall over the next hour. How does your schedule change?

**Solution of Interview question 15.1.**

Sell faster now, before the expected fall, at the cost of more impact; how much faster depends on the forecast’s size and horizon against my impact.

*What the interviewer is looking for: Direction; the trade-off with impact; horizon.*

**Interview question 15.2 ★★ researcher.**

Set up execution with an Ornstein–Uhlenbeck signal as a linear-quadratic control problem.

**Solution of Interview question 15.2.**

State (holdings, signal), control the trade; cost impact plus risk minus drift times holdings; dynamics linear with the OU persistence; solve by Riccati.

*What the interviewer is looking for: State, cost, dynamics, solution method.*

**Interview question 15.3 ★★ researcher.**

Why is the optimal execution under transient impact bucket-shaped?

**Solution of Interview question 15.3.**

A first block uses the book as it is, the continuous part trades at the refill rate, and the last block uses liquidity no later trade will pay for.

*What the interviewer is looking for: Resilience; end effects.*

**Interview question 15.4 ★★ trader.**

Should an execution speed up or slow down after the price has moved in its favour?

**Solution of Interview question 15.4.**

Speed up, in the mean–variance sense: the gain pays for cutting risk (aggressive in the money); moderately, since strong adaptation pays too much impact.

*What the interviewer is looking for: Direction; moderation.*

**Interview question 15.5 ★★ developer.**

How would you compare two execution policies fairly in simulation?

**Solution of Interview question 15.5.**

Same orders, same market paths (common random numbers), many repetitions, costs against the same arrival price, report means with standard errors and the risk.

*What the interviewer is looking for: Common random numbers; errors; risk.*

**Interview question 15.6 ★★★ researcher.**

How would you estimate the value of a short-horizon signal for execution from historical orders?

**Solution of Interview question 15.6.**

Estimate the signal’s predictive power for returns over execution horizons, simulate the policy on historical orders with the signal as known at arrival, and compare with the schedule without it, out of sample and net of the extra impact.

*What the interviewer is looking for: Out of sample; horizon matching; net of impact.*
