/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.model.volatility.smile.fitting.interpolation;
import java.util.BitSet;
import cern.jet.random.engine.RandomEngine;
import com.opengamma.analytics.financial.model.volatility.smile.fitting.MixedLogNormalModelFitter;
import com.opengamma.analytics.financial.model.volatility.smile.fitting.SmileModelFitter;
import com.opengamma.analytics.financial.model.volatility.smile.function.MixedLogNormalModelData;
import com.opengamma.analytics.financial.model.volatility.smile.function.MixedLogNormalVolatilityFunction;
import com.opengamma.analytics.financial.model.volatility.smile.function.VolatilityFunctionProvider;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.util.ArgumentChecker;
/**
*
*/
public class SmileInterpolatorMixedLogNormal extends SmileInterpolator<MixedLogNormalModelData> {
private static final VolatilityFunctionProvider<MixedLogNormalModelData> MODEL = MixedLogNormalVolatilityFunction.getInstance();
public SmileInterpolatorMixedLogNormal() {
super(MODEL);
}
public SmileInterpolatorMixedLogNormal(final int seed) {
super(seed, MODEL);
}
public SmileInterpolatorMixedLogNormal(final WeightingFunction weightingFunction) {
super(MODEL, weightingFunction);
}
public SmileInterpolatorMixedLogNormal(final int seed, final WeightingFunction weightingFunction) {
super(seed, MODEL, weightingFunction);
}
@Override
protected DoubleMatrix1D getGlobalStart(final double forward, final double[] strikes, final double expiry, final double[] impliedVols) {
final RandomEngine random = getRandom();
final DoubleMatrix1D fitP = getPolynomialFit(forward, strikes, impliedVols);
final double a = fitP.getEntry(0);
final double b = fitP.getEntry(1);
final double c = fitP.getEntry(2);
if (Math.abs(b) < 1e-3 && Math.abs(c) < 1e-3) { //almost flat smile
final double theta = Math.PI / 2 - 0.01;
return new DoubleMatrix1D(a, 0.01, theta, theta);
}
final double theta = Math.PI / 2 * random.nextDouble();
return new DoubleMatrix1D(a * (0.8 + 0.4 * random.nextDouble()), a * 0.5 * random.nextDouble(), theta, theta);
}
@Override
protected BitSet getLocalFixedValues() {
final BitSet res = new BitSet();
res.set(2); //fit vol 0 for local (3-point) fit
return res;
}
@Override
protected MixedLogNormalModelData toSmileModelData(final DoubleMatrix1D modelParameters) {
ArgumentChecker.notNull(modelParameters, "model parameters");
return new MixedLogNormalModelData(modelParameters.getData());
}
@Override
protected SmileModelFitter<MixedLogNormalModelData> getFitter(final double forward, final double[] strikes, final double expiry, final double[] impliedVols, final double[] errors) {
return new MixedLogNormalModelFitter(forward, strikes, expiry, impliedVols, errors, MODEL, 2, true);
}
}