finmath-lib stochastic automatic differentiation


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 extends finmath lib by providing an interface RandomVariableDifferentiable for random variables which provide automatic differentiation. The interface extends RandomVariable 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 RandomVariableDifferentiable.

All the backward automatic differentiation code is contained in RandomVariableDifferentiableAAD.

The interface RandomVariable is provided by finmath-lib and specifies the arithmetic operations which may be performed on random variables, e.g.,

RandomVariableDifferentiable add(RandomVariableDifferentiable randomVariable);    
RandomVariableDifferentiable mult(RandomVariableDifferentiable randomVariable);
RandomVariableDifferentiable exp();

// ...  

The interface RandomVariableDifferentiable will introduce two additional methods:

Long getID();   
Map<Long, RandomVariable> 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 RandomVariableDifferentiables (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: */
RandomVariable derivative = gradientOfX.get(Y.getID());

AAD on Cuda GPUs

It is possible to combine the automatic-differentiation-extensions with the cuda-extensions. See https://github.com/finmath/finmath-lib-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)
RandomVariableDifferentiable initialValue  = randomVariableFactory.createRandomVariable(modelInitialValue);
RandomVariableDifferentiable riskFreeRate  = randomVariableFactory.createRandomVariable(modelRiskFreeRate);
RandomVariableDifferentiable 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 EulerSchemeFromProcessModel(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);
RandomVariable value = (RandomVariableDifferentiable) europeanOption.getValue(0.0, monteCarloBlackScholesModel);

/*
 * Calculate sensitivities using AAD
 */
Map<Long, RandomVariable> derivative = ((RandomVariableDifferentiable)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();