Almgren-Chriss Optimal Execution

Finance

Buying a million shares of a stock in one click would push the price up before you finish the order. So instead you BREAK the order into pieces and trade them gradually. But trading gradually means the price might drift against you while you wait. This is the OPTIMAL EXECUTION PROBLEM, and the Almgren-Chriss (2001) framework is the standard analytical approach to it. The model formalizes a trade-off: SLOW execution minimizes MARKET IMPACT (the cost of moving the price by trading), but exposes you to PRICE VARIANCE (the cost of waiting). The optimal schedule depends on the trader's RISK AVERSION — how much variance you're willing to accept to save on impact.

Almgren-Chriss sits at the core of every institutional execution algorithm: VWAP, TWAP, Implementation Shortfall, percent-of-volume schedulers all derive from variants of the framework. It's also the textbook entry point for MARKET MICROSTRUCTURE — the study of how prices, orders, and liquidity actually interact in real markets, beyond the frictionless models used in derivatives pricing.

The model

Liquidate shares over a horizon , broken into equal-spaced intervals of length . Let be the inventory remaining at time , with and . Each interval, you sell shares.

Three components of cost.

(1) Price dynamics. Absent your trading, the stock price would follow

with standard normal — arithmetic Brownian motion over the execution horizon (acceptable approximation for short horizons; for longer ones use geometric).

(2) Permanent impact. Trading shares moves the price PERMANENTLY downward by :

Permanent impact captures the information leakage of trading — once you've sold a lot, the market revises its view of fair value downward, and the price stays lower.

(3) Temporary impact. Each trade is also executed at a temporarily worse price proportional to the trading RATE :

Temporary impact captures the bid-ask spread and the order-book depth — to fill a large order quickly, you have to walk down the bid book. It decays away as soon as you stop trading.

The TOTAL realized cost (the difference between the actual execution proceeds and what the entire position would have been worth at the initial price) has an EXPECTED PART (deterministic, from the impact terms) and a VARIANCE PART (stochastic, from and your remaining inventory). Almgren-Chriss minimize a weighted combination

where is the trader's RISK AVERSION. means "minimize expected cost only" — slow execution, accepting price risk for low impact. means "minimize variance" — execute immediately, paying maximum impact for no risk.

The optimal schedule

Calculus of variations applied to (or discrete optimization in the time-discretized version) gives the closed form:

where the rate is determined by

The CHARACTERISTIC LENGTH is the natural timescale on which the trader's risk aversion balances impact cost. When (small ), the trajectory is approximately linear — TWAP. When (large ), the trajectory is concentrated near — front-loaded execution.

The efficient frontier of execution

Varying traces out a curve in (expected cost, std of cost) space — the analogue of the mean-variance efficient frontier for portfolio choice. Every point on the curve is the OPTIMAL trade-off for some risk aversion. Different institutional traders sit at different points:

Code

# Almgren-Chriss (2001) optimal execution schedule for liquidating X
# shares over time T, with linear permanent + temporary impact and a
# variance penalty controlled by risk-aversion lambda.

import numpy as np

X      = 1_000_000           # shares to liquidate
T      = 1.0                 # one trading day
N      = 20                  # number of trading intervals
tau    = T / N
sigma  = 0.3 / np.sqrt(252)  # daily price volatility
gamma  = 2.5e-7              # permanent impact coefficient
eta    = 2.5e-6              # temporary impact coefficient
eta_tilde = eta - gamma * tau / 2

def ac_trajectory(lam):
    """Almgren-Chriss optimal inventory schedule.
       x_k = X * sinh(kappa (T - k*tau)) / sinh(kappa T)
       with kappa = arcosh(1 + lam sigma² tau² / (2 eta_tilde)) / tau."""
    arg = 1 + (lam * sigma**2 * tau**2) / (2 * eta_tilde)
    kappa = np.arccosh(arg) / tau
    k = np.arange(N + 1)
    return X * np.sinh(kappa * (T - k * tau)) / np.sinh(kappa * T), kappa

def ac_cost(x):
    """Expected impact cost and variance from price uncertainty
    on remaining inventory."""
    trades = np.diff(x)                          # negative: shares sold
    perm = -gamma * np.sum((X - x[:-1]) * trades)
    temp =  eta * np.sum(trades**2) / tau
    cost = perm + temp
    var  = sigma**2 * tau * np.sum(x[1:]**2)
    return cost, var

print(f"Almgren-Chriss optimal schedule, X = {X:,}, T = {T}, N = {N}:")
print(f"  {'lambda':>10s}  {'kappa*T':>10s}  {'cost':>14s}  {'std':>14s}  {'first trade':>12s}")
for lam in [1e-9, 1e-5, 1e-3, 1e-1]:
    x, kappa = ac_trajectory(lam)
    c, v = ac_cost(x)
    print(f"  {lam:>10.0e}  {kappa*T:>10.3f}  {c:>14.2f}  "
          f"{np.sqrt(v):>14.2f}  {x[0]-x[1]:>12.0f}")

# TWAP for comparison
twap = X * (1 - np.arange(N + 1) / N)
c_twap, v_twap = ac_cost(twap)
print(f"\nTWAP (uniform, equivalent to lambda → 0):")
print(f"  Cost = {c_twap:.2f}, Std = {np.sqrt(v_twap):.2f}")
print(f"\nHigh lambda → faster execution → higher cost, lower variance.")
print(f"TWAP is the lambda → 0 limit; Implementation Shortfall is lambda → ∞.")

Output:

Almgren-Chriss optimal schedule, X = 1,000,000, T = 1.0, N = 20:
      lambda     kappa*T            cost             std   first trade
       1e-09       0.000      2618750.00        10500.85         50000
       1e-05       0.038      2618750.11        10499.77         50022
       1e-03       0.378      2619852.73        10394.58         52188
       1e-01       3.779      4864914.73         6210.13        172361

TWAP (uniform, equivalent to lambda → 0):
  Cost = 2618750.00, Std = 10500.85

High lambda → faster execution → higher cost, lower variance.
TWAP is the lambda → 0 limit; Implementation Shortfall is lambda → ∞.

Two regimes visible in the table. At small (1e-9 to 1e-5), — the trajectory is essentially linear (TWAP), with the first trade equal to and the std at its maximum. As grows to 1e-3, and the schedule is mildly front-loaded — first trade 52,200 (slightly above the TWAP level), cost up by 0.04%, std down by 1%. At , and the schedule is aggressively front-loaded: first trade 172,000 (17% of total, 3.4× the TWAP rate), expected cost up by 86%, std down by 41%. You can see the trade-off explicitly: pay impact NOW to avoid price risk LATER.

Beyond the linear model

Almgren-Chriss assumes LINEAR impact, but empirical evidence (Almgren-Thum-Hauptmann-Li 2005, Bouchaud-Bonart-Donier-Gould 2018) supports a SQUARE-ROOT law: impact scales as in trade size, not linearly. Quoted as:

where is the order size, is average daily volume, is daily volatility, and is an empirically-fit constant (typically 0.5-1 for liquid stocks). The square-root law is one of the most robust empirical regularities in market microstructure — it holds across asset classes, time periods, and market structures. The linear model in Almgren-Chriss is a TANGENT approximation; for production codes you use the square-root version, which is no longer closed-form but still solvable numerically.

What practical execution algorithms actually do

The standard institutional execution products:

Connections to the rest of microstructure

Almgren-Chriss is just the entry point. The market microstructure literature continues with:

Related