finMath.net

# Monte-Carlo Simulation of a Black Scholes Model

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-4: Monte-Carlo Simulation and Valuation

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

## Experiment 0

The following will create an object of type TimeDiscretizationFromArray (from the package net.finmath.time) and then print the object (using the toString()-method). The time discretization starts in 0.0 and has 100 time steps of size 0.1.
JShell:

var td = new net.finmath.time.TimeDiscretizationFromArray(0.0, 100, 0.1);
td.toString();

We may shorten the name of object by importing a classes from the package or all classes from the packages (like name-spaces), e.g. here from net.finmath.time via import net.finmath.time.*;.

## Experiment 1

In the following experiment we create a class of type BrownianMotionFromMersenneRandomNumbers (from the package net.finmath.montecarlo) which represent samples of a set of (independent) normal distributed random variables $$\Delta W(t_{i})$$ (the so called Brownian increments). The arguments of BrownianMotionFromMersenneRandomNumbers are (timeDiscretization, numberOfFactors, numberOfPaths, seed), where numberOfFactors refers to the vector dimension of $$\Delta W(t_{i})$$. In the following we create a one factor (i.e., one dimensional) Brownian motion:

JShell:

import net.finmath.montecarlo.*;
import net.finmath.plots.*;
import net.finmath.time.*;

var td = new TimeDiscretizationFromArray(0.0, 100, 0.1);
var bm = new BrownianMotionFromMersenneRandomNumbers(td, 1, 10000, 3213);   // change number of paths
var x = bm.getBrownianIncrement(0,0);

To plot a histogram of the random variable x enter
JShell:

var plot = Plots.createHistogram(x, 100, 5.0);
plot.setTitle("Histogram").setXAxisLabel("value").setYAxisLabel("frequency");
plot.show();


For fun, you may also create an animation:
JShell:

for(int i=2; i<100; i+=1) {
int numberOfPaths = i*i*Math.max(i/10,1);
Plots.updateHistogram(plot, (new BrownianMotionFromMersenneRandomNumbers(td, 1, numberOfPaths, 3213)).getBrownianIncrement(0,0), 100, 5.0);
} ## Experiment 2

Given a Brownian motion providing the Brownian increments $$\Delta W(t_{i})$$, we create a model (here a BlackScholesModel) and from that a simulation of this model using an Euler scheme (via EulerSchemeFromProcessModel). The model is $$\mathrm{d}S(t) = r S(t) \mathrm{d} + \sigma(t) S(t) \mathrm{d}W(t) ; \quad S(t_{0}) = S_{0}$$, where $$S(t_{0})$$ is the modelInitialValue, $$r$$ is the modelRiskFreeRate, $$\sigma$$ is the modelVolatility.
JShell:

import net.finmath.montecarlo.*;
import net.finmath.montecarlo.process.*;
import net.finmath.montecarlo.assetderivativevaluation.*;
import net.finmath.montecarlo.assetderivativevaluation.models.*;
import net.finmath.stochastic.*;
import net.finmath.time.*;
import net.finmath.plots.*;

double modelInitialValue = 100.0;
double modelRiskFreeRate = 0.05;
double modelVolatility = 0.20;

// Create a model
var model = new BlackScholesModel(modelInitialValue, modelRiskFreeRate, modelVolatility);

// Create a corresponding MC process from the model
var td = new TimeDiscretizationFromArray(0.0, 300, 0.01);
var brownianMotion = new BrownianMotionFromMersenneRandomNumbers(td, 1, 10000, 3231);
var process = new EulerSchemeFromProcessModel(model, brownianMotion);

// Create a function, plotting paths t -> S(t)
DoubleToRandomVariableFunction paths = time -> process.getProcessValue(td.getTimeIndex(time), 0 /* assetIndex */);

// Plot 100 of paths against the given time discretization.
var plot = new PlotProcess2D(td, paths, 100);
plot.setTitle("Black Scholes model paths").setXAxisLabel("time").setYAxisLabel("value");
plot.show(); ## Experiment 3

We value a financial product on our simulation, that is we calculate the expectation $$E(f(S(T))$$ for, e.g. $$f(x) = \max(x - K)$$. The function $$f$$ represents the financial product, in the example below we use an EuropeanOption. The product provides a method getValue which implements $$E(f(S(T))$$ given a simulation providing S(T), in our example the object simulation. Note: the following requires that Experiment 2 has initialized the object simulation. We first create the product
JShell: (continued from experiment 2)

import net.finmath.montecarlo.assetderivativevaluation.products.*;

double maturity = 3.0;
double strike = 106.0;

var europeanOption = new EuropeanOption(maturity, strike);

Given that the objects process and europeanOption have been initialized, we can value the product against the simulation:
JShell: (continued)

// Using the process (Euler scheme) and provide methods like getAssetValue and getNumeraire
var simulation = new MonteCarloAssetModel(process);

// Use the simulation to value the product
var valueOfEuropeanOption = europeanOption.getValue(0.0, simulation);
var value = valueOfEuropeanOption.average().doubleValue();

The value reported it 18.115.... Request the standard error via
JShell: (continued)

valueOfEuropeanOption.getStandardError();


The reported standard error is 0.27....

You can plot the products payoff function and the histogram of the simulated values of $$S(T)$$ where $$T$$ corresponds to the optionMaturity:

JShell: (continued)

var underlying = simulation.getAssetValue(maturity, 0 /* assetIndex */);

var plot = Plots.createHistogramBehindValues(underlying, valueOfEuropeanOption, 100 /* bins */, 5.0 /* stddev */);
plot.setTitle("European option value and distribution of underlying").setXAxisLabel("underlying").setYAxisLabel("value");
plot.show(); ### Analytic Benchmark

We may compare the value obtained from the Monte-Carlo simulation with the analytic solution using Black-Scholes formula:

JShell: (continued)

import net.finmath.functions.AnalyticFormulas;

AnalyticFormulas.blackScholesOptionValue(modelInitialValue, modelRiskFreeRate, modelVolatility, maturity, strike);

The value reported is 17.984... .

## Summary (Experiments 1-3)

We have created a simulation, calculated the value of a European option.

## Where to continue

You may continue with