/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.model.option.definition.twoasset;
import org.apache.commons.lang.Validate;
import com.opengamma.analytics.financial.model.option.definition.EuropeanExerciseFunction;
import com.opengamma.analytics.financial.model.option.definition.OptionDefinition;
import com.opengamma.analytics.financial.model.option.definition.OptionExerciseFunction;
import com.opengamma.analytics.financial.model.option.definition.OptionPayoffFunction;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.time.Expiry;
/**
* Defines a European-style exchange-one-asset-for-another option. The holder
* can exchange an amount $Q_1$ of the first underlying for an amount $Q_2$ of
* the second underlying.
* <p>
* The payoff of this option is:
* $$
* \begin{eqnarray*}
* max\left(Q_1S_1 - Q_2S_2, 0\right)
* \end{eqnarray*}
* $$
* where $Q_1$ is the quantity of the first asset, $S_1$ is the spot price of
* the first underlying, $Q_2$ is the quantity of the second asset and $S_2$ is
* the spot price of the second underlying.
*/
public class EuropeanExchangeAssetOptionDefinition extends OptionDefinition {
private final OptionExerciseFunction<StandardTwoAssetOptionDataBundle> _exerciseFunction = new EuropeanExerciseFunction<>();
private final OptionPayoffFunction<StandardTwoAssetOptionDataBundle> _payoffFunction = new OptionPayoffFunction<StandardTwoAssetOptionDataBundle>() {
@SuppressWarnings("synthetic-access")
@Override
public double getPayoff(final StandardTwoAssetOptionDataBundle data, final Double optionPrice) {
Validate.notNull(data, "data");
final double s1 = data.getFirstSpot();
final double s2 = data.getSecondSpot();
return Math.max(_firstQuantity * s1 - _secondQuantity * s2, 0);
}
};
private final double _firstQuantity;
private final double _secondQuantity;
/**
*
* @param expiry The expiry
* @param firstQuantity The quantity of the first asset
* @param secondQuantity The quantity of the second asset
*/
public EuropeanExchangeAssetOptionDefinition(final Expiry expiry, final double firstQuantity, final double secondQuantity) {
super(null, expiry, null);
ArgumentChecker.notNegativeOrZero(firstQuantity, "quantity 1");
ArgumentChecker.notNegativeOrZero(secondQuantity, "quantity 2");
_firstQuantity = firstQuantity;
_secondQuantity = secondQuantity;
}
/**
*
* @return The quantity of the first asset
*/
public double getFirstQuantity() {
return _firstQuantity;
}
/**
*
* @return The quantity of the second asset
*/
public double getSecondQuantity() {
return _secondQuantity;
}
/**
* The exercise function of this option is European (see {@link EuropeanExerciseFunction})
* @return The exercise function
*/
@SuppressWarnings("unchecked")
@Override
public OptionExerciseFunction<StandardTwoAssetOptionDataBundle> getExerciseFunction() {
return _exerciseFunction;
}
/**
* @return The payoff function
*/
@SuppressWarnings("unchecked")
@Override
public OptionPayoffFunction<StandardTwoAssetOptionDataBundle> getPayoffFunction() {
return _payoffFunction;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
long temp;
temp = Double.doubleToLongBits(_firstQuantity);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(_secondQuantity);
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 EuropeanExchangeAssetOptionDefinition other = (EuropeanExchangeAssetOptionDefinition) obj;
if (Double.doubleToLongBits(_firstQuantity) != Double.doubleToLongBits(other._firstQuantity)) {
return false;
}
if (Double.doubleToLongBits(_secondQuantity) != Double.doubleToLongBits(other._secondQuantity)) {
return false;
}
return true;
}
}