/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.model.option.pricing.tree; import org.apache.commons.lang.NotImplementedException; import com.opengamma.analytics.math.function.Function1D; import com.opengamma.analytics.math.statistics.descriptive.MeanCalculator; /** * */ public class TimeVaryingLatticeSpecification extends LatticeSpecification { @Override public double[] getParameters(final double spot, final double strike, final double timeToExpiry, final double volatility, final double interestRate, final int nSteps, final double dt) { throw new NotImplementedException(); } /** * Overloaded getParameters method * @param vol Volatility * @param nu Computed by getShiftedDrift method * @param spaceStep Space step * @return {(modified time step), (up probability)} */ public double[] getParameters(final double vol, final double nu, final double spaceStep) { final double[] res = new double[2]; final double volSq = vol * vol; final double nuSq = nu * nu; res[0] = 0.5 * (-volSq + Math.sqrt(volSq * volSq + 4. * nuSq * spaceStep * spaceStep)) / nuSq; res[1] = 0.5 + 0.5 * nu * res[0] / spaceStep; return res; } /** * Parameters for trinomial tree * @param vol Volatility * @param nu Computed by getShiftedDrift method * @param dt Time step * @param spaceStep Homogeneous space step * @return {(up probability), (middle probability), (down probability)} */ public double[] getParametersTrinomial(final double vol, final double nu, final double dt, final double spaceStep) { final double nudt = nu * dt; final double dx = vol * Math.sqrt(3. * dt); final double part = (vol * vol * dt + nudt * nudt) / dx / dx; final double upProbability = 0.5 * (part + nudt / dx); final double middleProbability = 1. - part; final double downProbability = 0.5 * (part - nudt / dx); return new double[] {upProbability, middleProbability, downProbability }; } @Override public double getTheta(final double spot, final double volatility, final double interestRate, final double dividend, final double dt, final double[] greeksTmp) { return 0.5 * (greeksTmp[3] - greeksTmp[0]) / dt; } /** * Finite difference approximation of theta. Note that the time step is not homogeneous in the time varying volatility lattice. * @param dt0 First time step * @param dt1 Second time step * @param greeksTmp asset price at (0,0) in greeksTmp[0] and asset price at (2,1) in greeksTmp[3] * @return Option theta */ public double getTheta(final double dt0, final double dt1, final double[] greeksTmp) { return (greeksTmp[3] - greeksTmp[0]) / (dt0 + dt1); } /** * @param volatility Volatility * @param interestRate Interest rate * @param dividend Dividend * @return (interest rate) - (dividend) - 0.5 * volatility * volatility for all layers */ public double[] getShiftedDrift(final double[] volatility, final double[] interestRate, final double[] dividend) { final int nSteps = volatility.length; final double[] res = new double[nSteps]; for (int i = 0; i < nSteps; ++i) { res[i] = interestRate[i] - dividend[i] - 0.5 * volatility[i] * volatility[i]; } return res; } /** * @param timeToExpiry Time to expiry * @param volatility Volatility * @param nSteps Number of steps * @param nu Computed by getShiftedDrift method * @return space step */ public double getSpaceStep(final double timeToExpiry, final double[] volatility, final int nSteps, final double[] nu) { final Function1D<double[], Double> calculator = new MeanCalculator(); final double meanNu = calculator.evaluate(nu); final double meanVol = calculator.evaluate(volatility); final double dt = timeToExpiry / nSteps; return Math.sqrt(meanVol * meanVol * dt + meanNu * meanNu * dt * dt); } /** * @param volatility Volatility * @param nu Computed by getShiftedDrift method * @param dt time step * @return space step */ public double getSpaceStepTrinomial(final double[] volatility, final double[] nu, final double dt) { final Function1D<double[], Double> calculator = new MeanCalculator(); final double meanNu = calculator.evaluate(nu); final double meanVol = calculator.evaluate(volatility); return Math.sqrt(3. * meanVol * meanVol * dt + meanNu * meanNu * dt * dt); } }