/** * Creates metadata for a surface providing Normal expiry-strike volatility. * <p> * The x-values represent time to expiry year fractions as defined by the specified day count. * The y-values represent strike * The z-values represent Normal volatility. * * @param name the surface name * @param dayCount the day count * @return the surface metadata */ public static SurfaceMetadata normalVolatilityByExpiryStrike(String name, DayCount dayCount) { return normalVolatilityByExpiryStrike(SurfaceName.of(name), dayCount); }
@Override public SurfaceMetadata createMetadata(RawOptionData capFloorData) { SurfaceMetadata metadata; if (capFloorData.getDataType().equals(BLACK_VOLATILITY)) { metadata = Surfaces.blackVolatilityByExpiryStrike(name.getName(), dayCount); } else if (capFloorData.getDataType().equals(NORMAL_VOLATILITY)) { metadata = Surfaces.normalVolatilityByExpiryStrike(name.getName(), dayCount); } else { throw new IllegalArgumentException("Data type not supported"); } return metadata; }
@Override public SurfaceMetadata createMetadata(RawOptionData capFloorData) { SurfaceMetadata metadata; if (capFloorData.getDataType().equals(BLACK_VOLATILITY)) { metadata = Surfaces.blackVolatilityByExpiryStrike(name.getName(), dayCount); } else if (capFloorData.getDataType().equals(NORMAL_VOLATILITY)) { metadata = Surfaces.normalVolatilityByExpiryStrike(name.getName(), dayCount); } else { throw new IllegalArgumentException("Data type not supported"); } return metadata; }
@Override public SurfaceMetadata createMetadata(RawOptionData capFloorData) { SurfaceMetadata metadata; if (capFloorData.getDataType().equals(BLACK_VOLATILITY)) { metadata = Surfaces.blackVolatilityByExpiryStrike(name.getName(), dayCount); } else if (capFloorData.getDataType().equals(NORMAL_VOLATILITY)) { metadata = Surfaces.normalVolatilityByExpiryStrike(name.getName(), dayCount); } else { throw new IllegalArgumentException("Data type not supported"); } return metadata; }
@Override public SurfaceMetadata createMetadata(RawOptionData capFloorData) { List<GenericVolatilitySurfacePeriodParameterMetadata> list = new ArrayList<>(); ImmutableList<Period> expiries = capFloorData.getExpiries(); int nExpiries = expiries.size(); DoubleArray strikes = capFloorData.getStrikes(); int nStrikes = strikes.size(); for (int i = 0; i < nExpiries; ++i) { for (int j = 0; j < nStrikes; ++j) { if (Double.isFinite(capFloorData.getData().get(i, j))) { list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(expiries.get(i), SimpleStrike.of(strikes.get(j)))); } } } SurfaceMetadata metadata; if (capFloorData.getDataType().equals(ValueType.BLACK_VOLATILITY)) { metadata = Surfaces.blackVolatilityByExpiryStrike(name.getName(), dayCount); } else if (capFloorData.getDataType().equals(ValueType.NORMAL_VOLATILITY)) { metadata = Surfaces.normalVolatilityByExpiryStrike(name.getName(), dayCount); } else { throw new IllegalArgumentException("Data type not supported"); } return metadata.withParameterMetadata(list); }
public void test_createMetadata_normal() { SabrIborCapletFloorletVolatilityBootstrapDefinition base = SabrIborCapletFloorletVolatilityBootstrapDefinition.ofFixedBeta( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, 0.5, LINEAR, FLAT, FLAT, SabrVolatilityFormula.hagan()); RawOptionData capData = RawOptionData.of( ImmutableList.of(Period.ofYears(1), Period.ofYears(5)), DoubleArray.of(0.005, 0.01, 0.015), ValueType.STRIKE, DoubleMatrix.copyOf(new double[][] {{0.15, 0.12, 0.13}, {0.1, Double.NaN, 0.09}}), ValueType.NORMAL_VOLATILITY); SurfaceMetadata expected = Surfaces.normalVolatilityByExpiryStrike(NAME.getName(), ACT_ACT_ISDA); SurfaceMetadata computed = base.createMetadata(capData); assertEquals(computed, expected); }
public void normalVolatilityByExpiryStrike_string() { SurfaceMetadata test = Surfaces.normalVolatilityByExpiryStrike(NAME, ACT_360); SurfaceMetadata expected = DefaultSurfaceMetadata.builder() .surfaceName(SURFACE_NAME) .xValueType(ValueType.YEAR_FRACTION) .yValueType(ValueType.STRIKE) .zValueType(ValueType.NORMAL_VOLATILITY) .dayCount(ACT_360) .build(); assertEquals(test, expected); }
public void normalVolatilityByExpiryStrike_surfaceName() { SurfaceMetadata test = Surfaces.normalVolatilityByExpiryStrike(SURFACE_NAME, ACT_360); SurfaceMetadata expected = DefaultSurfaceMetadata.builder() .surfaceName(SURFACE_NAME) .xValueType(ValueType.YEAR_FRACTION) .yValueType(ValueType.STRIKE) .zValueType(ValueType.NORMAL_VOLATILITY) .dayCount(ACT_360) .build(); assertEquals(test, expected); }
public void test_createMetadata() { DirectIborCapletFloorletVolatilityDefinition base = DirectIborCapletFloorletVolatilityDefinition.of( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LAMBDA_EXPIRY, LAMBDA_STRIKE, INTERPOLATOR); assertEquals(base.createMetadata(SAMPLE_BLACK), Surfaces.blackVolatilityByExpiryStrike(NAME.getName(), ACT_ACT_ISDA)); assertEquals(base.createMetadata(SAMPLE_NORMAL), Surfaces.normalVolatilityByExpiryStrike(NAME.getName(), ACT_ACT_ISDA)); assertThrowsIllegalArg(() -> base.createMetadata(RawOptionData.of(EXPIRIES, STRIKES, STRIKE, DATA, ValueType.PRICE))); }
public void test_createMetadata() { SabrIborCapletFloorletVolatilityCalibrationDefinition base = SabrIborCapletFloorletVolatilityCalibrationDefinition.ofFixedBeta( NAME, USD_LIBOR_3M, ACT_365F, BETA_RHO, ALPHA_KNOTS, BETA_RHO_KNOTS, NU_KNOTS, DOUBLE_QUADRATIC, FLAT, LINEAR, HAGAN); assertEquals(base.createMetadata(SAMPLE_BLACK), Surfaces.blackVolatilityByExpiryStrike(NAME.getName(), ACT_365F)); assertEquals(base.createMetadata(SAMPLE_NORMAL), Surfaces.normalVolatilityByExpiryStrike(NAME.getName(), ACT_365F)); assertThrowsIllegalArg(() -> base.createMetadata(RawOptionData.of(EXPIRIES, STRIKES, STRIKE, DATA, ValueType.PRICE))); }
public void recovery_test_normal2() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition definition = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of( IborCapletFloorletVolatilitiesName.of("test"), USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); 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); NormalIborCapletFloorletExpiryStrikeVolatilities resVol = (NormalIborCapletFloorletExpiryStrikeVolatilities) res.getVolatilities(); for (int i = 0; i < strikes.size(); ++i) { Pair<List<ResolvedIborCapFloorLeg>, List<Double>> capsAndVols = getCapsNormalEquivVols(i); List<ResolvedIborCapFloorLeg> caps = capsAndVols.getFirst(); List<Double> vols = capsAndVols.getSecond(); int nCaps = caps.size(); for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of( Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols.get(j)); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of( USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_NORMAL.presentValue(caps.get(j), RATES_PROVIDER, constVol).getAmount(); double priceCalib = LEG_PRICER_NORMAL.presentValue(caps.get(j), RATES_PROVIDER, resVol).getAmount(); assertEquals(priceOrg, priceCalib, Math.max(priceOrg, 1d) * TOL); } } assertEquals(res.getChiSquare(), 0d); }
public void test_createMetadata_normal() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition base = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); RawOptionData capData = RawOptionData.of( ImmutableList.of(Period.ofYears(1), Period.ofYears(5)), DoubleArray.of(0.005, 0.01, 0.015), ValueType.STRIKE, DoubleMatrix.copyOf(new double[][] {{0.15, 0.12, 0.13}, {0.1, Double.NaN, 0.09}}), ValueType.NORMAL_VOLATILITY); List<GenericVolatilitySurfacePeriodParameterMetadata> list = new ArrayList<>(); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.005))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.01))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.015))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(5), SimpleStrike.of(0.005))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(5), SimpleStrike.of(0.015))); SurfaceMetadata expected = Surfaces.normalVolatilityByExpiryStrike( NAME.getName(), ACT_ACT_ISDA).withParameterMetadata(list); SurfaceMetadata computed = base.createMetadata(capData); assertEquals(computed, expected); }
public void recovery_test_normal() { double lambdaT = 0.07; double lambdaK = 0.07; double error = 1.0e-5; DirectIborCapletFloorletVolatilityDefinition definition = DirectIborCapletFloorletVolatilityDefinition.of( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, lambdaT, lambdaK, INTERPOLATOR); ImmutableList<Period> maturities = createNormalMaturities(); DoubleArray strikes = createNormalStrikes(); DoubleMatrix errorMatrix = DoubleMatrix.filled(maturities.size(), strikes.size(), error); RawOptionData data = RawOptionData.of( maturities, strikes, STRIKE, createFullNormalDataMatrix(), errorMatrix, NORMAL_VOLATILITY); IborCapletFloorletVolatilityCalibrationResult res = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER); NormalIborCapletFloorletExpiryStrikeVolatilities resVol = (NormalIborCapletFloorletExpiryStrikeVolatilities) res.getVolatilities(); for (int i = 0; i < strikes.size(); ++i) { Pair<List<ResolvedIborCapFloorLeg>, List<Double>> capsAndVols = getCapsNormalVols(i); List<ResolvedIborCapFloorLeg> caps = capsAndVols.getFirst(); List<Double> vols = capsAndVols.getSecond(); int nCaps = caps.size(); for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of( Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols.get(j)); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of( USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_NORMAL.presentValue(caps.get(j), RATES_PROVIDER, constVol).getAmount(); double priceCalib = LEG_PRICER_NORMAL.presentValue(caps.get(j), RATES_PROVIDER, resVol).getAmount(); assertEquals(priceOrg, priceCalib, Math.max(priceOrg, 1d) * TOL); } } }
public 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.getVolatilities(); for (int i = 0; i < strikes.size(); ++i) { Pair<List<ResolvedIborCapFloorLeg>, List<Double>> capsAndVols = getCapsNormalEquivVols(i); List<ResolvedIborCapFloorLeg> caps = capsAndVols.getFirst(); List<Double> vols = capsAndVols.getSecond(); int nCaps = caps.size(); for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of( Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols.get(j)); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of( USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_NORMAL.presentValue(caps.get(j), RATES_PROVIDER, constVol).getAmount(); double priceCalib = LEG_PRICER_BLACK.presentValue(caps.get(j), RATES_PROVIDER, resVol).getAmount(); assertEquals(priceOrg, priceCalib, Math.max(priceOrg, 1d) * TOL); } } assertEquals(res.getChiSquare(), 0d); }
for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of( Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols.get(j)); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of( USD_LIBOR_3M, CALIBRATION_TIME, volSurface);
for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of( Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols.get(j)); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of( USD_LIBOR_3M, CALIBRATION_TIME, volSurface);
public void recovery_test_normal() { double beta = 0.7; SabrIborCapletFloorletVolatilityCalibrationDefinition definition = SabrIborCapletFloorletVolatilityCalibrationDefinition.ofFixedBeta( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, beta, ALPHA_KNOTS, BETA_RHO_KNOTS, NU_KNOTS, 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.getVolatilities(); for (int i = 0; i < strikes.size(); ++i) { Pair<List<ResolvedIborCapFloorLeg>, List<Double>> capsAndVols = getCapsNormalEquivVols(i); List<ResolvedIborCapFloorLeg> caps = capsAndVols.getFirst(); List<Double> vols = capsAndVols.getSecond(); int nCaps = caps.size(); for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of( Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols.get(j)); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of( USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_NORMAL.presentValue(caps.get(j), RATES_PROVIDER, constVol).getAmount(); double priceCalib = LEG_PRICER_SABR.presentValue(caps.get(j), RATES_PROVIDER, resVols).getAmount(); assertEquals(priceOrg, priceCalib, Math.max(priceOrg, 1d) * TOL * 3d); } } }
for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of( Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols.get(j)); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of( USD_LIBOR_3M, CALIBRATION_TIME, volSurface);
public void recovery_test_normal_fixedRho() { DoubleArray initial = DoubleArray.of(0.05, 0.7, 0.35, 0.9); SabrIborCapletFloorletVolatilityCalibrationDefinition definition = SabrIborCapletFloorletVolatilityCalibrationDefinition.ofFixedRho(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, 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.getVolatilities(); for (int i = 0; i < strikes.size(); ++i) { Pair<List<ResolvedIborCapFloorLeg>, List<Double>> capsAndVols = getCapsNormalEquivVols(i); List<ResolvedIborCapFloorLeg> caps = capsAndVols.getFirst(); List<Double> vols = capsAndVols.getSecond(); int nCaps = caps.size(); for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of( Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols.get(j)); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of( USD_LIBOR_3M, CALIBRATION_TIME, volSurface); double priceOrg = LEG_PRICER_NORMAL.presentValue(caps.get(j), RATES_PROVIDER, constVol).getAmount(); double priceCalib = LEG_PRICER_SABR.presentValue(caps.get(j), RATES_PROVIDER, resVols).getAmount(); assertEquals(priceOrg, priceCalib, Math.max(priceOrg, 1d) * TOL * 5d); } } }
for (int j = 0; j < nCaps; ++j) { ConstantSurface volSurface = ConstantSurface.of( Surfaces.normalVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols.get(j)); NormalIborCapletFloorletExpiryStrikeVolatilities constVol = NormalIborCapletFloorletExpiryStrikeVolatilities.of( USD_LIBOR_3M, CALIBRATION_TIME, volSurface);