/**
* 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;
import java.util.Iterator;
import org.apache.commons.lang.Validate;
import com.opengamma.timeseries.DoubleTimeSeries;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.time.Expiry;
/**
*
* Definition for a fade-in option. The payoff of the option is the same as that
* for a standard option with the size of the payoff weighted by how many
* times the asset price was inside a pre-defined range <i>(L, U)</i>
*
*/
public class FadeInOptionDefinition extends OptionDefinition {
private final OptionPayoffFunction<StandardOptionWithSpotTimeSeriesDataBundle> _payoffFunction = new OptionPayoffFunction<StandardOptionWithSpotTimeSeriesDataBundle>() {
@Override
public double getPayoff(final StandardOptionWithSpotTimeSeriesDataBundle data, final Double optionPrice) {
Validate.notNull(data);
Validate.notNull(data.getSpotTimeSeries());
final DoubleTimeSeries<?> spotTS = data.getSpotTimeSeries();
final Iterator<Double> iter = spotTS.valuesIterator();
int inRange = 0;
double value = 0;
while (iter.hasNext()) {
value = iter.next();
if (value > getLowerBound() && value < getUpperBound()) {
inRange++;
}
}
return inRange * (isCall() ? Math.max(0, data.getSpot() - getStrike()) : Math.max(0, getStrike() - data.getSpot())) / spotTS.size();
}
};
private final OptionExerciseFunction<StandardOptionWithSpotTimeSeriesDataBundle> _exerciseFunction = new EuropeanExerciseFunction<>();
private final double _lowerBound;
private final double _upperBound;
public FadeInOptionDefinition(final double strike, final Expiry expiry, final boolean isCall, final double lowerBound, final double upperBound) {
super(strike, expiry, isCall);
ArgumentChecker.notNegative(lowerBound, "lower bound");
ArgumentChecker.notNegative(upperBound, "upper bound");
if (upperBound < lowerBound) {
throw new IllegalArgumentException("Upper bound was less than lower bound");
}
_lowerBound = lowerBound;
_upperBound = upperBound;
}
public double getLowerBound() {
return _lowerBound;
}
public double getUpperBound() {
return _upperBound;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
long temp;
temp = Double.doubleToLongBits(_lowerBound);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(_upperBound);
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 FadeInOptionDefinition other = (FadeInOptionDefinition) obj;
if (Double.doubleToLongBits(_lowerBound) != Double.doubleToLongBits(other._lowerBound)) {
return false;
}
if (Double.doubleToLongBits(_upperBound) != Double.doubleToLongBits(other._upperBound)) {
return false;
}
return true;
}
@SuppressWarnings("unchecked")
@Override
public OptionExerciseFunction<StandardOptionWithSpotTimeSeriesDataBundle> getExerciseFunction() {
return _exerciseFunction;
}
@SuppressWarnings("unchecked")
@Override
public OptionPayoffFunction<StandardOptionWithSpotTimeSeriesDataBundle> getPayoffFunction() {
return _payoffFunction;
}
}