/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.forex.provider; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; import org.testng.annotations.Test; import org.threeten.bp.ZonedDateTime; import com.opengamma.analytics.financial.forex.definition.ForexSwapDefinition; import com.opengamma.analytics.financial.forex.derivative.ForexSwap; import com.opengamma.analytics.financial.interestrate.InstrumentDerivative; import com.opengamma.analytics.financial.provider.calculator.discounting.CurrencyExposureDiscountingCalculator; import com.opengamma.analytics.financial.provider.calculator.discounting.ParSpreadMarketQuoteCurveSensitivityDiscountingCalculator; import com.opengamma.analytics.financial.provider.calculator.discounting.ParSpreadMarketQuoteDiscountingCalculator; import com.opengamma.analytics.financial.provider.calculator.discounting.PresentValueCurveSensitivityDiscountingCalculator; import com.opengamma.analytics.financial.provider.calculator.discounting.PresentValueDiscountingCalculator; import com.opengamma.analytics.financial.provider.calculator.generic.TodayPaymentCalculator; import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderDiscount; import com.opengamma.analytics.financial.provider.description.interestrate.ParameterProviderInterface; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MulticurveSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyMulticurveSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.SimpleParameterSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.SimpleParameterSensitivityMulticurveDiscountInterpolatedFDCalculator; import com.opengamma.analytics.financial.provider.sensitivity.parameter.SimpleParameterSensitivityParameterCalculator; import com.opengamma.analytics.financial.util.AssertSensitivityObjects; import com.opengamma.util.money.Currency; import com.opengamma.util.money.MultipleCurrencyAmount; import com.opengamma.util.test.TestGroup; import com.opengamma.util.time.DateUtils; /** * Test related to the method for Forex Swap transaction by discounting on each payment. */ @Test(groups = TestGroup.UNIT) public class ForexSwapDiscountingMethodTest { private static final MulticurveProviderDiscount MULTICURVES = MulticurveProviderDiscountForexDataSets.createMulticurvesForex(); private static final Currency CUR_1 = Currency.EUR; private static final Currency CUR_2 = Currency.USD; private static final ZonedDateTime NEAR_DATE = DateUtils.getUTCDate(2011, 5, 26); private static final ZonedDateTime FAR_DATE = DateUtils.getUTCDate(2011, 6, 27); // 1m private static final double NOMINAL_1 = 100000000; private static final double FORWARD_POINTS = -0.0007; private static final ForexSwapDefinition FX_SWAP_DEFINITION = new ForexSwapDefinition(CUR_1, CUR_2, NEAR_DATE, FAR_DATE, NOMINAL_1, MULTICURVES.getFxRate(CUR_1, CUR_2), FORWARD_POINTS); private static final ZonedDateTime REFERENCE_DATE = DateUtils.getUTCDate(2011, 5, 20); private static final ForexSwap FX_SWAP = (ForexSwap) FX_SWAP_DEFINITION.toDerivative(REFERENCE_DATE); private static final ForexSwapDiscountingMethod METHOD_FX_SWAP = ForexSwapDiscountingMethod.getInstance(); private static final ForexDiscountingMethod METHOD_FX = ForexDiscountingMethod.getInstance(); private static final PresentValueDiscountingCalculator PVDC = PresentValueDiscountingCalculator.getInstance(); private static final PresentValueCurveSensitivityDiscountingCalculator PVCSDC = PresentValueCurveSensitivityDiscountingCalculator.getInstance(); private static final CurrencyExposureDiscountingCalculator CEDC = CurrencyExposureDiscountingCalculator.getInstance(); private static final ParSpreadMarketQuoteDiscountingCalculator PSMQDC = ParSpreadMarketQuoteDiscountingCalculator.getInstance(); private static final ParSpreadMarketQuoteCurveSensitivityDiscountingCalculator PSMQCSDC = ParSpreadMarketQuoteCurveSensitivityDiscountingCalculator.getInstance(); private static final SimpleParameterSensitivityParameterCalculator<ParameterProviderInterface> PSPSC = new SimpleParameterSensitivityParameterCalculator<>( PSMQCSDC); private static final double SHIFT = 1.0E-7; private static final SimpleParameterSensitivityMulticurveDiscountInterpolatedFDCalculator PSMQCS_FDC = new SimpleParameterSensitivityMulticurveDiscountInterpolatedFDCalculator( PSMQDC, SHIFT); private static final TodayPaymentCalculator TPC = TodayPaymentCalculator.getInstance(); private static final double TOLERANCE_PV = 1.0E-2; // one cent out of 100m private static final double TOLERANCE_RATE = 1.0E-10; private static final double TOLERANCE_RATE_DELTA = 1.0E-8; @Test /** * Tests the present value computation. */ public void presentValue() { final MultipleCurrencyAmount pv = METHOD_FX_SWAP.presentValue(FX_SWAP, MULTICURVES); final MultipleCurrencyAmount pvNear = METHOD_FX.presentValue((FX_SWAP).getNearLeg(), MULTICURVES); final MultipleCurrencyAmount pvFar = METHOD_FX.presentValue((FX_SWAP).getFarLeg(), MULTICURVES); assertEquals(pvNear.getAmount(CUR_1) + pvFar.getAmount(CUR_1), pv.getAmount(CUR_1)); assertEquals(pvNear.getAmount(CUR_2) + pvFar.getAmount(CUR_2), pv.getAmount(CUR_2)); } @Test /** * Test the present value through the method and through the calculator. */ public void presentValueMethodVsCalculator() { final MultipleCurrencyAmount pvMethod = METHOD_FX_SWAP.presentValue(FX_SWAP, MULTICURVES); final MultipleCurrencyAmount pvCalculator = FX_SWAP.accept(PVDC, MULTICURVES); assertEquals("Forex present value: Method vs Calculator", pvMethod, pvCalculator); } @Test /** * Tests the currency exposure computation. */ public void currencyExposure() { final MultipleCurrencyAmount exposureMethod = METHOD_FX_SWAP.currencyExposure(FX_SWAP, MULTICURVES); final MultipleCurrencyAmount pv = METHOD_FX_SWAP.presentValue(FX_SWAP, MULTICURVES); assertEquals("Currency exposure", pv, exposureMethod); final MultipleCurrencyAmount exposureCalculator = FX_SWAP.accept(CEDC, MULTICURVES); assertEquals("Currency exposure: Method vs Calculator", exposureMethod, exposureCalculator); } @Test /** * Test the present value sensitivity to interest rate. */ public void presentValueCurveSensitivity() { MultipleCurrencyMulticurveSensitivity pvs = METHOD_FX_SWAP.presentValueCurveSensitivity(FX_SWAP, MULTICURVES); pvs = pvs.cleaned(); MultipleCurrencyMulticurveSensitivity pvsNear = METHOD_FX.presentValueCurveSensitivity((FX_SWAP).getNearLeg(), MULTICURVES); final MultipleCurrencyMulticurveSensitivity pvsFar = METHOD_FX.presentValueCurveSensitivity((FX_SWAP).getFarLeg(), MULTICURVES); pvsNear = pvsNear.plus(pvsFar); pvsNear = pvsNear.cleaned(); assertTrue("Forex swap present value curve sensitivity", pvs.equals(pvsNear)); } @Test /** * Test the present value curve sensitivity through the method and through the calculator. */ public void presentValueCurveSensitivityMethodVsCalculator() { final MultipleCurrencyMulticurveSensitivity pvcsMethod = METHOD_FX_SWAP.presentValueCurveSensitivity(FX_SWAP, MULTICURVES); final MultipleCurrencyMulticurveSensitivity pvcsCalculator = FX_SWAP.accept(PVCSDC, MULTICURVES); assertEquals("Forex swap present value curve sensitivity: Method vs Calculator", pvcsMethod, pvcsCalculator); } @Test /** * Tests the TodayPaymentCalculator for forex transactions. */ public void forexTodayPaymentBeforeNearDate() { final InstrumentDerivative fx = FX_SWAP_DEFINITION.toDerivative(NEAR_DATE.minusDays(1)); final MultipleCurrencyAmount cash = fx.accept(TPC); assertEquals("TodayPaymentCalculator: forex", 0.0, cash.getAmount(FX_SWAP_DEFINITION.getNearLeg().getCurrency1()), TOLERANCE_PV); assertEquals("TodayPaymentCalculator: forex", 0.0, cash.getAmount(FX_SWAP_DEFINITION.getNearLeg().getCurrency2()), TOLERANCE_PV); assertEquals("TodayPaymentCalculator: forex", 2, cash.getCurrencyAmounts().length); } @Test /** * Tests the TodayPaymentCalculator for forex transactions. */ public void forexTodayPaymentOnNearDate() { final InstrumentDerivative fx = FX_SWAP_DEFINITION.toDerivative(NEAR_DATE); final MultipleCurrencyAmount cash = fx.accept(TPC); assertEquals("TodayPaymentCalculator: forex", FX_SWAP_DEFINITION.getNearLeg().getPaymentCurrency1().getReferenceAmount(), cash.getAmount(FX_SWAP_DEFINITION.getNearLeg().getCurrency1()), TOLERANCE_PV); assertEquals("TodayPaymentCalculator: forex", FX_SWAP_DEFINITION.getNearLeg().getPaymentCurrency2().getReferenceAmount(), cash.getAmount(FX_SWAP_DEFINITION.getNearLeg().getCurrency2()), TOLERANCE_PV); assertEquals("TodayPaymentCalculator: forex", 2, cash.getCurrencyAmounts().length); } @Test /** * Tests the TodayPaymentCalculator for forex transactions. */ public void forexTodayPaymentBeforeFarDate() { final InstrumentDerivative fx = FX_SWAP_DEFINITION.toDerivative(FAR_DATE.minusDays(1)); final MultipleCurrencyAmount cash = fx.accept(TPC); assertEquals("TodayPaymentCalculator: forex", 0.0, cash.getAmount(FX_SWAP_DEFINITION.getFarLeg().getCurrency1()), TOLERANCE_PV); assertEquals("TodayPaymentCalculator: forex", 0.0, cash.getAmount(FX_SWAP_DEFINITION.getFarLeg().getCurrency2()), TOLERANCE_PV); assertEquals("TodayPaymentCalculator: forex", 2, cash.getCurrencyAmounts().length); } @Test /** * Tests the TodayPaymentCalculator for forex transactions. */ public void forexTodayPaymentOnFarDate() { final InstrumentDerivative fx = FX_SWAP_DEFINITION.toDerivative(FAR_DATE); final MultipleCurrencyAmount cash = fx.accept(TPC); assertEquals("TodayPaymentCalculator: forex", FX_SWAP_DEFINITION.getFarLeg().getPaymentCurrency1().getReferenceAmount(), cash.getAmount(FX_SWAP_DEFINITION.getFarLeg().getCurrency1()), TOLERANCE_PV); assertEquals("TodayPaymentCalculator: forex", FX_SWAP_DEFINITION.getFarLeg().getPaymentCurrency2().getReferenceAmount(), cash.getAmount(FX_SWAP_DEFINITION.getFarLeg().getCurrency2()), TOLERANCE_PV); assertEquals("TodayPaymentCalculator: forex", 2, cash.getCurrencyAmounts().length); } @Test /** * Tests the parSpread method. */ public void parSpread() { final double parSpread = METHOD_FX_SWAP.parSpread(FX_SWAP, MULTICURVES); final ForexSwapDefinition fxSwap0Definition = new ForexSwapDefinition(CUR_1, CUR_2, NEAR_DATE, FAR_DATE, NOMINAL_1, MULTICURVES.getFxRate(CUR_1, CUR_2), FORWARD_POINTS + parSpread); final ForexSwap fxSwap0 = (ForexSwap) fxSwap0Definition.toDerivative(REFERENCE_DATE); final MultipleCurrencyAmount pv0 = METHOD_FX_SWAP.presentValue(fxSwap0, MULTICURVES); assertEquals("Forex swap: par spread", 0, MULTICURVES.getFxRates().convert(pv0, CUR_1).getAmount(), TOLERANCE_PV); } @Test /** * Tests the par spread method vs calculator */ public void parSpreadMethodVsCalculator() { final double parSpreadMethod = METHOD_FX_SWAP.parSpread(FX_SWAP, MULTICURVES); final double parSpreadCalculator = FX_SWAP.accept(PSMQDC, MULTICURVES); assertEquals("Forex swap: par spread", parSpreadMethod, parSpreadCalculator, TOLERANCE_RATE); } @Test /** * Tests the par spread curve sensitivity versus a finite difference computation. */ public void parSpreadCurveSensitivity() { final SimpleParameterSensitivity psComputed = PSPSC.calculateSensitivity(FX_SWAP, MULTICURVES, MULTICURVES.getAllNames()); final SimpleParameterSensitivity psFD = PSMQCS_FDC.calculateSensitivity(FX_SWAP, MULTICURVES); AssertSensitivityObjects.assertEquals("CashDiscountingProviderMethod: presentValueCurveSensitivity ", psFD, psComputed, TOLERANCE_RATE_DELTA); } @Test /** * Tests the par spread curve sensitivity through the method and through the calculator. */ public void parSpreadCurveSensitivityMethodVsCalculator() { final MulticurveSensitivity pvcsMethod = METHOD_FX_SWAP.parSpreadCurveSensitivity(FX_SWAP, MULTICURVES); final MulticurveSensitivity pvcsCalculator = FX_SWAP.accept(PSMQCSDC, MULTICURVES); assertEquals("Forex swap present value curve sensitivity: Method vs Calculator", pvcsMethod, pvcsCalculator); } }