private System.Func <SabrFormulaData, double> getVolatilityFunction(EuropeanVanillaOption option, double forward) { return((SabrFormulaData data) => { ArgChecker.notNull(data, "data"); return FUNCTION.volatility(forward, option.Strike, option.TimeToExpiry, data); }); }
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); }
//------------------------------------------------------------------------- public virtual void present_value_theta_formula() { double forward = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD); double pvbp = PRICER_SWAP.LegPricer.pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), MULTI_USD); double volatility = NORMAL_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.Expiry, SWAP_TENOR_YEAR, STRIKE, forward); NormalFunctionData normalData = NormalFunctionData.of(forward, Math.Abs(pvbp), volatility); double expiry = NORMAL_VOLS_USD_STD.relativeTime(SWAPTION_LONG_REC.Expiry); EuropeanVanillaOption option = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT); double pvThetaExpected = NORMAL.getTheta(option, normalData); CurrencyAmount pvThetaComputed = PRICER_SWAPTION_NORMAL.presentValueTheta(SWAPTION_LONG_REC, MULTI_USD, NORMAL_VOLS_USD_STD); assertEquals(pvThetaComputed.Currency, USD); assertEquals(pvThetaComputed.Amount, pvThetaExpected, TOLERANCE_PV); }
//------------------------------------------------------------------------- public virtual void test_presentValueTheta() { CurrencyAmount pvThetaRecComputed = PRICER_SWAPTION.presentValueTheta(SWAPTION_REC_LONG, RATE_PROVIDER, VOLS); CurrencyAmount pvThetaPayComputed = PRICER_SWAPTION.presentValueTheta(SWAPTION_PAY_SHORT, RATE_PROVIDER, VOLS); double forward = PRICER_SWAP.parRate(RSWAP_REC, RATE_PROVIDER); double annuityCash = PRICER_SWAP.LegPricer.annuityCash(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), forward); double volatility = VOLS.volatility(SWAPTION_REC_LONG.Expiry, SWAP_TENOR_YEAR, STRIKE, forward); double discount = RATE_PROVIDER.discountFactor(USD, SETTLE_DATE); NormalFunctionData normalData = NormalFunctionData.of(forward, annuityCash * discount, volatility); double expiry = VOLS.relativeTime(SWAPTION_REC_LONG.Expiry); EuropeanVanillaOption optionRec = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT); EuropeanVanillaOption optionPay = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.CALL); double pvThetaRecExpected = NORMAL.getTheta(optionRec, normalData); double pvThetaPayExpected = -NORMAL.getTheta(optionPay, normalData); assertEquals(pvThetaRecComputed.Currency, USD); assertEquals(pvThetaRecComputed.Amount, pvThetaRecExpected, NOTIONAL * TOL); assertEquals(pvThetaPayComputed.Currency, USD); assertEquals(pvThetaPayComputed.Amount, pvThetaPayExpected, NOTIONAL * TOL); }
private void volatilityAdjoint2ForInstrument(EuropeanVanillaOption option, double tolerance1, double tolerance2) { // vol double volatility = FUNCTION.volatility(F, option.Strike, option.TimeToExpiry, DATA); double[] volatilityAdjoint = toArray(FUNCTION.volatilityAdjoint(F, option.Strike, option.TimeToExpiry, DATA)); double[] volD = 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[][] volD2 = new double[2][2]; double[][] volD2 = RectangularArrays.ReturnRectangularDoubleArray(2, 2); double vol = FUNCTION.volatilityAdjoint2(F, option.Strike, option.TimeToExpiry, DATA, volD, volD2); assertEquals(volatility, vol, tolerance1); // Derivative for (int loopder = 0; loopder < 6; loopder++) { assertEquals(volatilityAdjoint[loopder + 1], volD[loopder], tolerance1); } // Derivative forward-forward double deltaF = 0.000001; double volatilityFP = FUNCTION.volatility(F + deltaF, option.Strike, option.TimeToExpiry, DATA); double volatilityFM = FUNCTION.volatility(F - deltaF, option.Strike, option.TimeToExpiry, DATA); double derivativeFF_FD = (volatilityFP + volatilityFM - 2 * volatility) / (deltaF * deltaF); assertEquals(derivativeFF_FD, volD2[0][0], tolerance2); // Derivative strike-strike double deltaK = 0.000001; double volatilityKP = FUNCTION.volatility(F, option.Strike + deltaK, option.TimeToExpiry, DATA); double volatilityKM = FUNCTION.volatility(F, option.Strike - deltaK, option.TimeToExpiry, DATA); double derivativeKK_FD = (volatilityKP + volatilityKM - 2 * volatility) / (deltaK * deltaK); assertEquals(derivativeKK_FD, volD2[1][1], tolerance2); // Derivative strike-forward double volatilityFPKP = FUNCTION.volatility(F + deltaF, option.Strike + deltaK, option.TimeToExpiry, DATA); double derivativeFK_FD = (volatilityFPKP + volatility - volatilityFP - volatilityKP) / (deltaF * deltaK); assertEquals(derivativeFK_FD, volD2[0][1], tolerance2); assertEquals(volD2[0][1], volD2[1][0], 1E-6); }
private EuropeanVanillaOption withStrike(EuropeanVanillaOption option, double strike) { return(EuropeanVanillaOption.of(strike, option.TimeToExpiry, option.PutCall)); }
//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"); }