/** * 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.multiply; import static com.opengamma.analytics.math.ComplexMathUtils.square; import org.apache.commons.lang.Validate; import com.opengamma.analytics.math.function.Function1D; import com.opengamma.analytics.math.number.ComplexNumber; /** * This class represents the characteristic exponent for a Brownian motion driven by normally-distributed increments * $$ * \begin{align*} * \phi_X &= E\left[e^{iuX}\right]\\ * &= \frac{1}{\sqrt{2\pi}\sigma}\int_{-\infty}^{\infty} e^{iux} \exp\left(-\frac{(x - \mu)^2}{2\sigma^2}\right)\\ * %&= \exp\left({iu\mu - \tfrac{1}{2}\sigma^2 u^2}\right) * \end{align*} * $$ * and * $$ * \begin{align*} * \phi_{X_t}(u) &= [\phi_X(u)]^t \\ * &= \exp\left(t\left(iu\mu - \frac{\sigma^2 u^2}{2}\right)\right) * \end{align*} * $$ * */ public class GaussianCharacteristicExponent implements CharacteristicExponent { private final double _mu; private final double _sigma; /** * * @param mu The mean of the Gaussian distribution * @param sigma The standard deviation of the Gaussian distribution, not negative or zero */ public GaussianCharacteristicExponent(final double mu, final double sigma) { Validate.isTrue(sigma > 0.0, "sigma > 0"); _mu = mu; _sigma = sigma; } @Override public Function1D<ComplexNumber, ComplexNumber> getFunction(final double t) { return new Function1D<ComplexNumber, ComplexNumber>() { @Override public ComplexNumber evaluate(ComplexNumber x) { return getValue(x, t); } }; } @Override public ComplexNumber getValue(ComplexNumber u, double t) { Validate.isTrue(t > 0.0, "t > 0"); Validate.notNull(u, "u"); final ComplexNumber temp = multiply(_sigma, u); final ComplexNumber res = add(multiply(u, new ComplexNumber(0, _mu)), multiply(-0.5, multiply(temp, temp))); return multiply(t, res); } @Override public Function1D<ComplexNumber, ComplexNumber[]> getAdjointFunction(final double t) { return new Function1D<ComplexNumber, ComplexNumber[]>() { @Override public ComplexNumber[] evaluate(ComplexNumber x) { return getCharacteristicExponentAdjoint(x, t); } }; } @Override public ComplexNumber[] getCharacteristicExponentAdjoint(final ComplexNumber u, final double t) { final ComplexNumber[] res = new ComplexNumber[3]; res[0] = getValue(u, t); res[1] = multiply(u, new ComplexNumber(0.0, t)); res[2] = multiply(-_sigma * t, square(u)); return res; } /** * * @return $\infty$ */ @Override public double getLargestAlpha() { return Double.POSITIVE_INFINITY; } /** * * @return $-\infty$ */ @Override public double getSmallestAlpha() { return Double.NEGATIVE_INFINITY; } /** * Gets the mean. * @return the mean */ public double getMu() { return _mu; } /** * Gets the standard deviation. * @return the standard deviation */ public double getSigma() { return _sigma; } @Override public int hashCode() { final int prime = 31; int result = 1; long temp; temp = Double.doubleToLongBits(_mu); result = prime * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(_sigma); result = prime * result + (int) (temp ^ (temp >>> 32)); 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 GaussianCharacteristicExponent other = (GaussianCharacteristicExponent) obj; if (Double.doubleToLongBits(_mu) != Double.doubleToLongBits(other._mu)) { return false; } return Double.doubleToLongBits(_sigma) == Double.doubleToLongBits(other._sigma); } }