/**
* 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;
import java.util.BitSet;
import com.opengamma.analytics.financial.model.volatility.smile.function.MixedLogNormalModelData;
import com.opengamma.analytics.financial.model.volatility.smile.function.VolatilityFunctionProvider;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.minimization.NonLinearParameterTransforms;
import com.opengamma.analytics.math.minimization.NullTransform;
import com.opengamma.analytics.math.minimization.ParameterLimitsTransform;
import com.opengamma.analytics.math.minimization.UncoupledParameterTransforms;
/**
*
*/
public class MixedLogNormalModelFitter extends SmileModelFitter<MixedLogNormalModelData> {
//private static final double PI_BY_2 = Math.PI / 2.0;
private final ParameterLimitsTransform[] _transforms;
private final boolean _useShiftedMean;
private final int _nNormals;
public MixedLogNormalModelFitter(final double forward, final double[] strikes, final double timeToExpiry, final double[] impliedVols, final double[] error,
final VolatilityFunctionProvider<MixedLogNormalModelData> model,
final int numNormals, final boolean useShiftedMeans) {
super(forward, strikes, timeToExpiry, impliedVols, error, model);
final int n = useShiftedMeans ? 3 * numNormals - 2 : 2 * numNormals - 1;
_transforms = new ParameterLimitsTransform[n];
// for (int i = 0; i < numNormals; i++) {
// _transforms[i] = new SingleRangeLimitTransform(0.0, LimitType.GREATER_THAN);
// }
//TODO investigate whether it is better to restrict the range of angles
for (int i = 0; i < n; i++) {
_transforms[i] = new NullTransform();
}
_useShiftedMean = useShiftedMeans;
_nNormals = numNormals;
}
@Override
protected NonLinearParameterTransforms getTransform(final DoubleMatrix1D start) {
final BitSet fixed = new BitSet();
return new UncoupledParameterTransforms(start, _transforms, fixed);
}
@Override
protected NonLinearParameterTransforms getTransform(final DoubleMatrix1D start, final BitSet fixed) {
return new UncoupledParameterTransforms(start, _transforms, fixed);
}
@Override
public MixedLogNormalModelData toSmileModelData(final DoubleMatrix1D modelParameters) {
return new MixedLogNormalModelData(modelParameters.getData(), _useShiftedMean);
}
@Override
protected Function1D<DoubleMatrix1D, Boolean> getConstraintFunction(final NonLinearParameterTransforms t) {
return new Function1D<DoubleMatrix1D, Boolean>() {
@SuppressWarnings("synthetic-access")
@Override
public Boolean evaluate(final DoubleMatrix1D x) {
if (x.getEntry(0) <= 1e-4) {
return false;
}
for (int i = 1; i < _nNormals; i++) {
if (x.getEntry(i) < 0.0) {
return false;
}
}
//Don't constrain angles
// for (int i = 0; i < _nNormals - 1; i++) {
// double temp = x.getEntry(i + _nNormals);
// if (temp < 0.0 || temp > PI_BY_2) {
// return true;
// }
// if (_useShiftedMean) {
// temp = x.getEntry(i + 2 * _nNormals - 1);
// if (temp < 0.0 || temp > PI_BY_2) {
// return true;
// }
// }
// }
return true;
}
};
}
@Override
protected DoubleMatrix1D getMaximumStep() {
final int n = _useShiftedMean ? 3 * _nNormals - 2 : 2 * _nNormals - 1;
return new DoubleMatrix1D(n, 0.1);
}
}