/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.provider.method;
import com.opengamma.analytics.financial.forex.method.FXMatrix;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivative;
import com.opengamma.analytics.financial.model.interestrate.definition.LiborMarketModelDisplacedDiffusionParameters;
import com.opengamma.analytics.financial.provider.calculator.libormarket.PresentValueLMMDDCalculator;
import com.opengamma.analytics.financial.provider.description.interestrate.LiborMarketModelDisplacedDiffusionProvider;
import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderInterface;
import com.opengamma.util.money.Currency;
/**
* Specific objective function for Hull-White model calibration with cap/floor.
*/
public class SuccessiveRootFinderLMMDDCalibrationObjective extends SuccessiveRootFinderCalibrationObjectiveWithMultiCurves {
/**
* The pricing method used to price the cap/floor.
*/
private static final PresentValueLMMDDCalculator PVLMC = PresentValueLMMDDCalculator.getInstance();
/**
* The Hull-White parameters before calibration. The calibration is done on the last volatility.
*/
private final LiborMarketModelDisplacedDiffusionParameters _lmmParameters;
/**
* The currency for which the LMM parameters are valid (LMM on the discounting curve).
*/
private final Currency _ccyLMM;
/**
* The Hull-White parameters and curves bundle.
*/
private LiborMarketModelDisplacedDiffusionProvider _lmmProvider;
/**
* The start index for the calibration.
*/
private int _startIndex;
/**
* The end index for the calibration.
*/
private int _endIndex;
/**
* The initial LMM volatilities before calibration.
*/
private final double[][] _volatilityInit;
/**
* Constructor of the objective function with the Hull-White parameters. The parameters range and accuracy are set at some default value
* (minimum: 1.0E-6; maximum: 1.0, function value accuracy: 1.0E-4; parameter absolute accuracy: 1.0E-9).
* @param parameters The Hull-White parameters.
* @param ccy The currency for which the LMM parameters are valid (LMM on the discounting curve).
*/
public SuccessiveRootFinderLMMDDCalibrationObjective(final LiborMarketModelDisplacedDiffusionParameters parameters, final Currency ccy) {
super(new FXMatrix(ccy), ccy);
_lmmParameters = parameters;
_ccyLMM = ccy;
setMinimumParameter(1.0E-6);
setMaximumParameter(1.0);
setFunctionValueAccuracy(1.0E-4);
setVariableAbsoluteAccuracy(1.0E-9);
_volatilityInit = new double[_lmmParameters.getNbPeriod()][_lmmParameters.getNbFactor()];
for (int loopperiod = 0; loopperiod < _lmmParameters.getNbPeriod(); loopperiod++) {
for (int loopfact = 0; loopfact < _lmmParameters.getNbFactor(); loopfact++) {
_volatilityInit[loopperiod][loopfact] = parameters.getVolatility()[loopperiod][loopfact];
}
}
}
/**
* Sets the Hull-White curve bundle using the Hull-White parameters and a given set of curves.
* @param multicurves The multi-curves provider.
*/
@Override
public void setMulticurves(MulticurveProviderInterface multicurves) {
_lmmProvider = new LiborMarketModelDisplacedDiffusionProvider(multicurves, _lmmParameters, _ccyLMM);
}
/**
* Gets the Hull-White data.
* @return The Hull-White data.
*/
public LiborMarketModelDisplacedDiffusionParameters getLMMParameters() {
return _lmmParameters;
}
/**
* Sets the LMM.
* @return The LMM.
*/
public LiborMarketModelDisplacedDiffusionProvider getLMMProvider() {
return _lmmProvider;
}
@Override
public void setInstrument(InstrumentDerivative instrument) {
super.setInstrument(instrument);
}
/**
* Gets the start index.
* @return The start index.
*/
public int getStartIndex() {
return _startIndex;
}
/**
* Sets the start index.
* @param startIndex The start index.
*/
public void setStartIndex(int startIndex) {
_startIndex = startIndex;
}
/**
* Gets the end index.
* @return The end index.
*/
public int getEndIndex() {
return _endIndex;
}
/**
* Sets the end index.
* @param endIndex The end index.
*/
public void setEndIndex(int endIndex) {
_endIndex = endIndex;
}
/**
* Gets the initial volatility array.
* @return The initial volatility array.
*/
public double[][] getVolatilityInit() {
return _volatilityInit;
}
@Override
public Double evaluate(Double x) {
int nbVol = _endIndex - _startIndex + 1;
double[][] volChanged = new double[nbVol][_lmmParameters.getNbFactor()];
for (int loopperiod = 0; loopperiod < nbVol; loopperiod++) {
for (int loopfact = 0; loopfact < _lmmParameters.getNbFactor(); loopfact++) {
volChanged[loopperiod][loopfact] = _volatilityInit[loopperiod + _startIndex][loopfact] * x;
}
}
_lmmParameters.setVolatility(volChanged, _startIndex);
return getInstrument().accept(PVLMC, _lmmProvider).getAmount(_ccyLMM) - getPrice();
}
}