/** * 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 com.opengamma.strata.basics.date.DayCounts.ACT_365F; import static com.opengamma.strata.basics.index.IborIndices.EUR_EURIBOR_3M; import static com.opengamma.strata.basics.index.IborIndices.EUR_EURIBOR_6M; import static com.opengamma.strata.basics.index.OvernightIndices.EUR_EONIA; import static com.opengamma.strata.product.swap.type.FixedIborSwapConventions.EUR_FIXED_1Y_EURIBOR_3M; import static com.opengamma.strata.product.swap.type.FixedIborSwapConventions.EUR_FIXED_1Y_EURIBOR_6M; import static com.opengamma.strata.product.swap.type.FixedOvernightSwapConventions.EUR_FIXED_1Y_EONIA_OIS; import java.time.LocalDate; import java.time.Period; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import com.opengamma.strata.basics.ReferenceData; import com.opengamma.strata.basics.StandardId; import com.opengamma.strata.basics.currency.Currency; 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.data.ImmutableMarketData; import com.opengamma.strata.data.ImmutableMarketDataBuilder; import com.opengamma.strata.data.MarketData; 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.CurveName; import com.opengamma.strata.market.curve.CurveNode; 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.QuoteId; import com.opengamma.strata.pricer.rate.RatesProvider; import com.opengamma.strata.product.deposit.type.IborFixingDepositTemplate; import com.opengamma.strata.product.fra.type.FraTemplate; import com.opengamma.strata.product.swap.type.FixedIborSwapTemplate; import com.opengamma.strata.product.swap.type.FixedOvernightSwapTemplate; public class CalibrationEurStandard { 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 = "EUR_EONIA_EOD"; public static final CurveName DSCON_CURVE_NAME = CurveName.of(DSCON_NAME); private static final String FWD3_NAME = "EUR_EURIBOR_3M"; public static final CurveName FWD3_CURVE_NAME = CurveName.of(FWD3_NAME); private static final String FWD6_NAME = "EUR_EURIBOR_6M"; public static final CurveName FWD6_CURVE_NAME = CurveName.of(FWD6_NAME); private static final String CURVE_GROUP_NAME_STR = "EUR-DSCON-EURIBOR3M-EURIBOR6M"; private static final CurveGroupName CURVE_GROUP_NAME = CurveGroupName.of(CURVE_GROUP_NAME_STR); /** 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<>(); static { DSC_NAMES.put(DSCON_CURVE_NAME, EUR); Set<Index> eurEoniaSet = new HashSet<>(); eurEoniaSet.add(EUR_EONIA); IDX_NAMES.put(DSCON_CURVE_NAME, eurEoniaSet); Set<Index> eurEuribor3Set = new HashSet<>(); eurEuribor3Set.add(EUR_EURIBOR_3M); IDX_NAMES.put(FWD3_CURVE_NAME, eurEuribor3Set); Set<Index> eurEuriabor6Set = new HashSet<>(); eurEuriabor6Set.add(EUR_EURIBOR_6M); IDX_NAMES.put(FWD6_CURVE_NAME, eurEuriabor6Set); } private static final CurveInterpolator INTERPOLATOR_LINEAR = CurveInterpolators.LINEAR; private static final CurveExtrapolator EXTRAPOLATOR_FLAT = CurveExtrapolators.FLAT; private static final CurveCalibrator CALIBRATOR = CurveCalibrator.of(1e-9, 1e-9, 100); public static RatesProvider calibrateEurStandard( LocalDate valuationDate, double[] dscOisQuotes, Period[] dscOisTenors, double fwd3FixingQuote, double[] fwd3FraQuotes, double[] fwd3IrsQuotes, Period[] fwd3FraTenors, Period[] fwd3IrsTenors, double fwd6FixingQuote, double[] fwd6FraQuotes, double[] fwd6IrsQuotes, Period[] fwd6FraTenors, Period[] fwd6IrsTenors) { /* Curve Discounting/EUR-EONIA */ String[] dscIdValues = dscIdValues(dscOisTenors); /* Curve EUR-EURIBOR-3M */ double[] fwd3MarketQuotes = fwdMarketQuotes(fwd3FixingQuote, fwd3FraQuotes, fwd3IrsQuotes); String[] fwd3IdValues = fwdIdValue(3, fwd3FixingQuote, fwd3FraQuotes, fwd3IrsQuotes, fwd3FraTenors, fwd3IrsTenors); /* Curve EUR-EURIBOR-6M */ double[] fwd6MarketQuotes = fwdMarketQuotes(fwd6FixingQuote, fwd6FraQuotes, fwd6IrsQuotes); String[] fwd6IdValues = fwdIdValue(6, fwd6FixingQuote, fwd6FraQuotes, fwd6IrsQuotes, fwd6FraTenors, fwd6IrsTenors); /* All quotes for the curve calibration */ MarketData allQuotes = allQuotes(valuationDate, dscOisQuotes, dscIdValues, fwd3MarketQuotes, fwd3IdValues, fwd6MarketQuotes, fwd6IdValues); /* All nodes by groups. */ CurveGroupDefinition config = config(dscOisTenors, dscIdValues, fwd3FraTenors, fwd3IrsTenors, fwd3IdValues, fwd6FraTenors, fwd6IrsTenors, fwd6IdValues); /* Results */ return CALIBRATOR.calibrate(config, allQuotes, REF_DATA); } public static String[] dscIdValues(Period[] dscOisTenors) { String[] dscIdValues = new String[dscOisTenors.length]; for (int i = 0; i < dscOisTenors.length; i++) { dscIdValues[i] = "OIS" + dscOisTenors[i].toString(); } return dscIdValues; } public static String[] fwdIdValue( int tenor, double fwdFixingQuote, double[] fwdFraQuotes, double[] fwdIrsQuotes, Period[] fwdFraTenors, Period[] fwdIrsTenors) { String[] fwdIdValue = new String[1 + fwdFraQuotes.length + fwdIrsQuotes.length]; fwdIdValue[0] = "FIXING" + tenor + "M"; for (int i = 0; i < fwdFraQuotes.length; i++) { fwdIdValue[i + 1] = "FRA" + fwdFraTenors[i].toString() + "x" + fwdFraTenors[i].plusMonths(tenor).toString(); } for (int i = 0; i < fwdIrsQuotes.length; i++) { fwdIdValue[i + 1 + fwdFraQuotes.length] = "IRS" + tenor + "M-" + fwdIrsTenors[i].toString(); } return fwdIdValue; } public static double[] fwdMarketQuotes( double fwdFixingQuote, double[] fwdFraQuotes, double[] fwdIrsQuotes) { int fwdNbFraNodes = fwdFraQuotes.length; int fwdNbIrsNodes = fwdIrsQuotes.length; int fwdNbNodes = 1 + fwdNbFraNodes + fwdNbIrsNodes; double[] fwdMarketQuotes = new double[fwdNbNodes]; fwdMarketQuotes[0] = fwdFixingQuote; System.arraycopy(fwdFraQuotes, 0, fwdMarketQuotes, 1, fwdNbFraNodes); System.arraycopy(fwdIrsQuotes, 0, fwdMarketQuotes, 1 + fwdNbFraNodes, fwdNbIrsNodes); return fwdMarketQuotes; } public static CurveGroupDefinition config( Period[] dscOisTenors, String[] dscIdValues, Period[] fwd3FraTenors, Period[] fwd3IrsTenors, String[] fwd3IdValues, Period[] fwd6FraTenors, Period[] fwd6IrsTenors, String[] fwd6IdValues) { CurveNode[] dscNodes = new CurveNode[dscOisTenors.length]; for (int i = 0; i < dscOisTenors.length; i++) { dscNodes[i] = FixedOvernightSwapCurveNode.of( FixedOvernightSwapTemplate.of(Period.ZERO, Tenor.of(dscOisTenors[i]), EUR_FIXED_1Y_EONIA_OIS), QuoteId.of(StandardId.of(SCHEME, dscIdValues[i]))); } CurveNode[] fwd3Nodes = new CurveNode[fwd3IdValues.length]; fwd3Nodes[0] = IborFixingDepositCurveNode.of(IborFixingDepositTemplate.of(EUR_EURIBOR_3M), QuoteId.of(StandardId.of(SCHEME, fwd3IdValues[0]))); for (int i = 0; i < fwd3FraTenors.length; i++) { fwd3Nodes[i + 1] = FraCurveNode.of(FraTemplate.of(fwd3FraTenors[i], EUR_EURIBOR_3M), QuoteId.of(StandardId.of(SCHEME, fwd3IdValues[i + 1]))); } for (int i = 0; i < fwd3IrsTenors.length; i++) { fwd3Nodes[i + 1 + fwd3FraTenors.length] = FixedIborSwapCurveNode.of( FixedIborSwapTemplate.of(Period.ZERO, Tenor.of(fwd3IrsTenors[i]), EUR_FIXED_1Y_EURIBOR_3M), QuoteId.of(StandardId.of(SCHEME, fwd3IdValues[i + 1 + fwd3FraTenors.length]))); } CurveNode[] fwd6Nodes = new CurveNode[fwd6IdValues.length]; fwd6Nodes[0] = IborFixingDepositCurveNode.of(IborFixingDepositTemplate.of(EUR_EURIBOR_6M), QuoteId.of(StandardId.of(SCHEME, fwd6IdValues[0]))); for (int i = 0; i < fwd6FraTenors.length; i++) { fwd6Nodes[i + 1] = FraCurveNode.of(FraTemplate.of(fwd6FraTenors[i], EUR_EURIBOR_6M), QuoteId.of(StandardId.of(SCHEME, fwd6IdValues[i + 1]))); } for (int i = 0; i < fwd6IrsTenors.length; i++) { fwd6Nodes[i + 1 + fwd6FraTenors.length] = FixedIborSwapCurveNode.of( FixedIborSwapTemplate.of(Period.ZERO, Tenor.of(fwd6IrsTenors[i]), EUR_FIXED_1Y_EURIBOR_6M), QuoteId.of(StandardId.of(SCHEME, fwd6IdValues[i + 1 + fwd6FraTenors.length]))); } 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(dscNodes).build(); 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(fwd3Nodes).build(); InterpolatedNodalCurveDefinition FWD6_CURVE_DEFN = InterpolatedNodalCurveDefinition.builder() .name(FWD6_CURVE_NAME) .xValueType(ValueType.YEAR_FRACTION) .yValueType(ValueType.ZERO_RATE) .dayCount(CURVE_DC) .interpolator(INTERPOLATOR_LINEAR) .extrapolatorLeft(EXTRAPOLATOR_FLAT) .extrapolatorRight(EXTRAPOLATOR_FLAT) .nodes(fwd6Nodes).build(); return CurveGroupDefinition.builder() .name(CURVE_GROUP_NAME) .addCurve(DSC_CURVE_DEFN, EUR, EUR_EONIA) .addForwardCurve(FWD3_CURVE_DEFN, EUR_EURIBOR_3M) .addForwardCurve(FWD6_CURVE_DEFN, EUR_EURIBOR_6M).build(); } public static MarketData allQuotes( LocalDate valuationDate, double[] dscOisQuotes, String[] dscIdValues, double[] fwd3MarketQuotes, String[] fwd3IdValue, double[] fwd6MarketQuotes, String[] fwd6IdValue) { /* All quotes for the curve calibration */ ImmutableMarketDataBuilder builder = ImmutableMarketData.builder(valuationDate); for (int i = 0; i < dscOisQuotes.length; i++) { builder.addValue(QuoteId.of(StandardId.of(SCHEME, dscIdValues[i])), dscOisQuotes[i]); } for (int i = 0; i < fwd3MarketQuotes.length; i++) { builder.addValue(QuoteId.of(StandardId.of(SCHEME, fwd3IdValue[i])), fwd3MarketQuotes[i]); } for (int i = 0; i < fwd6MarketQuotes.length; i++) { builder.addValue(QuoteId.of(StandardId.of(SCHEME, fwd6IdValue[i])), fwd6MarketQuotes[i]); } return builder.build(); } }