/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.tutorial.analysis.swaption;
import org.testng.annotations.Test;
import org.threeten.bp.LocalDate;
import org.threeten.bp.ZonedDateTime;
import com.opengamma.analytics.financial.datasets.CalendarUSD;
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.AnnuityCouponIborDefinition;
import com.opengamma.analytics.financial.instrument.annuity.AnnuityDefinition;
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.IborIndex;
import com.opengamma.analytics.financial.instrument.payment.CouponDefinition;
import com.opengamma.analytics.financial.instrument.payment.CouponFixedDefinition;
import com.opengamma.analytics.financial.instrument.payment.CouponIborDefinition;
import com.opengamma.analytics.financial.instrument.swap.SwapFixedIborDefinition;
import com.opengamma.analytics.financial.instrument.swaption.SwaptionPhysicalFixedIborDefinition;
import com.opengamma.analytics.financial.interestrate.PresentValueSABRSensitivityDataBundle;
import com.opengamma.analytics.financial.interestrate.SwaptionSurfaceSensitivityNodeCalculator;
import com.opengamma.analytics.financial.interestrate.datasets.StandardDataSetsSABRSwaptionUSD;
import com.opengamma.analytics.financial.interestrate.payments.derivative.Payment;
import com.opengamma.analytics.financial.interestrate.sensitivity.PresentValueSwaptionSurfaceSensitivity;
import com.opengamma.analytics.financial.interestrate.swap.derivative.Swap;
import com.opengamma.analytics.financial.interestrate.swaption.derivative.SwaptionPhysicalFixedIbor;
import com.opengamma.analytics.financial.interestrate.swaption.provider.SwaptionPhysicalFixedIborNormalMethod;
import com.opengamma.analytics.financial.interestrate.swaption.provider.SwaptionPhysicalFixedIborSABRMethod;
import com.opengamma.analytics.financial.model.option.definition.SABRInterestRateParameters;
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.calculator.normalswaption.PresentValueCurveSensitivityNormalSwaptionCalculator;
import com.opengamma.analytics.financial.provider.calculator.normalswaption.PresentValueNormalSwaptionCalculator;
import com.opengamma.analytics.financial.provider.calculator.sabrswaption.PresentValueCurveSensitivitySABRSwaptionCalculator;
import com.opengamma.analytics.financial.provider.calculator.sabrswaption.PresentValueSABRSensitivitySABRSwaptionCalculator;
import com.opengamma.analytics.financial.provider.calculator.sabrswaption.PresentValueSABRSwaptionCalculator;
import com.opengamma.analytics.financial.provider.curve.CurveBuildingBlockBundle;
import com.opengamma.analytics.financial.provider.description.NormalDataSets;
import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderDiscount;
import com.opengamma.analytics.financial.provider.description.interestrate.NormalSwaptionExpiryTenorProvider;
import com.opengamma.analytics.financial.provider.description.interestrate.NormalSwaptionProviderInterface;
import com.opengamma.analytics.financial.provider.description.interestrate.ParameterProviderInterface;
import com.opengamma.analytics.financial.provider.description.interestrate.SABRSwaptionProviderDiscount;
import com.opengamma.analytics.financial.provider.description.interestrate.SABRSwaptionProviderInterface;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyParameterSensitivity;
import com.opengamma.analytics.financial.provider.sensitivity.parameter.ParameterSensitivityParameterCalculator;
import com.opengamma.analytics.math.surface.InterpolatedDoublesSurface;
import com.opengamma.analytics.tutorial.datasets.RecentDataSetsMulticurveStandardUsd;
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.MultipleCurrencyAmount;
import com.opengamma.util.time.DateUtils;
import com.opengamma.util.tuple.Pair;
/**
* Examples of risk analysis for different swaptions in USD.
* Those examples can be used for tutorials.
*/
public class SwaptionUsdAnalysis {
private static final ZonedDateTime VALUATION_DATE = DateUtils.getUTCDate(2014, 7, 16);
/** Calculators **/
private static final SwaptionPhysicalFixedIborSABRMethod METHOD_SWPT_SABR =
SwaptionPhysicalFixedIborSABRMethod.getInstance();
private static final SwaptionPhysicalFixedIborNormalMethod METHOD_SWPT_NORMAL =
SwaptionPhysicalFixedIborNormalMethod.getInstance();
private static final PresentValueDiscountingCalculator PVDC = PresentValueDiscountingCalculator.getInstance();
private static final PresentValueCurveSensitivityDiscountingCalculator PVCSDC =
PresentValueCurveSensitivityDiscountingCalculator.getInstance();
private static final ParRateDiscountingCalculator PRDC = ParRateDiscountingCalculator.getInstance();
private static final PresentValueSABRSwaptionCalculator PVSSC = PresentValueSABRSwaptionCalculator.getInstance();
private static final PresentValueCurveSensitivitySABRSwaptionCalculator PVCSSSC =
PresentValueCurveSensitivitySABRSwaptionCalculator.getInstance();
private static final PresentValueNormalSwaptionCalculator PVNSC = PresentValueNormalSwaptionCalculator.getInstance();
private static final PresentValueCurveSensitivityNormalSwaptionCalculator PVCSNSC =
PresentValueCurveSensitivityNormalSwaptionCalculator.getInstance();
private static final ParameterSensitivityParameterCalculator<ParameterProviderInterface> PSDC =
new ParameterSensitivityParameterCalculator<>(PVCSDC);
private static final ParameterSensitivityParameterCalculator<NormalSwaptionProviderInterface> PSNSC =
new ParameterSensitivityParameterCalculator<>(PVCSNSC);
private static final ParameterSensitivityParameterCalculator<SABRSwaptionProviderInterface> PSSSC =
new ParameterSensitivityParameterCalculator<>(PVCSSSC);
private static final MarketQuoteSensitivityBlockCalculator<ParameterProviderInterface> MQSBDC =
new MarketQuoteSensitivityBlockCalculator<>(PSDC);
private static final MarketQuoteSensitivityBlockCalculator<NormalSwaptionProviderInterface> MQSBNSC =
new MarketQuoteSensitivityBlockCalculator<>(PSNSC);
private static final MarketQuoteSensitivityBlockCalculator<SABRSwaptionProviderInterface> MQSBSSC =
new MarketQuoteSensitivityBlockCalculator<>(PSSSC);
private static final PresentValueSABRSensitivitySABRSwaptionCalculator PVSSSSC =
PresentValueSABRSensitivitySABRSwaptionCalculator.getInstance();
private static final SwaptionSurfaceSensitivityNodeCalculator SSSNC =
new SwaptionSurfaceSensitivityNodeCalculator();
private static final Calendar NYC = new CalendarUSD("NYC");
private static final GeneratorSwapFixedIborMaster GENERATOR_IRS_MASTER = GeneratorSwapFixedIborMaster.getInstance();
private static final GeneratorSwapFixedIbor USD6MLIBOR3M = GENERATOR_IRS_MASTER.getGenerator("USD6MLIBOR3M", NYC);
private static final IborIndex USDLIBOR3M = USD6MLIBOR3M.getIborIndex();
private static final AdjustedDateParameters ADJUSTED_DATE_LIBOR = new AdjustedDateParameters(NYC, USD6MLIBOR3M.getBusinessDayConvention());
private static final OffsetAdjustedDateParameters OFFSET_ADJ_LIBOR =
new OffsetAdjustedDateParameters(-2, OffsetType.BUSINESS, NYC, USD6MLIBOR3M.getBusinessDayConvention());
private static final double NOTIONAL = 1_000_000;
/** Curves and fixing */
private static final SABRInterestRateParameters SABR_PARAMETER = StandardDataSetsSABRSwaptionUSD.createSABR1();
private static final InterpolatedDoublesSurface NORMAL_SURFACE_SWAPTION_EXP_TENOR =
NormalDataSets.normalSurfaceSwaptionExpiryTenor();
private static final Pair<MulticurveProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_STD_PAIR =
RecentDataSetsMulticurveStandardUsd.getCurvesUSDOisL1L3L6_20140728(VALUATION_DATE);
private static final MulticurveProviderDiscount MULTICURVE_STD = MULTICURVE_STD_PAIR.getFirst();
private static final CurveBuildingBlockBundle BLOCK_STD = MULTICURVE_STD_PAIR.getSecond();
private static final SABRSwaptionProviderDiscount MULTICURVE_STD_SABR =
new SABRSwaptionProviderDiscount(MULTICURVE_STD, SABR_PARAMETER, USD6MLIBOR3M);
private static final NormalSwaptionExpiryTenorProvider MULTICURVE_STD_NORMAL =
new NormalSwaptionExpiryTenorProvider(MULTICURVE_STD, NORMAL_SURFACE_SWAPTION_EXP_TENOR, USD6MLIBOR3M);
private static final Pair<MulticurveProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_NEG_PAIR =
RecentDataSetsMulticurveStandardUsd.getCurvesUSDOisL1L3L6_Negative(VALUATION_DATE);
private static final MulticurveProviderDiscount MULTICURVE_NEG = MULTICURVE_NEG_PAIR.getFirst();
private static final NormalSwaptionExpiryTenorProvider MULTICURVE_NEG_NORMAL =
new NormalSwaptionExpiryTenorProvider(MULTICURVE_NEG, NORMAL_SURFACE_SWAPTION_EXP_TENOR, USD6MLIBOR3M);
private static final ZonedDateTimeDoubleTimeSeries TS_FIXED_IBOR_USD3M_WITHOUT_TODAY =
RecentDataSetsMulticurveStandardUsd.fixingUsdLibor3MWithoutLast();
private static final double BP1 = 1.0E-4;
/** SWAPTION 1 : USD Fixed v USDLIBOR3M */
private static final ZonedDateTime EXPIRATION_DATE_1 = DateUtils.getUTCDate(2016, 7, 14);
private static final LocalDate EFFECTIVE_DATE_1 = LocalDate.of(2016, 7, 18);
private static final LocalDate MATURITY_DATE_1 = LocalDate.of(2026, 7, 18);
private static final double FIXED_RATE_1 = 0.0300;
private static final boolean PAYER_1 = false;
private static final boolean LONG_1 = true;
private static final SwapFixedIborDefinition IRS_R_1_DEFINITION =
swap(EFFECTIVE_DATE_1, MATURITY_DATE_1, FIXED_RATE_1, NOTIONAL, PAYER_1);
private static final SwaptionPhysicalFixedIborDefinition SWPT_R_L_1_DEFINITION =
SwaptionPhysicalFixedIborDefinition.from(EXPIRATION_DATE_1, IRS_R_1_DEFINITION, PAYER_1, LONG_1); // Long Receiver
/** SWAPTION 2 : USD Fixed v USDLIBOR3M */
private static final ZonedDateTime EXPIRATION_DATE_2 = DateUtils.getUTCDate(2016, 1, 18);
private static final LocalDate EFFECTIVE_DATE_2 = LocalDate.of(2016, 1, 20);
private static final LocalDate MATURITY_DATE_2 = LocalDate.of(2019, 1, 20);
private static final double FIXED_RATE_2 = -0.0005;
private static final boolean PAYER_2 = false;
private static final boolean LONG_2 = true;
private static final SwapFixedIborDefinition IRS_R_2_DEFINITION =
swap(EFFECTIVE_DATE_2, MATURITY_DATE_2, FIXED_RATE_2, NOTIONAL, PAYER_2);
private static final SwaptionPhysicalFixedIborDefinition SWPT_R_L_2_DEFINITION =
SwaptionPhysicalFixedIborDefinition.from(EXPIRATION_DATE_2, IRS_R_2_DEFINITION, PAYER_2, LONG_2); // Long Receiver
private static final Swap<? extends Payment, ? extends Payment> IRS_R_1 = IRS_R_1_DEFINITION.toDerivative(VALUATION_DATE,
new ZonedDateTimeDoubleTimeSeries[] {TS_FIXED_IBOR_USD3M_WITHOUT_TODAY, TS_FIXED_IBOR_USD3M_WITHOUT_TODAY });
private static final SwaptionPhysicalFixedIbor SWPT_R_L_1 = SWPT_R_L_1_DEFINITION.toDerivative(VALUATION_DATE);
private static final Swap<? extends Payment, ? extends Payment> IRS_R_2 = IRS_R_2_DEFINITION.toDerivative(VALUATION_DATE,
new ZonedDateTimeDoubleTimeSeries[] {TS_FIXED_IBOR_USD3M_WITHOUT_TODAY, TS_FIXED_IBOR_USD3M_WITHOUT_TODAY });
private static final SwaptionPhysicalFixedIbor SWPT_R_L_2 = SWPT_R_L_2_DEFINITION.toDerivative(VALUATION_DATE);
@SuppressWarnings("unused")
@Test
public void swaptionStandard() {
// Forward rate
double prIrs1Std = IRS_R_1.accept(PRDC, MULTICURVE_STD);
// Present value
MultipleCurrencyAmount pvIrs1Std = IRS_R_1.accept(PVDC, MULTICURVE_STD);
MultipleCurrencyAmount pvSwpt1StdSabr = SWPT_R_L_1.accept(PVSSC, MULTICURVE_STD_SABR);
MultipleCurrencyAmount pvSwpt1StdNorm = SWPT_R_L_1.accept(PVNSC, MULTICURVE_STD_NORMAL);
// Bucketed PV01
MultipleCurrencyParameterSensitivity pvcsIrs1Std =
MQSBDC.fromInstrument(IRS_R_1, MULTICURVE_STD, BLOCK_STD).multipliedBy(BP1);
MultipleCurrencyParameterSensitivity pvcsSwpt1StdSabr =
MQSBSSC.fromInstrument(SWPT_R_L_1, MULTICURVE_STD_SABR, BLOCK_STD).multipliedBy(BP1);
MultipleCurrencyParameterSensitivity pvcsSwpt1StdNorm =
MQSBNSC.fromInstrument(SWPT_R_L_1, MULTICURVE_STD_NORMAL, BLOCK_STD).multipliedBy(BP1);
// Implied volatility: Black vol or normal vol
double ivSwpt1StdSabr = METHOD_SWPT_SABR.impliedVolatility(SWPT_R_L_1, MULTICURVE_STD_SABR);
double ivSwpt1StdNorm = METHOD_SWPT_NORMAL.impliedVolatility(SWPT_R_L_1, MULTICURVE_STD_NORMAL);
// Vega: sensitivity to SABR parameters or normal volatility
PresentValueSABRSensitivityDataBundle pvvsSwpt1StdSabr = SWPT_R_L_1.accept(PVSSSSC, MULTICURVE_STD_SABR);
PresentValueSwaptionSurfaceSensitivity pvvsSwpt1StdNorm =
METHOD_SWPT_NORMAL.presentValueVolatilitySensitivity(SWPT_R_L_2, MULTICURVE_STD_NORMAL);
}
@SuppressWarnings("unused")
@Test
public void swaptionNegativeStrike() {
// Forward rate
double prIrs2Neg = IRS_R_2.accept(PRDC, MULTICURVE_NEG);
// Present value
MultipleCurrencyAmount pvIrs2Neg = IRS_R_2.accept(PVDC, MULTICURVE_NEG);
MultipleCurrencyAmount pvSwpt2NegNorm = SWPT_R_L_2.accept(PVNSC, MULTICURVE_NEG_NORMAL);
// Bucketed PV01
MultipleCurrencyParameterSensitivity pvcsIrs2Neg =
MQSBDC.fromInstrument(IRS_R_2, MULTICURVE_NEG, BLOCK_STD).multipliedBy(BP1);
MultipleCurrencyParameterSensitivity pvcsSwpt2NegNorm =
MQSBNSC.fromInstrument(SWPT_R_L_2, MULTICURVE_NEG_NORMAL, BLOCK_STD).multipliedBy(BP1);
// Vega (sensitivity to normal vol)
PresentValueSwaptionSurfaceSensitivity pvvs2NegNorm =
METHOD_SWPT_NORMAL.presentValueVolatilitySensitivity(SWPT_R_L_2, MULTICURVE_NEG_NORMAL);
PresentValueSwaptionSurfaceSensitivity pvnns = SSSNC.calculateNodeSensitivities(pvvs2NegNorm, MULTICURVE_NEG_NORMAL);
}
private static SwapFixedIborDefinition swap(final LocalDate effectiveDate, final LocalDate maturityDate, final double rate,
final double notional, final boolean payer) {
NotionalProvider notionalProvider = new NotionalProvider() {
@Override
public double getAmount(final LocalDate date) {
return notional;
}
};
AnnuityDefinition<?> fixedGeneric = new FixedAnnuityDefinitionBuilder().
payer(payer).currency(USD6MLIBOR3M.getCurrency()).notional(notionalProvider).startDate(effectiveDate).
endDate(maturityDate).dayCount(USD6MLIBOR3M.getFixedLegDayCount()).
accrualPeriodFrequency(USD6MLIBOR3M.getFixedLegPeriod()).rate(rate).
accrualPeriodParameters(ADJUSTED_DATE_LIBOR).build();
AnnuityCouponFixedDefinition fixegLeg =
new AnnuityCouponFixedDefinition((CouponFixedDefinition[])fixedGeneric.getPayments(), NYC);
/** Ibor leg */
AnnuityDefinition<? extends CouponDefinition> iborGeneric =
(AnnuityDefinition<? extends CouponDefinition>)
new FloatingAnnuityDefinitionBuilder().payer(!payer).notional(notionalProvider).startDate(effectiveDate).
endDate(maturityDate).index(USDLIBOR3M).accrualPeriodFrequency(USDLIBOR3M.getTenor()).
rollDateAdjuster(RollConvention.NONE.getRollDateAdjuster(0)).
resetDateAdjustmentParameters(ADJUSTED_DATE_LIBOR).accrualPeriodParameters(ADJUSTED_DATE_LIBOR).
dayCount(USDLIBOR3M.getDayCount()).fixingDateAdjustmentParameters(OFFSET_ADJ_LIBOR).
currency(USDLIBOR3M.getCurrency()).build();
AnnuityCouponIborDefinition iborLeg =
new AnnuityCouponIborDefinition((CouponIborDefinition[]) iborGeneric.getPayments(), USDLIBOR3M, NYC);
SwapFixedIborDefinition irs = new SwapFixedIborDefinition(fixegLeg, iborLeg);
return irs;
}
}