/** * Applies a perturbation to the specified underlying. * <p> * This should be invoked once for each of the underlying instances. * It is intended to be used to pass the result of each invocation to the * constructor of the combined instance. * * @param <R> the type of the underlying * @param underlyingIndex the index of the underlying instance * @param underlyingType the type of the parameterized data at the specified index * @param perturbation the perturbation to apply * @return a parameterized data instance based on this with the specified perturbation applied */ public <R extends ParameterizedData> R underlyingWithPerturbation( int underlyingIndex, Class<R> underlyingType, ParameterPerturbation perturbation) { ParameterizedData underlying = underlyings[underlyingIndex]; // perturb using a derived perturbation that adjusts the index int adjustment = lookup[underlyingIndex]; ParameterizedData perturbed = underlying.withPerturbation( (idx, value, meta) -> perturbation.perturbParameter(idx + adjustment, value, meta)); return underlyingType.cast(perturbed); }
@Override public ConstantRecoveryRates withPerturbation(ParameterPerturbation perturbation) { double perturbedValue = perturbation.perturbParameter(0, recoveryRate, getParameterMetadata(0)); return new ConstantRecoveryRates(legalEntityId, valuationDate, perturbedValue); }
@Override public ConstantCurve withPerturbation(ParameterPerturbation perturbation) { return new ConstantCurve(metadata, perturbation.perturbParameter(0, yValue, getParameterMetadata(0))); }
@Override public ConstantNodalCurve withPerturbation(ParameterPerturbation perturbation) { double perturbedValue = perturbation.perturbParameter(0, yValue, getParameterMetadata(0)); return new ConstantNodalCurve(metadata, xValue, perturbedValue); }
@Override public ConstantSurface withPerturbation(ParameterPerturbation perturbation) { return new ConstantSurface(metadata, perturbation.perturbParameter(0, zValue, getParameterMetadata(0))); }
@Override public ParallelShiftedCurve withPerturbation(ParameterPerturbation perturbation) { Curve bumpedCurve = underlyingCurve.withPerturbation(perturbation); int shiftIndex = underlyingCurve.getParameterCount(); double bumpedShift = perturbation.perturbParameter(shiftIndex, shiftAmount, getParameterMetadata(shiftIndex)); return new ParallelShiftedCurve(bumpedCurve, shiftType, bumpedShift); }
@Override public SmileDeltaParameters withPerturbation(ParameterPerturbation perturbation) { int size = volatility.size(); DoubleArray perturbedValues = DoubleArray.of( size, i -> perturbation.perturbParameter(i, volatility.get(i), getParameterMetadata(i))); return new SmileDeltaParameters(expiry, delta, perturbedValues, parameterMetadata); }
@Override public InterpolatedNodalCurve withPerturbation(ParameterPerturbation perturbation) { int size = yValues.size(); DoubleArray perturbedValues = DoubleArray.of( size, i -> perturbation.perturbParameter(i, yValues.get(i), getParameterMetadata(i))); return withYValues(perturbedValues); }
@Override public CombinedCurve withPerturbation(ParameterPerturbation perturbation) { Curve newBaseCurve = baseCurve.withPerturbation( (idx, value, meta) -> perturbation.perturbParameter( idx, baseCurve.getParameter(idx), baseCurve.getParameterMetadata(idx))); int offset = baseCurve.getParameterCount(); Curve newSpreadCurve = spreadCurve.withPerturbation( (idx, value, meta) -> perturbation.perturbParameter( idx + offset, spreadCurve.getParameter(idx), spreadCurve.getParameterMetadata(idx))); List<ParameterMetadata> newParamMeta = Stream.concat( IntStream.range(0, newBaseCurve.getParameterCount()) .mapToObj(i -> newBaseCurve.getParameterMetadata(i)), IntStream.range(0, newSpreadCurve.getParameterCount()) .mapToObj(i -> newSpreadCurve.getParameterMetadata(i))) .collect(toImmutableList()); return CombinedCurve.of( newBaseCurve, newSpreadCurve, metadata.withParameterMetadata(newParamMeta)); }
@Override public ParameterizedFunctionalCurve withPerturbation(ParameterPerturbation perturbation) { int size = parameters.size(); DoubleArray perturbedValues = DoubleArray.of( size, i -> perturbation.perturbParameter(i, parameters.get(i), getParameterMetadata(i))); return withParameters(perturbedValues); }
@Override public InterpolatedNodalSurface withPerturbation(ParameterPerturbation perturbation) { int size = zValues.size(); DoubleArray perturbedValues = DoubleArray.of( size, i -> perturbation.perturbParameter(i, zValues.get(i), getParameterMetadata(i))); return withZValues(perturbedValues); }
/** * Returns a perturbed copy of the data. * <p> * The perturbation instance will be invoked once for each parameter in this instance, * returning the perturbed value for that parameter. The result of this method is a * new instance that is based on those perturbed values. * <p> * This instance is immutable and unaffected by this method call. * * @param perturbation the perturbation to apply * @return a parameterized data instance based on this with the specified perturbation applied */ public default ParameterizedData withPerturbation(ParameterPerturbation perturbation) { ParameterizedData result = this; for (int i = 0; i < getParameterCount(); i++) { double currentValue = getParameter(i); double perturbedValue = perturbation.perturbParameter(i, currentValue, getParameterMetadata(i)); // compare using Double.doubleToLongBits() result = JodaBeanUtils.equal(currentValue, perturbedValue) ? result : result.withParameter(i, perturbedValue); } return result; }