/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate.payments.derivative; import org.apache.commons.lang.ObjectUtils; import com.opengamma.analytics.financial.interestrate.InstrumentDerivativeVisitor; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.Currency; /** * Class describing a fixed payment coupon with FX reset. * The currency is the currency of the payment. * The notional is expressed in the reference currency, from which the FX reset will be computed. * The payment is (getNotional() * FX(at FX reset date) * _rate * getPaymentYearFraction()) * For exact description of the instrument, see reference. * <P> * Reference: Coupon with FX Reset Notional, OpenGamma Documentation 26, September 2014. */ public class CouponFixedFxReset extends Coupon { // TODO: nominal exchange? /** The fixed rate of the fixed coupon. */ private final double _rate; /** The reference currency. */ private final Currency _referenceCurrency; /** The FX fixing time. The notional used for the payment is the FX rate between the reference currency (RC) and the * payment currency (PC): 1 RC = X . PC. */ private final double _fxFixingTime; /** The spot (delivery) time for the FX transaction underlying the FX fixing. */ private final double _fxDeliveryTime; /** * Constructor of the coupon. * @param currency The payment currency. * @param paymentTime Time (in years) up to the payment. * @param paymentAccrualFactor Accrual factor of the accrual period. * @param notional Coupon notional in the reference currency. * @param rate Fixed rate. * @param referenceCurrency The reference currency for the FX reset. Not null. * @param fxFixingTime The FX fixing date. The notional used for the payment is the FX rate between the reference * currency (RC) and the payment currency (PC): 1 RC = X . PC. * @param fxDeliveryTime The spot or delivery date for the FX transaction underlying the FX fixing. */ public CouponFixedFxReset(Currency currency, double paymentTime, double paymentAccrualFactor, double notional, double rate, Currency referenceCurrency, double fxFixingTime, double fxDeliveryTime) { super(currency, paymentTime, paymentAccrualFactor, notional); ArgumentChecker.notNull(referenceCurrency, "reference currency"); _rate = rate; _referenceCurrency = referenceCurrency; _fxFixingTime = fxFixingTime; _fxDeliveryTime = fxDeliveryTime; } /** * Returns the amount paid for a given FX reset rate. * @param fxRate The exchange rate between the reference currency (RC) and the payment currency (PC): 1 RC = X . PC. * @return The amount. */ public double paymentAmount(double fxRate) { return getNotional() * fxRate * _rate * getPaymentYearFraction(); } /** * Returns the fixed rate. * @return The rate. */ public double getRate() { return _rate; } /** * Returns the reference currency. * @return The currency. */ public Currency getReferenceCurrency() { return _referenceCurrency; } /** * Returns the FX fixing time. * @return The time. */ public double getFxFixingTime() { return _fxFixingTime; } /** * Returns the FX delivery time. * @return The time. */ public double getFxDeliveryTime() { return _fxDeliveryTime; } @Override public <S, T> T accept(InstrumentDerivativeVisitor<S, T> visitor, S data) { ArgumentChecker.notNull(visitor, "visitor"); return visitor.visitCouponFixedFxReset(this, data); } @Override public <T> T accept(InstrumentDerivativeVisitor<?, T> visitor) { ArgumentChecker.notNull(visitor, "visitor"); return visitor.visitCouponFixedFxReset(this); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); long temp; temp = Double.doubleToLongBits(_fxFixingTime); result = prime * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(_fxDeliveryTime); result = prime * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(_rate); result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + _referenceCurrency.hashCode(); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } CouponFixedFxReset other = (CouponFixedFxReset) obj; if (Double.doubleToLongBits(_fxFixingTime) != Double.doubleToLongBits(other._fxFixingTime)) { return false; } if (Double.doubleToLongBits(_fxDeliveryTime) != Double.doubleToLongBits(other._fxDeliveryTime)) { return false; } if (Double.doubleToLongBits(_rate) != Double.doubleToLongBits(other._rate)) { return false; } if (!ObjectUtils.equals(_referenceCurrency, other._referenceCurrency)) { return false; } return true; } @Override public Coupon withNotional(double notional) { throw new UnsupportedOperationException("CouponFixedFXReset does not support withNotional method."); } }