What is AAD (adjoint algorithmic differentiation)?
AAD is a way to compute every sensitivity of a price or risk number in one extra pass through the code that computes it. The cost of that pass does not grow with the number of risk factors: it can be as little as 2 times the cost of one valuation with XAD's tape, whether the trade or book depends on ten inputs or ten thousand. The derivatives are exact for the code as written, not estimates.
Sensitivities, and why they cost so much
A sensitivity says how much a result moves when one input moves: the delta of an option to its underlying, the vega to a volatility, the move in CVA when one point of a credit curve shifts. Risk management, hedging, regulatory capital and margin all need them, often thousands per trade or netting set, every day.
The usual way to get them is bump and revalue: shift one input by a small amount, price again, and divide the change in price by the shift. One revaluation per input. A book that depends on a few hundred risk factors costs a few hundred valuations, and a Monte Carlo valuation can take minutes on its own. This is why sensitivity runs fill overnight grids. AAD vs bump and revalue compares the two in detail.
The idea: the chain rule, run backwards
Every pricing program, however large, is a long sequence of simple operations: additions, multiplications, exponentials, a square root, a maximum. Each one has a derivative that is easy to write down. The chain rule from school calculus says that the derivative of the whole program is the product of these small derivatives along the way. Algorithmic differentiation applies that rule to the code itself, automatically, operation by operation.
It can run in two directions:
- Forward mode carries derivatives from the inputs to the outputs, alongside the normal calculation. One pass gives the derivatives with respect to one input, so it costs one pass per input, like bumping, but without the error of a finite bump.
- Adjoint mode runs the other way. The program first runs normally and records its operations. A second pass then walks that record backwards, from the result to the inputs, and collects the sensitivity of the result to every input at once. That is AAD: one backward pass for all the sensitivities of one result.
Prices and risk numbers are few results that depend on many inputs. That is exactly the shape where adjoint mode wins, which is why AAD has become the standard tool for sensitivities in banks.
A worked example
Take a small function of two inputs, written as three lines of code:
a = sin(x1)
b = x1 * x2
z = a + b
We want both sensitivities of z, at x1 = π and x2 = 2.
Bumping runs the three lines once as a base, then once more with x1 shifted and once more with x2 shifted: three runs, and two answers that are only as good as the size of the shift.
The adjoint pass runs the three lines once, keeps a record of them, and walks back from z, asking at each step how much z moves if that intermediate value moves:
| Step, backwards | Rule used | Result |
|---|---|---|
z = a + b | z moves one for one with a and with b | sensitivity to a: 1, to b: 1 |
b = x1 * x2 | b moves by x2 per unit of x1, and by x1 per unit of x2 | x1 collects 2, x2 collects π |
a = sin(x1) | a moves by cos(x1) per unit of x1, and cos(π) is −1 | x1 collects −1 |
Adding up what each input collected gives ∂z/∂x1 = 2 − 1 = 1 and ∂z/∂x2 = π, both exact, from one forward run and one backward pass. With a thousand inputs the backward pass would still be one pass; bumping would need a thousand and one runs.
The AAD tutorial in the XAD documentation works through the same example step by step, in forward and adjoint mode, with the maths.
What it costs
- Time. All first-order sensitivities of one result cost as little as 2 times one valuation with XAD's tape, independent of how many inputs there are. With code generation, the whole run, every sensitivity included, is up to 3 times faster than one plain valuation of the original code. The published bound and its history are in Capriotti and Giles, “15 years of adjoint algorithmic differentiation (AAD) in finance”, Quantitative Finance, 2024.
- Memory. The record of operations, called the tape, has to be kept until the backward pass. For a long Monte Carlo simulation it can be large. Checkpointing, path-wise processing and code generation keep it in bounds; good AAD tools do this for you.
- Code changes. The code has to be differentiable as a whole. With an operator-overloading library such as XAD, the main change is the number type:
doublebecomes an active type that records itself. Branches on prices, discontinuous payoffs and calls into closed libraries need care, and every sensitivity is checked against bumping before it is trusted.
Where it is used
Wherever a few results depend on many inputs: XVA and its sensitivities across a whole book, SA-CVA and FRTB standardised approach capital, forward SIMM for initial margin and MVA, model calibration, and the Greeks of exotic trades priced by Monte Carlo. Our case studies give the results banks report on their own code.
Next steps
- AAD vs bump and revalue: cost, accuracy and when bumping still makes sense.
- XAD, the AAD library for C++ and Python, and its documentation.
- AAD training for quant teams, on their own code.
- AAD enablement: AAD built into your pricing and risk code.