/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.instrument.payment; import org.threeten.bp.Period; import org.threeten.bp.ZonedDateTime; import com.opengamma.analytics.financial.instrument.InstrumentDefinitionVisitor; import com.opengamma.analytics.financial.instrument.index.GeneratorDeposit; import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponFixed; import com.opengamma.analytics.financial.schedule.ScheduleCalculator; import com.opengamma.analytics.util.time.TimeCalculator; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.Currency; /** * Class describing a fixed payment coupon. */ public class CouponFixedDefinition extends CouponDefinition { /** * The fixed rate of the fixed coupon. */ private final double _rate; /** * The amount to be paid by the fixed coupon (=getNotional() * _rate * getPaymentYearFraction()) */ private final double _amount; /** * Constructor from all the coupon details. * @param currency The payment currency. * @param paymentDate Coupon payment date. * @param accrualStartDate Start date of the accrual period. * @param accrualEndDate End date of the accrual period. * @param paymentYearFraction Accrual factor of the accrual period. * @param notional Coupon notional. * @param rate Fixed rate. */ public CouponFixedDefinition(final Currency currency, final ZonedDateTime paymentDate, final ZonedDateTime accrualStartDate, final ZonedDateTime accrualEndDate, final double paymentYearFraction, final double notional, final double rate) { super(currency, paymentDate, accrualStartDate, accrualEndDate, paymentYearFraction, notional); _rate = rate; _amount = notional * rate * paymentYearFraction; } /** * Fixed coupon constructor from a coupon and the fixed rate. * @param coupon Underlying coupon. * @param rate Fixed rate. */ public CouponFixedDefinition(final CouponDefinition coupon, final double rate) { super(coupon.getCurrency(), coupon.getPaymentDate(), coupon.getAccrualStartDate(), coupon.getAccrualEndDate(), coupon.getPaymentYearFraction(), coupon.getNotional()); _rate = rate; _amount = coupon.getNotional() * rate * coupon.getPaymentYearFraction(); } /** * Static constructor for a fixed coupon definition. * @param currency The payment currency. * @param paymentDate Coupon payment date. * @param accrualStartDate Start date of the accrual period. * @param accrualEndDate End date of the accrual period. * @param paymentYearFraction Accrual factor of the accrual period. * @param notional Coupon notional. * @param rate Fixed rate. * @return The fixed coupon definition */ public static CouponFixedDefinition from(final Currency currency, final ZonedDateTime paymentDate, final ZonedDateTime accrualStartDate, final ZonedDateTime accrualEndDate, final double paymentYearFraction, final double notional, final double rate) { return new CouponFixedDefinition(currency, paymentDate, accrualStartDate, accrualEndDate, paymentYearFraction, notional, rate); } public static CouponFixedDefinition from(final CouponFloatingDefinition floatingCoupon, final double fixedRate) { return new CouponFixedDefinition(floatingCoupon.getCurrency(), floatingCoupon.getPaymentDate(), floatingCoupon.getAccrualStartDate(), floatingCoupon.getAccrualEndDate(), floatingCoupon.getPaymentYearFraction(), floatingCoupon.getNotional(), fixedRate); } public static CouponFixedDefinition from(final CouponIborSpreadDefinition floatingCoupon, final double fixedRate) { return new CouponFixedDefinition(floatingCoupon.getCurrency(), floatingCoupon.getPaymentDate(), floatingCoupon.getAccrualStartDate(), floatingCoupon.getAccrualEndDate(), floatingCoupon.getPaymentYearFraction(), floatingCoupon.getNotional(), fixedRate + floatingCoupon.getSpread()); } /** * Build a fixed coupon from a start date, tenor and deposit generator. * @param startDate The coupon start date. * @param tenor The coupon tenor. The end date is used both for the end accrual and the payment date. * @param generator The deposit generator with relevant conventions. * @param notional Coupon notional. * @param fixedRate The coupon fixed rate. * @return The coupon. */ public static CouponFixedDefinition from(final ZonedDateTime startDate, final Period tenor, final GeneratorDeposit generator, final double notional, final double fixedRate) { final ZonedDateTime endDate = ScheduleCalculator.getAdjustedDate(startDate, tenor, generator.getBusinessDayConvention(), generator.getCalendar(), generator.isEndOfMonth()); final double paymentYearFraction = generator.getDayCount().getDayCountFraction(startDate, endDate, generator.getCalendar()); return new CouponFixedDefinition(generator.getCurrency(), endDate, startDate, endDate, paymentYearFraction, notional, fixedRate); } /** * Gets the fixed rate. * @return The rate. */ public double getRate() { return _rate; } /** * Gets the payment amount. * @return The amount. */ public double getAmount() { return _amount; } /** * Creates a new coupon with all the details the same except the notional which is the one provided. * @param notional The new notional. * @return The coupon. */ public CouponFixedDefinition withNotional(final double notional) { return new CouponFixedDefinition(getCurrency(), getPaymentDate(), getAccrualStartDate(), getAccrualEndDate(), getPaymentYearFraction(), notional, _rate); } /** * Creates a new coupon with all the details the same except the rate which is the one provided. * @param rate The new rate. * @return The coupon. */ public CouponFixedDefinition withRate(final double rate) { return new CouponFixedDefinition(getCurrency(), getPaymentDate(), getAccrualStartDate(), getAccrualEndDate(), getPaymentYearFraction(), getNotional(), rate); } @Override public String toString() { return super.toString() + " *Fixed coupon* Rate = " + _rate + ", Amount = " + _amount; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); long temp; temp = Double.doubleToLongBits(_amount); result = prime * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(_rate); result = prime * result + (int) (temp ^ (temp >>> 32)); return result; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (getClass() != obj.getClass()) { return false; } final CouponFixedDefinition other = (CouponFixedDefinition) obj; if (Double.doubleToLongBits(_amount) != Double.doubleToLongBits(other._amount)) { return false; } if (Double.doubleToLongBits(_rate) != Double.doubleToLongBits(other._rate)) { return false; } return true; } @Override public CouponFixed toDerivative(final ZonedDateTime date) { ArgumentChecker.notNull(date, "date"); ArgumentChecker.isTrue(!date.isAfter(getPaymentDate()), "date {} is after payment date {}", date, getPaymentDate()); // Required: reference date <= payment date final double paymentTime = TimeCalculator.getTimeBetween(date, getPaymentDate()); return new CouponFixed(getCurrency(), paymentTime, getPaymentYearFraction(), getNotional(), getRate(), getAccrualStartDate(), getAccrualEndDate()); } @Override public <U, V> V accept(final InstrumentDefinitionVisitor<U, V> visitor, final U data) { ArgumentChecker.notNull(visitor, "visitor"); return visitor.visitCouponFixedDefinition(this, data); } @Override public <V> V accept(final InstrumentDefinitionVisitor<?, V> visitor) { ArgumentChecker.notNull(visitor, "visitor"); return visitor.visitCouponFixedDefinition(this); } }