/**
* 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 org.testng.annotations.Test;
import org.threeten.bp.ZonedDateTime;
import com.opengamma.analytics.financial.forex.definition.ForexDefinition;
import com.opengamma.analytics.financial.forex.definition.ForexNonDeliverableForwardDefinition;
import com.opengamma.analytics.financial.forex.derivative.Forex;
import com.opengamma.analytics.financial.forex.derivative.ForexNonDeliverableForward;
import com.opengamma.analytics.financial.forex.method.FXMatrix;
import com.opengamma.analytics.financial.provider.calculator.discounting.CurrencyExposureDiscountingCalculator;
import com.opengamma.analytics.financial.provider.calculator.discounting.PresentValueDiscountingCalculator;
import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderInterface;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyMulticurveSensitivity;
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;
/**
* Tests related to the valuation of non-deliverable forward by discounting.
*/
@Test(groups = TestGroup.UNIT)
public class ForexNonDeliverableForwardDiscountingMethodTest {
private static final MulticurveProviderInterface MULTICURVES = MulticurveProviderDiscountForexDataSets.createMulticurvesForex();
private static final Currency KRW = Currency.of("KRW");
private static final Currency USD = Currency.USD;
private static final ZonedDateTime FIXING_DATE = DateUtils.getUTCDate(2012, 5, 2);
private static final ZonedDateTime PAYMENT_DATE = DateUtils.getUTCDate(2012, 5, 4);
private static final double NOMINAL_USD = 100000000; // 1m
private static final double FX_RATE = 1123.45;
private static final ForexNonDeliverableForwardDefinition NDF_DEFINITION = new ForexNonDeliverableForwardDefinition(KRW, USD, NOMINAL_USD, FX_RATE, FIXING_DATE,
PAYMENT_DATE);
private static final ForexDefinition FOREX_DEFINITION = new ForexDefinition(USD, KRW, PAYMENT_DATE, NOMINAL_USD, FX_RATE);
private static final ZonedDateTime REFERENCE_DATE = DateUtils.getUTCDate(2011, 11, 10);
// private static final double USD_KRW = 1111.11;
private static final FXMatrix FX_MATRIX = MulticurveProviderDiscountForexDataSets.fxMatrix();
private static final ForexNonDeliverableForward NDF = NDF_DEFINITION.toDerivative(REFERENCE_DATE);
private static final Forex FOREX = FOREX_DEFINITION.toDerivative(REFERENCE_DATE);
private static final ForexNonDeliverableForwardDiscountingMethod METHOD_NDF = ForexNonDeliverableForwardDiscountingMethod.getInstance();
private static final ForexDiscountingMethod METHOD_FX = ForexDiscountingMethod.getInstance();
private static final PresentValueDiscountingCalculator PVDC = PresentValueDiscountingCalculator.getInstance();
private static final CurrencyExposureDiscountingCalculator CEC = CurrencyExposureDiscountingCalculator.getInstance();
private static final double TOLERANCE_PV = 1.0E-2;
@Test
/**
* Tests the currency exposure.
*/
public void currencyExposure() {
final MultipleCurrencyAmount ce = METHOD_NDF.currencyExposure(NDF, MULTICURVES);
final double df1 = MULTICURVES.getDiscountFactor(KRW, NDF.getPaymentTime());
final double df2 = MULTICURVES.getDiscountFactor(USD, NDF.getPaymentTime());
final double ce1 = -NOMINAL_USD * df1 * FX_RATE;
final double ce2 = NOMINAL_USD * df2;
assertEquals("Currency exposure - non-deliverable forward", ce1, ce.getAmount(KRW), TOLERANCE_PV);
assertEquals("Currency exposure - non-deliverable forward", ce2, ce.getAmount(USD), TOLERANCE_PV);
}
@Test
/**
* Checks that the NDF currency exposure is the same as the standard FX forward currency exposure.
*/
public void currencyExposureVsForex() {
final MultipleCurrencyAmount ceNDF = METHOD_NDF.currencyExposure(NDF, MULTICURVES);
final MultipleCurrencyAmount ceFX = METHOD_FX.currencyExposure(FOREX, MULTICURVES);
assertEquals("Currency exposure - non-deliverable forward", ceFX, ceNDF);
}
@Test
/**
* Checks that the NDF present value calculator is coherent with present value method.
*/
public void currencyExposureMethodVsCalculator() {
final MultipleCurrencyAmount ceMethod = METHOD_NDF.currencyExposure(NDF, MULTICURVES);
final MultipleCurrencyAmount ceCalculator = NDF.accept(CEC, MULTICURVES);
assertEquals("Currency exposure - non-deliverable forward", ceMethod, ceCalculator);
}
@Test
/**
* Tests the present value.
*/
public void presentValue() {
final MultipleCurrencyAmount ce = METHOD_NDF.currencyExposure(NDF, MULTICURVES);
final MultipleCurrencyAmount pv = METHOD_NDF.presentValue(NDF, MULTICURVES);
final double pvExpected = ce.getAmount(KRW) * FX_MATRIX.getFxRate(KRW, USD) + ce.getAmount(USD);
assertEquals("Present value - non-deliverable forward", pvExpected, pv.getAmount(USD), TOLERANCE_PV);
}
@Test
/**
* Checks that the NDF present value is coherent with the standard FX forward present value.
*/
public void presentValueVsForex() {
final MultipleCurrencyAmount pvNDF = METHOD_NDF.presentValue(NDF, MULTICURVES);
final MultipleCurrencyAmount pvFX = METHOD_FX.presentValue(FOREX, MULTICURVES);
assertEquals("Present value - non-deliverable forward", pvFX.getAmount(USD) + pvFX.getAmount(KRW) * FX_MATRIX.getFxRate(KRW, USD), pvNDF.getAmount(USD), TOLERANCE_PV);
}
@Test
/**
* Checks that the NDF present value calculator is coherent with present value method.
*/
public void presentValueMethodVsCalculator() {
final MultipleCurrencyAmount pvMethod = METHOD_NDF.presentValue(NDF, MULTICURVES);
final MultipleCurrencyAmount pvCalculator = NDF.accept(PVDC, MULTICURVES);
assertEquals("Present value - non-deliverable forward", pvMethod, pvCalculator);
}
@Test
/**
* Checks that the NDF forward rate is coherent with the standard FX forward present value.
*/
public void forwardRateVsForex() {
final double fwdNDF = METHOD_NDF.forwardForexRate(NDF, MULTICURVES);
final double fwdFX = METHOD_FX.forwardForexRate(FOREX, MULTICURVES);
assertEquals("Forward rate - non-deliverable forward", fwdNDF, fwdFX, TOLERANCE_PV);
}
// @Test
// /**
// * Tests the forward Forex rate through the method and through the calculator.
// */
// public void forwardRateMethodVsCalculator() {
// final double fwdMethod = METHOD_NDF.forwardForexRate(NDF, MULTICURVES);
// final ForwardRateForexCalculator FWDC = ForwardRateForexCalculator.getInstance();
// final double fwdCalculator = NDF.accept(FWDC, MULTICURVES);
// assertEquals("Forex: forward rate", fwdMethod, fwdCalculator, 1.0E-10);
// }
@Test
/**
* Tests the present value curve sensitivity using the Forex instrument curve sensitivity as reference.
*/
public void presentValueCurveSensitivity() {
final MultipleCurrencyMulticurveSensitivity pvcsNDF = METHOD_NDF.presentValueCurveSensitivity(NDF, MULTICURVES).cleaned();
final MultipleCurrencyMulticurveSensitivity pvcsFX = METHOD_FX.presentValueCurveSensitivity(FOREX, MULTICURVES).cleaned();
final MultipleCurrencyMulticurveSensitivity pvcsFXConverted = pvcsFX.converted(USD, FX_MATRIX).cleaned();
AssertSensitivityObjects.assertEquals("ForexNonDeliverableForwardDiscountingMethod: presentValueCurveSensitivity", pvcsFXConverted, pvcsNDF, TOLERANCE_PV);
}
}