/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.interestrate.swaption.method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivative;
import com.opengamma.analytics.financial.interestrate.YieldCurveBundle;
import com.opengamma.analytics.financial.interestrate.method.PricingMethod;
import com.opengamma.analytics.financial.interestrate.method.SuccessiveLeastSquareCalibrationEngine;
import com.opengamma.analytics.financial.interestrate.swaption.derivative.SwaptionPhysicalFixedIbor;
import com.opengamma.analytics.math.linearalgebra.DecompositionFactory;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.matrix.MatrixAlgebraFactory;
import com.opengamma.analytics.math.statistics.leastsquare.LeastSquareResults;
import com.opengamma.analytics.math.statistics.leastsquare.NonLinearLeastSquare;
import com.opengamma.util.ArgumentChecker;
/**
* Specific calibration engine for the LMM model with swaption.
* @deprecated {@link YieldCurveBundle} is deprecated
*/
@Deprecated
public class SwaptionPhysicalLMMDDSuccessiveLeastSquareCalibrationEngine extends SuccessiveLeastSquareCalibrationEngine {
/**
* The precision used in least-square search.
*/
private static final double DEFAULT_PRECISION = 1.0E-15;
/**
* The list of the last index in the Ibor date for each instrument.
*/
private final List<Integer> _instrumentIndex = new ArrayList<>();
/**
* The number of instruments in a calibration block. The total number of instruments should be a multiple of that number.
*/
private final int _nbInstrumentsBlock;
/**
* Constructor of the calibration engine.
* @param calibrationObjective The calibration objective.
* @param nbInstrumentsBlock The number of instruments in a calibration block.
*/
public SwaptionPhysicalLMMDDSuccessiveLeastSquareCalibrationEngine(final SwaptionPhysicalLMMDDSuccessiveLeastSquareCalibrationObjective calibrationObjective, final int nbInstrumentsBlock) {
super(calibrationObjective);
_instrumentIndex.add(0);
_nbInstrumentsBlock = nbInstrumentsBlock;
}
/**
* Gets the instrument index.
* @return The instrument index.
*/
public List<Integer> getInstrumentIndex() {
return _instrumentIndex;
}
/**
* Returns the number of instruments in a calibration block.
* @return The number.
*/
public int getNbInstrumentsBlock() {
return _nbInstrumentsBlock;
}
@Override
public void addInstrument(final InstrumentDerivative instrument, final PricingMethod method) {
ArgumentChecker.notNull(instrument, "Instrument");
ArgumentChecker.notNull(method, "Method");
ArgumentChecker.isTrue(instrument instanceof SwaptionPhysicalFixedIbor, "Calibration instruments should be swaptions");
final SwaptionPhysicalFixedIbor swaption = (SwaptionPhysicalFixedIbor) instrument;
getBasket().add(instrument);
getMethod().add(method);
getCalibrationPrice().add(0.0);
_instrumentIndex.add(Arrays.binarySearch(((SwaptionPhysicalLMMDDSuccessiveLeastSquareCalibrationObjective) getCalibrationObjective()).getLMMParameters().getIborTime(), swaption
.getUnderlyingSwap().getSecondLeg().getNthPayment(swaption.getUnderlyingSwap().getSecondLeg().getNumberOfPayments() - 1).getPaymentTime()));
}
@Override
public void calibrate(final YieldCurveBundle curves) {
final int nbInstruments = getBasket().size();
ArgumentChecker.isTrue(nbInstruments % _nbInstrumentsBlock == 0, "Number of instruments incompatible with block size");
final int nbBlocks = nbInstruments / _nbInstrumentsBlock;
computeCalibrationPrice(curves);
getCalibrationObjective().setCurves(curves);
final SwaptionPhysicalLMMDDSuccessiveLeastSquareCalibrationObjective objective = (SwaptionPhysicalLMMDDSuccessiveLeastSquareCalibrationObjective) getCalibrationObjective();
final NonLinearLeastSquare ls = new NonLinearLeastSquare(DecompositionFactory.SV_COMMONS, MatrixAlgebraFactory.OG_ALGEBRA, DEFAULT_PRECISION);
// final NonLinearLeastSquare ls = new NonLinearLeastSquare();
for (int loopblock = 0; loopblock < nbBlocks; loopblock++) {
final InstrumentDerivative[] instruments = new InstrumentDerivative[_nbInstrumentsBlock];
final double[] prices = new double[_nbInstrumentsBlock];
for (int loopins = 0; loopins < _nbInstrumentsBlock; loopins++) {
instruments[loopins] = getBasket().get(loopblock * _nbInstrumentsBlock + loopins);
prices[loopins] = getCalibrationPrice().get(loopblock * _nbInstrumentsBlock + loopins);
}
getCalibrationObjective().setInstruments(instruments);
getCalibrationObjective().setPrice(prices);
objective.setStartIndex(_instrumentIndex.get(loopblock * _nbInstrumentsBlock));
objective.setEndIndex(_instrumentIndex.get((loopblock + 1) * _nbInstrumentsBlock) - 1);
// Implementation note: the index start is from the first instrument of the block and the index end is from the last instrument of the block.
final DoubleMatrix1D observedValues = new DoubleMatrix1D(_nbInstrumentsBlock, 0.0);
@SuppressWarnings("unused")
final
LeastSquareResults result = ls.solve(observedValues, getCalibrationObjective(), new DoubleMatrix1D(1.0, 0.0));
// Implementation note: the start value is a multiplicative factor of one and an additive term of 0 (parameters unchanged).
// The observed values are 0 as the function returns the difference between the calculated prices and the targets.
}
}
}