finMath.net

Algorithmic Differentiation to derive Forward Sensitivities

Getting Started

Checkout finmath-experiments from git and run maven (mvn or mvnw) from its directory. This will start a JShell. See Getting Started for details.

Experiment 0: Monte-Carlo Simulation and Valuation (Recap)

Run the following experiment from your JShell (which was launched from finmath-experiments).

Initial Setup

In the experiments on the Monte-Carlo simulation a simulation object and a product object has been created and the delta of option has been evaluated using finite difference. Repeat this:

Create the model and its simulation:

JShell:

				import net.finmath.montecarlo.*;
				import net.finmath.montecarlo.assetderivativevaluation.*;
				import net.finmath.montecarlo.assetderivativevaluation.models.*;
				import net.finmath.montecarlo.automaticdifferentiation.*;
				import net.finmath.montecarlo.automaticdifferentiation.backward.*;
				import net.finmath.montecarlo.process.*;
				import net.finmath.time.*;
				
				double modelInitialValue = 100.0;
				double modelRiskFreeRate = 0.05;
				double modelVolatility = 0.20;
				
				RandomVariableFactory randomVariableFactory = new RandomVariableDifferentiableAADFactory();
				
				// Create a model
				var model = new BlackScholesModel(modelInitialValue, modelRiskFreeRate, modelVolatility, randomVariableFactory);
				
				// Create a corresponding MC process
				var td = new TimeDiscretizationFromArray(0.0, 300, 0.01);
				var brownianMotion = new BrownianMotionFromMersenneRandomNumbers(td, 1, 10000, 3231);
				var process = new EulerSchemeFromProcessModel(model, brownianMotion);
				
				// Using the process (Euler scheme), create an MC simulation of a Black-Scholes model
				var simulation = new MonteCarloAssetModel(process);
			

Create the product:

JShell:

				import net.finmath.montecarlo.assetderivativevaluation.products.*;
				
				double maturity = 3.0;
				double strike = 106.0;
				
				var europeanOption = new EuropeanOption(maturity, strike);
			

Experiment 1 - Dynamic delta hedge using algorithmic differentiation (requires run of "Initial Setup")

The class DeltaHedgedPortfolioWithAAD takes any financial product (any object implementing AssetMonteCarloProduct) and performs a so called “delta hedge” (on the simulation's time discretization). It uses AAD to calculate the delta \( \phi(t,\omega_{k}) = V(T,\omega_{k}) / S(t,\omega_{k}) \) and constructs the hedge portfolio (replication portfolio) from it.

Important: We will first conduct an experiment which will (likely) give wrong results. We will then fix the issue.

JShell: (continued)

				import net.finmath.plots.*;

				var hedge = new DeltaHedgedPortfolioWithAAD(europeanOption);
				var underlyingAtMaturity = simulation.getAssetValue(maturity, 0);
				var hedgeValue = hedge.getValue(maturity, simulation);

				var plot = Plots.createScatter(underlyingAtMaturity, hedgeValue, 50.0, 110.0);
				plot.setTitle("Hedge Portfolio").setXAxisLabel("underlying").setYAxisLabel("portfolio value");
				plot.show();
			

The result of this experiment is a hedge portfolio which is constant at maturities. The reason is that all values of delta are 0 (except the one at the initial time t0). In the default setting, the algorithm implemented in RandomVariableDifferentiableAAD will only retain derivatives of the leaf nodes of the operator tree. It does not retain the derivatives of intermediate values (since this consumes a significant amount of memory). We can change this by passing a property to the RandomVariableDifferentiableAADFactory.

Re-create the model and its simulation (with the modified RandomVariableDifferentiableAADFactory):

JShell:

				import net.finmath.montecarlo.*;
				import net.finmath.montecarlo.automaticdifferentiation.*;
				import net.finmath.montecarlo.automaticdifferentiation.backward.*;
				
				Map<String, Object> properties = Map.of("isGradientRetainsLeafNodesOnly", false);		// CHANGE MADE HERE
				RandomVariableFactory randomVariableFactory = new RandomVariableDifferentiableAADFactory(properties);
				
				// Create a model
				var model = new BlackScholesModel(modelInitialValue, modelRiskFreeRate, modelVolatility, randomVariableFactory);
				
				// Create a corresponding MC process
				var td = new TimeDiscretizationFromArray(0.0, 300, 0.01);
				var brownianMotion = new BrownianMotionFromMersenneRandomNumbers(td, 1, 10000, 3231);
				var process = new EulerSchemeFromProcessModel(model, brownianMotion);
				
				// Using the process (Euler scheme), create an MC simulation of a Black-Scholes model
				var simulation = new MonteCarloAssetModel(process);
			
Now perform the hedge simulation on the newly created simulation.
JShell: (continued)

				import net.finmath.plots.*;

				var hedge = new DeltaHedgedPortfolioWithAAD(europeanOption);
				var underlyingAtMaturity = simulation.getAssetValue(maturity, 0);
				var hedgeValue = hedge.getValue(maturity, simulation);

				var plot = Plots.createPlotScatter(underlyingAtMaturity, hedgeValue, 50.0, 110.0);
				plot.setTitle("Hedge Portfolio").setXAxisLabel("underlying").setYAxisLabel("portfolio value");
				plot.show();