/*
* (c) Copyright Christian P. Fries, Germany. All rights reserved. Contact: email@christian-fries.de.
*
* Created on 15.12.2007
*/
package net.finmath.montecarlo.interestrate.modelplugins;
import java.util.Arrays;
import net.finmath.montecarlo.RandomVariable;
import net.finmath.stochastic.RandomVariableInterface;
import net.finmath.time.TimeDiscretizationInterface;
/**
* A covariance model build from a volatility model implementing
* <code>LIBORVolatilityModel</code> and a correlation model
* implementing <code>LIBORCorrelationModel</code>.
*
* <p>
* The model parameters are given by the concatenation of the
* parameters of the <code>LIBORVolatilityModel</code> and
* the parameters of the <code>LIBORCorrelationModel</code>,
* in this ordering
* </p>
*
* @author Christian Fries
*/
public class LIBORCovarianceModelFromVolatilityAndCorrelation extends AbstractLIBORCovarianceModelParametric {
private LIBORVolatilityModel volatilityModel;
private LIBORCorrelationModel correlationModel;
public LIBORCovarianceModelFromVolatilityAndCorrelation(TimeDiscretizationInterface timeDiscretization, TimeDiscretizationInterface liborPeriodDiscretization, LIBORVolatilityModel volatilityModel, LIBORCorrelationModel correlationModel) {
super(timeDiscretization, liborPeriodDiscretization, correlationModel.getNumberOfFactors());
this.volatilityModel = volatilityModel;
this.correlationModel = correlationModel;
}
@Override
public RandomVariableInterface[] getFactorLoading(int timeIndex, int component, RandomVariableInterface[] realizationAtTimeIndex) {
RandomVariableInterface[] factorLoading = new RandomVariableInterface[correlationModel.getNumberOfFactors()];
RandomVariableInterface volatility = volatilityModel.getVolatility(timeIndex, component);
for (int factorIndex = 0; factorIndex < factorLoading.length; factorIndex++) {
factorLoading[factorIndex] = volatility.mult(correlationModel.getFactorLoading(timeIndex, factorIndex, component));
}
return factorLoading;
}
@Override
public RandomVariableInterface getFactorLoadingPseudoInverse(int timeIndex, int component, int factor, RandomVariableInterface[] realizationAtTimeIndex) {
// Note that we assume that the correlation model getFactorLoading gives orthonormal vectors
RandomVariableInterface factorLoadingPseudoInverse = volatilityModel.getVolatility(timeIndex, component).invert()
.mult(correlationModel.getFactorLoading(timeIndex, factor, component));
// @todo numberOfComponents should be stored as a member?!
int numberOfComponents = getLiborPeriodDiscretization().getNumberOfTimeSteps();
double factorWeight = 0.0;
for(int componentIndex=0; componentIndex<numberOfComponents; componentIndex++) {
double factorElement = correlationModel.getFactorLoading(timeIndex, factor, componentIndex);
factorWeight += factorElement*factorElement;
}
factorLoadingPseudoInverse = factorLoadingPseudoInverse.mult(1/factorWeight);
return factorLoadingPseudoInverse;
}
/* (non-Javadoc)
* @see net.finmath.montecarlo.interestrate.modelplugins.AbstractLIBORCovarianceModel#getCovariance(int, int, int)
*/
@Override
public RandomVariableInterface getCovariance(int timeIndex, int component1, int component2, RandomVariableInterface[] realizationAtTimeIndex) {
RandomVariableInterface covariance = new RandomVariable(0.0, correlationModel.getCorrelation(timeIndex, component1, component2));
covariance = covariance.mult(volatilityModel.getVolatility(timeIndex, component1))
.mult(volatilityModel.getVolatility(timeIndex, component2));
return covariance;
}
@Override
public double[] getParameter() {
double[] volatilityParameter = volatilityModel.getParameter();
double[] correlationParameter = correlationModel.getParameter();
int parameterLength = 0;
parameterLength += volatilityParameter != null ? volatilityParameter.length : 0;
parameterLength += correlationParameter != null ? correlationParameter.length : 0;
double[] parameter = new double[parameterLength];
int parameterIndex = 0;
if(volatilityParameter != null) {
System.arraycopy(volatilityParameter, 0, parameter, parameterIndex, volatilityParameter.length);
parameterIndex += volatilityParameter.length;
}
if(correlationParameter != null) {
System.arraycopy(correlationParameter, 0, parameter, parameterIndex, correlationParameter.length);
parameterIndex += correlationParameter.length;
}
return parameter;
}
@Override
public Object clone() {
return new LIBORCovarianceModelFromVolatilityAndCorrelation(
this.getTimeDiscretization(),
this.getLiborPeriodDiscretization(),
(LIBORVolatilityModel)volatilityModel.clone(), (LIBORCorrelationModel)correlationModel.clone());
}
@Override
public AbstractLIBORCovarianceModelParametric getCloneWithModifiedParameters(double[] parameters) {
LIBORVolatilityModel volatilityModel = this.volatilityModel;
LIBORCorrelationModel correlationModel = this.correlationModel;
double[] volatilityParameter = volatilityModel.getParameter();
double[] correlationParameter = correlationModel.getParameter();
int parameterIndex = 0;
if(volatilityParameter != null) {
double[] newVolatilityParameter = new double[volatilityParameter.length];
System.arraycopy(parameters, parameterIndex, newVolatilityParameter, 0, newVolatilityParameter.length);
parameterIndex += newVolatilityParameter.length;
if(!Arrays.equals(newVolatilityParameter, volatilityModel.getParameter())) {
volatilityModel = ((LIBORVolatilityModel) volatilityModel.clone());
volatilityModel.setParameter(newVolatilityParameter);
}
}
if(correlationParameter != null) {
double[] newCorrelationParameter = new double[correlationParameter.length];
System.arraycopy(parameters, parameterIndex, newCorrelationParameter, 0, newCorrelationParameter.length);
parameterIndex += newCorrelationParameter.length;
if(!Arrays.equals(newCorrelationParameter, correlationModel.getParameter()))
correlationModel = ((LIBORCorrelationModel) correlationModel.clone());
correlationModel.setParameter(newCorrelationParameter);
}
return new LIBORCovarianceModelFromVolatilityAndCorrelation(this.getTimeDiscretization(), this.getLiborPeriodDiscretization(), volatilityModel, correlationModel);
}
public LIBORVolatilityModel getVolatilityModel() {
return volatilityModel;
}
public LIBORCorrelationModel getCorrelationModel() {
return correlationModel;
}
}