/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.provider.calculator.generic;
import com.opengamma.analytics.financial.forex.derivative.Forex;
import com.opengamma.analytics.financial.forex.derivative.ForexNonDeliverableForward;
import com.opengamma.analytics.financial.forex.derivative.ForexOptionDigital;
import com.opengamma.analytics.financial.forex.derivative.ForexOptionSingleBarrier;
import com.opengamma.analytics.financial.forex.derivative.ForexOptionVanilla;
import com.opengamma.analytics.financial.forex.derivative.ForexSwap;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivativeVisitorAdapter;
import com.opengamma.analytics.financial.interestrate.annuity.derivative.Annuity;
import com.opengamma.analytics.financial.interestrate.annuity.derivative.AnnuityCouponFixed;
import com.opengamma.analytics.financial.interestrate.cash.derivative.Cash;
import com.opengamma.analytics.financial.interestrate.cash.derivative.DepositCounterpart;
import com.opengamma.analytics.financial.interestrate.cash.derivative.DepositZero;
import com.opengamma.analytics.financial.interestrate.fra.derivative.ForwardRateAgreement;
import com.opengamma.analytics.financial.interestrate.future.derivative.InterestRateFutureOptionMarginTransaction;
import com.opengamma.analytics.financial.interestrate.future.derivative.InterestRateFutureTransaction;
import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponFixed;
import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponFixedAccruedCompounding;
import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponIbor;
import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponIborGearing;
import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponIborSpread;
import com.opengamma.analytics.financial.interestrate.payments.derivative.CouponON;
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.derivative.PaymentFixed;
import com.opengamma.analytics.financial.interestrate.swap.derivative.Swap;
import com.opengamma.analytics.financial.interestrate.swap.derivative.SwapFixedCoupon;
import com.opengamma.analytics.financial.interestrate.swaption.derivative.SwaptionCashFixedIbor;
import com.opengamma.analytics.financial.interestrate.swaption.derivative.SwaptionPhysicalFixedIbor;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.money.MultipleCurrencyAmount;
/**
* Calculates the payment amounts due on the valuation date (|time to payment|<small).
*/
public final class TodayPaymentCalculator extends InstrumentDerivativeVisitorAdapter<Void, MultipleCurrencyAmount> {
/**
* The default time limit below which the payment is consider as being today.
*/
private static final double DEFAULT_TIME_LIMIT_TODAY = 0.002;
/**
* The method unique instance.
*/
private static final TodayPaymentCalculator INSTANCE = new TodayPaymentCalculator(DEFAULT_TIME_LIMIT_TODAY);
/**
* Return the unique instance of the class.
* @return The instance.
*/
public static TodayPaymentCalculator getInstance() {
return INSTANCE;
}
/**
* Primary constructor
* Note on negative timeLimits: toDerivative functions often drop past payments so using this calculator with timeLimits < -1dy may have unexpected impacts.
* @param timeLimit the horizon in years, either positive (forward looking) or negative (backward looking) in which the calculator returns payment amounts
* @return the calculator
*/
public static TodayPaymentCalculator getInstance(final double timeLimit) {
return new TodayPaymentCalculator(timeLimit);
}
private final double _timeLimit;
/**
* Constructor.
*/
private TodayPaymentCalculator(final double timeLimit) {
_timeLimit = timeLimit;
}
/**
* // We wish to add payments if they occur within the time horizon, which may be forward, or backward, in time
* @param paymentTime the payment time in question
* @return true if the payment is to be counted as happening within the time limit / horizon
*/
private boolean isWithinLimit(final double paymentTime) {
return (Math.abs(paymentTime) < Math.abs(_timeLimit) && _timeLimit * paymentTime >= 0);
}
// ----- Deposit -----
@Override
public MultipleCurrencyAmount visitCash(final Cash deposit) {
ArgumentChecker.notNull(deposit, "instrument");
MultipleCurrencyAmount cash = MultipleCurrencyAmount.of(deposit.getCurrency(), 0.0);
if (isWithinLimit(deposit.getStartTime())) {
cash = cash.plus(deposit.getCurrency(), -deposit.getInitialAmount());
}
if (isWithinLimit(deposit.getEndTime())) {
cash = cash.plus(deposit.getCurrency(), deposit.getNotional() + deposit.getInterestAmount());
}
return cash;
}
@Override
public MultipleCurrencyAmount visitDepositZero(final DepositZero deposit) {
ArgumentChecker.notNull(deposit, "instrument");
MultipleCurrencyAmount cash = MultipleCurrencyAmount.of(deposit.getCurrency(), 0.0);
if (isWithinLimit(deposit.getStartTime())) {
cash = cash.plus(deposit.getCurrency(), -deposit.getInitialAmount());
}
if (isWithinLimit(deposit.getEndTime())) {
cash = cash.plus(deposit.getCurrency(), deposit.getNotional() + deposit.getInterestAmount());
}
return cash;
}
@Override
public MultipleCurrencyAmount visitDepositCounterpart(final DepositCounterpart deposit) {
ArgumentChecker.notNull(deposit, "instrument");
MultipleCurrencyAmount cash = MultipleCurrencyAmount.of(deposit.getCurrency(), 0.0);
if (isWithinLimit(deposit.getStartTime())) {
cash = cash.plus(deposit.getCurrency(), -deposit.getInitialAmount());
}
if (isWithinLimit(deposit.getEndTime())) {
cash = cash.plus(deposit.getCurrency(), deposit.getNotional() + deposit.getInterestAmount());
}
return cash;
}
@Override
public MultipleCurrencyAmount visitForwardRateAgreement(final ForwardRateAgreement fra) {
ArgumentChecker.notNull(fra, "instrument");
return MultipleCurrencyAmount.of(fra.getCurrency(), 0.0);
}
@Override
public MultipleCurrencyAmount visitInterestRateFutureTransaction(final InterestRateFutureTransaction future) {
ArgumentChecker.notNull(future, "instrument");
return MultipleCurrencyAmount.of(future.getCurrency(), 0.0);
}
@Override
public MultipleCurrencyAmount visitInterestRateFutureOptionMarginTransaction(final InterestRateFutureOptionMarginTransaction futureOption) {
ArgumentChecker.notNull(futureOption, "instrument");
return MultipleCurrencyAmount.of(futureOption.getUnderlyingSecurity().getCurrency(), 0.0);
}
@Override
public MultipleCurrencyAmount visitCouponFixed(final CouponFixed payment) {
ArgumentChecker.notNull(payment, "instrument");
MultipleCurrencyAmount cash = MultipleCurrencyAmount.of(payment.getCurrency(), 0.0);
if (isWithinLimit(payment.getPaymentTime())) {
cash = cash.plus(payment.getCurrency(), payment.getAmount());
}
return cash;
}
@Override
public MultipleCurrencyAmount visitFixedPayment(final PaymentFixed payment) {
ArgumentChecker.notNull(payment, "instrument");
MultipleCurrencyAmount cash = MultipleCurrencyAmount.of(payment.getCurrency(), 0.0);
if (isWithinLimit(payment.getPaymentTime())) {
cash = cash.plus(payment.getCurrency(), payment.getAmount());
}
return cash;
}
@Override
public MultipleCurrencyAmount visitCouponIbor(final CouponIbor payment) {
ArgumentChecker.notNull(payment, "instrument");
return MultipleCurrencyAmount.of(payment.getCurrency(), 0.0);
}
@Override
public MultipleCurrencyAmount visitCouponIborSpread(final CouponIborSpread payment) {
ArgumentChecker.notNull(payment, "instrument");
return MultipleCurrencyAmount.of(payment.getCurrency(), 0.0);
}
@Override
public MultipleCurrencyAmount visitCouponIborGearing(final CouponIborGearing payment) {
ArgumentChecker.notNull(payment, "instrument");
return MultipleCurrencyAmount.of(payment.getCurrency(), 0.0);
}
@Override
public MultipleCurrencyAmount visitCouponOIS(final CouponON payment) {
ArgumentChecker.notNull(payment, "instrument");
return MultipleCurrencyAmount.of(payment.getCurrency(), 0.0);
}
@Override
public MultipleCurrencyAmount visitCouponFixedAccruedCompounding(final CouponFixedAccruedCompounding payment) {
ArgumentChecker.notNull(payment, "instrument");
return MultipleCurrencyAmount.of(payment.getCurrency(), 0.0);
}
@Override
public MultipleCurrencyAmount visitCouponONCompounded(final CouponONCompounded payment) {
ArgumentChecker.notNull(payment, "instrument");
return MultipleCurrencyAmount.of(payment.getCurrency(), 0.0);
}
@Override
public MultipleCurrencyAmount visitGenericAnnuity(final Annuity<? extends Payment> annuity) {
ArgumentChecker.notNull(annuity, "instrument");
MultipleCurrencyAmount pv = MultipleCurrencyAmount.of(annuity.getCurrency(), 0.0);
for (final Payment p : annuity.getPayments()) {
pv = pv.plus(p.accept(this));
}
return pv;
}
@Override
public MultipleCurrencyAmount visitFixedCouponAnnuity(final AnnuityCouponFixed annuity) {
return visitGenericAnnuity(annuity);
}
@Override
public MultipleCurrencyAmount visitSwap(final Swap<?, ?> swap) {
ArgumentChecker.notNull(swap, "instrument");
final MultipleCurrencyAmount cash = swap.getFirstLeg().accept(this);
return cash.plus(swap.getSecondLeg().accept(this));
}
@Override
public MultipleCurrencyAmount visitFixedCouponSwap(final SwapFixedCoupon<?> swap) {
return visitSwap(swap);
}
@Override
public MultipleCurrencyAmount visitSwaptionPhysicalFixedIbor(final SwaptionPhysicalFixedIbor swaption) {
ArgumentChecker.notNull(swaption, "instrument");
return MultipleCurrencyAmount.of(swaption.getCurrency(), 0.0);
}
@Override
public MultipleCurrencyAmount visitSwaptionCashFixedIbor(final SwaptionCashFixedIbor swaption) {
ArgumentChecker.notNull(swaption, "instrument");
return MultipleCurrencyAmount.of(swaption.getCurrency(), 0.0);
}
@Override
public MultipleCurrencyAmount visitForex(final Forex forex) {
ArgumentChecker.notNull(forex, "instrument");
return visitFixedPayment(forex.getPaymentCurrency1()).plus(visitFixedPayment(forex.getPaymentCurrency2()));
}
@Override
public MultipleCurrencyAmount visitForexSwap(final ForexSwap forex) {
ArgumentChecker.notNull(forex, "instrument");
return visitForex(forex.getNearLeg()).plus(visitForex(forex.getFarLeg()));
}
@Override
public MultipleCurrencyAmount visitForexOptionVanilla(final ForexOptionVanilla forex) {
ArgumentChecker.notNull(forex, "instrument");
return MultipleCurrencyAmount.of(forex.getCurrency1(), 0.0);
}
@Override
public MultipleCurrencyAmount visitForexOptionSingleBarrier(final ForexOptionSingleBarrier forex) {
ArgumentChecker.notNull(forex, "instrument");
return MultipleCurrencyAmount.of(forex.getCurrency1(), 0.0);
}
@Override
public MultipleCurrencyAmount visitForexOptionDigital(final ForexOptionDigital forex) {
ArgumentChecker.notNull(forex, "instrument");
return MultipleCurrencyAmount.of(forex.getCurrency1(), 0.0);
}
@Override
public MultipleCurrencyAmount visitForexNonDeliverableForward(final ForexNonDeliverableForward forex) {
ArgumentChecker.notNull(forex, "instrument");
return MultipleCurrencyAmount.of(forex.getCurrency1(), 0.0);
}
}