/** * Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.pricer.fxopt; import static com.opengamma.strata.basics.currency.Currency.EUR; import static com.opengamma.strata.basics.currency.Currency.USD; import static com.opengamma.strata.product.common.LongShort.LONG; import static org.testng.Assert.assertEquals; import java.time.LocalDate; import java.time.ZoneId; import java.time.ZonedDateTime; import org.testng.annotations.Test; import com.opengamma.strata.basics.currency.CurrencyAmount; import com.opengamma.strata.basics.currency.MultiCurrencyAmount; import com.opengamma.strata.basics.currency.Payment; import com.opengamma.strata.market.sensitivity.PointSensitivities; import com.opengamma.strata.pricer.DiscountingPaymentPricer; import com.opengamma.strata.pricer.fx.RatesProviderFxDataSets; import com.opengamma.strata.pricer.rate.ImmutableRatesProvider; import com.opengamma.strata.product.TradeInfo; import com.opengamma.strata.product.fx.ResolvedFxSingle; import com.opengamma.strata.product.fxopt.ResolvedFxSingleBarrierOption; import com.opengamma.strata.product.fxopt.ResolvedFxSingleBarrierOptionTrade; import com.opengamma.strata.product.fxopt.ResolvedFxVanillaOption; import com.opengamma.strata.product.option.BarrierType; import com.opengamma.strata.product.option.KnockType; import com.opengamma.strata.product.option.SimpleConstantContinuousBarrier; /** * Test {@link BlackFxSingleBarrierOptionTradePricer}. */ @Test public class BlackFxSingleBarrierOptionTradePricerTest { private static final ZoneId ZONE = ZoneId.of("Z"); private static final LocalDate VAL_DATE = LocalDate.of(2011, 6, 13); private static final ZonedDateTime VAL_DATETIME = VAL_DATE.atStartOfDay(ZONE); private static final LocalDate PAY_DATE = LocalDate.of(2014, 9, 15); private static final LocalDate EXPIRY_DATE = LocalDate.of(2014, 9, 15); private static final ZonedDateTime EXPIRY_DATETIME = EXPIRY_DATE.atStartOfDay(ZONE); private static final BlackFxOptionSmileVolatilities VOLS = FxVolatilitySmileDataSet.createVolatilitySmileProvider5(VAL_DATETIME); private static final ImmutableRatesProvider RATES_PROVIDER = RatesProviderFxDataSets.createProviderEurUsdActActIsda(VAL_DATE); private static final double NOTIONAL = 100_000_000d; private static final double LEVEL_LOW = 1.35; private static final SimpleConstantContinuousBarrier BARRIER_DKI = SimpleConstantContinuousBarrier.of(BarrierType.DOWN, KnockType.KNOCK_IN, LEVEL_LOW); private static final double REBATE_AMOUNT = 50_000d; private static final CurrencyAmount REBATE = CurrencyAmount.of(USD, REBATE_AMOUNT); private static final double STRIKE_RATE = 1.45; private static final CurrencyAmount EUR_AMOUNT_REC = CurrencyAmount.of(EUR, NOTIONAL); private static final CurrencyAmount USD_AMOUNT_PAY = CurrencyAmount.of(USD, -NOTIONAL * STRIKE_RATE); private static final ResolvedFxSingle FX_PRODUCT = ResolvedFxSingle.of(EUR_AMOUNT_REC, USD_AMOUNT_PAY, PAY_DATE); private static final ResolvedFxVanillaOption CALL = ResolvedFxVanillaOption.builder() .longShort(LONG) .expiry(EXPIRY_DATETIME) .underlying(FX_PRODUCT) .build(); private static final ResolvedFxSingleBarrierOption OPTION_PRODUCT = ResolvedFxSingleBarrierOption.of(CALL, BARRIER_DKI, REBATE); private static final TradeInfo TRADE_INFO = TradeInfo.builder().tradeDate(VAL_DATE).build(); private static final LocalDate CASH_SETTLE_DATE = LocalDate.of(2011, 6, 16); private static final Payment PREMIUM = Payment.of(EUR, NOTIONAL * 0.027, CASH_SETTLE_DATE); private static final ResolvedFxSingleBarrierOptionTrade OPTION_TRADE = ResolvedFxSingleBarrierOptionTrade.builder() .premium(PREMIUM) .product(OPTION_PRODUCT) .info(TRADE_INFO) .build(); private static final BlackFxSingleBarrierOptionProductPricer PRICER_PRODUCT = BlackFxSingleBarrierOptionProductPricer.DEFAULT; private static final BlackFxSingleBarrierOptionTradePricer PRICER_TRADE = BlackFxSingleBarrierOptionTradePricer.DEFAULT; private static final DiscountingPaymentPricer PRICER_PAYMENT = DiscountingPaymentPricer.DEFAULT; private static final double TOL = 1.0e-13; public void test_presentValue() { MultiCurrencyAmount pvSensiTrade = PRICER_TRADE.presentValue(OPTION_TRADE, RATES_PROVIDER, VOLS); CurrencyAmount pvSensiProduct = PRICER_PRODUCT.presentValue(OPTION_PRODUCT, RATES_PROVIDER, VOLS); CurrencyAmount pvSensiPremium = PRICER_PAYMENT.presentValue(PREMIUM, RATES_PROVIDER); assertEquals(pvSensiTrade, MultiCurrencyAmount.of(pvSensiProduct, pvSensiPremium)); } public void test_presentValueSensitivity() { PointSensitivities pvSensiTrade = PRICER_TRADE.presentValueSensitivityRatesStickyStrike(OPTION_TRADE, RATES_PROVIDER, VOLS); PointSensitivities pvSensiProduct = PRICER_PRODUCT.presentValueSensitivityRatesStickyStrike(OPTION_PRODUCT, RATES_PROVIDER, VOLS).build(); PointSensitivities pvSensiPremium = PRICER_PAYMENT.presentValueSensitivity(PREMIUM, RATES_PROVIDER).build(); assertEquals(pvSensiTrade, pvSensiProduct.combinedWith(pvSensiPremium)); } public void test_presentValueSensitivityBlackVolatility() { PointSensitivities pvSensiTrade = PRICER_TRADE.presentValueSensitivityModelParamsVolatility(OPTION_TRADE, RATES_PROVIDER, VOLS); PointSensitivities pvSensiProduct = PRICER_PRODUCT.presentValueSensitivityModelParamsVolatility(OPTION_PRODUCT, RATES_PROVIDER, VOLS).build(); assertEquals(pvSensiTrade, pvSensiProduct); } public void test_currencyExposure() { MultiCurrencyAmount ceComputed = PRICER_TRADE.currencyExposure(OPTION_TRADE, RATES_PROVIDER, VOLS); MultiCurrencyAmount ceExpected = PRICER_PRODUCT.currencyExposure(OPTION_PRODUCT, RATES_PROVIDER, VOLS) .plus(PRICER_PAYMENT.presentValue(PREMIUM, RATES_PROVIDER)); assertEquals(ceComputed.size(), 2); assertEquals(ceComputed.getAmount(EUR).getAmount(), ceExpected.getAmount(EUR).getAmount(), TOL * NOTIONAL); assertEquals(ceComputed.getAmount(USD).getAmount(), ceExpected.getAmount(USD).getAmount(), TOL * NOTIONAL); } public void test_currentCash_zero() { assertEquals(PRICER_TRADE.currentCash(OPTION_TRADE, VAL_DATE), CurrencyAmount.zero(PREMIUM.getCurrency())); } public void test_currentCash_onSettle() { assertEquals(PRICER_TRADE.currentCash(OPTION_TRADE, CASH_SETTLE_DATE), PREMIUM.getValue()); } }