// Heston Local Volatility using Dupire's equation public double HestonLVAnalytic(double S, double K, double T, double rf, double q, double kappa, double theta, double sigma, double lambda, double v0, double rho, double[] x, double[] w, int trap) { HestonPrice HP = new HestonPrice(); double[] int1 = new Double[32]; double[] int2 = new Double[32]; double[] int3 = new Double[32]; double[] int4 = new Double[32]; double[] int5 = new Double[32]; for (int k = 0; k <= 31; k++) { int1[k] = w[k] * dPjdT(1, x[k], kappa, theta, lambda, rho, sigma, T, K, S, rf, q, v0, trap); int2[k] = w[k] * dPjdT(2, x[k], kappa, theta, lambda, rho, sigma, T, K, S, rf, q, v0, trap); int3[k] = w[k] * HP.HestonProb(x[k], kappa, theta, lambda, rho, sigma, T, K, S, rf, v0, q, 2, trap); int4[k] = w[k] * d2P1dK2(x[k], kappa, theta, lambda, rho, sigma, T, K, S, rf, q, v0, trap); int5[k] = w[k] * dP2dK2_2(x[k], kappa, theta, lambda, rho, sigma, T, K, S, rf, q, v0, trap); } double pi = Math.PI; double dP1dT = (1.0 / pi) * int1.Sum(); double dP2dT = (1.0 / pi) * int2.Sum(); double P2 = 0.5 + (1.0 / pi) * int3.Sum(); // dC/dT : derivative of call with respect to T double dCdT = S * dP1dT - K * Math.Exp(-rf * T) * (-rf * P2 + dP2dT); double dP1dK2 = (1.0 / pi) * int4.Sum(); double TwodP2dK2 = (1.0 / pi) * int5.Sum(); // d2C/dK2 : second derivative of call with respect to K^2 double d2CdK2 = S * dP1dK2 - Math.Exp(-rf * T) * TwodP2dK2; // Local Variance double LocalVar = 2.0 * dCdT / (K * K * d2CdK2); // Local Volatility double LocalVol = Math.Sqrt(LocalVar); return(LocalVol); }
// Heston Local Volatility using Dupire's formula. // Uses finite differences for the required derivatives public double HestonLVFD(double S, double K, double T, double rf, double q, double kappa, double theta, double sigma, double v0, double rho, double lambda, int trap, double[] x, double[] w, double dt, double dK) { HestonPrice HP = new HestonPrice(); // dC/dT by central finite difference double CT_1 = HP.HestonPriceGaussLaguerre("C", S, K, rf, q, T - dt, kappa, theta, sigma, v0, lambda, rho, x, w, trap); double CT1 = HP.HestonPriceGaussLaguerre("C", S, K, rf, q, T + dt, kappa, theta, sigma, v0, lambda, rho, x, w, trap); double dCdT = (CT1 - CT_1) / (2.0 * dt); // dC2/dK2 by central finite differences double CK_1 = HP.HestonPriceGaussLaguerre("C", S, K - dK, rf, q, T, kappa, theta, sigma, v0, lambda, rho, x, w, trap); double CK0 = HP.HestonPriceGaussLaguerre("C", S, K, rf, q, T, kappa, theta, sigma, v0, lambda, rho, x, w, trap); double CK1 = HP.HestonPriceGaussLaguerre("C", S, K + dK, rf, q, T, kappa, theta, sigma, v0, lambda, rho, x, w, trap); double dC2dK2 = (CK_1 - 2.0 * CK0 + CK1) / (dK * dK); // Local variance double LocalVar = 2.0 * dCdT / (K * K * dC2dK2); // Local volatility double LocalVol = Math.Sqrt(LocalVar); return(LocalVol); }