/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.pricer.index; import static com.opengamma.strata.basics.currency.Currency.EUR; import static com.opengamma.strata.basics.index.IborIndices.EUR_EURIBOR_3M; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import java.time.LocalDate; import org.testng.annotations.Test; import com.opengamma.strata.basics.ReferenceData; import com.opengamma.strata.basics.currency.CurrencyAmount; import com.opengamma.strata.collect.DoubleArrayMath; import com.opengamma.strata.collect.array.DoubleArray; import com.opengamma.strata.market.param.CurrencyParameterSensitivities; import com.opengamma.strata.market.sensitivity.PointSensitivities; import com.opengamma.strata.pricer.model.HullWhiteOneFactorPiecewiseConstantParameters; import com.opengamma.strata.pricer.model.HullWhiteOneFactorPiecewiseConstantParametersProvider; import com.opengamma.strata.pricer.rate.ImmutableRatesProvider; import com.opengamma.strata.pricer.sensitivity.RatesFiniteDifferenceSensitivityCalculator; import com.opengamma.strata.product.index.ResolvedIborFuture; /** * Test {@link HullWhiteIborFutureProductPricer}. */ @Test public class HullWhiteIborFutureProductPricerTest { private static final ReferenceData REF_DATA = ReferenceData.standard(); private static final LocalDate VALUATION = LocalDate.of(2011, 5, 12); private static final HullWhiteOneFactorPiecewiseConstantParametersProvider HW_PROVIDER = HullWhiteIborFutureDataSet.createHullWhiteProvider(VALUATION); private static final ImmutableRatesProvider RATE_PROVIDER = HullWhiteIborFutureDataSet.createRatesProvider(VALUATION); private static final ResolvedIborFuture FUTURE = HullWhiteIborFutureDataSet.IBOR_FUTURE.resolve(REF_DATA); private static final double TOL = 1.0e-13; private static final double TOL_FD = 1.0e-6; private static final HullWhiteIborFutureProductPricer PRICER = HullWhiteIborFutureProductPricer.DEFAULT; private static final DiscountingIborFutureProductPricer PRICER_DSC = DiscountingIborFutureProductPricer.DEFAULT; private static final RatesFiniteDifferenceSensitivityCalculator FD_CAL = new RatesFiniteDifferenceSensitivityCalculator(TOL_FD); public void test_price() { double computed = PRICER.price(FUTURE, RATE_PROVIDER, HW_PROVIDER); LocalDate start = FUTURE.getIborRate().getObservation().getEffectiveDate(); LocalDate end = FUTURE.getIborRate().getObservation().getMaturityDate(); double fixingYearFraction = FUTURE.getIborRate().getObservation().getYearFraction(); double convexity = HW_PROVIDER.futuresConvexityFactor(FUTURE.getLastTradeDate(), start, end); double forward = RATE_PROVIDER.iborIndexRates(EUR_EURIBOR_3M).rate(FUTURE.getIborRate().getObservation()); double expected = 1d - convexity * forward + (1d - convexity) / fixingYearFraction; assertEquals(computed, expected, TOL); } public void test_parRate() { double computed = PRICER.parRate(FUTURE, RATE_PROVIDER, HW_PROVIDER); double price = PRICER.price(FUTURE, RATE_PROVIDER, HW_PROVIDER); assertEquals(computed, 1d - price, TOL); } public void test_convexityAdjustment() { double computed = PRICER.convexityAdjustment(FUTURE, RATE_PROVIDER, HW_PROVIDER); double priceHw = PRICER.price(FUTURE, RATE_PROVIDER, HW_PROVIDER); double priceDsc = PRICER_DSC.price(FUTURE, RATE_PROVIDER); // no convexity adjustment assertEquals(priceDsc + computed, priceHw, TOL); } public void test_priceSensitivity() { PointSensitivities point = PRICER.priceSensitivityRates(FUTURE, RATE_PROVIDER, HW_PROVIDER); CurrencyParameterSensitivities computed = RATE_PROVIDER.parameterSensitivity(point); CurrencyParameterSensitivities expected = FD_CAL.sensitivity(RATE_PROVIDER, (p) -> CurrencyAmount.of(EUR, PRICER.price(FUTURE, (p), HW_PROVIDER))); assertTrue(computed.equalWithTolerance(expected, TOL_FD)); } public void test_priceSensitivityHullWhiteParameter() { DoubleArray computed = PRICER.priceSensitivityModelParamsHullWhite(FUTURE, RATE_PROVIDER, HW_PROVIDER); DoubleArray vols = HW_PROVIDER.getParameters().getVolatility(); int size = vols.size(); double[] expected = new double[size]; for (int i = 0; i < size; ++i) { double[] volsUp = vols.toArray(); double[] volsDw = vols.toArray(); volsUp[i] += TOL_FD; volsDw[i] -= TOL_FD; HullWhiteOneFactorPiecewiseConstantParameters paramsUp = HullWhiteOneFactorPiecewiseConstantParameters.of( HW_PROVIDER.getParameters().getMeanReversion(), DoubleArray.copyOf(volsUp), HW_PROVIDER.getParameters() .getVolatilityTime().subArray(1, size)); HullWhiteOneFactorPiecewiseConstantParameters paramsDw = HullWhiteOneFactorPiecewiseConstantParameters.of( HW_PROVIDER.getParameters().getMeanReversion(), DoubleArray.copyOf(volsDw), HW_PROVIDER.getParameters() .getVolatilityTime().subArray(1, size)); HullWhiteOneFactorPiecewiseConstantParametersProvider provUp = HullWhiteOneFactorPiecewiseConstantParametersProvider .of(paramsUp, HW_PROVIDER.getDayCount(), HW_PROVIDER.getValuationDateTime()); HullWhiteOneFactorPiecewiseConstantParametersProvider provDw = HullWhiteOneFactorPiecewiseConstantParametersProvider .of(paramsDw, HW_PROVIDER.getDayCount(), HW_PROVIDER.getValuationDateTime()); double priceUp = PRICER.price(FUTURE, RATE_PROVIDER, provUp); double priceDw = PRICER.price(FUTURE, RATE_PROVIDER, provDw); expected[i] = 0.5 * (priceUp - priceDw) / TOL_FD; } assertTrue(DoubleArrayMath.fuzzyEquals(computed.toArray(), expected, TOL_FD)); } //------------------------------------------------------------------------- public void regression_value() { double price = PRICER.price(FUTURE, RATE_PROVIDER, HW_PROVIDER); assertEquals(price, 0.9802338355115904, TOL); double parRate = PRICER.parRate(FUTURE, RATE_PROVIDER, HW_PROVIDER); assertEquals(parRate, 0.01976616448840962, TOL); double adjustment = PRICER.convexityAdjustment(FUTURE, RATE_PROVIDER, HW_PROVIDER); assertEquals(adjustment, -1.3766374738599652E-4, TOL); } public void regression_sensitivity() { PointSensitivities point = PRICER.priceSensitivityRates(FUTURE, RATE_PROVIDER, HW_PROVIDER); CurrencyParameterSensitivities computed = RATE_PROVIDER.parameterSensitivity(point); double[] expected = new double[] {0.0, 0.0, 0.9514709785770106, -1.9399920741192112, 0.0, 0.0, 0.0, 0.0 }; assertEquals(computed.size(), 1); assertTrue(DoubleArrayMath.fuzzyEquals(computed.getSensitivity(HullWhiteIborFutureDataSet.FWD3_NAME, EUR) .getSensitivity().toArray(), expected, TOL)); } }