/**
* 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.USD;
import static com.opengamma.strata.basics.date.DayCounts.ACT_365F;
import static com.opengamma.strata.basics.index.IborIndices.USD_LIBOR_3M;
import static com.opengamma.strata.basics.index.OvernightIndices.USD_FED_FUND;
import static com.opengamma.strata.product.swap.type.FixedIborSwapConventions.USD_FIXED_6M_LIBOR_3M;
import static com.opengamma.strata.product.swap.type.FixedOvernightSwapConventions.USD_FIXED_1Y_FED_FUND_OIS;
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.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.opengamma.strata.basics.ReferenceData;
import com.opengamma.strata.basics.StandardId;
import com.opengamma.strata.basics.currency.Currency;
import com.opengamma.strata.basics.currency.CurrencyAmount;
import com.opengamma.strata.basics.currency.MultiCurrencyAmount;
import com.opengamma.strata.basics.date.DayCount;
import com.opengamma.strata.basics.date.Tenor;
import com.opengamma.strata.basics.index.Index;
import com.opengamma.strata.collect.timeseries.LocalDateDoubleTimeSeries;
import com.opengamma.strata.data.ImmutableMarketData;
import com.opengamma.strata.data.ImmutableMarketDataBuilder;
import com.opengamma.strata.data.MarketData;
import com.opengamma.strata.data.MarketDataId;
import com.opengamma.strata.market.ValueType;
import com.opengamma.strata.market.curve.CurveGroupDefinition;
import com.opengamma.strata.market.curve.CurveGroupName;
import com.opengamma.strata.market.curve.CurveMetadata;
import com.opengamma.strata.market.curve.CurveName;
import com.opengamma.strata.market.curve.CurveNode;
import com.opengamma.strata.market.curve.DefaultCurveMetadata;
import com.opengamma.strata.market.curve.InterpolatedNodalCurveDefinition;
import com.opengamma.strata.market.curve.interpolator.CurveExtrapolator;
import com.opengamma.strata.market.curve.interpolator.CurveExtrapolators;
import com.opengamma.strata.market.curve.interpolator.CurveInterpolator;
import com.opengamma.strata.market.curve.interpolator.CurveInterpolators;
import com.opengamma.strata.market.curve.node.FixedIborSwapCurveNode;
import com.opengamma.strata.market.curve.node.FixedOvernightSwapCurveNode;
import com.opengamma.strata.market.curve.node.FraCurveNode;
import com.opengamma.strata.market.curve.node.IborFixingDepositCurveNode;
import com.opengamma.strata.market.observable.IndexQuoteId;
import com.opengamma.strata.market.observable.QuoteId;
import com.opengamma.strata.market.param.CurrencyParameterSensitivities;
import com.opengamma.strata.market.sensitivity.PointSensitivityBuilder;
import com.opengamma.strata.pricer.deposit.DiscountingIborFixingDepositProductPricer;
import com.opengamma.strata.pricer.fra.DiscountingFraTradePricer;
import com.opengamma.strata.pricer.rate.IborIndexRates;
import com.opengamma.strata.pricer.rate.ImmutableRatesProvider;
import com.opengamma.strata.pricer.rate.RatesProvider;
import com.opengamma.strata.pricer.rate.SimpleIborIndexRates;
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.common.BuySell;
import com.opengamma.strata.product.deposit.ResolvedIborFixingDepositTrade;
import com.opengamma.strata.product.deposit.type.IborFixingDepositTemplate;
import com.opengamma.strata.product.fra.ResolvedFraTrade;
import com.opengamma.strata.product.fra.type.FraTemplate;
import com.opengamma.strata.product.swap.ResolvedSwap;
import com.opengamma.strata.product.swap.ResolvedSwapTrade;
import com.opengamma.strata.product.swap.SwapTrade;
import com.opengamma.strata.product.swap.type.FixedIborSwapConventions;
import com.opengamma.strata.product.swap.type.FixedIborSwapTemplate;
import com.opengamma.strata.product.swap.type.FixedOvernightSwapTemplate;
/**
* Test for curve calibration with 2 curves in USD.
* One curve is Discounting and Fed Fund forward and the other one is Libor 3M forward.
*/
@Test
public class CalibrationZeroRateAndDiscountFactorUsd2OisIrsTest {
private static final LocalDate VAL_DATE_BD = LocalDate.of(2015, 7, 21);
private static final LocalDate VAL_DATE_HO = LocalDate.of(2015, 12, 25);
private static final CurveInterpolator INTERPOLATOR_LINEAR = CurveInterpolators.LINEAR;
private static final CurveExtrapolator EXTRAPOLATOR_FLAT = CurveExtrapolators.FLAT;
private static final DayCount CURVE_DC = ACT_365F;
// reference data
private static final ReferenceData REF_DATA = ReferenceData.standard();
private static final String SCHEME = "CALIBRATION";
/** Curve names */
private static final String DSCON_NAME = "USD-DSCON-OIS";
private static final CurveName DSCON_CURVE_NAME = CurveName.of(DSCON_NAME);
private static final String FWD3_NAME = "USD-LIBOR3M-FRAIRS";
private static final CurveName FWD3_CURVE_NAME = CurveName.of(FWD3_NAME);
/** Curves associations to currencies and indices. */
private static final Map<CurveName, Currency> DSC_NAMES = new HashMap<>();
private static final Map<CurveName, Set<Index>> IDX_NAMES = new HashMap<>();
private static final MarketData TS_EMPTY = MarketData.empty(VAL_DATE_BD);
private static final MarketData TS_BD_LIBOR3M;
private static final MarketData TS_HO_LIBOR3M;
static {
DSC_NAMES.put(DSCON_CURVE_NAME, USD);
Set<Index> usdFedFundSet = new HashSet<>();
usdFedFundSet.add(USD_FED_FUND);
IDX_NAMES.put(DSCON_CURVE_NAME, usdFedFundSet);
Set<Index> usdLibor3Set = new HashSet<>();
usdLibor3Set.add(USD_LIBOR_3M);
IDX_NAMES.put(FWD3_CURVE_NAME, usdLibor3Set);
double fixingValue = 0.002345;
LocalDateDoubleTimeSeries tsBdUsdLibor3M =
LocalDateDoubleTimeSeries.builder().put(VAL_DATE_BD, fixingValue).build();
LocalDate fixingDateHo = LocalDate.of(2015, 12, 24);
LocalDateDoubleTimeSeries tsHoUsdLibor3M =
LocalDateDoubleTimeSeries.builder().put(fixingDateHo, fixingValue).build();
TS_BD_LIBOR3M = ImmutableMarketData.builder(VAL_DATE_BD)
.addTimeSeries(IndexQuoteId.of(USD_LIBOR_3M), tsBdUsdLibor3M)
.build();
TS_HO_LIBOR3M = ImmutableMarketData.builder(VAL_DATE_HO)
.addTimeSeries(IndexQuoteId.of(USD_LIBOR_3M), tsHoUsdLibor3M)
.build();
}
/** Data for USD-DSCON curve */
/* Market values */
private static final double[] DSC_MARKET_QUOTES = new double[] {
0.00072000, 0.00082000, 0.00093000, 0.00090000, 0.00105000,
0.00118500, 0.00318650, 0.00318650, 0.00704000, 0.01121500, 0.01515000,
0.01845500, 0.02111000, 0.02332000, 0.02513500, 0.02668500};
private static final int DSC_NB_NODES = DSC_MARKET_QUOTES.length;
private static final String[] DSC_ID_VALUE = new String[] {
"OIS1M", "OIS2M", "OIS3M", "OIS6M", "OIS9M",
"OIS1Y", "OIS18M", "OIS2Y", "OIS3Y", "OIS4Y", "OIS5Y",
"OIS6Y", "OIS7Y", "OIS8Y", "OIS9Y", "OIS10Y"};
/* Nodes */
private static final CurveNode[] DSC_NODES = new CurveNode[DSC_NB_NODES];
/* Tenors */
private static final Period[] DSC_OIS_TENORS = new Period[] {
Period.ofMonths(1), Period.ofMonths(2), Period.ofMonths(3), Period.ofMonths(6), Period.ofMonths(9),
Period.ofYears(1), Period.ofMonths(18), Period.ofYears(2), Period.ofYears(3), Period.ofYears(4), Period.ofYears(5),
Period.ofYears(6), Period.ofYears(7), Period.ofYears(8), Period.ofYears(9), Period.ofYears(10)};
private static final int DSC_NB_OIS_NODES = DSC_OIS_TENORS.length;
static {
for (int i = 0; i < DSC_NB_OIS_NODES; i++) {
DSC_NODES[i] = FixedOvernightSwapCurveNode.of(
FixedOvernightSwapTemplate.of(Period.ZERO, Tenor.of(DSC_OIS_TENORS[i]), USD_FIXED_1Y_FED_FUND_OIS),
QuoteId.of(StandardId.of(SCHEME, DSC_ID_VALUE[i])));
}
}
/** Data for USD-LIBOR3M curve */
/* Market values */
private static final double[] FWD3_MARKET_QUOTES = new double[] {
0.00236600,
0.00258250, 0.00296050,
0.00294300, 0.00503000, 0.00939150, 0.01380800, 0.01732000,
0.02396200, 0.02930000, 0.03195000, 0.03423500, 0.03615500,
0.03696850, 0.03734500};
private static final int FWD3_NB_NODES = FWD3_MARKET_QUOTES.length;
private static final String[] FWD3_ID_VALUE = new String[] {
"Fixing",
"FRA3Mx6M", "FRA6Mx9M",
"IRS1Y", "IRS2Y", "IRS3Y", "IRS4Y", "IRS5Y",
"IRS7Y", "IRS10Y", "IRS12Y", "IRS15Y", "IRS20Y",
"IRS25Y", "IRS30Y"};
/* Nodes */
private static final CurveNode[] FWD3_NODES = new CurveNode[FWD3_NB_NODES];
/* Tenors */
private static final Period[] FWD3_FRA_TENORS = new Period[] { // Period to start
Period.ofMonths(3), Period.ofMonths(6)};
private static final int FWD3_NB_FRA_NODES = FWD3_FRA_TENORS.length;
private static final Period[] FWD3_IRS_TENORS = new Period[] {
Period.ofYears(1), Period.ofYears(2), Period.ofYears(3), Period.ofYears(4), Period.ofYears(5),
Period.ofYears(7), Period.ofYears(10), Period.ofYears(12), Period.ofYears(15), Period.ofYears(20),
Period.ofYears(25), Period.ofYears(30)};
private static final int FWD3_NB_IRS_NODES = FWD3_IRS_TENORS.length;
static {
FWD3_NODES[0] = IborFixingDepositCurveNode.of(IborFixingDepositTemplate.of(USD_LIBOR_3M),
QuoteId.of(StandardId.of(SCHEME, FWD3_ID_VALUE[0])));
for (int i = 0; i < FWD3_NB_FRA_NODES; i++) {
FWD3_NODES[i + 1] = FraCurveNode.of(FraTemplate.of(FWD3_FRA_TENORS[i], USD_LIBOR_3M),
QuoteId.of(StandardId.of(SCHEME, FWD3_ID_VALUE[i + 1])));
}
for (int i = 0; i < FWD3_NB_IRS_NODES; i++) {
FWD3_NODES[i + 1 + FWD3_NB_FRA_NODES] = FixedIborSwapCurveNode.of(
FixedIborSwapTemplate.of(Period.ZERO, Tenor.of(FWD3_IRS_TENORS[i]), USD_FIXED_6M_LIBOR_3M),
QuoteId.of(StandardId.of(SCHEME, FWD3_ID_VALUE[i + 1 + FWD3_NB_FRA_NODES])));
}
}
/** All quotes for the curve calibration on good business day. */
private static final ImmutableMarketData ALL_QUOTES_BD;
static {
ImmutableMarketDataBuilder builder = ImmutableMarketData.builder(VAL_DATE_BD);
for (int i = 0; i < FWD3_NB_NODES; i++) {
builder.addValue(QuoteId.of(StandardId.of(SCHEME, FWD3_ID_VALUE[i])), FWD3_MARKET_QUOTES[i]);
}
for (int i = 0; i < DSC_NB_NODES; i++) {
builder.addValue(QuoteId.of(StandardId.of(SCHEME, DSC_ID_VALUE[i])), DSC_MARKET_QUOTES[i]);
}
ALL_QUOTES_BD = builder.build();
}
/** All quotes for the curve calibration on holiday. */
private static final ImmutableMarketData ALL_QUOTES_HO = ALL_QUOTES_BD.toBuilder().valuationDate(VAL_DATE_HO).build();
/** All nodes by groups. */
private static final List<List<CurveNode[]>> CURVES_NODES = new ArrayList<>();
static {
List<CurveNode[]> groupDsc = new ArrayList<>();
groupDsc.add(DSC_NODES);
CURVES_NODES.add(groupDsc);
List<CurveNode[]> groupFwd3 = new ArrayList<>();
groupFwd3.add(FWD3_NODES);
CURVES_NODES.add(groupFwd3);
}
/** All metadata by groups */
private static final List<List<CurveMetadata>> CURVES_METADATA = new ArrayList<>();
static {
List<CurveMetadata> groupDsc = new ArrayList<>();
groupDsc.add(DefaultCurveMetadata.builder().curveName(DSCON_CURVE_NAME).xValueType(ValueType.YEAR_FRACTION)
.yValueType(ValueType.ZERO_RATE).dayCount(CURVE_DC).build());
CURVES_METADATA.add(groupDsc);
List<CurveMetadata> groupFwd3 = new ArrayList<>();
groupFwd3.add(DefaultCurveMetadata.builder().curveName(FWD3_CURVE_NAME).xValueType(ValueType.YEAR_FRACTION)
.yValueType(ValueType.ZERO_RATE).dayCount(CURVE_DC).build());
CURVES_METADATA.add(groupFwd3);
}
private static final DiscountingIborFixingDepositProductPricer FIXING_PRICER =
DiscountingIborFixingDepositProductPricer.DEFAULT;
private static final DiscountingFraTradePricer FRA_PRICER =
DiscountingFraTradePricer.DEFAULT;
private static final DiscountingSwapProductPricer SWAP_PRICER =
DiscountingSwapProductPricer.DEFAULT;
private static final MarketQuoteSensitivityCalculator MQC = MarketQuoteSensitivityCalculator.DEFAULT;
private static final CurveCalibrator CALIBRATOR = CurveCalibrator.of(1e-9, 1e-9, 100);
// Constants
private static final double TOLERANCE_PV = 1.0E-6;
private static final double TOLERANCE_PV_DELTA = 1.0E+2;
private static final CurveGroupName CURVE_GROUP_NAME = CurveGroupName.of("USD-DSCON-LIBOR3M");
private static final InterpolatedNodalCurveDefinition DSC_CURVE_DEFN =
InterpolatedNodalCurveDefinition.builder()
.name(DSCON_CURVE_NAME)
.xValueType(ValueType.YEAR_FRACTION)
.yValueType(ValueType.ZERO_RATE)
.dayCount(CURVE_DC)
.interpolator(INTERPOLATOR_LINEAR)
.extrapolatorLeft(EXTRAPOLATOR_FLAT)
.extrapolatorRight(EXTRAPOLATOR_FLAT)
.nodes(DSC_NODES).build();
private static final InterpolatedNodalCurveDefinition FWD3_CURVE_DEFN =
InterpolatedNodalCurveDefinition.builder()
.name(FWD3_CURVE_NAME)
.xValueType(ValueType.YEAR_FRACTION)
.yValueType(ValueType.ZERO_RATE)
.dayCount(CURVE_DC)
.interpolator(INTERPOLATOR_LINEAR)
.extrapolatorLeft(EXTRAPOLATOR_FLAT)
.extrapolatorRight(EXTRAPOLATOR_FLAT)
.nodes(FWD3_NODES).build();
private static final CurveGroupDefinition CURVE_GROUP_CONFIG =
CurveGroupDefinition.builder()
.name(CURVE_GROUP_NAME)
.addCurve(DSC_CURVE_DEFN, USD, USD_FED_FUND)
.addForwardCurve(FWD3_CURVE_DEFN, USD_LIBOR_3M).build();
private static final CurveGroupDefinition GROUP_1 =
CurveGroupDefinition.builder()
.name(CurveGroupName.of("USD-DSCON"))
.addCurve(DSC_CURVE_DEFN, USD, USD_FED_FUND)
.build();
private static final CurveGroupDefinition GROUP_2 =
CurveGroupDefinition.builder()
.name(CurveGroupName.of("USD-LIBOR3M"))
.addForwardCurve(FWD3_CURVE_DEFN, USD_LIBOR_3M)
.build();
private static final ImmutableRatesProvider KNOWN_DATA = ImmutableRatesProvider.builder(VAL_DATE_BD).build();
//-------------------------------------------------------------------------
public void calibration_present_value_oneGroup_no_fixing() {
RatesProvider result =
CALIBRATOR.calibrate(CURVE_GROUP_CONFIG, ALL_QUOTES_BD, REF_DATA);
assertResult(result, ALL_QUOTES_BD);
}
public void calibration_present_value_oneGroup_fixing() {
RatesProvider result =
CALIBRATOR.calibrate(CURVE_GROUP_CONFIG, ALL_QUOTES_BD.combinedWith(TS_BD_LIBOR3M), REF_DATA);
assertResult(result, ALL_QUOTES_BD);
}
public void calibration_present_value_oneGroup_holiday() {
RatesProvider result =
CALIBRATOR.calibrate(CURVE_GROUP_CONFIG, ALL_QUOTES_HO.combinedWith(TS_HO_LIBOR3M), REF_DATA);
assertResult(result, ALL_QUOTES_HO);
}
public void calibration_present_value_twoGroups() {
RatesProvider result =
CALIBRATOR.calibrate(ImmutableList.of(GROUP_1, GROUP_2), KNOWN_DATA, ALL_QUOTES_BD, REF_DATA);
assertResult(result, ALL_QUOTES_BD);
}
private void assertResult(RatesProvider result, ImmutableMarketData allQuotes) {
// Test PV Dsc
CurveNode[] dscNodes = CURVES_NODES.get(0).get(0);
List<ResolvedTrade> dscTrades = new ArrayList<>();
for (int i = 0; i < dscNodes.length; i++) {
dscTrades.add(dscNodes[i].resolvedTrade(1d, allQuotes, REF_DATA));
}
// OIS
for (int i = 0; i < DSC_NB_OIS_NODES; i++) {
MultiCurrencyAmount pvIrs = SWAP_PRICER
.presentValue(((ResolvedSwapTrade) dscTrades.get(i)).getProduct(), result);
assertEquals(pvIrs.getAmount(USD).getAmount(), 0.0, TOLERANCE_PV);
}
// Test PV Fwd3
CurveNode[] fwd3Nodes = CURVES_NODES.get(1).get(0);
List<ResolvedTrade> fwd3Trades = new ArrayList<>();
for (int i = 0; i < fwd3Nodes.length; i++) {
fwd3Trades.add(fwd3Nodes[i].resolvedTrade(1d, allQuotes, REF_DATA));
}
// Fixing
CurrencyAmount pvFixing = FIXING_PRICER.presentValue(
((ResolvedIborFixingDepositTrade) fwd3Trades.get(0)).getProduct(), result);
assertEquals(pvFixing.getAmount(), 0.0, TOLERANCE_PV);
// FRA
for (int i = 0; i < FWD3_NB_FRA_NODES; i++) {
CurrencyAmount pvFra = FRA_PRICER.presentValue(
((ResolvedFraTrade) fwd3Trades.get(i + 1)), result);
assertEquals(pvFra.getAmount(), 0.0, TOLERANCE_PV);
}
// IRS
for (int i = 0; i < FWD3_NB_IRS_NODES; i++) {
MultiCurrencyAmount pvIrs = SWAP_PRICER.presentValue(
((ResolvedSwapTrade) fwd3Trades.get(i + 1 + FWD3_NB_FRA_NODES)).getProduct(), result);
assertEquals(pvIrs.getAmount(USD).getAmount(), 0.0, TOLERANCE_PV);
}
}
public void calibration_market_quote_sensitivity_one_group_no_fixing() {
double shift = 1.0E-6;
Function<MarketData, RatesProvider> f =
marketData -> CALIBRATOR.calibrate(CURVE_GROUP_CONFIG, marketData, REF_DATA);
calibration_market_quote_sensitivity_check(f, CURVE_GROUP_CONFIG, shift, TS_EMPTY);
}
public void calibration_market_quote_sensitivity_one_group_fixing() {
double shift = 1.0E-6;
Function<MarketData, RatesProvider> f =
marketData -> CALIBRATOR.calibrate(CURVE_GROUP_CONFIG, marketData, REF_DATA);
calibration_market_quote_sensitivity_check(f, CURVE_GROUP_CONFIG, shift, TS_BD_LIBOR3M);
}
public void calibration_market_quote_sensitivity_two_group() {
double shift = 1.0E-6;
Function<MarketData, RatesProvider> calibrator =
marketData -> CALIBRATOR.calibrate(ImmutableList.of(GROUP_1, GROUP_2), KNOWN_DATA, marketData, REF_DATA);
calibration_market_quote_sensitivity_check(calibrator, CURVE_GROUP_CONFIG, shift, TS_EMPTY);
}
private void calibration_market_quote_sensitivity_check(
Function<MarketData, RatesProvider> calibrator,
CurveGroupDefinition config,
double shift,
MarketData ts) {
double notional = 100_000_000.0;
double rate = 0.0400;
SwapTrade trade = FixedIborSwapConventions.USD_FIXED_1Y_LIBOR_3M.createTrade(
VAL_DATE_BD, Period.ofMonths(6), Tenor.TENOR_7Y, BuySell.BUY, notional, rate, REF_DATA);
RatesProvider result = CALIBRATOR.calibrate(config, ALL_QUOTES_BD.combinedWith(ts), REF_DATA);
ResolvedSwap product = trade.getProduct().resolve(REF_DATA);
PointSensitivityBuilder pts = SWAP_PRICER.presentValueSensitivity(product, result);
CurrencyParameterSensitivities ps = result.parameterSensitivity(pts.build());
CurrencyParameterSensitivities mqs = MQC.sensitivity(ps, result);
double pv0 = SWAP_PRICER.presentValue(product, result).getAmount(USD).getAmount();
double[] mqsDscComputed = mqs.getSensitivity(DSCON_CURVE_NAME, USD).getSensitivity().toArray();
for (int i = 0; i < DSC_NB_NODES; i++) {
Map<MarketDataId<?>, Object> map = new HashMap<>(ALL_QUOTES_BD.getValues());
map.put(QuoteId.of(StandardId.of(SCHEME, DSC_ID_VALUE[i])), DSC_MARKET_QUOTES[i] + shift);
ImmutableMarketData marketData = ImmutableMarketData.of(VAL_DATE_BD, map);
RatesProvider rpShifted = calibrator.apply(marketData.combinedWith(ts));
double pvS = SWAP_PRICER.presentValue(product, rpShifted).getAmount(USD).getAmount();
assertEquals(mqsDscComputed[i], (pvS - pv0) / shift, TOLERANCE_PV_DELTA);
}
double[] mqsFwd3Computed = mqs.getSensitivity(FWD3_CURVE_NAME, USD).getSensitivity().toArray();
for (int i = 0; i < FWD3_NB_NODES; i++) {
Map<MarketDataId<?>, Object> map = new HashMap<>(ALL_QUOTES_BD.getValues());
map.put(QuoteId.of(StandardId.of(SCHEME, FWD3_ID_VALUE[i])), FWD3_MARKET_QUOTES[i] + shift);
ImmutableMarketData marketData = ImmutableMarketData.of(VAL_DATE_BD, map);
RatesProvider rpShifted = calibrator.apply(marketData.combinedWith(ts));
double pvS = SWAP_PRICER.presentValue(product, rpShifted).getAmount(USD).getAmount();
assertEquals(mqsFwd3Computed[i], (pvS - pv0) / shift, TOLERANCE_PV_DELTA);
}
}
/* Check calibration for discounting and forward curve interpolated on (pseudo-) discount factors. */
public void calibration_present_value_discountCurve() {
CurveInterpolator interp = CurveInterpolators.LOG_LINEAR;
CurveExtrapolator extrapRight = CurveExtrapolators.LOG_LINEAR;
CurveExtrapolator extrapLeft = CurveExtrapolators.QUADRATIC_LEFT;
InterpolatedNodalCurveDefinition dsc =
InterpolatedNodalCurveDefinition.builder()
.name(DSCON_CURVE_NAME)
.xValueType(ValueType.YEAR_FRACTION)
.yValueType(ValueType.DISCOUNT_FACTOR)
.dayCount(CURVE_DC)
.interpolator(interp)
.extrapolatorLeft(extrapLeft)
.extrapolatorRight(extrapRight)
.nodes(DSC_NODES).build();
InterpolatedNodalCurveDefinition fwd =
InterpolatedNodalCurveDefinition.builder()
.name(FWD3_CURVE_NAME)
.xValueType(ValueType.YEAR_FRACTION)
.yValueType(ValueType.DISCOUNT_FACTOR)
.dayCount(CURVE_DC)
.interpolator(interp)
.extrapolatorLeft(extrapLeft)
.extrapolatorRight(extrapRight)
.nodes(FWD3_NODES).build();
CurveGroupDefinition config =
CurveGroupDefinition.builder()
.name(CURVE_GROUP_NAME)
.addCurve(dsc, USD, USD_FED_FUND)
.addForwardCurve(fwd, USD_LIBOR_3M)
.build();
RatesProvider result = CALIBRATOR.calibrate(config, ALL_QUOTES_BD, REF_DATA);
assertResult(result, ALL_QUOTES_BD);
double shift = 1.0E-6;
Function<MarketData, RatesProvider> f =
marketData -> CALIBRATOR.calibrate(config, marketData, REF_DATA);
calibration_market_quote_sensitivity_check(f, config, shift, TS_EMPTY);
}
/* Check calibration for forward curve directly interpolated on forward rates. */
public void calibration_present_value_simple_forward() {
InterpolatedNodalCurveDefinition dsc =
InterpolatedNodalCurveDefinition.builder()
.name(DSCON_CURVE_NAME)
.xValueType(ValueType.YEAR_FRACTION)
.yValueType(ValueType.ZERO_RATE)
.dayCount(CURVE_DC)
.interpolator(INTERPOLATOR_LINEAR)
.extrapolatorLeft(EXTRAPOLATOR_FLAT)
.extrapolatorRight(EXTRAPOLATOR_FLAT)
.nodes(DSC_NODES).build();
InterpolatedNodalCurveDefinition fwd =
InterpolatedNodalCurveDefinition.builder()
.name(FWD3_CURVE_NAME)
.xValueType(ValueType.YEAR_FRACTION)
.yValueType(ValueType.FORWARD_RATE)
.dayCount(CURVE_DC)
.interpolator(INTERPOLATOR_LINEAR)
.extrapolatorLeft(EXTRAPOLATOR_FLAT)
.extrapolatorRight(EXTRAPOLATOR_FLAT)
.nodes(FWD3_NODES).build();
CurveGroupDefinition config =
CurveGroupDefinition.builder()
.name(CURVE_GROUP_NAME)
.addCurve(dsc, USD, USD_FED_FUND)
.addForwardCurve(fwd, USD_LIBOR_3M)
.build();
RatesProvider result = CALIBRATOR.calibrate(config, ALL_QUOTES_BD, REF_DATA);
assertResult(result, ALL_QUOTES_BD);
IborIndexRates ibor3M = result.iborIndexRates(USD_LIBOR_3M);
assertTrue(ibor3M instanceof SimpleIborIndexRates,
"USD-LIBOR-3M curve should be simple interpolation on forward rates");
double shift = 1.0E-6;
Function<MarketData, RatesProvider> f =
marketData -> CALIBRATOR.calibrate(config, marketData, REF_DATA);
calibration_market_quote_sensitivity_check(f, config, shift, TS_EMPTY);
}
public void calibration_present_value_discountCurve_clamped() {
CurveInterpolator interp = CurveInterpolators.LOG_NATURAL_SPLINE_DISCOUNT_FACTOR;
CurveExtrapolator extrapRight = CurveExtrapolators.LOG_LINEAR;
CurveExtrapolator extrapLeft = CurveExtrapolators.INTERPOLATOR;
InterpolatedNodalCurveDefinition dsc =
InterpolatedNodalCurveDefinition.builder()
.name(DSCON_CURVE_NAME)
.xValueType(ValueType.YEAR_FRACTION)
.yValueType(ValueType.DISCOUNT_FACTOR)
.dayCount(CURVE_DC)
.interpolator(interp)
.extrapolatorLeft(extrapLeft)
.extrapolatorRight(extrapRight)
.nodes(DSC_NODES).build();
InterpolatedNodalCurveDefinition fwd =
InterpolatedNodalCurveDefinition.builder()
.name(FWD3_CURVE_NAME)
.xValueType(ValueType.YEAR_FRACTION)
.yValueType(ValueType.DISCOUNT_FACTOR)
.dayCount(CURVE_DC)
.interpolator(interp)
.extrapolatorLeft(extrapLeft)
.extrapolatorRight(extrapRight)
.nodes(FWD3_NODES).build();
CurveGroupDefinition config =
CurveGroupDefinition.builder()
.name(CURVE_GROUP_NAME)
.addCurve(dsc, USD, USD_FED_FUND)
.addForwardCurve(fwd, USD_LIBOR_3M)
.build();
RatesProvider result = CALIBRATOR.calibrate(config, ALL_QUOTES_BD, REF_DATA);
assertResult(result, ALL_QUOTES_BD);
double shift = 1.0E-6;
Function<MarketData, RatesProvider> f =
marketData -> CALIBRATOR.calibrate(config, marketData, REF_DATA);
calibration_market_quote_sensitivity_check(f, config, shift, TS_EMPTY);
}
//-------------------------------------------------------------------------
@SuppressWarnings("unused")
@Test(enabled = false)
void performance() {
long startTime, endTime;
int nbTests = 100;
int nbRep = 3;
int count = 0;
for (int i = 0; i < nbRep; i++) {
startTime = System.currentTimeMillis();
for (int looprep = 0; looprep < nbTests; looprep++) {
RatesProvider result = CALIBRATOR.calibrate(CURVE_GROUP_CONFIG, ALL_QUOTES_BD, REF_DATA);
count += result.getValuationDate().getDayOfMonth();
}
endTime = System.currentTimeMillis();
System.out.println("Performance: " + nbTests + " calibrations for 2 curve with 30 nodes in "
+ (endTime - startTime) + " ms.");
}
System.out.println("Avoiding hotspot: " + count);
// Previous run: 1500 ms for 100 calibrations (2 curve simultaneous - 30 nodes)
}
}