Example #1
0
        // node sensitivity function
        private System.Func <DoubleArray, DoubleMatrix> createJacobianFunction(SabrIborCapletFloorletVolatilityCalibrationDefinition sabrDefinition, RatesProvider ratesProvider, SabrParametersIborCapletFloorletVolatilities volatilities, IList <ResolvedIborCapFloorLeg> capList, IList <double> priceList, Currency currency)
        {
            int            nCaps      = capList.Count;
            SabrParameters sabrParams = volatilities.Parameters;
            CurveName      alphaName  = sabrParams.AlphaCurve.Name;
            CurveName      betaName   = sabrParams.BetaCurve.Name;
            CurveName      rhoName    = sabrParams.RhoCurve.Name;
            CurveName      nuName     = sabrParams.NuCurve.Name;

            System.Func <DoubleArray, DoubleMatrix> jacobianFunction = (DoubleArray x) =>
            {
                SabrParametersIborCapletFloorletVolatilities volsNew = updateParameters(sabrDefinition, volatilities, x);
                double[][] jacobian = new double[nCaps][];
                for (int i = 0; i < nCaps; ++i)
                {
                    PointSensitivities             point = sabrPricer.presentValueSensitivityModelParamsSabr(capList[i], ratesProvider, volsNew).build();
                    CurrencyParameterSensitivities sensi = volsNew.parameterSensitivity(point);
                    double      targetPriceInv           = 1d / priceList[i];
                    DoubleArray sensitivities            = sensi.getSensitivity(alphaName, currency).Sensitivity;
                    if (sabrDefinition.BetaCurve.Present)
                    { // beta fixed
                        sensitivities = sensitivities.concat(sensi.getSensitivity(rhoName, currency).Sensitivity);
                    }
                    else
                    { // rho fixed
                        sensitivities = sensitivities.concat(sensi.getSensitivity(betaName, currency).Sensitivity);
                    }
                    jacobian[i] = sensitivities.concat(sensi.getSensitivity(nuName, currency).Sensitivity).multipliedBy(targetPriceInv).toArray();
                }
                return(DoubleMatrix.ofUnsafe(jacobian));
            };
            return(jacobianFunction);
        }
Example #2
0
        public virtual void recovery_test_black_fixedRho()
        {
            double rho = 0.15;
            SabrIborCapletFloorletVolatilityCalibrationDefinition definition = SabrIborCapletFloorletVolatilityCalibrationDefinition.ofFixedRho(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, rho, ALPHA_KNOTS, BETA_RHO_KNOTS, NU_KNOTS, DOUBLE_QUADRATIC, FLAT, FLAT, HAGAN);
            ImmutableList <Period> maturities = createBlackMaturities();
            DoubleArray            strikes    = createBlackStrikes();
            DoubleMatrix           volData    = createFullBlackDataMatrix();
            DoubleMatrix           error      = DoubleMatrix.filled(volData.rowCount(), volData.columnCount(), 1.0e-3);
            RawOptionData          data       = RawOptionData.of(maturities, strikes, ValueType.STRIKE, volData, error, ValueType.BLACK_VOLATILITY);
            IborCapletFloorletVolatilityCalibrationResult res     = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER);
            SabrParametersIborCapletFloorletVolatilities  resVols = (SabrParametersIborCapletFloorletVolatilities)res.Volatilities;

            for (int i = 0; i < NUM_BLACK_STRIKES; ++i)
            {
                Pair <IList <ResolvedIborCapFloorLeg>, IList <double> > capsAndVols = getCapsBlackVols(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.blackVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols[j]);
                    BlackIborCapletFloorletExpiryStrikeVolatilities constVol = BlackIborCapletFloorletExpiryStrikeVolatilities.of(USD_LIBOR_3M, CALIBRATION_TIME, volSurface);
                    double priceOrg   = LEG_PRICER_BLACK.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);
                }
            }
            assertEquals(resVols.Index, USD_LIBOR_3M);
            assertEquals(resVols.Name, definition.Name);
            assertEquals(resVols.ValuationDateTime, CALIBRATION_TIME);
            assertEquals(resVols.ParameterCount, ALPHA_KNOTS.size() + BETA_RHO_KNOTS.size() + NU_KNOTS.size() + 2);     // beta, shift counted
            assertEquals(resVols.Parameters.ShiftCurve, definition.ShiftCurve);
            assertEquals(resVols.Parameters.RhoCurve, definition.RhoCurve.get());
        }
        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 test_recovery_black_fixedRho()
        {
            SabrIborCapletFloorletVolatilityBootstrapDefinition definition = SabrIborCapletFloorletVolatilityBootstrapDefinition.ofFixedRho(IborCapletFloorletVolatilitiesName.of("test"), USD_LIBOR_3M, ACT_ACT_ISDA, 0.0, CurveInterpolators.STEP_UPPER, CurveExtrapolators.FLAT, CurveExtrapolators.FLAT, SabrHaganVolatilityFunctionProvider.DEFAULT);
            DoubleMatrix  volData    = createFullBlackDataMatrix();
            double        errorValue = 1.0e-3;
            DoubleMatrix  error      = DoubleMatrix.filled(volData.rowCount(), volData.columnCount(), errorValue);
            RawOptionData data       = RawOptionData.of(createBlackMaturities(), createBlackStrikes(), ValueType.STRIKE, volData, error, ValueType.BLACK_VOLATILITY);
            IborCapletFloorletVolatilityCalibrationResult res     = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER);
            SabrParametersIborCapletFloorletVolatilities  resVols = (SabrParametersIborCapletFloorletVolatilities)res.Volatilities;
            double expSq = 0d;

            for (int i = 0; i < NUM_BLACK_STRIKES; ++i)
            {
                Pair <IList <ResolvedIborCapFloorLeg>, IList <double> > capsAndVols = getCapsBlackVols(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.blackVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols[j]);
                    BlackIborCapletFloorletExpiryStrikeVolatilities constVol = BlackIborCapletFloorletExpiryStrikeVolatilities.of(USD_LIBOR_3M, CALIBRATION_TIME, volSurface);
                    double priceOrg   = LEG_PRICER_BLACK.presentValue(caps[j], RATES_PROVIDER, constVol).Amount;
                    double priceCalib = LEG_PRICER_SABR.presentValue(caps[j], RATES_PROVIDER, resVols).Amount;
                    expSq += Math.Pow((priceOrg - priceCalib) / priceOrg / errorValue, 2);
                    assertEquals(priceOrg, priceCalib, Math.Max(priceOrg, 1d) * TOL * 3d);
                }
            }
            assertEquals(res.ChiSquare, expSq, expSq * 1.0e-14);
            assertEquals(resVols.Index, USD_LIBOR_3M);
            assertEquals(resVols.Name, definition.Name);
            assertEquals(resVols.ValuationDateTime, CALIBRATION_TIME);
            assertEquals(resVols.Parameters.ShiftCurve, definition.ShiftCurve);
            assertEquals(resVols.Parameters.RhoCurve, definition.RhoCurve.get());
        }
        public virtual void coverage()
        {
            SabrParametersIborCapletFloorletVolatilities test1 = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM);

            coverImmutableBean(test1);
            SabrParametersIborCapletFloorletVolatilities test2 = SabrParametersIborCapletFloorletVolatilities.of(NAME2, IborIndices.EUR_LIBOR_3M, DATE_TIME.plusDays(1), IborCapletFloorletSabrRateVolatilityDataSet.SABR_PARAM_FLAT);

            coverBeanEquals(test1, test2);
        }
Example #6
0
 // price function
 private System.Func <DoubleArray, DoubleArray> createPriceFunction(SabrIborCapletFloorletVolatilityCalibrationDefinition sabrDefinition, RatesProvider ratesProvider, SabrParametersIborCapletFloorletVolatilities volatilities, IList <ResolvedIborCapFloorLeg> capList, IList <double> priceList)
 {
     System.Func <DoubleArray, DoubleArray> priceFunction = (DoubleArray x) =>
     {
         SabrParametersIborCapletFloorletVolatilities volsNew = updateParameters(sabrDefinition, volatilities, x);
         return(DoubleArray.of(capList.Count, n => sabrPricer.presentValue(capList[n], ratesProvider, volsNew).Amount / priceList[n]));
     };
     return(priceFunction);
 }
        public virtual void test_calc()
        {
            SabrParametersIborCapletFloorletVolatilities test = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM);

            assertEquals(test.alpha(1.56), PARAM.alpha(1.56));
            assertEquals(test.beta(1.56), PARAM.beta(1.56));
            assertEquals(test.rho(1.56), PARAM.rho(1.56));
            assertEquals(test.nu(1.56), PARAM.nu(1.56));
            assertEquals(test.shift(1.56), PARAM.shift(1.56));
        }
Example #8
0
        // price function
        private System.Func <DoubleArray, DoubleArray> createPriceFunction(RatesProvider ratesProvider, SabrParametersIborCapletFloorletVolatilities volatilities, ZonedDateTime prevExpiry, IList <ResolvedIborCapFloorLeg> capList, IList <double> priceList, int[] startIndex, int nExpiries, int timeIndex, int nCaplets, bool betaFixed)
        {
            int currentStart = startIndex[timeIndex];

            System.Func <DoubleArray, DoubleArray> priceFunction = (DoubleArray x) =>
            {
                SabrParametersIborCapletFloorletVolatilities volsNew = updateParameters(volatilities, nExpiries, timeIndex, betaFixed, x);
                return(DoubleArray.of(nCaplets, n => capList[currentStart + n].CapletFloorletPeriods.Where(p => p.FixingDateTime.isAfter(prevExpiry)).Select(p => sabrPeriodPricer.presentValue(p, ratesProvider, volsNew).Amount).Sum() / priceList[currentStart + n]));
            };
            return(priceFunction);
        }
        public virtual void test_relativeTime()
        {
            SabrParametersIborCapletFloorletVolatilities prov = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM);
            double test1 = prov.relativeTime(DATE_TIME);

            assertEquals(test1, 0d);
            double test2 = prov.relativeTime(DATE_TIME.plusYears(2));
            double test3 = prov.relativeTime(DATE_TIME.minusYears(2));

            assertEquals(test2, -test3, 1e-2);
        }
        public virtual void test_findData()
        {
            SabrParametersIborCapletFloorletVolatilities test = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM);

            assertEquals(test.findData(PARAM.AlphaCurve.Name), PARAM.AlphaCurve);
            assertEquals(test.findData(PARAM.BetaCurve.Name), PARAM.BetaCurve);
            assertEquals(test.findData(PARAM.RhoCurve.Name), PARAM.RhoCurve);
            assertEquals(test.findData(PARAM.NuCurve.Name), PARAM.NuCurve);
            assertEquals(test.findData(PARAM.ShiftCurve.Name), PARAM.ShiftCurve);
            assertEquals(test.findData(SurfaceName.of("Rubbish")), null);
        }
Example #11
0
        //-------------------------------------------------------------------------
        public override IborCapletFloorletVolatilityCalibrationResult calibrate(IborCapletFloorletVolatilityDefinition definition, ZonedDateTime calibrationDateTime, RawOptionData capFloorData, RatesProvider ratesProvider)
        {
            ArgChecker.isTrue(ratesProvider.ValuationDate.Equals(calibrationDateTime.toLocalDate()), "valuationDate of ratesProvider should be coherent to calibrationDateTime");
            ArgChecker.isTrue(definition is SabrIborCapletFloorletVolatilityCalibrationDefinition, "definition should be SabrIborCapletFloorletVolatilityCalibrationDefinition");
            SabrIborCapletFloorletVolatilityCalibrationDefinition sabrDefinition = (SabrIborCapletFloorletVolatilityCalibrationDefinition)definition;
            // unpack cap data, create node caps
            IborIndex index           = sabrDefinition.Index;
            LocalDate calibrationDate = calibrationDateTime.toLocalDate();
            LocalDate baseDate        = index.EffectiveDateOffset.adjust(calibrationDate, ReferenceData);
            LocalDate startDate       = baseDate.plus(index.Tenor);

            System.Func <Surface, IborCapletFloorletVolatilities> volatilitiesFunction = this.volatilitiesFunction(sabrDefinition, calibrationDateTime, capFloorData);
            SurfaceMetadata metadata   = sabrDefinition.createMetadata(capFloorData);
            IList <Period>  expiries   = capFloorData.Expiries;
            DoubleArray     strikes    = capFloorData.Strikes;
            int             nExpiries  = expiries.Count;
            IList <double>  timeList   = new List <double>();
            IList <double>  strikeList = new List <double>();
            IList <double>  volList    = new List <double>();
            IList <ResolvedIborCapFloorLeg> capList = new List <ResolvedIborCapFloorLeg>();
            IList <double> priceList   = new List <double>();
            IList <double> errorList   = new List <double>();
            DoubleMatrix   errorMatrix = capFloorData.Error.orElse(DoubleMatrix.filled(nExpiries, strikes.size(), 1d));

            int[] startIndex = new int[nExpiries + 1];
            for (int i = 0; i < nExpiries; ++i)
            {
                LocalDate   endDate           = baseDate.plus(expiries[i]);
                DoubleArray volatilityForTime = capFloorData.Data.row(i);
                DoubleArray errorForTime      = errorMatrix.row(i);
                reduceRawData(sabrDefinition, ratesProvider, capFloorData.Strikes, volatilityForTime, errorForTime, startDate, endDate, metadata, volatilitiesFunction, timeList, strikeList, volList, capList, priceList, errorList);
                startIndex[i + 1] = volList.Count;
                ArgChecker.isTrue(startIndex[i + 1] > startIndex[i], "no valid option data for {}", expiries[i]);
            }
            // create initial caplet vol surface
            IList <CurveMetadata> metadataList                = sabrDefinition.createSabrParameterMetadata();
            DoubleArray           initialValues               = sabrDefinition.createFullInitialValues();
            IList <Curve>         curveList                   = sabrDefinition.createSabrParameterCurve(metadataList, initialValues);
            SabrParameters        sabrParamsInitial           = SabrParameters.of(curveList[0], curveList[1], curveList[2], curveList[3], sabrDefinition.ShiftCurve, sabrDefinition.SabrVolatilityFormula);
            SabrParametersIborCapletFloorletVolatilities vols = SabrParametersIborCapletFloorletVolatilities.of(sabrDefinition.Name, index, calibrationDateTime, sabrParamsInitial);
            // solve least square
            UncoupledParameterTransforms transform = new UncoupledParameterTransforms(initialValues, sabrDefinition.createFullTransform(TRANSFORMS), new BitArray());

            System.Func <DoubleArray, DoubleArray>  valueFunction    = createPriceFunction(sabrDefinition, ratesProvider, vols, capList, priceList);
            System.Func <DoubleArray, DoubleMatrix> jacobianFunction = createJacobianFunction(sabrDefinition, ratesProvider, vols, capList, priceList, index.Currency);
            NonLinearTransformFunction      transFunc    = new NonLinearTransformFunction(valueFunction, jacobianFunction, transform);
            LeastSquareResults              res          = solver.solve(DoubleArray.filled(priceList.Count, 1d), DoubleArray.copyOf(errorList), transFunc.FittingFunction, transFunc.FittingJacobian, transform.transform(initialValues));
            LeastSquareResultsWithTransform resTransform = new LeastSquareResultsWithTransform(res, transform);

            vols = updateParameters(sabrDefinition, vols, resTransform.ModelParameters);

            return(IborCapletFloorletVolatilityCalibrationResult.ofLeastSquare(vols, res.ChiSq));
        }
        public virtual void test_parameterSensitivity()
        {
            double alphaSensi = 2.24, betaSensi = 3.45, rhoSensi = -2.12, nuSensi = -0.56, shiftSensi = 2.5;
            SabrParametersIborCapletFloorletVolatilities prov = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM);

            for (int i = 0; i < NB_TEST; i++)
            {
                double                         expiryTime             = prov.relativeTime(TEST_OPTION_EXPIRY[i]);
                PointSensitivities             point                  = PointSensitivities.of(IborCapletFloorletSabrSensitivity.of(NAME, expiryTime, ALPHA, EUR, alphaSensi), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime, BETA, EUR, betaSensi), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime, RHO, EUR, rhoSensi), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime, NU, EUR, nuSensi), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime, SHIFT, EUR, shiftSensi));
                CurrencyParameterSensitivities sensiComputed          = prov.parameterSensitivity(point);
                UnitParameterSensitivity       alphaSensitivities     = prov.Parameters.AlphaCurve.yValueParameterSensitivity(expiryTime);
                UnitParameterSensitivity       betaSensitivities      = prov.Parameters.BetaCurve.yValueParameterSensitivity(expiryTime);
                UnitParameterSensitivity       rhoSensitivities       = prov.Parameters.RhoCurve.yValueParameterSensitivity(expiryTime);
                UnitParameterSensitivity       nuSensitivities        = prov.Parameters.NuCurve.yValueParameterSensitivity(expiryTime);
                UnitParameterSensitivity       shiftSensitivities     = prov.Parameters.ShiftCurve.yValueParameterSensitivity(expiryTime);
                CurrencyParameterSensitivity   alphaSensiObj          = sensiComputed.getSensitivity(IborCapletFloorletSabrRateVolatilityDataSet.META_ALPHA.CurveName, EUR);
                CurrencyParameterSensitivity   betaSensiObj           = sensiComputed.getSensitivity(IborCapletFloorletSabrRateVolatilityDataSet.META_BETA.CurveName, EUR);
                CurrencyParameterSensitivity   rhoSensiObj            = sensiComputed.getSensitivity(IborCapletFloorletSabrRateVolatilityDataSet.META_RHO.CurveName, EUR);
                CurrencyParameterSensitivity   nuSensiObj             = sensiComputed.getSensitivity(IborCapletFloorletSabrRateVolatilityDataSet.META_NU.CurveName, EUR);
                CurrencyParameterSensitivity   shiftSensiObj          = sensiComputed.getSensitivity(IborCapletFloorletSabrRateVolatilityDataSet.META_SHIFT.CurveName, EUR);
                DoubleArray                    alphaNodeSensiComputed = alphaSensiObj.Sensitivity;
                DoubleArray                    betaNodeSensiComputed  = betaSensiObj.Sensitivity;
                DoubleArray                    rhoNodeSensiComputed   = rhoSensiObj.Sensitivity;
                DoubleArray                    nuNodeSensiComputed    = nuSensiObj.Sensitivity;
                DoubleArray                    shiftNodeSensiComputed = shiftSensiObj.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());
                assertEquals(shiftSensitivities.Sensitivity.size(), shiftNodeSensiComputed.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);
                }
                for (int k = 0; k < shiftNodeSensiComputed.size(); ++k)
                {
                    assertEquals(shiftNodeSensiComputed.get(k), shiftSensitivities.Sensitivity.get(k) * shiftSensi, TOLERANCE_VOL);
                }
            }
        }
Example #13
0
        // update vols
        private SabrParametersIborCapletFloorletVolatilities updateParameters(SabrIborCapletFloorletVolatilityCalibrationDefinition sabrDefinition, SabrParametersIborCapletFloorletVolatilities volatilities, DoubleArray newValues)
        {
            SabrParameters sabrParams    = volatilities.Parameters;
            CurveMetadata  alphaMetadata = sabrParams.AlphaCurve.Metadata;
            CurveMetadata  betaMetadata  = sabrParams.BetaCurve.Metadata;
            CurveMetadata  rhoMetadata   = sabrParams.RhoCurve.Metadata;
            CurveMetadata  nuMetadata    = sabrParams.NuCurve.Metadata;
            IList <Curve>  newCurveList  = sabrDefinition.createSabrParameterCurve(ImmutableList.of(alphaMetadata, betaMetadata, rhoMetadata, nuMetadata), newValues);
            SabrParameters newSabrParams = SabrParameters.of(newCurveList[0], newCurveList[1], newCurveList[2], newCurveList[3], sabrDefinition.ShiftCurve, sabrDefinition.SabrVolatilityFormula);
            SabrParametersIborCapletFloorletVolatilities newVols = SabrParametersIborCapletFloorletVolatilities.of(volatilities.Name, volatilities.Index, volatilities.ValuationDateTime, newSabrParams);

            return(newVols);
        }
Example #14
0
        // update vols
        private SabrParametersIborCapletFloorletVolatilities updateParameters(SabrParametersIborCapletFloorletVolatilities volatilities, int nExpiries, int timeIndex, bool betaFixed, DoubleArray newParameters)
        {
            int nBetaParams = volatilities.Parameters.BetaCurve.ParameterCount;
            int nRhoParams  = volatilities.Parameters.RhoCurve.ParameterCount;
            SabrParametersIborCapletFloorletVolatilities newVols = volatilities.withParameter(timeIndex, newParameters.get(0)).withParameter(timeIndex + nExpiries + nBetaParams + nRhoParams, newParameters.get(3));

            if (betaFixed)
            {
                newVols = newVols.withParameter(timeIndex + nExpiries + nBetaParams, newParameters.get(2));
                return(newVols);
            }
            newVols = newVols.withParameter(timeIndex + nExpiries, newParameters.get(1));
            return(newVols);
        }
        public virtual void test_volatility()
        {
            SabrParametersIborCapletFloorletVolatilities prov = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM);

            for (int i = 0; i < NB_TEST; i++)
            {
                for (int j = 0; j < NB_STRIKE; ++j)
                {
                    double expiryTime  = prov.relativeTime(TEST_OPTION_EXPIRY[i]);
                    double volExpected = PARAM.volatility(expiryTime, TEST_STRIKE[j], TEST_FORWARD);
                    double volComputed = prov.volatility(TEST_OPTION_EXPIRY[i], TEST_STRIKE[j], TEST_FORWARD);
                    assertEquals(volComputed, volExpected, TOLERANCE_VOL);
                    ValueDerivatives volAdjExpected = PARAM.volatilityAdjoint(expiryTime, TEST_STRIKE[j], TEST_FORWARD);
                    ValueDerivatives volAdjComputed = prov.volatilityAdjoint(expiryTime, TEST_STRIKE[j], TEST_FORWARD);
                    assertEquals(volAdjComputed.Value, volExpected, TOLERANCE_VOL);
                    assertTrue(DoubleArrayMath.fuzzyEquals(volAdjComputed.Derivatives.toArray(), volAdjExpected.Derivatives.toArray(), TOLERANCE_VOL));
                }
            }
        }
        public virtual void test_of()
        {
            SabrParametersIborCapletFloorletVolatilities test = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM);

            assertEquals(test.Index, EUR_EURIBOR_3M);
            assertEquals(test.DayCount, ACT_ACT_ISDA);
            assertEquals(test.Parameters, PARAM);
            assertEquals(test.ValuationDateTime, DATE_TIME);
            assertEquals(test.ParameterCount, PARAM.ParameterCount);
            int    nParams  = PARAM.ParameterCount;
            double newValue = 152d;

            for (int i = 0; i < nParams; ++i)
            {
                assertEquals(test.getParameter(i), PARAM.getParameter(i));
                assertEquals(test.getParameterMetadata(i), PARAM.getParameterMetadata(i));
                assertEquals(test.withParameter(i, newValue), SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM.withParameter(i, newValue)));
                assertEquals(test.withPerturbation((n, v, m) => 2d * v), SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, DATE_TIME, PARAM.withPerturbation((n, v, m) => 2d * v)));
            }
        }
        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 };
            SabrParametersIborCapletFloorletVolatilities prov = SabrParametersIborCapletFloorletVolatilities.of(NAME, EUR_EURIBOR_3M, 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(IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, ALPHA, EUR, points1[0]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, BETA, EUR, points1[1]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, RHO, EUR, points1[2]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, NU, EUR, points1[3]));
                PointSensitivities             sensi2   = PointSensitivities.of(IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, ALPHA, EUR, points2[0]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, BETA, EUR, points2[1]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, RHO, EUR, points2[2]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime0, NU, EUR, points2[3]));
                PointSensitivities             sensi3   = PointSensitivities.of(IborCapletFloorletSabrSensitivity.of(NAME, expiryTime3, ALPHA, EUR, points3[0]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime3, BETA, EUR, points3[1]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime3, RHO, EUR, points3[2]), IborCapletFloorletSabrSensitivity.of(NAME, expiryTime3, NU, EUR, 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.AlphaCurve.Name, EUR).Sensitivity.toArray(), expected.getSensitivity(PARAM.AlphaCurve.Name, EUR).Sensitivity.toArray(), TOLERANCE_VOL);
                DoubleArrayMath.fuzzyEquals(computed.getSensitivity(PARAM.BetaCurve.Name, EUR).Sensitivity.toArray(), expected.getSensitivity(PARAM.BetaCurve.Name, EUR).Sensitivity.toArray(), TOLERANCE_VOL);
                DoubleArrayMath.fuzzyEquals(computed.getSensitivity(PARAM.RhoCurve.Name, EUR).Sensitivity.toArray(), expected.getSensitivity(PARAM.RhoCurve.Name, EUR).Sensitivity.toArray(), TOLERANCE_VOL);
                DoubleArrayMath.fuzzyEquals(computed.getSensitivity(PARAM.NuCurve.Name, EUR).Sensitivity.toArray(), expected.getSensitivity(PARAM.NuCurve.Name, EUR).Sensitivity.toArray(), TOLERANCE_VOL);
            }
        }
        public virtual void test_recovery_flatVol()
        {
            double beta = 0.8;
            SabrIborCapletFloorletVolatilityBootstrapDefinition definition = SabrIborCapletFloorletVolatilityBootstrapDefinition.ofFixedBeta(IborCapletFloorletVolatilitiesName.of("test"), USD_LIBOR_3M, ACT_ACT_ISDA, beta, CurveInterpolators.STEP_UPPER, CurveExtrapolators.FLAT, CurveExtrapolators.FLAT, SabrHaganVolatilityFunctionProvider.DEFAULT);
            RawOptionData data = RawOptionData.of(createBlackMaturities(), createBlackStrikes(), ValueType.STRIKE, createFullFlatBlackDataMatrix(), ValueType.BLACK_VOLATILITY);
            IborCapletFloorletVolatilityCalibrationResult res     = CALIBRATOR.calibrate(definition, CALIBRATION_TIME, data, RATES_PROVIDER);
            SabrParametersIborCapletFloorletVolatilities  resVols = (SabrParametersIborCapletFloorletVolatilities)res.Volatilities;

            for (int i = 0; i < NUM_BLACK_STRIKES; ++i)
            {
                Pair <IList <ResolvedIborCapFloorLeg>, IList <double> > capsAndVols = getCapsFlatBlackVols(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.blackVolatilityByExpiryStrike("test", ACT_ACT_ISDA), vols[j]);
                    BlackIborCapletFloorletExpiryStrikeVolatilities constVol = BlackIborCapletFloorletExpiryStrikeVolatilities.of(USD_LIBOR_3M, CALIBRATION_TIME, volSurface);
                    double priceOrg   = LEG_PRICER_BLACK.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);
                }
            }
        }
Example #19
0
        // node sensitivity function
        private System.Func <DoubleArray, DoubleMatrix> createJacobianFunction(RatesProvider ratesProvider, SabrParametersIborCapletFloorletVolatilities volatilities, ZonedDateTime prevExpiry, IList <ResolvedIborCapFloorLeg> capList, IList <double> priceList, Currency currency, int[] startIndex, int nExpiries, int timeIndex, int nCaplets, bool betaFixed)
        {
            Curve alphaCurve   = volatilities.Parameters.AlphaCurve;
            Curve betaCurve    = volatilities.Parameters.BetaCurve;
            Curve rhoCurve     = volatilities.Parameters.RhoCurve;
            Curve nuCurve      = volatilities.Parameters.NuCurve;
            int   currentStart = startIndex[timeIndex];

            System.Func <DoubleArray, DoubleMatrix> jacobianFunction = (DoubleArray x) =>
            {
                SabrParametersIborCapletFloorletVolatilities volsNew = updateParameters(volatilities, nExpiries, timeIndex, betaFixed, x);
//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[][] jacobian = new double[nCaplets][4];
                double[][] jacobian = RectangularArrays.ReturnRectangularDoubleArray(nCaplets, 4);
                for (int i = 0; i < nCaplets; ++i)
                {
                    PointSensitivities             point       = capList[currentStart + i].CapletFloorletPeriods.Where(p => p.FixingDateTime.isAfter(prevExpiry)).Select(p => sabrPeriodPricer.presentValueSensitivityModelParamsSabr(p, ratesProvider, volsNew)).Aggregate((c1, c2) => c1.combinedWith(c2)).get().build();
                    double                         targetPrice = priceList[currentStart + i];
                    CurrencyParameterSensitivities sensi       = volsNew.parameterSensitivity(point);
                    jacobian[i][0] = sensi.getSensitivity(alphaCurve.Name, currency).Sensitivity.get(timeIndex) / targetPrice;
                    if (betaFixed)
                    {
                        jacobian[i][1] = 0d;
                        jacobian[i][2] = sensi.getSensitivity(rhoCurve.Name, currency).Sensitivity.get(timeIndex) / targetPrice;
                    }
                    else
                    {
                        jacobian[i][1] = sensi.getSensitivity(betaCurve.Name, currency).Sensitivity.get(timeIndex) / targetPrice;
                        jacobian[i][2] = 0d;
                    }
                    jacobian[i][3] = sensi.getSensitivity(nuCurve.Name, currency).Sensitivity.get(timeIndex) / targetPrice;
                }
                return(DoubleMatrix.ofUnsafe(jacobian));
            };
            return(jacobianFunction);
        }
Example #20
0
 /// <summary>
 /// Obtains {@code SabrParametersIborCapletFloorletVolatilities} with constant shift for specified valuation date.
 /// </summary>
 /// <param name="dateTime">  the valuation date time </param>
 /// <param name="index">  the index </param>
 /// <returns> the volatility provider </returns>
 public static SabrParametersIborCapletFloorletVolatilities getVolatilities(ZonedDateTime dateTime, IborIndex index)
 {
     return(SabrParametersIborCapletFloorletVolatilities.of(NAME, index, dateTime, SABR_PARAM_CONST_SHIFT));
 }
Example #21
0
        /// <summary>
        /// Obtains {@code SabrParametersIborCapletFloorletVolatilities} with constant SABR parameters for specified valuation date.
        /// </summary>
        /// <param name="valuationDate">  the valuation date </param>
        /// <param name="index">  the index </param>
        /// <returns> the volatility provider </returns>
        public static SabrParametersIborCapletFloorletVolatilities getVolatilitiesFlatParameters(LocalDate valuationDate, IborIndex index)
        {
            ZonedDateTime dateTime = valuationDate.atStartOfDay(ZoneOffset.UTC);

            return(SabrParametersIborCapletFloorletVolatilities.of(NAME, index, dateTime, SABR_PARAM_FLAT));
        }
Example #22
0
        //-------------------------------------------------------------------------
        public override IborCapletFloorletVolatilityCalibrationResult calibrate(IborCapletFloorletVolatilityDefinition definition, ZonedDateTime calibrationDateTime, RawOptionData capFloorData, RatesProvider ratesProvider)
        {
            ArgChecker.isTrue(ratesProvider.ValuationDate.Equals(calibrationDateTime.toLocalDate()), "valuationDate of ratesProvider should be coherent to calibrationDateTime");
            ArgChecker.isTrue(definition is SabrIborCapletFloorletVolatilityBootstrapDefinition, "definition should be SabrIborCapletFloorletVolatilityBootstrapDefinition");
            SabrIborCapletFloorletVolatilityBootstrapDefinition bsDefinition = (SabrIborCapletFloorletVolatilityBootstrapDefinition)definition;
            IborIndex index           = bsDefinition.Index;
            LocalDate calibrationDate = calibrationDateTime.toLocalDate();
            LocalDate baseDate        = index.EffectiveDateOffset.adjust(calibrationDate, ReferenceData);
            LocalDate startDate       = baseDate.plus(index.Tenor);

            System.Func <Surface, IborCapletFloorletVolatilities> volatilitiesFunction = this.volatilitiesFunction(bsDefinition, calibrationDateTime, capFloorData);
            SurfaceMetadata metaData                = bsDefinition.createMetadata(capFloorData);
            IList <Period>  expiries                = capFloorData.Expiries;
            int             nExpiries               = expiries.Count;
            DoubleArray     strikes                 = capFloorData.Strikes;
            DoubleMatrix    errorsMatrix            = capFloorData.Error.orElse(DoubleMatrix.filled(nExpiries, strikes.size(), 1d));
            IList <double>  timeList                = new List <double>();
            IList <double>  strikeList              = new List <double>();
            IList <double>  volList                 = new List <double>();
            IList <ResolvedIborCapFloorLeg> capList = new List <ResolvedIborCapFloorLeg>();
            IList <double> priceList                = new List <double>();
            IList <double> errorList                = new List <double>();

            int[] startIndex = new int[nExpiries + 1];
            for (int i = 0; i < nExpiries; ++i)
            {
                LocalDate   endDate        = baseDate.plus(expiries[i]);
                DoubleArray volatilityData = capFloorData.Data.row(i);
                DoubleArray errors         = errorsMatrix.row(i);
                reduceRawData(bsDefinition, ratesProvider, strikes, volatilityData, errors, startDate, endDate, metaData, volatilitiesFunction, timeList, strikeList, volList, capList, priceList, errorList);
                startIndex[i + 1] = volList.Count;
                ArgChecker.isTrue(startIndex[i + 1] > startIndex[i], "no valid option data for {}", expiries[i]);
            }

            IList <CurveMetadata> metadataList   = bsDefinition.createSabrParameterMetadata();
            DoubleArray           timeToExpiries = DoubleArray.of(nExpiries, i => timeList[startIndex[i]]);

            BitArray @fixed  = new BitArray();
            bool     betaFix = false;
            Curve    betaCurve;
            Curve    rhoCurve;

            if (bsDefinition.BetaCurve.Present)
            {
                betaFix = true;
                @fixed.Set(1, true);
                betaCurve = bsDefinition.BetaCurve.get();
                rhoCurve  = InterpolatedNodalCurve.of(metadataList[2], timeToExpiries, DoubleArray.filled(nExpiries), bsDefinition.Interpolator, bsDefinition.ExtrapolatorLeft, bsDefinition.ExtrapolatorRight);
            }
            else
            {
                @fixed.Set(2, true);
                betaCurve = InterpolatedNodalCurve.of(metadataList[1], timeToExpiries, DoubleArray.filled(nExpiries), bsDefinition.Interpolator, bsDefinition.ExtrapolatorLeft, bsDefinition.ExtrapolatorRight);
                rhoCurve  = bsDefinition.RhoCurve.get();
            }
            InterpolatedNodalCurve alphaCurve = InterpolatedNodalCurve.of(metadataList[0], timeToExpiries, DoubleArray.filled(nExpiries), bsDefinition.Interpolator, bsDefinition.ExtrapolatorLeft, bsDefinition.ExtrapolatorRight);
            InterpolatedNodalCurve nuCurve    = InterpolatedNodalCurve.of(metadataList[3], timeToExpiries, DoubleArray.filled(nExpiries), bsDefinition.Interpolator, bsDefinition.ExtrapolatorLeft, bsDefinition.ExtrapolatorRight);
            Curve          shiftCurve         = bsDefinition.ShiftCurve;
            SabrParameters sabrParams         = SabrParameters.of(alphaCurve, betaCurve, rhoCurve, nuCurve, shiftCurve, bsDefinition.SabrVolatilityFormula);
            SabrParametersIborCapletFloorletVolatilities vols = SabrParametersIborCapletFloorletVolatilities.of(bsDefinition.Name, index, calibrationDateTime, sabrParams);
            double        totalChiSq = 0d;
            ZonedDateTime prevExpiry = calibrationDateTime.minusDays(1L);     // included if calibrationDateTime == fixingDateTime

            for (int i = 0; i < nExpiries; ++i)
            {
                DoubleArray start = computeInitialValues(ratesProvider, betaCurve, shiftCurve, timeList, volList, capList, startIndex, i, betaFix, capFloorData.DataType);
                UncoupledParameterTransforms transform = new UncoupledParameterTransforms(start, TRANSFORMS, @fixed);
                int nCaplets     = startIndex[i + 1] - startIndex[i];
                int currentStart = startIndex[i];
                System.Func <DoubleArray, DoubleArray>  valueFunction    = createPriceFunction(ratesProvider, vols, prevExpiry, capList, priceList, startIndex, nExpiries, i, nCaplets, betaFix);
                System.Func <DoubleArray, DoubleMatrix> jacobianFunction = createJacobianFunction(ratesProvider, vols, prevExpiry, capList, priceList, index.Currency, startIndex, nExpiries, i, nCaplets, betaFix);
                NonLinearTransformFunction transFunc = new NonLinearTransformFunction(valueFunction, jacobianFunction, transform);
                DoubleArray        adjustedPrices    = this.adjustedPrices(ratesProvider, vols, prevExpiry, capList, priceList, startIndex, i, nCaplets);
                DoubleArray        errors            = DoubleArray.of(nCaplets, n => errorList[currentStart + n]);
                LeastSquareResults res = solver.solve(adjustedPrices, errors, transFunc.FittingFunction, transFunc.FittingJacobian, transform.transform(start));
                LeastSquareResultsWithTransform resTransform = new LeastSquareResultsWithTransform(res, transform);
                vols        = updateParameters(vols, nExpiries, i, betaFix, resTransform.ModelParameters);
                totalChiSq += res.ChiSq;
                prevExpiry  = capList[startIndex[i + 1] - 1].FinalFixingDateTime;
            }
            return(IborCapletFloorletVolatilityCalibrationResult.ofLeastSquare(vols, totalChiSq));
        }