Checkout finmath-experiments from git and run maven (mvn
or mvnw
) from
its directory. This will start a JShell.
See Getting Started for details.
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.
var td = new net.finmath.time.TimeDiscretizationFromArray(0.0, 100, 0.1);
td.toString();
net.finmath.time
via import net.finmath.time.*;
.
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:
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);
x
enter
var plot = Plots.createHistogram(x, 100, 5.0);
plot.setTitle("Histogram").setXAxisLabel("value").setYAxisLabel("frequency");
plot.show();
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);
Thread.sleep(100);
}
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
.
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();
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
import net.finmath.montecarlo.assetderivativevaluation.products.*;
double maturity = 3.0;
double strike = 106.0;
var europeanOption = new EuropeanOption(maturity, strike);
process
and europeanOption
have been initialized, we can value the product against the simulation:
// 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();
18.115...
. Request the standard error via
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
:
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();
We may compare the value obtained from the Monte-Carlo simulation with the analytic solution using Black-Scholes formula:
import net.finmath.functions.AnalyticFormulas;
AnalyticFormulas.blackScholesOptionValue(modelInitialValue, modelRiskFreeRate, modelVolatility, maturity, strike);