/**
* Copyright (C) 2009 - 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.List;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivativeVisitor;
import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponFixed;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.money.Currency;
/**
* A wrapper class for a GenericAnnuity containing FixedCouponPayment.
*/
public class AnnuityCouponFixed extends Annuity<CouponFixed> {
/**
* Constructor from an array of fixed coupons.
* @param payments The payments array.
*/
public AnnuityCouponFixed(final CouponFixed[] payments) {
super(payments);
}
/**
* @param currency The currency, not null
* @param paymentTimes The payment times, not null
* @param couponRate The coupon rate
* @param yieldCurveName The yield curve name
* @param isPayer True if the annuity is paid
* @deprecated Use the constructor that does not take a yield curve name
*/
@Deprecated
public AnnuityCouponFixed(final Currency currency, final double[] paymentTimes, final double couponRate, final String yieldCurveName, final boolean isPayer) {
this(currency, paymentTimes, 1.0, couponRate, yieldCurveName, isPayer);
}
/**
* @param currency The currency, not null
* @param paymentTimes The payment times, not null
* @param couponRate The coupon rate
* @param isPayer True if the annuity is paid
*/
public AnnuityCouponFixed(final Currency currency, final double[] paymentTimes, final double couponRate, final boolean isPayer) {
this(currency, paymentTimes, 1.0, couponRate, isPayer);
}
/**
* @param currency The currency, not null
* @param paymentTimes The payment times, not null
* @param notional The notional
* @param couponRate The coupon rate
* @param yieldCurveName The yield curve name
* @param isPayer True if the annuity is paid
* @deprecated Use the constructor that does not take a yield curve name
*/
@Deprecated
public AnnuityCouponFixed(final Currency currency, final double[] paymentTimes, final double notional, final double couponRate, final String yieldCurveName, final boolean isPayer) {
this(currency, paymentTimes, notional, couponRate, initBasisYearFraction(paymentTimes), yieldCurveName, isPayer);
}
/**
* @param currency The currency, not null
* @param paymentTimes The payment times, not null
* @param notional The notional
* @param couponRate The coupon rate
* @param isPayer True if the annuity is paid
*/
public AnnuityCouponFixed(final Currency currency, final double[] paymentTimes, final double notional, final double couponRate, final boolean isPayer) {
this(currency, paymentTimes, notional, couponRate, initBasisYearFraction(paymentTimes), isPayer);
}
/**
* Constructor from payment times and year fractions and unique notional and rate.
* @param currency The payment currency.
* @param paymentTimes The times (in year) of payment.
* @param notional The common notional.
* @param couponRate The common coupon rate.
* @param yearFractions The year fraction of each payment.
* @param yieldCurveName The discounting curve name.
* @param isPayer Payer flag.
* @deprecated Use the constructor that does not take a yield curve name
*/
@Deprecated
public AnnuityCouponFixed(final Currency currency, final double[] paymentTimes, final double notional, final double couponRate, final double[] yearFractions,
final String yieldCurveName, final boolean isPayer) {
super(init(currency, paymentTimes, notional * (isPayer ? -1.0 : 1.0), couponRate, yearFractions, yieldCurveName));
}
/**
* Constructor from payment times and year fractions and unique notional and rate.
* @param currency The payment currency.
* @param paymentTimes The times (in year) of payment.
* @param notional The common notional.
* @param couponRate The common coupon rate.
* @param yearFractions The year fraction of each payment.
* @param isPayer Payer flag.
*/
public AnnuityCouponFixed(final Currency currency, final double[] paymentTimes, final double notional, final double couponRate, final double[] yearFractions,
final boolean isPayer) {
super(init(currency, paymentTimes, notional * (isPayer ? -1.0 : 1.0), couponRate, yearFractions));
}
/**
* Return the coupon rate of the annuity first coupon.
* @return The rate.
*/
public double getCouponRate() {
return getNthPayment(0).getFixedRate();
}
/**
* Creates a new annuity with the same characteristics, except the rate which is 1.0.
* @return The new annuity.
*/
public AnnuityCouponFixed withUnitCoupon() {
final CouponFixed[] cpn = new CouponFixed[getNumberOfPayments()];
for (int loopcpn = 0; loopcpn < getNumberOfPayments(); loopcpn++) {
cpn[loopcpn] = getNthPayment(loopcpn).withUnitCoupon();
}
return new AnnuityCouponFixed(cpn);
}
/**
* Creates a new annuity with the same characteristics, except that the rate of all coupons is the one given.
* @param rate The rate.
* @return The new annuity.
*/
public AnnuityCouponFixed withRate(final double rate) {
final CouponFixed[] cpn = new CouponFixed[getNumberOfPayments()];
for (int loopcpn = 0; loopcpn < getNumberOfPayments(); loopcpn++) {
cpn[loopcpn] = getNthPayment(loopcpn).withRate(rate);
}
return new AnnuityCouponFixed(cpn);
}
/**
* Creates a new annuity with the same characteristics, except that the rate of all coupons are shifted by the given amount.
* @param spread The spread.
* @return The new annuity.
*/
public AnnuityCouponFixed withRateShifted(final double spread) {
final CouponFixed[] cpn = new CouponFixed[getNumberOfPayments()];
for (int loopcpn = 0; loopcpn < getNumberOfPayments(); loopcpn++) {
cpn[loopcpn] = getNthPayment(loopcpn).withRateShifted(spread);
}
return new AnnuityCouponFixed(cpn);
}
/**
* Creates a new annuity with the same characteristics, except that the notional all coupons is the one given.
* @param notional The notional.
* @return The new annuity.
*/
public AnnuityCouponFixed withNotional(final double notional) {
final CouponFixed[] cpn = new CouponFixed[getNumberOfPayments()];
for (int loopcpn = 0; loopcpn < getNumberOfPayments(); loopcpn++) {
cpn[loopcpn] = getNthPayment(loopcpn).withNotional(notional);
}
return new AnnuityCouponFixed(cpn);
}
/**
* Remove the payments paying on or before the given time.
* @param trimTime The time.
* @return The trimmed annuity.
*/
@Override
public AnnuityCouponFixed trimBefore(final double trimTime) {
final List<CouponFixed> list = new ArrayList<>();
for (final CouponFixed payment : getPayments()) {
if (payment.getPaymentTime() > trimTime) {
list.add(payment);
}
}
return new AnnuityCouponFixed(list.toArray(new CouponFixed[list.size()]));
}
/**
* Remove the payments paying strictly after before the given time.
* @param trimTime The time.
* @return The trimmed annuity.
*/
@Override
public AnnuityCouponFixed trimAfter(final double trimTime) {
final List<CouponFixed> list = new ArrayList<>();
for (final CouponFixed payment : getPayments()) {
if (payment.getPaymentTime() <= trimTime) {
list.add(payment);
}
}
return new AnnuityCouponFixed(list.toArray(new CouponFixed[list.size()]));
}
/**
* A list of fixed coupon from payment times and year fractions and unique notional and rate.
* @param currency The payment currency.
* @param paymentTimes The times (in year) of payment.
* @param notional The common notional.
* @param couponRate The common coupon rate.
* @param yearFractions The year fraction of each payment.
* @param yieldCurveName The discounting curve name.
* @return The array of fixed coupons.
* @deprecated Use the method that does not take yield curve names
*/
@Deprecated
private static CouponFixed[] init(final Currency currency, final double[] paymentTimes, final double notional, final double couponRate, final double[] yearFractions, final String yieldCurveName) {
ArgumentChecker.notNull(paymentTimes, "payment times");
ArgumentChecker.isTrue(paymentTimes.length > 0, "payment times array is empty");
ArgumentChecker.notNull(yearFractions, "year fractions");
ArgumentChecker.isTrue(yearFractions.length > 0, "year fraction array is empty");
ArgumentChecker.notNull(yieldCurveName, "yield curve name");
final int n = paymentTimes.length;
ArgumentChecker.isTrue(yearFractions.length == n, "Number of year fractions must equal the number of payments");
final CouponFixed[] temp = new CouponFixed[n];
for (int i = 0; i < n; i++) {
temp[i] = new CouponFixed(currency, paymentTimes[i], yieldCurveName, yearFractions[i], notional, couponRate);
}
return temp;
}
/**
* A list of fixed coupon from payment times and year fractions and unique notional and rate.
* @param currency The payment currency.
* @param paymentTimes The times (in year) of payment.
* @param notional The common notional.
* @param couponRate The common coupon rate.
* @param yearFractions The year fraction of each payment.
* @return The array of fixed coupons.
*/
private static CouponFixed[] init(final Currency currency, final double[] paymentTimes, final double notional, final double couponRate, final double[] yearFractions) {
ArgumentChecker.notNull(paymentTimes, "payment times");
ArgumentChecker.isTrue(paymentTimes.length > 0, "payment times array is empty");
ArgumentChecker.notNull(yearFractions, "year fractions");
ArgumentChecker.isTrue(yearFractions.length > 0, "year fraction array is empty");
final int n = paymentTimes.length;
ArgumentChecker.isTrue(yearFractions.length == n, "Number of year fractions must equal the number of payments");
final CouponFixed[] temp = new CouponFixed[n];
for (int i = 0; i < n; i++) {
temp[i] = new CouponFixed(currency, paymentTimes[i], yearFractions[i], notional, couponRate);
}
return temp;
}
private static double[] initBasisYearFraction(final double[] paymentTimes) {
ArgumentChecker.notNull(paymentTimes, "payment times");
ArgumentChecker.isTrue(paymentTimes.length > 0, "payment times array is empty");
final int n = paymentTimes.length;
final double[] res = new double[n];
for (int i = 0; i < n; i++) {
res[i] = (i == 0 ? paymentTimes[0] : paymentTimes[i] - paymentTimes[i - 1]); // TODO ????????? so the payment year fractions could be 2.5, 0.5, 0.5, 0.5?
}
return res;
}
@Override
public <S, T> T accept(final InstrumentDerivativeVisitor<S, T> visitor, final S data) {
ArgumentChecker.notNull(visitor, "visitor");
return visitor.visitFixedCouponAnnuity(this, data);
}
@Override
public <T> T accept(final InstrumentDerivativeVisitor<?, T> visitor) {
ArgumentChecker.notNull(visitor, "visitor");
return visitor.visitFixedCouponAnnuity(this);
}
}