/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.model.volatility.surface; import java.util.List; import com.opengamma.analytics.math.function.Function1D; import com.opengamma.analytics.math.function.Function2D; import com.opengamma.analytics.math.interpolation.BasisFunctionAggregation; import com.opengamma.analytics.math.interpolation.BasisFunctionGenerator; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.analytics.math.surface.FunctionalDoublesSurface; import com.opengamma.analytics.math.surface.FunctionalSurface; import com.opengamma.analytics.math.surface.Surface; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.tuple.Pair; /** * Represent a volatility term structure (in this context a volatility surface with no strike dependence) using * 1D basis-splines */ public class BasisSplineVolatilityTermStructureProvider implements VolatilitySurfaceProvider { private final List<Function1D<Double, Double>> _bSplines; /** * Represent a volatility term structure (in this context a volatility surface with no strike dependence) using * 1D basis-splines * @param bSlines List of 1D functions (of time-to-expiry) - the basis functions */ public BasisSplineVolatilityTermStructureProvider(final List<Function1D<Double, Double>> bSlines) { ArgumentChecker.noNulls(bSlines, "null bSplines"); _bSplines = bSlines; } /** * Represent a volatility term structure (in this context a volatility surface with no strike dependence) using * 1D basis-splines * @param t1 The lower time * @param t2 The upper time * @param nKnots Number of knots * @param degree The degree of the spline */ public BasisSplineVolatilityTermStructureProvider(final double t1, final double t2, final int nKnots, final int degree) { final BasisFunctionGenerator gen = new BasisFunctionGenerator(); _bSplines = gen.generateSet(t1, t2, nKnots, degree); } /** * {@inheritDoc} * The model parameters in this case are the weights of the basis functions */ @Override public VolatilitySurface getVolSurface(final DoubleMatrix1D modelParameters) { ArgumentChecker.notNull(modelParameters, "modelParameters"); //BasisFunctionAggregation checks length of modelParameters final Function1D<Double, Double> func = new BasisFunctionAggregation<>(_bSplines, modelParameters.getData()); final Function2D<Double, Double> func2D = new Function2D<Double, Double>() { @Override public Double evaluate(final Double t, final Double k) { return func.evaluate(t); } }; final FunctionalDoublesSurface surface = new FunctionalDoublesSurface(func2D); return new VolatilitySurface(surface); } /** * {@inheritDoc} * The model parameters in this case are the weights of the basis functions */ @Override public Surface<Double, Double, DoubleMatrix1D> getParameterSensitivitySurface(final DoubleMatrix1D modelParameters) { ArgumentChecker.notNull(modelParameters, "modelParameters"); //BasisFunctionAggregation checks length of modelParameters final BasisFunctionAggregation<Double> bSpline = new BasisFunctionAggregation<>(_bSplines, modelParameters.getData()); final Function2D<Double, DoubleMatrix1D> func = new Function2D<Double, DoubleMatrix1D>() { @Override public DoubleMatrix1D evaluate(final Double t, final Double k) { return bSpline.weightSensitivity(t); } }; return new FunctionalSurface<>(func); } @Override public Surface<Double, Double, Pair<Double, DoubleMatrix1D>> getVolAndParameterSensitivitySurface(final DoubleMatrix1D modelParameters) { ArgumentChecker.notNull(modelParameters, "modelParameters"); //BasisFunctionAggregation checks length of modelParameters final BasisFunctionAggregation<Double> bSpline = new BasisFunctionAggregation<>(_bSplines, modelParameters.getData()); final Function2D<Double, Pair<Double, DoubleMatrix1D>> func = new Function2D<Double, Pair<Double, DoubleMatrix1D>>() { @Override public Pair<Double, DoubleMatrix1D> evaluate(final Double t, final Double k) { return bSpline.valueAndWeightSensitivity(t); } }; return new FunctionalSurface<>(func); } /** * {@inheritDoc} * The number of parameters is the number of basis functions, which is #knots + degree - 1 */ @Override public int getNumModelParameters() { return _bSplines.size(); } }