//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void test() public virtual void test() { assertEquals(DATA.Alpha, ALPHA, 0); assertEquals(DATA.Beta, BETA, 0); assertEquals(DATA.Nu, NU, 0); assertEquals(DATA.Rho, RHO, 0); assertEquals(DATA.getParameter(0), ALPHA, 0); assertEquals(DATA.getParameter(1), BETA, 0); assertEquals(DATA.getParameter(2), RHO, 0); assertEquals(DATA.getParameter(3), NU, 0); assertEquals(DATA.NumberOfParameters, 4); SabrFormulaData other = SabrFormulaData.of(new double[] { ALPHA, BETA, RHO, NU }); assertEquals(other, DATA); assertEquals(other.GetHashCode(), DATA.GetHashCode()); other = other.with(0, ALPHA - 0.01); assertFalse(other.Equals(DATA)); other = SabrFormulaData.of(ALPHA, BETA * 0.5, RHO, NU); assertFalse(other.Equals(DATA)); other = SabrFormulaData.of(ALPHA, BETA, RHO, NU * 0.5); assertFalse(other.Equals(DATA)); other = SabrFormulaData.of(ALPHA, BETA, RHO * 0.5, NU); assertFalse(other.Equals(DATA)); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void testATMSmoothness() public virtual void testATMSmoothness() { double timeToExpiry = 1; double alpha = 0.05; double beta = 0.5; double nu = 0.50; double rho = -0.25; int nbPoints = 100; double forward = 0.05; double[] sabrVolatilty = new double[2 * nbPoints + 1]; double range = 5E-9; double[] strike = new double[2 * nbPoints + 1]; for (int looppts = -nbPoints; looppts <= nbPoints; looppts++) { strike[looppts + nbPoints] = forward + ((double)looppts) / nbPoints * range; SabrFormulaData SabrData = SabrFormulaData.of(alpha, beta, rho, nu); sabrVolatilty[looppts + nbPoints] = FUNCTION.volatility(forward, strike[looppts + nbPoints], timeToExpiry, SabrData); } for (int looppts = -nbPoints; looppts < nbPoints; looppts++) { assertTrue(Math.Abs(sabrVolatilty[looppts + nbPoints + 1] - sabrVolatilty[looppts + nbPoints]) / (strike[looppts + nbPoints + 1] - strike[looppts + nbPoints]) < 20.0); } }
//------------------------------------------------------------------------- public virtual void coverage() { coverImmutableBean(DATA); SabrFormulaData another = SabrFormulaData.of(1.2, 0.4, 0.0, 0.2); coverBeanEquals(DATA, another); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void testVolatilityAdjointLargeRhoZLessThan1() public virtual void testVolatilityAdjointLargeRhoZLessThan1() { double eps = 1e-4; double tol = 1e-5; SabrFormulaData data = DATA.withRho(1.0 - 1e-9); testVolatilityAdjoint(F, CALL_ITM, data, eps, tol); }
/// <summary> /// The limit for $rhp \to 1$ when $z \geq 1$ does not exists. Returning an illegal argument. /// </summary> //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void test_rho_close_to_1_large() public virtual void test_rho_close_to_1_large() { double rhoEps = 1.e-5; double rhoIn = 1.0 - 0.5 * rhoEps; SabrFormulaData dataIn = SabrFormulaData.of(ALPHA, BETA, rhoIn, NU); assertThrowsIllegalArg(() => FUNCTION.volatility(10 * F, STRIKE_ITM, T, dataIn)); assertThrowsIllegalArg(() => FUNCTION.volatilityAdjoint(10 * F, STRIKE_ITM, T, dataIn)); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void testVolatilityAdjointSmallAlpha() public virtual void testVolatilityAdjointSmallAlpha() { double eps = 1e-7; double tol = 1e-3; SabrFormulaData data = DATA.withAlpha(1e-5); testVolatilityAdjoint(F, CALL_ATM, data, eps, tol); testVolatilityAdjoint(F, CALL_ITM, data, eps, tol); testVolatilityAdjoint(F, CALL_OTM, data, eps, tol); }
/// <summary> /// Test the rho = 1 edge case /// </summary> //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void testVolatilityAdjointRho1() public virtual void testVolatilityAdjointRho1() { double eps = 1e-4; double tol = 1e-5; SabrFormulaData data = DATA.withRho(1.0); testVolatilityAdjoint(F, CALL_ATM, data, eps, tol); testVolatilityAdjoint(F, CALL_ITM, data, eps, tol); testVolatilityAdjoint(F, CALL_OTM, data, eps, tol); }
/// <summary> /// Test the nu = 0 edge case /// </summary> //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void testVolatilityAdjointNu0() public virtual void testVolatilityAdjointNu0() { double eps = 1e-5; double tol = 1e-6; SabrFormulaData data = DATA.withNu(0.0); testVolatilityAdjoint(F, CALL_ATM, data, eps, tol); testVolatilityAdjoint(F, CALL_ITM, data, eps, 2e-4); testVolatilityAdjoint(F, CALL_OTM, data, eps, 5e-5); }
//----------------------------------------------------------------------- public override bool Equals(object obj) { if (obj == this) { return(true); } if (obj != null && obj.GetType() == this.GetType()) { SabrFormulaData other = (SabrFormulaData)obj; return(JodaBeanUtils.equal(parameters, other.parameters)); } return(false); }
/// <summary> /// Check that $\rho \simeq 1$ case is smoothly connected with a general case, i.e., /// comparing the approximated computation and full computation around the cutoff, which is currently $\rho = 1.0 - 1.0e-5$ /// </summary> //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void test_rho_close_to_1() public virtual void test_rho_close_to_1() { double rhoEps = 1.e-5; // rhoIn is larger than the cutoff, // thus vol and sensitivities are computed by approximation formulas which are regular in the limit rho -> 1. double rhoIn = 1.0 - 0.5 * rhoEps; double rho1 = 1.0d; // rhoOut is smaller than the cutoff, thus vol and sensitivities are computed by full formula. double rhoOut = 1.0 - 1.5 * rhoEps; SabrFormulaData data1 = SabrFormulaData.of(ALPHA, BETA, rho1, NU); SabrFormulaData dataIn = SabrFormulaData.of(ALPHA, BETA, rhoIn, NU); SabrFormulaData dataOut = SabrFormulaData.of(ALPHA, BETA, rhoOut, NU); /* * z<1 case, i.e., finite values in the rho->1 limit */ double volatilityOut = FUNCTION.volatility(F, STRIKE_OTM, T, dataOut); double[] adjointOut = toArray(FUNCTION.volatilityAdjoint(F, STRIKE_OTM, T, dataOut)); double[] volatilityDOut = new double[6]; //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][] volatilityD2Out = new double[2][2]; double[][] volatilityD2Out = RectangularArrays.ReturnRectangularDoubleArray(2, 2); double volatility2Out = FUNCTION.volatilityAdjoint2(F, STRIKE_OTM, T, dataOut, volatilityDOut, volatilityD2Out); double volatilityIn = FUNCTION.volatility(F, STRIKE_OTM, T, dataIn); double[] adjointIn = toArray(FUNCTION.volatilityAdjoint(F, STRIKE_OTM, T, dataIn)); double[] volatilityDIn = new double[6]; //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][] volatilityD2In = new double[2][2]; double[][] volatilityD2In = RectangularArrays.ReturnRectangularDoubleArray(2, 2); double volatility2In = FUNCTION.volatilityAdjoint2(F, STRIKE_OTM, T, dataIn, volatilityDIn, volatilityD2In); double volatility1 = FUNCTION.volatility(F, STRIKE_OTM, T, data1); assertEquals(volatilityOut, volatility1, TOLERANCE_VOL_LIMIT); assertEquals(volatilityOut, volatilityIn, TOLERANCE_VOL_LIMIT); assertEquals(volatility2Out, volatility2In, TOLERANCE_VOL_LIMIT); for (int i = 0; i < adjointOut.Length; ++i) { double @ref = adjointOut[i]; assertEquals(adjointOut[i], adjointIn[i], Math.Max(Math.Abs(@ref), 1.0) * 1.e-3); } for (int i = 0; i < volatilityDOut.Length; ++i) { double @ref = volatilityDOut[i]; assertEquals(volatilityDOut[i], volatilityDIn[i], Math.Max(Math.Abs(@ref), 1.0) * 1.e-3); } }
//TODO write a fuzzer that hits SABR with random parameters //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test(enabled = false) public void testRandomParameters() public virtual void testRandomParameters() { double eps = 1e-5; double tol = 1e-3; for (int count = 0; count < 100; count++) { double alpha = Math.Exp(NORMAL.nextRandom() * 0.2 - 2); double beta = GlobalRandom.NextDouble; //TODO Uniform numbers in distribution double nu = Math.Exp(NORMAL.nextRandom() * 0.3 - 1); double rho = 2 * GlobalRandom.NextDouble - 1; SabrFormulaData data = SabrFormulaData.of(alpha, beta, rho, nu); testVolatilityAdjoint(F, CALL_ATM, data, eps, tol); testVolatilityAdjoint(F, CALL_ITM, data, eps, tol); testVolatilityAdjoint(F, CALL_OTM, data, eps, tol); } }
/// <summary> /// Calculate the true SABR delta and gamma and compare with that found by finite difference /// </summary> //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test(enabled = false) public void testGreeks() public virtual void testGreeks() { double eps = 1e-3; double f = 1.2; double k = 1.4; double t = 5.0; double alpha = 0.3; double beta = 0.6; double rho = -0.4; double nu = 0.4; SabrFormulaData sabrData = SabrFormulaData.of(alpha, beta, rho, nu); ValueDerivatives adj = FUNCTION.volatilityAdjoint(f, k, t, sabrData); double bsDelta = BlackFormulaRepository.delta(f, k, t, adj.Value, true); double bsVega = BlackFormulaRepository.vega(f, k, t, adj.Value); double volForwardSense = adj.getDerivative(1); double delta = bsDelta + bsVega * volForwardSense; SabrFormulaData data = SabrFormulaData.of(alpha, beta, rho, nu); double volUp = FUNCTION.volatility(f + eps, k, t, data); double volDown = FUNCTION.volatility(f - eps, k, t, data); double priceUp = BlackFormulaRepository.price(f + eps, k, t, volUp, true); double price = BlackFormulaRepository.price(f, k, t, adj.Value, true); double priceDown = BlackFormulaRepository.price(f - eps, k, t, volDown, true); double fdDelta = (priceUp - priceDown) / 2 / eps; assertEquals(fdDelta, delta, 1e-6); double bsVanna = BlackFormulaRepository.vanna(f, k, t, adj.Value); double bsGamma = BlackFormulaRepository.gamma(f, k, t, adj.Value); double[] volD1 = new double[5]; //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][] volD2 = new double[2][2]; double[][] volD2 = RectangularArrays.ReturnRectangularDoubleArray(2, 2); FUNCTION.volatilityAdjoint2(f, k, t, sabrData, volD1, volD2); double d2Sigmad2Fwd = volD2[0][0]; double gamma = bsGamma + 2 * bsVanna * adj.getDerivative(1) + bsVega * d2Sigmad2Fwd; double fdGamma = (priceUp + priceDown - 2 * price) / eps / eps; double d2Sigmad2FwdFD = (volUp + volDown - 2 * adj.Value) / eps / eps; assertEquals(d2Sigmad2FwdFD, d2Sigmad2Fwd, 1e-4); assertEquals(fdGamma, gamma, 1e-2); }
/// <summary> /// Test the alpha = 0 edge case. Implied vol is zero for alpha = 0, and except in the ATM case, the alpha sensitivity is infinite. We /// choose to (arbitrarily) return 1e7 in this case. /// </summary> //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void testVolatilityAdjointAlpha0() public virtual void testVolatilityAdjointAlpha0() { double eps = 1e-5; double tol = 1e-6; SabrFormulaData data = DATA.withAlpha(0.0); testVolatilityAdjoint(F, CALL_ATM, data, eps, tol); double volatility = FUNCTION.volatility(F, STRIKE_ITM, T, data); ValueDerivatives volatilityAdjoint = FUNCTION.volatilityAdjoint(F, STRIKE_ITM, T, data); assertEquals(volatility, volatilityAdjoint.Value, tol); assertEquals(0.0, volatilityAdjoint.getDerivative(0), tol); assertEquals(0.0, volatilityAdjoint.getDerivative(1), tol); assertEquals(1e7, volatilityAdjoint.getDerivative(2), tol); assertEquals(0.0, volatilityAdjoint.getDerivative(3), tol); assertEquals(0.0, volatilityAdjoint.getDerivative(4), tol); assertEquals(0.0, volatilityAdjoint.getDerivative(5), tol); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void testWrongParameterLength() public virtual void testWrongParameterLength() { assertThrowsIllegalArg(() => SabrFormulaData.of(new double[] { ALPHA, BETA, RHO, NU, 0.1 })); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @SuppressWarnings("null") private double fdSensitivity(com.opengamma.strata.pricer.impl.option.EuropeanVanillaOption optionData, double forward, SabrFormulaData sabrData, SabrParameter param, double delta) private double fdSensitivity(EuropeanVanillaOption optionData, double forward, SabrFormulaData sabrData, SabrParameter param, double delta) { System.Func <SabrFormulaData, double> funcC = null; System.Func <SabrFormulaData, double> funcB = null; System.Func <SabrFormulaData, double> funcA = null; SabrFormulaData dataC = null; SabrFormulaData dataB = sabrData; SabrFormulaData dataA = null; System.Func <SabrFormulaData, double> func = getVolatilityFunction(optionData, forward); FiniteDifferenceType fdType = null; switch (param) { case com.opengamma.strata.pricer.impl.volatility.smile.SabrHaganVolatilityFunctionProviderTest.SabrParameter.Strike: double strike = optionData.Strike; if (strike >= delta) { fdType = FiniteDifferenceType.CENTRAL; funcA = getVolatilityFunction(withStrike(optionData, strike - delta), forward); funcC = getVolatilityFunction(withStrike(optionData, strike + delta), forward); } else { fdType = FiniteDifferenceType.FORWARD; funcA = func; funcB = getVolatilityFunction(withStrike(optionData, strike + delta), forward); funcC = getVolatilityFunction(withStrike(optionData, strike + 2 * delta), forward); } dataC = sabrData; dataB = sabrData; dataA = sabrData; break; case com.opengamma.strata.pricer.impl.volatility.smile.SabrHaganVolatilityFunctionProviderTest.SabrParameter.Forward: if (forward > delta) { fdType = FiniteDifferenceType.CENTRAL; funcA = getVolatilityFunction(optionData, forward - delta); funcC = getVolatilityFunction(optionData, forward + delta); } else { fdType = FiniteDifferenceType.FORWARD; funcA = func; funcB = getVolatilityFunction(optionData, forward + delta); funcC = getVolatilityFunction(optionData, forward + 2 * delta); } dataC = sabrData; dataB = sabrData; dataA = sabrData; break; case com.opengamma.strata.pricer.impl.volatility.smile.SabrHaganVolatilityFunctionProviderTest.SabrParameter.Alpha: double a = sabrData.Alpha; if (a >= delta) { fdType = FiniteDifferenceType.CENTRAL; dataA = sabrData.withAlpha(a - delta); dataC = sabrData.withAlpha(a + delta); } else { fdType = FiniteDifferenceType.FORWARD; dataA = sabrData; dataB = sabrData.withAlpha(a + delta); dataC = sabrData.withAlpha(a + 2 * delta); } funcC = func; funcB = func; funcA = func; break; case com.opengamma.strata.pricer.impl.volatility.smile.SabrHaganVolatilityFunctionProviderTest.SabrParameter.Beta: double b = sabrData.Beta; if (b >= delta) { fdType = FiniteDifferenceType.CENTRAL; dataA = sabrData.withBeta(b - delta); dataC = sabrData.withBeta(b + delta); } else { fdType = FiniteDifferenceType.FORWARD; dataA = sabrData; dataB = sabrData.withBeta(b + delta); dataC = sabrData.withBeta(b + 2 * delta); } funcC = func; funcB = func; funcA = func; break; case com.opengamma.strata.pricer.impl.volatility.smile.SabrHaganVolatilityFunctionProviderTest.SabrParameter.Nu: double n = sabrData.Nu; if (n >= delta) { fdType = FiniteDifferenceType.CENTRAL; dataA = sabrData.withNu(n - delta); dataC = sabrData.withNu(n + delta); } else { fdType = FiniteDifferenceType.FORWARD; dataA = sabrData; dataB = sabrData.withNu(n + delta); dataC = sabrData.withNu(n + 2 * delta); } funcC = func; funcB = func; funcA = func; break; case com.opengamma.strata.pricer.impl.volatility.smile.SabrHaganVolatilityFunctionProviderTest.SabrParameter.Rho: double r = sabrData.Rho; if ((r + 1) < delta) { fdType = FiniteDifferenceType.FORWARD; dataA = sabrData; dataB = sabrData.withRho(r + delta); dataC = sabrData.withRho(r + 2 * delta); } else if ((1 - r) < delta) { fdType = FiniteDifferenceType.BACKWARD; dataA = sabrData.withRho(r - 2 * delta); dataB = sabrData.withRho(r - delta); dataC = sabrData; } else { fdType = FiniteDifferenceType.CENTRAL; dataC = sabrData.withRho(r + delta); dataA = sabrData.withRho(r - delta); } funcC = func; funcB = func; funcA = func; break; default: throw new MathException("enum not found"); } if (fdType != null) { switch (fdType) { case FiniteDifferenceType.FORWARD: return((-1.5 * funcA(dataA) + 2.0 * funcB(dataB) - 0.5 * funcC(dataC)) / delta); case FiniteDifferenceType.BACKWARD: return((0.5 * funcA(dataA) - 2.0 * funcB(dataB) + 1.5 * funcC(dataC)) / delta); case FiniteDifferenceType.CENTRAL: return((funcC(dataC) - funcA(dataA)) / 2.0 / delta); default: throw new MathException("enum not found"); } } throw new MathException("enum not found"); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void testNegativeNu() public virtual void testNegativeNu() { assertThrowsIllegalArg(() => SabrFormulaData.of(ALPHA, BETA, RHO, -NU)); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void testHighRho() public virtual void testHighRho() { assertThrowsIllegalArg(() => SabrFormulaData.of(ALPHA, BETA, RHO + 10, NU)); }
private void testVolatilityAdjoint(double forward, EuropeanVanillaOption optionData, SabrFormulaData sabrData, double eps, double tol) { double volatility = FUNCTION.volatility(forward, optionData.Strike, optionData.TimeToExpiry, sabrData); double[] volatilityAdjoint = toArray(FUNCTION.volatilityAdjoint(forward, optionData.Strike, optionData.TimeToExpiry, sabrData)); assertEquals(volatility, volatilityAdjoint[0], tol); assertEqualsRelTol("Forward Sensitivity" + sabrData.ToString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Forward, eps), volatilityAdjoint[1], tol); assertEqualsRelTol("Strike Sensitivity" + sabrData.ToString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Strike, eps), volatilityAdjoint[2], tol); assertEqualsRelTol("Alpha Sensitivity" + sabrData.ToString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Alpha, eps), volatilityAdjoint[3], tol); assertEqualsRelTol("Beta Sensitivity" + sabrData.ToString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Beta, eps), volatilityAdjoint[4], tol); assertEqualsRelTol("Rho Sensitivity" + sabrData.ToString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Rho, eps), volatilityAdjoint[5], tol); assertEqualsRelTol("Nu Sensitivity" + sabrData.ToString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Nu, eps), volatilityAdjoint[6], tol); }