public void test_of_SurfaceMetadata() { InterpolatedNodalSurface test = InterpolatedNodalSurface.of(METADATA_ENTRIES, XVALUES, YVALUES, ZVALUES, INTERPOLATOR); assertThat(test.getName()).isEqualTo(SURFACE_NAME); assertThat(test.getParameterCount()).isEqualTo(SIZE); assertThat(test.getParameter(0)).isEqualTo(ZVALUES.get(0)); assertThat(test.getParameter(1)).isEqualTo(ZVALUES.get(1)); assertThat(test.getParameterMetadata(0)).isSameAs(METADATA_ENTRIES.getParameterMetadata().get().get(0)); assertThat(test.getParameterMetadata(1)).isSameAs(METADATA_ENTRIES.getParameterMetadata().get().get(1)); assertThat(test.withParameter(0, 2d)).isEqualTo( InterpolatedNodalSurface.of(METADATA_ENTRIES, XVALUES, YVALUES, ZVALUES.with(0, 2d), INTERPOLATOR)); assertThat(test.withPerturbation((i, v, m) -> v - 2d)).isEqualTo( InterpolatedNodalSurface.of(METADATA_ENTRIES, XVALUES, YVALUES, ZVALUES_BUMPED, INTERPOLATOR)); assertThat(test.getInterpolator()).isEqualTo(INTERPOLATOR); assertThat(test.getMetadata()).isEqualTo(METADATA_ENTRIES); assertThat(test.getXValues()).isEqualTo(XVALUES); assertThat(test.getYValues()).isEqualTo(YVALUES); assertThat(test.getZValues()).isEqualTo(ZVALUES); }
public void test_withZValues() { InterpolatedNodalSurface base = InterpolatedNodalSurface.of(METADATA, XVALUES, YVALUES, ZVALUES, INTERPOLATOR); InterpolatedNodalSurface test = base.withZValues(ZVALUES_BUMPED); assertThat(test.getName()).isEqualTo(SURFACE_NAME); assertThat(test.getParameterCount()).isEqualTo(SIZE); assertThat(test.getMetadata()).isEqualTo(METADATA); assertThat(test.getXValues()).isEqualTo(XVALUES); assertThat(test.getYValues()).isEqualTo(YVALUES); assertThat(test.getZValues()).isEqualTo(ZVALUES_BUMPED); }
public void test_volatility() { for (int i = 0; i < NB_TEST; i++) { double expiryTime = VOLS.relativeTime(TEST_OPTION_EXPIRY[i]); double volExpected = SURFACE.zValue(expiryTime, Math.log(TEST_STRIKE_PRICE[i] / TEST_FUTURE_PRICE[i])); double volComputed = VOLS.volatility( TEST_OPTION_EXPIRY[i], TEST_FUTURE_EXPIRY[i], TEST_STRIKE_PRICE[i], TEST_FUTURE_PRICE[i]); assertEquals(volComputed, volExpected, TOLERANCE_VOL); } }
/** * Restricted copy constructor. * @param beanToCopy the bean to copy from, not null */ private Builder(InterpolatedNodalSurface beanToCopy) { this.metadata = beanToCopy.getMetadata(); this.xValues = beanToCopy.getXValues(); this.yValues = beanToCopy.getYValues(); this.zValues = beanToCopy.getZValues(); this.interpolator = beanToCopy.getInterpolator(); }
public void test_withMetadata() { InterpolatedNodalSurface base = InterpolatedNodalSurface.of(METADATA, XVALUES, YVALUES, ZVALUES, INTERPOLATOR); InterpolatedNodalSurface test = base.withMetadata(METADATA_ENTRIES); assertThat(test.getName()).isEqualTo(SURFACE_NAME); assertThat(test.getParameterCount()).isEqualTo(SIZE); assertThat(test.getMetadata()).isEqualTo(METADATA_ENTRIES); assertThat(test.getXValues()).isEqualTo(XVALUES); assertThat(test.getYValues()).isEqualTo(YVALUES); assertThat(test.getZValues()).isEqualTo(ZVALUES); }
private void testSurfaceSensitivity( CurrencyParameterSensitivity computed, BlackIborCapletFloorletExpiryStrikeVolatilities vols, Function<IborCapletFloorletVolatilities, CurrencyAmount> valueFn) { double pvBase = valueFn.apply(vols).getAmount(); InterpolatedNodalSurface surfaceBase = (InterpolatedNodalSurface) vols.getSurface(); int nParams = surfaceBase.getParameterCount(); for (int i = 0; i < nParams; i++) { DoubleArray zBumped = surfaceBase.getZValues().with(i, surfaceBase.getZValues().get(i) + EPS_FD); InterpolatedNodalSurface surfaceBumped = surfaceBase.withZValues(zBumped); BlackIborCapletFloorletExpiryStrikeVolatilities volsBumped = BlackIborCapletFloorletExpiryStrikeVolatilities.of(vols.getIndex(), vols.getValuationDateTime(), surfaceBumped); double fd = (valueFn.apply(volsBumped).getAmount() - pvBase) / EPS_FD; assertEquals(computed.getSensitivity().get(i), fd, NOTIONAL * EPS_FD); } }
assertEquals(resVol.getValuationDateTime(), CALIBRATION_TIME); InterpolatedNodalSurface surface = (InterpolatedNodalSurface) resVol.getSurface(); for (int i = 0; i < surface.getParameterCount(); ++i) { GenericVolatilitySurfacePeriodParameterMetadata metadata = (GenericVolatilitySurfacePeriodParameterMetadata) surface.getParameterMetadata(i); assertEquals(metadata.getStrike().getValue(), surface.getYValues().get(i));
public void test_nodeSensitivity() { for (int i = 0; i < NB_EXPIRY; i++) { for (int j = 0; j < NB_STRIKE; ++j) { double timeToExpiry = VOLS.relativeTime(TEST_EXPIRY[i]); FxOptionSensitivity sensi = FxOptionSensitivity.of( VOLS.getName(), CURRENCY_PAIR, timeToExpiry, TEST_STRIKE[j], FORWARD[i], GBP, 1d); CurrencyParameterSensitivities computed = VOLS.parameterSensitivity(sensi); for (int k = 0; k < SURFACE.getParameterCount(); k++) { double value = computed.getSensitivities().get(0).getSensitivity().get(k); double nodeExpiry = SURFACE.getXValues().get(k); double nodeStrike = SURFACE.getYValues().get(k); double expected = nodeSensitivity( VOLS, CURRENCY_PAIR, TEST_EXPIRY[i], TEST_STRIKE[j], FORWARD[i], nodeExpiry, nodeStrike); assertEquals(value, expected, EPS); } } } }
public void test_parameterSensitivity() { double expiry = ACT_365F.relativeYearFraction(VAL_DATE, LocalDate.of(2015, 8, 14)); LocalDate fixing = LocalDate.of(2016, 9, 14); double strikePrice = 1.0025; double futurePrice = 0.9975; double sensitivity = 123456; IborFutureOptionSensitivity point = IborFutureOptionSensitivity.of( VOL_SIMPLE_MONEY_RATE.getName(), expiry, fixing, strikePrice, futurePrice, EUR, sensitivity); CurrencyParameterSensitivities ps = VOL_SIMPLE_MONEY_RATE.parameterSensitivity(point); double shift = 1.0E-6; double v0 = VOL_SIMPLE_MONEY_RATE.volatility(expiry, fixing, strikePrice, futurePrice); for (int i = 0; i < NORMAL_VOL_RATES.size(); i++) { DoubleArray v = NORMAL_VOL_RATES.with(i, NORMAL_VOL_RATES.get(i) + shift); InterpolatedNodalSurface param = InterpolatedNodalSurface.of( Surfaces.normalVolatilityByExpirySimpleMoneyness("Rate", ACT_365F, MoneynessType.RATES), TIMES, MONEYNESS_RATES, v, INTERPOLATOR_2D); NormalIborFutureOptionExpirySimpleMoneynessVolatilities vol = NormalIborFutureOptionExpirySimpleMoneynessVolatilities.of(EUR_EURIBOR_3M, VAL_DATE_TIME, param); double vP = vol.volatility(expiry, fixing, strikePrice, futurePrice); double s = ps.getSensitivity(PARAMETERS_RATE.getName(), EUR).getSensitivity().get(i); assertEquals(s, (vP - v0) / shift * sensitivity, TOLERANCE_DELTA); } }
public void test_getter() { assertEquals(VOLS.getValuationDate(), VAL_DATE); assertEquals(VOLS.getIndex(), GBP_LIBOR_3M); assertEquals(VOLS.getSurface(), SURFACE); assertEquals(VOLS.getParameterCount(), TIME.size()); assertEquals(VOLS.findData(CURVE.getName()).get(), CURVE); assertEquals(VOLS.findData(SURFACE.getName()).get(), SURFACE); assertFalse(VOLS.findData(CurveName.of("foo")).isPresent()); int nParams = VOLS.getParameterCount(); double newValue = 152d; for (int i = 0; i < nParams; ++i) { assertEquals(VOLS.getParameter(i), SURFACE.getParameter(i)); assertEquals(VOLS.getParameterMetadata(i), SURFACE.getParameterMetadata(i)); assertEquals(VOLS.withParameter(i, newValue), ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities.of( GBP_LIBOR_3M, VAL_DATE_TIME, SURFACE.withParameter(i, newValue), CURVE)); assertEquals(VOLS.withPerturbation((n, v, m) -> 2d * v), ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities.of( GBP_LIBOR_3M, VAL_DATE_TIME, SURFACE.withPerturbation((n, v, m) -> 2d * v), CURVE)); } }
public void test_serialization() { InterpolatedNodalSurface test = InterpolatedNodalSurface.of(METADATA, XVALUES, YVALUES, ZVALUES, INTERPOLATOR); assertSerialization(test); }
@Override public InterpolatedNodalSurface withParameter(int parameterIndex, double newValue) { return withZValues(zValues.with(parameterIndex, newValue)); }
@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); }
public void test_withZValues_badSize() { InterpolatedNodalSurface base = InterpolatedNodalSurface.of(METADATA, XVALUES, YVALUES, ZVALUES, INTERPOLATOR); assertThrowsIllegalArg(() -> base.withZValues(DoubleArray.EMPTY)); assertThrowsIllegalArg(() -> base.withZValues(DoubleArray.of(4d, 6d))); }
private InterpolatedNodalSurface[] bumpSurface(InterpolatedNodalSurface surface, int position) { DoubleArray zValues = surface.getZValues(); InterpolatedNodalSurface surfaceUp = surface.withZValues(zValues.with(position, zValues.get(position) + EPS)); InterpolatedNodalSurface surfaceDw = surface.withZValues(zValues.with(position, zValues.get(position) - EPS)); return new InterpolatedNodalSurface[] {surfaceUp, surfaceDw }; }
public void test_lookup() { InterpolatedNodalSurface test = InterpolatedNodalSurface.of(METADATA, XVALUES, YVALUES, ZVALUES, INTERPOLATOR); assertThat(test.zValue(XVALUES.get(0), YVALUES.get(0))).isEqualTo(ZVALUES.get(0)); assertThat(test.zValue(XVALUES.get(1), YVALUES.get(1))).isEqualTo(ZVALUES.get(1)); assertThat(test.zValue(XVALUES.get(2), YVALUES.get(2))).isEqualTo(ZVALUES.get(2)); assertThat(test.zValue(0d, 1.5d)).isEqualTo(6d); assertThat(test.zValue(1d, 3d)).isEqualTo(7d); BoundSurfaceInterpolator bound = INTERPOLATOR.bind(XVALUES, YVALUES, ZVALUES); assertThat(test.zValue(1.5d, 3.7d)).isEqualTo(bound.interpolate(1.5d, 3.7d)); DoubleArray sensiValues = test.zValueParameterSensitivity(1.5d, 1.5d).getSensitivity(); DoubleArray sensiValuesInterp = bound.parameterSensitivity(1.5d, 1.5d); assertTrue(sensiValues.equalWithTolerance(sensiValuesInterp, 1e-8)); }
@Override public CurrencyParameterSensitivity createParameterSensitivity(Currency currency, DoubleArray sensitivities) { return CurrencyParameterSensitivity.of(getName(), parameterMetadata, currency, sensitivities); }
CurrencyParameterSensitivity sensiCouponAlpha = computedCoupon.getSensitivity(surfaceAlpha.getName(), EUR); int nParamsAlpha = surfaceAlpha.getParameterCount(); for (int i = 0; i < nParamsAlpha; ++i) { InterpolatedNodalSurface[] bumpedSurfaces = bumpSurface(surfaceAlpha, i); coupon, caplet, foorlet, ratesProvider, i, sensiCouponAlpha.getSensitivity(), computedCap.getSensitivity(surfaceAlpha.getName(), EUR).getSensitivity(), computedFloor.getSensitivity(surfaceAlpha.getName(), EUR).getSensitivity(), replaceSabrParameters(sabrUp, volatilities), replaceSabrParameters(sabrDw, volatilities)); CurrencyParameterSensitivity sensiCouponBeta = computedCoupon.getSensitivity(surfaceBeta.getName(), EUR); int nParamsBeta = surfaceBeta.getParameterCount(); for (int i = 0; i < nParamsBeta; ++i) { InterpolatedNodalSurface[] bumpedSurfaces = bumpSurface(surfaceBeta, i); coupon, caplet, foorlet, ratesProvider, i, sensiCouponBeta.getSensitivity(), computedCap.getSensitivity(surfaceBeta.getName(), EUR).getSensitivity(), computedFloor.getSensitivity(surfaceBeta.getName(), EUR).getSensitivity(), replaceSabrParameters(sabrUp, volatilities), replaceSabrParameters(sabrDw, volatilities)); CurrencyParameterSensitivity sensiCouponRho = computedCoupon.getSensitivity(surfaceRho.getName(), EUR); int nParamsRho = surfaceRho.getParameterCount(); for (int i = 0; i < nParamsRho; ++i) { InterpolatedNodalSurface[] bumpedSurfaces = bumpSurface(surfaceRho, i);
@ImmutableConstructor private InterpolatedNodalSurface( SurfaceMetadata metadata, DoubleArray xValues, DoubleArray yValues, DoubleArray zValues, SurfaceInterpolator interpolator) { validateInputs(metadata, xValues, yValues, zValues, interpolator); for (int i = 1; i < xValues.size(); i++) { if (xValues.get(i) < xValues.get(i - 1)) { throw new IllegalArgumentException("Array of x-values must be sorted"); } if (xValues.get(i) == xValues.get(i - 1) && yValues.get(i) <= yValues.get(i - 1)) { throw new IllegalArgumentException("Array of y-values must be sorted and unique within x-values"); } } this.metadata = metadata; this.xValues = xValues; this.yValues = yValues; this.zValues = zValues; this.interpolator = interpolator; this.boundInterpolator = interpolator.bind(xValues, yValues, zValues); this.parameterMetadata = IntStream.range(0, getParameterCount()) .mapToObj(i -> metadata.getParameterMetadata(i)) .collect(toImmutableList()); }
private Function<DoubleArray, DoubleMatrix> getJacobianFunction( List<ResolvedIborCapFloorLeg> capList, RatesProvider ratesProvider, Function<Surface, IborCapletFloorletVolatilities> volatilitiesFunction, InterpolatedNodalSurface baseSurface) { int nCaps = capList.size(); int nNodes = baseSurface.getParameterCount(); Function<DoubleArray, DoubleMatrix> jacobianFunction = new Function<DoubleArray, DoubleMatrix>() { @Override public DoubleMatrix apply(DoubleArray capletVols) { IborCapletFloorletVolatilities newVols = volatilitiesFunction.apply(baseSurface.withZValues(capletVols)); return DoubleMatrix.ofArrayObjects( nCaps, nNodes, n -> newVols.parameterSensitivity( getLegPricer().presentValueSensitivityModelParamsVolatility(capList.get(n), ratesProvider, newVols).build()) .getSensitivities() .get(0) .getSensitivity()); } }; return jacobianFunction; }