net.finmath.montecarlo.RandomVariableLowMemory 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.function.DoubleBinaryOperator;
import java.util.function.DoubleUnaryOperator;
import java.util.function.IntToDoubleFunction;
import java.util.stream.DoubleStream;
import org.apache.commons.math3.util.FastMath;
import net.finmath.functions.DoubleTernaryOperator;
import net.finmath.stochastic.RandomVariableInterface;
/**
* The class RandomVariable 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
* RandomVariableInterface
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 RandomVariableLowMemory implements RandomVariableInterface {
private static final long serialVersionUID = 7620120320663270600L;
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 RandomVariableInterface
.
*
* @param value Object implementing RandomVariableInterface
.
*/
public RandomVariableLowMemory(RandomVariableInterface value) {
super();
this.time = value.getFiltrationTime();
this.realizations = value.isDeterministic() ? null : getFloatArray(value.getRealizations());
this.valueIfNonStochastic = value.isDeterministic() ? value.get(0) : Double.NaN;
}
/**
* Create a non stochastic random variable, i.e. a constant.
*
* @param value the value, a constant.
*/
public RandomVariableLowMemory(double value) {
this(-Double.MAX_VALUE, value);
}
/**
* 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 RandomVariableLowMemory(double time, double value) {
super();
this.time = time;
this.realizations = null;
this.valueIfNonStochastic = value;
}
/**
* 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.
*/
public RandomVariableLowMemory(double time, int numberOfPath, double value) {
super();
this.time = time;
this.realizations = new float[numberOfPath];
java.util.Arrays.fill(this.realizations, (float)value);
this.valueIfNonStochastic = Double.NaN;
}
/**
* Create a stochastic random variable.
*
* @param time the filtration time, set to 0.0 if not used.
* @param realisations the vector of realizations.
*/
public RandomVariableLowMemory(double time, float[] realisations) {
super();
this.time = time;
this.realizations = realisations;
this.valueIfNonStochastic = Double.NaN;
}
/**
* Create a stochastic random variable.
*
* @param time the filtration time, set to 0.0 if not used.
* @param realisations the vector of realizations.
*/
public RandomVariableLowMemory(double time, double[] realisations) {
super();
this.time = time;
this.realizations = getFloatArray(realisations);
this.valueIfNonStochastic = Double.NaN;
}
private float[] getFloatArray(double[] arrayOfDouble) {
float[] arrayOfFloat = new float[arrayOfDouble.length];
for(int i=0; i quantileEnd) return getQuantileExpectation(quantileEnd, quantileStart);
float[] 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.RandomVariableInterface#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.
*/
float[] 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(getDoubleArray(realizations));
}
}
@Override
public Double doubleValue() {
if(isDeterministic()) return valueIfNonStochastic;
else throw new UnsupportedOperationException("The random variable is non-deterministic");
}
@Override
public double[] getRealizations() {
if(isDeterministic()) {
double[] result = new double[1];
result[0] = get(0);
return result;
}
else {
return getDoubleArray(realizations);
}
}
public IntToDoubleFunction getOperator() {
if(isDeterministic()) {
return i -> valueIfNonStochastic;
}
else {
return i -> realizations[i];
}
}
@Override
public RandomVariableInterface apply(DoubleUnaryOperator operator) {
if(isDeterministic()) {
return new RandomVariable(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 RandomVariable(newTime, result, newSize);
}
@Override
public RandomVariableInterface apply(DoubleTernaryOperator operator, RandomVariableInterface argument1, RandomVariableInterface 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 RandomVariable(newTime, result, newSize);
}
public RandomVariableInterface cap(double cap) {
if(isDeterministic()) {
double newValueIfNonStochastic = Math.min(valueIfNonStochastic,cap);
return new RandomVariableLowMemory(time, newValueIfNonStochastic);
}
else {
double[] newRealizations = new double[realizations.length];
for(int i=0; i= 0 ? valueIfTriggerNonNegative.get(0) : valueIfTriggerNegative.get(0);
return new RandomVariableLowMemory(newTime, newValueIfNonStochastic);
}
else {
int numberOfPaths = Math.max(Math.max(trigger.size(), valueIfTriggerNonNegative.size()), valueIfTriggerNegative.size());
double[] newRealizations = new double[numberOfPaths];
for(int i=0; i= 0.0 ? valueIfTriggerNonNegative.get(i) : valueIfTriggerNegative.get(i);
}
return new RandomVariableLowMemory(newTime, newRealizations);
}
}
public RandomVariableInterface barrier(RandomVariableInterface trigger, RandomVariableInterface valueIfTriggerNonNegative, double valueIfTriggerNegative) {
return this.barrier(trigger, valueIfTriggerNonNegative, new RandomVariableLowMemory(valueIfTriggerNonNegative.getFiltrationTime(), valueIfTriggerNegative));
}
/* (non-Javadoc)
* @see net.finmath.stochastic.RandomVariableInterface#invert()
*/
public RandomVariableInterface invert() {
if(isDeterministic()) {
double newValueIfNonStochastic = 1.0/valueIfNonStochastic;
return new RandomVariableLowMemory(time, newValueIfNonStochastic);
}
else {
double[] newRealizations = new double[realizations.length];
for(int i=0; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy