/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.tutorial.analysis.swap;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import org.testng.annotations.Test;
import org.threeten.bp.LocalDate;
import org.threeten.bp.ZonedDateTime;
import com.opengamma.analytics.financial.datasets.CalendarGBP;
import com.opengamma.analytics.financial.instrument.NotionalProvider;
import com.opengamma.analytics.financial.instrument.annuity.AdjustedDateParameters;
import com.opengamma.analytics.financial.instrument.annuity.AnnuityCouponFixedDefinition;
import com.opengamma.analytics.financial.instrument.annuity.AnnuityDefinition;
import com.opengamma.analytics.financial.instrument.annuity.CompoundingMethod;
import com.opengamma.analytics.financial.instrument.annuity.FixedAnnuityDefinitionBuilder;
import com.opengamma.analytics.financial.instrument.annuity.FloatingAnnuityDefinitionBuilder;
import com.opengamma.analytics.financial.instrument.annuity.OffsetAdjustedDateParameters;
import com.opengamma.analytics.financial.instrument.annuity.OffsetType;
import com.opengamma.analytics.financial.instrument.index.GeneratorSwapFixedIbor;
import com.opengamma.analytics.financial.instrument.index.GeneratorSwapFixedIborMaster;
import com.opengamma.analytics.financial.instrument.index.GeneratorSwapFixedON;
import com.opengamma.analytics.financial.instrument.index.GeneratorSwapFixedONMaster;
import com.opengamma.analytics.financial.instrument.index.IborIndex;
import com.opengamma.analytics.financial.instrument.index.IndexON;
import com.opengamma.analytics.financial.instrument.payment.CouponDefinition;
import com.opengamma.analytics.financial.instrument.payment.CouponFixedDefinition;
import com.opengamma.analytics.financial.instrument.payment.PaymentDefinition;
import com.opengamma.analytics.financial.instrument.swap.SwapCouponFixedCouponDefinition;
import com.opengamma.analytics.financial.interestrate.annuity.derivative.Annuity;
import com.opengamma.analytics.financial.interestrate.payments.derivative.Payment;
import com.opengamma.analytics.financial.interestrate.swap.derivative.Swap;
import com.opengamma.analytics.financial.provider.calculator.discounting.ParRateDiscountingCalculator;
import com.opengamma.analytics.financial.provider.calculator.discounting.PresentValueCurveSensitivityDiscountingCalculator;
import com.opengamma.analytics.financial.provider.calculator.discounting.PresentValueDiscountingCalculator;
import com.opengamma.analytics.financial.provider.calculator.generic.MarketQuoteSensitivityBlockCalculator;
import com.opengamma.analytics.financial.provider.curve.CurveBuildingBlockBundle;
import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderDiscount;
import com.opengamma.analytics.financial.provider.description.interestrate.ParameterProviderInterface;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyMulticurveSensitivity;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyParameterSensitivity;
import com.opengamma.analytics.financial.provider.sensitivity.parameter.ParameterSensitivityParameterAbstractCalculator;
import com.opengamma.analytics.financial.provider.sensitivity.parameter.ParameterSensitivityParameterCalculator;
import com.opengamma.analytics.financial.provider.sensitivity.parameter.ParameterSensitivityUnderlyingParameterCalculator;
import com.opengamma.analytics.financial.util.AssertSensitivityObjects;
import com.opengamma.analytics.tutorial.datasets.RecentDataSetsMulticurveOisMeetingDatesGbp;
import com.opengamma.analytics.tutorial.datasets.RecentDataSetsMulticurveStandardGbp;
import com.opengamma.analytics.util.export.ExportUtils;
import com.opengamma.financial.convention.businessday.BusinessDayConventionFactory;
import com.opengamma.financial.convention.calendar.Calendar;
import com.opengamma.financial.convention.rolldate.RollConvention;
import com.opengamma.timeseries.precise.zdt.ZonedDateTimeDoubleTimeSeries;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.MultipleCurrencyAmount;
import com.opengamma.util.time.DateUtils;
import com.opengamma.util.tuple.Pair;
/**
* Examples of risk analysis for different swaps in GBP.
* Those examples can be used for tutorials.
*/
public class SwapRiskGbpAnalysis {
private static final ZonedDateTime VALUATION_DATE = DateUtils.getUTCDate(2014, 7, 16);
private static final Calendar LON = new CalendarGBP("LON");
private static final GeneratorSwapFixedONMaster GENERATOR_OIS_MASTER = GeneratorSwapFixedONMaster.getInstance();
private static final GeneratorSwapFixedIborMaster GENERATOR_IRS_MASTER = GeneratorSwapFixedIborMaster.getInstance();
private static final GeneratorSwapFixedON GENERATOR_OIS_GBP = GENERATOR_OIS_MASTER.getGenerator("GBP1YSONIA", LON);
private static final IndexON GBPSONIA = GENERATOR_OIS_GBP.getIndex();
private static final Currency GBP = Currency.GBP;
private static final GeneratorSwapFixedIbor GBP6MLIBOR6M = GENERATOR_IRS_MASTER.getGenerator("GBP6MLIBOR6M", LON);
private static final IborIndex GBPLIBOR6M = GBP6MLIBOR6M.getIborIndex();
private static final AdjustedDateParameters ADJUSTED_DATE_LIBOR = new AdjustedDateParameters(LON, GBP6MLIBOR6M.getBusinessDayConvention());
private static final OffsetAdjustedDateParameters OFFSET_ADJ_LIBOR =
new OffsetAdjustedDateParameters(-2, OffsetType.BUSINESS, LON, GBP6MLIBOR6M.getBusinessDayConvention());
private static final AdjustedDateParameters ADJUSTED_DATE_SONIA = new AdjustedDateParameters(LON, GENERATOR_OIS_GBP.getBusinessDayConvention());
private static final OffsetAdjustedDateParameters OFFSET_PAY_SONIA =
new OffsetAdjustedDateParameters(GENERATOR_OIS_GBP.getPaymentLag(), OffsetType.BUSINESS, LON, BusinessDayConventionFactory.of("Following"));
private static final OffsetAdjustedDateParameters OFFSET_FIX_SONIA =
new OffsetAdjustedDateParameters(0, OffsetType.BUSINESS, LON, BusinessDayConventionFactory.of("Following"));
/** GBP Fixed v SONIA */
private static final LocalDate EFFECTIVE_DATE_1 = LocalDate.of(2014, 11, 6);
private static final LocalDate MATURITY_DATE_1 = LocalDate.of(2014, 12, 4);
private static final double FIXED_RATE_1 = 0.0051875;
private static final boolean PAYER_1 = false;
/** GBP Fixed v LIBOR6M */
private static final LocalDate EFFECTIVE_DATE_2 = LocalDate.of(2014, 11, 6);
private static final LocalDate MATURITY_DATE_2 = LocalDate.of(2024, 11, 6);
private static final double FIXED_RATE_2 = 0.0200;
private static final boolean PAYER_2 = false;
private static final double NOTIONAL_1 = 1000000; // 1m
private static final NotionalProvider NOTIONAL_PROV_1 = new NotionalProvider() {
@Override
public double getAmount(final LocalDate date) {
return NOTIONAL_1;
}
};
/** OIS GBP 1 **/
/** Fixed leg */
private static final PaymentDefinition[] PAYMENT_LEG_1_DEFINITION = new FixedAnnuityDefinitionBuilder().
payer(PAYER_1).
currency(GBPSONIA.getCurrency()).
notional(NOTIONAL_PROV_1).
startDate(EFFECTIVE_DATE_1).
endDate(MATURITY_DATE_1).
dayCount(GENERATOR_OIS_GBP.getFixedLegDayCount()).
accrualPeriodFrequency(GENERATOR_OIS_GBP.getLegsPeriod()).
rate(FIXED_RATE_1).
accrualPeriodParameters(ADJUSTED_DATE_SONIA).
paymentDateAdjustmentParameters(OFFSET_PAY_SONIA).
build().getPayments();
private static final CouponFixedDefinition[] CPN_FIXED_1_DEFINITION = new CouponFixedDefinition[PAYMENT_LEG_1_DEFINITION.length];
static {
for (int loopcpn = 0; loopcpn < PAYMENT_LEG_1_DEFINITION.length; loopcpn++) {
CPN_FIXED_1_DEFINITION[loopcpn] = (CouponFixedDefinition) PAYMENT_LEG_1_DEFINITION[loopcpn];
}
}
private static final AnnuityCouponFixedDefinition FIXED_LEG_1_DEFINITION = new AnnuityCouponFixedDefinition(CPN_FIXED_1_DEFINITION, LON);
/** ON leg */
@SuppressWarnings("unchecked")
private static final AnnuityDefinition<? extends CouponDefinition> ON_LEG_1_DEFINITION = (AnnuityDefinition<? extends CouponDefinition>) new FloatingAnnuityDefinitionBuilder().
payer(!PAYER_1).
notional(NOTIONAL_PROV_1).
startDate(EFFECTIVE_DATE_1).
endDate(MATURITY_DATE_1).
index(GBPSONIA).
accrualPeriodFrequency(GENERATOR_OIS_GBP.getLegsPeriod()).
rollDateAdjuster(RollConvention.NONE.getRollDateAdjuster(0)).
resetDateAdjustmentParameters(ADJUSTED_DATE_SONIA).
accrualPeriodParameters(ADJUSTED_DATE_SONIA).
dayCount(GBPSONIA.getDayCount()).
fixingDateAdjustmentParameters(OFFSET_FIX_SONIA).
currency(GBP).
compoundingMethod(CompoundingMethod.FLAT).
build();
private static final SwapCouponFixedCouponDefinition OIS_1_DEFINITION = new SwapCouponFixedCouponDefinition(FIXED_LEG_1_DEFINITION, ON_LEG_1_DEFINITION);
/** GBP IRS 1 **/
private static final PaymentDefinition[] PAYMENT_LEG_2_DEFINITION = new FixedAnnuityDefinitionBuilder().
payer(PAYER_2).currency(GBP6MLIBOR6M.getCurrency()).notional(NOTIONAL_PROV_1).startDate(EFFECTIVE_DATE_2).
endDate(MATURITY_DATE_2).dayCount(GBP6MLIBOR6M.getFixedLegDayCount()).accrualPeriodFrequency(GBP6MLIBOR6M.getFixedLegPeriod()).
rate(FIXED_RATE_2).accrualPeriodParameters(ADJUSTED_DATE_LIBOR).build().getPayments();
private static final CouponFixedDefinition[] CPN_FIXED_2_DEFINITION = new CouponFixedDefinition[PAYMENT_LEG_2_DEFINITION.length];
static {
for (int loopcpn = 0; loopcpn < PAYMENT_LEG_2_DEFINITION.length; loopcpn++) {
CPN_FIXED_2_DEFINITION[loopcpn] = (CouponFixedDefinition) PAYMENT_LEG_2_DEFINITION[loopcpn];
}
}
private static final AnnuityCouponFixedDefinition FIXED_LEG_2_DEFINITION = new AnnuityCouponFixedDefinition(CPN_FIXED_2_DEFINITION, LON);
private static final AnnuityDefinition<? extends CouponDefinition> IBOR_LEG_2_DEFINITION = (AnnuityDefinition<? extends CouponDefinition>)
new FloatingAnnuityDefinitionBuilder().
payer(!PAYER_2).notional(NOTIONAL_PROV_1).startDate(EFFECTIVE_DATE_2).endDate(MATURITY_DATE_2).
index(GBPLIBOR6M).accrualPeriodFrequency(GBPLIBOR6M.getTenor()).rollDateAdjuster(RollConvention.NONE.getRollDateAdjuster(0)).
resetDateAdjustmentParameters(ADJUSTED_DATE_LIBOR).accrualPeriodParameters(ADJUSTED_DATE_LIBOR).dayCount(GBPLIBOR6M.getDayCount()).
fixingDateAdjustmentParameters(OFFSET_ADJ_LIBOR).currency(GBPLIBOR6M.getCurrency()).build();
private static final SwapCouponFixedCouponDefinition IRS_1_DEFINITION = new SwapCouponFixedCouponDefinition(FIXED_LEG_2_DEFINITION, IBOR_LEG_2_DEFINITION);
/** Curves and fixing */
private static final ZonedDateTimeDoubleTimeSeries TS_FIXED_SONIA_WITHOUT_TODAY = RecentDataSetsMulticurveStandardGbp.fixingGbpSoniaWithoutLast();
private static final ZonedDateTimeDoubleTimeSeries TS_FIXED_LIBOR6M_WITHOUT_TODAY = RecentDataSetsMulticurveStandardGbp.fixingGbpLibor6MWithoutLast();
/** Curve with standard OIS and IRS nodes. */
private static final Pair<MulticurveProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_STD_PAIR =
RecentDataSetsMulticurveStandardGbp.getCurvesGbpOisL6(VALUATION_DATE);
private static final MulticurveProviderDiscount MULTICURVE_STD = MULTICURVE_STD_PAIR.getFirst();
private static final CurveBuildingBlockBundle BLOCK_STD = MULTICURVE_STD_PAIR.getSecond();
/** Curve with standard nodes and the discounting curve a spread to the LIBOR6M curve */
private static final Pair<MulticurveProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_STD_SPREAD_PAIR =
RecentDataSetsMulticurveStandardGbp.getCurvesGbpOisL6Spread(VALUATION_DATE);
private static final MulticurveProviderDiscount MULTICURVE_STD_SPREAD = MULTICURVE_STD_SPREAD_PAIR.getFirst();
private static final CurveBuildingBlockBundle BLOCK_STD_SPREAD = MULTICURVE_STD_SPREAD_PAIR.getSecond();
private static final Pair<MulticurveProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_BOE_PAIR =
RecentDataSetsMulticurveOisMeetingDatesGbp.getCurvesGbpOis(VALUATION_DATE);
private static final MulticurveProviderDiscount MULTICURVE_BOE = MULTICURVE_BOE_PAIR.getFirst();
private static final CurveBuildingBlockBundle BLOCK_BOE = MULTICURVE_BOE_PAIR.getSecond();
private static final Pair<MulticurveProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_STD_BOE_PAIR =
RecentDataSetsMulticurveOisMeetingDatesGbp.getCurvesGbpOisWithStdInstruments(VALUATION_DATE);
private static final MulticurveProviderDiscount MULTICURVE_STD_BOE = MULTICURVE_BOE_PAIR.getFirst();
private static final CurveBuildingBlockBundle BLOCK_STD_BOE = MULTICURVE_BOE_PAIR.getSecond();
private static final Annuity<?> FIXED_LEG_1 = FIXED_LEG_1_DEFINITION.toDerivative(VALUATION_DATE);
private static final Annuity<?> ON_LEG_1 = ON_LEG_1_DEFINITION.toDerivative(VALUATION_DATE, TS_FIXED_SONIA_WITHOUT_TODAY);
private static final Swap<? extends Payment, ? extends Payment> OIS_1 = OIS_1_DEFINITION.toDerivative(VALUATION_DATE,
new ZonedDateTimeDoubleTimeSeries[] {TS_FIXED_SONIA_WITHOUT_TODAY, TS_FIXED_SONIA_WITHOUT_TODAY });
private static final Swap<? extends Payment, ? extends Payment> IRS_1 = IRS_1_DEFINITION.toDerivative(VALUATION_DATE,
new ZonedDateTimeDoubleTimeSeries[] {TS_FIXED_LIBOR6M_WITHOUT_TODAY, TS_FIXED_LIBOR6M_WITHOUT_TODAY });
/** Calculators **/
private static final PresentValueDiscountingCalculator PVDC = PresentValueDiscountingCalculator.getInstance();
private static final ParRateDiscountingCalculator PRDC = ParRateDiscountingCalculator.getInstance();
private static final PresentValueCurveSensitivityDiscountingCalculator PVCSDC = PresentValueCurveSensitivityDiscountingCalculator.getInstance();
private static final ParameterSensitivityParameterAbstractCalculator<ParameterProviderInterface> PSC = new ParameterSensitivityParameterCalculator<>(PVCSDC);
private static final ParameterSensitivityParameterAbstractCalculator<ParameterProviderInterface> PSUC = new ParameterSensitivityUnderlyingParameterCalculator<>(PVCSDC);
private static final MarketQuoteSensitivityBlockCalculator<ParameterProviderInterface> MQSBC = new MarketQuoteSensitivityBlockCalculator<>(PSC);
private static final MarketQuoteSensitivityBlockCalculator<ParameterProviderInterface> MQSUBC = new MarketQuoteSensitivityBlockCalculator<>(PSUC);
private static final double TOLERANCE_PV = 1.0E-2;
private static final double TOLERANCE_PV_DELTA = 1.0E-1;
private static final double BP1 = 1.0E-4;
@Test
public void presentValueStdCurve() {
MultipleCurrencyAmount pvFixed = FIXED_LEG_1.accept(PVDC, MULTICURVE_STD);
MultipleCurrencyAmount pvIbor = ON_LEG_1.accept(PVDC, MULTICURVE_STD);
MultipleCurrencyAmount pvOis1Std = OIS_1.accept(PVDC, MULTICURVE_STD);
assertTrue("SwapRiskUsdAnalysis: present value", pvFixed.getAmount(GBP) * pvIbor.getAmount(GBP) < 0);
assertEquals("SwapRiskUsdAnalysis: present value", pvOis1Std.getAmount(GBP), pvFixed.getAmount(GBP) + pvIbor.getAmount(GBP), TOLERANCE_PV);
MultipleCurrencyAmount pvOis1Spread = OIS_1.accept(PVDC, MULTICURVE_STD_SPREAD);
assertEquals("SwapRiskUsdAnalysis: present value", pvOis1Std.getAmount(GBP), pvOis1Spread.getAmount(GBP), TOLERANCE_PV);
MultipleCurrencyAmount pvIrs1Std = IRS_1.accept(PVDC, MULTICURVE_STD);
MultipleCurrencyAmount pvIrs1Spread = IRS_1.accept(PVDC, MULTICURVE_STD_SPREAD);
assertEquals("SwapRiskUsdAnalysis: present value", pvIrs1Std.getAmount(GBP), pvIrs1Spread.getAmount(GBP), 2000); // Discounting is different due to different extrapolation mechanisms
}
@SuppressWarnings("unused")
@Test
public void parRateStdCurve() {
double pr1 = OIS_1.accept(PRDC, MULTICURVE_STD);
}
@SuppressWarnings("unused")
@Test
public void bucketedPv01StdCurve() {
MultipleCurrencyMulticurveSensitivity pvPointSensi1Std = OIS_1.accept(PVCSDC, MULTICURVE_STD);
MultipleCurrencyParameterSensitivity pvParameterSensi1Std = PSC.pointToParameterSensitivity(pvPointSensi1Std, MULTICURVE_STD);
MultipleCurrencyParameterSensitivity pvmqsOis1Std = MQSBC.fromInstrument(OIS_1, MULTICURVE_STD, BLOCK_STD).multipliedBy(BP1);
MultipleCurrencyMulticurveSensitivity pvPointSensi1Spread = OIS_1.accept(PVCSDC, MULTICURVE_STD_SPREAD);
MultipleCurrencyParameterSensitivity pvParameterSensi1Spread = PSUC.pointToParameterSensitivity(pvPointSensi1Spread, MULTICURVE_STD_SPREAD);
MultipleCurrencyParameterSensitivity pvmqsOis1Spread = MQSUBC.fromInstrument(OIS_1, MULTICURVE_STD_SPREAD, BLOCK_STD_SPREAD).multipliedBy(BP1);
AssertSensitivityObjects.assertEquals("Sensitivity with standard and spread curves", pvmqsOis1Std, pvmqsOis1Spread, TOLERANCE_PV_DELTA);
MultipleCurrencyParameterSensitivity pvmqsIrs1Std = MQSBC.fromInstrument(IRS_1, MULTICURVE_STD, BLOCK_STD).multipliedBy(BP1);
MultipleCurrencyParameterSensitivity pvmqsIrs1StdUn = MQSUBC.fromInstrument(IRS_1, MULTICURVE_STD, BLOCK_STD).multipliedBy(BP1);
AssertSensitivityObjects.assertEquals("Sensitivity with and without underlying curve sensitivity", pvmqsIrs1Std, pvmqsIrs1StdUn, TOLERANCE_PV_DELTA);
MultipleCurrencyParameterSensitivity pvmqsIrs1Spread = MQSUBC.fromInstrument(IRS_1, MULTICURVE_STD_SPREAD, BLOCK_STD_SPREAD).multipliedBy(BP1);
}
@Test
public void presentValueBoeCurve() {
MultipleCurrencyAmount pvFixed = FIXED_LEG_1.accept(PVDC, MULTICURVE_BOE);
MultipleCurrencyAmount pvIbor = ON_LEG_1.accept(PVDC, MULTICURVE_BOE);
MultipleCurrencyAmount pvSwap1Std = OIS_1.accept(PVDC, MULTICURVE_BOE);
assertTrue("SwapRiskUsdAnalysis: present value", pvFixed.getAmount(GBP) * pvIbor.getAmount(GBP) < 0);
assertEquals("SwapRiskUsdAnalysis: present value", pvSwap1Std.getAmount(GBP),
pvFixed.getAmount(GBP) + pvIbor.getAmount(GBP), TOLERANCE_PV);
System.out.println("--- BOE PVs ---");
System.out.println("PV fixed-rate leg," + String.valueOf(pvFixed.getAmount(GBP)));
System.out.println("PV floating-rate leg," + String.valueOf(pvIbor.getAmount(GBP)));
System.out.println("PV swap," + String.valueOf(pvSwap1Std.getAmount(GBP)));
}
@Test
public void parRateBoeCurve() {
double pr1 = OIS_1.accept(PRDC, MULTICURVE_BOE);
System.out.println("--- BOE Break-even rate ---");
System.out.println("Par rate," + String.valueOf(pr1));
}
@Test
public void bucketedPv0BoeCurve() {
MultipleCurrencyParameterSensitivity pvmqs1Boe =
MQSBC.fromInstrument(OIS_1, MULTICURVE_BOE, BLOCK_BOE).multipliedBy(BP1);
ExportUtils.consolePrint(pvmqs1Boe, MULTICURVE_BOE);
}
}