/*
* (c) Copyright Christian P. Fries, Germany. All rights reserved. Contact: email@christianfries.com.
*
* Created on 07.09.2014
*/
package net.finmath.marketdata.model.volatilities;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.finmath.exception.CalculationException;
import net.finmath.marketdata.calibration.ParameterObjectInterface;
import net.finmath.marketdata.calibration.ParameterTransformation;
import net.finmath.marketdata.calibration.Solver;
import net.finmath.marketdata.model.AnalyticModelInterface;
import net.finmath.marketdata.products.AnalyticProductInterface;
import net.finmath.optimizer.OptimizerFactoryInterface;
import net.finmath.optimizer.SolverException;
/**
* Base class for parametric volatility surfaces, implementing a generic calibration algorithm.
*
* @author Christian Fries
*/
public abstract class AbstractVolatilitySurfaceParametric extends AbstractVolatilitySurface implements ParameterObjectInterface {
private static final Logger logger = Logger.getLogger("net.finmath");
public AbstractVolatilitySurfaceParametric(String name, LocalDate referenceDate) {
super(name, referenceDate);
}
/**
* Returns a clone of this volatility surface with modified parameters.
*
* @param value Parameter array.
* @return Clone with new parameters.
* @throws CloneNotSupportedException Thrown if this object cannot be cloned.
*/
public abstract AbstractVolatilitySurfaceParametric getCloneForParameter(double[] value) throws CloneNotSupportedException;
public AbstractVolatilitySurfaceParametric getCloneCalibrated(final AnalyticModelInterface calibrationModel, final Vector<AnalyticProductInterface> calibrationProducts, final List<Double> calibrationTargetValues, Map<String,Object> calibrationParameters) throws CalculationException, SolverException {
return getCloneCalibrated(calibrationModel, calibrationProducts, calibrationTargetValues, calibrationParameters, null);
}
public AbstractVolatilitySurfaceParametric getCloneCalibrated(final AnalyticModelInterface calibrationModel, final Vector<AnalyticProductInterface> calibrationProducts, final List<Double> calibrationTargetValues, Map<String,Object> calibrationParameters, final ParameterTransformation parameterTransformation) throws CalculationException, SolverException {
return getCloneCalibrated(calibrationModel, calibrationProducts, calibrationTargetValues, calibrationParameters, parameterTransformation, null);
}
/**
* Create a clone of this volatility surface using a generic calibration
* of its parameters to given market data.
*
* @param calibrationModel The model used during calibration (contains additional objects required during valuation, e.g. curves).
* @param calibrationProducts The calibration products.
* @param calibrationTargetValues The target values of the calibration products.
* @param calibrationParameters A map containing additional settings like "evaluationTime" (Double).
* @param parameterTransformation An optional parameter transformation.
* @param optimizerFactory The factory providing the optimizer to be used during calibration.
* @return An object having the same type as this one, using (hopefully) calibrated parameters.
* @throws CalculationException Exception thrown when evaluation fails.
* @throws SolverException Exception thrown when solver fails.
*/
public AbstractVolatilitySurfaceParametric getCloneCalibrated(final AnalyticModelInterface calibrationModel, final Vector<AnalyticProductInterface> calibrationProducts, final List<Double> calibrationTargetValues, Map<String,Object> calibrationParameters, final ParameterTransformation parameterTransformation, OptimizerFactoryInterface optimizerFactory) throws CalculationException, SolverException {
if(calibrationParameters == null) calibrationParameters = new HashMap<String,Object>();
Integer maxIterationsParameter = (Integer)calibrationParameters.get("maxIterations");
Double accuracyParameter = (Double)calibrationParameters.get("accuracy");
Double evaluationTimeParameter = (Double)calibrationParameters.get("evaluationTime");
// @TODO currently ignored, we use the setting form the OptimizerFactoryInterface
int maxIterations = maxIterationsParameter != null ? maxIterationsParameter.intValue() : 600;
double accuracy = accuracyParameter != null ? accuracyParameter.doubleValue() : 1E-8;
double evaluationTime = evaluationTimeParameter != null ? evaluationTimeParameter.doubleValue() : 0.0;
AnalyticModelInterface model = calibrationModel.addVolatilitySurfaces(this);
Solver solver = new Solver(model, calibrationProducts, calibrationTargetValues, parameterTransformation, evaluationTime, optimizerFactory);
Set<ParameterObjectInterface> objectsToCalibrate = new HashSet<ParameterObjectInterface>();
objectsToCalibrate.add(this);
AnalyticModelInterface modelCalibrated = solver.getCalibratedModel(objectsToCalibrate);
// Diagnostic output
if (logger.isLoggable(Level.FINE)) {
double lastAccuracy = solver.getAccuracy();
int lastIterations = solver.getIterations();
logger.fine("The solver achived an accuracy of " + lastAccuracy + " in " + lastIterations + ".");
}
return (AbstractVolatilitySurfaceParametric)modelCalibrated.getVolatilitySurface(this.getName());
}
}