/* *
 * Title:        

* Description:

* Copyright: Copyright (c)

* Company:

* @author * @version 1.0 */ package umontreal.iro.lecuyer.stochprocess; import umontreal.iro.lecuyer.rng.*; import umontreal.iro.lecuyer.probdist.*; import umontreal.iro.lecuyer.randvar.*; /** * This class represents a Brownian motion process * {X(t) : t >= 0}, * sampled at times * 0 = t0 < t1 < ... < td. * This process obeys the stochastic differential equation *

*

*
* dX(t) = μdt + σdB(t), *

* with initial condition X(0) = x0, * where μ and σ are the drift and volatility parameters, * and * {B(t), t >= 0} is a standard Brownian motion * (with drift 0 and volatility 1). * This process has stationary and independent increments over disjoint * time intervals (it is a Lévy process) and the increment over an interval * of length t is normally distributed with mean μt and variance * σ2t. * *

* In this class, this process is generated using the sequential (or random walk) * technique: X(0) = x0 and *

*

*
* X(tj) - X(tj-1) = μ(tj - tj-1) + σ(t_j - t_j-1)1/2Zj *

* where * Zj∼N(0, 1). * */ public class BrownianMotion extends StochasticProcess { protected NormalGen gen; protected double mu, sigma; // Precomputed values for standard BM protected double[] mudt, sigmasqrdt; /** * Constructs a new BrownianMotion with * parameters μ = mu, σ = sigma and initial value * * X(t0) = x0. * The normal variates Zj in will be * generated by inversion using stream. * */ public BrownianMotion (double x0, double mu, double sigma, RandomStream stream) { this (x0, mu, sigma, new NormalGen (stream)); } /** * Constructs a new BrownianMotion with parameters μ = * mu, σ = sigma and initial value * X(t0) = x0. * Here, the normal variate generator * {@link umontreal.iro.lecuyer.randvar.NormalGen NormalGen} is specified * directly instead of specifying the stream and using inversion. * The normal generator gen can use another method than inversion. * */ public BrownianMotion (double x0, double mu, double sigma, NormalGen gen) { this.mu = mu; this.sigma = sigma; this.x0 = x0; this.gen = gen; } public double nextObservation() { double x = path[observationIndex]; x += mudt[observationIndex] + sigmasqrdt[observationIndex] * gen.nextDouble(); observationIndex++; path[observationIndex] = x; return x; } /** * Generates and returns the next observation at time tj+1 = * nextTime. It uses the previous observation time tj defined earlier * (either by this method or by setObservationTimes), * as well as the value of the previous observation X(tj). * Warning: This method will reset the observations time tj+1 * for this process to nextTime. The user must make sure that * the tj+1 supplied is *  >= tj. * */ public double nextObservation (double nextTime) { // This method is useful for generating variance gamma processes double x = path[observationIndex]; double previousTime = t[observationIndex]; observationIndex++; t[observationIndex] = nextTime; double dt = nextTime - previousTime; x += mu * dt + sigma * Math.sqrt (dt) * gen.nextDouble(); path[observationIndex] = x; return x; } /** * Generates an observation of the process in dt time units, * assuming that the process has value x at the current time. * Uses the process parameters specified in the constructor. * Note that this method does not affect the sample path of the process * stored internally (if any). * */ public double nextObservation (double x, double dt) { x += mu * dt + sigma * Math.sqrt (dt) * gen.nextDouble(); return x; } public double[] generatePath() { double x = x0; for (int j = 0; j < d; j++) { x += mudt[j] + sigmasqrdt[j] * gen.nextDouble(); path[j + 1] = x; } observationIndex = d; observationCounter = d; return path; } /** * Same as generatePath(), but a vector of uniform random numbers * must be provided to the method. These uniform random numbers are used * to generate the path. * */ public double[] generatePath (double[] uniform01) { double x = x0; for (int j = 0; j < d; j++) { x += mudt[j] + sigmasqrdt[j] * NormalDist.inverseF01(uniform01[j]); path[j + 1] = x; } observationIndex = d; observationCounter = d; return path; } public double[] generatePath (RandomStream stream) { gen.setStream (stream); return generatePath(); } /** * Resets the parameters * X(t0) = x0, * μ = mu and * * σ = sigma of the process. * Warning: This method will recompute some quantities stored internally, * which may be slow if called too frequently. * */ public void setParams (double x0, double mu, double sigma) { this.x0 = x0; this.mu = mu; if (sigma <= 0) throw new IllegalArgumentException ("sigma <= 0"); this.sigma = sigma; if (observationTimesSet) init(); // Otherwise not needed. } /** * Resets the random stream of the normal generator to stream. * */ public void setStream (RandomStream stream) { gen.setStream (stream); } /** * Returns the random stream of the normal generator. * */ public RandomStream getStream() { return gen.getStream (); } /** * Returns the value of μ. * */ public double getMu() { return mu; } /** * Returns the value of σ. * */ public double getSigma() { return sigma; } /** * Returns the normal random variate generator used. * The {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream} * used by that generator can be changed via * getGen().setStream(stream), for example. * */ public NormalGen getGen() { return gen; } // This is called by setObservationTimes to precompute constants // in order to speed up the path generation. protected void init() { super.init(); mudt = new double[d]; sigmasqrdt = new double[d]; for (int j = 0; j < d; j++) { double dt = t[j+1] - t[j]; mudt[j] = mu * dt; sigmasqrdt[j] = sigma * Math.sqrt (dt); } } }

Ads help maintain this website.