com.opengamma.analytics.financial.model.option.definition.SimpleChooserOptionDefinition.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.analytics.financial.model.option.definition.SimpleChooserOptionDefinition.java

Source

/**
 * 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.Collections;
import java.util.Set;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.Validate;

import com.opengamma.analytics.financial.greeks.Greek;
import com.opengamma.analytics.financial.model.option.pricing.analytic.AnalyticOptionModel;
import com.opengamma.analytics.financial.model.option.pricing.analytic.BlackScholesMertonModel;
import com.opengamma.util.time.Expiry;

/**
 * A simple chooser option gives the holder the right to choose whether the
 * option is to be a standard call or put (both with the same expiry) after a
 * certain time. The exercise style of the option, once the choice has been
 * made, is European.
 * <p>
 * The payoff of this option is:
 * $$
 * \begin{align*}
 * \mathrm{payoff} = \max(c_{BSM}(S, K, T_2), p_{BSM}(S, K, T_2))
 * \end{align*}
 * $$
 * where $c_{BSM}$ is the general Black-Scholes Merton call price, $c_{BSM}$ is
 * the general Black-Scholes Merton put price (see {@link BlackScholesMertonModel}),
 * $K$ is the strike, $S$ is the spot and $T_2$ is the time to expiry of the
 * underlying option.
 */

public class SimpleChooserOptionDefinition extends OptionDefinition {
    /** The payoff function */
    private final OptionPayoffFunction<StandardOptionDataBundle> _payoffFunction = new OptionPayoffFunction<StandardOptionDataBundle>() {

        @SuppressWarnings("synthetic-access")
        @Override
        public double getPayoff(final StandardOptionDataBundle data, final Double optionPrice) {
            Validate.notNull(data);
            final double callPrice = BSM.getGreeks(getCallDefinition(), data, GREEKS).get(Greek.FAIR_PRICE);
            final double putPrice = BSM.getGreeks(getPutDefinition(), data, GREEKS).get(Greek.FAIR_PRICE);
            return Math.max(callPrice, putPrice);
        }
    };
    /** The exercise function */
    private final OptionExerciseFunction<StandardOptionDataBundle> _exerciseFunction = new EuropeanExerciseFunction<>();
    /** The strike of the underlying option */
    private final double _underlyingStrike;
    /** The expiry of the underlying option */
    private final Expiry _underlyingExpiry;
    /** The underlying call */
    private final OptionDefinition _callDefinition;
    /** The underlying put */
    private final OptionDefinition _putDefinition;
    /** Black-Scholes Merton model */
    private static final AnalyticOptionModel<OptionDefinition, StandardOptionDataBundle> BSM = new BlackScholesMertonModel();
    /** The greeks that can be computed */
    private static final Set<Greek> GREEKS = Collections.singleton(Greek.FAIR_PRICE);

    /**
     * @param chooseDate The date when the choice is to be made (i.e. the chooser option expiry)
     * @param underlyingStrike The strike of the underlying option
     * @param underlyingExpiry The expiry of the underlying European option
     */
    public SimpleChooserOptionDefinition(final Expiry chooseDate, final double underlyingStrike,
            final Expiry underlyingExpiry) {
        super(null, chooseDate, null);
        Validate.notNull(underlyingExpiry);
        Validate.isTrue(underlyingStrike > 0, "underlying strike");
        if (underlyingExpiry.getExpiry().isBefore(chooseDate.getExpiry())) {
            throw new IllegalArgumentException("Underlying option expiry must be after the choice date");
        }
        _underlyingStrike = underlyingStrike;
        _underlyingExpiry = underlyingExpiry;
        _callDefinition = new EuropeanVanillaOptionDefinition(underlyingStrike, underlyingExpiry, true);
        _putDefinition = new EuropeanVanillaOptionDefinition(underlyingStrike, underlyingExpiry, false);
    }

    /**
     * @return The underlying call definition
     */
    public OptionDefinition getCallDefinition() {
        return _callDefinition;
    }

    /**
     * @return The underlying put definition
     */
    public OptionDefinition getPutDefinition() {
        return _putDefinition;
    }

    /**
     * @return The strike of the underlying option
     */
    public double getUnderlyingStrike() {
        return _underlyingStrike;
    }

    /**
     * @return The expiry of the underlying option
     */
    public Expiry getUnderlyingExpiry() {
        return _underlyingExpiry;
    }

    /**
     * {@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();
        result = prime * result + ((_underlyingExpiry == null) ? 0 : _underlyingExpiry.hashCode());
        long temp;
        temp = Double.doubleToLongBits(_underlyingStrike);
        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 SimpleChooserOptionDefinition other = (SimpleChooserOptionDefinition) obj;
        if (Double.doubleToLongBits(_underlyingStrike) != Double.doubleToLongBits(other._underlyingStrike)) {
            return false;
        }
        return ObjectUtils.equals(_underlyingExpiry, other._underlyingExpiry);
    }
}