/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate.annuity.derivative; import java.util.ArrayList; import java.util.Arrays; import com.opengamma.analytics.financial.interestrate.InstrumentDerivative; import com.opengamma.analytics.financial.interestrate.InstrumentDerivativeVisitor; import com.opengamma.analytics.financial.interestrate.ParRateCalculator; import com.opengamma.analytics.financial.interestrate.YieldCurveBundle; import com.opengamma.analytics.financial.interestrate.payments.derivative.CapFloorIbor; import com.opengamma.analytics.financial.interestrate.payments.derivative.Coupon; import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponFixed; import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponIborGearing; import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponIborRatchet; import com.opengamma.util.ArgumentChecker; /** * A wrapper class for a AnnuityDefinition containing mainly CouponIborRatchetDefinition. The first coupon should be a CouponFixed or a CouponIborGearing. * The other coupons should be CouponFixed or a CouponIborRatchet. */ @SuppressWarnings("deprecation") public class AnnuityCouponIborRatchet extends Annuity<Coupon> { /** * List of calibration types for the Ratchet Ibor coupon annuity. */ public enum RatchetIborCalibrationType { /** * The calibration instruments are caps at strike given by the coupon in the forward curve. */ FORWARD_COUPON } /** * Flag indicating if a coupon is already fixed. */ private final boolean[] _isFixed; /** * @param payments The payments composing the annuity. */ public AnnuityCouponIborRatchet(final Coupon[] payments) { super(payments); _isFixed = new boolean[payments.length]; ArgumentChecker.isTrue((payments[0] instanceof CouponFixed) || (payments[0] instanceof CouponIborGearing), "First coupon should be CouponFixed or a CouponIborGearing"); _isFixed[0] = (payments[0] instanceof CouponFixed); for (int looppay = 1; looppay < payments.length; looppay++) { ArgumentChecker.isTrue((payments[looppay] instanceof CouponFixed) || (payments[looppay] instanceof CouponIborRatchet), "Next coupons should be CouponFixed or CouponIborRatchet"); _isFixed[looppay] = (payments[looppay] instanceof CouponFixed); } } /** * Gets the flag indicating if a coupon is already fixed. * @return The flag. */ public boolean[] isFixed() { return _isFixed; } /** * @param type The calibration type * @param curves The yield curves * @return A list of coupons that are used in calibration * @deprecated {@link YieldCurveBundle} is deprecated */ //REVIEW emcleod This method does not belong in this class @Deprecated public InstrumentDerivative[] calibrationBasket(final RatchetIborCalibrationType type, final YieldCurveBundle curves) { final ArrayList<InstrumentDerivative> calibration = new ArrayList<>(); final ParRateCalculator prc = ParRateCalculator.getInstance(); switch (type) { case FORWARD_COUPON: final int nbCpn = getNumberOfPayments(); final double[] cpnRate = new double[nbCpn]; for (int loopcpn = 0; loopcpn < nbCpn; loopcpn++) { if (getNthPayment(loopcpn) instanceof CouponIborRatchet) { final CouponIborRatchet cpn = (CouponIborRatchet) getNthPayment(loopcpn); final double ibor = prc.visitCouponIborSpread(cpn, curves); final double cpnMain = cpn.getMainCoefficients()[0] * cpnRate[loopcpn - 1] + cpn.getMainCoefficients()[1] * ibor + cpn.getMainCoefficients()[2]; final double cpnFloor = cpn.getFloorCoefficients()[0] * cpnRate[loopcpn - 1] + cpn.getFloorCoefficients()[1] * ibor + cpn.getFloorCoefficients()[2]; final double cpnCap = cpn.getCapCoefficients()[0] * cpnRate[loopcpn - 1] + cpn.getCapCoefficients()[1] * ibor + cpn.getCapCoefficients()[2]; cpnRate[loopcpn] = Math.min(Math.max(cpnFloor, cpnMain), cpnCap); calibration.add(new CapFloorIbor(cpn.getCurrency(), cpn.getPaymentTime(), cpn.getFundingCurveName(), cpn.getPaymentYearFraction(), cpn.getNotional(), cpn.getFixingTime(), cpn.getIndex(), cpn.getFixingPeriodStartTime(), cpn.getFixingPeriodEndTime(), cpn.getFixingAccrualFactor(), cpn.getForwardCurveName(), cpnRate[loopcpn], true)); } else { if (getNthPayment(loopcpn) instanceof CouponFixed) { final CouponFixed cpn = (CouponFixed) getNthPayment(loopcpn); cpnRate[loopcpn] = cpn.getFixedRate(); } else { final CouponIborGearing cpn = (CouponIborGearing) getNthPayment(loopcpn); final double ibor = prc.visitCouponIborGearing(cpn, curves); cpnRate[loopcpn] = cpn.getFactor() * ibor + cpn.getSpread(); } } } break; default: break; } return calibration.toArray(new InstrumentDerivative[calibration.size()]); } @Override public <S, T> T accept(final InstrumentDerivativeVisitor<S, T> visitor, final S data) { return visitor.visitAnnuityCouponIborRatchet(this, data); } @Override public <T> T accept(final InstrumentDerivativeVisitor<?, T> visitor) { return visitor.visitAnnuityCouponIborRatchet(this); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + Arrays.hashCode(_isFixed); return result; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (!(obj instanceof AnnuityCouponIborRatchet)) { return false; } final AnnuityCouponIborRatchet other = (AnnuityCouponIborRatchet) obj; if (!Arrays.equals(_isFixed, other._isFixed)) { return false; } return true; } }