finmath-lib automatic differentiation extensions
Enabling finmath lib to utilize automatic differentiation algorithms (e.g. AAD).
This project implements a stochastic automatic differentiation.
The implementation is fast, memory efficient and thread safe. It handles automatic differentiation of the conditional expectation (American Monte-Carlo), see http://ssrn.com/abstract=3000822.
The project provides an interface RandomVariableDifferentiableInterface
for random variables which provide automatic differentiation. The interface extends RandomVariableInterface
and hence allows to use auto-diff in all Monte-Carlo contexts (via a replacement of the corresponding parameters / factories).
The project also provides implementations of this interface, e.g. utilizing the backward (a.k.a. adjoint) method via RandomVariableDifferentiableAADFactory
. This factory creates a random variable RandomVariableDifferentiableAAD
which implements RandomVariableDifferentiableInterface
.
All the backward automatic differentiation code is contained in RandomVariableDifferentiableAAD
.
The interface RandomVariableInterface
is provided by finmath-lib and specifies the arithmetic operations which may be performed on random variables, e.g.,
RandomVariableDifferentiableInterface add(RandomVariableDifferentiableInterface randomVariable);
RandomVariableDifferentiableInterface mult(RandomVariableDifferentiableInterface randomVariable);
RandomVariableDifferentiableInterface exp();
// ...
The interface RandomVariableDifferentiableInterface
will introduce two additional methods:
Long getID();
Map<Long, RandomVariableInterface> getGradient();
The method getGradient
will return a map providing the first order differentiation of the given random variable (this
) with respect to all its input RandomVariableDifferentiableInterface
s (leaf nodes). To get the differentiation with respect to a specific object use
/* Get the gradient of X with respect to all its leaf nodes: /*
Map gradientOfX = X.getGradient();
/* Get the derivative of X with respect to Y: */
RandomVariableInterface derivative = gradientOfX.get(Y.getID());
AAD on Cuda GPUs
It is possible to combine the automatic-differentiation-extensions with the cuda-extensions.
Using
AbstractRandomVariableFactory randomVariableFactory = new RandomVariableDifferentiableAADFactory();
will create a standard (CPU) random variable with automatic differentiation. Instead, using
AbstractRandomVariableFactory randomVariableFactory = new RandomVariableDifferentiableAADFactory(new RandomVariableCudaFactory());
will create a Cuda GPU random variable with automatic differentiation.
Example
The following sample code calculates valuation, delta, vega and rho for an almost arbitrary product (here an EuropeanOption) using AAD on the Monte-Carlo valuation
RandomVariableDifferentiableAADFactory randomVariableFactory = new RandomVariableDifferentiableAADFactory();
// Generate independent variables (quantities w.r.t. to which we like to differentiate)
RandomVariableDifferentiableInterface initialValue = randomVariableFactory.createRandomVariable(modelInitialValue);
RandomVariableDifferentiableInterface riskFreeRate = randomVariableFactory.createRandomVariable(modelRiskFreeRate);
RandomVariableDifferentiableInterface volatility = randomVariableFactory.createRandomVariable(modelVolatility);
// Create a model
AbstractModel model = new BlackScholesModel(initialValue, riskFreeRate, volatility);
// Create a time discretization
TimeDiscretizationInterface timeDiscretization = new TimeDiscretization(0.0 /* initial */, numberOfTimeSteps, deltaT);
// Create a corresponding MC process
AbstractProcess process = new ProcessEulerScheme(new BrownianMotion(timeDiscretization, 1 /* numberOfFactors */, numberOfPaths, seed));
// Using the process (Euler scheme), create an MC simulation of a Black-Scholes model
AssetModelMonteCarloSimulationInterface monteCarloBlackScholesModel = new MonteCarloAssetModel(model, process);
/*
* Value a call option (using the product implementation)
*/
EuropeanOption europeanOption = new EuropeanOption(optionMaturity, optionStrike);
RandomVariableInterface value = (RandomVariableDifferentiableInterface) europeanOption.getValue(0.0, monteCarloBlackScholesModel);
/*
* Calculate sensitivities using AAD
*/
Map<Long, RandomVariableInterface> derivative = ((RandomVariableDifferentiableInterface)value).getGradient();
double valueMonteCarlo = value.getAverage();
double deltaAAD = derivative.get(initialValue.getID()).getAverage();
double rhoAAD = derivative.get(riskFreeRate.getID()).getAverage();
double vegaAAD = derivative.get(volatility.getID()).getAverage();