/* *
* 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 variance gamma (VG) process
*
* {S(t) = X(t;θ, σ, ν) : t >= 0}. This process is
* obtained as a subordinate of the Brownian motion process
* B(t;θ, σ)
* using the operational time
* G(t;1, ν) (see):
*
*
* See also for applications to modelling
* asset returns and option pricing.
*
*
* The process is sampled as follows: when generatePath() is called, the method
* generatePath() of the inner {@link GammaProcess} is called;
* its path is then used to set the observation times of the
* {@link BrownianMotion}. Finally, the method generatePath() of
* the {@link BrownianMotion} is called.
* Warning: If one wants to reduced the variance as much as possible
* in a QMC simulation, this way of proceeding is not optimal. Use
* the method generatePath(uniform01) instead.
*
*
* If one calls the nextObservation method, the operational
* time is generated first, followed by the corresponding
* brownian motion increment, which is then returned.
*
*
* Note that if one wishes to use bridge sampling with the
* nextObservation method, both the gamma process G
* and the Brownian motion process B should use bridge sampling so that
* their observations are synchronized.
*
*/
public class VarianceGammaProcess extends StochasticProcess {
protected GammaProcess randomTime; // For the transformed time method
protected BrownianMotion BM;
protected double theta,
sigma,
nu;
public VarianceGammaProcess() {}
/**
* Constructs a new VarianceGammaProcess with parameters
*
* θ = theta ,
* σ = sigma ,
* ν = nu
* and initial value
* S(t0) = s0 .
* stream is used to generate both the {@link BrownianMotion} B and the
* {@link GammaProcess} G in.
*
*/
public VarianceGammaProcess (double s0, double theta, double sigma,
double nu, RandomStream stream) {
this (s0, new BrownianMotion (s0, theta, sigma, stream),
new GammaProcess (0.0, 1.0, nu, stream));
}
/**
* Constructs a new VarianceGammaProcess.
* The parameters θ and σ are set to the parameters μ and
* σ, respectively, of the {@link BrownianMotion} BM and
* the parameter ν is set to the parameter ν of the {@link GammaProcess}
* Gamma. The parameters μ and x0 of the {@link GammaProcess} are
* overwritten to equal 1 and 0 respectively.
* The initial value of the process is
* S(t0) =
.
*
*/
public VarianceGammaProcess (double s0, BrownianMotion BM,
GammaProcess Gamma) {
this.BM = BM;
Gamma.setParams(0.0, 1.0, Gamma.getNu()); // forces the average of the GammaProcess
randomTime = Gamma; // to be 1.0 and the initial value to be 0.0
setParams (s0, BM.getMu(), BM.getSigma(), Gamma.getNu());
}
/**
* Generates the observation for the next time.
* It also works with bridge sampling; however both
* {@link BrownianMotionBridge} and {@link GammaProcessBridge}
* must be used in the constructor in that case. Furthermore, for bridge
* sampling, the order of the observations is that of the bridge,
* not sequential order.
*
*/
public double nextObservation() {
// We first generate w, then verify what its new counter value is
// This is necessary to be general enough to handle bridge sampling
double nextBM = BM.nextObservation (randomTime.nextObservation ());
observationIndex = BM.getCurrentObservationIndex();
path[observationIndex] = nextBM;
observationCounter++;
return nextBM;
}
/**
* Generates and returns the path. To do so, it
* first generates the complete path of the inner {@link GammaProcess}
* and sets the observation times of the inner {@link BrownianMotion}
* to this path. This method is not optimal to reduce the variance in
* QMC simulations; use generatePath(double[] uniform01) for that.
*
*/
public double[] generatePath() {
BM.setObservationTimes(randomTime.generatePath(), d);
path = BM.generatePath();
observationIndex = d;
observationCounter = d;
return path;
}
/**
* Similar to the usual generatePath(), but here the uniform
* random numbers used for the simulation must be provided to the method. This
* allows to properly use the uniform random variates in QMC simulations.
* This method divides the table of uniform random
* numbers uniform01 in two smaller tables, the first one, containing the
* odd indices of uniform01 which are used to generate the path of the inner
* {@link GammaProcess}, and the even indices (in the second table) are used to
* generate the path of the inner {@link BrownianMotion}. This way of proceeding
* reduces the variance as much as possible for QMC simulations.
*
*/
public double[] generatePath (double[] uniform01) {
int dd = uniform01.length;
int d = dd / 2;
if (dd % 2 != 0) {
throw new IllegalArgumentException (
"The Array uniform01 must have a even length");
}
double[] QMCpointsGP = new double[d];
double[] QMCpointsBM = new double[d];
for(int i = 0; i < d; i++){
QMCpointsGP[i] = uniform01[2 * i]; // the odd numbers for the gamma process
QMCpointsBM[i] = uniform01[2 * i + 1]; // and the even for the BM process
}
BM.setObservationTimes(randomTime.generatePath(QMCpointsGP), d);
path = BM.generatePath(QMCpointsBM);
observationIndex = d;
observationCounter = d;
return path;
}
/**
* Resets the observation index and counter to 0 and
* applies the resetStartProcess method to the
* {@link BrownianMotion} and the {@link GammaProcess} objects
* used to generate this process.
*
*/
public void resetStartProcess() {
observationIndex = 0;
observationCounter = 0;
BM.resetStartProcess();
randomTime.resetStartProcess();
}
/**
* Sets the parameters
*
* S(t0) = s0, θ = theta, σ = sigma
* and ν = nu of the process.
* Warning: This method will recompute some quantities stored internally,
* which may be slow if called repeatedly.
*
*/
public void setParams (double s0, double theta, double sigma, double nu) {
this.x0 = s0;
this.theta = theta;
this.sigma = sigma;
this.nu = nu;
if (observationTimesSet) init(); // Otherwise no need to.
}
/**
* Returns the value of the parameter θ.
*
*/
public double getTheta() { return theta; }
/**
* Returns the value of the parameter σ.
*
*/
public double getSigma() { return sigma; }
/**
* Returns the value of the parameter ν.
*
*/
public double getNu() { return nu; }
protected void init() {
super.init();
if(observationTimesSet){
randomTime.setObservationTimes(t, d);
randomTime.x0 = t[0];
}
}
/**
* Sets the observation times on the VarianceGammaProcess as
* usual, but also sets the observation times of the underlying
* {@link GammaProcess}. It furthermore sets the starting value
* of the {@link GammaProcess} to t[0].
*
*/
public void setObservationTimes (double t[], int d) {
super.setObservationTimes(t, d); //sets the observation times of the GammaProcess by
} //calling init()
/**
* Resets the {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream}'s.
* Warning: this method sets both the
* {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream} of the
* {@link BrownianMotion} and of the {@link GammaProcess} to
* the same {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream}.
*
*/
public void setStream (RandomStream stream) {
BM.setStream (stream);
}
/**
* Returns the random stream of the {@link BrownianMotion} process, which should
* be the same as for the {@link GammaProcess}.
*
*/
public RandomStream getStream() {
return BM.getStream();
}
/**
* Returns a reference to the inner {@link BrownianMotion}.
*
*/
public BrownianMotion getBrownianMotion() {
return BM;
}
/**
* Returns a reference to the inner {@link GammaProcess}.
*
*/
public GammaProcess getGammaProcess() {
return randomTime;
}
}
Ads help maintain this website.