/** * 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 org.apache.commons.lang.Validate; import com.opengamma.util.time.Expiry; /** * A capped power option is a power option with a cap on the maximum payoff. * <p> * The exercise style is European. The payoff of these options is: * $$ * \begin{align*} * c &= \min(\max(S^i - K, 0), C) \\ * p &= \min(\max(K - S^i, 0), C) * \end{align*} * $$ * where $K$ is the strike, $i$ is the power ($i > 0$), $C$ is the cap ($C > 0$) * and $S$ is the spot. */ public class CappedPowerOptionDefinition extends OptionDefinition { private final OptionPayoffFunction<StandardOptionDataBundle> _payoffFunction = new OptionPayoffFunction<StandardOptionDataBundle>() { @Override public double getPayoff(final StandardOptionDataBundle data, final Double optionPrice) { Validate.notNull(data); final double spot = data.getSpot(); return isCall() ? Math.min(Math.max(Math.pow(spot, getPower()) - getStrike(), 0), getCap()) : Math.min(Math.max(getStrike() - Math.pow(spot, getPower()), 0), getCap()); } }; private final OptionExerciseFunction<StandardOptionDataBundle> _exerciseFunction = new EuropeanExerciseFunction<>(); private final double _power; private final double _cap; /** * * @param strike The strike * @param expiry The expiry * @param power The power, not negative * @param cap The cap, not negative * @param isCall Is the option a put or call */ public CappedPowerOptionDefinition(final double strike, final Expiry expiry, final double power, final double cap, final boolean isCall) { super(strike, expiry, isCall); Validate.isTrue(power > 0, "power must be > 0"); Validate.isTrue(cap > 0, "cap must be > 0"); if (!isCall && cap > strike) { throw new IllegalArgumentException("Cannot have cap larger than strike for a put"); } _power = power; _cap = cap; } /** * @return The power. */ public double getPower() { return _power; } /** * @return The cap. */ public double getCap() { return _cap; } /** * {@inheritDoc} */ @Override public OptionExerciseFunction<StandardOptionDataBundle> getExerciseFunction() { return _exerciseFunction; } /** * {@inheritDoc} */ @Override public OptionPayoffFunction<StandardOptionDataBundle> getPayoffFunction() { return _payoffFunction; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); long temp; temp = Double.doubleToLongBits(_cap); result = prime * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(_power); 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 CappedPowerOptionDefinition other = (CappedPowerOptionDefinition) obj; if (Double.doubleToLongBits(_cap) != Double.doubleToLongBits(other._cap)) { return false; } if (Double.doubleToLongBits(_power) != Double.doubleToLongBits(other._power)) { return false; } return true; } }