com.opengamma.analytics.financial.model.option.pricing.fourier.EuropeanPriceIntegrand.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.analytics.financial.model.option.pricing.fourier.EuropeanPriceIntegrand.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.pricing.fourier;

import static com.opengamma.analytics.math.ComplexMathUtils.add;
import static com.opengamma.analytics.math.ComplexMathUtils.divide;
import static com.opengamma.analytics.math.ComplexMathUtils.exp;
import static com.opengamma.analytics.math.ComplexMathUtils.multiply;
import static com.opengamma.analytics.math.ComplexMathUtils.subtract;
import static com.opengamma.analytics.math.number.ComplexNumber.MINUS_I;

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

import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.BlackFunctionData;
import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.EuropeanVanillaOption;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.number.ComplexNumber;

/**
 * 
 */
public class EuropeanPriceIntegrand {
    private final MartingaleCharacteristicExponent _ce;
    private final double _alpha;
    private final boolean _useVarianceReduction;

    public EuropeanPriceIntegrand(final MartingaleCharacteristicExponent ce, final double alpha,
            final boolean useVarianceReduction) {
        Validate.notNull(ce, "characteristic exponent");
        _ce = ce;
        _alpha = alpha;
        _useVarianceReduction = useVarianceReduction;
    }

    public Function1D<Double, Double> getFunction(final BlackFunctionData data,
            final EuropeanVanillaOption option) {
        Validate.notNull(data, "data");
        Validate.notNull(option, "option");
        final double t = option.getTimeToExpiry();
        final Function1D<ComplexNumber, ComplexNumber> characteristicFunction = _ce.getFunction(t);
        final double k = Math.log(option.getStrike() / data.getForward());
        final double blackVol = data.getBlackVolatility();
        final CharacteristicExponent gaussian;
        final Function1D<ComplexNumber, ComplexNumber> gaussianFunction;
        if (_useVarianceReduction) {
            gaussian = new GaussianCharacteristicExponent(-0.5 * blackVol * blackVol, blackVol);
            gaussianFunction = gaussian.getFunction(t);
        } else {
            gaussian = null;
            gaussianFunction = null;
        }
        return new Function1D<Double, Double>() {

            @Override
            public Double evaluate(final Double x) {
                @SuppressWarnings("synthetic-access")
                final ComplexNumber res = getIntegrand(x, characteristicFunction, gaussianFunction, k);
                return res.getReal();
            }
        };
    }

    private ComplexNumber getIntegrand(final double x, final Function1D<ComplexNumber, ComplexNumber> ce,
            final Function1D<ComplexNumber, ComplexNumber> gaussian, final double k) {
        final ComplexNumber z = new ComplexNumber(x, -1 - _alpha);
        final ComplexNumber num1 = exp(add(new ComplexNumber(0, -x * k), ce.evaluate(z)));
        final ComplexNumber num2 = gaussian == null ? new ComplexNumber(0.0)
                : exp(add(new ComplexNumber(0, -x * k), gaussian.evaluate(z)));
        final ComplexNumber denom = multiply(z, subtract(MINUS_I, z));
        final ComplexNumber res = divide(subtract(num1, num2), denom);
        return res;
    }

    public MartingaleCharacteristicExponent getCharacteristicExponent() {
        return _ce;
    }

    public double getAlpha() {
        return _alpha;
    }

    public boolean useVarianceReduction() {
        return _useVarianceReduction;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        long temp;
        temp = Double.doubleToLongBits(_alpha);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        result = prime * result + _ce.hashCode();
        result = prime * result + (_useVarianceReduction ? 1231 : 1237);
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final EuropeanPriceIntegrand other = (EuropeanPriceIntegrand) obj;
        if (Double.doubleToLongBits(_alpha) != Double.doubleToLongBits(other._alpha)) {
            return false;
        }
        if (!ObjectUtils.equals(_ce, other._ce)) {
            return false;
        }
        return _useVarianceReduction == other._useVarianceReduction;
    }
}