/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.interestrate.capletstripping;
import java.util.Arrays;
import com.opengamma.analytics.financial.model.volatility.discrete.DiscreteVolatilityFunctionProvider;
import com.opengamma.analytics.financial.model.volatility.discrete.DiscreteVolatilityFunctionProviderFromVolSurface;
import com.opengamma.analytics.financial.model.volatility.surface.BasisSplineVolatilityTermStructureProvider;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.interpolation.PenaltyMatrixGenerator;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.matrix.DoubleMatrix2D;
import com.opengamma.analytics.math.matrix.MatrixAlgebra;
import com.opengamma.analytics.math.matrix.OGMatrixAlgebra;
import com.opengamma.analytics.math.minimization.PositiveOrZero;
import com.opengamma.util.ArgumentChecker;
/**
* This represents the (caplet) volatility surface using a curve (built from basis-splines) in the expiry direction
* only (i.e. there is no strike dependence). A penalty on the curvature of the curve is applied, and we solve for the
* market cap (or floor) values in a (penalised) least-squares sense. <p>
* This is mainly used to strip a single strike. If used with multiple strikes, the lack of strike
* dependence will make it impossible to recover the market values.
* @see {@link CapletStripperInterpolatedTermStructure}
*/
public class CapletStripperPSplineTermStructure implements CapletStripper {
private static final MatrixAlgebra MA = new OGMatrixAlgebra();
private static final Function1D<DoubleMatrix1D, Boolean> POSITIVE = new PositiveOrZero();
private final CapletStrippingCore _imp;
private final DoubleMatrix2D _penalty;
private final int _size;
/**
*
* @param pricer The pricer (which contained the details of the market values of the caps/floors)
* @param vtsp provider of volatility term structures made from basis-spline
* @param lambda the strength of the penalty
*/
public CapletStripperPSplineTermStructure(final MultiCapFloorPricer pricer, final BasisSplineVolatilityTermStructureProvider vtsp, final double lambda) {
final DiscreteVolatilityFunctionProvider volFuncPro = new DiscreteVolatilityFunctionProviderFromVolSurface(vtsp);
_imp = new CapletStrippingCore(pricer, volFuncPro);
_size = vtsp.getNumModelParameters();
_penalty = (DoubleMatrix2D) MA.scale(PenaltyMatrixGenerator.getPenaltyMatrix(_size, 2), lambda);
}
@Override
public CapletStrippingResult solve(final double[] marketValues, final MarketDataType type) {
ArgumentChecker.notNull(marketValues, "marketValues");
final int n = marketValues.length;
final double[] errors = new double[n];
Arrays.fill(errors, 1.0);
final DoubleMatrix1D guess = new DoubleMatrix1D(_size, 0.4);
return solve(marketValues, type, errors, guess);
}
@Override
public CapletStrippingResult solve(final double[] marketValues, final MarketDataType type, final double[] errors) {
final DoubleMatrix1D guess = new DoubleMatrix1D(_size, 0.4);
return solve(marketValues, type, errors, guess);
}
@Override
public CapletStrippingResult solve(final double[] marketValues, final MarketDataType type, final DoubleMatrix1D guess) {
ArgumentChecker.notNull(marketValues, "marketValues");
final int n = marketValues.length;
final double[] errors = new double[n];
Arrays.fill(errors, 1.0);
return solve(marketValues, type, errors, guess);
}
@Override
public CapletStrippingResult solve(final double[] marketValues, final MarketDataType type, final double[] errors, final DoubleMatrix1D guess) {
if (type == MarketDataType.PRICE) {
return _imp.solveForCapPrices(marketValues, errors, guess, _penalty, POSITIVE);
} else if (type == MarketDataType.VOL) {
return _imp.solveForCapVols(marketValues, errors, guess, _penalty, POSITIVE);
}
throw new IllegalArgumentException("Unknown MarketDataType " + type.toString());
}
}