/**
* 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 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.basics.currency.MultiCurrencyAmount;
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;
import com.opengamma.strata.product.index.ResolvedIborFutureTrade;
/**
* Test {@link HullWhiteIborFutureTradePricer}.
*/
@Test
public class HullWhiteIborFutureTradePricerTest {
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 ResolvedIborFutureTrade FUTURE_TRADE = HullWhiteIborFutureDataSet.IBOR_FUTURE_TRADE.resolve(REF_DATA);
private static final ResolvedIborFuture FUTURE = FUTURE_TRADE.getProduct();
private static final double LAST_PRICE = HullWhiteIborFutureDataSet.LAST_MARGIN_PRICE;
private static final double NOTIONAL = HullWhiteIborFutureDataSet.NOTIONAL;
private static final long QUANTITY = HullWhiteIborFutureDataSet.QUANTITY;
private static final double TOL = 1.0e-13;
private static final double TOL_FD = 1.0e-6;
private static final HullWhiteIborFutureTradePricer PRICER = HullWhiteIborFutureTradePricer.DEFAULT;
private static final HullWhiteIborFutureProductPricer PRICER_PRODUCT = HullWhiteIborFutureProductPricer.DEFAULT;
private static final RatesFiniteDifferenceSensitivityCalculator FD_CAL =
new RatesFiniteDifferenceSensitivityCalculator(TOL_FD);
public void test_price() {
double computed = PRICER.price(FUTURE_TRADE, RATE_PROVIDER, HW_PROVIDER);
double expected = PRICER_PRODUCT.price(FUTURE, RATE_PROVIDER, HW_PROVIDER);
assertEquals(computed, expected, TOL);
}
public void test_presentValue() {
CurrencyAmount computed = PRICER.presentValue(FUTURE_TRADE, RATE_PROVIDER, HW_PROVIDER, LAST_PRICE);
double price = PRICER_PRODUCT.price(FUTURE, RATE_PROVIDER, HW_PROVIDER);
double expected = (price - LAST_PRICE) * FUTURE.getAccrualFactor() * NOTIONAL * QUANTITY;
assertEquals(computed.getCurrency(), EUR);
assertEquals(computed.getAmount(), expected, TOL * NOTIONAL * QUANTITY);
}
public void test_parSpread() {
double computed = PRICER.parSpread(FUTURE_TRADE, RATE_PROVIDER, HW_PROVIDER, LAST_PRICE);
CurrencyAmount pv = PRICER.presentValue(FUTURE_TRADE, RATE_PROVIDER, HW_PROVIDER, LAST_PRICE + computed);
assertEquals(pv.getAmount(), 0d, TOL * NOTIONAL * QUANTITY);
}
public void test_presentValueSensitivity() {
PointSensitivities point = PRICER.presentValueSensitivityRates(FUTURE_TRADE, RATE_PROVIDER, HW_PROVIDER);
CurrencyParameterSensitivities computed = RATE_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities expected =
FD_CAL.sensitivity(RATE_PROVIDER, p -> PRICER.presentValue(FUTURE_TRADE, p, HW_PROVIDER, LAST_PRICE));
assertTrue(computed.equalWithTolerance(expected, NOTIONAL * QUANTITY * TOL_FD));
}
public void test_presentValueSensitivityHullWhiteParameter() {
DoubleArray computed = PRICER.presentValueSensitivityModelParamsHullWhite(FUTURE_TRADE, 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.presentValue(FUTURE_TRADE, RATE_PROVIDER, provUp, LAST_PRICE).getAmount();
double priceDw = PRICER.presentValue(FUTURE_TRADE, RATE_PROVIDER, provDw, LAST_PRICE).getAmount();
expected[i] = 0.5 * (priceUp - priceDw) / TOL_FD;
}
assertTrue(DoubleArrayMath.fuzzyEquals(computed.toArray(), expected, NOTIONAL * QUANTITY * TOL_FD));
}
public void test_parSpreadSensitivity() {
PointSensitivities point = PRICER.parSpreadSensitivityRates(FUTURE_TRADE, RATE_PROVIDER, HW_PROVIDER);
CurrencyParameterSensitivities computed = RATE_PROVIDER.parameterSensitivity(point);
CurrencyParameterSensitivities expected = FD_CAL.sensitivity(RATE_PROVIDER,
p -> CurrencyAmount.of(EUR, PRICER.parSpread(FUTURE_TRADE, p, HW_PROVIDER, LAST_PRICE)));
assertTrue(computed.equalWithTolerance(expected, NOTIONAL * QUANTITY * TOL_FD));
}
public void test_currencyExposure() {
PointSensitivities point = PRICER.presentValueSensitivityRates(FUTURE_TRADE, RATE_PROVIDER, HW_PROVIDER);
MultiCurrencyAmount expected = RATE_PROVIDER.currencyExposure(point)
.plus(PRICER.presentValue(FUTURE_TRADE, RATE_PROVIDER, HW_PROVIDER, LAST_PRICE));
MultiCurrencyAmount computed = PRICER.currencyExposure(FUTURE_TRADE, RATE_PROVIDER, HW_PROVIDER, LAST_PRICE);
assertEquals(computed.size(), 1);
assertEquals(computed.getAmount(EUR).getAmount(), expected.getAmount(EUR).getAmount(), NOTIONAL * QUANTITY * TOL);
}
//-------------------------------------------------------------------------
public void regression_pv() {
CurrencyAmount pv = PRICER.presentValue(FUTURE_TRADE, RATE_PROVIDER, HW_PROVIDER, LAST_PRICE);
assertEquals(pv.getAmount(), 23383.551159035414, NOTIONAL * QUANTITY * TOL);
}
public void regression_pvSensi() {
PointSensitivities point = PRICER.presentValueSensitivityRates(FUTURE_TRADE, RATE_PROVIDER, HW_PROVIDER);
CurrencyParameterSensitivities computed = RATE_PROVIDER.parameterSensitivity(point);
double[] expected = new double[] {0.0, 0.0, 9.514709785770103E7, -1.939992074119211E8, 0.0, 0.0, 0.0, 0.0 };
assertEquals(computed.size(), 1);
assertTrue(DoubleArrayMath.fuzzyEquals(computed.getSensitivity(HullWhiteIborFutureDataSet.FWD3_NAME, EUR)
.getSensitivity().toArray(), expected, NOTIONAL * QUANTITY * TOL));
}
}