/* * (c) Copyright Christian P. Fries, Germany. All rights reserved. Contact: email@christianfries.com. * * Created on 25.05.2013 */ package net.finmath.montecarlo; import net.finmath.stochastic.RandomVariableInterface; import net.finmath.time.TimeDiscretizationInterface; /** * Provides a correlated Brownian motion from given (independent) increments * and a given matrix of factor loadings. * * The i-th factor of this BrownianMotion is <i>dW<sub>i</sub></i> where * <i>dW<sub>i</sub> = f<sub>i,1</sub> dU<sub>1</sub> + ... + f<sub>i,m</sub> dU<sub>m</sub></i> * for <i>i = 1, ..., n</i>. * * Here <i>f<sub>i,j</sub></i> are the factor loadings, an <i>n × m</i>-matrix. * * If <i>dU<sub>j</sub></i> are independent, then <i>dW<sub>i</sub> dW<sub>k</sub> = ρ<sub>i,k</sub> dt</i> * where <i>ρ<sub>i,k</sub> = f<sub>i</sub> · f<sub>j</sub></i>. * * Note: It is possible to create this class with a Brownian motion <i>U</i> which is * already correlated. The factors loadings will be applied accordingly. * * @author Christian Fries */ public class CorrelatedBrownianMotion implements BrownianMotionInterface { private BrownianMotionInterface uncollelatedFactors; private double[][] factorLoadings; /** * Create a correlated Brownian motion from given independent increments * and a given matrix of factor loadings. * * The i-th factor of this BrownianMotion is <i>dW<sub>i</sub></i> where * <i>dW<sub>i</sub> = f<sub>i,1</sub> dU<sub>1</sub> + ... + f<sub>i,m</sub> dU<sub>m</sub></i> * for <i>i = 1, ..., n</i>. * * Here <i>f<sub>i,j</sub></i> are the factor loadings, an <i>n × m</i>-matrix. * * If <i>dU<sub>j</sub></i> are independent, then <i>dW<sub>i</sub> dW<sub>k</sub> = ρ<sub>i,k</sub> dt</i> * where <i>ρ<sub>i,k</sub> = f<sub>i</sub> · f<sub>j</sub></i>. * * @param uncollelatedFactors The Brownian motion providing the (uncorrelated) factors <i>dU<sub>j</sub></i>. * @param factorLoadings The factor loadings <i>f<sub>i,j</sub></i>. */ public CorrelatedBrownianMotion(BrownianMotionInterface uncollelatedFactors, double[][] factorLoadings) { super(); this.uncollelatedFactors = uncollelatedFactors; this.factorLoadings = factorLoadings; } /* (non-Javadoc) * @see net.finmath.montecarlo.BrownianMotionInterface#getBrownianIncrement(int, int) */ @Override public RandomVariableInterface getBrownianIncrement(int timeIndex, int factor) { RandomVariableInterface brownianIncrement = new RandomVariable(0.0); for(int factorIndex=0; factorIndex<factorLoadings[factor].length; factorIndex++) { if(factorLoadings[factor][factorIndex] != 0) { RandomVariableInterface independentFactor = uncollelatedFactors.getBrownianIncrement(timeIndex, factorIndex); brownianIncrement = brownianIncrement.addProduct(independentFactor, factorLoadings[factor][factorIndex]); } } return brownianIncrement; } /* (non-Javadoc) * @see net.finmath.montecarlo.BrownianMotionInterface#getTimeDiscretization() */ @Override public TimeDiscretizationInterface getTimeDiscretization() { return uncollelatedFactors.getTimeDiscretization(); } /* (non-Javadoc) * @see net.finmath.montecarlo.BrownianMotionInterface#getNumberOfFactors() */ @Override public int getNumberOfFactors() { return factorLoadings.length; } /* (non-Javadoc) * @see net.finmath.montecarlo.BrownianMotionInterface#getNumberOfPaths() */ @Override public int getNumberOfPaths() { return uncollelatedFactors.getNumberOfPaths(); } @Override public RandomVariableInterface getRandomVariableForConstant(double value) { return uncollelatedFactors.getRandomVariableForConstant(value); } /* (non-Javadoc) * @see net.finmath.montecarlo.BrownianMotionInterface#getCloneWithModifiedSeed(int) */ @Override public BrownianMotionInterface getCloneWithModifiedSeed(int seed) { return new CorrelatedBrownianMotion(uncollelatedFactors.getCloneWithModifiedSeed(seed), factorLoadings); } /* (non-Javadoc) * @see net.finmath.montecarlo.BrownianMotionInterface#getCloneWithModifiedTimeDiscretization(net.finmath.time.TimeDiscretizationInterface) */ @Override public BrownianMotionInterface getCloneWithModifiedTimeDiscretization(TimeDiscretizationInterface newTimeDiscretization) { return new CorrelatedBrownianMotion(uncollelatedFactors.getCloneWithModifiedTimeDiscretization(newTimeDiscretization), factorLoadings); } @Override public RandomVariableInterface getIncrement(int timeIndex, int factor) { return getBrownianIncrement(timeIndex, factor); } }