/// <summary>
        /// Calculates the present value sensitivity of the FX barrier option product.
        /// <para>
        /// The present value sensitivity of the product is the sensitivity of <seealso cref="#presentValue"/> to
        /// the underlying curve parameters.
        /// </para>
        /// <para>
        /// The sensitivity is computed by bump and re-price.
        ///
        /// </para>
        /// </summary>
        /// <param name="option">  the option product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the Black volatility provider </param>
        /// <param name="baseTreeData">  the trinomial tree data </param>
        /// <returns> the present value of the product </returns>
        public virtual CurrencyParameterSensitivities presentValueSensitivityRates(ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities, RecombiningTrinomialTreeData baseTreeData)
        {
            ArgChecker.isTrue(baseTreeData.NumberOfSteps == calibrator.NumberOfSteps, "the number of steps mismatch between pricer and trinomial tree data");
            double                         shift            = 1.0e-5;
            CurrencyAmount                 pvBase           = presentValue(option, ratesProvider, volatilities, baseTreeData);
            ResolvedFxVanillaOption        underlyingOption = option.UnderlyingOption;
            ResolvedFxSingle               underlyingFx     = underlyingOption.Underlying;
            CurrencyPair                   currencyPair     = underlyingFx.CurrencyPair;
            ImmutableRatesProvider         immRatesProvider = ratesProvider.toImmutableRatesProvider();
            ImmutableMap <Currency, Curve> baseCurves       = immRatesProvider.DiscountCurves;
            CurrencyParameterSensitivities result           = CurrencyParameterSensitivities.empty();

            foreach (KeyValuePair <Currency, Curve> entry in baseCurves.entrySet())
            {
                if (currencyPair.contains(entry.Key))
                {
                    Curve       curve       = entry.Value;
                    int         nParams     = curve.ParameterCount;
                    DoubleArray sensitivity = DoubleArray.of(nParams, i =>
                    {
                        Curve dscBumped = curve.withParameter(i, curve.getParameter(i) + shift);
                        IDictionary <Currency, Curve> mapBumped = new Dictionary <Currency, Curve>(baseCurves);
                        mapBumped[entry.Key] = dscBumped;
                        ImmutableRatesProvider providerDscBumped = immRatesProvider.toBuilder().discountCurves(mapBumped).build();
                        double pvBumped = presentValue(option, providerDscBumped, volatilities).Amount;
                        return((pvBumped - pvBase.Amount) / shift);
                    });
                    result = result.combinedWith(curve.createParameterSensitivity(pvBase.Currency, sensitivity));
                }
            }
            return(result);
        }
Ejemplo n.º 2
0
        //-------------------------------------------------------------------------
        // computes diagonal part
        private CurrencyParameterSensitivities sensitivityDiagonal(RatesProvider provider, System.Func <ImmutableRatesProvider, CurrencyAmount> valueFn)
        {
            ImmutableRatesProvider         immProv     = provider.toImmutableRatesProvider();
            CurrencyAmount                 valueInit   = valueFn(immProv);
            CurrencyParameterSensitivities discounting = sensitivity(immProv, immProv.DiscountCurves, (@base, bumped) => @base.toBuilder().discountCurves(bumped).build(), valueFn, valueInit);
            CurrencyParameterSensitivities forward     = sensitivity(immProv, immProv.IndexCurves, (@base, bumped) => @base.toBuilder().indexCurves(bumped).build(), valueFn, valueInit);

            return(discounting.combinedWith(forward));
        }
        public virtual void test_ratesProvider()
        {
            ImmutableMap <Currency, CurveId> discounts = ImmutableMap.of(USD, CURVE_ID_DSC);
            ImmutableMap <Index, CurveId>    forwards  = ImmutableMap.of(USD_FED_FUND, CURVE_ID_DSC, USD_LIBOR_3M, CURVE_ID_FWD, US_CPI_U, CURVE_ID_FWD);
            RatesMarketDataLookup            test      = RatesMarketDataLookup.of(discounts, forwards);
            LocalDate     valDate       = date(2015, 6, 30);
            Curve         dscCurve      = ConstantCurve.of(Curves.discountFactors(CURVE_ID_DSC.CurveName, ACT_360), 1d);
            Curve         fwdCurve      = ConstantCurve.of(Curves.discountFactors(CURVE_ID_FWD.CurveName, ACT_360), 2d);
            MarketData    md            = ImmutableMarketData.of(valDate, ImmutableMap.of(CURVE_ID_DSC, dscCurve, CURVE_ID_FWD, fwdCurve));
            RatesProvider ratesProvider = test.ratesProvider(md);

            assertEquals(ratesProvider.ValuationDate, valDate);
            assertEquals(ratesProvider.findData(CURVE_ID_DSC.CurveName), dscCurve);
            assertEquals(ratesProvider.findData(CURVE_ID_FWD.CurveName), fwdCurve);
            assertEquals(ratesProvider.findData(CurveName.of("Rubbish")), null);
            assertEquals(ratesProvider.IborIndices, ImmutableSet.of(USD_LIBOR_3M));
            assertEquals(ratesProvider.OvernightIndices, ImmutableSet.of(USD_FED_FUND));
            assertEquals(ratesProvider.PriceIndices, ImmutableSet.of(US_CPI_U));
            assertEquals(ratesProvider.TimeSeriesIndices, ImmutableSet.of());
            // check discount factors
            SimpleDiscountFactors df = (SimpleDiscountFactors)ratesProvider.discountFactors(USD);

            assertEquals(df.Curve.Name, dscCurve.Name);
            assertThrowsIllegalArg(() => ratesProvider.discountFactors(GBP));
            // check Ibor
            DiscountIborIndexRates ibor   = (DiscountIborIndexRates)ratesProvider.iborIndexRates(USD_LIBOR_3M);
            SimpleDiscountFactors  iborDf = (SimpleDiscountFactors)ibor.DiscountFactors;

            assertEquals(iborDf.Curve.Name, fwdCurve.Name);
            assertThrowsIllegalArg(() => ratesProvider.iborIndexRates(GBP_LIBOR_3M));
            // check Overnight
            DiscountOvernightIndexRates on   = (DiscountOvernightIndexRates)ratesProvider.overnightIndexRates(USD_FED_FUND);
            SimpleDiscountFactors       onDf = (SimpleDiscountFactors)on.DiscountFactors;

            assertEquals(onDf.Curve.Name, dscCurve.Name);
            assertThrowsIllegalArg(() => ratesProvider.overnightIndexRates(GBP_SONIA));
            // check price curve must be interpolated
            assertThrowsIllegalArg(() => ratesProvider.priceIndexValues(US_CPI_U));
            // to immutable
            ImmutableRatesProvider expectedImmutable = ImmutableRatesProvider.builder(valDate).fxRateProvider(MarketDataFxRateProvider.of(md)).discountCurve(USD, dscCurve).indexCurve(USD_FED_FUND, dscCurve).indexCurve(USD_LIBOR_3M, fwdCurve).indexCurve(US_CPI_U, fwdCurve).build();

            assertEquals(ratesProvider.toImmutableRatesProvider(), expectedImmutable);
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes cross-curve gamma by applying finite difference method to curve delta.
        /// <para>
        /// This computes the cross-curve gamma, i.e., the second order sensitivities to full curves.
        /// Thus the sensitivities of curve delta to other curves are produced.
        /// </para>
        /// <para>
        /// The sensitivities are computed for discount curves, and forward curves for {@code RateIndex} and {@code PriceIndex}.
        /// This implementation works only for single currency trades.
        ///
        /// </para>
        /// </summary>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="sensitivitiesFn">  the sensitivity function </param>
        /// <returns> the cross gamma </returns>
        public CrossGammaParameterSensitivities calculateCrossGammaCrossCurve(RatesProvider ratesProvider, System.Func <ImmutableRatesProvider, CurrencyParameterSensitivities> sensitivitiesFn)
        {
            ImmutableRatesProvider           immProv   = ratesProvider.toImmutableRatesProvider();
            CurrencyParameterSensitivities   baseDelta = sensitivitiesFn(immProv);   // used to check target sensitivity exits.
            CrossGammaParameterSensitivities result    = CrossGammaParameterSensitivities.empty();

            foreach (CurrencyParameterSensitivity baseDeltaSingle in baseDelta.Sensitivities)
            {
                CrossGammaParameterSensitivities resultInner = CrossGammaParameterSensitivities.empty();
                // discount curve
                foreach (KeyValuePair <Currency, Curve> entry in immProv.DiscountCurves.entrySet())
                {
                    Currency currency = entry.Key;
                    Curve    curve    = entry.Value;
                    if (baseDelta.findSensitivity(curve.Name, currency).Present)
                    {
                        CrossGammaParameterSensitivity gammaSingle = computeGammaForCurve(baseDeltaSingle, curve, c => immProv.toBuilder().discountCurve(currency, c).build(), sensitivitiesFn);
                        resultInner = resultInner.combinedWith(gammaSingle);
                    }
                    else if (curve.split().size() > 1)
                    {
                        ImmutableList <Curve> curves = curve.split();
                        int nCurves = curves.size();
                        for (int i = 0; i < nCurves; ++i)
                        {
                            int   currentIndex    = i;
                            Curve underlyingCurve = curves.get(currentIndex);
                            if (baseDelta.findSensitivity(underlyingCurve.Name, currency).Present)
                            {
                                CrossGammaParameterSensitivity gammaSingle = computeGammaForCurve(baseDeltaSingle, underlyingCurve, c => immProv.toBuilder().discountCurve(currency, curve.withUnderlyingCurve(currentIndex, c)).build(), sensitivitiesFn);
                                resultInner = resultInner.combinedWith(gammaSingle);
                            }
                        }
                    }
                }
                // forward curve
                foreach (KeyValuePair <Index, Curve> entry in immProv.IndexCurves.entrySet())
                {
                    Index index = entry.Key;
                    if (index is RateIndex || index is PriceIndex)
                    {
                        Currency currency = getCurrency(index);
                        Curve    curve    = entry.Value;
                        if (baseDelta.findSensitivity(curve.Name, currency).Present)
                        {
                            CrossGammaParameterSensitivity gammaSingle = computeGammaForCurve(baseDeltaSingle, curve, c => immProv.toBuilder().indexCurve(index, c).build(), sensitivitiesFn);
                            resultInner = resultInner.combinedWith(gammaSingle);
                        }
                        else if (curve.split().size() > 1)
                        {
                            ImmutableList <Curve> curves = curve.split();
                            int nCurves = curves.size();
                            for (int i = 0; i < nCurves; ++i)
                            {
                                int   currentIndex    = i;
                                Curve underlyingCurve = curves.get(currentIndex);
                                if (baseDelta.findSensitivity(underlyingCurve.Name, currency).Present)
                                {
                                    CrossGammaParameterSensitivity gammaSingle = computeGammaForCurve(baseDeltaSingle, underlyingCurve, c => immProv.toBuilder().indexCurve(index, curve.withUnderlyingCurve(currentIndex, c)).build(), sensitivitiesFn);
                                    resultInner = resultInner.combinedWith(gammaSingle);
                                }
                            }
                        }
                    }
                }
                result = result.combinedWith(combineSensitivities(baseDeltaSingle, resultInner));
            }
            return(result);
        }
Ejemplo n.º 5
0
        public virtual void test_builtData()
        {
//JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET:
//ORIGINAL LINE: java.util.List<com.opengamma.strata.calc.marketdata.PerturbationMapping<?>> perturbationMapping = new java.util.ArrayList<>();
            IList <PerturbationMapping <object> > perturbationMapping = new List <PerturbationMapping <object> >();
            int nScenarios = 3;

            foreach (KeyValuePair <QuoteId, double> entry in MARKET_QUOTES.entrySet())
            {
                DoubleArray shifts = DoubleArray.of(nScenarios, n => Math.Pow(0.9, n));
                ScenarioPerturbation <double> perturb = GenericDoubleShifts.of(ShiftType.SCALED, shifts);
                perturbationMapping.Add(PerturbationMapping.of(MarketDataFilter.ofId(entry.Key), perturb));
            }
            ScenarioDefinition    scenarioDefinition   = ScenarioDefinition.ofMappings(perturbationMapping);
            ImmutableMarketData   dataWithSurface      = ImmutableMarketData.builder(VALUATION_DATE).addValueMap(MARKET_QUOTES).addValueMap(MARKET_FX_QUOTES).addValue(VOL_ID, EXP_VOLS).addValue(RatesCurveGroupId.of(CURVE_GROUP_NAME), RatesCurveGroup.ofCurves(CURVE_GROUP_DEFINITION, EXP_RATES.toImmutableRatesProvider().DiscountCurves.values())).build();
            ScenarioMarketData    marketDataCalibrated = StandardComponents.marketDataFactory().createMultiScenario(REQUIREMENTS, SCENARIO_CONFIG, dataWithSurface, REF_DATA, scenarioDefinition);
            Results               results  = CALC_RUNNER.calculateMultiScenario(RULES, TARGETS, COLUMN, marketDataCalibrated, REF_DATA);
            CurrencyScenarioArray computed = results.get(0, 0, typeof(CurrencyScenarioArray)).Value;
            CurrencyAmount        expected = PRICER.presentValue(OPTION_TRADE.resolve(REF_DATA), EXP_RATES, EXP_VOLS).convertedTo(USD, EXP_RATES);

            // dependency graph is absent, thus scenarios are not created
            assertTrue(computed.ScenarioCount == 1);
            assertEquals(computed.get(0), expected);
        }