All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.finmath.montecarlo.RandomVariableLazyEvaluation Maven / Gradle / Ivy

Go to download

finmath lib is a Mathematical Finance Library in Java. It provides algorithms and methodologies related to mathematical finance.

The newest version!
/*
 * (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.DoubleSupplier;
import java.util.function.DoubleUnaryOperator;
import java.util.function.IntToDoubleFunction;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;

import net.finmath.functions.DoubleTernaryOperator;
import net.finmath.stochastic.RandomVariable;

/**
 * Implements a Monte-Carlo random variable (like RandomVariableFromDoubleArray using
 * late evaluation of Java 8 streams
 *
 * Accesses performed exclusively through the interface
 * RandomVariable is thread safe (and does not mutate the class).
 *
 * The implementation require Java 8 or better.
 *
 * @TODO The implementation of getAverage does not use a Kahan summation, while RandomVariableFromDoubleArray does.
 *
 * @author Christian Fries
 * @author OSC
 * @version 2.0
 */
public class RandomVariableLazyEvaluation implements RandomVariable {

	/**
	 *
	 */
	private static final long serialVersionUID = 8413020544732461630L;

	private final double            time;	                // Time (filtration)

	// Operator
	private       IntToDoubleFunction   realizations;
	private final int                   size;
	// Data model for the non-stochastic case (if realizations==null)
	private final double                valueIfNonStochastic;

	private transient double[] realizationsArray = null;

	/**
	 * Create a random variable from a given other implementation of RandomVariable.
	 *
	 * @param value Object implementing RandomVariable.
	 */
	public RandomVariableLazyEvaluation(final RandomVariable value) {
		super();
		time = value.getFiltrationTime();
		realizations = value.isDeterministic() ? null : value::get;
		size = value.size();
		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 RandomVariableLazyEvaluation(final double value) {
		this(0.0, 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 RandomVariableLazyEvaluation(final RandomVariable value, final DoubleUnaryOperator function) {
		super();
		time = value.getFiltrationTime();
		realizations = value.isDeterministic() ? null : new IntToDoubleFunction() {
			@Override
			public double applyAsDouble(final int i) {
				return function.applyAsDouble(value.get(i));
			}
		};
		size = value.size();
		valueIfNonStochastic = value.isDeterministic() ? function.applyAsDouble(value.get(0)) : Double.NaN;
	}

	/**
	 * 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 RandomVariableLazyEvaluation(final double time, final double value) {
		super();
		this.time = time;
		realizations = null;
		size = 1;
		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 path/state of the associated Monte-Carlo simulation or lattice.
	 * @param value the value, a constant.
	 */
	public RandomVariableLazyEvaluation(final double time, final int numberOfPath, final double value) {
		super();
		this.time = time;
		size = numberOfPath;
		realizations = new IntToDoubleFunction() {
			@Override
			public double applyAsDouble(final int i) {
				return value;
			}
		};
		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 RandomVariableLazyEvaluation(final double time, final double[] realisations) {
		super();
		this.time = time;
		size = realisations.length;
		realizations = new IntToDoubleFunction() {
			@Override
			public double applyAsDouble(final int i) {
				return realisations[i];
			}
		};
		valueIfNonStochastic = Double.NaN;
		realizationsArray = realisations;
	}

	/**
	 * Create a stochastic random variable.
	 *
	 * @param time the filtration time, set to 0.0 if not used.
	 * @param realisations the vector of realizations.
	 * @param size The number of path/state of the associated Monte-Carlo simulation or lattice.
	 */
	public RandomVariableLazyEvaluation(final double time, final IntToDoubleFunction realisations, final int size) {
		super();
		this.time = time;
		realizations = realisations;
		this.size = size;
		valueIfNonStochastic = Double.NaN;
	}

	/* (non-Javadoc)
	 * @see net.finmath.stochastic.RandomVariable#equals(net.finmath.montecarlo.RandomVariableFromDoubleArray)
	 */
	@Override
	public boolean equals(final RandomVariable randomVariable) {
		if(time != randomVariable.getFiltrationTime()) {
			return false;
		}
		if(this.isDeterministic() && randomVariable.isDeterministic()) {
			return valueIfNonStochastic == randomVariable.get(0);
		}

		if(this.isDeterministic() != randomVariable.isDeterministic()) {
			return false;
		}

		for(int i=0; i quantileEnd) {
			return getQuantileExpectation(quantileEnd, quantileStart);
		}

		final double[] realizationsSorted = getRealizations().clone();
		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;
	}

	/* (non-Javadoc)
	 * @see net.finmath.stochastic.RandomVariable#getHistogram()
	 */
	@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.
			 */
			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 double[] realizationsSorted = getRealizations().clone();
			Arrays.sort(realizationsSorted);

			int sampleIndex=0;
			for (int intervalIndex=0; intervalIndex 0) {
				for(int i=0; i= 0 ? y : z);
			}
		}, valueIfTriggerNonNegative, valueIfTriggerNegative);
	}

	@Override
	public RandomVariable invert() {
		return apply(new DoubleUnaryOperator() {
			@Override
			public double applyAsDouble(final double x) {
				return 1.0 / x;
			}
		});
	}

	/* (non-Javadoc)
	 * @see net.finmath.stochastic.RandomVariable#abs()
	 */
	@Override
	public RandomVariable abs() {
		return apply(Math::abs);
	}

	/* (non-Javadoc)
	 * @see net.finmath.stochastic.RandomVariable#addProduct(net.finmath.stochastic.RandomVariable, double)
	 */
	@Override
	public RandomVariable addProduct(final RandomVariable factor1, final double factor2) {
		return apply(new DoubleBinaryOperator() {
			@Override
			public double applyAsDouble(final double x, final double y) {
				return x + y * factor2;
			}
		}, factor1);
	}


	/* (non-Javadoc)
	 * @see net.finmath.stochastic.RandomVariable#addProduct(net.finmath.stochastic.RandomVariable, net.finmath.stochastic.RandomVariable)
	 */
	@Override
	public RandomVariable addProduct(final RandomVariable factor1, final RandomVariable factor2) {
		return apply(new DoubleBinaryOperator() {
			@Override
			public double applyAsDouble(final double x, final double y) {
				return x + y;
			}
		}, new DoubleBinaryOperator() {
			@Override
			public double applyAsDouble(final double x, final double y) {
				return x * y;
			}
		}, factor1, factor2);
	}

	/* (non-Javadoc)
	 * @see net.finmath.stochastic.RandomVariable#addRatio(net.finmath.stochastic.RandomVariable, net.finmath.stochastic.RandomVariable)
	 */
	@Override
	public RandomVariable addRatio(final RandomVariable numerator, final RandomVariable denominator) {
		return apply(new DoubleBinaryOperator() {
			@Override
			public double applyAsDouble(final double x, final double y) {
				return x + y;
			}
		}, new DoubleBinaryOperator() {
			@Override
			public double applyAsDouble(final double x, final double y) {
				return x / y;
			}
		}, numerator, denominator);
	}

	/* (non-Javadoc)
	 * @see net.finmath.stochastic.RandomVariable#subRatio(net.finmath.stochastic.RandomVariable, net.finmath.stochastic.RandomVariable)
	 */
	@Override
	public RandomVariable subRatio(final RandomVariable numerator, final RandomVariable denominator) {
		return apply(new DoubleBinaryOperator() {
			@Override
			public double applyAsDouble(final double x, final double y) {
				return x - y;
			}
		}, new DoubleBinaryOperator() {
			@Override
			public double applyAsDouble(final double x, final double y) {
				return x / y;
			}
		}, numerator, denominator);
	}

	@Override
	public RandomVariable isNaN() {
		if(isDeterministic()) {
			return new RandomVariableLazyEvaluation(time, Double.isNaN(valueIfNonStochastic) ? 1.0 : 0.0);
		}
		else {
			final double[] newRealizations = new double[size()];
			for(int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy