/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.pricer.curve; import static com.opengamma.strata.basics.currency.Currency.EUR; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import java.time.LocalDate; import java.time.Period; import java.util.ArrayList; import java.util.List; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; 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.data.MarketData; import com.opengamma.strata.market.curve.CurveGroupDefinition; import com.opengamma.strata.market.curve.CurveNode; import com.opengamma.strata.market.curve.NodalCurveDefinition; import com.opengamma.strata.market.param.CurrencyParameterSensitivities; import com.opengamma.strata.market.param.CurrencyParameterSensitivity; import com.opengamma.strata.market.sensitivity.PointSensitivities; import com.opengamma.strata.pricer.deposit.DiscountingIborFixingDepositProductPricer; import com.opengamma.strata.pricer.fra.DiscountingFraProductPricer; import com.opengamma.strata.pricer.rate.RatesProvider; import com.opengamma.strata.pricer.sensitivity.MarketQuoteSensitivityCalculator; import com.opengamma.strata.pricer.swap.DiscountingSwapProductPricer; import com.opengamma.strata.product.ResolvedTrade; import com.opengamma.strata.product.deposit.ResolvedIborFixingDepositTrade; import com.opengamma.strata.product.fra.ResolvedFraTrade; import com.opengamma.strata.product.swap.ResolvedSwapTrade; /** * Test curve calibration */ @Test public class CalibrationDiscountingSimpleEur3Test { private static final LocalDate VAL_DATE = LocalDate.of(2015, 7, 24); // reference data private static final ReferenceData REF_DATA = ReferenceData.standard(); /** Data for EUR-DSCON curve */ /* Market values */ private static final double[] DSC_MARKET_QUOTES = new double[] { 0.0010, 0.0020, 0.0030, 0.0040}; /* Tenors */ private static final Period[] DSC_OIS_TENORS = new Period[] { Period.ofYears(2), Period.ofYears(5), Period.ofYears(10), Period.ofYears(30)}; /** Data for EUR-EURIBOR3M curve */ /* Market values */ private static final double FWD3_FIXING_QUOTE = 0.0050; private static final double[] FWD3_FRA_QUOTES = new double[] {0.0051, 0.0052, 0.0053}; private static final double[] FWD3_IRS_QUOTES = new double[] {0.0054, 0.0055, 0.0056, 0.0057}; /* Tenors */ private static final Period[] FWD3_FRA_TENORS = new Period[] { // Period to start Period.ofMonths(3), Period.ofMonths(6), Period.ofMonths(9)}; private static final Period[] FWD3_IRS_TENORS = new Period[] { Period.ofYears(2), Period.ofYears(5), Period.ofYears(10), Period.ofYears(30)}; /** Data for EUR-EURIBOR6M curve */ /* Market values */ private static final double FWD6_FIXING_QUOTE = 0.001; private static final double[] FWD6_FRA_QUOTES = new double[] {0.011, 0.012}; private static final double[] FWD6_IRS_QUOTES = new double[] {0.013, 0.014, 0.015, 0.016, 0.017}; /* Tenors */ private static final Period[] FWD6_FRA_TENORS = new Period[] { // Period to start Period.ofMonths(3), Period.ofMonths(6)}; private static final Period[] FWD6_IRS_TENORS = new Period[] { Period.ofYears(2), Period.ofYears(3), Period.ofYears(5), Period.ofYears(10), Period.ofYears(30)}; private static final DiscountingIborFixingDepositProductPricer PRICER_FIXING = DiscountingIborFixingDepositProductPricer.DEFAULT; private static final DiscountingFraProductPricer PRICER_FRA = DiscountingFraProductPricer.DEFAULT; private static final DiscountingSwapProductPricer SWAP_PRICER = DiscountingSwapProductPricer.DEFAULT; private static final MarketQuoteSensitivityCalculator MQC = MarketQuoteSensitivityCalculator.DEFAULT; // Constants private static final double TOLERANCE_PV = 1.0E-6; private static final double TOLERANCE_DELTA = 1.0E-10; //------------------------------------------------------------------------- public void calibration_present_value() { RatesProvider result = CalibrationEurStandard.calibrateEurStandard(VAL_DATE, DSC_MARKET_QUOTES, DSC_OIS_TENORS, FWD3_FIXING_QUOTE, FWD3_FRA_QUOTES, FWD3_IRS_QUOTES, FWD3_FRA_TENORS, FWD3_IRS_TENORS, FWD6_FIXING_QUOTE, FWD6_FRA_QUOTES, FWD6_IRS_QUOTES, FWD6_FRA_TENORS, FWD6_IRS_TENORS); /* Curve Discounting/EUR-EONIA */ String[] dscIdValues = CalibrationEurStandard.dscIdValues(DSC_OIS_TENORS); /* Curve EUR-EURIBOR-3M */ double[] fwd3MarketQuotes = CalibrationEurStandard.fwdMarketQuotes(FWD3_FIXING_QUOTE, FWD3_FRA_QUOTES, FWD3_IRS_QUOTES); String[] fwd3IdValue = CalibrationEurStandard.fwdIdValue(3, FWD3_FIXING_QUOTE, FWD3_FRA_QUOTES, FWD3_IRS_QUOTES, FWD3_FRA_TENORS, FWD3_IRS_TENORS); /* Curve EUR-EURIBOR-6M */ double[] fwd6MarketQuotes = CalibrationEurStandard.fwdMarketQuotes(FWD6_FIXING_QUOTE, FWD6_FRA_QUOTES, FWD6_IRS_QUOTES); String[] fwd6IdValue = CalibrationEurStandard.fwdIdValue(6, FWD6_FIXING_QUOTE, FWD6_FRA_QUOTES, FWD6_IRS_QUOTES, FWD6_FRA_TENORS, FWD6_IRS_TENORS); /* All quotes for the curve calibration */ MarketData allQuotes = CalibrationEurStandard.allQuotes( VAL_DATE, DSC_MARKET_QUOTES, dscIdValues, fwd3MarketQuotes, fwd3IdValue, fwd6MarketQuotes, fwd6IdValue); /* All nodes by groups. */ CurveGroupDefinition config = CalibrationEurStandard.config(DSC_OIS_TENORS, dscIdValues, FWD3_FRA_TENORS, FWD3_IRS_TENORS, fwd3IdValue, FWD6_FRA_TENORS, FWD6_IRS_TENORS, fwd6IdValue); ImmutableList<NodalCurveDefinition> definitions = config.getCurveDefinitions(); // Test PV Dsc ImmutableList<CurveNode> dscNodes = definitions.get(0).getNodes(); List<ResolvedTrade> dscTrades = new ArrayList<>(); for (int i = 0; i < dscNodes.size(); i++) { dscTrades.add(dscNodes.get(i).resolvedTrade(1d, allQuotes, REF_DATA)); } // OIS for (int i = 0; i < DSC_MARKET_QUOTES.length; i++) { MultiCurrencyAmount pvIrs = SWAP_PRICER .presentValue(((ResolvedSwapTrade) dscTrades.get(i)).getProduct(), result); assertEquals(pvIrs.getAmount(EUR).getAmount(), 0.0, TOLERANCE_PV); } // Test PV Fwd3 ImmutableList<CurveNode> fwd3Nodes = definitions.get(1).getNodes(); List<ResolvedTrade> fwd3Trades = new ArrayList<>(); for (int i = 0; i < fwd3Nodes.size(); i++) { fwd3Trades.add(fwd3Nodes.get(i).resolvedTrade(1d, allQuotes, REF_DATA)); } // FRA for (int i = 0; i < FWD3_FRA_QUOTES.length; i++) { CurrencyAmount pvFra = PRICER_FRA .presentValue(((ResolvedFraTrade) fwd3Trades.get(i + 1)).getProduct(), result); assertEquals(pvFra.getAmount(), 0.0, TOLERANCE_PV); } // IRS for (int i = 0; i < FWD3_IRS_QUOTES.length; i++) { MultiCurrencyAmount pvIrs = SWAP_PRICER .presentValue(((ResolvedSwapTrade) fwd3Trades.get(i + 1 + FWD3_FRA_QUOTES.length)).getProduct(), result); assertEquals(pvIrs.getAmount(EUR).getAmount(), 0.0, TOLERANCE_PV); } // Test PV Fwd6 ImmutableList<CurveNode> fwd6Nodes = definitions.get(2).getNodes(); List<ResolvedTrade> fwd6Trades = new ArrayList<>(); for (int i = 0; i < fwd6Nodes.size(); i++) { fwd6Trades.add(fwd6Nodes.get(i).resolvedTrade(1d, allQuotes, REF_DATA)); } // IRS for (int i = 0; i < FWD6_IRS_QUOTES.length; i++) { MultiCurrencyAmount pvIrs = SWAP_PRICER .presentValue(((ResolvedSwapTrade) fwd6Trades.get(i + 1 + FWD6_FRA_QUOTES.length)).getProduct(), result); assertEquals(pvIrs.getAmount(EUR).getAmount(), 0.0, TOLERANCE_PV); } } //------------------------------------------------------------------------- public void calibration_transition_coherence_par_rate() { RatesProvider provider = CalibrationEurStandard.calibrateEurStandard(VAL_DATE, DSC_MARKET_QUOTES, DSC_OIS_TENORS, FWD3_FIXING_QUOTE, FWD3_FRA_QUOTES, FWD3_IRS_QUOTES, FWD3_FRA_TENORS, FWD3_IRS_TENORS, FWD6_FIXING_QUOTE, FWD6_FRA_QUOTES, FWD6_IRS_QUOTES, FWD6_FRA_TENORS, FWD6_IRS_TENORS); /* Curve Discounting/EUR-EONIA */ String[] dscIdValues = CalibrationEurStandard.dscIdValues(DSC_OIS_TENORS); /* Curve EUR-EURIBOR-3M */ double[] fwd3MarketQuotes = CalibrationEurStandard.fwdMarketQuotes(FWD3_FIXING_QUOTE, FWD3_FRA_QUOTES, FWD3_IRS_QUOTES); String[] fwd3IdValue = CalibrationEurStandard.fwdIdValue(3, FWD3_FIXING_QUOTE, FWD3_FRA_QUOTES, FWD3_IRS_QUOTES, FWD3_FRA_TENORS, FWD3_IRS_TENORS); /* Curve EUR-EURIBOR-6M */ double[] fwd6MarketQuotes = CalibrationEurStandard.fwdMarketQuotes(FWD6_FIXING_QUOTE, FWD6_FRA_QUOTES, FWD6_IRS_QUOTES); String[] fwd6IdValue = CalibrationEurStandard.fwdIdValue(6, FWD6_FIXING_QUOTE, FWD6_FRA_QUOTES, FWD6_IRS_QUOTES, FWD6_FRA_TENORS, FWD6_IRS_TENORS); /* All quotes for the curve calibration */ MarketData allQuotes = CalibrationEurStandard.allQuotes( VAL_DATE, DSC_MARKET_QUOTES, dscIdValues, fwd3MarketQuotes, fwd3IdValue, fwd6MarketQuotes, fwd6IdValue); /* All nodes by groups. */ CurveGroupDefinition config = CalibrationEurStandard.config(DSC_OIS_TENORS, dscIdValues, FWD3_FRA_TENORS, FWD3_IRS_TENORS, fwd3IdValue, FWD6_FRA_TENORS, FWD6_IRS_TENORS, fwd6IdValue); ImmutableList<NodalCurveDefinition> definitions = config.getCurveDefinitions(); // Test PV Dsc ImmutableList<CurveNode> dscNodes = definitions.get(0).getNodes(); List<ResolvedTrade> dscTrades = new ArrayList<>(); for (int i = 0; i < dscNodes.size(); i++) { dscTrades.add(dscNodes.get(i).resolvedTrade(1d, allQuotes, REF_DATA)); } // OIS for (int loopnode = 0; loopnode < DSC_MARKET_QUOTES.length; loopnode++) { PointSensitivities pts = SWAP_PRICER.parRateSensitivity( ((ResolvedSwapTrade) dscTrades.get(loopnode)).getProduct(), provider).build(); CurrencyParameterSensitivities ps = provider.parameterSensitivity(pts); CurrencyParameterSensitivities mqs = MQC.sensitivity(ps, provider); assertEquals(mqs.size(), 3); // Calibration of all curves simultaneously CurrencyParameterSensitivity mqsDsc = mqs.getSensitivity(CalibrationEurStandard.DSCON_CURVE_NAME, EUR); assertTrue(mqsDsc.getMarketDataName().equals(CalibrationEurStandard.DSCON_CURVE_NAME)); assertTrue(mqsDsc.getCurrency().equals(EUR)); DoubleArray mqsData = mqsDsc.getSensitivity(); assertEquals(mqsData.size(), DSC_MARKET_QUOTES.length); for (int i = 0; i < mqsData.size(); i++) { assertEquals(mqsData.get(i), (i == loopnode) ? 1.0 : 0.0, TOLERANCE_DELTA); } } // Test PV Fwd3 ImmutableList<CurveNode> fwd3Nodes = definitions.get(1).getNodes(); List<ResolvedTrade> fwd3Trades = new ArrayList<>(); for (int i = 0; i < fwd3Nodes.size(); i++) { fwd3Trades.add(fwd3Nodes.get(i).resolvedTrade(1d, allQuotes, REF_DATA)); } for (int loopnode = 0; loopnode < fwd3MarketQuotes.length; loopnode++) { PointSensitivities pts = null; if (fwd3Trades.get(loopnode) instanceof ResolvedIborFixingDepositTrade) { pts = PRICER_FIXING.parSpreadSensitivity( ((ResolvedIborFixingDepositTrade) fwd3Trades.get(loopnode)).getProduct(), provider); } if (fwd3Trades.get(loopnode) instanceof ResolvedFraTrade) { pts = PRICER_FRA.parSpreadSensitivity( ((ResolvedFraTrade) fwd3Trades.get(loopnode)).getProduct(), provider); } if (fwd3Trades.get(loopnode) instanceof ResolvedSwapTrade) { pts = SWAP_PRICER.parSpreadSensitivity( ((ResolvedSwapTrade) fwd3Trades.get(loopnode)).getProduct(), provider).build(); } CurrencyParameterSensitivities ps = provider.parameterSensitivity(pts); CurrencyParameterSensitivities mqs = MQC.sensitivity(ps, provider); assertEquals(mqs.size(), 3); // Calibration of all curves simultaneously CurrencyParameterSensitivity mqsDsc = mqs.getSensitivity(CalibrationEurStandard.DSCON_CURVE_NAME, EUR); CurrencyParameterSensitivity mqsFwd3 = mqs.getSensitivity(CalibrationEurStandard.FWD3_CURVE_NAME, EUR); DoubleArray mqsDscData = mqsDsc.getSensitivity(); assertEquals(mqsDscData.size(), DSC_MARKET_QUOTES.length); for (int i = 0; i < mqsDscData.size(); i++) { assertEquals(mqsDscData.get(i), 0.0, TOLERANCE_DELTA); } DoubleArray mqsFwd3Data = mqsFwd3.getSensitivity(); assertEquals(mqsFwd3Data.size(), fwd3MarketQuotes.length); for (int i = 0; i < mqsFwd3Data.size(); i++) { assertEquals(mqsFwd3Data.get(i), (i == loopnode) ? 1.0 : 0.0, TOLERANCE_DELTA); } } // Test PV Fwd6 ImmutableList<CurveNode> fwd6Nodes = definitions.get(2).getNodes(); List<ResolvedTrade> fwd6Trades = new ArrayList<>(); for (int i = 0; i < fwd6Nodes.size(); i++) { fwd6Trades.add(fwd6Nodes.get(i).resolvedTrade(1d, allQuotes, REF_DATA)); } for (int loopnode = 0; loopnode < fwd6MarketQuotes.length; loopnode++) { PointSensitivities pts = null; if (fwd6Trades.get(loopnode) instanceof ResolvedIborFixingDepositTrade) { pts = PRICER_FIXING.parSpreadSensitivity( ((ResolvedIborFixingDepositTrade) fwd6Trades.get(loopnode)).getProduct(), provider); } if (fwd6Trades.get(loopnode) instanceof ResolvedFraTrade) { pts = PRICER_FRA.parSpreadSensitivity( ((ResolvedFraTrade) fwd6Trades.get(loopnode)).getProduct(), provider); } if (fwd6Trades.get(loopnode) instanceof ResolvedSwapTrade) { pts = SWAP_PRICER.parSpreadSensitivity( ((ResolvedSwapTrade) fwd6Trades.get(loopnode)).getProduct(), provider).build(); } CurrencyParameterSensitivities ps = provider.parameterSensitivity(pts); CurrencyParameterSensitivities mqs = MQC.sensitivity(ps, provider); assertEquals(mqs.size(), 3); CurrencyParameterSensitivity mqsDsc = mqs.getSensitivity(CalibrationEurStandard.DSCON_CURVE_NAME, EUR); CurrencyParameterSensitivity mqsFwd3 = mqs.getSensitivity(CalibrationEurStandard.FWD3_CURVE_NAME, EUR); CurrencyParameterSensitivity mqsFwd6 = mqs.getSensitivity(CalibrationEurStandard.FWD6_CURVE_NAME, EUR); DoubleArray mqsDscData = mqsDsc.getSensitivity(); assertEquals(mqsDscData.size(), DSC_MARKET_QUOTES.length); for (int i = 0; i < mqsDscData.size(); i++) { assertEquals(mqsDscData.get(i), 0.0, TOLERANCE_DELTA); } DoubleArray mqsFwd3Data = mqsFwd3.getSensitivity(); assertEquals(mqsFwd3Data.size(), fwd3MarketQuotes.length); for (int i = 0; i < mqsFwd3Data.size(); i++) { assertEquals(mqsFwd3Data.get(i), 0.0, TOLERANCE_DELTA); } DoubleArray mqsFwd6Data = mqsFwd6.getSensitivity(); assertEquals(mqsFwd6Data.size(), fwd6MarketQuotes.length); for (int i = 0; i < mqsFwd6Data.size(); i++) { assertEquals(mqsFwd6Data.get(i), (i == loopnode) ? 1.0 : 0.0, TOLERANCE_DELTA); } } } }