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

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

Go to download

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

There is a newer version: 6.0.19
Show newest version
/*
 * (c) Copyright Christian P. Fries, Germany. Contact: [email protected].
 *
 * Created on 25.05.2013
 */

package net.finmath.montecarlo;

import java.util.HashMap;
import java.util.Map;

import net.finmath.stochastic.RandomVariable;
import net.finmath.time.TimeDiscretization;

/**
 * Provides a Brownian motion from given (independent) increments and performs a control of the expectation and the standard deviation.
 *
 * This class references a class providing Brownian increments \( \Delta U(t_{i}) \) and transforms them via
 * \[
 * 	\Delta W(t_{i}) = a \Delta U(t_{i}) + b
 * \]
 * such that \Delta W(t_{i}) has exact mean 0 and exact standard deviation \( \sqrt{\Delta t_{i}} \).
 *
 * @author Christian Fries
 * @version 1.0
 */
public class BrownianMotionWithControlVariate implements BrownianMotion {

	private final BrownianMotion	brownianMotion;

	private transient Map averages = new HashMap<>();
	private transient Map scalings = new HashMap<>();

	/**
	 * Create a controlled Brownian motion.
	 *
	 * @param brownianMotion The Brownian motion providing the (un-controlled) factors dUj.
	 */
	public BrownianMotionWithControlVariate(final BrownianMotion brownianMotion) {
		super();
		this.brownianMotion	= brownianMotion;
	}

	@Override
	public RandomVariable getBrownianIncrement(final int timeIndex, final int factorIndex) {
		final RandomVariable brownianIncrement = brownianMotion.getBrownianIncrement(timeIndex, factorIndex);

		final int mapIndex = timeIndex * brownianMotion.getNumberOfFactors() + factorIndex;
		final double average = averages.computeIfAbsent(mapIndex, index -> { return brownianIncrement.getAverage();});
		final double scaling = scalings.computeIfAbsent(mapIndex, index -> { return Math.sqrt(brownianMotion.getTimeDiscretization().getTimeStep(timeIndex)) / brownianIncrement.getStandardDeviation();});

		RandomVariable brownianIncrementControlled = brownianIncrement;

		if(average != 0.0) {
			brownianIncrementControlled = brownianIncrementControlled.sub(average);
		}

		if(Double.isFinite(scaling) && scaling != 1.0) {
			brownianIncrementControlled = brownianIncrementControlled.mult(scaling);
		}

		return brownianIncrementControlled;
	}

	@Override
	public TimeDiscretization getTimeDiscretization() {
		return brownianMotion.getTimeDiscretization();
	}

	@Override
	public int getNumberOfFactors() {
		return brownianMotion.getNumberOfFactors();
	}

	@Override
	public int getNumberOfPaths() {
		return brownianMotion.getNumberOfPaths();
	}

	@Override
	public RandomVariable getRandomVariableForConstant(final double value) {
		return brownianMotion.getRandomVariableForConstant(value);
	}

	@Override
	public BrownianMotion getCloneWithModifiedSeed(final int seed) {
		return new BrownianMotionWithControlVariate(brownianMotion.getCloneWithModifiedSeed(seed));
	}

	@Override
	public BrownianMotion getCloneWithModifiedTimeDiscretization(final TimeDiscretization newTimeDiscretization) {
		return new BrownianMotionWithControlVariate(brownianMotion.getCloneWithModifiedTimeDiscretization(newTimeDiscretization));
	}

	@Override
	public RandomVariable getIncrement(final int timeIndex, final int factor) {
		return getBrownianIncrement(timeIndex, factor);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy