public virtual void recovery_test_normal2_shift() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition definition = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(IborCapletFloorletVolatilitiesName.of("test"), USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC, ConstantCurve.of("Black shift", 0.02)); DoubleArray strikes = createNormalEquivStrikes(); RawOptionData data = RawOptionData.of(createNormalEquivMaturities(), strikes, ValueType.STRIKE, createFullNormalEquivDataMatrix(), ValueType.NORMAL_VOLATILITY); IborCapletFloorletVolatilityCalibrationResult res = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER); ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities resVol = (ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities)res.Volatilities; for (int i = 0; i < strikes.size(); ++i) { Pair <IList <ResolvedIborCapFloorLeg>, IList <double> > capsAndVols = getCapsNormalEquivVols(i); IList <ResolvedIborCapFloorLeg> caps = capsAndVols.First; IList <double> vols = capsAndVols.Second; int nCaps = caps.Count; for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of(Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols[j]); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of(USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_NORMAL.presentValue(caps[j], RATES_PROVIDER, constVol).Amount; double priceCalib = LEG_PRICER_BLACK.presentValue(caps[j], RATES_PROVIDER, resVol).Amount; assertEquals(priceOrg, priceCalib, Math.Max(priceOrg, 1d) * TOL); } } assertEquals(res.ChiSquare, 0d); }
public virtual void test_recovery_normal_fixedRho() { SabrIborCapletFloorletVolatilityBootstrapDefinition definition = SabrIborCapletFloorletVolatilityBootstrapDefinition.ofFixedRho(IborCapletFloorletVolatilitiesName.of("test"), USD_LIBOR_3M, ACT_ACT_ISDA, 0.0, CurveInterpolators.LINEAR, CurveExtrapolators.FLAT, CurveExtrapolators.FLAT, SabrHaganVolatilityFunctionProvider.DEFAULT); RawOptionData data = RawOptionData.of(createNormalEquivMaturities(), createNormalEquivStrikes(), ValueType.STRIKE, createFullNormalEquivDataMatrix(), ValueType.NORMAL_VOLATILITY); IborCapletFloorletVolatilityCalibrationResult res = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER); SabrParametersIborCapletFloorletVolatilities resVols = (SabrParametersIborCapletFloorletVolatilities)res.Volatilities; for (int i = 1; i < NUM_BLACK_STRIKES; ++i) { Pair <IList <ResolvedIborCapFloorLeg>, IList <double> > capsAndVols = getCapsNormalEquivVols(i); IList <ResolvedIborCapFloorLeg> caps = capsAndVols.First; IList <double> vols = capsAndVols.Second; int nCaps = caps.Count; for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of(Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols[j]); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of(USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_NORMAL.presentValue(caps[j], RATES_PROVIDER, constVol).Amount; double priceCalib = LEG_PRICER_SABR.presentValue(caps[j], RATES_PROVIDER, resVols).Amount; assertEquals(priceOrg, priceCalib, Math.Max(priceOrg, 1d) * TOL * 3d); } } assertTrue(res.ChiSquare > 0d); assertEquals(resVols.Index, USD_LIBOR_3M); assertEquals(resVols.Name, definition.Name); assertEquals(resVols.ValuationDateTime, CALIBRATION_TIME); }
public virtual void recovery_test_normal_shift_fixedRho() { double shift = 0.02; DoubleArray initial = DoubleArray.of(0.05, 0.35, 0.0, 0.9); SabrIborCapletFloorletVolatilityCalibrationDefinition definition = SabrIborCapletFloorletVolatilityCalibrationDefinition.ofFixedRho(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, shift, ALPHA_KNOTS, BETA_RHO_KNOTS, NU_KNOTS, initial, DOUBLE_QUADRATIC, FLAT, FLAT, HAGAN); ImmutableList <Period> maturities = createNormalEquivMaturities(); DoubleArray strikes = createNormalEquivStrikes(); DoubleMatrix volData = createFullNormalEquivDataMatrix(); DoubleMatrix error = DoubleMatrix.filled(volData.rowCount(), volData.columnCount(), 1.0e-3); RawOptionData data = RawOptionData.of(maturities, strikes, ValueType.STRIKE, volData, error, ValueType.NORMAL_VOLATILITY); IborCapletFloorletVolatilityCalibrationResult res = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER); SabrIborCapletFloorletVolatilities resVols = (SabrIborCapletFloorletVolatilities)res.Volatilities; for (int i = 0; i < strikes.size(); ++i) { Pair <IList <ResolvedIborCapFloorLeg>, IList <double> > capsAndVols = getCapsNormalEquivVols(i); IList <ResolvedIborCapFloorLeg> caps = capsAndVols.First; IList <double> vols = capsAndVols.Second; int nCaps = caps.Count; for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of(Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols[j]); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of(USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_NORMAL.presentValue(caps[j], RATES_PROVIDER, constVol).Amount; double priceCalib = LEG_PRICER_SABR.presentValue(caps[j], RATES_PROVIDER, resVols).Amount; assertEquals(priceOrg, priceCalib, Math.Max(priceOrg, 1d) * TOL * 5d); } } }
public virtual void recovery_test_normalToBlack() { double lambdaT = 0.07; double lambdaK = 0.07; double error = 1.0e-5; ConstantCurve shiftCurve = ConstantCurve.of("Black shift", 0.02); DirectIborCapletFloorletVolatilityDefinition definition = DirectIborCapletFloorletVolatilityDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, lambdaT, lambdaK, INTERPOLATOR, shiftCurve); ImmutableList <Period> maturities = createNormalEquivMaturities(); DoubleArray strikes = createNormalEquivStrikes(); DoubleMatrix errorMatrix = DoubleMatrix.filled(maturities.size(), strikes.size(), error); RawOptionData data = RawOptionData.of(maturities, strikes, STRIKE, createFullNormalEquivDataMatrix(), errorMatrix, NORMAL_VOLATILITY); IborCapletFloorletVolatilityCalibrationResult res = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER); ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities resVol = (ShiftedBlackIborCapletFloorletExpiryStrikeVolatilities)res.Volatilities; for (int i = 0; i < strikes.size(); ++i) { Pair <IList <ResolvedIborCapFloorLeg>, IList <double> > capsAndVols = getCapsNormalEquivVols(i); IList <ResolvedIborCapFloorLeg> caps = capsAndVols.First; IList <double> vols = capsAndVols.Second; int nCaps = caps.Count; for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of(Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols[j]); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of(USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_NORMAL.presentValue(caps[j], RATES_PROVIDER, constVol).Amount; double priceCalib = LEG_PRICER_BLACK.presentValue(caps[j], RATES_PROVIDER, resVol).Amount; assertEquals(priceOrg, priceCalib, Math.Max(priceOrg, 1d) * TOL); } } }
public virtual void test_volatility_sensitivity() { double eps = 1.0e-6; int nData = TIME.size(); for (int i = 0; i < NB_TEST; i++) { for (int k = 0; k < NB_TEST; k++) { double expiryTime = VOLS.relativeTime(TEST_OPTION_EXPIRY[i]); IborCapletFloorletSensitivity point = IborCapletFloorletSensitivity.of(IborCapletFloorletVolatilitiesName.of(NAME), expiryTime, TEST_STRIKE[k], TEST_FORWARD, GBP, TEST_SENSITIVITY[i]); CurrencyParameterSensitivity sensActual = VOLS.parameterSensitivity(point).Sensitivities.get(0); DoubleArray computed = sensActual.Sensitivity; for (int j = 0; j < nData; ++j) { DoubleArray volDataUp = VOL.subArray(0, nData).with(j, VOL.get(j) + eps); DoubleArray volDataDw = VOL.subArray(0, nData).with(j, VOL.get(j) - eps); InterpolatedNodalSurface paramUp = InterpolatedNodalSurface.of(METADATA, TIME, STRIKE, volDataUp, INTERPOLATOR_2D); InterpolatedNodalSurface paramDw = InterpolatedNodalSurface.of(METADATA, TIME, STRIKE, volDataDw, INTERPOLATOR_2D); NormalIborCapletFloorletExpiryStrikeVolatilities provUp = NormalIborCapletFloorletExpiryStrikeVolatilities.of(GBP_LIBOR_3M, VAL_DATE_TIME, paramUp); NormalIborCapletFloorletExpiryStrikeVolatilities provDw = NormalIborCapletFloorletExpiryStrikeVolatilities.of(GBP_LIBOR_3M, VAL_DATE_TIME, paramDw); double volUp = provUp.volatility(TEST_OPTION_EXPIRY[i], TEST_STRIKE[k], TEST_FORWARD); double volDw = provDw.volatility(TEST_OPTION_EXPIRY[i], TEST_STRIKE[k], TEST_FORWARD); double fd = 0.5 * (volUp - volDw) / eps; assertEquals(computed.get(j), fd * TEST_SENSITIVITY[i], eps); } } } }
private System.Func <Surface, IborCapletFloorletVolatilities> normalVolatilitiesFunction(IborIndex index, ZonedDateTime calibrationDateTime) { System.Func <Surface, IborCapletFloorletVolatilities> func = (Surface s) => { return(NormalIborCapletFloorletExpiryStrikeVolatilities.of(index, calibrationDateTime, s)); }; return(func); }
private void testSurfaceSensitivity(CurrencyParameterSensitivity computed, NormalIborCapletFloorletExpiryStrikeVolatilities vols, System.Func <IborCapletFloorletVolatilities, CurrencyAmount> valueFn) { double pvBase = valueFn(vols).Amount; InterpolatedNodalSurface surfaceBase = (InterpolatedNodalSurface)vols.Surface; int nParams = surfaceBase.ParameterCount; for (int i = 0; i < nParams; ++i) { DoubleArray zBumped = surfaceBase.ZValues.with(i, surfaceBase.ZValues.get(i) + EPS_FD); InterpolatedNodalSurface surfaceBumped = surfaceBase.withZValues(zBumped); NormalIborCapletFloorletExpiryStrikeVolatilities volsBumped = NormalIborCapletFloorletExpiryStrikeVolatilities.of(vols.Index, vols.ValuationDateTime, surfaceBumped); double fd = (valueFn(volsBumped).Amount - pvBase) / EPS_FD; assertEquals(computed.Sensitivity.get(i), fd, NOTIONAL * EPS_FD); } }
public virtual void recovery_test_normal1() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition definition = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(IborCapletFloorletVolatilitiesName.of("test"), USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); DoubleArray strikes = createNormalStrikes(); RawOptionData data = RawOptionData.of(createNormalMaturities(), strikes, ValueType.STRIKE, createFullNormalDataMatrix(), ValueType.NORMAL_VOLATILITY); IborCapletFloorletVolatilityCalibrationResult res = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER); NormalIborCapletFloorletExpiryStrikeVolatilities resVol = (NormalIborCapletFloorletExpiryStrikeVolatilities)res.Volatilities; for (int i = 0; i < strikes.size(); ++i) { Pair <IList <ResolvedIborCapFloorLeg>, IList <double> > capsAndVols = getCapsNormalVols(i); IList <ResolvedIborCapFloorLeg> caps = capsAndVols.First; IList <double> vols = capsAndVols.Second; int nCaps = caps.Count; for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of(Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols[j]); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of(USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_NORMAL.presentValue(caps[j], RATES_PROVIDER, constVol).Amount; double priceCalib = LEG_PRICER_NORMAL.presentValue(caps[j], RATES_PROVIDER, resVol).Amount; assertEquals(priceOrg, priceCalib, Math.Max(priceOrg, 1d) * TOL); } } assertEquals(res.ChiSquare, 0d); assertEquals(res.ChiSquare, 0d); assertEquals(resVol.Index, USD_LIBOR_3M); assertEquals(resVol.Name, definition.Name); assertEquals(resVol.ValuationDateTime, CALIBRATION_TIME); InterpolatedNodalSurface surface = (InterpolatedNodalSurface)resVol.Surface; for (int i = 0; i < surface.ParameterCount; ++i) { GenericVolatilitySurfacePeriodParameterMetadata metadata = (GenericVolatilitySurfacePeriodParameterMetadata)surface.getParameterMetadata(i); assertEquals(metadata.Strike.Value, surface.YValues.get(i)); } }
/// <summary> /// Creates volatilities provider with specified date and index. /// </summary> /// <param name="valuationDate"> the valuation date </param> /// <param name="index"> the index </param> /// <returns> the volatilities provider </returns> public static NormalIborCapletFloorletExpiryStrikeVolatilities createNormalVolatilities(ZonedDateTime valuationDate, IborIndex index) { return(NormalIborCapletFloorletExpiryStrikeVolatilities.of(index, valuationDate, NORMAL_SURFACE_EXP_STR)); }