LIBORCovarianceModelFromVolatilityAndCorrelation.java
/*
* (c) Copyright Christian P. Fries, Germany. Contact: email@christian-fries.de.
*
* Created on 15.12.2007
*/
package net.finmath.montecarlo.interestrate.models.covariance;
import java.util.Arrays;
import java.util.Map;
import net.finmath.exception.CalculationException;
import net.finmath.stochastic.RandomVariable;
import net.finmath.stochastic.Scalar;
import net.finmath.time.TimeDiscretization;
/**
* 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
* @version 1.0
*/
public class LIBORCovarianceModelFromVolatilityAndCorrelation extends AbstractLIBORCovarianceModelParametric {
/**
*
*/
private static final long serialVersionUID = -8782024526695367005L;
private final LIBORVolatilityModel volatilityModel;
private final LIBORCorrelationModel correlationModel;
public LIBORCovarianceModelFromVolatilityAndCorrelation(final TimeDiscretization timeDiscretization, final TimeDiscretization liborPeriodDiscretization, final LIBORVolatilityModel volatilityModel, final LIBORCorrelationModel correlationModel) {
super(timeDiscretization, liborPeriodDiscretization, correlationModel.getNumberOfFactors());
this.volatilityModel = volatilityModel;
this.correlationModel = correlationModel;
}
@Override
public RandomVariable[] getFactorLoading(final int timeIndex, final int component, final RandomVariable[] realizationAtTimeIndex) {
final RandomVariable[] factorLoading = new RandomVariable[correlationModel.getNumberOfFactors()];
final RandomVariable 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 RandomVariable getFactorLoadingPseudoInverse(final int timeIndex, final int component, final int factor, final RandomVariable[] realizationAtTimeIndex) {
// Note that we assume that the correlation model getFactorLoading gives orthonormal vectors
RandomVariable factorLoadingPseudoInverse = volatilityModel.getVolatility(timeIndex, component).invert()
.mult(correlationModel.getFactorLoading(timeIndex, factor, component));
// @TODO numberOfComponents should be stored as a member?!
final int numberOfComponents = getLiborPeriodDiscretization().getNumberOfTimeSteps();
double factorWeight = 0.0;
for(int componentIndex=0; componentIndex<numberOfComponents; componentIndex++) {
final double factorElement = correlationModel.getFactorLoading(timeIndex, factor, componentIndex);
factorWeight += factorElement*factorElement;
}
factorLoadingPseudoInverse = factorLoadingPseudoInverse.mult(1/factorWeight);
return factorLoadingPseudoInverse;
}
/* (non-Javadoc)
* @see net.finmath.montecarlo.interestrate.models.covariance.AbstractLIBORCovarianceModel#getCovariance(int, int, int)
*/
@Override
public RandomVariable getCovariance(final int timeIndex, final int component1, final int component2, final RandomVariable[] realizationAtTimeIndex) {
final RandomVariable volatilityOfComponent1 = volatilityModel.getVolatility(timeIndex, component1);
final RandomVariable volatilityOfComponent2 = volatilityModel.getVolatility(timeIndex, component2);
final double correlationOfComponent1And2 = correlationModel.getCorrelation(timeIndex, component1, component2);
final RandomVariable covariance = volatilityOfComponent1.mult(volatilityOfComponent2).mult(correlationOfComponent1And2);
return covariance;
}
@Override
public RandomVariable[] getParameter() {
final RandomVariable[] volatilityParameter = volatilityModel.getParameter();
final RandomVariable[] correlationParameter = correlationModel.getParameter();
int parameterLength = 0;
parameterLength += volatilityParameter != null ? volatilityParameter.length : 0;
parameterLength += correlationParameter != null ? correlationParameter.length : 0;
final RandomVariable[] parameter = new RandomVariable[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 AbstractLIBORCovarianceModelParametric getCloneWithModifiedParameters(final double[] parameters) {
return getCloneWithModifiedParameters(Scalar.arrayOf(parameters));
}
@Override
public double[] getParameterAsDouble() {
final RandomVariable[] parameters = getParameter();
final double[] parametersAsDouble = new double[parameters.length];
for(int i=0; i<parameters.length; i++) {
parametersAsDouble[i] = parameters[i].doubleValue();
}
return parametersAsDouble;
}
@Override
public Object clone() {
return new LIBORCovarianceModelFromVolatilityAndCorrelation(
this.getTimeDiscretization(),
this.getLiborPeriodDiscretization(),
(LIBORVolatilityModel)volatilityModel.clone(), (LIBORCorrelationModel)correlationModel.clone());
}
@Override
public AbstractLIBORCovarianceModelParametric getCloneWithModifiedParameters(final RandomVariable[] parameters) {
LIBORVolatilityModel volatilityModel = this.volatilityModel;
LIBORCorrelationModel correlationModel = this.correlationModel;
final RandomVariable[] volatilityParameter = volatilityModel.getParameter();
final RandomVariable[] correlationParameter = correlationModel.getParameter();
int parameterIndex = 0;
if(volatilityParameter != null) {
final RandomVariable[] newVolatilityParameter = new RandomVariable[volatilityParameter.length];
System.arraycopy(parameters, parameterIndex, newVolatilityParameter, 0, newVolatilityParameter.length);
parameterIndex += newVolatilityParameter.length;
if(!Arrays.equals(newVolatilityParameter, volatilityModel.getParameter())) {
volatilityModel = volatilityModel.getCloneWithModifiedParameter(newVolatilityParameter);
}
}
if(correlationParameter != null) {
final RandomVariable[] newCorrelationParameter = new RandomVariable[correlationParameter.length];
System.arraycopy(parameters, parameterIndex, newCorrelationParameter, 0, newCorrelationParameter.length);
parameterIndex += newCorrelationParameter.length;
if(!Arrays.equals(newCorrelationParameter, correlationModel.getParameter())) {
correlationModel = correlationModel.getCloneWithModifiedParameter(newCorrelationParameter);
}
}
return new LIBORCovarianceModelFromVolatilityAndCorrelation(this.getTimeDiscretization(), this.getLiborPeriodDiscretization(), volatilityModel, correlationModel);
}
public LIBORVolatilityModel getVolatilityModel() {
return volatilityModel;
}
public LIBORCorrelationModel getCorrelationModel() {
return correlationModel;
}
@Override
public AbstractLIBORCovarianceModelParametric getCloneWithModifiedData(final Map<String, Object> dataModified)
throws CalculationException {
TimeDiscretization timeDiscretization = this.getTimeDiscretization();
TimeDiscretization liborPeriodDiscretization = this.getLiborPeriodDiscretization();
LIBORVolatilityModel volatilityModel = this.volatilityModel;
LIBORCorrelationModel correlationModel = this.correlationModel;
if(dataModified != null) {
if((dataModified.containsKey("timeDiscretization")||dataModified.containsKey("liborPeriodDiscretization")||dataModified.containsKey("randomVariableFactory"))) {
if(!dataModified.containsKey("volatilityModel")) {
volatilityModel = volatilityModel.getCloneWithModifiedData(dataModified);
}
if(!dataModified.containsKey("correlationModel")) {
correlationModel = correlationModel.getCloneWithModifiedData(dataModified);
}
}
timeDiscretization = (TimeDiscretization)dataModified.getOrDefault("timeDiscretization", timeDiscretization);
liborPeriodDiscretization = (TimeDiscretization)dataModified.getOrDefault("liborPeriodDiscretization", liborPeriodDiscretization);
// the discretizations have to be compatible to the volatilityModels!
volatilityModel = (LIBORVolatilityModel)dataModified.getOrDefault("volatilityModel", volatilityModel);
correlationModel = (LIBORCorrelationModel)dataModified.getOrDefault("correlationModel", correlationModel);
}
final AbstractLIBORCovarianceModelParametric newModel = new LIBORCovarianceModelFromVolatilityAndCorrelation(timeDiscretization, liborPeriodDiscretization, volatilityModel, correlationModel);
return newModel;
}
}