/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.interestrate.swap.method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.opengamma.analytics.financial.interestrate.InterestRateCurveSensitivity;
import com.opengamma.analytics.financial.interestrate.YieldCurveBundle;
import com.opengamma.analytics.financial.interestrate.annuity.derivative.Annuity;
import com.opengamma.analytics.financial.interestrate.annuity.method.AnnuityDiscountingMethod;
import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponFixedAccruedCompounding;
import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponONCompounded;
import com.opengamma.analytics.financial.interestrate.payments.derivative.Payment;
import com.opengamma.analytics.financial.interestrate.payments.method.CouponONCompoundedDiscountingMethod;
import com.opengamma.analytics.financial.interestrate.swap.derivative.Swap;
import com.opengamma.analytics.financial.model.interestrate.curve.YieldAndDiscountCurve;
import com.opengamma.financial.convention.calendar.Calendar;
import com.opengamma.financial.convention.daycount.DayCount;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.money.CurrencyAmount;
import com.opengamma.util.tuple.DoublesPair;
/**
* Class to compute the quantities related to swaps (annuity, PVBP, coupon equivalent).
* @deprecated Use {@link com.opengamma.analytics.financial.interestrate.swap.provider.SwapFixedCouponDiscountingMethod}
*/
@Deprecated
public class SwapFixedCompoundingONCompoundingDiscountingMethod {
/**
* The method unique instance.
*/
private static final SwapFixedCompoundingONCompoundingDiscountingMethod INSTANCE = new SwapFixedCompoundingONCompoundingDiscountingMethod();
/**
* Return the unique instance of the class.
* @return The instance.
*/
public static SwapFixedCompoundingONCompoundingDiscountingMethod getInstance() {
return INSTANCE;
}
/**
* Private constructor.
*/
protected SwapFixedCompoundingONCompoundingDiscountingMethod() {
}
/**
* The methods.
*/
protected static final AnnuityDiscountingMethod METHOD_ANNUITY = AnnuityDiscountingMethod.getInstance();
private static final CouponONCompoundedDiscountingMethod METHOD_COUPON_ON_CMP = CouponONCompoundedDiscountingMethod.getInstance();
/**
* REVIEW: MH 26-Sep-13: Is "cash annuity" used with couponFixedAccruedCompounding swaps?
* Computes the conventional cash annuity of a swap. The computation is relevant only for standard swaps with constant notional and regular payments.
* @param fixedCouponSwap The underlying swap.
* @param forward The swap forward rate.
* @return The cash annuity.
*/
public double getAnnuityCash(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final double forward) {
final Annuity<? extends Payment> annuity = fixedCouponSwap.getFirstLeg();
final int nbFixedPeriod = annuity.getPayments().length;
final int nbFixedPaymentYear = (int) Math.round(1.0 / fixedCouponSwap.getFirstLeg().getNthPayment(0).getPaymentYearFraction());
final double notional = Math.abs(fixedCouponSwap.getFirstLeg().getNthPayment(0).getNotional());
final double annuityCash = 1.0 / forward * (1.0 - 1.0 / Math.pow(1 + forward / nbFixedPaymentYear, nbFixedPeriod)) * notional;
return annuityCash;
}
/**
* Computes the derivative of cash annuity with respect to the forward. The computation is relevant only for standard swaps with constant notional and regular payments.
* @param fixedCouponSwap The underlying swap.
* @param forward The swap forward.
* @return The cash annuity derivative.
*/
public double getAnnuityCashDerivative(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final double forward) {
final int nbFixedPeriod = fixedCouponSwap.getFirstLeg().getPayments().length;
final int nbFixedPaymentYear = (int) Math.round(1.0 / fixedCouponSwap.getFirstLeg().getNthPayment(0).getPaymentYearFraction());
final double notional = Math.abs(fixedCouponSwap.getFirstLeg().getNthPayment(0).getNotional());
double annuityCashDerivative = -1.0 / (forward * forward) * (1.0 - 1.0 / Math.pow(1 + forward / nbFixedPaymentYear, nbFixedPeriod)) * notional;
annuityCashDerivative += 1.0 / (forward * nbFixedPaymentYear) * nbFixedPeriod * Math.pow(1 + forward / nbFixedPaymentYear, -nbFixedPeriod - 1.0) * notional;
return annuityCashDerivative;
}
/**
* Computes the forward rate of the swaps with one fixed payment.
* @param fixedCouponSwap The underlying swap. Should have one fixed payment.
* @param curves The yield curve bundle.
* @return The forward rate.
*/
public double forward(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final YieldCurveBundle curves) {
ArgumentChecker.notNull(fixedCouponSwap, "Swap");
ArgumentChecker.isTrue(fixedCouponSwap.getFirstLeg().getNumberOfPayments() == 1, "Swap should have one fixed payment");
ArgumentChecker.isTrue(fixedCouponSwap.getSecondLeg().getNumberOfPayments() == 1, "Swap should have one floating payment");
CouponFixedAccruedCompounding cpnFixed = fixedCouponSwap.getFirstLeg().getNthPayment(0);
CurrencyAmount pvLegFloating = METHOD_COUPON_ON_CMP.presentValue(fixedCouponSwap.getSecondLeg().getNthPayment(0), curves);
double dfPay = curves.getCurve(cpnFixed.getFundingCurveName()).getDiscountFactor(cpnFixed.getPaymentTime());
double rate = Math.pow(-pvLegFloating.getAmount() / (dfPay * cpnFixed.getNotional()), 1.0d / cpnFixed.getPaymentYearFraction()) - 1.0d;
return rate;
}
/**
* Computes the "modified forward", i.e. the quantity F such that the swap with amount $N(F + 1)$ has a pv of 0.
* The modified forward is also equal to $(1+forward)^\delta - 1$.
* @param fixedCouponSwap The underlying swap. Should have one fixed payment.
* @param curves The yield curve bundle.
* @return The modified forward rate.
*/
public double forwardModified(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final YieldCurveBundle curves) {
ArgumentChecker.notNull(fixedCouponSwap, "Swap");
ArgumentChecker.isTrue(fixedCouponSwap.getFirstLeg().getNumberOfPayments() == 1, "Swap should have one fixed payment");
ArgumentChecker.isTrue(fixedCouponSwap.getSecondLeg().getNumberOfPayments() == 1, "Swap should have one floating payment");
CouponFixedAccruedCompounding cpnFixed = fixedCouponSwap.getFirstLeg().getNthPayment(0);
CurrencyAmount pvLegFloating = METHOD_COUPON_ON_CMP.presentValue(fixedCouponSwap.getSecondLeg().getNthPayment(0), curves);
double dfPay = curves.getCurve(cpnFixed.getFundingCurveName()).getDiscountFactor(cpnFixed.getPaymentTime());
double rate = -pvLegFloating.getAmount() / (dfPay * cpnFixed.getNotional()) - 1.0d;
return rate;
}
/**
* Computes the "modified forward", i.e. the quantity F such that the swap with amount $N(F + 1)$ has a pv of 0.
* The modified forward is also equal to $(1+forward)^\delta - 1$.
* @param fixedCouponSwap The underlying swap. Should have one fixed payment.
* @param curves The yield curve bundle.
* @return The modified forward rate.
*/
public InterestRateCurveSensitivity forwardModifiedCurveSensitivity(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final YieldCurveBundle curves) {
ArgumentChecker.notNull(fixedCouponSwap, "Swap");
ArgumentChecker.isTrue(fixedCouponSwap.getFirstLeg().getNumberOfPayments() == 1, "Swap should have one fixed payment");
ArgumentChecker.isTrue(fixedCouponSwap.getSecondLeg().getNumberOfPayments() == 1, "Swap should have one floating payment");
CouponFixedAccruedCompounding cpnFixed = fixedCouponSwap.getFirstLeg().getNthPayment(0);
CurrencyAmount pvLegFloating = METHOD_COUPON_ON_CMP.presentValue(fixedCouponSwap.getSecondLeg().getNthPayment(0), curves);
double dfPay = curves.getCurve(cpnFixed.getFundingCurveName()).getDiscountFactor(cpnFixed.getPaymentTime());
// double rate = -pvLegFloating.getAmount() / (dfPay * cpnFixed.getNotional()) - 1.0d;
// Backward sweep
double rateBar = 1.0;
double pvFloatingBar = -1.0d / (dfPay * cpnFixed.getNotional()) * rateBar;
double dfBar = pvLegFloating.getAmount() / (dfPay * dfPay * cpnFixed.getNotional()) * rateBar;
final double dfDr = -cpnFixed.getPaymentTime() * dfPay;
final List<DoublesPair> list = new ArrayList<>();
list.add(new DoublesPair(cpnFixed.getPaymentTime(), dfDr * dfBar));
final Map<String, List<DoublesPair>> dfMap = new HashMap<>();
dfMap.put(cpnFixed.getFundingCurveName(), list);
InterestRateCurveSensitivity result = new InterestRateCurveSensitivity(dfMap);
InterestRateCurveSensitivity pvLegFloatingDr = METHOD_COUPON_ON_CMP.presentValueCurveSensitivity(fixedCouponSwap.getSecondLeg().getNthPayment(0), curves);
result = result.plus(pvLegFloatingDr.multipliedBy(pvFloatingBar));
return result;
}
/**
* Computes the physical annuity (also called PVBP or level) of the fixed leg of a swap.
* @param fixedCouponSwap The underlying swap.
* @param discountingCurve The discount curve.
* @return The physical annuity.
*/
public double presentValueBasisPoint(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final YieldAndDiscountCurve discountingCurve) {
final Annuity<CouponFixedAccruedCompounding> annuityFixed = fixedCouponSwap.getFirstLeg();
double pvbp = 0;
for (int loopcpn = 0; loopcpn < annuityFixed.getPayments().length; loopcpn++) {
pvbp += annuityFixed.getNthPayment(loopcpn).getPaymentYearFraction() * Math.abs(annuityFixed.getNthPayment(loopcpn).getNotional())
* discountingCurve.getDiscountFactor(annuityFixed.getNthPayment(loopcpn).getPaymentTime());
}
return pvbp;
}
/**
* Computes the physical annuity (also called PVBP or level) of the fixed leg of a swap.
* @param fixedCouponSwap The underlying swap.
* @param curves The yield curve bundle (containing the appropriate discounting curve).
* @return The physical annuity.
*/
public double presentValueBasisPoint(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final YieldCurveBundle curves) {
final Annuity<CouponFixedAccruedCompounding> annuityFixed = fixedCouponSwap.getFirstLeg();
final YieldAndDiscountCurve discountingCurve = curves.getCurve(annuityFixed.getNthPayment(0).getFundingCurveName());
return presentValueBasisPoint(fixedCouponSwap, discountingCurve);
}
/**
* Computes the physical annuity (also called PVBP or level) of the fixed leg of a swap modified by a day count.
* @param fixedCouponSwap The underlying swap.
* @param dayCount Day count convention for the PVBP modification.
* @param calendar The calendar, not null
* @param discountingCurve The discount curve.
* @return The physical annuity.
*/
public double presentValueBasisPoint(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final DayCount dayCount, final Calendar calendar,
final YieldAndDiscountCurve discountingCurve) {
ArgumentChecker.notNull(fixedCouponSwap, "swap");
ArgumentChecker.notNull(dayCount, "day count");
ArgumentChecker.notNull(discountingCurve, "discounting curve");
final Annuity<? extends Payment> annuityFixed = fixedCouponSwap.getFirstLeg();
if (annuityFixed.getNumberOfPayments() == 0) {
return 0;
}
double pvbp = 0;
for (int loopcpn = 0; loopcpn < annuityFixed.getPayments().length; loopcpn++) {
final CouponFixedAccruedCompounding coupon = (CouponFixedAccruedCompounding) annuityFixed.getNthPayment(loopcpn);
pvbp += dayCount.getDayCountFraction(coupon.getAccrualStartDate(), coupon.getAccrualEndDate(), calendar)
* Math.abs(coupon.getNotional()) * discountingCurve.getDiscountFactor(annuityFixed.getNthPayment(loopcpn).getPaymentTime());
}
return pvbp;
}
/**
* Computes the physical annuity (also called PVBP or level) of the fixed leg of a swap modified by a day count.
* @param fixedCouponSwap The underlying swap.
* @param dayCount Day count convention for the PVBP modification.
* @param calendar The calendar, not null
* @param curves The yield curve bundle (containing the appropriate discounting curve).
* @return The physical annuity.
*/
public double presentValueBasisPoint(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final DayCount dayCount, final Calendar calendar,
final YieldCurveBundle curves) {
final Annuity<CouponFixedAccruedCompounding> annuityFixed = fixedCouponSwap.getFirstLeg();
final YieldAndDiscountCurve discountingCurve = curves.getCurve(annuityFixed.getNthPayment(0).getFundingCurveName());
return presentValueBasisPoint(fixedCouponSwap, dayCount, calendar, discountingCurve);
}
/**
* Compute the sensitivity of the PVBP to the discounting curve.
* @param fixedCouponSwap The swap.
* @param discountingCurve The discounting curve.
* @return The sensitivity.
*/
public List<DoublesPair> presentValueBasisPointCurveSensitivity(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final YieldAndDiscountCurve discountingCurve) {
final Annuity<CouponFixedAccruedCompounding> annuityFixed = fixedCouponSwap.getFirstLeg();
double time;
final List<DoublesPair> list = new ArrayList<>();
for (int loopcpn = 0; loopcpn < annuityFixed.getPayments().length; loopcpn++) {
time = annuityFixed.getNthPayment(loopcpn).getPaymentTime();
final DoublesPair s = new DoublesPair(time, -time * discountingCurve.getDiscountFactor(time) * annuityFixed.getNthPayment(loopcpn).getPaymentYearFraction()
* Math.abs(annuityFixed.getNthPayment(loopcpn).getNotional()));
list.add(s);
}
return list;
}
/**
* Compute the sensitivity of the PVBP to a curve bundle.
* @param fixedCouponSwap The swap.
* @param curves The yield curve bundle (containing the appropriate discounting curve).
* @return The sensitivity.
*/
public InterestRateCurveSensitivity presentValueBasisPointCurveSensitivity(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final YieldCurveBundle curves) {
final Map<String, List<DoublesPair>> result = new HashMap<>();
final Annuity<CouponFixedAccruedCompounding> annuityFixed = fixedCouponSwap.getFirstLeg();
final YieldAndDiscountCurve discountingCurve = curves.getCurve(annuityFixed.getNthPayment(0).getFundingCurveName());
result.put(annuityFixed.getNthPayment(0).getFundingCurveName(), presentValueBasisPointCurveSensitivity(fixedCouponSwap, discountingCurve));
return new InterestRateCurveSensitivity(result);
}
/**
* Compute the sensitivity of the PVBP to the discounting curve.
* @param fixedCouponSwap The swap.
* @param dayCount Day count convention for the PVBP modification.
* @param calendar The calendar
* @param discountingCurve The discounting curve.
* @return The sensitivity.
*/
public List<DoublesPair> presentValueBasisPointCurveSensitivity(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final DayCount dayCount,
final Calendar calendar, final YieldAndDiscountCurve discountingCurve) {
final Annuity<CouponFixedAccruedCompounding> annuityFixed = fixedCouponSwap.getFirstLeg();
double time;
final List<DoublesPair> list = new ArrayList<>();
for (int loopcpn = 0; loopcpn < annuityFixed.getPayments().length; loopcpn++) {
time = annuityFixed.getNthPayment(loopcpn).getPaymentTime();
final DoublesPair s = new DoublesPair(time, -time * discountingCurve.getDiscountFactor(time)
* dayCount.getDayCountFraction(annuityFixed.getNthPayment(loopcpn).getAccrualStartDate(), annuityFixed.getNthPayment(loopcpn).getAccrualEndDate(), calendar)
* Math.abs(annuityFixed.getNthPayment(loopcpn).getNotional()));
list.add(s);
}
return list;
}
/**
* Compute the sensitivity of the PVBP to the discounting curve.
* @param fixedCouponSwap The swap.
* @param dayCount Day count convention for the PVBP modification.
* @param discountingCurve The discounting curve.
* @return The sensitivity.
*/
public List<DoublesPair> presentValueBasisPointCurveSensitivity(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final DayCount dayCount,
final YieldAndDiscountCurve discountingCurve) {
final Annuity<CouponFixedAccruedCompounding> annuityFixed = fixedCouponSwap.getFirstLeg();
double time;
final List<DoublesPair> list = new ArrayList<>();
for (int loopcpn = 0; loopcpn < annuityFixed.getPayments().length; loopcpn++) {
time = annuityFixed.getNthPayment(loopcpn).getPaymentTime();
final DoublesPair s = new DoublesPair(time, -time * discountingCurve.getDiscountFactor(time)
* dayCount.getDayCountFraction(annuityFixed.getNthPayment(loopcpn).getAccrualStartDate(), annuityFixed.getNthPayment(loopcpn).getAccrualEndDate())
* Math.abs(annuityFixed.getNthPayment(loopcpn).getNotional()));
list.add(s);
}
return list;
}
/**
* Compute the sensitivity of the PVBP to a curve bundle.
* @param fixedCouponSwap The swap.
* @param dayCount Day count convention for the PVBP modification.
* @param calendar The calendar
* @param curves The yield curve bundle (containing the appropriate discounting curve).
* @return The sensitivity.
*/
public InterestRateCurveSensitivity presentValueBasisPointCurveSensitivity(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final DayCount dayCount,
final Calendar calendar, final YieldCurveBundle curves) {
final Map<String, List<DoublesPair>> result = new HashMap<>();
final Annuity<CouponFixedAccruedCompounding> annuityFixed = fixedCouponSwap.getFirstLeg();
final YieldAndDiscountCurve discountingCurve = curves.getCurve(annuityFixed.getNthPayment(0).getFundingCurveName());
result.put(annuityFixed.getNthPayment(0).getFundingCurveName(), presentValueBasisPointCurveSensitivity(fixedCouponSwap, dayCount, calendar, discountingCurve));
return new InterestRateCurveSensitivity(result);
}
/**
* Compute the sensitivity of the PVBP to a curve bundle.
* @param fixedCouponSwap The swap.
* @param dayCount Day count convention for the PVBP modification.
* @param curves The yield curve bundle (containing the appropriate discounting curve).
* @return The sensitivity.
*/
public InterestRateCurveSensitivity presentValueBasisPointCurveSensitivity(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap,
final DayCount dayCount,
final YieldCurveBundle curves) {
final Map<String, List<DoublesPair>> result = new HashMap<>();
final Annuity<CouponFixedAccruedCompounding> annuityFixed = fixedCouponSwap.getFirstLeg();
final YieldAndDiscountCurve discountingCurve = curves.getCurve(annuityFixed.getNthPayment(0).getFundingCurveName());
result.put(annuityFixed.getNthPayment(0).getFundingCurveName(), presentValueBasisPointCurveSensitivity(fixedCouponSwap, dayCount, discountingCurve));
return new InterestRateCurveSensitivity(result);
}
/**
* Computes the coupon equivalent of a swap (without margins).
* @param fixedCouponSwap The underlying swap.
* @param pvbp The swap PVBP.
* @param curves The curves.
* @return The coupon equivalent.
*/
public double couponEquivalent(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final double pvbp, final YieldCurveBundle curves) {
return METHOD_ANNUITY.presentValuePositiveNotional(fixedCouponSwap.getFirstLeg(), curves).getAmount() / pvbp;
}
/**
* Computes the coupon equivalent of a swap (without margins).
* @param fixedCouponSwap The underlying swap.
* @param curves The curves.
* @return The coupon equivalent.
*/
public double couponEquivalent(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final YieldCurveBundle curves) {
final double pvbp = presentValueBasisPoint(fixedCouponSwap, curves);
return couponEquivalent(fixedCouponSwap, pvbp, curves);
}
/**
* Computes the coupon equivalent of a swap (without margins).
* @param fixedCouponSwap The underlying swap.
* @param dayCount Day count convention for the PVBP modification.
* @param calendar The calendar
* @param curves The curves.
* @return The coupon equivalent.
*/
public double couponEquivalent(final Swap<CouponFixedAccruedCompounding, CouponONCompounded> fixedCouponSwap, final DayCount dayCount,
final Calendar calendar, final YieldCurveBundle curves) {
final double pvbp = presentValueBasisPoint(fixedCouponSwap, dayCount, calendar, curves);
return couponEquivalent(fixedCouponSwap, pvbp, curves);
}
}