EuropeanOption.java
package net.finmath.tree.assetderivativevaluation.products;
import java.util.function.DoubleUnaryOperator;
import net.finmath.modelling.products.CallOrPut;
import net.finmath.stochastic.RandomVariable;
import net.finmath.tree.TreeModel;
/**
* Implements the valuation of a European option on a single asset.
*
* Given a model for an asset <i>S</i>, the European option with strike <i>K</i>, maturity <i>T</i>
* pays
* <br>
* <i>V(T) = max((S(T) - K) * CallOrPut , 0)</i> in <i>T</i>.
* <br>
*
* @author Alessandro Gnoatto
*/
public class EuropeanOption extends AbstractNonPathDependentProduct {
private final double maturity;
private final double strike;
private final CallOrPut callOrPutSign;
private final String underlyingName;
/**
* Construct a product representing an European option on an asset S (where S the asset with index <code>underlyingIndex</code> from the model - single asset case).
* @param underlyingName Name of the underlying
* @param maturity The maturity T in the option payoff max(sign * (S(T)-K),0).
* @param strike The strike K in the option payoff max(sign * (S(T)-K),0).
* @param callOrPutSign The sign in the payoff.
*/
public EuropeanOption(final String underlyingName, final double maturity, final double strike, final double callOrPutSign) {
super(maturity);
this.underlyingName = underlyingName;
this.maturity = maturity;
this.strike = strike;
if(callOrPutSign == 1.0) {
this.callOrPutSign = CallOrPut.CALL;
}else if(callOrPutSign == - 1.0) {
this.callOrPutSign = CallOrPut.PUT;
}else {
throw new IllegalArgumentException("Unknown option type");
}
}
/**
* Construct a product representing an European option on an asset S (where S the asset with index <code>underlyingIndex</code> from the model - single asset case).
* @param underlyingName Name of the underlying
* @param maturity The maturity T in the option payoff max(sign * (S(T)-K),0).
* @param strike The strike K in the option payoff max(sign * (S(T)-K),0).
* @param callOrPutSign The sign in the payoff.
*/
public EuropeanOption(final String underlyingName, final double maturity, final double strike, final CallOrPut callOrPutSign) {
super(maturity);
this.underlyingName = underlyingName;
this.maturity = maturity;
this.strike = strike;
this.callOrPutSign = callOrPutSign;
}
/**
* Construct a product representing an European option on an asset S (where S the asset with index 0 from the model - single asset case).
* @param maturity The maturity T in the option payoff max(S(T)-K,0)
* @param strike The strike K in the option payoff max(S(T)-K,0).
* @param callOrPutSign The sign in the payoff.
*/
public EuropeanOption(final double maturity, final double strike, final double callOrPutSign) {
super(maturity);
this.maturity = maturity;
this.strike = strike;
if(callOrPutSign == 1.0) {
this.callOrPutSign = CallOrPut.CALL;
}else if(callOrPutSign == - 1.0) {
this.callOrPutSign = CallOrPut.PUT;
}else {
throw new IllegalArgumentException("Unknown option type");
}
this.underlyingName = null; // Use underlyingIndex
}
/**
* Construct a product representing an European option on an asset S (where S the asset with index 0 from the model - single asset case).
* @param maturity The maturity T in the option payoff max(S(T)-K,0)
* @param strike The strike K in the option payoff max(S(T)-K,0).
* @param callOrPutSign The sign in the payoff.
*/
public EuropeanOption(final double maturity, final double strike, final CallOrPut callOrPutSign) {
super(maturity);
this.maturity = maturity;
this.strike = strike;
this.callOrPutSign = callOrPutSign;
this.underlyingName = null; // Use underlyingIndex
}
/**
* Construct a product representing an European option on an asset S (where S the asset with index <code>underlyingIndex</code> from the model - single asset case).
* @param underlyingName Name of the underlying
* @param maturity The maturity T in the option payoff max(S(T)-K,0)
* @param strike The strike K in the option payoff max(S(T)-K,0).
*/
public EuropeanOption(final String underlyingName, final double maturity, final double strike) {
this(underlyingName, maturity, strike, 1.0);
}
/**
* Construct a product representing an European option on an asset S (where S the asset with index 0 from the model - single asset case).
* @param maturity The maturity T in the option payoff max(S(T)-K,0)
* @param strike The strike K in the option payoff max(S(T)-K,0).
*/
public EuropeanOption(final double maturity, final double strike) {
this(maturity, strike, 1.0);
}
@Override
public DoubleUnaryOperator getPayOffFunction(){
if(callOrPutSign == CallOrPut.CALL) {
return assetValue -> Math.max(assetValue - strike, 0);
}else {
return assetValue -> Math.max(strike - assetValue, 0);
}
}
@Override
public RandomVariable[] getValues(double evaluationTime, TreeModel model) {
final int k0 = timeToIndex(evaluationTime,model);
final int n = model.getNumberOfTimes()-1;
final RandomVariable[] values = new RandomVariable[n -k0 +1];
values[n-k0] = model.getTransformedValuesAtGivenTimeRV(model.getLastTime(),this.getPayOffFunction());
for (int timeIndex = n - 1; timeIndex >= k0; timeIndex--) {
values[timeIndex - k0] = model.getConditionalExpectationRV(values[(timeIndex+1)], timeIndex);
}
return values;
}
@Override
public double getMaturity() {
return maturity;
}
public double getStrike() {
return strike;
}
public CallOrPut getCallOrPutSign() {
return callOrPutSign;
}
public String getUnderlyingName() {
return underlyingName;
}
}