/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.pricer.bond; import static com.opengamma.strata.basics.currency.Currency.USD; import static com.opengamma.strata.pricer.CompoundedRateType.CONTINUOUS; import static com.opengamma.strata.pricer.CompoundedRateType.PERIODIC; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; 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.array.DoubleArray; import com.opengamma.strata.market.curve.CurveMetadata; import com.opengamma.strata.market.param.CurrencyParameterSensitivities; import com.opengamma.strata.market.sensitivity.PointSensitivities; import com.opengamma.strata.pricer.datasets.LegalEntityDiscountingProviderDataSets; import com.opengamma.strata.pricer.sensitivity.RatesFiniteDifferenceSensitivityCalculator; import com.opengamma.strata.product.bond.ResolvedBondFuture; import com.opengamma.strata.product.bond.ResolvedBondFutureTrade; /** * Test {@link DiscountingBondFutureTradePricer}. */ @Test public class DiscountingBondFutureTradetPricerTest { private static final ReferenceData REF_DATA = ReferenceData.standard(); // product and trade private static final ResolvedBondFuture FUTURE_PRODUCT = BondDataSets.FUTURE_PRODUCT_USD.resolve(REF_DATA); private static final ResolvedBondFutureTrade FUTURE_TRADE = BondDataSets.FUTURE_TRADE_USD.resolve(REF_DATA); private static final double SETTLE_PRICE = BondDataSets.SETTLE_PRICE_USD; private static final double NOTIONAL = BondDataSets.NOTIONAL_USD; private static final long QUANTITY = BondDataSets.QUANTITY_USD; // curves private static final LegalEntityDiscountingProvider PROVIDER = LegalEntityDiscountingProviderDataSets.ISSUER_REPO_ZERO; private static final CurveMetadata METADATA_ISSUER = LegalEntityDiscountingProviderDataSets.META_ZERO_ISSUER_USD; private static final CurveMetadata METADATA_REPO = LegalEntityDiscountingProviderDataSets.META_ZERO_REPO_USD; // parameters private static final double Z_SPREAD = 0.0075; private static final int PERIOD_PER_YEAR = 4; private static final double TOL = 1.0e-12; private static final double EPS = 1.0e-6; // pricers private static final DiscountingBondFutureTradePricer TRADE_PRICER = DiscountingBondFutureTradePricer.DEFAULT; private static final DiscountingBondFutureProductPricer PRODUCT_PRICER = DiscountingBondFutureProductPricer.DEFAULT; private static final RatesFiniteDifferenceSensitivityCalculator FD_CAL = new RatesFiniteDifferenceSensitivityCalculator(EPS); public void test_price() { double computed = TRADE_PRICER.price(FUTURE_TRADE, PROVIDER); double expected = PRODUCT_PRICER.price(FUTURE_PRODUCT, PROVIDER); assertEquals(computed, expected, TOL); } public void test_priceWithZSpread_continuous() { double computed = TRADE_PRICER.priceWithZSpread(FUTURE_TRADE, PROVIDER, Z_SPREAD, CONTINUOUS, 0); double expected = PRODUCT_PRICER.priceWithZSpread(FUTURE_PRODUCT, PROVIDER, Z_SPREAD, CONTINUOUS, 0); assertEquals(computed, expected, TOL); } public void test_priceWithZSpread_periodic() { double computed = TRADE_PRICER.priceWithZSpread(FUTURE_TRADE, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); double expected = PRODUCT_PRICER.priceWithZSpread(FUTURE_PRODUCT, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); assertEquals(computed, expected, TOL); } public void test_presentValue() { CurrencyAmount computed = TRADE_PRICER.presentValue(FUTURE_TRADE, PROVIDER, SETTLE_PRICE); double expected = (PRODUCT_PRICER.price(FUTURE_PRODUCT, PROVIDER) - SETTLE_PRICE) * NOTIONAL * QUANTITY; assertEquals(computed.getCurrency(), USD); assertEquals(computed.getAmount(), expected, TOL * NOTIONAL * QUANTITY); } public void test_presentValueWithZSpread_continuous() { CurrencyAmount computed = TRADE_PRICER.presentValueWithZSpread( FUTURE_TRADE, PROVIDER, SETTLE_PRICE, Z_SPREAD, CONTINUOUS, 0); double expected = (PRODUCT_PRICER.priceWithZSpread(FUTURE_PRODUCT, PROVIDER, Z_SPREAD, CONTINUOUS, 0) - SETTLE_PRICE) * NOTIONAL * QUANTITY; assertEquals(computed.getCurrency(), USD); assertEquals(computed.getAmount(), expected, TOL * NOTIONAL * QUANTITY); } public void test_presentValueWithZSpread_periodic() { CurrencyAmount computed = TRADE_PRICER.presentValueWithZSpread( FUTURE_TRADE, PROVIDER, SETTLE_PRICE, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); double expected = NOTIONAL * QUANTITY * (PRODUCT_PRICER.priceWithZSpread(FUTURE_PRODUCT, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR) - SETTLE_PRICE); assertEquals(computed.getCurrency(), USD); assertEquals(computed.getAmount(), expected, TOL * NOTIONAL * QUANTITY); } public void test_presentValueSensitivity() { PointSensitivities point = TRADE_PRICER.presentValueSensitivity(FUTURE_TRADE, PROVIDER); CurrencyParameterSensitivities computed = PROVIDER.parameterSensitivity(point); CurrencyParameterSensitivities expected = FD_CAL.sensitivity(PROVIDER, (p) -> TRADE_PRICER.presentValue(FUTURE_TRADE, (p), SETTLE_PRICE)); assertTrue(computed.equalWithTolerance(expected, 10.0 * EPS * NOTIONAL * QUANTITY)); } public void test_presentValueSensitivityWithZSpread_continuous() { PointSensitivities point = TRADE_PRICER.presentValueSensitivityWithZSpread( FUTURE_TRADE, PROVIDER, Z_SPREAD, CONTINUOUS, 0); CurrencyParameterSensitivities computed = PROVIDER.parameterSensitivity(point); CurrencyParameterSensitivities expected = FD_CAL.sensitivity(PROVIDER, (p) -> TRADE_PRICER.presentValueWithZSpread(FUTURE_TRADE, (p), SETTLE_PRICE, Z_SPREAD, CONTINUOUS, 0)); assertTrue(computed.equalWithTolerance(expected, 10.0 * EPS * NOTIONAL * QUANTITY)); } public void test_presentValueSensitivityWithZSpread_periodic() { PointSensitivities point = TRADE_PRICER.presentValueSensitivityWithZSpread( FUTURE_TRADE, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); CurrencyParameterSensitivities computed = PROVIDER.parameterSensitivity(point); CurrencyParameterSensitivities expected = FD_CAL.sensitivity(PROVIDER, (p) -> TRADE_PRICER.presentValueWithZSpread(FUTURE_TRADE, (p), SETTLE_PRICE, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR)); assertTrue(computed.equalWithTolerance(expected, 10.0 * EPS * NOTIONAL * QUANTITY)); } //------------------------------------------------------------------------- public void test_parSpread() { double computed = TRADE_PRICER.parSpread(FUTURE_TRADE, PROVIDER, SETTLE_PRICE); double expected = PRODUCT_PRICER.price(FUTURE_PRODUCT, PROVIDER) - SETTLE_PRICE; assertEquals(computed, expected, TOL); } public void test_parSpreadWithZSpread_continuous() { double computed = TRADE_PRICER.parSpreadWithZSpread(FUTURE_TRADE, PROVIDER, SETTLE_PRICE, Z_SPREAD, CONTINUOUS, 0); double expected = PRODUCT_PRICER.priceWithZSpread(FUTURE_PRODUCT, PROVIDER, Z_SPREAD, CONTINUOUS, 0) - SETTLE_PRICE; assertEquals(computed, expected, TOL); } public void test_parSpreadWithZSpread_periodic() { double computed = TRADE_PRICER.parSpreadWithZSpread( FUTURE_TRADE, PROVIDER, SETTLE_PRICE, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); double expected = PRODUCT_PRICER.priceWithZSpread(FUTURE_PRODUCT, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR) - SETTLE_PRICE; assertEquals(computed, expected, TOL); } public void test_parSpreadSensitivity() { PointSensitivities point = TRADE_PRICER.parSpreadSensitivity(FUTURE_TRADE, PROVIDER); CurrencyParameterSensitivities computed = PROVIDER.parameterSensitivity(point); CurrencyParameterSensitivities expected = FD_CAL.sensitivity( PROVIDER, (p) -> CurrencyAmount.of(USD, TRADE_PRICER.parSpread(FUTURE_TRADE, (p), SETTLE_PRICE))); assertTrue(computed.equalWithTolerance(expected, 10.0 * EPS * NOTIONAL * QUANTITY)); } public void test_parSpreadSensitivityWithZSpread_continuous() { PointSensitivities point = TRADE_PRICER.parSpreadSensitivityWithZSpread( FUTURE_TRADE, PROVIDER, Z_SPREAD, CONTINUOUS, 0); CurrencyParameterSensitivities computed = PROVIDER.parameterSensitivity(point); CurrencyParameterSensitivities expected = FD_CAL.sensitivity(PROVIDER, (p) -> CurrencyAmount.of( USD, TRADE_PRICER.parSpreadWithZSpread(FUTURE_TRADE, (p), SETTLE_PRICE, Z_SPREAD, CONTINUOUS, 0))); assertTrue(computed.equalWithTolerance(expected, 10.0 * EPS * NOTIONAL * QUANTITY)); } public void test_parSpreadSensitivityWithZSpread_periodic() { PointSensitivities point = TRADE_PRICER.parSpreadSensitivityWithZSpread( FUTURE_TRADE, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); CurrencyParameterSensitivities computed = PROVIDER.parameterSensitivity(point); CurrencyParameterSensitivities expected = FD_CAL.sensitivity(PROVIDER, (p) -> CurrencyAmount.of(USD, TRADE_PRICER.parSpreadWithZSpread(FUTURE_TRADE, (p), SETTLE_PRICE, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR))); assertTrue(computed.equalWithTolerance(expected, 10.0 * EPS * NOTIONAL * QUANTITY)); } //------------------------------------------------------------------------- public void test_currencyExposure() { MultiCurrencyAmount ceComputed = TRADE_PRICER.currencyExposure(FUTURE_TRADE, PROVIDER, SETTLE_PRICE); CurrencyAmount pv = TRADE_PRICER.presentValue(FUTURE_TRADE, PROVIDER, SETTLE_PRICE); assertEquals(ceComputed, MultiCurrencyAmount.of(pv)); } public void test_currencyExposureWithZSpread() { MultiCurrencyAmount ceComputed = TRADE_PRICER.currencyExposureWithZSpread( FUTURE_TRADE, PROVIDER, SETTLE_PRICE, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); CurrencyAmount pv = TRADE_PRICER.presentValueWithZSpread( FUTURE_TRADE, PROVIDER, SETTLE_PRICE, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); assertEquals(ceComputed, MultiCurrencyAmount.of(pv)); } //------------------------------------------------------------------------- // regression to 2.x public void regression() { CurrencyAmount pv = TRADE_PRICER.presentValue(FUTURE_TRADE, PROVIDER, SETTLE_PRICE); assertEquals(pv.getAmount(), -2937800.66334416, EPS * NOTIONAL * QUANTITY); PointSensitivities pvPoint = TRADE_PRICER.presentValueSensitivity(FUTURE_TRADE, PROVIDER); CurrencyParameterSensitivities test = PROVIDER.parameterSensitivity(pvPoint); DoubleArray expectedIssuer = DoubleArray.of( -48626.82968419264, -513532.4556150143, -1768520.182827613, -1.262340715772077E8, -5.208162480624767E8, 0); DoubleArray actualIssuer = test.getSensitivity(METADATA_ISSUER.getCurveName(), USD).getSensitivity(); assertTrue(actualIssuer.equalWithTolerance(expectedIssuer, TOL * NOTIONAL * QUANTITY)); DoubleArray expectedRepo = DoubleArray.of(1.8204636592806276E7, 2.5799948548745323E7, 0.0, 0.0, 0.0, 0.0); DoubleArray actualRepo = test.getSensitivity(METADATA_REPO.getCurveName(), USD).getSensitivity(); assertTrue(actualRepo.equalWithTolerance(expectedRepo, TOL * NOTIONAL * QUANTITY)); } public void regression_withZSpread_continuous() { CurrencyAmount pv = TRADE_PRICER.presentValueWithZSpread( FUTURE_TRADE, PROVIDER, SETTLE_PRICE, Z_SPREAD, CONTINUOUS, 0); assertEquals(pv.getAmount(), -7728642.649169521, EPS * NOTIONAL * QUANTITY); } public void regression_withZSpread_periodic() { CurrencyAmount pv = TRADE_PRICER.presentValueWithZSpread( FUTURE_TRADE, PROVIDER, SETTLE_PRICE, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); assertEquals(pv.getAmount(), -7710148.864076961, EPS * NOTIONAL * QUANTITY); PointSensitivities pvPoint = TRADE_PRICER.presentValueSensitivityWithZSpread( FUTURE_TRADE, PROVIDER, Z_SPREAD, PERIODIC, PERIOD_PER_YEAR); CurrencyParameterSensitivities test = PROVIDER.parameterSensitivity(pvPoint); DoubleArray expectedIssuer = DoubleArray.of( -48374.31671055041, -510470.43789512076, -1748988.1122760356, -1.2199872917663E8, -5.0289585725762194E8, 0); DoubleArray actualIssuer = test.getSensitivity(METADATA_ISSUER.getCurveName(), USD).getSensitivity(); assertTrue(actualIssuer.equalWithTolerance(expectedIssuer, TOL * NOTIONAL * QUANTITY)); DoubleArray expectedRepo = DoubleArray.of(1.7625865116887797E7, 2.497970288088735E7, 0.0, 0.0, 0.0, 0.0); DoubleArray actualRepo = test.getSensitivity(METADATA_REPO.getCurveName(), USD).getSensitivity(); assertTrue(actualRepo.equalWithTolerance(expectedRepo, TOL * NOTIONAL * QUANTITY)); } }