/**
* Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.measure.cms;
import static com.opengamma.strata.basics.date.HolidayCalendarIds.EUTA;
import static com.opengamma.strata.collect.TestHelper.date;
import static com.opengamma.strata.product.common.PayReceive.PAY;
import static org.assertj.core.api.Assertions.assertThat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.opengamma.strata.basics.ReferenceData;
import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.basics.currency.MultiCurrencyAmount;
import com.opengamma.strata.basics.date.BusinessDayAdjustment;
import com.opengamma.strata.basics.date.BusinessDayConventions;
import com.opengamma.strata.basics.index.IborIndex;
import com.opengamma.strata.basics.schedule.Frequency;
import com.opengamma.strata.basics.schedule.PeriodicSchedule;
import com.opengamma.strata.basics.schedule.RollConventions;
import com.opengamma.strata.basics.schedule.StubConvention;
import com.opengamma.strata.basics.value.ValueAdjustment;
import com.opengamma.strata.basics.value.ValueSchedule;
import com.opengamma.strata.basics.value.ValueStep;
import com.opengamma.strata.calc.Measure;
import com.opengamma.strata.calc.runner.CalculationParameters;
import com.opengamma.strata.calc.runner.FunctionRequirements;
import com.opengamma.strata.collect.result.Result;
import com.opengamma.strata.collect.timeseries.LocalDateDoubleTimeSeries;
import com.opengamma.strata.data.scenario.MultiCurrencyScenarioArray;
import com.opengamma.strata.data.scenario.ScenarioMarketData;
import com.opengamma.strata.market.curve.CurveId;
import com.opengamma.strata.market.observable.IndexQuoteId;
import com.opengamma.strata.measure.Measures;
import com.opengamma.strata.measure.curve.TestMarketDataMap;
import com.opengamma.strata.measure.rate.RatesMarketDataLookup;
import com.opengamma.strata.measure.swaption.SwaptionMarketDataLookup;
import com.opengamma.strata.pricer.cms.SabrExtrapolationReplicationCmsLegPricer;
import com.opengamma.strata.pricer.cms.SabrExtrapolationReplicationCmsPeriodPricer;
import com.opengamma.strata.pricer.cms.SabrExtrapolationReplicationCmsProductPricer;
import com.opengamma.strata.pricer.cms.SabrExtrapolationReplicationCmsTradePricer;
import com.opengamma.strata.pricer.rate.RatesProvider;
import com.opengamma.strata.pricer.swaption.SabrSwaptionVolatilities;
import com.opengamma.strata.pricer.swaption.SwaptionSabrRateVolatilityDataSet;
import com.opengamma.strata.pricer.swaption.SwaptionVolatilitiesId;
import com.opengamma.strata.product.cms.Cms;
import com.opengamma.strata.product.cms.CmsLeg;
import com.opengamma.strata.product.cms.CmsTrade;
import com.opengamma.strata.product.cms.ResolvedCmsTrade;
import com.opengamma.strata.product.swap.SwapIndex;
import com.opengamma.strata.product.swap.SwapIndices;
/**
* Test {@link CmsTradeCalculationFunction}.
*/
@Test
public class CmsTradeCalculationFunctionTest {
private static final ReferenceData REF_DATA = ReferenceData.standard();
private static final SwapIndex SWAP_INDEX = SwapIndices.EUR_EURIBOR_1100_5Y;
private static final LocalDate START = LocalDate.of(2015, 10, 21);
private static final LocalDate END = LocalDate.of(2020, 10, 21);
private static final Frequency FREQUENCY = Frequency.P12M;
private static final BusinessDayAdjustment BUSS_ADJ_EUR =
BusinessDayAdjustment.of(BusinessDayConventions.FOLLOWING, EUTA);
private static final PeriodicSchedule SCHEDULE_EUR =
PeriodicSchedule.of(START, END, FREQUENCY, BUSS_ADJ_EUR, StubConvention.NONE, RollConventions.NONE);
private static final List<ValueStep> NOTIONAL_STEPS = new ArrayList<ValueStep>();
private static final double NOTIONAL_VALUE_0 = 100_000_000;
private static final double NOTIONAL_VALUE_1 = 1.1e6;
private static final double NOTIONAL_VALUE_2 = 0.9e6;
private static final double NOTIONAL_VALUE_3 = 1.2e6;
static {
NOTIONAL_STEPS.add(ValueStep.of(1, ValueAdjustment.ofReplace(NOTIONAL_VALUE_1)));
NOTIONAL_STEPS.add(ValueStep.of(2, ValueAdjustment.ofReplace(NOTIONAL_VALUE_2)));
NOTIONAL_STEPS.add(ValueStep.of(3, ValueAdjustment.ofReplace(NOTIONAL_VALUE_3)));
}
private static final ValueSchedule NOTIONAL = ValueSchedule.of(NOTIONAL_VALUE_0, NOTIONAL_STEPS);
private static final Cms PRODUCT = Cms.of(CmsLeg.builder()
.index(SWAP_INDEX)
.notional(NOTIONAL)
.payReceive(PAY)
.paymentSchedule(SCHEDULE_EUR)
.build());
public static final CmsTrade TRADE = CmsTrade.builder()
.product(PRODUCT)
.build();
public static final ResolvedCmsTrade RTRADE = TRADE.resolve(REF_DATA);
private static final Currency CURRENCY = PRODUCT.getCmsLeg().getCurrency();
public static final IborIndex INDEX = (IborIndex) PRODUCT.allRateIndices().iterator().next();
private static final CurveId DISCOUNT_CURVE_ID = CurveId.of("Default", "Discount");
private static final CurveId FORWARD_CURVE_ID = CurveId.of("Default", "Forward");
public static final RatesMarketDataLookup RATES_LOOKUP = RatesMarketDataLookup.of(
ImmutableMap.of(CURRENCY, DISCOUNT_CURVE_ID),
ImmutableMap.of(INDEX, FORWARD_CURVE_ID));
private static final SwaptionVolatilitiesId SWAPTION_ID = SwaptionVolatilitiesId.of("SABRVols");
public static final SwaptionMarketDataLookup SWAPTION_LOOKUP = SwaptionMarketDataLookup.of(INDEX, SWAPTION_ID);
private static final double CUT_OFF_STRIKE = 0.10;
private static final double MU = 2.50;
public static final CmsSabrExtrapolationParams CMS_MODEL = CmsSabrExtrapolationParams.of(CUT_OFF_STRIKE, MU);
private static final CalculationParameters PARAMS = CalculationParameters.of(RATES_LOOKUP, SWAPTION_LOOKUP, CMS_MODEL);
private static final LocalDate VAL_DATE = START.plusMonths(1);
public static final SabrSwaptionVolatilities VOLS = SwaptionSabrRateVolatilityDataSet.getVolatilitiesEur(VAL_DATE, false);
//-------------------------------------------------------------------------
public void test_requirementsAndCurrency() {
CmsTradeCalculationFunction function = new CmsTradeCalculationFunction();
Set<Measure> measures = function.supportedMeasures();
FunctionRequirements reqs = function.requirements(TRADE, measures, PARAMS, REF_DATA);
assertThat(reqs.getOutputCurrencies()).containsOnly(CURRENCY);
assertThat(reqs.getValueRequirements()).isEqualTo(
ImmutableSet.of(DISCOUNT_CURVE_ID, FORWARD_CURVE_ID, SWAPTION_ID));
assertThat(reqs.getTimeSeriesRequirements()).isEqualTo(ImmutableSet.of(IndexQuoteId.of(INDEX)));
assertThat(function.naturalCurrency(TRADE, REF_DATA)).isEqualTo(CURRENCY);
}
public void test_simpleMeasures() {
CmsTradeCalculationFunction function = new CmsTradeCalculationFunction();
ScenarioMarketData md = marketData();
RatesProvider provider = RATES_LOOKUP.ratesProvider(md.scenario(0));
SabrExtrapolationReplicationCmsTradePricer pricer = new SabrExtrapolationReplicationCmsTradePricer(
new SabrExtrapolationReplicationCmsProductPricer(
new SabrExtrapolationReplicationCmsLegPricer(
SabrExtrapolationReplicationCmsPeriodPricer.of(CUT_OFF_STRIKE, MU))));
ResolvedCmsTrade resolved = TRADE.resolve(REF_DATA);
MultiCurrencyAmount expectedPv = pricer.presentValue(resolved, provider, VOLS);
Set<Measure> measures = ImmutableSet.of(Measures.PRESENT_VALUE, Measures.RESOLVED_TARGET);
assertThat(function.calculate(TRADE, measures, PARAMS, md, REF_DATA))
.containsEntry(
Measures.PRESENT_VALUE, Result.success(MultiCurrencyScenarioArray.of(ImmutableList.of(expectedPv))))
.containsEntry(
Measures.RESOLVED_TARGET, Result.success(TRADE.resolve(REF_DATA)));
}
//-------------------------------------------------------------------------
static ScenarioMarketData marketData() {
LocalDateDoubleTimeSeries ts = LocalDateDoubleTimeSeries.of(date(2015, 10, 19), 0.013);
TestMarketDataMap md = new TestMarketDataMap(
VAL_DATE,
ImmutableMap.of(
DISCOUNT_CURVE_ID, SwaptionSabrRateVolatilityDataSet.CURVE_DSC_EUR,
FORWARD_CURVE_ID, SwaptionSabrRateVolatilityDataSet.CURVE_FWD_EUR,
SWAPTION_ID, VOLS),
ImmutableMap.of(
IndexQuoteId.of(SWAP_INDEX), ts));
return md;
}
}