com.opengamma.strata.pricer.impl.volatility.smile.SabrModelFitter Maven / Gradle / Ivy
/*
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.pricer.impl.volatility.smile;
import java.util.BitSet;
import com.opengamma.strata.collect.array.DoubleArray;
import com.opengamma.strata.math.impl.minimization.DoubleRangeLimitTransform;
import com.opengamma.strata.math.impl.minimization.NonLinearParameterTransforms;
import com.opengamma.strata.math.impl.minimization.ParameterLimitsTransform;
import com.opengamma.strata.math.impl.minimization.ParameterLimitsTransform.LimitType;
import com.opengamma.strata.math.impl.minimization.SingleRangeLimitTransform;
import com.opengamma.strata.math.impl.minimization.UncoupledParameterTransforms;
import com.opengamma.strata.pricer.model.SabrVolatilityFormula;
/**
* SABR model fitter.
*
* Attempts to calibrate SABR model to the implied volatilities of European vanilla options, by minimizing 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.
*/
public final class SabrModelFitter extends SmileModelFitter {
private static final double RHO_LIMIT = 0.999;
// Allowing for rho to be equal to 1 or -1 does not make sense from a financial point of view and creates numerical instability
private static final ParameterLimitsTransform[] DEFAULT_TRANSFORMS;
static {
DEFAULT_TRANSFORMS = new ParameterLimitsTransform[4];
DEFAULT_TRANSFORMS[0] = new SingleRangeLimitTransform(0, LimitType.GREATER_THAN); // alpha > 0
DEFAULT_TRANSFORMS[1] = new DoubleRangeLimitTransform(0, 1.0); // 0 <= beta <= 1
DEFAULT_TRANSFORMS[2] = new DoubleRangeLimitTransform(-RHO_LIMIT, RHO_LIMIT); // -RHO_LIMIT <= rho <= RHO_LIMIT
DEFAULT_TRANSFORMS[3] = new DoubleRangeLimitTransform(0.01d, 2.50d);
// nu > 0 and limit on Nu to avoid numerical instability in formula for large nu.
}
//-------------------------------------------------------------------------
/**
* Constructs SABR model fitter from forward, strikes, time to expiry, implied volatilities and error values.
*
* {@code strikes}, {@code impliedVols} and {@code error} should be the same length and ordered coherently.
*
* @param forward the forward value of the underlying
* @param strikes the 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
* @param sabrVolatilityFormula the volatility formula
*/
@SuppressWarnings("unchecked")
public SabrModelFitter(
double forward,
DoubleArray strikes,
double timeToExpiry,
DoubleArray impliedVols,
DoubleArray error,
SabrVolatilityFormula sabrVolatilityFormula) {
super(
forward,
strikes,
timeToExpiry,
impliedVols,
error,
(VolatilityFunctionProvider) sabrVolatilityFormula);
}
/**
* Constructs SABR model fitter from forward, strikes, time to expiry, implied volatilities and error values.
*
* {@code strikes}, {@code impliedVols} and {@code error} should be the same length and ordered coherently.
*
* @param forward the forward value of the underlying
* @param strikes the 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
* @param model the volatility function provider
*/
public SabrModelFitter(
double forward,
DoubleArray strikes,
double timeToExpiry,
DoubleArray impliedVols,
DoubleArray error,
VolatilityFunctionProvider model) {
super(forward, strikes, timeToExpiry, impliedVols, error, model);
}
//-------------------------------------------------------------------------
@Override
public SabrFormulaData toSmileModelData(DoubleArray modelParameters) {
return SabrFormulaData.of(modelParameters.toArray());
}
@Override
protected NonLinearParameterTransforms getTransform(DoubleArray start) {
final BitSet fixed = new BitSet();
return new UncoupledParameterTransforms(start, DEFAULT_TRANSFORMS, fixed);
}
@Override
protected NonLinearParameterTransforms getTransform(DoubleArray start, BitSet fixed) {
return new UncoupledParameterTransforms(start, DEFAULT_TRANSFORMS, fixed);
}
@Override
protected DoubleArray getMaximumStep() {
return null;
}
}