/** * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.model.volatility.smile.fitting; import static org.testng.Assert.assertEquals; import java.util.Arrays; import java.util.Random; import org.testng.annotations.Test; import com.opengamma.analytics.financial.model.option.definition.SmileDeltaParameters; import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.EuropeanVanillaOption; import com.opengamma.analytics.financial.model.volatility.BlackFormulaRepository; import com.opengamma.analytics.financial.model.volatility.smile.function.MixedBivariateLogNormalModelVolatility; import com.opengamma.analytics.financial.model.volatility.smile.function.MixedLogNormalModelData; import com.opengamma.analytics.financial.model.volatility.smile.function.MixedLogNormalVolatilityFunction; import com.opengamma.analytics.math.random.NormalRandomNumberGenerator; import com.opengamma.util.ArgumentChecker; import com.opengamma.util.test.TestGroup; /** * Test. */ @Test(groups = TestGroup.UNIT) public class MixedBivariateLogNormalFitterTest { private final static double INF = 1. / 0.; /** * EPS_1 =EPS_2 = 1.E-14 should be chosen for this test */ @Test public void recoveryTest() { final int nNorms = 2; final int nParams = 5 * nNorms - 3; final int nDataPts = 10; final int nDataPtsX = 5; final int nParamsX = 3 * nNorms - 2; final int nParamsY = 3 * nNorms - 2; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] yy = new double[nDataPts]; double[] aaGuess1 = new double[nParams]; final double[] aaGuess1X = new double[nParamsX]; final double[] aaGuess1Y = new double[nParamsY]; final double[] inRelativePartialForwardsX = {1., 1. }; final double[] inRelativePartialForwardsY = {Math.exp(-0.2), (1. - Math.exp(-0.2) * 0.7) / 0.3 }; final double[] inSigmasX = {0.25, 0.7 }; final double[] inSigmasY = {0.3, 0.5 }; final double[] inWeights = {0.7, 0.3 }; final MixedLogNormalModelData inObjX = new MixedLogNormalModelData(inWeights, inSigmasX, inRelativePartialForwardsX); final MixedLogNormalModelData inObjY = new MixedLogNormalModelData(inWeights, inSigmasY, inRelativePartialForwardsY); final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final MixedLogNormalVolatilityFunction volfunc = MixedLogNormalVolatilityFunction.getInstance(); Arrays.fill(yy, 0.); for (int j = 0; j < nDataPtsX; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); yy[j] = volfunc.getVolatility(option, fwdX, inObjX); } for (int j = nDataPtsX; j < nDataPts; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); yy[j] = volfunc.getVolatility(option, fwdY, inObjY); } for (int i = 0; i < nParams; ++i) { aaGuess1[i] = 0.5; } final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); aaGuess1 = fitter1.getParams(); for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } final MixedLogNormalModelData objAns1X = new MixedLogNormalModelData(aaGuess1X, true); final double[] weights = objAns1X.getWeights(); final double[] sigmasX = objAns1X.getVolatilities(); final double[] relativePartialForwardsX = objAns1X.getRelativeForwards(); final MixedLogNormalModelData objAns1Y = new MixedLogNormalModelData(aaGuess1Y, true); final double[] sigmasY = objAns1Y.getVolatilities(); final double[] relativePartialForwardsY = objAns1Y.getRelativeForwards(); for (int i = 0; i < nNorms; ++i) { assertEquals(weights[i], inWeights[i], Math.abs((inWeights[0] + inWeights[1]) / 2.) * 1e-9); } for (int i = 0; i < nNorms; ++i) { assertEquals(sigmasX[i], inSigmasX[i], Math.abs((inSigmasX[0] + inSigmasX[1]) / 2.) * 1e-9); } for (int i = 0; i < nNorms; ++i) { assertEquals(sigmasY[i], inSigmasY[i], Math.abs((inSigmasY[0] + inSigmasY[1]) / 2.) * 1e-9); } for (int i = 0; i < nNorms; ++i) { assertEquals(relativePartialForwardsX[i], inRelativePartialForwardsX[i], Math.abs((inRelativePartialForwardsX[0] + inRelativePartialForwardsX[1]) / 2.) * 1e-11); } for (int i = 0; i < nNorms; ++i) { assertEquals(relativePartialForwardsY[i], inRelativePartialForwardsY[i], Math.abs((inRelativePartialForwardsY[0] + inRelativePartialForwardsY[1]) / 2.) * 1e-9); } final double[] ansVolsX = new double[100]; final double[] ansVolsY = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdX * (0.1 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansVolsX[i] = volfunc.getVolatility(option, fwdX, objAns1X); ansVolsY[i] = volfunc.getVolatility(option, fwdY, objAns1Y); } final double[] trueVolsX = new double[100]; final double[] trueVolsY = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdY * (0.1 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); trueVolsX[i] = volfunc.getVolatility(option, fwdX, inObjX); trueVolsY[i] = volfunc.getVolatility(option, fwdY, inObjY); } for (int i = 0; i < 100; i++) { assertEquals(ansVolsX[i], trueVolsX[i], Math.abs((inSigmasX[0] + inSigmasX[1]) / 2.) * 1e-8); assertEquals(ansVolsY[i], trueVolsY[i], Math.abs((inSigmasY[0] + inSigmasY[1]) / 2.) * 1e-8); } final double[] ansDensityX = new double[100]; final double[] ansDensityY = new double[100]; final double[] trueDensityX = new double[100]; final double[] trueDensityY = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdX * (0.01 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansDensityX[i] = getDualGamma(option, fwdX, objAns1X); trueDensityX[i] = getDualGamma(option, fwdX, inObjX); assertEquals(ansDensityX[i], trueDensityX[i], 1e-9); } for (int i = 0; i < 100; i++) { final double k = fwdY * (0.01 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansDensityY[i] = getDualGamma(option, fwdY, objAns1Y); trueDensityY[i] = getDualGamma(option, fwdY, inObjY); assertEquals(ansDensityY[i], trueDensityY[i], 1e-9); } for (int i = 0; i < 100; i++) { final double k = fwdY * (0.01 + 2. * i / 100.); final EuropeanVanillaOption optionCall = new EuropeanVanillaOption(k, time, true); final EuropeanVanillaOption optionPut = new EuropeanVanillaOption(k, time, false); final double callPrice = getPrice(optionCall, fwdX, objAns1X); final double putPrice = getPrice(optionPut, fwdX, objAns1X); assertEquals((callPrice - putPrice), (fwdX - k), fwdX * 1e-12); } for (int i = 0; i < 100; i++) { final double k = fwdY * (0.01 + 2. * i / 100.); final EuropeanVanillaOption optionCall = new EuropeanVanillaOption(k, time, true); final EuropeanVanillaOption optionPut = new EuropeanVanillaOption(k, time, false); final double callPrice = getPrice(optionCall, fwdY, objAns1Y); final double putPrice = getPrice(optionPut, fwdY, objAns1Y); assertEquals((callPrice - putPrice), (fwdY - k), fwdY * 1e-12); } } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void nullaaGuessTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = null; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void nullxxTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = null; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void nullyyTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = null; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void naNaaGuessTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {Double.NaN, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void naNxxTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {Double.NaN, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void naNyyTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {Double.NaN, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void naNtimeTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = Double.NaN; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void naNfwdXTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = Double.NaN; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void naNfwdYTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = Double.NaN; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void naNparamsGuessCorrectionTest() { final int nNorms = 2; final int nDataPtsX = 5; final double paramsGuessCorrection = Double.NaN; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, paramsGuessCorrection); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void iNFaaGuessTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {INF, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void iNFxxTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {INF, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void iNFyyTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {INF, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void iNFtimeTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = INF; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void iNFfwdXTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = INF; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void iNFfwdYTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = INF; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void iNFparamsGuessCorrectionTest() { final int nNorms = 2; final int nDataPtsX = 5; final double paramsGuessCorrection = INF; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, paramsGuessCorrection); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void wrongnDataPtsXTest() { final int nNorms = 2; final int nDataPtsX = 11; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void wrongYYlengthTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void wrongParamLengthTest() { final int nNorms = 6; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void negativeTimeTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = -1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void negativeFwdXTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = -1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void negativeFwdYTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = -1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); } /** * */ @Test(expectedExceptions = IllegalArgumentException.class) public void negativeParamsGuessCorrectionTest() { final int nNorms = 2; final int nDataPtsX = 5; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; final double[] aaGuess1 = new double[] {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 }; final double[] xx = new double[] {0.9, 0.95, 1.0, 1.05, 1.1, 0.9, 0.95, 1.0, 1.05, 1.15 }; final double[] yy = new double[] {0.09, 0.085, 0.08, 0.03105, 0.091, 0.09, 0.075, 0.066, 0.705, 0.115 }; final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, -1); } /** * Tests below are for debugging or application to forex cross */ @Test (enabled = false) public void fittingTestManyDataPts() { final int nNorms = 2; final int nParams = 5 * nNorms - 3; final int nDataPts = 200; final int nDataPtsX = 100; final int nParamsX = 3 * nNorms - 2; final double fwdX = 1.1; final double fwdY = 0.9; final double time = 0.6; final double[] xx = new double[nDataPts]; final double[] aa = new double[nParams]; double[] aaGuess1 = new double[nParams]; double[] aaGuess2 = new double[nParams]; final double[] aaX = new double[nParamsX]; final double[] aaGuessX = new double[nParamsX]; // Random objRand = new Random(); for (int i = 0; i < nParams; ++i) { aa[i] = 1. + 0.0125 * i; } final double rateX = 1. / nDataPtsX; final double rateY = 1. / (nDataPts - nDataPtsX); for (int i = 0; i < nDataPtsX; ++i) { xx[i] = fwdX * (0.5 + rateX * i); } for (int i = nDataPtsX; i < nDataPts; ++i) { xx[i] = fwdY * (0.5 + rateY * i); } final double[] yy = getFunctionValues(aa, xx, fwdX, fwdY, time, nNorms, nDataPts, nDataPtsX); for (int i = 0; i < nParams; ++i) { aaGuess1[i] = 0.9; } for (int i = 0; i < nParams; ++i) { aaGuess2[i] = 1.2; // aaGuess2[i] = objRand.nextDouble(); // aaGuess2[i] = 0.5 + objRand.nextDouble(); } /////Comparing true parameters with parameters returned by fitting///// System.out.println("true value: " + aa[0] + "\t" + aa[1]); System.out.println("\n"); final MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); System.out.println("guess: " + aaGuess1[0] + "\t" + aaGuess1[1]); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); aaGuess1 = fitter1.getParams(); System.out.println("inintial sq: " + fitter1.getInitialSq()); System.out.println("answer: " + aaGuess1[0] + "\t" + aaGuess1[1]); System.out.println("sq: " + fitter1.getFinalSq()); System.out.println("\n"); final MixedBivariateLogNormalFitter fitter2 = new MixedBivariateLogNormalFitter(); System.out.println("guess: " + aaGuess2[0] + "\t" + aaGuess2[1]); fitter2.doFit(aaGuess2, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); System.out.println("inintial sq: " + fitter2.getInitialSq()); aaGuess2 = fitter2.getParams(); System.out.println("answer: " + aaGuess2[0] + "\t" + aaGuess2[1]); System.out.println("sq: " + fitter2.getFinalSq()); System.out.println("\n"); final MixedBivariateLogNormalFitter fitter3 = new MixedBivariateLogNormalFitter(); System.out.println("guess: " + aa[0] + "\t" + aa[1]); fitter3.doFit(aa, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); System.out.println("inintial sq: " + fitter3.getInitialSq()); final double[] aaGuess3 = fitter3.getParams(); System.out.println("answer: " + aaGuess3[0] + "\t" + aaGuess3[1]); System.out.println("sq: " + fitter3.getFinalSq()); System.out.println("\n"); /////Comparing true volatility smile with volatility smile derived with fitted parameters///// for (int i = 0; i < nNorms; ++i) { aaGuessX[i] = aaGuess1[i]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuessX[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuessX[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; } for (int i = 0; i < nNorms; ++i) { aaX[i] = aaGuess2[i]; } for (int i = 0; i < nNorms - 1; ++i) { aaX[i + nNorms] = aaGuess2[i + 2 * nNorms]; aaX[i + 2 * nNorms - 1] = aaGuess2[i + 3 * nNorms - 1]; } final MixedLogNormalModelData objAns1 = new MixedLogNormalModelData(aaGuessX, true); final MixedLogNormalModelData objAns2 = new MixedLogNormalModelData(aaX, true); final MixedLogNormalVolatilityFunction volfunc = MixedLogNormalVolatilityFunction.getInstance(); for (int i = 0; i < 100; i++) { final double k = fwdX * (0.5 + 1. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); final double vol2 = volfunc.getVolatility(option, fwdX, objAns1); final double vol3 = volfunc.getVolatility(option, fwdX, objAns2); System.out.println(k + "\t" + vol2 + "\t" + vol3 + "\t" + yy[i]); } } /** * */ @Test (enabled = false) public void testDerivingZ1() { final int nNorms = 2; final int nParams = 5 * nNorms - 3; final int nDataPts = 14; final int nDataPtsX = 7; final int nParamsX = 3 * nNorms - 2; final int nParamsY = 3 * nNorms - 2; final double fwdX = 1.; final double fwdY = 1.; final double fwdZ = fwdX / fwdY; final double time = 1.0; double[] xx = new double[nDataPts]; final double[] yy = new double[nDataPts]; double[] aaGuess1 = new double[nParams]; final double[] aaGuess1X = new double[nParamsX]; final double[] aaGuess1Y = new double[nParamsY]; final double[] rhos = new double[nNorms]; final Random obj = new Random(); final double[] inRelativePartialForwardsX = {1., 1. }; final double[] inRelativePartialForwardsY = {Math.exp(-0.2), (1. - Math.exp(-0.2) * 0.7) / 0.3 }; final double[] inSigmasX = {0.25, 0.7 }; final double[] inSigmasY = {0.3, 0.5 }; final double[] inWeights = {0.7, 0.3 }; final MixedLogNormalModelData inObjX = new MixedLogNormalModelData(inWeights, inSigmasX, inRelativePartialForwardsX); final MixedLogNormalModelData inObjY = new MixedLogNormalModelData(inWeights, inSigmasY, inRelativePartialForwardsY); xx = new double[] {0.5, 0.7, 0.9, 1.0, 1.2, 1.5, 1.8, 0.5, 0.7, 0.9, 1.0, 1.2, 1.5, 1.8 }; final MixedLogNormalVolatilityFunction volfunc = MixedLogNormalVolatilityFunction.getInstance(); Arrays.fill(yy, 0.); for (int j = 0; j < nDataPtsX; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); yy[j] = volfunc.getVolatility(option, fwdX, inObjX); } for (int j = nDataPtsX; j < nDataPts; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); yy[j] = volfunc.getVolatility(option, fwdY, inObjY); } rhos[0] = 0.2; rhos[1] = 0.9; final MixedBivariateLogNormalModelVolatility objTrueZ = new MixedBivariateLogNormalModelVolatility(inWeights, inSigmasX, inSigmasY, inRelativePartialForwardsX, inRelativePartialForwardsY, rhos); final double[] inSigmasZ = objTrueZ.getSigmasZ(); final double[] inRelativePartialForwardsZ = objTrueZ.getRelativeForwardsZ(); System.out.println("true values: " + inSigmasX[0] + "\t" + inSigmasX[1]); System.out.println("\n"); for (int i = 0; i < nParams; ++i) { aaGuess1[i] = 1e-2 + obj.nextDouble(); } MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); boolean fitDone = false; while (fitDone == false) { for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } MixedLogNormalModelData tmpObj1X = new MixedLogNormalModelData(aaGuess1X, true); double[] tmpSigmasX = tmpObj1X.getVolatilities(); System.out.println("guess: " + tmpSigmasX[0] + "\t" + tmpSigmasX[1]); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); aaGuess1 = fitter1.getParams(); System.out.println("inintial sq: " + fitter1.getInitialSq()); for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } tmpObj1X = new MixedLogNormalModelData(aaGuess1X, true); tmpSigmasX = tmpObj1X.getVolatilities(); System.out.println("answer: " + tmpSigmasX[0] + "\t" + tmpSigmasX[1]); System.out.println("sq: " + fitter1.getFinalSq()); System.out.println("\n"); if (fitter1.getFinalSq() <= fitter1.getInitialSq() * 1e-10) { fitDone = true; } else { for (int i = 0; i < nParams; ++i) { aaGuess1[i] = 1e-2 + obj.nextDouble(); } fitter1 = new MixedBivariateLogNormalFitter(); } } for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } final MixedLogNormalModelData objAns1X = new MixedLogNormalModelData(aaGuess1X, true); final double[] weights = objAns1X.getWeights(); final double[] sigmasX = objAns1X.getVolatilities(); final double[] relativePartialForwardsX = objAns1X.getRelativeForwards(); final MixedLogNormalModelData objAns1Y = new MixedLogNormalModelData(aaGuess1Y, true); final double[] sigmasY = objAns1Y.getVolatilities(); final double[] relativePartialForwardsY = objAns1Y.getRelativeForwards(); final MixedBivariateLogNormalModelVolatility objZ = new MixedBivariateLogNormalModelVolatility(weights, sigmasX, sigmasY, relativePartialForwardsX, relativePartialForwardsY, rhos); final double[] sigmasZ = objZ.getSigmasZ(); final double[] relativePartialForwardsZ = objZ.getRelativeForwardsZ(); System.out.println("Parameters XY"); for (int i = 0; i < nNorms; ++i) { System.out.println(weights[i] + "\t" + inWeights[i]); assertEquals(weights[i], inWeights[i], Math.abs((inWeights[0] + inWeights[1]) / 2.) * 1e-6); } for (int i = 0; i < nNorms; ++i) { System.out.println(sigmasX[i] + "\t" + inSigmasX[i]); assertEquals(sigmasX[i], inSigmasX[i], Math.abs((inSigmasX[0] + inSigmasX[1]) / 2.) * 1e-6); } for (int i = 0; i < nNorms; ++i) { System.out.println(sigmasY[i] + "\t" + inSigmasY[i]); assertEquals(sigmasY[i], inSigmasY[i], Math.abs((inSigmasY[0] + inSigmasY[1]) / 2.) * 1e-6); } for (int i = 0; i < nNorms; ++i) { System.out.println(relativePartialForwardsX[i] + "\t" + inRelativePartialForwardsX[i]); assertEquals(relativePartialForwardsX[i], inRelativePartialForwardsX[i], Math.abs((inRelativePartialForwardsX[0] + inRelativePartialForwardsX[1]) / 2.) * 1e-6); } for (int i = 0; i < nNorms; ++i) { System.out.println(relativePartialForwardsY[i] + "\t" + inRelativePartialForwardsY[i]); assertEquals(relativePartialForwardsY[i], inRelativePartialForwardsY[i], Math.abs((inRelativePartialForwardsY[0] + inRelativePartialForwardsY[1]) / 2.) * 1e-6); } System.out.println("\n"); System.out.println("Parameters Z"); for (int i = 0; i < nNorms; ++i) { System.out.println(sigmasZ[i] + "\t" + inSigmasZ[i]); assertEquals(sigmasZ[i], inSigmasZ[i], Math.abs((inSigmasZ[0] + inSigmasZ[1]) / 2.) * 1e-6); } for (int i = 0; i < nNorms; ++i) { System.out.println(relativePartialForwardsZ[i] + "\t" + inRelativePartialForwardsZ[i]); assertEquals(relativePartialForwardsZ[i], inRelativePartialForwardsZ[i], Math.abs((inRelativePartialForwardsZ[0] + inRelativePartialForwardsZ[1]) / 2.) * 1e-6); } System.out.println("\n"); System.out.println("Imp Vols XYZ from fitting"); final double[] ansVolsX = new double[100]; final double[] ansVolsY = new double[100]; final double[] ansVolsZ = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdX * (0.1 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansVolsX[i] = volfunc.getVolatility(option, fwdX, objAns1X); ansVolsY[i] = volfunc.getVolatility(option, fwdY, objAns1Y); ansVolsZ[i] = objZ.getImpliedVolatilityZ(option, fwdZ); System.out.println(k + "\t" + ansVolsX[i] + "\t" + ansVolsY[i] + "\t" + ansVolsZ[i]); } System.out.println("\n"); System.out.println("True Imp Vols XYZ"); final double[] trueVolsX = new double[100]; final double[] trueVolsY = new double[100]; final double[] trueVolsZ = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdY * (0.1 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); trueVolsX[i] = volfunc.getVolatility(option, fwdX, inObjX); trueVolsY[i] = volfunc.getVolatility(option, fwdY, inObjY); trueVolsZ[i] = objTrueZ.getImpliedVolatilityZ(option, fwdZ); System.out.println(k + "\t" + trueVolsX[i] + "\t" + trueVolsY[i] + "\t" + trueVolsZ[i]); } System.out.println("\n"); final double[] kDataSet = {0.5, 0.7, 0.9, 1.0, 1.2, 1.5, 1.8 }; for (final double k : kDataSet) { final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); final double trueVol = objTrueZ.getImpliedVolatilityZ(option, fwdZ); System.out.println(k + "\t" + trueVol); } System.out.println("\n"); System.out.println("Imp Vols XYZ (1e-6)"); for (int i = 0; i < 100; i++) { // double k = fwdX * (0.1 + 2. * i / 100.); assertEquals(ansVolsX[i], trueVolsX[i], Math.abs((inSigmasX[0] + inSigmasX[1]) / 2.) * 1e-6); assertEquals(ansVolsY[i], trueVolsY[i], Math.abs((inSigmasY[0] + inSigmasY[1]) / 2.) * 1e-6); assertEquals(ansVolsZ[i], trueVolsZ[i], Math.abs((inSigmasZ[0] + inSigmasZ[1]) / 2.) * 1e-6); } System.out.println("\n"); System.out.println("Density X (1e-6)"); final double[] ansDensityX = new double[100]; final double[] ansDensityY = new double[100]; final double[] ansDensityZ = new double[100]; final double[] trueDensityX = new double[100]; final double[] trueDensityY = new double[100]; final double[] trueDensityZ = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdX * (0.01 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansDensityX[i] = getDualGamma(option, fwdX, objAns1X); trueDensityX[i] = getDualGamma(option, fwdX, inObjX); // System.out.println(k + "\t" + ansDensityX[i] + "\t" + trueDensityX[i]); assertEquals(ansDensityX[i], trueDensityX[i], 1e-6); } System.out.println("\n"); System.out.println("Density Y (1e-6)"); for (int i = 0; i < 100; i++) { final double k = fwdY * (0.01 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansDensityY[i] = getDualGamma(option, fwdY, objAns1Y); trueDensityY[i] = getDualGamma(option, fwdY, inObjY); // System.out.println(k + "\t" + ansDensityY[i] + "\t" + trueDensityY[i]); assertEquals(ansDensityY[i], trueDensityY[i], 1e-6); } System.out.println("\n"); System.out.println("Density Z (1e-6)"); for (int i = 0; i < 100; i++) { final double k = fwdY * (0.01 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansDensityZ[i] = getDualGammaZ(option, fwdZ, objZ); trueDensityZ[i] = getDualGammaZ(option, fwdZ, objTrueZ); // System.out.println(k + "\t" + ansDensityZ[i] + "\t" + trueDensityZ[i]); assertEquals(ansDensityZ[i], trueDensityZ[i], 1e-6); } System.out.println("\n"); System.out.println("Density(exp)"); for (int i = 0; i < 100; i++) { final double k = fwdX * (0.1 + 9. * i / 100.); final double denValueX = getDensity(weights, sigmasX, relativePartialForwardsX, k); final double denValueY = getDensity(weights, sigmasY, relativePartialForwardsY, k); final double denValueZ = getDensity(weights, sigmasZ, relativePartialForwardsZ, k); System.out.println(Math.log(k) + "\t" + denValueX + "\t" + denValueY + "\t" + denValueZ); } System.out.println("\n"); System.out.println("Put-Call Parity X (1e-10)"); for (int i = 0; i < 100; i++) { final double k = fwdY * (0.01 + 2. * i / 100.); final EuropeanVanillaOption optionCall = new EuropeanVanillaOption(k, time, true); final EuropeanVanillaOption optionPut = new EuropeanVanillaOption(k, time, false); final double callPrice = getPrice(optionCall, fwdX, objAns1X); final double putPrice = getPrice(optionPut, fwdX, objAns1X); // System.out.println(k + "\t" + (callPrice - putPrice) + "\t" + (fwdX - k)); assertEquals((callPrice - putPrice), (fwdX - k), fwdX * 1e-10); } System.out.println("\n"); System.out.println("Put-Call Parity Y (1e-10)"); for (int i = 0; i < 100; i++) { final double k = fwdY * (0.01 + 2. * i / 100.); final EuropeanVanillaOption optionCall = new EuropeanVanillaOption(k, time, true); final EuropeanVanillaOption optionPut = new EuropeanVanillaOption(k, time, false); final double callPrice = getPrice(optionCall, fwdY, objAns1Y); final double putPrice = getPrice(optionPut, fwdY, objAns1Y); // System.out.println(k + "\t" + (callPrice - putPrice) + "\t" + (fwdY - k)); assertEquals((callPrice - putPrice), (fwdY - k), fwdY * 1e-10); } System.out.println("\n"); System.out.println("Put-Call Parity Z (1e-8)"); for (int i = 0; i < 100; i++) { final double k = fwdZ * (0.01 + 2. * i / 100.); final EuropeanVanillaOption optionCall = new EuropeanVanillaOption(k, time, true); final EuropeanVanillaOption optionPut = new EuropeanVanillaOption(k, time, false); final double callPrice = objZ.getPriceZ(optionCall, fwdZ); final double putPrice = objZ.getPriceZ(optionPut, fwdZ); // System.out.println(k + "\t" + (callPrice - putPrice) + "\t" + (fwdY - k)); assertEquals((callPrice - putPrice), (fwdY - k), fwdY * 1e-10); } } /** * */ @Test (enabled = false) public void testError() { final int nNorms = 2; final int nParams = 5 * nNorms - 3; final int nDataPts = 14; final int nDataPtsX = 7; final int nParamsX = 3 * nNorms - 2; final int nParamsY = 3 * nNorms - 2; final double fwdX = 1.; final double fwdY = 1.; final double time = 1.0; double[] xx = new double[nDataPts]; final double[] yy = new double[nDataPts]; double[] aaGuess1 = new double[nParams]; final double[] aaGuess1X = new double[nParamsX]; final double[] aaGuess1Y = new double[nParamsY]; final double[] rhos = new double[nNorms]; final Random obj = new Random(); final double[] inRelativePartialForwardsX = {1., 1. }; final double[] inRelativePartialForwardsY = {Math.exp(-0.2), (1. - Math.exp(-0.2) * 0.7) / 0.3 }; final double[] inSigmasX = {0.25, 0.7 }; final double[] inSigmasY = {0.3, 0.5 }; final double[] inWeights = {0.7, 0.3 }; final MixedLogNormalModelData inObjX = new MixedLogNormalModelData(inWeights, inSigmasX, inRelativePartialForwardsX); final MixedLogNormalModelData inObjY = new MixedLogNormalModelData(inWeights, inSigmasY, inRelativePartialForwardsY); xx = new double[] {0.5, 0.7, 0.9, 1.0, 1.2, 1.5, 1.8, 0.5, 0.7, 0.9, 1.0, 1.2, 1.5, 1.8 }; final MixedLogNormalVolatilityFunction volfunc = MixedLogNormalVolatilityFunction.getInstance(); Arrays.fill(yy, 0.); for (int j = 0; j < nDataPtsX; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); yy[j] = volfunc.getVolatility(option, fwdX, inObjX); } for (int j = nDataPtsX; j < nDataPts; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); yy[j] = volfunc.getVolatility(option, fwdY, inObjY); } for (int i = 0; i < nNorms; ++i) { rhos[i] = 0.3 * (i + 1.); } System.out.println("true values: " + inSigmasX[0] + "\t" + inSigmasX[1]); System.out.println("\n"); // for (int i = 0; i < nParams; ++i) { // aaGuess1[i] = 1e-2 + obj.nextDouble(); //Too small guess values may cause instability of fitting // System.out.println(aaGuess1[i]); // } aaGuess1 = new double[] {0.7754891006466627, 0.43606844423507685, 0.012213666603921194, 0.29500288815152165, 0.5444481098115485, 0.5291315433000237, 0.2231641334515797 }; MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); final boolean fitDone = false; int counter = 0; while (fitDone == false && counter <= 100000) { counter += 1; for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } MixedLogNormalModelData tmpObj1X = new MixedLogNormalModelData(aaGuess1X, true); double[] tmpSigmasX = tmpObj1X.getVolatilities(); System.out.println("guess: " + tmpSigmasX[0] + "\t" + tmpSigmasX[1]); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); aaGuess1 = fitter1.getParams(); System.out.println("inintial sq: " + fitter1.getInitialSq()); for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } tmpObj1X = new MixedLogNormalModelData(aaGuess1X, true); tmpSigmasX = tmpObj1X.getVolatilities(); System.out.println("answer: " + tmpSigmasX[0] + "\t" + tmpSigmasX[1]); System.out.println("sq: " + fitter1.getFinalSq()); System.out.println("\n"); if (fitter1.getFinalSq() < fitter1.getInitialSq() * 1e-10) { // fitDone = true; } else { for (int i = 0; i < nParams; ++i) { aaGuess1[i] = 1e-2 + obj.nextDouble(); System.out.println(aaGuess1[i]); } fitter1 = new MixedBivariateLogNormalFitter(); } } // for (int i = 0; i < nNorms; ++i) { // aaGuess1X[i] = aaGuess1[i]; // aaGuess1Y[i] = aaGuess1[i + nNorms]; // } // for (int i = 0; i < nNorms - 1; ++i) { // aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; // aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; // aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; // aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; // } // // final MixedLogNormalModelData objAns1X = new MixedLogNormalModelData(aaGuess1X, true); // final double[] weights = objAns1X.getWeights(); // final double[] sigmasX = objAns1X.getVolatilities(); // final double[] relativePartialForwardsX = objAns1X.getRelativeForwards(); // // final MixedLogNormalModelData objAns1Y = new MixedLogNormalModelData(aaGuess1Y, true); // final double[] sigmasY = objAns1Y.getVolatilities(); // final double[] relativePartialForwardsY = objAns1Y.getRelativeForwards(); // // System.out.println("Imp Vols XYZ from fitting"); // // final MixedBivariateLogNormalModelVolatility objZ = new MixedBivariateLogNormalModelVolatility(weights, sigmasX, // sigmasY, relativePartialForwardsX, relativePartialForwardsY, rhos); // // double[] ansVolsX = new double[100]; // double[] ansVolsY = new double[100]; // double[] ansVolsZ = new double[100]; // for (int i = 0; i < 100; i++) { // double k = fwdX * (0.1 + 2. * i / 100.); // final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); // ansVolsX[i] = volfunc.getVolatility(option, fwdX, objAns1X); // ansVolsY[i] = volfunc.getVolatility(option, fwdY, objAns1Y); // ansVolsZ[i] = objZ.getVolatilityZ(option, fwdZ); // // System.out.println(k + "\t" + ansVolsX[i] + "\t" + ansVolsY[i] + "\t" + ansVolsZ[i]); // } // // System.out.println("\n"); // System.out.println("True Imp Vols XYZ"); // // final MixedBivariateLogNormalModelVolatility objTrueZ = new MixedBivariateLogNormalModelVolatility(inWeights, inSigmasX, // inSigmasY, inRelativePartialForwardsX, inRelativePartialForwardsY, rhos); // // double[] trueVolsX = new double[100]; // double[] trueVolsY = new double[100]; // double[] trueVolsZ = new double[100]; // for (int i = 0; i < 100; i++) { // double k = fwdY * (0.1 + 2. * i / 100.); // final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); // trueVolsX[i] = volfunc.getVolatility(option, fwdX, inObjX); // trueVolsY[i] = volfunc.getVolatility(option, fwdY, inObjY); // trueVolsZ[i] = objTrueZ.getVolatilityZ(option, fwdZ); // // System.out.println(k + "\t" + trueVolsX[i] + "\t" + trueVolsY[i] + "\t" + trueVolsZ[i]); // // } // // System.out.println("\n"); // System.out.println("Imp Vols XYZ (1e-5)"); // // final double[] inSigmasZ = objTrueZ.getVolatilitiesZ(); // // for (int i = 0; i < 100; i++) { // double k = fwdX * (0.1 + 2. * i / 100.); // assertEquals("Imp Vols of X " + k, ansVolsX[i], trueVolsX[i], Math.abs((inSigmasX[0] + inSigmasX[1]) / 2.) * 1e-5); // assertEquals("Imp Vols of Y " + k, ansVolsY[i], trueVolsY[i], Math.abs((inSigmasY[0] + inSigmasY[1]) / 2.) * 1e-5); // assertEquals("Imp Vols of Z " + k, ansVolsZ[i], trueVolsZ[i], Math.abs((inSigmasZ[0] + inSigmasZ[1]) / 2.) * 1e-5); // } } /** * */ @Test(enabled = false) public void testAccuracy() { final int nNorms = 2; final int nParams = 5 * nNorms - 3; final int nDataPts = 14; final int nDataPtsX = 7; final int nParamsX = 3 * nNorms - 2; final int nParamsY = 3 * nNorms - 2; final double fwdX = 1.; final double fwdY = 1.; final double fwdZ = fwdX / fwdY; final double time = 1.0; final double[] yy = new double[nDataPts]; double[] aaGuess1 = new double[nParams]; final double[] aaGuess1X = new double[nParamsX]; final double[] aaGuess1Y = new double[nParamsY]; final double[] rhos = new double[nNorms]; final Random obj = new Random(); final double[] inRelativePartialForwardsX = {1., 1. }; final double[] inRelativePartialForwardsY = {Math.exp(-0.2), (1. - Math.exp(-0.2) * 0.7) / 0.3 }; final double[] inSigmasX = {0.25, 0.7 }; final double[] inSigmasY = {0.3, 0.5 }; final double[] inWeights = {0.7, 0.3 }; final MixedLogNormalModelData inObjX = new MixedLogNormalModelData(inWeights, inSigmasX, inRelativePartialForwardsX); final MixedLogNormalModelData inObjY = new MixedLogNormalModelData(inWeights, inSigmasY, inRelativePartialForwardsY); final double[] xx = new double[] {0.5, 0.7, 0.9, 1.0, 1.2, 1.5, 1.8, 0.5, 0.7, 0.9, 1.0, 1.2, 1.5, 1.8 }; final MixedLogNormalVolatilityFunction volfunc = MixedLogNormalVolatilityFunction.getInstance(); Arrays.fill(yy, 0.); for (int j = 0; j < nDataPtsX; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); yy[j] = volfunc.getVolatility(option, fwdX, inObjX); } for (int j = nDataPtsX; j < nDataPts; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); yy[j] = volfunc.getVolatility(option, fwdY, inObjY); } for (int i = 0; i < nNorms; ++i) { rhos[i] = 0.2 * (0.5 * i + 1.); } System.out.println("true values: " + inSigmasX[0] + "\t" + inSigmasX[1]); System.out.println("\n"); for (int i = 0; i < nParams; ++i) { aaGuess1[i] = 1e-2 + obj.nextDouble(); } MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); boolean fitDone = false; while (fitDone == false) { for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } MixedLogNormalModelData tmpObj1X = new MixedLogNormalModelData(aaGuess1X, true); double[] tmpSigmasX = tmpObj1X.getVolatilities(); System.out.println("guess: " + tmpSigmasX[0] + "\t" + tmpSigmasX[1]); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); aaGuess1 = fitter1.getParams(); System.out.println("inintial sq: " + fitter1.getInitialSq()); for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } tmpObj1X = new MixedLogNormalModelData(aaGuess1X, true); tmpSigmasX = tmpObj1X.getVolatilities(); if (fitter1.getFinalSq() <= fitter1.getInitialSq() * 1e-14) { fitDone = true; System.out.println("\n"); System.out.println("answer: " + tmpSigmasX[0] + "\t" + tmpSigmasX[1]); System.out.println("sq: " + fitter1.getFinalSq()); System.out.println("\n"); System.out.println("\n"); } else { for (int i = 0; i < nParams; ++i) { aaGuess1[i] = 1e-2 + obj.nextDouble(); } fitter1 = new MixedBivariateLogNormalFitter(); } } for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } final MixedLogNormalModelData objAns1X = new MixedLogNormalModelData(aaGuess1X, true); final double[] weights = objAns1X.getWeights(); final double[] sigmasX = objAns1X.getVolatilities(); final double[] relativePartialForwardsX = objAns1X.getRelativeForwards(); final MixedLogNormalModelData objAns1Y = new MixedLogNormalModelData(aaGuess1Y, true); final double[] sigmasY = objAns1Y.getVolatilities(); final double[] relativePartialForwardsY = objAns1Y.getRelativeForwards(); final MixedBivariateLogNormalModelVolatility objZ = new MixedBivariateLogNormalModelVolatility(weights, sigmasX, sigmasY, relativePartialForwardsX, relativePartialForwardsY, rhos); final double[] ansVolsX = new double[100]; final double[] ansVolsY = new double[100]; final double[] ansVolsZ = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdX * (0.1 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansVolsX[i] = volfunc.getVolatility(option, fwdX, objAns1X); ansVolsY[i] = volfunc.getVolatility(option, fwdY, objAns1Y); ansVolsZ[i] = objZ.getImpliedVolatilityZ(option, fwdZ); // System.out.println(k + "\t" + ansVolsX[i] + "\t" + ansVolsY[i] + "\t" + ansVolsZ[i]); } final MixedBivariateLogNormalModelVolatility objTrueZ = new MixedBivariateLogNormalModelVolatility(inWeights, inSigmasX, inSigmasY, inRelativePartialForwardsX, inRelativePartialForwardsY, rhos); final double[] trueVolsX = new double[100]; final double[] trueVolsY = new double[100]; final double[] trueVolsZ = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdY * (0.1 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); trueVolsX[i] = volfunc.getVolatility(option, fwdX, inObjX); trueVolsY[i] = volfunc.getVolatility(option, fwdY, inObjY); trueVolsZ[i] = objTrueZ.getImpliedVolatilityZ(option, fwdZ); // System.out.println(k + "\t" + trueVolsX[i] + "\t" + trueVolsY[i] + "\t" + trueVolsZ[i]); } final double[] inSigmasZ = objTrueZ.getSigmasZ(); for (int i = 0; i < 100; i++) { // double k = fwdX * (0.1 + 2. * i / 100.); assertEquals(ansVolsX[i], trueVolsX[i], Math.abs((inSigmasX[0] + inSigmasX[1]) / 2.) * 1e-6); assertEquals(ansVolsY[i], trueVolsY[i], Math.abs((inSigmasY[0] + inSigmasY[1]) / 2.) * 1e-6); assertEquals(ansVolsZ[i], trueVolsZ[i], Math.abs((inSigmasZ[0] + inSigmasZ[1]) / 2.) * 1e-6); } } /** * */ @Test (enabled = false) public void testAccuracy2() { final int nNorms = 2; final int nParams = 5 * nNorms - 3; final int nDataPts = 14; final int nDataPtsX = 7; final int nParamsX = 3 * nNorms - 2; final int nParamsY = 3 * nNorms - 2; final double fwdX = 1.; final double fwdY = 1.; final double fwdZ = fwdX / fwdY; final double time = 1.0; double[] xx = new double[nDataPts]; final double[] yy = new double[nDataPts]; double[] aaGuess1 = new double[nParams]; final double[] aaGuess1X = new double[nParamsX]; final double[] aaGuess1Y = new double[nParamsY]; final double[] rhos = new double[nNorms]; final Random obj = new Random(); final double[] inRelativePartialForwardsX = {1., 1. }; final double[] inRelativePartialForwardsY = {Math.exp(-0.2), (1. - Math.exp(-0.2) * 0.7) / 0.3 }; final double[] inSigmasX = {0.25, 0.7 }; final double[] inSigmasY = {0.3, 0.5 }; final double[] inWeights = {0.7, 0.3 }; final MixedLogNormalModelData inObjX = new MixedLogNormalModelData(inWeights, inSigmasX, inRelativePartialForwardsX); final MixedLogNormalModelData inObjY = new MixedLogNormalModelData(inWeights, inSigmasY, inRelativePartialForwardsY); xx = new double[] {0.5, 0.7, 0.9, 1.0, 1.2, 1.5, 1.8, 0.5, 0.7, 0.9, 1.0, 1.2, 1.5, 1.8 }; final MixedLogNormalVolatilityFunction volfunc = MixedLogNormalVolatilityFunction.getInstance(); Arrays.fill(yy, 0.); for (int j = 0; j < nDataPtsX; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); yy[j] = volfunc.getVolatility(option, fwdX, inObjX); } for (int j = nDataPtsX; j < nDataPts; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); yy[j] = volfunc.getVolatility(option, fwdY, inObjY); } for (int i = 0; i < nNorms; ++i) { rhos[i] = 0.2 * (0.5 * i + 1.); } // System.out.println("true values: " + inSigmasX[0] + "\t" + inSigmasX[1]); // System.out.println("\n"); for (int i = 0; i < nParams; ++i) { aaGuess1[i] = 1e-2 + obj.nextDouble(); } MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); boolean fitDone = false; while (fitDone == false) { for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } // MixedLogNormalModelData tmpObj1X = new MixedLogNormalModelData(aaGuess1X, true); //double[] tmpSigmasX = tmpObj1X.getVolatilities(); // System.out.println("guess: " + tmpSigmasX[0] + "\t" + tmpSigmasX[1]); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1.); aaGuess1 = fitter1.getParams(); System.out.println("inintial sq: " + fitter1.getInitialSq()); System.out.println("final sq: " + fitter1.getFinalSq()); System.out.println("\n"); for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } // tmpObj1X = new MixedLogNormalModelData(aaGuess1X, true); // tmpSigmasX = tmpObj1X.getVolatilities(); if (fitter1.getFinalSq() <= fitter1.getInitialSq() * 1e-14) { fitDone = true; //System.out.println("\n"); //System.out.println("answer: " + tmpSigmasX[0] + "\t" + tmpSigmasX[1]); System.out.println("XY Fitting Done"); System.out.println("\n"); } else { for (int i = 0; i < nParams; ++i) { aaGuess1[i] = 1e-2 + obj.nextDouble(); } fitter1 = new MixedBivariateLogNormalFitter(); } } for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } final MixedLogNormalModelData objAns1X = new MixedLogNormalModelData(aaGuess1X, true); final double[] weights = objAns1X.getWeights(); final double[] sigmasX = objAns1X.getVolatilities(); final double[] relativePartialForwardsX = objAns1X.getRelativeForwards(); final MixedLogNormalModelData objAns1Y = new MixedLogNormalModelData(aaGuess1Y, true); final double[] sigmasY = objAns1Y.getVolatilities(); final double[] relativePartialForwardsY = objAns1Y.getRelativeForwards(); final MixedBivariateLogNormalModelVolatility objTrueZ = new MixedBivariateLogNormalModelVolatility(inWeights, inSigmasX, inSigmasY, inRelativePartialForwardsX, inRelativePartialForwardsY, rhos); final double[] xxZ = new double[nDataPtsX]; final double[] yyZ = new double[nDataPtsX]; for (int j = 0; j < nDataPtsX; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); xxZ[j] = xx[j]; yyZ[j] = objTrueZ.getImpliedVolatilityZ(option, fwdZ); } double[] rhosGuess = new double[nNorms]; for (int i = 0; i < nNorms; ++i) { rhosGuess[i] = 1. - obj.nextDouble(); } MixedBivariateLogNormalCorrelationFinder fitter = new MixedBivariateLogNormalCorrelationFinder(); boolean fitRhoDone = false; int counterRho = 0; while (fitRhoDone == false) { ++counterRho; fitter.doFit(rhosGuess, xxZ, yyZ, time, weights, sigmasX, sigmasY, relativePartialForwardsX, relativePartialForwardsY, fwdX, fwdY); rhosGuess = fitter.getParams(); System.out.println("\n"); System.out.println("inintial sq: " + fitter.getInitialSq()); System.out.println("final sq: " + fitter.getFinalSq()); System.out.println("\n"); if (fitter.getFinalSq() <= 1e-14) { fitRhoDone = true; System.out.println("Rho Fitting Done"); } else { for (int i = 0; i < nNorms; ++i) { rhosGuess[i] = 1. - obj.nextDouble(); } fitter = new MixedBivariateLogNormalCorrelationFinder(); } ArgumentChecker.isTrue(counterRho < 500, "Too many inerations for rho. Start with new guess parameters."); } System.out.println("\n"); rhosGuess = fitter.getParams(); final MixedBivariateLogNormalModelVolatility objZ = new MixedBivariateLogNormalModelVolatility(weights, sigmasX, sigmasY, relativePartialForwardsX, relativePartialForwardsY, rhosGuess); final double[] ansVolsX = new double[100]; final double[] ansVolsY = new double[100]; final double[] ansVolsZ = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdX * (0.1 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansVolsX[i] = volfunc.getVolatility(option, fwdX, objAns1X); ansVolsY[i] = volfunc.getVolatility(option, fwdY, objAns1Y); ansVolsZ[i] = objZ.getImpliedVolatilityZ(option, fwdZ); // System.out.println(k + "\t" + ansVolsX[i] + "\t" + ansVolsY[i] + "\t" + ansVolsZ[i]); } final double[] trueVolsX = new double[100]; final double[] trueVolsY = new double[100]; final double[] trueVolsZ = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdY * (0.1 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); trueVolsX[i] = volfunc.getVolatility(option, fwdX, inObjX); trueVolsY[i] = volfunc.getVolatility(option, fwdY, inObjY); trueVolsZ[i] = objTrueZ.getImpliedVolatilityZ(option, fwdZ); // System.out.println(k + "\t" + trueVolsX[i] + "\t" + trueVolsY[i] + "\t" + trueVolsZ[i]); } final double[] inSigmasZ = objTrueZ.getSigmasZ(); for (int i = 0; i < 100; i++) { //double k = fwdX * (0.1 + 2. * i / 100.); assertEquals(ansVolsX[i], trueVolsX[i], Math.abs((inSigmasX[0] + inSigmasX[1]) / 2.) * 1e-7); assertEquals(ansVolsY[i], trueVolsY[i], Math.abs((inSigmasY[0] + inSigmasY[1]) / 2.) * 1e-7); assertEquals(ansVolsZ[i], trueVolsZ[i], Math.abs((inSigmasZ[0] + inSigmasZ[1]) / 2.) * 1e-7); } } /** * */ @Test (enabled = false) public void testNoise() { final int nNorms = 2; final int nParams = 5 * nNorms - 3; final int nDataPts = 14; final int nDataPtsX = 7; final int nParamsX = 3 * nNorms - 2; final int nParamsY = 3 * nNorms - 2; final double fwdX = 1.; final double fwdY = 1.; final double fwdZ = fwdX / fwdY; final double time = 1.0; final double[] yy = new double[nDataPts]; final double[] yyNoRand = new double[nDataPts]; double[] aaGuess1 = new double[nParams]; final double[] aaGuess1X = new double[nParamsX]; final double[] aaGuess1Y = new double[nParamsY]; final Random objRand = new Random(); final NormalRandomNumberGenerator objRandNorm = new NormalRandomNumberGenerator(0, 5e-3); final double[] inRelativePartialForwardsX = {1., 1. }; final double[] inRelativePartialForwardsY = {Math.exp(-0.2), (1. - Math.exp(-0.2) * 0.7) / 0.3 }; final double[] inSigmasX = {0.25, 0.7 }; final double[] inSigmasY = {0.3, 0.5 }; final double[] inWeights = {0.7, 0.3 }; final MixedLogNormalModelData inObjX = new MixedLogNormalModelData(inWeights, inSigmasX, inRelativePartialForwardsX); final MixedLogNormalModelData inObjY = new MixedLogNormalModelData(inWeights, inSigmasY, inRelativePartialForwardsY); final double[] xx = new double[] {0.5, 0.7, 0.9, 1.0, 1.2, 1.5, 1.8, 0.5, 0.7, 0.9, 1.0, 1.2, 1.5, 1.8 }; final MixedLogNormalVolatilityFunction volfunc = MixedLogNormalVolatilityFunction.getInstance(); Arrays.fill(yy, 0.); for (int j = 0; j < nDataPtsX; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); final double[] tmpRandNorm = objRandNorm.getVector(1); yyNoRand[j] = volfunc.getVolatility(option, fwdX, inObjX); yy[j] = yyNoRand[j] * (1. + tmpRandNorm[0]); } for (int j = nDataPtsX; j < nDataPts; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(xx[j], time, true); final double[] tmpRandNorm = objRandNorm.getVector(1); yyNoRand[j] = volfunc.getVolatility(option, fwdY, inObjY); yy[j] = yyNoRand[j] * (1. + tmpRandNorm[0]); } for (int j = 0; j < nDataPts; ++j) { System.out.println(yy[j] + "\t" + yyNoRand[j]); } final double[] rhos = new double[] {0.4, 0.4 }; final MixedBivariateLogNormalModelVolatility objTrueZ = new MixedBivariateLogNormalModelVolatility(inWeights, inSigmasX, inSigmasY, inRelativePartialForwardsX, inRelativePartialForwardsY, rhos); // final double[] inSigmasZ = objTrueZ.getSigmasZ(); // final double[] inRelativePartialForwardsZ = objTrueZ.getRelativeForwardsZ(); System.out.println("true values: " + inSigmasX[0] + "\t" + inSigmasX[1]); System.out.println("\n"); for (int i = 0; i < nParams; ++i) { aaGuess1[i] = 1e-2 + objRand.nextDouble(); } MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); boolean fitDone = false; while (fitDone == false) { for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } MixedLogNormalModelData tmpObj1X = new MixedLogNormalModelData(aaGuess1X, true); double[] tmpSigmasX = tmpObj1X.getVolatilities(); System.out.println("guess: " + tmpSigmasX[0] + "\t" + tmpSigmasX[1]); fitter1.doFit(aaGuess1, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); aaGuess1 = fitter1.getParams(); System.out.println("inintial sq: " + fitter1.getInitialSq()); for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } tmpObj1X = new MixedLogNormalModelData(aaGuess1X, true); tmpSigmasX = tmpObj1X.getVolatilities(); System.out.println("answer: " + tmpSigmasX[0] + "\t" + tmpSigmasX[1]); System.out.println("sq: " + fitter1.getFinalSq()); System.out.println("\n"); if (fitter1.getFinalSq() <= fitter1.getInitialSq() * 1e-6) { fitDone = true; } else { for (int i = 0; i < nParams; ++i) { aaGuess1[i] = 1e-2 + objRand.nextDouble(); } fitter1 = new MixedBivariateLogNormalFitter(); } } for (int i = 0; i < nNorms; ++i) { aaGuess1X[i] = aaGuess1[i]; aaGuess1Y[i] = aaGuess1[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuess1X[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1X[i + 2 * nNorms - 1] = aaGuess1[i + 3 * nNorms - 1]; aaGuess1Y[i + nNorms] = aaGuess1[i + 2 * nNorms]; aaGuess1Y[i + 2 * nNorms - 1] = aaGuess1[i + 4 * nNorms - 2]; } final MixedLogNormalModelData objAns1X = new MixedLogNormalModelData(aaGuess1X, true); final double[] weights = objAns1X.getWeights(); final double[] sigmasX = objAns1X.getVolatilities(); final double[] relativePartialForwardsX = objAns1X.getRelativeForwards(); final MixedLogNormalModelData objAns1Y = new MixedLogNormalModelData(aaGuess1Y, true); final double[] sigmasY = objAns1Y.getVolatilities(); final double[] relativePartialForwardsY = objAns1Y.getRelativeForwards(); final MixedBivariateLogNormalModelVolatility objZ = new MixedBivariateLogNormalModelVolatility(weights, sigmasX, sigmasY, relativePartialForwardsX, relativePartialForwardsY, rhos); // final double[] sigmasZ = objZ.getSigmasZ(); // final double[] relativePartialForwardsZ = objZ.getRelativeForwardsZ(); System.out.println("Parameters XY"); for (int i = 0; i < nNorms; ++i) { System.out.println(weights[i] + "\t" + inWeights[i]); // assertEquals("weights ", weights[i], inWeights[i], Math.abs((inWeights[0] + inWeights[1]) / 2.) * 1e-6); } for (int i = 0; i < nNorms; ++i) { System.out.println(sigmasX[i] + "\t" + inSigmasX[i]); // assertEquals("sigmasY ", sigmasX[i], inSigmasX[i], Math.abs((inSigmasX[0] + inSigmasX[1]) / 2.) * 1e-6); } for (int i = 0; i < nNorms; ++i) { System.out.println(sigmasY[i] + "\t" + inSigmasY[i]); // assertEquals("sigmasY ", sigmasY[i], inSigmasY[i], Math.abs((inSigmasY[0] + inSigmasY[1]) / 2.) * 1e-6); } for (int i = 0; i < nNorms; ++i) { System.out.println(relativePartialForwardsX[i] + "\t" + inRelativePartialForwardsX[i]); // assertEquals("relativePartialForwardsX ", relativePartialForwardsX[i], inRelativePartialForwardsX[i], Math.abs((inRelativePartialForwardsX[0] + inRelativePartialForwardsX[1]) / 2.) * 1e-6); } for (int i = 0; i < nNorms; ++i) { System.out.println(relativePartialForwardsY[i] + "\t" + inRelativePartialForwardsY[i]); // assertEquals("relativePartialForwardsY ", relativePartialForwardsY[i], inRelativePartialForwardsY[i], Math.abs((inRelativePartialForwardsY[0] + inRelativePartialForwardsY[1]) / 2.) * 1e-6); } // // System.out.println("\n"); // System.out.println("Parameters Z"); // // for (int i = 0; i < nNorms; ++i) { // System.out.println(sigmasZ[i] + "\t" + inSigmasZ[i]); // assertEquals("sigmasZ ", sigmasZ[i], inSigmasZ[i], Math.abs((inSigmasZ[0] + inSigmasZ[1]) / 2.) * 1e-6); // } // for (int i = 0; i < nNorms; ++i) { // System.out.println(relativePartialForwardsZ[i] + "\t" + inRelativePartialForwardsZ[i]); // assertEquals("relativePartialForwardsZ ", relativePartialForwardsZ[i], inRelativePartialForwardsZ[i], Math.abs((inRelativePartialForwardsZ[0] + inRelativePartialForwardsZ[1]) / 2.) * 1e-6); // } System.out.println("\n"); System.out.println("Imp Vols XYZ from fitting"); final double[] ansVolsX = new double[100]; final double[] ansVolsY = new double[100]; final double[] ansVolsZ = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdX * (0.1 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansVolsX[i] = volfunc.getVolatility(option, fwdX, objAns1X); ansVolsY[i] = volfunc.getVolatility(option, fwdY, objAns1Y); ansVolsZ[i] = objZ.getImpliedVolatilityZ(option, fwdZ); System.out.println(k + "\t" + ansVolsX[i] + "\t" + ansVolsY[i] + "\t" + ansVolsZ[i]); } System.out.println("\n"); System.out.println("True Imp Vols XYZ"); final double[] trueVolsX = new double[100]; final double[] trueVolsY = new double[100]; final double[] trueVolsZ = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdY * (0.1 + 2. * i / 100.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); trueVolsX[i] = volfunc.getVolatility(option, fwdX, inObjX); trueVolsY[i] = volfunc.getVolatility(option, fwdY, inObjY); trueVolsZ[i] = objTrueZ.getImpliedVolatilityZ(option, fwdZ); System.out.println(k + "\t" + trueVolsX[i] + "\t" + trueVolsY[i] + "\t" + trueVolsZ[i]); } } /** * */ @Test (enabled = false) public void testMarketData() { final double[] deltas = new double[] {0.15, 0.25 }; final double[] expiries = new double[] {7. / 365, 14 / 365., 21 / 365., 1 / 12., 3 / 12., 0.5, 0.75, 1, 5 }; final double spotGBPUSD = 1.5993; final double spotEURGBP = 0.83559; final double spotEURUSD = 1.3364; final double[] fwdRateGBPUSD = new double[] {-0.000070, -0.000122, -0.000182, -0.000259, -0.000659, -0.0012900, -0.0019010, -0.002664, -0.0043820 }; final double[] fwdRateEURGBP = new double[] {0.000074, 0.000148, 0.000221, 0.000323, 0.00088250, 0.001677, 0.002481, 0.003268, 0.013689 }; final double[] fwdRateEURUSD = new double[] {0.000062, 0.000132, 0.0002035, 0.00030000, 0.00086550, 0.001638, 0.002328, 0.00298, 0.018482 }; final double[] atmGBPUSD = new double[] {0.060250000000000005, 0.0604, 0.0604, 0.0609, 0.0639, 0.069025, 0.07295, 0.0751, 0.09445 }; final double[] atmEURGBP = new double[] {0.06465, 0.06255, 0.06215, 0.06215, 0.06269999999999999, 0.06565, 0.067625, 0.06925, 0.0885 }; final double[] atmEURUSD = new double[] {0.0885, 0.0809, 0.08085, 0.080275, 0.080525, 0.082825, 0.08504999999999999, 0.086725, 0.09865 }; final double[][] rrGBPUSD = new double[][] { {-0.001075, -0.0019, -0.002525, -0.0031750000000000003, -0.00865, -0.0139, -0.01565, -0.0169, -0.0191 }, {-0.00045, -0.00115, -0.0016250000000000001, -0.002075, -0.005675, -0.00895, -0.01, -0.010900000000000002, -0.012549999999999999 } }; final double[][] rrEURGBP = new double[][] { {0.0018, 0.001325, 0.0008749999999999999, 0.000525, -0.001325, -0.002925, -0.005275, -0.006125, -0.0113 }, {0.0015, 0.001, 0.000675, 0.0004, -0.0009, -0.0017499999999999998, -0.00345, -0.0040999999999999995, -0.00825 } }; final double[][] rrEURUSD = new double[][] { {0.000525, -0.00005, -0.0011, -0.0025, -0.00845, -0.013700000000000002, -0.016675, -0.01905, -0.02265 }, {0.000675, 0.000125, -0.000625, -0.0017000000000000001, -0.005575, -0.00905, -0.0108, -0.012225, -0.014975 } }; final double[][] buttGBPUSD = new double[][] { {0.00315, 0.0028000000000000004, 0.0028499999999999997, 0.0026000000000000003, 0.0040999999999999995, 0.005375, 0.0060750000000000005, 0.006725, 0.00735 }, {0.0013750000000000001, 0.00125, 0.001275, 0.001225, 0.0020250000000000003, 0.002575, 0.002775, 0.003025, 0.003 } }; final double[][] buttEURGBP = new double[][] { {0.00305, 0.0027250000000000004, 0.002925, 0.00305, 0.0037, 0.005124999999999999, 0.006375, 0.006875, 0.00865 }, {0.0014000000000000002, 0.0008, 0.001175, 0.0014000000000000002, 0.0016500000000000002, 0.00215, 0.0027250000000000004, 0.0029, 0.0034000000000000002 } }; final double[][] buttEURUSD = new double[][] { {0.0026000000000000003, 0.0022500000000000003, 0.002425, 0.0023, 0.004225, 0.005625, 0.00645, 0.0072, 0.006600000000000001 }, {0.001225, 0.0011250000000000001, 0.001175, 0.001075, 0.0020250000000000003, 0.0026000000000000003, 0.0029, 0.0031750000000000003, 0.002925 } }; final int nDeltas = deltas.length; final int nExpiries = expiries.length; final double[] fwdGBPUSD = new double[nExpiries]; final double[] fwdEURGBP = new double[nExpiries]; final double[] fwdEURUSD = new double[nExpiries]; for (int i = 0; i < nExpiries; ++i) { fwdGBPUSD[i] = spotGBPUSD * Math.exp(fwdRateGBPUSD[i] * expiries[i]); fwdEURGBP[i] = spotEURGBP * Math.exp(fwdRateEURGBP[i] * expiries[i]); fwdEURUSD[i] = spotEURUSD * Math.exp(fwdRateEURUSD[i] * expiries[i]); } final double[][] strikeGBPUSD = new double[nExpiries][]; final double[][] volGBPUSD = new double[nExpiries][]; final double[][] strikeEURGBP = new double[nExpiries][]; final double[][] volEURGBP = new double[nExpiries][]; final double[][] strikeEURUSD = new double[nExpiries][]; final double[][] volEURUSD = new double[nExpiries][]; for (int i = 0; i < nExpiries; i++) { final double[] rr1 = new double[nDeltas]; final double[] s1 = new double[nDeltas]; final double[] rr2 = new double[nDeltas]; final double[] s2 = new double[nDeltas]; final double[] rr3 = new double[nDeltas]; final double[] s3 = new double[nDeltas]; for (int j = 0; j < nDeltas; j++) { rr1[j] = rrGBPUSD[j][i]; s1[j] = buttGBPUSD[j][i]; rr2[j] = rrEURGBP[j][i]; s2[j] = buttEURGBP[j][i]; rr3[j] = rrEURUSD[j][i]; s3[j] = buttEURUSD[j][i]; } final SmileDeltaParameters cal1 = new SmileDeltaParameters(expiries[i], atmGBPUSD[i], deltas, rr1, s1); final SmileDeltaParameters cal2 = new SmileDeltaParameters(expiries[i], atmEURGBP[i], deltas, rr2, s2); final SmileDeltaParameters cal3 = new SmileDeltaParameters(expiries[i], atmEURUSD[i], deltas, rr3, s3); strikeGBPUSD[i] = cal1.getStrike(fwdGBPUSD[i]); volGBPUSD[i] = cal1.getVolatility(); strikeEURGBP[i] = cal2.getStrike(fwdEURGBP[i]); volEURGBP[i] = cal2.getVolatility(); strikeEURUSD[i] = cal3.getStrike(fwdEURUSD[i]); volEURUSD[i] = cal3.getVolatility(); } final int nNorms = 2; final int nParams = 5 * nNorms - 3; final int nDataPtsX = 2 * nDeltas + 1; final int nDataPtsY = 2 * nDeltas + 1; final int nDataPts = nDataPtsX + nDataPtsY; final int nParamsX = 3 * nNorms - 2; final int nParamsY = 3 * nNorms - 2; final double[] xx = new double[nDataPts]; final double[] yy = new double[nDataPts]; double[] aaGuess = new double[nParams]; final double[] aaGuessX = new double[nParamsX]; final double[] aaGuessY = new double[nParamsY]; double[] rhos = new double[nNorms]; final Random objRand = new Random(); final int choiceOfExpiry = 8; final double fwdX = fwdEURUSD[choiceOfExpiry]; final double fwdY = fwdGBPUSD[choiceOfExpiry]; final double fwdZ = fwdX / fwdY; final double time = expiries[choiceOfExpiry]; for (int j = 0; j < nDataPtsX; ++j) { xx[j] = strikeEURUSD[choiceOfExpiry][j]; xx[j + nDataPtsX] = strikeGBPUSD[choiceOfExpiry][j]; yy[j] = volEURUSD[choiceOfExpiry][j]; yy[j + nDataPtsX] = volGBPUSD[choiceOfExpiry][j]; } // final MixedLogNormalVolatilityFunction volfunc = MixedLogNormalVolatilityFunction.getInstance(); rhos = new double[] {0.67, 0.69 }; for (int i = 0; i < nParams; ++i) { aaGuess[i] = 1e-2 + objRand.nextDouble(); } MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); boolean fitDone = false; while (fitDone == false) { for (int i = 0; i < nNorms; ++i) { aaGuessX[i] = aaGuess[i]; aaGuessY[i] = aaGuess[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuessX[i + nNorms] = aaGuess[i + 2 * nNorms]; aaGuessX[i + 2 * nNorms - 1] = aaGuess[i + 3 * nNorms - 1]; aaGuessY[i + nNorms] = aaGuess[i + 2 * nNorms]; aaGuessY[i + 2 * nNorms - 1] = aaGuess[i + 4 * nNorms - 2]; } MixedLogNormalModelData tmpObj1X = new MixedLogNormalModelData(aaGuessX, true); double[] tmpSigmasX = tmpObj1X.getVolatilities(); System.out.println("guess: " + tmpSigmasX[0] + "\t" + tmpSigmasX[1]); fitter1.doFit(aaGuess, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, 1); aaGuess = fitter1.getParams(); System.out.println("inintial sq: " + fitter1.getInitialSq()); for (int i = 0; i < nNorms; ++i) { aaGuessX[i] = aaGuess[i]; aaGuessY[i] = aaGuess[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuessX[i + nNorms] = aaGuess[i + 2 * nNorms]; aaGuessX[i + 2 * nNorms - 1] = aaGuess[i + 3 * nNorms - 1]; aaGuessY[i + nNorms] = aaGuess[i + 2 * nNorms]; aaGuessY[i + 2 * nNorms - 1] = aaGuess[i + 4 * nNorms - 2]; } tmpObj1X = new MixedLogNormalModelData(aaGuessX, true); tmpSigmasX = tmpObj1X.getVolatilities(); System.out.println("answer: " + tmpSigmasX[0] + "\t" + tmpSigmasX[1]); System.out.println("sq: " + fitter1.getFinalSq()); System.out.println("\n"); if (fitter1.getFinalSq() <= fitter1.getInitialSq() * 1e-10) { fitDone = true; } else { for (int i = 0; i < nParams; ++i) { aaGuess[i] = 1e-2 + objRand.nextDouble(); } fitter1 = new MixedBivariateLogNormalFitter(); } } for (int i = 0; i < nNorms; ++i) { aaGuessX[i] = aaGuess[i]; aaGuessY[i] = aaGuess[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuessX[i + nNorms] = aaGuess[i + 2 * nNorms]; aaGuessX[i + 2 * nNorms - 1] = aaGuess[i + 3 * nNorms - 1]; aaGuessY[i + nNorms] = aaGuess[i + 2 * nNorms]; aaGuessY[i + 2 * nNorms - 1] = aaGuess[i + 4 * nNorms - 2]; } final MixedLogNormalModelData objAns1X = new MixedLogNormalModelData(aaGuessX, true); final double[] weights = objAns1X.getWeights(); final double[] sigmasX = objAns1X.getVolatilities(); final double[] relativePartialForwardsX = objAns1X.getRelativeForwards(); final MixedLogNormalModelData objAns1Y = new MixedLogNormalModelData(aaGuessY, true); final double[] sigmasY = objAns1Y.getVolatilities(); final double[] relativePartialForwardsY = objAns1Y.getRelativeForwards(); final MixedBivariateLogNormalModelVolatility objZ = new MixedBivariateLogNormalModelVolatility(weights, sigmasX, sigmasY, relativePartialForwardsX, relativePartialForwardsY, rhos); final double[] sigmasZ = objZ.getSigmasZ(); final double[] relativePartialForwardsZ = objZ.getRelativeForwardsZ(); System.out.println("Parameters XY(weights, sigmasX, sigmasY, relfwdX, relrwdY)"); for (int i = 0; i < nNorms; ++i) { System.out.println(weights[i]); } for (int i = 0; i < nNorms; ++i) { System.out.println(sigmasX[i]); } for (int i = 0; i < nNorms; ++i) { System.out.println(sigmasY[i]); } for (int i = 0; i < nNorms; ++i) { System.out.println(relativePartialForwardsX[i]); } for (int i = 0; i < nNorms; ++i) { System.out.println(relativePartialForwardsY[i]); } System.out.println("\n"); System.out.println("Parameters Z"); for (int i = 0; i < nNorms; ++i) { System.out.println(sigmasZ[i]); } for (int i = 0; i < nNorms; ++i) { System.out.println(relativePartialForwardsZ[i]); } System.out.println("\n"); System.out.println(fwdZ); System.out.println("\n"); System.out.println("Imp Vols XYZ from fitting"); // double[] ansVolsX = new double[100]; // double[] ansVolsY = new double[100]; final double[] ansVolsZ = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdZ * (0.98 + .4 * i / 1000.); final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); //ansVolsX[i] = volfunc.getVolatility(option, fwdX, objAns1X); // ansVolsY[i] = volfunc.getVolatility(option, fwdY, objAns1Y); ansVolsZ[i] = objZ.getImpliedVolatilityZ(option, fwdZ); // System.out.println(k + "\t" + ansVolsX[i] + "\t" + ansVolsY[i]); System.out.println(k + "\t" + ansVolsZ[i]); } System.out.println("\n"); System.out.println("EURUSD(X)"); for (int i = 0; i < nDataPtsX; ++i) { System.out.println(strikeEURUSD[choiceOfExpiry][i] + "\t" + volEURUSD[choiceOfExpiry][i]); } System.out.println("\n"); System.out.println("GBPUSD(Y)"); for (int i = 0; i < nDataPtsX; ++i) { System.out.println(strikeGBPUSD[choiceOfExpiry][i] + "\t" + volGBPUSD[choiceOfExpiry][i]); } System.out.println("\n"); System.out.println("EURGBP(Z)"); for (int i = 0; i < nDataPtsX; ++i) { System.out.println(strikeEURGBP[choiceOfExpiry][i] + "\t" + volEURGBP[choiceOfExpiry][i]); } System.out.println("\n"); System.out.println("fwdX: " + "\t" + fwdX); System.out.println("fwdY: " + "\t" + fwdY); System.out.println("time: " + "\t" + time); } /** * */ @Test(enabled = false) public void testXYfitterZfitter() { final double[] deltas = new double[] {0.15, 0.25 }; final double[] expiries = new double[] {7. / 365, 14 / 365., 21 / 365., 1 / 12., 3 / 12., 0.5, 0.75, 1, 5 }; final double spotGBPUSD = 1.5993; final double spotEURGBP = 0.83559; final double spotEURUSD = 1.3364; final double[] fwdRateGBPUSD = new double[] {-0.000070, -0.000122, -0.000182, -0.000259, -0.000659, -0.0012900, -0.0019010, -0.002664, -0.0043820 }; final double[] fwdRateEURGBP = new double[] {0.000074, 0.000148, 0.000221, 0.000323, 0.00088250, 0.001677, 0.002481, 0.003268, 0.013689 }; final double[] fwdRateEURUSD = new double[] {0.000062, 0.000132, 0.0002035, 0.00030000, 0.00086550, 0.001638, 0.002328, 0.00298, 0.018482 }; final double[] atmGBPUSD = new double[] {0.060250000000000005, 0.0604, 0.0604, 0.0609, 0.0639, 0.069025, 0.07295, 0.0751, 0.09445 }; final double[] atmEURGBP = new double[] {0.06465, 0.06255, 0.06215, 0.06215, 0.06269999999999999, 0.06565, 0.067625, 0.06925, 0.0885 }; final double[] atmEURUSD = new double[] {0.0885, 0.0809, 0.08085, 0.080275, 0.080525, 0.082825, 0.08504999999999999, 0.086725, 0.09865 }; final double[][] rrGBPUSD = new double[][] { {-0.001075, -0.0019, -0.002525, -0.0031750000000000003, -0.00865, -0.0139, -0.01565, -0.0169, -0.0191 }, {-0.00045, -0.00115, -0.0016250000000000001, -0.002075, -0.005675, -0.00895, -0.01, -0.010900000000000002, -0.012549999999999999 } }; final double[][] rrEURGBP = new double[][] { {0.0018, 0.001325, 0.0008749999999999999, 0.000525, -0.001325, -0.002925, -0.005275, -0.006125, -0.0113 }, {0.0015, 0.001, 0.000675, 0.0004, -0.0009, -0.0017499999999999998, -0.00345, -0.0040999999999999995, -0.00825 } }; final double[][] rrEURUSD = new double[][] { {0.000525, -0.00005, -0.0011, -0.0025, -0.00845, -0.013700000000000002, -0.016675, -0.01905, -0.02265 }, {0.000675, 0.000125, -0.000625, -0.0017000000000000001, -0.005575, -0.00905, -0.0108, -0.012225, -0.014975 } }; final double[][] buttGBPUSD = new double[][] { {0.00315, 0.0028000000000000004, 0.0028499999999999997, 0.0026000000000000003, 0.0040999999999999995, 0.005375, 0.0060750000000000005, 0.006725, 0.00735 }, {0.0013750000000000001, 0.00125, 0.001275, 0.001225, 0.0020250000000000003, 0.002575, 0.002775, 0.003025, 0.003 } }; final double[][] buttEURGBP = new double[][] { {0.00305, 0.0027250000000000004, 0.002925, 0.00305, 0.0037, 0.005124999999999999, 0.006375, 0.006875, 0.00865 }, {0.0014000000000000002, 0.0008, 0.001175, 0.0014000000000000002, 0.0016500000000000002, 0.00215, 0.0027250000000000004, 0.0029, 0.0034000000000000002 } }; final double[][] buttEURUSD = new double[][] { {0.0026000000000000003, 0.0022500000000000003, 0.002425, 0.0023, 0.004225, 0.005625, 0.00645, 0.0072, 0.006600000000000001 }, {0.001225, 0.0011250000000000001, 0.001175, 0.001075, 0.0020250000000000003, 0.0026000000000000003, 0.0029, 0.0031750000000000003, 0.002925 } }; final int nDeltas = deltas.length; final int nExpiries = expiries.length; final double[] fwdGBPUSD = new double[nExpiries]; final double[] fwdEURGBP = new double[nExpiries]; final double[] fwdEURUSD = new double[nExpiries]; for (int i = 0; i < nExpiries; ++i) { fwdGBPUSD[i] = spotGBPUSD * Math.exp(fwdRateGBPUSD[i] * expiries[i]); fwdEURGBP[i] = spotEURGBP * Math.exp(fwdRateEURGBP[i] * expiries[i]); fwdEURUSD[i] = spotEURUSD * Math.exp(fwdRateEURUSD[i] * expiries[i]); } final double[][] strikeGBPUSD = new double[nExpiries][]; final double[][] volGBPUSD = new double[nExpiries][]; final double[][] strikeEURGBP = new double[nExpiries][]; final double[][] volEURGBP = new double[nExpiries][]; final double[][] strikeEURUSD = new double[nExpiries][]; final double[][] volEURUSD = new double[nExpiries][]; for (int i = 0; i < nExpiries; i++) { final double[] rr1 = new double[nDeltas]; final double[] s1 = new double[nDeltas]; final double[] rr2 = new double[nDeltas]; final double[] s2 = new double[nDeltas]; final double[] rr3 = new double[nDeltas]; final double[] s3 = new double[nDeltas]; for (int j = 0; j < nDeltas; j++) { rr1[j] = rrGBPUSD[j][i]; s1[j] = buttGBPUSD[j][i]; rr2[j] = rrEURGBP[j][i]; s2[j] = buttEURGBP[j][i]; rr3[j] = rrEURUSD[j][i]; s3[j] = buttEURUSD[j][i]; } final SmileDeltaParameters cal1 = new SmileDeltaParameters(expiries[i], atmGBPUSD[i], deltas, rr1, s1); final SmileDeltaParameters cal2 = new SmileDeltaParameters(expiries[i], atmEURGBP[i], deltas, rr2, s2); final SmileDeltaParameters cal3 = new SmileDeltaParameters(expiries[i], atmEURUSD[i], deltas, rr3, s3); strikeGBPUSD[i] = cal1.getStrike(fwdGBPUSD[i]); volGBPUSD[i] = cal1.getVolatility(); strikeEURGBP[i] = cal2.getStrike(fwdEURGBP[i]); volEURGBP[i] = cal2.getVolatility(); strikeEURUSD[i] = cal3.getStrike(fwdEURUSD[i]); volEURUSD[i] = cal3.getVolatility(); } final int nNorms = 5; final int nParams = 5 * nNorms - 3; final int nDataPtsX = 2 * nDeltas + 1; final int nDataPtsY = 2 * nDeltas + 1; final int nDataPts = nDataPtsX + nDataPtsY; final int nParamsX = 3 * nNorms - 2; final int nParamsY = 3 * nNorms - 2; final double[] xx = new double[nDataPts]; final double[] yy = new double[nDataPts]; double[] aaGuess = new double[nParams]; final double[] aaGuessX = new double[nParamsX]; final double[] aaGuessY = new double[nParamsY]; double[] rhosGuess = new double[nNorms]; final Random objRand = new Random(); final int choiceOfExpiry = 3; final double fwdX = fwdEURUSD[choiceOfExpiry]; final double fwdY = fwdGBPUSD[choiceOfExpiry]; final double fwdZ = fwdX / fwdY; final double time = expiries[choiceOfExpiry]; for (int j = 0; j < nDataPtsX; ++j) { xx[j] = strikeEURUSD[choiceOfExpiry][j]; xx[j + nDataPtsX] = strikeGBPUSD[choiceOfExpiry][j]; yy[j] = volEURUSD[choiceOfExpiry][j]; yy[j + nDataPtsX] = volGBPUSD[choiceOfExpiry][j]; } final MixedLogNormalVolatilityFunction volfunc = MixedLogNormalVolatilityFunction.getInstance(); for (int i = 0; i < nParams; ++i) { aaGuess[i] = (choiceOfExpiry + 1.) * (1e-2 + objRand.nextDouble()); } final double aaGuessFactor = choiceOfExpiry + 1.; MixedBivariateLogNormalFitter fitter1 = new MixedBivariateLogNormalFitter(); final double prec = 1e-6; // Precision should be chosen depending on maturities boolean fitDone = false; int counter = 0; while (fitDone == false) { ++counter; for (int i = 0; i < nNorms; ++i) { aaGuessX[i] = aaGuess[i]; aaGuessY[i] = aaGuess[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuessX[i + nNorms] = aaGuess[i + 2 * nNorms]; aaGuessX[i + 2 * nNorms - 1] = aaGuess[i + 3 * nNorms - 1]; aaGuessY[i + nNorms] = aaGuess[i + 2 * nNorms]; aaGuessY[i + 2 * nNorms - 1] = aaGuess[i + 4 * nNorms - 2]; } fitter1.doFit(aaGuess, xx, yy, time, fwdX, fwdY, nNorms, nDataPtsX, aaGuessFactor); aaGuess = fitter1.getParams(); System.out.println("XYinintial sq: " + fitter1.getInitialSq()); for (int i = 0; i < nNorms; ++i) { aaGuessX[i] = aaGuess[i]; aaGuessY[i] = aaGuess[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuessX[i + nNorms] = aaGuess[i + 2 * nNorms]; aaGuessX[i + 2 * nNorms - 1] = aaGuess[i + 3 * nNorms - 1]; aaGuessY[i + nNorms] = aaGuess[i + 2 * nNorms]; aaGuessY[i + 2 * nNorms - 1] = aaGuess[i + 4 * nNorms - 2]; } System.out.println("XYsq: " + fitter1.getFinalSq()); System.out.println("\n"); if (fitter1.getFinalSq() <= prec) { fitDone = true; System.out.println("XY Fitting Done"); } else { for (int i = 0; i < nParams; ++i) { aaGuess[i] = (choiceOfExpiry + 1.) * (1e-2 + objRand.nextDouble()); } fitter1 = new MixedBivariateLogNormalFitter(); } ArgumentChecker.isTrue(counter < 500, "Reduce the precision."); } for (int i = 0; i < nNorms; ++i) { aaGuessX[i] = aaGuess[i]; aaGuessY[i] = aaGuess[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { aaGuessX[i + nNorms] = aaGuess[i + 2 * nNorms]; aaGuessX[i + 2 * nNorms - 1] = aaGuess[i + 3 * nNorms - 1]; aaGuessY[i + nNorms] = aaGuess[i + 2 * nNorms]; aaGuessY[i + 2 * nNorms - 1] = aaGuess[i + 4 * nNorms - 2]; } final MixedLogNormalModelData objAns1X = new MixedLogNormalModelData(aaGuessX, true); final double[] weights = objAns1X.getWeights(); final double[] sigmasX = objAns1X.getVolatilities(); final double[] relativePartialForwardsX = objAns1X.getRelativeForwards(); final MixedLogNormalModelData objAns1Y = new MixedLogNormalModelData(aaGuessY, true); final double[] sigmasY = objAns1Y.getVolatilities(); final double[] relativePartialForwardsY = objAns1Y.getRelativeForwards(); final Random randObj = new Random(); for (int i = 0; i < nNorms; ++i) { rhosGuess[i] = 1. - randObj.nextDouble(); } MixedBivariateLogNormalCorrelationFinder fitter = new MixedBivariateLogNormalCorrelationFinder(); boolean fitRhoDone = false; int counterRho = 0; while (fitRhoDone == false) { ++counterRho; fitter.doFit(rhosGuess, strikeEURGBP[choiceOfExpiry], volEURGBP[choiceOfExpiry], time, weights, sigmasX, sigmasY, relativePartialForwardsX, relativePartialForwardsY, fwdX, fwdY); rhosGuess = fitter.getParams(); System.out.println("\n"); System.out.println("inintial sq: " + fitter.getInitialSq()); System.out.println("final sq: " + fitter.getFinalSq()); System.out.println("\n"); if (fitter.getFinalSq() <= prec * 1e2) { fitRhoDone = true; System.out.println("Rho Fitting Done"); } else { for (int i = 0; i < nNorms; ++i) { rhosGuess[i] = 1. - randObj.nextDouble(); } fitter = new MixedBivariateLogNormalCorrelationFinder(); } ArgumentChecker.isTrue(counterRho < 500, "Too many inerations for rho. Start with new guess parameters."); } System.out.println("\n"); rhosGuess = fitter.getParams(); final MixedBivariateLogNormalModelVolatility objZ = new MixedBivariateLogNormalModelVolatility(weights, sigmasX, sigmasY, relativePartialForwardsX, relativePartialForwardsY, rhosGuess); final double[] sigmasZ = objZ.getSigmasZ(); final double[] relativePartialForwardsZ = objZ.getRelativeForwardsZ(); System.out.println("Parameters XY(weights, sigmasX, sigmasY, relfwdX, relrwdY)"); for (int i = 0; i < nNorms; ++i) { System.out.println(weights[i]); } for (int i = 0; i < nNorms; ++i) { System.out.println(sigmasX[i]); } for (int i = 0; i < nNorms; ++i) { System.out.println(sigmasY[i]); } for (int i = 0; i < nNorms; ++i) { System.out.println(relativePartialForwardsX[i]); } for (int i = 0; i < nNorms; ++i) { System.out.println(relativePartialForwardsY[i]); } System.out.println("\n"); System.out.println("fwdX: " + "\t" + fwdX); System.out.println("fwdY: " + "\t" + fwdY); System.out.println("\n"); System.out.println("rhos"); for (int i = 0; i < nNorms; ++i) { System.out.println(rhosGuess[i]); } System.out.println("\n"); System.out.println("Parameters Z"); for (int i = 0; i < nNorms; ++i) { System.out.println(sigmasZ[i]); } for (int i = 0; i < nNorms; ++i) { System.out.println(relativePartialForwardsZ[i]); } System.out.println("\n"); System.out.println("fwdZ: " + "\t" + fwdZ); System.out.println("\n"); System.out.println("Imp Vols Z from fitting"); final double[] ansVolsX = new double[100]; final double[] ansVolsY = new double[100]; final double[] ansVolsZ = new double[100]; for (int i = 0; i < 100; i++) { final double k = fwdZ * (0.9 + choiceOfExpiry * 0.01 + (.2 - choiceOfExpiry * 0.02) * i / 100.); //The range should be appropriately chosen depending on expiry final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansVolsZ[i] = objZ.getImpliedVolatilityZ(option, fwdZ); System.out.println(k + "\t" + ansVolsZ[i]); } System.out.println("\n"); System.out.println("Imp Vols X from fitting"); for (int i = 0; i < 100; i++) { final double k = fwdX * (0.9 + .2 * i / 100.); //The range should be appropriately chosen depending on expiry final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansVolsX[i] = volfunc.getVolatility(option, fwdX, objAns1X); System.out.println(k + "\t" + ansVolsX[i]); } System.out.println("\n"); System.out.println("Imp Vols Y from fitting"); for (int i = 0; i < 100; i++) { final double k = fwdY * (0.9 + .2 * i / 100.); //The range should be appropriately chosen depending on expiry final EuropeanVanillaOption option = new EuropeanVanillaOption(k, time, true); ansVolsY[i] = volfunc.getVolatility(option, fwdY, objAns1Y); System.out.println(k + "\t" + ansVolsY[i]); } System.out.println("\n"); System.out.println("EURUSD(X)"); for (int i = 0; i < nDataPtsX; ++i) { System.out.println(strikeEURUSD[choiceOfExpiry][i] + "\t" + volEURUSD[choiceOfExpiry][i]); } System.out.println("\n"); System.out.println("GBPUSD(Y)"); for (int i = 0; i < nDataPtsX; ++i) { System.out.println(strikeGBPUSD[choiceOfExpiry][i] + "\t" + volGBPUSD[choiceOfExpiry][i]); } System.out.println("\n"); System.out.println("EURGBP(Z)"); for (int i = 0; i < nDataPtsX; ++i) { System.out.println(strikeEURGBP[choiceOfExpiry][i] + "\t" + volEURGBP[choiceOfExpiry][i]); } System.out.println("\n"); System.out.println("time: " + "\t" + time); } /** * */ @Test (enabled = false) public void checkingModelParams() { final int nNorms = 2; final int nDataPts = 14; final int nParamsX = 3 * nNorms - 2; final int nParamsY = 3 * nNorms - 2; final double[] yy = new double[nDataPts]; final double[] params = {0.03411550042789113, 0.0483524833777188, 0.2580039977762099, 0.4351726013225261, 0.8361207722192964, 0.7153215152466372, 0.7286439693179121 }; final double[] paramsX = new double[nParamsX]; final double[] paramsY = new double[nParamsY]; for (int i = 0; i < nNorms; ++i) { paramsX[i] = params[i]; paramsY[i] = params[i + nNorms]; } for (int i = 0; i < nNorms - 1; ++i) { paramsX[i + nNorms] = params[i + 2 * nNorms]; paramsX[i + 2 * nNorms - 1] = params[i + 3 * nNorms - 1]; paramsY[i + nNorms] = params[i + 2 * nNorms]; paramsY[i + 2 * nNorms - 1] = params[i + 4 * nNorms - 2]; } final MixedLogNormalModelData inObjX = new MixedLogNormalModelData(paramsX, true); final MixedLogNormalModelData inObjY = new MixedLogNormalModelData(paramsY, true); final double[] relativePartialForwardsX = inObjX.getRelativeForwards(); final double[] sigmasX = inObjX.getVolatilities(); final double[] relativePartialForwardsY = inObjY.getRelativeForwards(); final double[] sigmasY = inObjY.getVolatilities(); final double[] weights = inObjX.getWeights(); Arrays.fill(yy, 0.); System.out.println("sigmasX: " + "\t" + sigmasX[0] + "\t" + sigmasX[1]); System.out.println("sigmasY: " + "\t" + sigmasY[0] + "\t" + sigmasY[1]); System.out.println("weights: " + "\t" + weights[0] + "\t" + weights[1]); System.out.println("relativePartialForwardsX: " + "\t" + relativePartialForwardsX[0] + "\t" + relativePartialForwardsX[1]); System.out.println("relativePartialForwardsY: " + "\t" + relativePartialForwardsY[0] + "\t" + relativePartialForwardsY[1]); System.out.println("\n"); } private double getDensity(final double[] ws, final double[] sigs, final double[] rpfs, final double iValue) { double res = 0.; final int nNorms = ws.length; for (int i = 0; i < nNorms; ++i) { res += ws[i] * Math.exp(-0.5 * (Math.log(iValue) - (Math.log(rpfs[i]) - 0.5 * sigs[i] * sigs[i])) * (Math.log(iValue) - (Math.log(rpfs[i]) - 0.5 * sigs[i] * sigs[i])) / sigs[i] / sigs[i]); } return res; } private double getPrice(final EuropeanVanillaOption option, final double forward, final MixedLogNormalModelData data) { final double[] w = data.getWeights(); final double[] sigma = data.getVolatilities(); final double[] rf = data.getRelativeForwards(); final int n = w.length; final double t = option.getTimeToExpiry(); final double k = option.getStrike(); final double kStar = k / forward; final boolean isCall = option.isCall(); double sum = 0; for (int i = 0; i < n; i++) { sum += w[i] * BlackFormulaRepository.price(rf[i], kStar, t, sigma[i], isCall); } return forward * sum; } private double getDualGamma(final EuropeanVanillaOption option, final double forward, final MixedLogNormalModelData data) { final double[] w = data.getWeights(); final double[] sigma = data.getVolatilities(); final double[] rf = data.getRelativeForwards(); final int n = w.length; final double t = option.getTimeToExpiry(); final double k = option.getStrike(); final double kStar = k / forward; double sum = 0; for (int i = 0; i < n; i++) { sum += w[i] * BlackFormulaRepository.dualGamma(rf[i], kStar, t, sigma[i]); } return forward * sum; } private double getDualGammaZ(final EuropeanVanillaOption option, final double forward, final MixedBivariateLogNormalModelVolatility dataZ) { final double[] w = dataZ.getOrderedWeights(); final double[] sigma = dataZ.getSigmasZ(); final double[] rf = dataZ.getRelativeForwardsZ(); final int n = w.length; final double t = option.getTimeToExpiry(); final double k = option.getStrike(); final double kStar = k / forward; double sum = 0; for (int i = 0; i < n; i++) { sum += w[i] * BlackFormulaRepository.dualGamma(rf[i], kStar, t, sigma[i]); } return forward * sum; } private double[] getFunctionValues(final double[] params, final double[] dataStrikes, final double forwardX, final double forwardY, final double timeToExpiry, final int nNormals, final int nData, final int nDataX) { final MixedLogNormalVolatilityFunction volfunc = MixedLogNormalVolatilityFunction.getInstance(); final int dof = 3 * nNormals - 2; final double[] paramsX = new double[dof]; final double[] paramsY = new double[dof]; for (int i = 0; i < nNormals; ++i) { paramsX[i] = params[i]; } for (int i = 0; i < nNormals - 1; ++i) { paramsX[i + nNormals] = params[i + 2 * nNormals]; paramsX[i + 2 * nNormals - 1] = params[i + 3 * nNormals - 1]; } for (int i = 0; i < nNormals; ++i) { paramsY[i] = params[i + nNormals]; } for (int i = 0; i < nNormals - 1; ++i) { paramsY[i + nNormals] = params[i + 2 * nNormals]; paramsY[i + 2 * nNormals - 1] = params[i + 4 * nNormals - 2]; } final MixedLogNormalModelData dataX = new MixedLogNormalModelData(paramsX, true); final MixedLogNormalModelData dataY = new MixedLogNormalModelData(paramsY, true); final double[] res = new double[nData]; Arrays.fill(res, 0.); for (int j = 0; j < nDataX; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(dataStrikes[j], timeToExpiry, true); res[j] = volfunc.getVolatility(option, forwardX, dataX); } for (int j = nDataX; j < nData; ++j) { final EuropeanVanillaOption option = new EuropeanVanillaOption(dataStrikes[j], timeToExpiry, true); res[j] = volfunc.getVolatility(option, forwardY, dataY); } return res; } }