/** * 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.number.ComplexNumber.MINUS_I; import org.apache.commons.lang.NotImplementedException; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.Validate; import com.opengamma.analytics.math.ComplexMathUtils; import com.opengamma.analytics.math.function.Function1D; import com.opengamma.analytics.math.number.ComplexNumber; /** * This characteristic exponent converts a Levy process from calendar time to * business time (where time moves at a stochastic rate relative to calendar * time). This has the effect of introducing stochastic changes to the model * parameters of the original Levy process. * <p> * If the time-changed Levy process is $X_{Y_t}$, with $Y_t$ the business time, * the characteristic function is given by: * $$ * \begin{align*} * \phi(u, t) &= E\left[e^{iuX_{Y_t}}\right]\\ * &= E\left[e^{Y_t\psi_X(u)}\right]\\ * &= E\left[e^{i(-i\psi_X(u))Y_t}\right]\\ * &= \phi_{Y_t}(-i\psi_X(u), t) * \end{align*} * $$ * where $\psi_X(u)$ is the cumulant characteristic function of the Levy * process. The drift correction then becomes: * $$ * \begin{align*} * \omega(t) = -\frac{\ln(\phi(-i, t))}{t} * \end{align*} * $$ */ public class TimeChangedCharacteristicExponent implements CharacteristicExponent { private final CharacteristicExponent _base; private final CharacteristicExponent _timeChange; /** * * @param base The base characteristic exponent, not null * @param timeChange The characteristic exponent to time change, not null */ public TimeChangedCharacteristicExponent(final CharacteristicExponent base, final StocasticClockCharcteristicExponent timeChange) { Validate.notNull(base, "base"); Validate.notNull(timeChange, "timeChange"); _base = base; _timeChange = timeChange; } @Override public Function1D<ComplexNumber, ComplexNumber> getFunction(final double t) { final Function1D<ComplexNumber, ComplexNumber> baseFunction = _base.getFunction(1); final Function1D<ComplexNumber, ComplexNumber> timeChangeFunction = _timeChange.getFunction(t); return new Function1D<ComplexNumber, ComplexNumber>() { @Override public ComplexNumber evaluate(final ComplexNumber u) { final ComplexNumber z = ComplexMathUtils.multiply(MINUS_I, baseFunction.evaluate(u)); return timeChangeFunction.evaluate(z); } }; } @Override public ComplexNumber getValue(ComplexNumber u, double t) { Function1D<ComplexNumber, ComplexNumber> func = getFunction(t); return func.evaluate(u); } /** * * @return the smaller $alpha_{max}$ of the base characteristic exponent and the time-changed characteristic exponent */ @Override public double getLargestAlpha() { return Math.min(_base.getLargestAlpha(), _timeChange.getLargestAlpha()); } /** * * @return the larger $alpha_{min}$ of the base characteristic exponent and the time-changed characteristic exponent */ @Override public double getSmallestAlpha() { return Math.max(_base.getSmallestAlpha(), _timeChange.getSmallestAlpha()); } /** * Gets the base field. * @return the base */ public CharacteristicExponent getBase() { return _base; } /** * Gets the timeChange field. * @return the timeChange */ public CharacteristicExponent getTimeChange() { return _timeChange; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + _base.hashCode(); result = prime * result + _timeChange.hashCode(); 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 TimeChangedCharacteristicExponent other = (TimeChangedCharacteristicExponent) obj; if (!ObjectUtils.equals(_base, other._base)) { return false; } return ObjectUtils.equals(_timeChange, other._timeChange); } @Override public ComplexNumber[] getCharacteristicExponentAdjoint(ComplexNumber u, double t) { throw new NotImplementedException(); } @Override public Function1D<ComplexNumber, ComplexNumber[]> getAdjointFunction(double t) { throw new NotImplementedException(); } }