/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.forex.definition; import org.apache.commons.lang.ObjectUtils; import org.threeten.bp.ZonedDateTime; import com.opengamma.analytics.financial.forex.derivative.Forex; import com.opengamma.analytics.financial.instrument.InstrumentDefinition; import com.opengamma.analytics.financial.instrument.InstrumentDefinitionVisitor; import com.opengamma.analytics.financial.instrument.payment.PaymentFixedDefinition; import com.opengamma.analytics.financial.interestrate.InstrumentDerivative; import com.opengamma.analytics.financial.interestrate.payments.derivative.PaymentFixed; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.money.Currency; /** * Class describing a foreign exchange transaction (spot or forward). */ public class ForexDefinition implements InstrumentDefinition<InstrumentDerivative> { /** * The payment in the first currency. */ private final PaymentFixedDefinition _paymentCurrency1; /** * The payment in the second currency. */ private final PaymentFixedDefinition _paymentCurrency2; /** * Constructor from the financial details. * @param currency1 The first currency. * @param currency2 The second currency. * @param exchangeDate The date of the exchange. * @param amountCurrency1 The amount in the first currency. * @param fxRate The forex rate, understood as 1.0 Currency1 is exchanged for fxRate Currency2. The amount in Currency2 will be -amountCurrency1*fxRate. */ public ForexDefinition(final Currency currency1, final Currency currency2, final ZonedDateTime exchangeDate, final double amountCurrency1, final double fxRate) { ArgumentChecker.notNull(currency1, "Currency 1"); ArgumentChecker.notNull(currency2, "Currency 2"); ArgumentChecker.notNull(exchangeDate, "Exchange date"); ArgumentChecker.isTrue(fxRate > 0, "FX rate for {}/{} on {} must be positive. Found {}.", currency1, currency2, exchangeDate, fxRate); _paymentCurrency1 = new PaymentFixedDefinition(currency1, exchangeDate, amountCurrency1); _paymentCurrency2 = new PaymentFixedDefinition(currency2, exchangeDate, -amountCurrency1 * fxRate); } /** * Constructor from two fixed payments. The payments should take place on the same date. The signs of the amounts should be opposite. * @param paymentCurrency1 The first currency payment. * @param paymentCurrency2 The second currency payment. */ public ForexDefinition(final PaymentFixedDefinition paymentCurrency1, final PaymentFixedDefinition paymentCurrency2) { ArgumentChecker.notNull(paymentCurrency1, "Payment 1"); ArgumentChecker.notNull(paymentCurrency2, "Payment 2"); ZonedDateTime paymentDate1 = paymentCurrency1.getPaymentDate(); ZonedDateTime paymentDate2 = paymentCurrency2.getPaymentDate(); ArgumentChecker.isTrue(paymentDate1.equals(paymentDate2), "Payments on different date. {} and {}.", paymentCurrency1, paymentCurrency2); double referenceAmount1 = paymentCurrency1.getReferenceAmount(); double referenceAmount2 = paymentCurrency2.getReferenceAmount(); ArgumentChecker.isTrue((referenceAmount1 * referenceAmount2) <= 0, "Payments with same sign. {} and {}", paymentCurrency1, paymentCurrency2); this._paymentCurrency1 = paymentCurrency1; this._paymentCurrency2 = paymentCurrency2; } /** * Constructor from the financial details. * @param currency1 The first currency. * @param currency2 The second currency. * @param exchangeDate The date of the exchange. * @param amountCurrency1 The amount in the first currency. * @param amountCurrency2 The amount in the second currency. * @return The Forex transaction. */ public static ForexDefinition fromAmounts(final Currency currency1, final Currency currency2, final ZonedDateTime exchangeDate, final double amountCurrency1, final double amountCurrency2) { ArgumentChecker.notNull(currency1, "Currency 1"); ArgumentChecker.notNull(currency2, "Currency 2"); ArgumentChecker.notNull(exchangeDate, "Exchange date"); final PaymentFixedDefinition paymentCurrency1 = new PaymentFixedDefinition(currency1, exchangeDate, amountCurrency1); final PaymentFixedDefinition paymentCurrency2 = new PaymentFixedDefinition(currency2, exchangeDate, amountCurrency2); return new ForexDefinition(paymentCurrency1, paymentCurrency2); } /** * Gets the payment in the first currency. * @return The payment in the first currency. */ public PaymentFixedDefinition getPaymentCurrency1() { return _paymentCurrency1; } /** * Gets the payment in the second currency. * @return The payment in the second currency. */ public PaymentFixedDefinition getPaymentCurrency2() { return _paymentCurrency2; } /** * Gets the first currency. * @return The currency. */ public Currency getCurrency1() { return _paymentCurrency1.getCurrency(); } /** * Gets the second currency. * @return The currency. */ public Currency getCurrency2() { return _paymentCurrency2.getCurrency(); } /** * Gets the exchange date. * @return The exchange date. */ public ZonedDateTime getExchangeDate() { return _paymentCurrency2.getPaymentDate(); } @Override public Forex toDerivative(final ZonedDateTime date) { ArgumentChecker.notNull(date, "date"); final PaymentFixed payment1 = _paymentCurrency1.toDerivative(date); final PaymentFixed payment2 = _paymentCurrency2.toDerivative(date); return new Forex(payment1, payment2); } @Override public <U, V> V accept(final InstrumentDefinitionVisitor<U, V> visitor, final U data) { ArgumentChecker.notNull(visitor, "visitor"); return visitor.visitForexDefinition(this, data); } @Override public <V> V accept(final InstrumentDefinitionVisitor<?, V> visitor) { ArgumentChecker.notNull(visitor, "visitor"); return visitor.visitForexDefinition(this); } @Override public String toString() { String result = "Forex transaction:"; result += "\nCurrency 1 payment: " + _paymentCurrency1.toString(); result += "\nCurrency 2 payment: " + _paymentCurrency2.toString(); return result; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + _paymentCurrency1.hashCode(); result = prime * result + _paymentCurrency2.hashCode(); return result; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final ForexDefinition other = (ForexDefinition) obj; if (!ObjectUtils.equals(_paymentCurrency1, other._paymentCurrency1)) { return false; } if (!ObjectUtils.equals(_paymentCurrency2, other._paymentCurrency2)) { return false; } return true; } }