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 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 RandomVariableDifferentiableInterfaces (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. 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)
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();