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

Java tutorial

Introduction

Here is the source code for com.opengamma.analytics.financial.model.option.pricing.fourier.FourierModelGreeks.java

Source

/**
 * Copyright (C) 2011 - 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.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.integration.Integrator1D;
import com.opengamma.analytics.math.integration.RungeKuttaIntegrator1D;
import com.opengamma.analytics.math.number.ComplexNumber;

/**
 * 
 */
public class FourierModelGreeks {

    private static final IntegralLimitCalculator LIMIT_CALCULATOR = new IntegralLimitCalculator();
    private final Integrator1D<Double, Double> _integrator;

    public FourierModelGreeks() {
        this(new RungeKuttaIntegrator1D());
    }

    public FourierModelGreeks(final Integrator1D<Double, Double> integrator) {
        Validate.notNull(integrator, "null integrator");
        _integrator = integrator;
    }

    public double[] getGreeks(final BlackFunctionData data, final EuropeanVanillaOption option,
            final MartingaleCharacteristicExponent ce, final double alpha, final double limitTolerance) {
        Validate.notNull(data, "data");
        Validate.notNull(option, "option");
        Validate.notNull(ce, "characteristic exponent");
        Validate.isTrue(limitTolerance > 0, "limit tolerance must be > 0");
        Validate.isTrue(alpha <= ce.getLargestAlpha() && alpha >= ce.getSmallestAlpha(),
                "The value of alpha is not valid for the Characteristic Exponent and will most likely lead to mispricing. Choose a value between "
                        + ce.getSmallestAlpha() + " and " + ce.getLargestAlpha());

        final EuropeanCallFourierTransform psi = new EuropeanCallFourierTransform(ce);
        final double strike = option.getStrike();
        final double t = option.getTimeToExpiry();
        final double forward = data.getForward();
        final double discountFactor = data.getDiscountFactor();
        final Function1D<ComplexNumber, ComplexNumber> characteristicFunction = psi.getFunction(t);
        final double xMax = LIMIT_CALCULATOR.solve(characteristicFunction, alpha, limitTolerance);

        double kappa = Math.log(strike / forward);
        int n = ce.getCharacteristicExponentAdjoint(MINUS_I, 1.0).length; //TODO have method like getNumberOfparameters 

        Function1D<ComplexNumber, ComplexNumber[]> adjointFuncs = ce.getAdjointFunction(t);
        double[] res = new double[n - 1];

        //TODO This is inefficient as a call to ajointFuncs.evaluate(z), will return several values (the value of the characteristic function and its derivatives), but only one
        // of these values is used by each of the the integraters - a parallel quadrature scheme would be good here 
        for (int i = 0; i < n - 1; i++) {
            final Function1D<Double, Double> func = getIntegrandFunction(adjointFuncs, alpha, kappa, i + 1);
            final double integral = Math.exp(-alpha * Math.log(strike / forward))
                    * _integrator.integrate(func, 0.0, xMax) / Math.PI;
            res[i] = discountFactor * forward * integral;
        }
        return res;
    }

    public Function1D<Double, Double> getIntegrandFunction(
            final Function1D<ComplexNumber, ComplexNumber[]> ajointFunctions, final double alpha,
            final double kappa, final int index) {

        return new Function1D<Double, Double>() {

            @Override
            public Double evaluate(Double x) {
                final ComplexNumber z = new ComplexNumber(x, -1 - alpha);
                ComplexNumber[] ajoint = ajointFunctions.evaluate(z);
                ComplexNumber num = exp(add(new ComplexNumber(0, -x * kappa), ajoint[0]));
                if (index > 0) {
                    num = multiply(num, ajoint[index]);
                }
                final ComplexNumber denom = multiply(z, subtract(MINUS_I, z));
                final ComplexNumber res = divide(num, denom);
                return res.getReal();
            }
        };

    }

}