/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.provider.calculator.discounting; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.opengamma.analytics.financial.interestrate.InstrumentDerivativeVisitorAdapter; import com.opengamma.analytics.financial.interestrate.annuity.derivative.Annuity; import com.opengamma.analytics.financial.interestrate.annuity.derivative.AnnuityCouponFixed; import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponFixed; import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponIbor; import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponIborSpread; import com.opengamma.analytics.financial.interestrate.payments.derivative.Payment; import com.opengamma.analytics.financial.interestrate.payments.derivative.PaymentFixed; import com.opengamma.analytics.financial.interestrate.swap.derivative.Swap; import com.opengamma.analytics.financial.interestrate.swap.derivative.SwapFixedCoupon; import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderInterface; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.ForwardSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MulticurveSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.SimplyCompoundedForwardSensitivity; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.Currency; import com.opengamma.util.tuple.DoublesPair; /** * Calculator of the cash flow equivalent sensitivity to the curve. The result is a map of <Double, PresentValueSensitivity>. * The cash flow equivalent sensitivity is represented by the double which is the time of the cash flow and the PresentValueSensitivity which is the sensitivity of the * cash flow at that date. */ public class CashFlowEquivalentCurveSensitivityCalculator extends InstrumentDerivativeVisitorAdapter<MulticurveProviderInterface, Map<Double, MulticurveSensitivity>> { /** * The unique instance of the calculator. */ private static final CashFlowEquivalentCurveSensitivityCalculator s_instance = new CashFlowEquivalentCurveSensitivityCalculator(); /** * Gets the calculator instance. * @return The calculator. */ public static CashFlowEquivalentCurveSensitivityCalculator getInstance() { return s_instance; } /** * Constructor. */ CashFlowEquivalentCurveSensitivityCalculator() { } @Override public Map<Double, MulticurveSensitivity> visitFixedPayment(final PaymentFixed payment, final MulticurveProviderInterface multicurves) { return new HashMap<>(); } @Override public Map<Double, MulticurveSensitivity> visitCouponFixed(final CouponFixed coupon, final MulticurveProviderInterface multicurves) { return new HashMap<>(); } @Override public Map<Double, MulticurveSensitivity> visitCouponIbor(final CouponIbor payment, final MulticurveProviderInterface multicurves) { ArgumentChecker.notNull(payment, "Payment"); ArgumentChecker.notNull(multicurves, "Multicurves provider"); final Currency ccy = payment.getCurrency(); final double fixingStartTime = payment.getFixingPeriodStartTime(); final double fixingEndTime = payment.getFixingPeriodEndTime(); final double paymentTime = payment.getPaymentTime(); final double dfRatio = multicurves.getDiscountFactor(ccy, paymentTime) / multicurves.getDiscountFactor(ccy, fixingStartTime); final double af = payment.getFixingAccrualFactor(); final double beta = (1.0 + af * multicurves.getSimplyCompoundForwardRate(payment.getIndex(), fixingStartTime, fixingEndTime, payment.getFixingAccrualFactor())) * dfRatio; final double betaBar = payment.getNotional() * payment.getPaymentYearFraction() / af; final double forwardBar = af * dfRatio * betaBar; final Map<Double, MulticurveSensitivity> result = new HashMap<>(); final Map<String, List<ForwardSensitivity>> resultFwd = new HashMap<>(); final List<ForwardSensitivity> listForward = new ArrayList<>(); listForward.add(new SimplyCompoundedForwardSensitivity(fixingStartTime, fixingEndTime, af, forwardBar)); resultFwd.put(multicurves.getName(payment.getIndex()), listForward); final Map<String, List<DoublesPair>> resultDsc = new HashMap<>(); final List<DoublesPair> listDisc = new ArrayList<>(); final DoublesPair discStart = DoublesPair.of(fixingStartTime, beta * fixingStartTime * betaBar); listDisc.add(discStart); final DoublesPair discPay = DoublesPair.of(paymentTime, -paymentTime * beta * betaBar); listDisc.add(discPay); resultDsc.put(multicurves.getName(ccy), listDisc); result.put(fixingStartTime, MulticurveSensitivity.of(resultDsc, resultFwd)); return result; } @Override public Map<Double, MulticurveSensitivity> visitCouponIborSpread(final CouponIborSpread payment, final MulticurveProviderInterface multicurves) { ArgumentChecker.notNull(payment, "Payment"); ArgumentChecker.notNull(multicurves, "Multicurves provider"); final Currency ccy = payment.getCurrency(); final double fixingStartTime = payment.getFixingPeriodStartTime(); final double fixingEndTime = payment.getFixingPeriodEndTime(); final double paymentTime = payment.getPaymentTime(); final double dfRatio = multicurves.getDiscountFactor(ccy, paymentTime) / multicurves.getDiscountFactor(ccy, fixingStartTime); final double af = payment.getFixingAccrualFactor(); final double beta = (1.0 + af * multicurves.getSimplyCompoundForwardRate(payment.getIndex(), fixingStartTime, fixingEndTime, payment.getFixingAccrualFactor())) * dfRatio; final double betaBar = payment.getNotional() * payment.getPaymentYearFraction() / af; final double forwardBar = af * dfRatio * betaBar; final Map<Double, MulticurveSensitivity> result = new HashMap<>(); final Map<String, List<ForwardSensitivity>> resultFwd = new HashMap<>(); final List<ForwardSensitivity> listForward = new ArrayList<>(); listForward.add(new SimplyCompoundedForwardSensitivity(fixingStartTime, fixingEndTime, af, forwardBar)); resultFwd.put(multicurves.getName(payment.getIndex()), listForward); final Map<String, List<DoublesPair>> resultDsc = new HashMap<>(); final List<DoublesPair> listDisc = new ArrayList<>(); final DoublesPair discStart = DoublesPair.of(fixingStartTime, beta * fixingStartTime * betaBar); listDisc.add(discStart); final DoublesPair discPay = DoublesPair.of(paymentTime, -paymentTime * beta * betaBar); listDisc.add(discPay); resultDsc.put(multicurves.getName(ccy), listDisc); result.put(fixingStartTime, MulticurveSensitivity.of(resultDsc, resultFwd)); return result; } @Override public Map<Double, MulticurveSensitivity> visitGenericAnnuity(final Annuity<? extends Payment> annuity, final MulticurveProviderInterface multicurves) { ArgumentChecker.notNull(annuity, "Annuity"); ArgumentChecker.notNull(multicurves, "Multicurves provider"); final Map<Double, MulticurveSensitivity> result = new HashMap<>(); for (final Payment p : annuity.getPayments()) { final Map<Double, MulticurveSensitivity> paymentSensi = p.accept(this, multicurves); result.putAll(paymentSensi); // It is suppose that no two coupons have the same cfe sensitivity date. } return result; } @Override public Map<Double, MulticurveSensitivity> visitFixedCouponAnnuity(final AnnuityCouponFixed annuity, final MulticurveProviderInterface multicurves) { return visitGenericAnnuity(annuity, multicurves); } @Override public Map<Double, MulticurveSensitivity> visitSwap(final Swap<?, ?> swap, final MulticurveProviderInterface multicurves) { ArgumentChecker.notNull(swap, "Swap"); ArgumentChecker.notNull(multicurves, "Multicurves provider"); final Map<Double, MulticurveSensitivity> result = new HashMap<>(); final Map<Double, MulticurveSensitivity> legSensi1 = swap.getFirstLeg().accept(this, multicurves); result.putAll(legSensi1); final Map<Double, MulticurveSensitivity> legSensi2 = swap.getSecondLeg().accept(this, multicurves); result.putAll(legSensi2); // It is suppose that the two legs have different cfe sensitivity date. return result; } @Override public Map<Double, MulticurveSensitivity> visitFixedCouponSwap(final SwapFixedCoupon<?> swap, final MulticurveProviderInterface multicurves) { return visitSwap(swap, multicurves); } }