/* *
* 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 generated using difference of gamma sampling
* (see), which uses the representation of the VG process
* as the difference of two independent {@link GammaProcess}'es (see):
*
*
* where X(0) is a constant corresponding to the initial value of the process
* and
*
*
*
* μp
* =
* (( &thetas;^2 + 2σ^2/ν)1/2 + θ)/2
*
* μn
* =
* (( &thetas;^2 + 2σ^2/ν)1/2 - θ)/2
*
* νp
* =
* νμp2
*
* νn
* =
* νμn2
*
*
*
*
*/
public class VarianceGammaProcessDiff extends VarianceGammaProcess {
protected GammaProcess gpos;
protected GammaProcess gneg;
protected double mup, mun,
nup, nun;
/**
* Constructs a new VarianceGammaProcessDiff with parameters
*
* θ = theta ,
* σ = sigma ,
* ν = nu
* and initial value
* S(t0) = s0 . stream is
* used by two instances of {@link GammaProcess},
* Γ+ and
* Γ-,
* respectively. The other parameters are
* as in the class {@link VarianceGammaProcess}.
* The {@link GammaProcess} objects for
* Γ+ and
* Γ- are
* constructed using the parameters from and their
* initial values
* Γ+(t0) and
* Γ-(t0) are set to 0.
*
*/
public VarianceGammaProcessDiff (double s0, double theta, double sigma,
double nu, RandomStream stream) {
this (s0, theta, sigma, nu,
new GammaProcess (0.0, 1.0, 1.0, stream),
new GammaProcess (0.0, 1.0, 1.0, stream));
// Params mu, nu of the 2 gamma processes are redefined in init()
// which will be called after a call to 'setObservTimes'
}
/**
* The parameters of the {@link GammaProcess}
* objects for
* Γ+ and
* Γ- are
* set to those of and their
* initial values
* Γ+(t0) and
* Γ-(t0) are set to t0.
* The RandomStream of the
* Γ- process is overwritten with the
* RandomStream of the
* Γ+ process.
*
*/
public VarianceGammaProcessDiff (double s0, double theta, double sigma,
double nu, GammaProcess gpos,
GammaProcess gneg) {
this.gpos = gpos;
this.gneg = gneg;
setParams (s0, theta, sigma, nu);
gneg.setStream(gpos.getStream()); // to avoid confusion with stream because there is only
// one stream in the other constructor
}
public double nextObservation() {
// This implementation takes possible bridge sampling into account
double s = x0 + gpos.nextObservation() - gneg.nextObservation();
observationIndex = gpos.getCurrentObservationIndex();
path[observationIndex] = s;
observationCounter++;
return s;
}
// no longer useful, this method was created to automaticaly alternate
// between the two processes the uniform random variables used in the
// in the simulation. However, this method does not work if the two
// GammaProcess are PCA...
// public double[] generatePath() {
// gpos.resetStartProcess();
// gneg.resetStartProcess();
// double s;
// for (int i=1; i<=d; i++) {
// s = x0 + gpos.nextObservation() - gneg.nextObservation();
// path[gpos.getCurrentObservationIndex()] = s;
// // Note: we must get the observCounter from gpos in the case that
// // the process is generated by a Gamma bridge
// // The observCounter of gneg should be the same because both
// // gamma processes should be generated the same way
// }
// observationIndex = d;
// observationCounter = d;
// return path;
// }
/**
* Generates, returns and saves the path. To do so, the
* path of
* Γ+ is first generated and then the path
* of
* Γ-. This is not the optimal way of proceeding
* in order to reduce the variance in QMC simulations; for that,
* use generatePath(double[] uniform01) instead.
*
*/
public double[] generatePath() {
double[] pathUP = gpos.generatePath();
double[] pathDOWN = gneg.generatePath();
for (int i=0; igeneratePath(), 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 are used to generate the path of
* Γ+
* and the even indices are used to generate the path of
* Γ-.
* This way of proceeding further reduces the
* variance 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[] QMCpointsUP = new double[d];
double[] QMCpointsDW = new double[d];
for(int i = 0; i < d; i++){
QMCpointsUP[i] = uniform01[2*i]; // keeps the odd numbers for the gamma process
QMCpointsDW[i] = uniform01[2*i + 1]; // and the even for the BM process
}
gpos.resetStartProcess();
gneg.resetStartProcess();
double[] pathUP = gpos.generatePath(QMCpointsUP);
double[] pathDOWN = gneg.generatePath(QMCpointsDW);
for (int i=0; iVarianceGammaProcessDiff
* as usual, but also applies the resetStartProcess method to the two
* {@link GammaProcess} objects used to generate this process.
*
*/
public void resetStartProcess() {
observationIndex = 0;
observationCounter = 0;
gpos.resetStartProcess();
gneg.resetStartProcess();
}
/**
* Returns a reference to the {@link GammaProcess} object gpos
* used to generate the
* Γ+ component of the process.
*
*/
public GammaProcess getGpos() {
return gpos;
}
/**
* Returns a reference to the {@link GammaProcess} object gneg
* used to generate the
* Γ- component of the process.
*
*/
public GammaProcess getGneg() {
return gneg;
}
protected void init() {
// super.init() is not called because the init() in VarianceGammaProcess
// is very different.
mup = 0.5 * (Math.sqrt (theta*theta + 2*sigma*sigma/nu) + theta);
mun = 0.5 * (Math.sqrt (theta*theta + 2*sigma*sigma/nu) - theta);
nup = mup * mup * nu;
nun = mun * mun * nu;
if (observationTimesSet) {
path[0] = x0;
gpos.setParams(t[0], mup, nup);
gneg.setParams(t[0], mun, nun);
}
}
/**
* Sets the observation times on the VarianceGammaProcesDiff
* as usual, but also sets the observation times of the underlying
* {@link GammaProcess}'es.
*
*/
public void setObservationTimes (double t[], int d) {
gpos.setObservationTimes(t, d);
gneg.setObservationTimes(t, d);
super.setObservationTimes(t, d);
// the initial value is set to t[0] in the init, which is called in
// super.setObservationTimes(t, d).
}
/**
* Returns the RandomStream of the
* Γ+ process.
*
*/
public RandomStream getStream() {
return gpos.getStream ();
}
/**
* Sets the {@link umontreal.iro.lecuyer.rng.RandomStream RandomStream}
* of the two {@link GammaProcess}'es to stream.
*
*/
public void setStream (RandomStream stream) {
gpos.setStream(stream);
gneg.setStream(stream);
}
}
Ads help maintain this website.