/**
* 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.forex.derivative.ForexSwap;
import com.opengamma.analytics.financial.instrument.InstrumentDefinition;
import com.opengamma.analytics.financial.instrument.InstrumentDefinitionVisitor;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivative;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.money.Currency;
/**
* Class describing a Forex swap transaction (with a near and far leg).
*/
public class ForexSwapDefinition implements InstrumentDefinition<InstrumentDerivative> {
/**
* The near leg.
*/
private final ForexDefinition _nearLeg;
/**
* The far leg.
*/
private final ForexDefinition _farLeg;
/**
* Constructor from the two Forex legs.
* @param nearLeg The near leg.
* @param farLeg The far leg.
*/
public ForexSwapDefinition(final ForexDefinition nearLeg, final ForexDefinition farLeg) {
ArgumentChecker.notNull(nearLeg, "Near leg");
ArgumentChecker.notNull(farLeg, "Far leg");
_nearLeg = nearLeg;
_farLeg = farLeg;
}
/**
* Constructor from the financial details.
* @param currency1 The first currency.
* @param currency2 The second currency.
* @param nearDate The near date.
* @param farDate The far date.
* @param amount1 The amount of the near leg in the first currency.
* @param forexRate The near leg forex rate.
* @param forwardPoints The forward points, i.e. the far leg forex rate is forexRate+forwardPoints.
*/
public ForexSwapDefinition(final Currency currency1, final Currency currency2, final ZonedDateTime nearDate, final ZonedDateTime farDate, final double amount1,
final double forexRate, final double forwardPoints) {
ArgumentChecker.notNull(currency1, "Currency 1");
ArgumentChecker.notNull(currency2, "Currency 2");
ArgumentChecker.notNull(nearDate, "Near date");
ArgumentChecker.notNull(farDate, "Far date");
_nearLeg = new ForexDefinition(currency1, currency2, nearDate, amount1, forexRate);
_farLeg = new ForexDefinition(currency1, currency2, farDate, -amount1, forexRate + forwardPoints);
}
/**
* Gets the near leg.
* @return The near leg.
*/
public ForexDefinition getNearLeg() {
return _nearLeg;
}
/**
* Gets the far leg.
* @return The far leg.
*/
public ForexDefinition getFarLeg() {
return _farLeg;
}
/**
* {@inheritDoc}
* The first curve is the discounting curve for the first currency and the second curve is the discounting curve for the second currency.
*/
@Override
public InstrumentDerivative toDerivative(final ZonedDateTime date) {
ArgumentChecker.isTrue(!date.isAfter(_farLeg.getExchangeDate()), "date is after payment far date");
if (date.isAfter(_nearLeg.getExchangeDate())) { // Implementation note: only the far leg left.
return _farLeg.toDerivative(date);
}
final Forex nearLeg = _nearLeg.toDerivative(date);
final Forex farLeg = _farLeg.toDerivative(date);
return new ForexSwap(nearLeg, farLeg);
}
@Override
public <U, V> V accept(final InstrumentDefinitionVisitor<U, V> visitor, final U data) {
ArgumentChecker.notNull(visitor, "visitor");
return visitor.visitForexSwapDefinition(this, data);
}
@Override
public <V> V accept(final InstrumentDefinitionVisitor<?, V> visitor) {
ArgumentChecker.notNull(visitor, "visitor");
return visitor.visitForexSwapDefinition(this);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + _farLeg.hashCode();
result = prime * result + _nearLeg.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 ForexSwapDefinition other = (ForexSwapDefinition) obj;
if (!ObjectUtils.equals(_farLeg, other._farLeg)) {
return false;
}
if (!ObjectUtils.equals(_nearLeg, other._nearLeg)) {
return false;
}
return true;
}
}