private void presentValueSensitivityRawDataParallelSensitivity(SabrParametersSwaptionVolatilities sabrCalibrated, TenorRawOptionData dataRaw) { PointSensitivities points = LEG_PRICER.presentValueSensitivityModelParamsSabr(FLOOR_LEG, MULTICURVE, sabrCalibrated).build(); CurrencyParameterSensitivities sabrParametersSurfaceSensitivities = sabrCalibrated.parameterSensitivity(points); CurrencyParameterSensitivity parallelSensitivitiesSurface = RDSC.parallelSensitivity(sabrParametersSurfaceSensitivities, sabrCalibrated); DoubleArray sensitivityArray = parallelSensitivitiesSurface.Sensitivity; double fdShift = 1.0E-6; int surfacePointIndex = 0; for (int loopexpiry = 0; loopexpiry < EXPIRIES.size(); loopexpiry++) { for (int looptenor = 0; looptenor < TENORS.size(); looptenor++) { Tenor tenor = TENORS.get(looptenor); Pair <DoubleArray, DoubleArray> ds = dataRaw.getData(tenor).availableSmileAtExpiry(EXPIRIES.get(loopexpiry)); if (!ds.First.Empty) { double[] pv = new double[2]; // pv with shift up and down for (int loopsign = 0; loopsign < 2; loopsign++) { TenorRawOptionData dataShifted = SabrSwaptionCalibratorSmileTestUtils.rawDataShiftSmile(TENORS, EXPIRIES, ValueType.SIMPLE_MONEYNESS, MONEYNESS, ValueType.NORMAL_VOLATILITY, DATA_ARRAY_FULL, looptenor, loopexpiry, (2 * loopsign - 1) * fdShift); SabrParametersSwaptionVolatilities calibratedShifted = SABR_CALIBRATION.calibrateWithFixedBetaAndShift(DEFINITION, CALIBRATION_TIME, dataShifted, MULTICURVE, BETA_SURFACE, SHIFT_SABR_SURFACE); pv[loopsign] = LEG_PRICER.presentValue(FLOOR_LEG, MULTICURVE, calibratedShifted).Amount; } double sensitivityFd = (pv[1] - pv[0]) / (2 * fdShift); // FD sensitivity computation SabrSwaptionCalibratorSmileTestUtils.checkAcceptable(sensitivityFd, sensitivityArray.get(surfacePointIndex), 0.10, "Tenor/Expiry: " + TENORS.get(looptenor) + " / " + EXPIRIES.get(loopexpiry)); surfacePointIndex++; } } } }
public virtual void test_parameterSensitivity_multi() { double[] points1 = new double[] { 2.24, 3.45, -2.12, -0.56 }; double[] points2 = new double[] { -0.145, 1.01, -5.0, -11.0 }; double[] points3 = new double[] { 1.3, -4.32, 2.1, -7.18 }; SabrParametersSwaptionVolatilities prov = SabrParametersSwaptionVolatilities.of(NAME, CONV, DATE_TIME, PARAM); double expiryTime0 = prov.relativeTime(TEST_OPTION_EXPIRY[0]); double expiryTime3 = prov.relativeTime(TEST_OPTION_EXPIRY[3]); for (int i = 0; i < NB_TEST; i++) { PointSensitivities sensi1 = PointSensitivities.of(SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], ALPHA, USD, points1[0]), SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], BETA, USD, points1[1]), SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], RHO, USD, points1[2]), SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], NU, USD, points1[3])); PointSensitivities sensi2 = PointSensitivities.of(SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], ALPHA, USD, points2[0]), SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], BETA, USD, points2[1]), SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], RHO, USD, points2[2]), SwaptionSabrSensitivity.of(NAME, expiryTime0, TEST_TENOR[i], NU, USD, points2[3])); PointSensitivities sensi3 = PointSensitivities.of(SwaptionSabrSensitivity.of(NAME, expiryTime3, TEST_TENOR[i], ALPHA, USD, points3[0]), SwaptionSabrSensitivity.of(NAME, expiryTime3, TEST_TENOR[i], BETA, USD, points3[1]), SwaptionSabrSensitivity.of(NAME, expiryTime3, TEST_TENOR[i], RHO, USD, points3[2]), SwaptionSabrSensitivity.of(NAME, expiryTime3, TEST_TENOR[i], NU, USD, points3[3])); PointSensitivities sensis = sensi1.combinedWith(sensi2).combinedWith(sensi3).normalized(); CurrencyParameterSensitivities computed = prov.parameterSensitivity(sensis); CurrencyParameterSensitivities expected = prov.parameterSensitivity(sensi1).combinedWith(prov.parameterSensitivity(sensi2)).combinedWith(prov.parameterSensitivity(sensi3)); DoubleArrayMath.fuzzyEquals(computed.getSensitivity(PARAM.AlphaSurface.Name, USD).Sensitivity.toArray(), expected.getSensitivity(PARAM.AlphaSurface.Name, USD).Sensitivity.toArray(), TOLERANCE_VOL); DoubleArrayMath.fuzzyEquals(computed.getSensitivity(PARAM.BetaSurface.Name, USD).Sensitivity.toArray(), expected.getSensitivity(PARAM.BetaSurface.Name, USD).Sensitivity.toArray(), TOLERANCE_VOL); DoubleArrayMath.fuzzyEquals(computed.getSensitivity(PARAM.RhoSurface.Name, USD).Sensitivity.toArray(), expected.getSensitivity(PARAM.RhoSurface.Name, USD).Sensitivity.toArray(), TOLERANCE_VOL); DoubleArrayMath.fuzzyEquals(computed.getSensitivity(PARAM.NuSurface.Name, USD).Sensitivity.toArray(), expected.getSensitivity(PARAM.NuSurface.Name, USD).Sensitivity.toArray(), TOLERANCE_VOL); } }
public virtual void test_parameterSensitivity() { double alphaSensi = 2.24, betaSensi = 3.45, rhoSensi = -2.12, nuSensi = -0.56; SabrParametersSwaptionVolatilities prov = SabrParametersSwaptionVolatilities.of(NAME, CONV, DATE_TIME, PARAM); for (int i = 0; i < NB_TEST; i++) { double expiryTime = prov.relativeTime(TEST_OPTION_EXPIRY[i]); PointSensitivities point = PointSensitivities.of(SwaptionSabrSensitivity.of(NAME, expiryTime, TEST_TENOR[i], ALPHA, USD, alphaSensi), SwaptionSabrSensitivity.of(NAME, expiryTime, TEST_TENOR[i], BETA, USD, betaSensi), SwaptionSabrSensitivity.of(NAME, expiryTime, TEST_TENOR[i], RHO, USD, rhoSensi), SwaptionSabrSensitivity.of(NAME, expiryTime, TEST_TENOR[i], NU, USD, nuSensi)); CurrencyParameterSensitivities sensiComputed = prov.parameterSensitivity(point); UnitParameterSensitivity alphaSensitivities = prov.Parameters.AlphaSurface.zValueParameterSensitivity(expiryTime, TEST_TENOR[i]); UnitParameterSensitivity betaSensitivities = prov.Parameters.BetaSurface.zValueParameterSensitivity(expiryTime, TEST_TENOR[i]); UnitParameterSensitivity rhoSensitivities = prov.Parameters.RhoSurface.zValueParameterSensitivity(expiryTime, TEST_TENOR[i]); UnitParameterSensitivity nuSensitivities = prov.Parameters.NuSurface.zValueParameterSensitivity(expiryTime, TEST_TENOR[i]); CurrencyParameterSensitivity alphaSensiObj = sensiComputed.getSensitivity(SwaptionSabrRateVolatilityDataSet.META_ALPHA.SurfaceName, USD); CurrencyParameterSensitivity betaSensiObj = sensiComputed.getSensitivity(SwaptionSabrRateVolatilityDataSet.META_BETA_USD.SurfaceName, USD); CurrencyParameterSensitivity rhoSensiObj = sensiComputed.getSensitivity(SwaptionSabrRateVolatilityDataSet.META_RHO.SurfaceName, USD); CurrencyParameterSensitivity nuSensiObj = sensiComputed.getSensitivity(SwaptionSabrRateVolatilityDataSet.META_NU.SurfaceName, USD); DoubleArray alphaNodeSensiComputed = alphaSensiObj.Sensitivity; DoubleArray betaNodeSensiComputed = betaSensiObj.Sensitivity; DoubleArray rhoNodeSensiComputed = rhoSensiObj.Sensitivity; DoubleArray nuNodeSensiComputed = nuSensiObj.Sensitivity; assertEquals(alphaSensitivities.Sensitivity.size(), alphaNodeSensiComputed.size()); assertEquals(betaSensitivities.Sensitivity.size(), betaNodeSensiComputed.size()); assertEquals(rhoSensitivities.Sensitivity.size(), rhoNodeSensiComputed.size()); assertEquals(nuSensitivities.Sensitivity.size(), nuNodeSensiComputed.size()); for (int k = 0; k < alphaNodeSensiComputed.size(); ++k) { assertEquals(alphaNodeSensiComputed.get(k), alphaSensitivities.Sensitivity.get(k) * alphaSensi, TOLERANCE_VOL); } for (int k = 0; k < betaNodeSensiComputed.size(); ++k) { assertEquals(betaNodeSensiComputed.get(k), betaSensitivities.Sensitivity.get(k) * betaSensi, TOLERANCE_VOL); } for (int k = 0; k < rhoNodeSensiComputed.size(); ++k) { assertEquals(rhoNodeSensiComputed.get(k), rhoSensitivities.Sensitivity.get(k) * rhoSensi, TOLERANCE_VOL); } for (int k = 0; k < nuNodeSensiComputed.size(); ++k) { assertEquals(nuNodeSensiComputed.get(k), nuSensitivities.Sensitivity.get(k) * nuSensi, TOLERANCE_VOL); } } }
//------------------------------------------------------------------------- /// <summary> /// Runs the calibration of SABR on swaptions and print on the console the present value, bucketed PV01 and /// the bucketed Vega of a 18M x 4Y swaption. /// </summary> /// <param name="args"> -s to use the spares data </param> public static void Main(string[] args) { long start, end; // Swaption description BuySell payer = BuySell.BUY; Period expiry = Period.ofMonths(18); double notional = 1_000_000; double strike = 0.0100; Tenor tenor = Tenor.TENOR_4Y; LocalDate expiryDate = EUR_FIXED_1Y_EURIBOR_6M.FloatingLeg.StartDateBusinessDayAdjustment.adjust(CALIBRATION_DATE.plus(expiry), REF_DATA); SwapTrade underlying = EUR_FIXED_1Y_EURIBOR_6M.createTrade(expiryDate, tenor, payer, notional, strike, REF_DATA); Swaption swaption = Swaption.builder().expiryDate(AdjustableDate.of(expiryDate)).expiryTime(LocalTime.of(11, 0x0)).expiryZone(ZoneId.of("Europe/Berlin")).underlying(underlying.Product).longShort(LongShort.LONG).swaptionSettlement(PhysicalSwaptionSettlement.DEFAULT).build(); ResolvedSwaption resolvedSwaption = swaption.resolve(REF_DATA); // select data TenorRawOptionData data = DATA_FULL; if (args.Length > 0) { if (args[0].Equals("-s")) { data = DATA_SPARSE; } } start = DateTimeHelper.CurrentUnixTimeMillis(); // Curve calibration RatesProvider multicurve = CALIBRATOR.calibrate(CONFIGS, MARKET_QUOTES, REF_DATA); end = DateTimeHelper.CurrentUnixTimeMillis(); Console.WriteLine("Curve calibration time: " + (end - start) + " ms."); // SABR calibration start = DateTimeHelper.CurrentUnixTimeMillis(); double beta = 0.50; SurfaceMetadata betaMetadata = DefaultSurfaceMetadata.builder().xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.YEAR_FRACTION).zValueType(ValueType.SABR_BETA).surfaceName("Beta").build(); Surface betaSurface = ConstantSurface.of(betaMetadata, beta); double shift = 0.0300; Surface shiftSurface = ConstantSurface.of("SABR-Shift", shift); SabrParametersSwaptionVolatilities sabr = SABR_CALIBRATION.calibrateWithFixedBetaAndShift(DEFINITION, CALIBRATION_TIME, data, multicurve, betaSurface, shiftSurface); end = DateTimeHelper.CurrentUnixTimeMillis(); Console.WriteLine("SABR calibration time: " + (end - start) + " ms."); // Price and risk Console.WriteLine("Risk measures: "); start = DateTimeHelper.CurrentUnixTimeMillis(); CurrencyAmount pv = SWAPTION_PRICER.presentValue(resolvedSwaption, multicurve, sabr); Console.WriteLine(" |-> PV: " + pv.ToString()); PointSensitivities deltaPts = SWAPTION_PRICER.presentValueSensitivityRatesStickyModel(resolvedSwaption, multicurve, sabr).build(); CurrencyParameterSensitivities deltaBucketed = multicurve.parameterSensitivity(deltaPts); Console.WriteLine(" |-> Delta bucketed: " + deltaBucketed.ToString()); PointSensitivities vegaPts = SWAPTION_PRICER.presentValueSensitivityModelParamsSabr(resolvedSwaption, multicurve, sabr).build(); Console.WriteLine(" |-> Vega point: " + vegaPts.ToString()); CurrencyParameterSensitivities vegaBucketed = sabr.parameterSensitivity(vegaPts); for (int i = 0; i < vegaBucketed.size(); i++) { Console.WriteLine(" |-> Vega bucketed: " + vegaBucketed.Sensitivities.get(i)); } end = DateTimeHelper.CurrentUnixTimeMillis(); Console.WriteLine("PV and risk time: " + (end - start) + " ms."); }
public virtual void regressionPvSurfaceSensi() { PointSensitivities pointComputed = SWAPTION_PRICER.presentValueSensitivityModelParamsSabr(SWAPTION_PAY_LONG, RATE_PROVIDER, VOLS_REGRESSION).build(); assertSensitivity(pointComputed, SabrParameterType.ALPHA, 6.5786313367554754E7, REGRESSION_TOL); assertSensitivity(pointComputed, SabrParameterType.BETA, -1.2044275797229866E7, REGRESSION_TOL); assertSensitivity(pointComputed, SabrParameterType.RHO, 266223.51118849067, REGRESSION_TOL); assertSensitivity(pointComputed, SabrParameterType.NU, 400285.5505271345, REGRESSION_TOL); CurrencyParameterSensitivities sensiComputed = VOLS_REGRESSION.parameterSensitivity(pointComputed); double[][] alphaExp = new double[][] { new double[] { 0.0, 1.0, 0.0 }, new double[] { 0.5, 1.0, 0.0 }, new double[] { 1.0, 1.0, 0.0 }, new double[] { 2.0, 1.0, 0.0 }, new double[] { 5.0, 1.0, 0.0 }, new double[] { 10.0, 1.0, 0.0 }, new double[] { 0.0, 5.0, 0.0 }, new double[] { 0.5, 5.0, 0.0 }, new double[] { 1.0, 5.0, 6204.475194599179 }, new double[] { 2.0, 5.0, 3.94631212984123E7 }, new double[] { 5.0, 5.0, 0.0 }, new double[] { 10.0, 5.0, 0.0 }, new double[] { 0.0, 10.0, 0.0 }, new double[] { 0.5, 10.0, 0.0 }, new double[] { 1.0, 10.0, 4136.961894403858 }, new double[] { 2.0, 10.0, 2.631285063205345E7 }, new double[] { 5.0, 10.0, 0.0 }, new double[] { 10.0, 10.0, 0.0 } }; double[][] betaExp = new double[][] { new double[] { 0.0, 1.0, -0.0 }, new double[] { 0.5, 1.0, -0.0 }, new double[] { 1.0, 1.0, -0.0 }, new double[] { 2.0, 1.0, -0.0 }, new double[] { 5.0, 1.0, -0.0 }, new double[] { 10.0, 1.0, -0.0 }, new double[] { 0.0, 5.0, -0.0 }, new double[] { 0.5, 5.0, -0.0 }, new double[] { 1.0, 5.0, -1135.926404680998 }, new double[] { 2.0, 5.0, -7224978.759366533 }, new double[] { 5.0, 5.0, -0.0 }, new double[] { 10.0, 5.0, -0.0 }, new double[] { 0.0, 10.0, -0.0 }, new double[] { 0.5, 10.0, -0.0 }, new double[] { 1.0, 10.0, -757.402375482629 }, new double[] { 2.0, 10.0, -4817403.70908317 }, new double[] { 5.0, 10.0, -0.0 }, new double[] { 10.0, 10.0, -0.0 } }; double[][] rhoExp = new double[][] { new double[] { 0.0, 1.0, 0.0 }, new double[] { 0.5, 1.0, 0.0 }, new double[] { 1.0, 1.0, 0.0 }, new double[] { 2.0, 1.0, 0.0 }, new double[] { 5.0, 1.0, 0.0 }, new double[] { 10.0, 1.0, 0.0 }, new double[] { 0.0, 5.0, 0.0 }, new double[] { 0.5, 5.0, 0.0 }, new double[] { 1.0, 5.0, 25.10821912392996 }, new double[] { 2.0, 5.0, 159699.03429338703 }, new double[] { 5.0, 5.0, 0.0 }, new double[] { 10.0, 5.0, 0.0 }, new double[] { 0.0, 10.0, 0.0 }, new double[] { 0.5, 10.0, 0.0 }, new double[] { 1.0, 10.0, 16.741423326578513 }, new double[] { 2.0, 10.0, 106482.62725265314 }, new double[] { 5.0, 10.0, 0.0 }, new double[] { 10.0, 10.0, 0.0 } }; double[][] nuExp = new double[][] { new double[] { 0.0, 1.0, 0.0 }, new double[] { 0.5, 1.0, 0.0 }, new double[] { 1.0, 1.0, 0.0 }, new double[] { 2.0, 1.0, 0.0 }, new double[] { 5.0, 1.0, 0.0 }, new double[] { 10.0, 1.0, 0.0 }, new double[] { 0.0, 5.0, 0.0 }, new double[] { 0.5, 5.0, 0.0 }, new double[] { 1.0, 5.0, 37.751952372314484 }, new double[] { 2.0, 5.0, 240118.59649585965 }, new double[] { 5.0, 5.0, 0.0 }, new double[] { 10.0, 5.0, 0.0 }, new double[] { 0.0, 10.0, 0.0 }, new double[] { 0.5, 10.0, 0.0 }, new double[] { 1.0, 10.0, 25.171893432592533 }, new double[] { 2.0, 10.0, 160104.03018547 }, new double[] { 5.0, 10.0, 0.0 }, new double[] { 10.0, 10.0, 0.0 } }; double[][][] exps = new double[][][] { alphaExp, betaExp, rhoExp, nuExp }; SurfaceMetadata[] metadata = new SurfaceMetadata[] { SwaptionSabrRateVolatilityDataSet.META_ALPHA, SwaptionSabrRateVolatilityDataSet.META_BETA_USD, SwaptionSabrRateVolatilityDataSet.META_RHO, SwaptionSabrRateVolatilityDataSet.META_NU }; // x-y-value order does not match sorted order in surface, thus sort it CurrencyParameterSensitivities sensiExpected = CurrencyParameterSensitivities.empty(); for (int i = 0; i < exps.Length; ++i) { int size = exps[i].Length; IDictionary <DoublesPair, double> sensiMap = new SortedDictionary <DoublesPair, double>(); for (int j = 0; j < size; ++j) { sensiMap[DoublesPair.of(exps[i][j][0], exps[i][j][1])] = exps[i][j][2]; } IList <ParameterMetadata> paramMetadata = new List <ParameterMetadata>(size); IList <double> sensi = new List <double>(); foreach (KeyValuePair <DoublesPair, double> entry in sensiMap.SetOfKeyValuePairs()) { paramMetadata.Add(SwaptionSurfaceExpiryTenorParameterMetadata.of(entry.Key.First, entry.Key.Second)); sensi.Add(entry.Value); } SurfaceMetadata surfaceMetadata = metadata[i].withParameterMetadata(paramMetadata); sensiExpected = sensiExpected.combinedWith(CurrencyParameterSensitivity.of(surfaceMetadata.SurfaceName, surfaceMetadata.ParameterMetadata.get(), USD, DoubleArray.copyOf(sensi))); } testSurfaceParameterSensitivities(sensiComputed, sensiExpected, REGRESSION_TOL * NOTIONAL); }
public virtual void test_presentValueVega_SwaptionSensitivity() { SwaptionSensitivity vegaRec = SWAPTION_PRICER.presentValueSensitivityModelParamsVolatility(SWAPTION_REC_LONG, RATE_PROVIDER, VOLS); assertEquals(VOLS.parameterSensitivity(vegaRec), CurrencyParameterSensitivities.empty()); }