net.finmath.montecarlo.RandomVariableFromFloatArray Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of finmath-lib Show documentation
Show all versions of finmath-lib Show documentation
finmath lib is a Mathematical Finance Library in Java.
It provides algorithms and methodologies related to mathematical finance.
/*
* (c) Copyright Christian P. Fries, Germany. Contact: [email protected].
*
* Created on 09.02.2006
*/
package net.finmath.montecarlo;
import java.util.Arrays;
import java.util.List;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleSupplier;
import java.util.function.DoubleUnaryOperator;
import java.util.function.IntConsumer;
import java.util.function.IntToDoubleFunction;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import net.finmath.functions.DoubleTernaryOperator;
import net.finmath.stochastic.ConditionalExpectationEstimator;
import net.finmath.stochastic.RandomVariable;
/**
* The class RandomVariableFromFloatArray represents a random variable being the evaluation of a stochastic process
* at a certain time within a Monte-Carlo simulation.
* It is thus essentially a vector of floating point numbers - the realizations - together with a double - the time.
* The index of the vector represents path.
* The class may also be used for non-stochastic quantities which may potentially be stochastic
* (e.g. volatility). If only non-stochastic random variables are involved in an operation the class uses
* optimized code.
*
* Accesses performed exclusively through the interface
* RandomVariable
is thread safe (and does not mutate the class).
*
* This implementation uses floats for the realizations (consuming less memory compared to using doubles). However,
* the calculation of the average is performed using double precision.
*
* @author Christian Fries
* @version 1.8
*/
public class RandomVariableFromFloatArray implements RandomVariable {
private static final long serialVersionUID = -1352953450936857742L;
private static final int typePriorityDefault = 1;
private final int typePriority;
private final double time; // Time (filtration)
// Data model for the stochastic case (otherwise null)
private final float[] realizations; // Realizations
// Data model for the non-stochastic case (if realizations==null)
private final double valueIfNonStochastic;
/**
* Create a random variable from a given other implementation of RandomVariable
.
*
* @param value Object implementing RandomVariable
.
*/
public RandomVariableFromFloatArray(final RandomVariable value) {
super();
time = value.getFiltrationTime();
realizations = value.isDeterministic() ? null : getFloatArray(value.getRealizations());
valueIfNonStochastic = value.isDeterministic() ? value.doubleValue() : Double.NaN;
typePriority = typePriorityDefault;
}
/**
* Create a non stochastic random variable, i.e. a constant.
*
* @param value the value, a constant.
*/
public RandomVariableFromFloatArray(final double value) {
this(Double.NEGATIVE_INFINITY, value, typePriorityDefault);
}
/**
* Create a random variable by applying a function to a given other implementation of RandomVariable
.
*
* @param value Object implementing RandomVariable
.
* @param function A function mapping double to double.
*/
public RandomVariableFromFloatArray(final RandomVariable value, final DoubleUnaryOperator function) {
super();
time = value.getFiltrationTime();
realizations = value.isDeterministic() ? null : getFloatArray(value.getRealizationsStream().map(function).toArray());
valueIfNonStochastic = value.isDeterministic() ? function.applyAsDouble(value.get(0)) : Double.NaN;
typePriority = typePriorityDefault;
}
/**
* Create a non stochastic random variable, i.e. a constant.
*
* @param time the filtration time, set to 0.0 if not used.
* @param value the value, a constant.
* @param typePriority The priority of this type in construction of result types. See "operator type priority" for details.
*/
public RandomVariableFromFloatArray(final double time, final double value, final int typePriority) {
super();
this.time = time;
realizations = null;
valueIfNonStochastic = value;
this.typePriority = typePriority;
}
/**
* Create a non stochastic random variable, i.e. a constant.
*
* @param time the filtration time, set to 0.0 if not used.
* @param value the value, a constant.
*/
public RandomVariableFromFloatArray(final double time, final double value) {
this(time, value, typePriorityDefault);
}
/**
* Create a non stochastic random variable, i.e. a constant.
*
* @param time the filtration time, set to 0.0 if not used.
* @param newRealizations the value, a constant.
*/
public RandomVariableFromFloatArray(final double time, final float[] newRealizations) {
this(time, newRealizations, typePriorityDefault);
}
/**
* Create a non stochastic random variable, i.e. a constant.
*
* @param time the filtration time, set to 0.0 if not used.
* @param numberOfPath The number of paths.
* @param value the value, a constant.
*/
@Deprecated
public RandomVariableFromFloatArray(final double time, final int numberOfPath, final double value) {
super();
this.time = time;
realizations = new float[numberOfPath];
java.util.Arrays.fill(realizations, (float)value);
valueIfNonStochastic = Double.NaN;
typePriority = typePriorityDefault;
}
/**
* Create a stochastic random variable.
*
* Important: The realizations array is not cloned (no defensive copy is made).
*
* @TODO A future version should perform a defensive copy.
*
* @param time the filtration time, set to 0.0 if not used.
* @param realisations the vector of realizations.
* @param typePriority The priority of this type in construction of result types. See "operator type priority" for details.
*/
public RandomVariableFromFloatArray(final double time, final float[] realisations, final int typePriority) {
super();
this.time = time;
realizations = realisations;
valueIfNonStochastic = Double.NaN;
this.typePriority = typePriority;
}
/**
* Create a stochastic random variable.
*
* Important: The realizations array is not cloned (not defensive copy is made).
*
* @TODO A future version should perform a defensive copy.
*
* @param time the filtration time, set to 0.0 if not used.
* @param realisations the vector of realizations.
*/
public RandomVariableFromFloatArray(final double time, final double[] realisations) {
this(time, getFloatArray(realisations), typePriorityDefault);
}
/**
* Create a stochastic random variable.
*
* @param time the filtration time, set to 0.0 if not used.
* @param realizations A map mapping integer (path or state) to double, representing this random variable.
* @param size The size, i.e., number of paths.
* @param typePriority The priority of this type in construction of result types. See "operator type priority" for details.
*/
public RandomVariableFromFloatArray(final double time, final IntToDoubleFunction realizations, final int size, final int typePriority) {
super();
this.time = time;
this.realizations = size == 1 ? null : new float[size];//IntStream.range(0,size).parallel().mapToDouble(realisations).toArray();
valueIfNonStochastic = size == 1 ? realizations.applyAsDouble(0) : Double.NaN;
if(size > 1) {
IntStream.range(0,size).parallel().forEach(new IntConsumer() {
@Override
public void accept(final int i) {
RandomVariableFromFloatArray.this.realizations[i] = (float) realizations.applyAsDouble(i);
}
}
);
}
this.typePriority = typePriority;
}
/**
* Create a stochastic random variable.
*
* @param time the filtration time, set to 0.0 if not used.
* @param realizations A map mapping integer (path or state) to double, representing this random variable.
* @param size The size, i.e., number of paths.
*/
public RandomVariableFromFloatArray(final double time, final IntToDoubleFunction realizations, final int size) {
this(time, realizations, size, typePriorityDefault);
}
private static float[] getFloatArray(final double[] arrayOfDouble) {
final float[] arrayOfFloat = new float[arrayOfDouble.length];
for(int i=0; i quantileEnd) {
return getQuantileExpectation(quantileEnd, quantileStart);
}
final float[] realizationsSorted = realizations.clone();
java.util.Arrays.sort(realizationsSorted);
final int indexOfQuantileValueStart = Math.min(Math.max((int)Math.round((size()+1) * quantileStart - 1), 0), size()-1);
final int indexOfQuantileValueEnd = Math.min(Math.max((int)Math.round((size()+1) * quantileEnd - 1), 0), size()-1);
double quantileExpectation = 0.0;
for (int i=indexOfQuantileValueStart; i<=indexOfQuantileValueEnd;i++) {
quantileExpectation += realizationsSorted[i];
}
quantileExpectation /= indexOfQuantileValueEnd-indexOfQuantileValueStart+1;
return quantileExpectation;
}
@Override
public double[] getHistogram(final double[] intervalPoints)
{
final double[] histogramValues = new double[intervalPoints.length+1];
if(isDeterministic()) {
/*
* If the random variable is deterministic we will return an array
* consisting of 0's and one and only one 1.
*/
java.util.Arrays.fill(histogramValues, 0.0);
for (int intervalIndex=0; intervalIndex intervalPoints[intervalIndex]) {
histogramValues[intervalIndex] = 1.0;
break;
}
}
histogramValues[intervalPoints.length] = 1.0;
}
else {
/*
* If the random variable is deterministic we will return an array
* representing a density, where the sum of the entries is one.
* There is one exception:
* If the size of the random variable is 0, all entries will be zero.
*/
final float[] realizationsSorted = realizations.clone();
java.util.Arrays.sort(realizationsSorted);
int sampleIndex=0;
for (int intervalIndex=0; intervalIndex 0) {
for(int i=0; i this.getTypePriority()) {
// Check type priority
return randomVariable.add(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
final double newValueIfNonStochastic = valueIfNonStochastic + randomVariable.get(0);
return new RandomVariableFromFloatArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
final float[] newRealizations = new float[Math.max(size(), randomVariable.size())];
for(int i=0; i this.getTypePriority()) {
// Check type priority
return randomVariable.bus(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
final double newValueIfNonStochastic = valueIfNonStochastic - randomVariable.get(0);
return new RandomVariableFromFloatArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
final float[] newRealizations = new float[Math.max(size(), randomVariable.size())];
for(int i=0; i this.getTypePriority()) {
// Check type priority
return randomVariable.sub(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
final double newValueIfNonStochastic = randomVariable.get(0) - valueIfNonStochastic;
return new RandomVariableFromFloatArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
final float[] newRealizations = new float[Math.max(size(), randomVariable.size())];
for(int i=0; i this.getTypePriority()) {
// Check type priority
return randomVariable.mult(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
final double newValueIfNonStochastic = valueIfNonStochastic * randomVariable.get(0);
return new RandomVariableFromFloatArray(newTime, newValueIfNonStochastic);
}
else if(randomVariable.isDeterministic()) {
return this.mult(randomVariable.get(0));
} else if(isDeterministic()) {
final float[] newRealizations = new float[Math.max(size(), randomVariable.size())];
for(int i=0; i this.getTypePriority()) {
// Check type priority
return randomVariable.vid(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
final double newValueIfNonStochastic = valueIfNonStochastic / randomVariable.get(0);
return new RandomVariableFromFloatArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
final float[] newRealizations = new float[Math.max(size(), randomVariable.size())];
for(int i=0; i this.getTypePriority()) {
// Check type priority
return randomVariable.div(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
final double newValueIfNonStochastic = randomVariable.get(0) / valueIfNonStochastic;
return new RandomVariableFromFloatArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
final float[] newRealizations = new float[Math.max(size(), randomVariable.size())];
for(int i=0; i this.getTypePriority()) {
// Check type priority
return randomVariable.cap(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
final double newValueIfNonStochastic = Math.min(valueIfNonStochastic, randomVariable.get(0));
return new RandomVariableFromFloatArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
final float[] newRealizations = new float[Math.max(size(), randomVariable.size())];
for(int i=0; i this.getTypePriority()) {
// Check type priority
return randomVariable.floor(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
final double newValueIfNonStochastic = Math.max(valueIfNonStochastic, randomVariable.get(0));
return new RandomVariableFromFloatArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
final float[] newRealizations = new float[Math.max(size(), randomVariable.size())];
for(int i=0; i this.getTypePriority()) {
// Check type priority
return rate.mult(periodLength).add(1.0).mult(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(time, rate.getFiltrationTime());
if(rate.isDeterministic()) {
return this.mult(1.0 + rate.get(0) * periodLength);
} else if(isDeterministic() && !rate.isDeterministic()) {
final float[] newRealizations = new float[Math.max(size(), rate.size())];
for(int i=0; i this.getTypePriority()) {
// Check type priority
return rate.mult(periodLength).add(1.0).vid(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(time, rate.getFiltrationTime());
if(rate.isDeterministic()) {
return this.div(1.0 + rate.doubleValue() * periodLength);
} else if(isDeterministic() && !rate.isDeterministic()) {
final float[] newRealizations = new float[Math.max(size(), rate.size())];
for(int i=0; i= 0) {
return valueIfTriggerNonNegative;
} else {
return valueIfTriggerNegative;
}
}
else {
final int numberOfPaths = this.size();
final float[] newRealizations = new float[numberOfPaths];
for(int i=0; i= 0.0 ? valueIfTriggerNonNegative.get(i) : valueIfTriggerNegative.get(i));
}
return new RandomVariableFromFloatArray(newTime, newRealizations);
}
}
@Override
public RandomVariable addProduct(final RandomVariable factor1, final double factor2) {
if(factor1.getTypePriority() > this.getTypePriority()) {
// Check type priority
return factor1.mult(factor2).add(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(time, factor1.getFiltrationTime());
if(factor1.isDeterministic()) {
return this.add(factor1.get(0) * factor2);
} else if(isDeterministic() && !factor1.isDeterministic()) {
final float[] newRealizations = new float[Math.max(size(), factor1.size())];
for(int i=0; i this.getTypePriority() || factor2.getTypePriority() > this.getTypePriority()) {
// Check type priority
return factor1.mult(factor2).add(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(Math.max(time, factor1.getFiltrationTime()), factor2.getFiltrationTime());
if(isDeterministic() && factor1.isDeterministic() && factor2.isDeterministic()) {
final double newValueIfNonStochastic = valueIfNonStochastic + (factor1.doubleValue() * factor2.doubleValue());
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(factor1.isDeterministic() && factor2.isDeterministic()) {
return add(factor1.doubleValue() * factor2.doubleValue());
}
else if(factor2.isDeterministic()) {
return this.addProduct(factor1, factor2.doubleValue());
}
else if(factor1.isDeterministic()) {
return this.addProduct(factor2, factor1.doubleValue());
}
else if(!this.isDeterministic() && !factor1.isDeterministic() && !factor2.isDeterministic()) {
final float[] newRealizations = new float[Math.max(Math.max(size(), factor1.size()), factor2.size())];
for(int i=0; i factor1, final List factor2)
{
RandomVariable result = this;
for(int i=0; i this.getTypePriority() || denominator.getTypePriority() > this.getTypePriority()) {
// Check type priority
return numerator.div(denominator).add(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(Math.max(time, numerator.getFiltrationTime()), denominator.getFiltrationTime());
if(isDeterministic() && numerator.isDeterministic() && denominator.isDeterministic()) {
final double newValueIfNonStochastic = valueIfNonStochastic + (numerator.get(0) / denominator.get(0));
return new RandomVariableFromFloatArray(newTime, newValueIfNonStochastic);
}
else {
final float[] newRealizations = new float[Math.max(Math.max(size(), numerator.size()), denominator.size())];
for(int i=0; i this.getTypePriority() || denominator.getTypePriority() > this.getTypePriority()) {
// Check type priority
return numerator.div(denominator).mult(-1).add(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
final double newTime = Math.max(Math.max(time, numerator.getFiltrationTime()), denominator.getFiltrationTime());
if(isDeterministic() && numerator.isDeterministic() && denominator.isDeterministic()) {
final double newValueIfNonStochastic = valueIfNonStochastic - (numerator.get(0) / denominator.get(0));
return new RandomVariableFromFloatArray(newTime, newValueIfNonStochastic);
}
else {
final float[] newRealizations = new float[Math.max(Math.max(size(), numerator.size()), denominator.size())];
for(int i=0; i