net.finmath.montecarlo.RandomVariableFromDoubleArray 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.DoubleUnaryOperator;
import java.util.function.IntToDoubleFunction;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import org.apache.commons.math3.util.FastMath;
import net.finmath.functions.DoubleTernaryOperator;
import net.finmath.stochastic.ConditionalExpectationEstimator;
import net.finmath.stochastic.RandomVariable;
/**
* The class RandomVariableFromDoubleArray 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 doubles - 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).
*
* The implementation requires Java 8 or better.
*
* @author Christian Fries
* @version 2.1
*/
public class RandomVariableFromDoubleArray 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 double[] 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 RandomVariableFromDoubleArray(RandomVariable value) {
super();
this.time = value.getFiltrationTime();
this.realizations = value.isDeterministic() ? null : value.getRealizations();
this.valueIfNonStochastic = value.isDeterministic() ? value.get(0) : Double.NaN;
this.typePriority = typePriorityDefault;
}
/**
* Create a non stochastic random variable, i.e. a constant.
*
* @param value the value, a constant.
*/
public RandomVariableFromDoubleArray(double value) {
this(Double.NEGATIVE_INFINITY, value);
}
/**
* 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 RandomVariableFromDoubleArray(RandomVariable value, DoubleUnaryOperator function) {
super();
this.time = value.getFiltrationTime();
this.realizations = value.isDeterministic() ? null : value.getRealizationsStream().map(function).toArray();
this.valueIfNonStochastic = value.isDeterministic() ? function.applyAsDouble(value.get(0)) : Double.NaN;
this.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 RandomVariableFromDoubleArray(double time, double value, int typePriority) {
super();
this.time = time;
this.realizations = null;
this.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 RandomVariableFromDoubleArray(double time, 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 numberOfPath The number of paths.
* @param value the value, a constant.
*/
@Deprecated
public RandomVariableFromDoubleArray(double time, int numberOfPath, double value) {
super();
this.time = time;
this.realizations = new double[numberOfPath];
java.util.Arrays.fill(this.realizations, value);
this.valueIfNonStochastic = Double.NaN;
this.typePriority = typePriorityDefault;
}
/**
* 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.
* @param typePriority The priority of this type in construction of result types. See "operator type priority" for details.
*/
public RandomVariableFromDoubleArray(double time, double[] realisations, int typePriority) {
super();
this.time = time;
this.realizations = realisations;
this.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 RandomVariableFromDoubleArray(double time, double[] realisations) {
this(time, 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 RandomVariableFromDoubleArray(double time, IntToDoubleFunction realizations, int size, int typePriority) {
super();
this.time = time;
this.realizations = size == 1 ? null : new double[size];//IntStream.range(0,size).parallel().mapToDouble(realisations).toArray();
this.valueIfNonStochastic = size == 1 ? realizations.applyAsDouble(0) : Double.NaN;
if(size > 1) {
IntStream.range(0,size).parallel().forEach(i ->
this.realizations[i] = 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 RandomVariableFromDoubleArray(double time, IntToDoubleFunction realizations, int size) {
this(time, realizations, size, typePriorityDefault);
}
@Override
public boolean equals(RandomVariable randomVariable) {
if(this.time != randomVariable.getFiltrationTime()) {
return false;
}
if(this.isDeterministic() && randomVariable.isDeterministic()) {
return this.valueIfNonStochastic == randomVariable.get(0);
}
if(this.isDeterministic() != randomVariable.isDeterministic()) {
return false;
}
for(int i=0; i quantileEnd) {
return getQuantileExpectation(quantileEnd, quantileStart);
}
double[] realizationsSorted = realizations.clone();
java.util.Arrays.sort(realizationsSorted);
int indexOfQuantileValueStart = Math.min(Math.max((int)Math.round((size()+1) * quantileStart - 1), 0), size()-1);
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;
}
/* (non-Javadoc)
* @see net.finmath.stochastic.RandomVariable#getHistogram()
*/
@Override
public double[] getHistogram(double[] intervalPoints)
{
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.
*/
double[] realizationsSorted = realizations.clone();
java.util.Arrays.sort(realizationsSorted);
int sampleIndex=0;
for (int intervalIndex=0; intervalIndex 0) {
for(int i=0; i {
return valueIfNonStochastic;
});
}
else {
return Arrays.stream(realizations);
}
}
@Override
public double[] getRealizations() {
if(isDeterministic()) {
double[] result = new double[1];
result[0] = get(0);
return result;
}
else {
return realizations.clone();
}
}
@Override
public Double doubleValue() {
if(isDeterministic()) {
return valueIfNonStochastic;
} else {
throw new UnsupportedOperationException("The random variable is non-deterministic");
}
}
@Override
public IntToDoubleFunction getOperator() {
if(isDeterministic()) {
return i -> valueIfNonStochastic;
}
else {
return i -> realizations[i];
}
}
@Override
public RandomVariable apply(DoubleUnaryOperator operator) {
if(isDeterministic()) {
return new RandomVariableFromDoubleArray(time, operator.applyAsDouble(valueIfNonStochastic));
}
else
{
// Still faster than a parallel stream (2014.04)
double[] result = new double[this.realizations.length];
for(int i=0; i operator.applyAsDouble(argument0Operator.applyAsDouble(i), argument1Operator.applyAsDouble(i));
return new RandomVariableFromDoubleArray(newTime, result, newSize);
}
@Override
public RandomVariable apply(DoubleTernaryOperator operator, RandomVariable argument1, RandomVariable argument2) {
double newTime = Math.max(time, argument1.getFiltrationTime());
newTime = Math.max(newTime, argument2.getFiltrationTime());
int newSize = Math.max(Math.max(this.size(), argument1.size()), argument2.size());
IntToDoubleFunction argument0Operator = this.getOperator();
IntToDoubleFunction argument1Operator = argument1.getOperator();
IntToDoubleFunction argument2Operator = argument2.getOperator();
IntToDoubleFunction result = i -> operator.applyAsDouble(argument0Operator.applyAsDouble(i), argument1Operator.applyAsDouble(i), argument2Operator.applyAsDouble(i));
return new RandomVariableFromDoubleArray(newTime, result, newSize);
}
public RandomVariable apply(DoubleBinaryOperator operatorOuter, DoubleBinaryOperator operatorInner, RandomVariable argument1, RandomVariable argument2)
{
return apply((x,y,z) -> operatorOuter.applyAsDouble(x,operatorInner.applyAsDouble(y,z)), argument1, argument2);
}
@Override
public RandomVariable cap(double cap) {
if(isDeterministic()) {
double newValueIfNonStochastic = Math.min(valueIfNonStochastic,cap);
return new RandomVariableFromDoubleArray(time, newValueIfNonStochastic);
}
else {
double[] newRealizations = new double[realizations.length];
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.
double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
double newValueIfNonStochastic = valueIfNonStochastic + randomVariable.get(0);
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
double[] newRealizations = new double[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.
double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
double newValueIfNonStochastic = valueIfNonStochastic - randomVariable.get(0);
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
double[] newRealizations = new double[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.
double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
double newValueIfNonStochastic = randomVariable.get(0) - valueIfNonStochastic;
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
double[] newRealizations = new double[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.
double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
double newValueIfNonStochastic = valueIfNonStochastic * randomVariable.get(0);
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(randomVariable.isDeterministic()) {
return this.mult(randomVariable.get(0));
}
else if(isDeterministic()) {
double[] newRealizations = new double[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.
double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
double newValueIfNonStochastic = valueIfNonStochastic / randomVariable.get(0);
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
double[] newRealizations = new double[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.
double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
double newValueIfNonStochastic = randomVariable.get(0) / valueIfNonStochastic;
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
double[] newRealizations = new double[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.
double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
double newValueIfNonStochastic = FastMath.min(valueIfNonStochastic, randomVariable.get(0));
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
double[] newRealizations = new double[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.
double newTime = Math.max(time, randomVariable.getFiltrationTime());
if(isDeterministic() && randomVariable.isDeterministic()) {
double newValueIfNonStochastic = FastMath.max(valueIfNonStochastic, randomVariable.get(0));
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic()) {
double[] newRealizations = new double[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.
double newTime = Math.max(time, rate.getFiltrationTime());
if(isDeterministic() && rate.isDeterministic()) {
double newValueIfNonStochastic = valueIfNonStochastic * (1 + rate.get(0) * periodLength);
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic() && !rate.isDeterministic()) {
double[] rateRealizations = rate.getRealizations();
double[] newRealizations = new double[Math.max(size(), rate.size())];
for(int i=0; i this.getTypePriority()) {
// Check type priority
return rate.mult(periodLength).add(1.0).invert().mult(this);
}
// Set time of this random variable to maximum of time with respect to which measurability is known.
double newTime = Math.max(time, rate.getFiltrationTime());
if(isDeterministic() && rate.isDeterministic()) {
double newValueIfNonStochastic = valueIfNonStochastic / (1 + rate.get(0) * periodLength);
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic() && !rate.isDeterministic()) {
double[] rateRealizations = rate.getRealizations();
double[] newRealizations = new double[Math.max(size(), rate.size())];
for(int i=0; i= 0) return valueIfTriggerNonNegative;
else return valueIfTriggerNegative;
}
else {
int numberOfPaths = this.size();
double[] newRealizations = new double[numberOfPaths];
for(int i=0; i= 0.0 ? valueIfTriggerNonNegative.get(i) : valueIfTriggerNegative.get(i);
}
return new RandomVariableFromDoubleArray(newTime, newRealizations);
}
}
@Override
public RandomVariable invert() {
if(isDeterministic()) {
double newValueIfNonStochastic = 1.0/valueIfNonStochastic;
return new RandomVariableFromDoubleArray(time, newValueIfNonStochastic);
}
else {
double[] newRealizations = new double[realizations.length];
for(int i=0; i 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.
double newTime = Math.max(time, factor1.getFiltrationTime());
if(isDeterministic() && factor1.isDeterministic()) {
double newValueIfNonStochastic = valueIfNonStochastic + (factor1.get(0) * factor2);
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic() && !factor1.isDeterministic()) {
double[] factor1Realizations = factor1.getRealizations();
double[] newRealizations = new double[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.
double newTime = Math.max(Math.max(time, factor1.getFiltrationTime()), factor2.getFiltrationTime());
if(isDeterministic() && factor1.isDeterministic() && factor2.isDeterministic()) {
double newValueIfNonStochastic = valueIfNonStochastic + (factor1.get(0) * factor2.get(0));
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else if(isDeterministic() && !factor1.isDeterministic() && !factor2.isDeterministic()) {
double[] factor1Realizations = factor1.getRealizations();
double[] factor2Realizations = factor2.getRealizations();
double[] newRealizations = new double[Math.max(size(), factor1.size())];
for(int i=0; i factor1, 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.
double newTime = Math.max(Math.max(time, numerator.getFiltrationTime()), denominator.getFiltrationTime());
if(isDeterministic() && numerator.isDeterministic() && denominator.isDeterministic()) {
double newValueIfNonStochastic = valueIfNonStochastic + (numerator.get(0) / denominator.get(0));
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else {
double[] newRealizations = new double[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.
double newTime = Math.max(Math.max(time, numerator.getFiltrationTime()), denominator.getFiltrationTime());
if(isDeterministic() && numerator.isDeterministic() && denominator.isDeterministic()) {
double newValueIfNonStochastic = valueIfNonStochastic - (numerator.get(0) / denominator.get(0));
return new RandomVariableFromDoubleArray(newTime, newValueIfNonStochastic);
}
else {
double[] newRealizations = new double[Math.max(Math.max(size(), numerator.size()), denominator.size())];
for(int i=0; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy