//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @SuppressWarnings("unused") @Test(enabled = false) public void performance() public virtual void performance() { long start, end; int nbRep = 5; int nbTests = 10; for (int looprep = 0; looprep < nbRep; looprep++) { Console.WriteLine("Calibration time"); start = DateTimeHelper.CurrentUnixTimeMillis(); for (int i = 0; i < nbTests; i++) { ImmutableRatesProvider multicurve1 = CALIBRATOR.calibrate(GROUP_DEFINITION_NO_INFO, MARKET_QUOTES, REF_DATA); } end = DateTimeHelper.CurrentUnixTimeMillis(); Console.WriteLine(" |--> calibration only: " + (end - start) + " ms for " + nbTests + " runs."); start = DateTimeHelper.CurrentUnixTimeMillis(); for (int i = 0; i < nbTests; i++) { ImmutableRatesProvider multicurve1 = CALIBRATOR.calibrate(GROUP_DEFINITION, MARKET_QUOTES, REF_DATA); } end = DateTimeHelper.CurrentUnixTimeMillis(); Console.WriteLine(" |--> calibration and Jacobian: " + (end - start) + " ms for " + nbTests + " runs."); start = DateTimeHelper.CurrentUnixTimeMillis(); for (int i = 0; i < nbTests; i++) { ImmutableRatesProvider multicurve1 = CALIBRATOR.calibrate(GROUP_DEFINITION_PV_SENSI, MARKET_QUOTES, REF_DATA); } end = DateTimeHelper.CurrentUnixTimeMillis(); Console.WriteLine(" |--> calibration, Jacobian and PV sensi MQ: " + (end - start) + " ms for " + nbTests + " runs."); } }
/// <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); }
private RatesCurveGroup buildGroup(RatesCurveGroupDefinition groupDefn, RatesCurveCalibrator calibrator, MarketData marketData, ReferenceData refData) { // perform the calibration ImmutableRatesProvider calibratedProvider = calibrator.calibrate(groupDefn, marketData, refData); return(RatesCurveGroup.of(groupDefn.Name, calibratedProvider.DiscountCurves, calibratedProvider.IndexCurves)); }
//------------------------------------------------------------------------- public virtual void test_currencyExposure() { double eps = 1.0e-14; ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE).fxRateProvider(FX_MATRIX).discountCurve(GBP, DISCOUNT_CURVE_GBP).discountCurve(USD, DISCOUNT_CURVE_USD).build(); DiscountingFxResetNotionalExchangePricer test = new DiscountingFxResetNotionalExchangePricer(); // USD MultiCurrencyAmount computedUSD = test.currencyExposure(FX_RESET_NOTIONAL_EXCHANGE_REC_USD, prov); PointSensitivities pointUSD = test.presentValueSensitivity(FX_RESET_NOTIONAL_EXCHANGE_REC_USD, prov).build(); MultiCurrencyAmount expectedUSD = prov.currencyExposure(pointUSD.convertedTo(USD, prov)).plus(CurrencyAmount.of(FX_RESET_NOTIONAL_EXCHANGE_REC_USD.Currency, test.presentValue(FX_RESET_NOTIONAL_EXCHANGE_REC_USD, prov))); assertFalse(computedUSD.contains(GBP)); // 0 GBP assertEquals(computedUSD.getAmount(USD).Amount, expectedUSD.getAmount(USD).Amount, eps * NOTIONAL); // GBP MultiCurrencyAmount computedGBP = test.currencyExposure(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP, prov); PointSensitivities pointGBP = test.presentValueSensitivity(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP, prov).build(); MultiCurrencyAmount expectedGBP = prov.currencyExposure(pointGBP.convertedTo(GBP, prov)).plus(CurrencyAmount.of(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP.Currency, test.presentValue(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP, prov))); assertFalse(computedGBP.contains(USD)); // 0 USD assertEquals(computedGBP.getAmount(GBP).Amount, expectedGBP.getAmount(GBP).Amount, eps * NOTIONAL); // FD approximation FxMatrix fxMatrixUp = FxMatrix.of(GBP, USD, FX_RATE + EPS_FD); ImmutableRatesProvider provUp = ImmutableRatesProvider.builder(VAL_DATE).fxRateProvider(fxMatrixUp).discountCurve(GBP, DISCOUNT_CURVE_GBP).discountCurve(USD, DISCOUNT_CURVE_USD).build(); double expectedFdUSD = -(test.presentValue(FX_RESET_NOTIONAL_EXCHANGE_REC_USD, provUp) - test.presentValue(FX_RESET_NOTIONAL_EXCHANGE_REC_USD, prov)) * FX_RATE * FX_RATE / EPS_FD; assertEquals(computedUSD.getAmount(USD).Amount, expectedFdUSD, EPS_FD * NOTIONAL); double expectedFdGBP = (test.presentValue(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP, provUp) - test.presentValue(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP, prov)) / EPS_FD; assertEquals(computedGBP.getAmount(GBP).Amount, expectedFdGBP, EPS_FD * NOTIONAL); }
public virtual void test_currencyExposureOnFixing_noTimeSeries() { double eps = 1.0e-14; LocalDate valuationDate = date(2014, 6, 27); LocalDate paymentDate = date(2014, 7, 1); LocalDate fixingDate = date(2014, 6, 27); FxResetNotionalExchange resetNotionalUSD = FxResetNotionalExchange.of(CurrencyAmount.of(USD, NOTIONAL), paymentDate, FxIndexObservation.of(GBP_USD_WM, fixingDate, REF_DATA)); FxResetNotionalExchange resetNotionalGBP = FxResetNotionalExchange.of(CurrencyAmount.of(GBP, -NOTIONAL), paymentDate, FxIndexObservation.of(GBP_USD_WM, fixingDate, REF_DATA)); ImmutableRatesProvider prov = ImmutableRatesProvider.builder(valuationDate).fxRateProvider(FX_MATRIX).discountCurve(GBP, DISCOUNT_CURVE_GBP).discountCurve(USD, DISCOUNT_CURVE_USD).build(); DiscountingFxResetNotionalExchangePricer test = new DiscountingFxResetNotionalExchangePricer(); // USD MultiCurrencyAmount computedUSD = test.currencyExposure(resetNotionalUSD, prov); PointSensitivities pointUSD = test.presentValueSensitivity(resetNotionalUSD, prov).build(); MultiCurrencyAmount expectedUSD = prov.currencyExposure(pointUSD.convertedTo(USD, prov)).plus(CurrencyAmount.of(resetNotionalUSD.Currency, test.presentValue(resetNotionalUSD, prov))); assertFalse(computedUSD.contains(GBP)); // 0 GBP assertEquals(computedUSD.getAmount(USD).Amount, expectedUSD.getAmount(USD).Amount, eps * NOTIONAL); // GBP MultiCurrencyAmount computedGBP = test.currencyExposure(resetNotionalGBP, prov); PointSensitivities pointGBP = test.presentValueSensitivity(resetNotionalGBP, prov).build(); MultiCurrencyAmount expectedGBP = prov.currencyExposure(pointGBP.convertedTo(GBP, prov)).plus(CurrencyAmount.of(resetNotionalGBP.Currency, test.presentValue(resetNotionalGBP, prov))); assertFalse(computedGBP.contains(USD)); // 0 USD assertEquals(computedGBP.getAmount(GBP).Amount, expectedGBP.getAmount(GBP).Amount, eps * NOTIONAL); // FD approximation FxMatrix fxMatrixUp = FxMatrix.of(GBP, USD, FX_RATE + EPS_FD); ImmutableRatesProvider provUp = ImmutableRatesProvider.builder(valuationDate).fxRateProvider(fxMatrixUp).discountCurve(GBP, DISCOUNT_CURVE_GBP).discountCurve(USD, DISCOUNT_CURVE_USD).build(); double expectedFdUSD = -(test.presentValue(resetNotionalUSD, provUp) - test.presentValue(resetNotionalUSD, prov)) * FX_RATE * FX_RATE / EPS_FD; assertEquals(computedUSD.getAmount(USD).Amount, expectedFdUSD, EPS_FD * NOTIONAL); double expectedFdGBP = (test.presentValue(resetNotionalGBP, provUp) - test.presentValue(resetNotionalGBP, prov)) / EPS_FD; assertEquals(computedGBP.getAmount(GBP).Amount, expectedFdGBP, EPS_FD * NOTIONAL); }
public virtual void test_currentCash_zero() { ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE).fxRateProvider(FX_MATRIX).discountCurve(GBP, DISCOUNT_CURVE_GBP).discountCurve(USD, DISCOUNT_CURVE_USD).build(); DiscountingFxResetNotionalExchangePricer test = new DiscountingFxResetNotionalExchangePricer(); double cc = test.currentCash(FX_RESET_NOTIONAL_EXCHANGE_REC_USD, prov); assertEquals(cc, 0d); }
public virtual void test_currentCash_zero() { ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE).discountCurve(GBP, DISCOUNT_CURVE_GBP).build(); DiscountingNotionalExchangePricer test = DiscountingNotionalExchangePricer.DEFAULT; double computed = test.currentCash(NOTIONAL_EXCHANGE_REC_GBP, prov); assertEquals(computed, 0d); }
//------------------------------------------------------------------------- public override DoubleArray apply(DoubleArray x) { // create child provider from matrix ImmutableRatesProvider childProvider = providerGenerator.generate(x); // calculate value for each trade using the child provider return(DoubleArray.of(trades.Count, i => measures.value(trades[i], childProvider))); }
/// <summary> /// Creates an instance. /// </summary> /// <param name="knownProvider"> the underlying known provider </param> /// <param name="curveDefinitions"> the curve definitions </param> /// <param name="curveMetadata"> the curve metadata </param> /// <param name="discountCurveNames"> the map of discount curves </param> /// <param name="forwardCurveNames"> the map of index forward curves </param> private ImmutableRatesProviderGenerator(ImmutableRatesProvider knownProvider, IList <CurveDefinition> curveDefinitions, IList <CurveMetadata> curveMetadata, SetMultimap <CurveName, Currency> discountCurveNames, SetMultimap <CurveName, Index> forwardCurveNames) { this.knownProvider = ArgChecker.notNull(knownProvider, "knownProvider"); this.curveDefinitions = ImmutableList.copyOf(ArgChecker.notNull(curveDefinitions, "curveDefinitions")); this.curveMetadata = ImmutableList.copyOf(ArgChecker.notNull(curveMetadata, "curveMetadata")); this.discountCurveNames = ImmutableSetMultimap.copyOf(ArgChecker.notNull(discountCurveNames, "discountCurveNames")); this.forwardCurveNames = ImmutableSetMultimap.copyOf(ArgChecker.notNull(forwardCurveNames, "forwardCurveNames")); }
//------------------------------------------------------------------------- /// <summary> /// Calibrates a single curve group, containing one or more curves. /// <para> /// The calibration is defined using <seealso cref="RatesCurveGroupDefinition"/>. /// Observable market data, time-series and FX are also needed to complete the calibration. /// The valuation date is defined by the market data. /// </para> /// <para> /// The Jacobian matrices are computed and stored in curve metadata. /// /// </para> /// </summary> /// <param name="curveGroupDefn"> the curve group definition </param> /// <param name="marketData"> the market data required to build a trade for the instrument, including time-series </param> /// <param name="refData"> the reference data, used to resolve the trades </param> /// <returns> the rates provider resulting from the calibration </returns> public ImmutableRatesProvider calibrate(RatesCurveGroupDefinition curveGroupDefn, MarketData marketData, ReferenceData refData) { //JAVA TO C# CONVERTER TODO TASK: Most Java stream collectors are not converted by Java to C# Converter: IDictionary <Index, LocalDateDoubleTimeSeries> timeSeries = marketData.TimeSeriesIds.Where(typeof(IndexQuoteId).isInstance).Select(typeof(IndexQuoteId).cast).collect(toImmutableMap(id => id.Index, id => marketData.getTimeSeries(id))); ImmutableRatesProvider knownData = ImmutableRatesProvider.builder(marketData.ValuationDate).fxRateProvider(MarketDataFxRateProvider.of(marketData)).timeSeries(timeSeries).build(); return(calibrate(ImmutableList.of(curveGroupDefn), knownData, marketData, refData)); }
//------------------------------------------------------------------------- // 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_currentCash_onPayment() { ImmutableRatesProvider prov = ImmutableRatesProvider.builder(NOTIONAL_EXCHANGE_REC_GBP.PaymentDate).discountCurve(GBP, DISCOUNT_CURVE_GBP).build(); DiscountingNotionalExchangePricer test = DiscountingNotionalExchangePricer.DEFAULT; double notional = NOTIONAL_EXCHANGE_REC_GBP.PaymentAmount.Amount; double computed = test.currentCash(NOTIONAL_EXCHANGE_REC_GBP, prov); assertEquals(computed, notional); }
//------------------------------------------------------------------------- public override DoubleMatrix apply(DoubleArray x) { // create child provider from matrix ImmutableRatesProvider provider = providerGenerator.generate(x); // calculate derivative for each trade using the child provider int size = trades.Count; return(DoubleMatrix.ofArrayObjects(size, size, i => measures.derivative(trades[i], provider, curveOrder))); }
//------------------------------------------------------------------------- public virtual void test_currencyExposure() { ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE).discountCurve(GBP, DISCOUNT_CURVE_GBP).build(); DiscountingNotionalExchangePricer test = DiscountingNotionalExchangePricer.DEFAULT; MultiCurrencyAmount computed = test.currencyExposure(NOTIONAL_EXCHANGE_REC_GBP, prov); PointSensitivities point = test.presentValueSensitivity(NOTIONAL_EXCHANGE_REC_GBP, prov).build(); MultiCurrencyAmount expected = prov.currencyExposure(point).plus(CurrencyAmount.of(NOTIONAL_EXCHANGE_REC_GBP.Currency, test.presentValue(NOTIONAL_EXCHANGE_REC_GBP, prov))); assertEquals(computed, expected); }
static DiscountingFraProductPricerTest() { CurveInterpolator interp = CurveInterpolators.DOUBLE_QUADRATIC; DoubleArray time_gbp = DoubleArray.of(0.0, 0.1, 0.25, 0.5, 0.75, 1.0, 2.0); DoubleArray rate_gbp = DoubleArray.of(0.0160, 0.0165, 0.0155, 0.0155, 0.0155, 0.0150, 0.014); InterpolatedNodalCurve dscCurve = InterpolatedNodalCurve.of(Curves.zeroRates("GBP-Discount", DAY_COUNT), time_gbp, rate_gbp, interp); DoubleArray time_index = DoubleArray.of(0.0, 0.25, 0.5, 1.0); DoubleArray rate_index = DoubleArray.of(0.0180, 0.0180, 0.0175, 0.0165); InterpolatedNodalCurve indexCurve = InterpolatedNodalCurve.of(Curves.zeroRates("GBP-GBPIBOR3M", DAY_COUNT), time_index, rate_index, interp); IMM_PROV = ImmutableRatesProvider.builder(VAL_DATE).discountCurve(GBP, dscCurve).iborIndexCurve(GBP_LIBOR_3M, indexCurve).build(); }
public virtual void test_presentValueSensitivity_dfCurve_FD() { double eps = 1.0e-6; ImmutableRatesProvider prov = RatesProviderDataSets.MULTI_GBP_USD_SIMPLE; RatesFiniteDifferenceSensitivityCalculator cal = new RatesFiniteDifferenceSensitivityCalculator(eps); DiscountingFraProductPricer pricer = DiscountingFraProductPricer.DEFAULT; ResolvedFra fraExp = RFRA; PointSensitivities point = pricer.presentValueSensitivity(fraExp, prov); CurrencyParameterSensitivities computed = prov.parameterSensitivity(point); CurrencyParameterSensitivities expected = cal.sensitivity(prov, p => pricer.presentValue(fraExp, p)); assertTrue(computed.equalWithTolerance(expected, eps * FRA.Notional)); }
public virtual void test_currentCash_onPayment() { double eps = 1.0e-14; ImmutableRatesProvider prov = ImmutableRatesProvider.builder(FX_RESET_NOTIONAL_EXCHANGE_REC_USD.PaymentDate).fxRateProvider(FX_MATRIX).discountCurve(GBP, DISCOUNT_CURVE_GBP).discountCurve(USD, DISCOUNT_CURVE_USD).build(); DiscountingFxResetNotionalExchangePricer test = new DiscountingFxResetNotionalExchangePricer(); double rate = prov.fxIndexRates(FX_RESET_NOTIONAL_EXCHANGE_REC_USD.Observation.Index).rate(FX_RESET_NOTIONAL_EXCHANGE_REC_USD.Observation, FX_RESET_NOTIONAL_EXCHANGE_REC_USD.ReferenceCurrency); double ccUSD = test.currentCash(FX_RESET_NOTIONAL_EXCHANGE_REC_USD, prov); assertEquals(ccUSD, NOTIONAL * rate, eps); double ccGBP = test.currentCash(FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP, prov); assertEquals(ccGBP, -NOTIONAL / rate, eps); }
/// <summary> /// Calibrates a list of curve groups, each containing one or more curves. /// <para> /// The calibration is defined using a list of <seealso cref="RatesCurveGroupDefinition"/>. /// Observable market data and existing known data are also needed to complete the calibration. /// </para> /// <para> /// A curve must only exist in one group. /// /// </para> /// </summary> /// <param name="allGroupsDefn"> the curve group definitions </param> /// <param name="knownData"> the starting data for the calibration </param> /// <param name="marketData"> the market data required to build a trade for the instrument </param> /// <param name="refData"> the reference data, used to resolve the trades </param> /// <returns> the rates provider resulting from the calibration </returns> public ImmutableRatesProvider calibrate(IList <RatesCurveGroupDefinition> allGroupsDefn, ImmutableRatesProvider knownData, MarketData marketData, ReferenceData refData) { // this method effectively takes one CurveGroupDefinition // the list is a split of the definition, not multiple independent definitions if (!knownData.ValuationDate.Equals(marketData.ValuationDate)) { throw new System.ArgumentException(Messages.format("Valuation dates do not match: {} and {}", knownData.ValuationDate, marketData.ValuationDate)); } // perform calibration one group at a time, building up the result by mutating these variables ImmutableRatesProvider providerCombined = knownData; ImmutableList <CurveParameterSize> orderPrev = ImmutableList.of(); ImmutableMap <CurveName, JacobianCalibrationMatrix> jacobians = ImmutableMap.of(); foreach (RatesCurveGroupDefinition groupDefn in allGroupsDefn) { if (groupDefn.Entries.Empty) { continue; } RatesCurveGroupDefinition groupDefnBound = groupDefn.bindTimeSeries(knownData.ValuationDate, knownData.TimeSeries); // combine all data in the group into flat lists ImmutableList <ResolvedTrade> trades = groupDefnBound.resolvedTrades(marketData, refData); ImmutableList <double> initialGuesses = groupDefnBound.initialGuesses(marketData); ImmutableList <CurveParameterSize> orderGroup = toOrder(groupDefnBound); ImmutableList <CurveParameterSize> orderPrevAndGroup = ImmutableList.builder <CurveParameterSize>().addAll(orderPrev).addAll(orderGroup).build(); // calibrate RatesProviderGenerator providerGenerator = ImmutableRatesProviderGenerator.of(providerCombined, groupDefnBound, refData); DoubleArray calibratedGroupParams = calibrateGroup(providerGenerator, trades, initialGuesses, orderGroup); ImmutableRatesProvider calibratedProvider = providerGenerator.generate(calibratedGroupParams); // use calibration to build Jacobian matrices if (groupDefnBound.ComputeJacobian) { jacobians = updateJacobiansForGroup(calibratedProvider, trades, orderGroup, orderPrev, orderPrevAndGroup, jacobians); } ImmutableMap <CurveName, DoubleArray> sensitivityToMarketQuote = ImmutableMap.of(); if (groupDefnBound.ComputePvSensitivityToMarketQuote) { ImmutableRatesProvider providerWithJacobian = providerGenerator.generate(calibratedGroupParams, jacobians); sensitivityToMarketQuote = sensitivityToMarketQuoteForGroup(providerWithJacobian, trades, orderGroup); } orderPrev = orderPrevAndGroup; // use Jacobians to build output curves providerCombined = providerGenerator.generate(calibratedGroupParams, jacobians, sensitivityToMarketQuote); } // return the calibrated provider return(providerCombined); }
// computes the sensitivity of baseDeltaSingle to Curve internal CrossGammaParameterSensitivity computeGammaForCurve(CurrencyParameterSensitivity baseDeltaSingle, Curve curve, System.Func <Curve, ImmutableRatesProvider> ratesProviderFn, System.Func <ImmutableRatesProvider, CurrencyParameterSensitivities> sensitivitiesFn) { System.Func <DoubleArray, DoubleArray> function = (DoubleArray t) => { Curve newCurve = replaceParameters(curve, t); ImmutableRatesProvider newRates = ratesProviderFn(newCurve); CurrencyParameterSensitivities sensiMulti = sensitivitiesFn(newRates); return(sensiMulti.getSensitivity(baseDeltaSingle.MarketDataName, baseDeltaSingle.Currency).Sensitivity); }; int nParams = curve.ParameterCount; DoubleMatrix sensi = fd.differentiate(function).apply(DoubleArray.of(nParams, n => curve.getParameter(n))); IList <ParameterMetadata> metadata = IntStream.range(0, nParams).mapToObj(i => curve.getParameterMetadata(i)).collect(toImmutableList()); return(CrossGammaParameterSensitivity.of(baseDeltaSingle.MarketDataName, baseDeltaSingle.ParameterMetadata, curve.Name, metadata, baseDeltaSingle.Currency, sensi)); }
static CurveSensitivityUtilsJacobianTest() { Tenor[] tenors = new Tenor[] { Tenor.TENOR_1D, Tenor.TENOR_1M, Tenor.TENOR_3M, Tenor.TENOR_6M, Tenor.TENOR_1Y, Tenor.TENOR_2Y, Tenor.TENOR_3Y, Tenor.TENOR_4Y, Tenor.TENOR_5Y, Tenor.TENOR_7Y, Tenor.TENOR_10Y, Tenor.TENOR_15Y, Tenor.TENOR_20Y, Tenor.TENOR_30Y }; IList <TenorParameterMetadata> metadataList = new List <TenorParameterMetadata>(); for (int looptenor = 0; looptenor < tenors.Length; looptenor++) { metadataList.Add(TenorParameterMetadata.of(tenors[looptenor])); } DoubleArray rate_eur = DoubleArray.of(0.0160, 0.0165, 0.0155, 0.0155, 0.0155, 0.0150, 0.0150, 0.0160, 0.0165, 0.0155, 0.0155, 0.0155, 0.0150, 0.0140); InterpolatedNodalCurve curve_single_eur = InterpolatedNodalCurve.builder().metadata(DefaultCurveMetadata.builder().curveName(EUR_SINGLE_NAME).parameterMetadata(metadataList).dayCount(ACT_365F).xValueType(ValueType.YEAR_FRACTION).yValueType(ValueType.ZERO_RATE).build()).xValues(TIME_EUR).yValues(rate_eur).extrapolatorLeft(CurveExtrapolators.FLAT).extrapolatorRight(CurveExtrapolators.FLAT).interpolator(CurveInterpolators.LINEAR).build(); MULTICURVE_EUR_SINGLE_INPUT = ImmutableRatesProvider.builder(VALUATION_DATE).discountCurve(EUR, curve_single_eur).iborIndexCurve(EUR_EURIBOR_6M, curve_single_eur).build(); LIST_CURVE_NAMES_1.Add(CurveParameterSize.of(EUR_SINGLE_NAME, TIME_EUR.size())); }
public virtual void check_equivalent_notional() { ImmutableRatesProvider multicurve = CALIBRATOR.calibrate(GROUP_DEFINITION_PV_SENSI, MARKET_QUOTES, REF_DATA); // Create notional equivalent for a basis trade ResolvedSwapTrade trade = ThreeLegBasisSwapConventions.EUR_FIXED_1Y_EURIBOR_3M_EURIBOR_6M.createTrade(VALUATION_DATE, Period.ofMonths(7), Tenor.TENOR_6Y, BuySell.SELL, 1_000_000, 0.03, REF_DATA).resolve(REF_DATA); PointSensitivities pts = PRICER_SWAP_TRADE.presentValueSensitivity(trade, multicurve); CurrencyParameterSensitivities ps = multicurve.parameterSensitivity(pts); CurrencyParameterSensitivities mqs = MQSC.sensitivity(ps, multicurve); CurrencyParameterSensitivities notionalEquivalent = NEC.notionalEquivalent(mqs, multicurve); // Check metadata are same as market quote sensitivities. foreach (CurrencyParameterSensitivity sensi in mqs.Sensitivities) { assertEquals(notionalEquivalent.getSensitivity(sensi.MarketDataName, sensi.Currency).ParameterMetadata, sensi.ParameterMetadata); } // Check sensitivity: trade sensitivity = sum(notional equivalent sensitivities) int totalNbParameters = 0; IDictionary <CurveName, IList <ResolvedTrade> > equivalentTrades = new Dictionary <CurveName, IList <ResolvedTrade> >(); ImmutableList <CurveDefinition> curveGroups = GROUP_DEFINITION.CurveDefinitions; ImmutableList.Builder <CurveParameterSize> builder = ImmutableList.builder(); foreach (CurveDefinition entry in curveGroups) { totalNbParameters += entry.ParameterCount; DoubleArray notionalCurve = notionalEquivalent.getSensitivity(entry.Name, Currency.EUR).Sensitivity; ImmutableList <CurveNode> nodes = entry.Nodes; IList <ResolvedTrade> resolvedTradesCurve = new List <ResolvedTrade>(); for (int i = 0; i < nodes.size(); i++) { resolvedTradesCurve.Add(nodes.get(i).resolvedTrade(notionalCurve.get(i), MARKET_QUOTES, REF_DATA)); } equivalentTrades[entry.Name] = resolvedTradesCurve; builder.add(entry.toCurveParameterSize()); } ImmutableList <CurveParameterSize> order = builder.build(); // order of the curves DoubleArray totalSensitivity = DoubleArray.filled(totalNbParameters); foreach (KeyValuePair <CurveName, IList <ResolvedTrade> > entry in equivalentTrades.SetOfKeyValuePairs()) { foreach (ResolvedTrade t in entry.Value) { totalSensitivity = totalSensitivity.plus(PV_MEASURES.derivative(t, multicurve, order)); } } DoubleArray instrumentSensi = PV_MEASURES.derivative(trade, multicurve, order); assertTrue(totalSensitivity.equalWithTolerance(instrumentSensi, TOLERANCE_PV_DELTA)); }
private double sumMod(ImmutableRatesProvider provider) { double result = 0.0; // Index ImmutableMap <Index, Curve> mapIndex = provider.IndexCurves; foreach (KeyValuePair <Index, Curve> entry in mapIndex.entrySet()) { if (entry.Key is IborIndex) { InterpolatedNodalCurve curveInt = checkInterpolated(entry.Value); result += sumSingle(curveInt); } } return(result); }
//------------------------------------------------------------------------- public virtual void test_forecastValueSensitivity() { ImmutableRatesProvider prov = ImmutableRatesProvider.builder(VAL_DATE).fxRateProvider(FX_MATRIX).discountCurve(GBP, DISCOUNT_CURVE_GBP).discountCurve(USD, DISCOUNT_CURVE_USD).build(); FxResetNotionalExchange[] expanded = new FxResetNotionalExchange[] { FX_RESET_NOTIONAL_EXCHANGE_REC_USD, FX_RESET_NOTIONAL_EXCHANGE_PAY_GBP }; for (int i = 0; i < 2; ++i) { FxResetNotionalExchange fxReset = expanded[i]; DiscountingFxResetNotionalExchangePricer test = new DiscountingFxResetNotionalExchangePricer(); PointSensitivityBuilder pointSensitivityComputed = test.forecastValueSensitivity(expanded[i], prov); CurrencyParameterSensitivities parameterSensitivityComputed = prov.parameterSensitivity(pointSensitivityComputed.build()); CurrencyParameterSensitivities parameterSensitivityExpected = FD_CALCULATOR.sensitivity(prov, (p) => CurrencyAmount.of(fxReset.Currency, test.forecastValue(fxReset, (p)))); assertTrue(parameterSensitivityComputed.equalWithTolerance(parameterSensitivityExpected, Math.Abs(expanded[i].Notional) * EPS_FD * 10.0)); } }
public virtual void check_pv_sensitivity() { ImmutableRatesProvider multicurve = CALIBRATOR.calibrate(GROUP_DEFINITION_PV_SENSI, MARKET_QUOTES, REF_DATA); // the trades used for calibration IDictionary <CurveName, IList <Trade> > trades = new Dictionary <CurveName, IList <Trade> >(); IDictionary <CurveName, IList <ResolvedTrade> > resolvedTrades = new Dictionary <CurveName, IList <ResolvedTrade> >(); ImmutableList <CurveDefinition> curveGroups = GROUP_DEFINITION.CurveDefinitions; ImmutableList.Builder <CurveParameterSize> builder = ImmutableList.builder(); foreach (CurveDefinition entry in curveGroups) { ImmutableList <CurveNode> nodes = entry.Nodes; IList <Trade> tradesCurve = new List <Trade>(); IList <ResolvedTrade> resolvedTradesCurve = new List <ResolvedTrade>(); foreach (CurveNode node in nodes) { tradesCurve.Add(node.trade(1d, MARKET_QUOTES, REF_DATA)); resolvedTradesCurve.Add(node.resolvedTrade(1d, MARKET_QUOTES, REF_DATA)); } trades[entry.Name] = tradesCurve; resolvedTrades[entry.Name] = resolvedTradesCurve; builder.add(entry.toCurveParameterSize()); } ImmutableList <CurveParameterSize> order = builder.build(); // order of the curves // Check CurveInfo present and sensitivity as expected IDictionary <CurveName, DoubleArray> mqsGroup = new Dictionary <CurveName, DoubleArray>(); int nodeIndex = 0; foreach (CurveParameterSize cps in order) { int nbParameters = cps.ParameterCount; double[] mqsCurve = new double[nbParameters]; for (int looptrade = 0; looptrade < nbParameters; looptrade++) { DoubleArray mqsNode = PV_MEASURES.derivative(resolvedTrades[cps.Name][looptrade], multicurve, order); mqsCurve[looptrade] = mqsNode.get(nodeIndex); nodeIndex++; } Optional <Curve> curve = multicurve.findData(cps.Name); DoubleArray pvSensitivityExpected = DoubleArray.ofUnsafe(mqsCurve); mqsGroup[cps.Name] = pvSensitivityExpected; assertTrue(curve.Present); assertTrue(curve.get().Metadata.findInfo(CurveInfoType.PV_SENSITIVITY_TO_MARKET_QUOTE).Present); DoubleArray pvSensitivityMetadata = curve.get().Metadata.findInfo(CurveInfoType.PV_SENSITIVITY_TO_MARKET_QUOTE).get(); assertTrue(pvSensitivityExpected.equalWithTolerance(pvSensitivityMetadata, 1.0E-10)); } }
// modified sensitivity function - sensitivities are computed only for ibor index curves private CurrencyParameterSensitivities sensiModFn(ImmutableRatesProvider provider) { CurrencyParameterSensitivities sensi = CurrencyParameterSensitivities.empty(); // Index ImmutableMap <Index, Curve> mapIndex = provider.IndexCurves; foreach (KeyValuePair <Index, Curve> entry in mapIndex.entrySet()) { if (entry.Key is IborIndex) { InterpolatedNodalCurve curveInt = checkInterpolated(entry.Value); double sumSqrt = sumMod(provider); sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(curveInt.Name, USD, DoubleArray.of(curveInt.ParameterCount, i => 2d * sumSqrt * curveInt.XValues.get(i)))); } } return(sensi); }
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); }
// computes the sensitivity with respect to the curves private CurrencyParameterSensitivities sensitivity <T>(ImmutableRatesProvider provider, IDictionary <T, Curve> baseCurves, System.Func <ImmutableRatesProvider, IDictionary <T, Curve>, ImmutableRatesProvider> storeBumpedFn, System.Func <ImmutableRatesProvider, CurrencyAmount> valueFn, CurrencyAmount valueInit) { CurrencyParameterSensitivities result = CurrencyParameterSensitivities.empty(); foreach (KeyValuePair <T, Curve> entry in baseCurves.SetOfKeyValuePairs()) { Curve curve = entry.Value; DoubleArray sensitivity = DoubleArray.of(curve.ParameterCount, i => { Curve dscBumped = curve.withParameter(i, curve.getParameter(i) + shift); IDictionary <T, Curve> mapBumped = new Dictionary <T, Curve>(baseCurves); mapBumped[entry.Key] = dscBumped; ImmutableRatesProvider providerDscBumped = storeBumpedFn(provider, mapBumped); return((valueFn(providerDscBumped).Amount - valueInit.Amount) / shift); }); result = result.combinedWith(curve.createParameterSensitivity(valueInit.Currency, sensitivity)); } return(result); }
/// <summary> /// Test parameter sensitivity with finite difference sensitivity calculator. No cutoff period. </summary> public virtual void rateChfNoCutOffParameterSensitivity() { LocalDate[] valuationDate = new LocalDate[] { date(2015, 1, 1), date(2015, 1, 8) }; DoubleArray time = DoubleArray.of(0.0, 0.5, 1.0, 2.0, 5.0, 10.0); DoubleArray rate = DoubleArray.of(0.0100, 0.0110, 0.0115, 0.0130, 0.0135, 0.0135); for (int loopvaldate = 0; loopvaldate < 2; loopvaldate++) { Curve onCurve = InterpolatedNodalCurve.of(Curves.zeroRates("ON", ACT_ACT_ISDA), time, rate, INTERPOLATOR); ImmutableRatesProvider prov = ImmutableRatesProvider.builder(valuationDate[loopvaldate]).overnightIndexCurve(CHF_TOIS, onCurve, TIME_SERIES).build(); OvernightAveragedRateComputation ro = OvernightAveragedRateComputation.of(CHF_TOIS, START_DATE, END_DATE, 0, REF_DATA); ForwardOvernightAveragedRateComputationFn obsFn = ForwardOvernightAveragedRateComputationFn.DEFAULT; PointSensitivityBuilder sensitivityBuilderComputed = obsFn.rateSensitivity(ro, DUMMY_ACCRUAL_START_DATE, DUMMY_ACCRUAL_END_DATE, prov); CurrencyParameterSensitivities parameterSensitivityComputed = prov.parameterSensitivity(sensitivityBuilderComputed.build()); CurrencyParameterSensitivities parameterSensitivityExpected = CAL_FD.sensitivity(prov, (p) => CurrencyAmount.of(CHF_TOIS.Currency, obsFn.rate(ro, DUMMY_ACCRUAL_START_DATE, DUMMY_ACCRUAL_END_DATE, (p)))); assertTrue(parameterSensitivityComputed.equalWithTolerance(parameterSensitivityExpected, EPS_FD * 10.0)); } }
private static Pair <MultiCurrencyAmount[], CurrencyParameterSensitivities[]> computation(IDictionary <CurveGroupName, RatesCurveGroupDefinition> configs, ResolvedSwapTrade[] swaps) { int nbSwaps = swaps.Length; /* Calibrate curves */ ImmutableRatesProvider multicurve = CALIBRATOR.calibrate(configs[CONFIG_NAME], MARKET_QUOTES, REF_DATA); /* Computes PV and bucketed PV01 */ MultiCurrencyAmount[] pv = new MultiCurrencyAmount[nbSwaps]; CurrencyParameterSensitivities[] mqs = new CurrencyParameterSensitivities[nbSwaps]; for (int loopswap = 0; loopswap < nbSwaps; loopswap++) { pv[loopswap] = PRICER_SWAP.presentValue(swaps[loopswap], multicurve); PointSensitivities pts = PRICER_SWAP.presentValueSensitivity(swaps[loopswap], multicurve); CurrencyParameterSensitivities ps = multicurve.parameterSensitivity(pts); mqs[loopswap] = MQC.sensitivity(ps, multicurve); } return(Pair.of(pv, mqs)); }
/// <summary> /// Obtains a generator from an existing provider and definition. /// </summary> /// <param name="knownProvider"> the underlying known provider </param> /// <param name="groupDefn"> the curve group definition </param> /// <param name="refData"> the reference data to use </param> /// <returns> the generator </returns> public static ImmutableRatesProviderGenerator of(ImmutableRatesProvider knownProvider, RatesCurveGroupDefinition groupDefn, ReferenceData refData) { IList <CurveDefinition> curveDefns = new List <CurveDefinition>(); IList <CurveMetadata> curveMetadata = new List <CurveMetadata>(); SetMultimap <CurveName, Currency> discountNames = HashMultimap.create(); SetMultimap <CurveName, Index> indexNames = HashMultimap.create(); foreach (CurveDefinition curveDefn in groupDefn.CurveDefinitions) { curveDefns.Add(curveDefn); curveMetadata.Add(curveDefn.metadata(knownProvider.ValuationDate, refData)); CurveName curveName = curveDefn.Name; // A curve group is guaranteed to include an entry for every definition RatesCurveGroupEntry entry = groupDefn.findEntry(curveName).get(); ISet <Currency> ccy = entry.DiscountCurrencies; discountNames.putAll(curveName, ccy); indexNames.putAll(curveName, entry.Indices); } return(new ImmutableRatesProviderGenerator(knownProvider, curveDefns, curveMetadata, discountNames, indexNames)); }