Package com.opengamma.analytics.financial.model.volatility.smile.fitting

Source Code of com.opengamma.analytics.financial.model.volatility.smile.fitting.SmileModelFitter

/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.model.volatility.smile.fitting;

import java.util.BitSet;

import org.apache.commons.lang.Validate;

import com.opengamma.analytics.financial.model.volatility.smile.function.SmileModelData;
import com.opengamma.analytics.financial.model.volatility.smile.function.VolatilityFunctionProvider;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.linearalgebra.DecompositionFactory;
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.NonLinearParameterTransforms;
import com.opengamma.analytics.math.minimization.NonLinearTransformFunction;
import com.opengamma.analytics.math.statistics.leastsquare.LeastSquareResults;
import com.opengamma.analytics.math.statistics.leastsquare.LeastSquareResultsWithTransform;
import com.opengamma.analytics.math.statistics.leastsquare.NonLinearLeastSquare;

/**
*
* @param <T> The data for the smile model used
*/
public abstract class SmileModelFitter<T extends SmileModelData> {
  private static final MatrixAlgebra MA = new OGMatrixAlgebra();
  private static final NonLinearLeastSquare SOLVER = new NonLinearLeastSquare(DecompositionFactory.SV_COLT, MA, 1e-12);
  private static final Function1D<DoubleMatrix1D, Boolean> UNCONSTRAINED = new Function1D<DoubleMatrix1D, Boolean>() {
    @Override
    public Boolean evaluate(final DoubleMatrix1D x) {
      return true;
    }
  };

  private final VolatilityFunctionProvider<T> _model;
  private final Function1D<T, double[]> _volFunc;
  private final Function1D<T, double[][]> _volAdjointFunc;
  private final DoubleMatrix1D _marketValues;
  private final DoubleMatrix1D _errors;

  /**
   * Attempts to calibrate a model to the implied volatilities of European vanilla options, by minimising the sum of squares between the
   * market and model implied volatilities. All the options must be for the same expiry and (implicitly) on the same underlying.
   * @param forward The forward value of the underlying
   * @param strikes ordered values of strikes
   * @param timeToExpiry The time-to-expiry
   * @param impliedVols The market implied volatilities
   * @param error The 'measurement' error to apply to the market volatility of a particular option TODO: Review should this be part of  EuropeanOptionMarketData?
   * @param model VolatilityFunctionProvider
   */
  public SmileModelFitter(final double forward, final double[] strikes, final double timeToExpiry, final double[] impliedVols,
      final double[] error, final VolatilityFunctionProvider<T> model) {
    Validate.notNull(strikes, "null strikes");
    Validate.notNull(impliedVols, "null implied vols");
    Validate.notNull(error, "null errors");
    Validate.notNull(model, "null model");
    final int n = strikes.length;
    Validate.isTrue(n == impliedVols.length, "vols not the same length as strikes");
    Validate.isTrue(n == error.length, "errors not the same length as strikes");

    _marketValues = new DoubleMatrix1D(impliedVols);
    _errors = new DoubleMatrix1D(error);

    _volFunc = model.getVolatilityFunction(forward, strikes, timeToExpiry);
    _volAdjointFunc = model.getModelAdjointFunction(forward, strikes, timeToExpiry);
    _model = model;
  }

  /**
   * Solve using the default NonLinearParameterTransforms for the concrete implementation
   * @param start The first guess at the parameter values
   * @return The LeastSquareResults
   */
  public LeastSquareResultsWithTransform solve(final DoubleMatrix1D start) {
    return solve(start, new BitSet());
  }

  /**
   * Solve using the default NonLinearParameterTransforms for the concrete implementation, but with some parameters fixed to their initial
   * values (indicated by fixed)
   * @param start The first guess at the parameter values
   * @param fixed Indicates which parameters are fixed
   * @return The LeastSquareResults
   */
  public LeastSquareResultsWithTransform solve(final DoubleMatrix1D start, final BitSet fixed) {
    final NonLinearParameterTransforms transform = getTransform(start, fixed);
    return solve(start, transform);
  }

  /**
   * Solve using a user supplied NonLinearParameterTransforms
   * @param start The first guess at the parameter values
   * @param transform Transform from model parameters to fitting parameters, and vice versa
   * @return The LeastSquareResults
   */
  public LeastSquareResultsWithTransform solve(final DoubleMatrix1D start, final NonLinearParameterTransforms transform) {
    final NonLinearTransformFunction transFunc = new NonLinearTransformFunction(getModelValueFunction(), getModelJacobianFunction(), transform);

    final LeastSquareResults solRes = SOLVER.solve(_marketValues, _errors, transFunc.getFittingFunction(), transFunc.getFittingJacobian(),
        transform.transform(start), getConstraintFunction(transform), getMaximumStep());
    return new LeastSquareResultsWithTransform(solRes, transform);
  }

  protected Function1D<DoubleMatrix1D, DoubleMatrix1D> getModelValueFunction() {

    return new Function1D<DoubleMatrix1D, DoubleMatrix1D>() {
      @SuppressWarnings("synthetic-access")
      @Override
      public DoubleMatrix1D evaluate(final DoubleMatrix1D x) {
        final T data = toSmileModelData(x);
        final double[] res = _volFunc.evaluate(data);
        return new DoubleMatrix1D(res);
      }
    };
  }

  protected Function1D<DoubleMatrix1D, DoubleMatrix2D> getModelJacobianFunction() {

    return new Function1D<DoubleMatrix1D, DoubleMatrix2D>() {
      @SuppressWarnings("synthetic-access")
      @Override
      public DoubleMatrix2D evaluate(final DoubleMatrix1D x) {
        final T data = toSmileModelData(x);
        //this thing will be (#strikes/vols) x (# model Params)
        final double[][] volAdjoint = _volAdjointFunc.evaluate(data);
        return new DoubleMatrix2D(volAdjoint);
      }
    };
  }

  protected abstract DoubleMatrix1D getMaximumStep();

  protected abstract NonLinearParameterTransforms getTransform(final DoubleMatrix1D start);

  protected abstract NonLinearParameterTransforms getTransform(final DoubleMatrix1D start, final BitSet fixed);

  protected abstract T toSmileModelData(final DoubleMatrix1D modelParameters);

  protected Function1D<DoubleMatrix1D, Boolean> getConstraintFunction(@SuppressWarnings("unused") final NonLinearParameterTransforms t) {
    return UNCONSTRAINED;
  }

  public VolatilityFunctionProvider<T> getModel() {
    return _model;
  }

}
TOP

Related Classes of com.opengamma.analytics.financial.model.volatility.smile.fitting.SmileModelFitter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.