All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.finmath.fouriermethod.models.BatesModel Maven / Gradle / Ivy

/*
 * (c) Copyright Christian P. Fries, Germany. Contact: [email protected].
 *
 * Created on 23.03.2014
 */
package net.finmath.fouriermethod.models;

import java.time.LocalDate;
import java.util.Arrays;

import org.apache.commons.math3.complex.Complex;

import net.finmath.fouriermethod.CharacteristicFunction;
import net.finmath.marketdata.model.curves.DiscountCurve;

/**
 * Implements the characteristic function of a Bates model.
 *
 * The Bates model for an underlying \( S \) is given by
 * \[
 * 	dS(t) = r^{\text{c}} S(t) dt + \sqrt{V(t)} S(t) dW_{1}(t) + S dJ, \quad S(0) = S_{0},
 * \]
 * \[
 * 	dV(t) = \kappa ( \theta - V(t) ) dt + \xi \sqrt{V(t)} dW_{2}(t), \quad V(0) = \sigma^2,
 * \]
 * \[
 * 	dW_{1} dW_{2} = \rho dt
 * \]
 * \[
 * 	dN(t) = r^{\text{d}} N(t) dt, \quad N(0) = N_{0},
 * \]
 * where \( W \) is Brownian motion and \( J \)  is a jump process (compound Poisson process).
 *
 * The free parameters of this model are:
 * 
*
\( S_{0} \)
spot - initial value of S
*
\( r \)
the risk free rate
*
\( \sigma \)
the initial volatility level
*
\( \xi \)
the volatility of volatility
*
\( \theta \)
the mean reversion level of the stochastic volatility
*
\( \kappa \)
the mean reversion speed of the stochastic volatility
*
\( \rho \)
the correlation of the Brownian drivers
*
\( a \)
the jump size mean
*
\( b \)
the jump size standard deviation
*
* * The process \( J \) is given by \( J(t) = \sum_{i=1}^{N(t)} (Y_{i}-1) \), where * \( \log(Y_{i}) \) are i.i.d. normals with mean \( a - \frac{1}{2} b^{2} \) and standard deviation \( b \). * Here \( a \) is the jump size mean and \( b \) is the jump size std. dev. * * The model can be rewritten as \( S = \exp(X) \), where * \[ * dX = \mu dt + \sqrt{V(t)} dW + dJ^{X}, \quad X(0) = \log(S_{0}), * \] * with * \[ * J^{X}(t) = \sum_{i=1}^{N(t)} \log(Y_{i}) * \] * with \( \mu = r - \frac{1}{2} \sigma^2 - (exp(a)-1) \lambda \). * * * @author Christian Fries * @author Andy Graf * @author Lorenzo Toricelli * @version 1.0 */ public class BatesModel implements CharacteristicFunctionModel { private final LocalDate referenceDate; private final double initialValue; private final DiscountCurve discountCurveForForwardRate; private final double riskFreeRate; // Actually the same as the drift (which is not stochastic) private final DiscountCurve discountCurveForDiscountRate; private final double discountRate; private final double[] volatility; private final double[] alpha; private final double[] beta; private final double[] sigma; private final double[] rho; private final double[] lambda; //3 constants private final double k; private final double delta; private final int numberOfFactors; /** * Create a two factor Bates model. * * @param referenceDate The date representing the time t = 0. All other double times are following {@link net.finmath.time.FloatingpointDate}. * @param initialValue Initial value of S. * @param discountCurveForForwardRate The curve specifying \( t \mapsto exp(- r^{\text{c}}(t) \cdot t) \) - with \( r^{\text{c}}(t) \) the risk free rate * @param discountCurveForDiscountRate The curve specifying \( t \mapsto exp(- r^{\text{d}}(t) \cdot t) \) - with \( r^{\text{d}}(t) \) the discount rate * @param volatility Square root of initial value of the stochastic variance process V. * @param alpha The parameter alpha/beta is the mean reversion level of the variance process V. * @param beta Mean reversion speed of variance process V. * @param sigma Volatility of volatility. * @param rho Correlations of the Brownian drives (underlying, variance). * @param lambda Coefficients of for the jump intensity. * @param k Jump size mean. * @param delta Jump size variance. */ public BatesModel( LocalDate referenceDate, double initialValue, DiscountCurve discountCurveForForwardRate, DiscountCurve discountCurveForDiscountRate, double[] volatility, double[] alpha, double[] beta, double[] sigma, double[] rho, double[] lambda, double k, double delta ) { super(); this.referenceDate = referenceDate; this.initialValue = initialValue; this.discountCurveForForwardRate = discountCurveForForwardRate; riskFreeRate = Double.NaN; this.discountCurveForDiscountRate = discountCurveForDiscountRate; discountRate = Double.NaN; this.volatility = volatility; this.alpha = alpha; this.beta = beta; this.sigma = sigma; this.rho = rho; this.lambda = lambda; this.k = k; this.delta = delta; numberOfFactors = alpha.length; } /** * Create a two factor Bates model. * * @param initialValue Initial value of S. * @param discountCurveForForwardRate The curve specifying \( t \mapsto exp(- r^{\text{c}}(t) \cdot t) \) - with \( r^{\text{c}}(t) \) the risk free rate * @param discountCurveForDiscountRate The curve specifying \( t \mapsto exp(- r^{\text{d}}(t) \cdot t) \) - with \( r^{\text{d}}(t) \) the discount rate * @param volatility Square root of initial value of the stochastic variance process V. * @param alpha The parameter alpha/beta is the mean reversion level of the variance process V. * @param beta Mean reversion speed of variance process V. * @param sigma Volatility of volatility. * @param rho Correlations of the Brownian drives (underlying, variance). * @param lambda Coefficients of for the jump intensity. * @param k Jump size mean. * @param delta Jump size variance. */ public BatesModel( double initialValue, DiscountCurve discountCurveForForwardRate, DiscountCurve discountCurveForDiscountRate, double[] volatility, double[] alpha, double[] beta, double[] sigma, double[] rho, double[] lambda, double k, double delta ) { this(null, initialValue, discountCurveForForwardRate, discountCurveForDiscountRate, volatility,alpha,beta,sigma,rho,lambda,k,delta); } /** * Create a two factor Bates model. * * @param initialValue Initial value of S. * @param riskFreeRate Risk free rate. * @param discountRate The rate used for discounting. * @param volatility Square root of initial value of the stochastic variance process V. * @param alpha The parameter alpha/beta is the mean reversion level of the variance process V. * @param beta Mean reversion speed of variance process V. * @param sigma Volatility of volatility. * @param rho Correlations of the Brownian drives (underlying, variance). * @param lambda Coefficients of for the jump intensity. * @param k Jump size mean. * @param delta Jump size variance. */ public BatesModel( double initialValue, double riskFreeRate, double discountRate, double[] volatility, double[] alpha, double[] beta, double[] sigma, double[] rho, double[] lambda, double k, double delta ) { referenceDate = null; this.initialValue = initialValue; discountCurveForForwardRate = null; this.riskFreeRate = riskFreeRate; discountCurveForDiscountRate = null; this.discountRate = discountRate; this.volatility = volatility; this.alpha = alpha; this.beta = beta; this.sigma = sigma; this.rho = rho; this.lambda = lambda; this.k = k; this.delta = delta; numberOfFactors = alpha.length; } /** * Create a one factor Bates model. * * @param initialValue Initial value of S. * @param riskFreeRate Risk free rate. * @param volatility Square root of initial value of the stochastic variance process V. * @param alpha The parameter alpha/beta is the mean reversion level of the variance process V. * @param beta Mean reversion speed of variance process V. * @param sigma Volatility of volatility. * @param rho Correlations of the Brownian drives (underlying, variance). * @param lambdaZero Constant part of the jump intensity. * @param lambdaOne Coefficients of the jump intensity, linear in variance. * @param k Jump size mean. * @param delta Jump size variance. */ public BatesModel( double initialValue, double riskFreeRate, double volatility, double alpha, double beta, double sigma, double rho, double lambdaZero, double lambdaOne, double k, double delta ) { this(initialValue, riskFreeRate,riskFreeRate, new double[]{ volatility }, new double[]{ alpha }, new double[]{ beta }, new double[]{ sigma }, new double[]{ rho }, new double[]{ lambdaZero, lambdaOne }, k, delta ); } /* (non-Javadoc) * @see net.finmath.fouriermethod.models.ProcessCharacteristicFunctionInterface#apply(double) */ @Override public CharacteristicFunction apply(final double time) { final double logDiscountFactorForForward = this.getLogDiscountFactorForForward(time); final double logDiscountFactorForDiscounting = this.getLogDiscountFactorForDiscounting(time); return new CharacteristicFunction() { @Override public Complex apply(Complex argument) { Complex iargument = argument.multiply(Complex.I); Complex c = iargument .multiply(iargument) .add(iargument.multiply(-1)) .multiply(0.5*delta*delta) .exp() .multiply(new Complex(1+k).pow(iargument)) .add(-1) .add(iargument.multiply(-k)); Complex[] gamma = new Complex[numberOfFactors]; Complex[] a = new Complex[numberOfFactors]; Complex[] b = new Complex[numberOfFactors]; for(int i = 0; i < numberOfFactors; i++) { gamma[i] = iargument .multiply(rho[i]*sigma[i]) .subtract(beta[i]) .pow(2) .subtract( iargument.multiply(iargument) .add(iargument.multiply(-1)) .multiply(0.5) .add(c.multiply(lambda[i+1])) .multiply(2*sigma[i]*sigma[i]) ) .sqrt() ; a[i] = iargument .multiply(rho[i] * sigma[i]) .subtract(beta[i]) .subtract(gamma[i]) .multiply((-alpha[i]*time)/(sigma[i]*sigma[i])) .subtract(iargument .multiply(rho[i]*sigma[i]) .subtract(beta[i]) .subtract(gamma[i]) .multiply(new Complex(1).divide(gamma[i].multiply(time).exp()) .subtract(1) .divide(gamma[i]) ) .multiply(0.5) .add(new Complex(1).divide(gamma[i].multiply(time).exp())) .log() .add(gamma[i].multiply(time)) .multiply((2*alpha[i])/(sigma[i]*sigma[i])) ) ; b[i] = iargument .multiply(iargument) .add(iargument.multiply(-1)) .multiply(0.5) .add(c.multiply(lambda[i+1])) .multiply(-2) .divide(iargument .multiply(rho[i] * sigma[i]) .subtract(beta[i]) .add(gamma[i] .multiply(new Complex(1).divide(gamma[i].multiply(time).exp()) .add(1) .divide(new Complex(1).divide(gamma[i].multiply(time).exp()) .subtract(1) ) ) ) ) ; } Complex characteristicFunction = a[0] .add(b[0].multiply(volatility[0])) .add(c.multiply(time*lambda[0])) .add(iargument.multiply(Math.log(initialValue) - logDiscountFactorForForward)) .add(logDiscountFactorForDiscounting); if(numberOfFactors == 2) { characteristicFunction = characteristicFunction .add(a[1]) .add(b[1].multiply(volatility[1])); } characteristicFunction = characteristicFunction.exp(); return characteristicFunction; } }; } /** * Small helper to calculate rate off the curve or use constant. * * @param time Maturity. * @return The log of the discount factor, i.e., - rate * time. */ private double getLogDiscountFactorForForward(double time) { return discountCurveForForwardRate == null ? -riskFreeRate * time : Math.log(discountCurveForForwardRate.getDiscountFactor(null, time)); } /** * Small helper to calculate rate off the curve or use constant. * * @param time Maturity. * @return The log of the discount factor, i.e., - rate * time. */ private double getLogDiscountFactorForDiscounting(double time) { return discountCurveForDiscountRate == null ? -discountRate * time : Math.log(discountCurveForDiscountRate.getDiscountFactor(null, time)); } /** * @return the referenceDate */ public LocalDate getReferenceDate() { return referenceDate; } /** * @return the initialValue */ public double getInitialValue() { return initialValue; } /** * @return the riskFreeRate */ public double getRiskFreeRate() { return riskFreeRate; } /** * @return the volatility */ public double[] getVolatility() { return volatility; } /** * @return the discountRate */ public double getDiscountRate() { return discountRate; } /** * @return the alpha */ public double[] getAlpha() { return alpha; } /** * @return the beta */ public double[] getBeta() { return beta; } /** * @return the sigma */ public double[] getSigma() { return sigma; } /** * @return the rho */ public double[] getRho() { return rho; } /** * @return the lambda */ public double[] getLambda() { return lambda; } /** * @return the k */ public double getK() { return k; } /** * @return the delta */ public double getDelta() { return delta; } /** * @return the numberOfFactors */ public int getNumberOfFactors() { return numberOfFactors; } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "BatesModel [initialValue=" + initialValue + ", riskFreeRate=" + riskFreeRate + ", volatility=" + Arrays.toString(volatility) + ", discountRate=" + discountRate + ", alpha=" + Arrays.toString(alpha) + ", beta=" + Arrays.toString(beta) + ", sigma=" + Arrays.toString(sigma) + ", rho=" + Arrays.toString(rho) + ", lambda=" + Arrays.toString(lambda) + ", k=" + k + ", delta=" + delta + ", numberOfFactors=" + numberOfFactors + "]"; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy