public virtual void test_zeroRatePointSensitivity() { RepoCurveDiscountFactors @base = RepoCurveDiscountFactors.of(DSC_FACTORS, GROUP); RepoCurveZeroRateSensitivity expected = RepoCurveZeroRateSensitivity.of(DSC_FACTORS.zeroRatePointSensitivity(DATE_AFTER), GROUP); RepoCurveZeroRateSensitivity computed = @base.zeroRatePointSensitivity(DATE_AFTER); assertEquals(computed, expected); }
/// <summary> /// Calculates the par spread curve sensitivity. /// <para> /// The calculation is based on both of initial and final payments. /// Thus the number resulting may not be meaningful when deposit has already started and only the final /// payment remains (no initial payment). /// /// </para> /// </summary> /// <param name="deposit"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the par spread curve sensitivity </returns> public virtual PointSensitivities parSpreadSensitivity(ResolvedTermDeposit deposit, RatesProvider provider) { Currency currency = deposit.Currency; double accrualFactorInv = 1d / deposit.YearFraction; double dfStart = provider.discountFactor(currency, deposit.StartDate); double dfEndInv = 1d / provider.discountFactor(currency, deposit.EndDate); DiscountFactors discountFactors = provider.discountFactors(currency); PointSensitivityBuilder sensStart = discountFactors.zeroRatePointSensitivity(deposit.StartDate).multipliedBy(dfEndInv * accrualFactorInv); PointSensitivityBuilder sensEnd = discountFactors.zeroRatePointSensitivity(deposit.EndDate).multipliedBy(-dfStart * dfEndInv * dfEndInv * accrualFactorInv); return(sensStart.combinedWith(sensEnd).build()); }
/// <summary> /// Calculates the present value sensitivity by discounting the final cash flow (nominal + interest) /// and the initial payment (initial amount). /// </summary> /// <param name="deposit"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the point sensitivity of the present value </returns> public virtual PointSensitivities presentValueSensitivity(ResolvedTermDeposit deposit, RatesProvider provider) { Currency currency = deposit.Currency; // backward sweep double dfEndBar = deposit.Notional + deposit.Interest; double dfStartBar = -initialAmount(deposit, provider); // sensitivity DiscountFactors discountFactors = provider.discountFactors(currency); PointSensitivityBuilder sensStart = discountFactors.zeroRatePointSensitivity(deposit.StartDate).multipliedBy(dfStartBar); PointSensitivityBuilder sensEnd = discountFactors.zeroRatePointSensitivity(deposit.EndDate).multipliedBy(dfEndBar); return(sensStart.combinedWith(sensEnd).build()); }
public virtual PointSensitivityBuilder pvbpSensitivity(RatePaymentPeriod paymentPeriod, RatesProvider provider) { ArgChecker.isTrue(!paymentPeriod.FxReset.Present, "FX reset is not supported"); int accPeriodCount = paymentPeriod.AccrualPeriods.size(); ArgChecker.isTrue(accPeriodCount == 1 || paymentPeriod.CompoundingMethod.Equals(CompoundingMethod.FLAT), "Only one accrued period or Flat compounding supported"); // no compounding if (accPeriodCount == 1) { RateAccrualPeriod accrualPeriod = paymentPeriod.AccrualPeriods.get(0); DiscountFactors discountFactors = provider.discountFactors(paymentPeriod.Currency); return(discountFactors.zeroRatePointSensitivity(paymentPeriod.PaymentDate).multipliedBy(accrualPeriod.YearFraction * paymentPeriod.Notional)); } else { // Flat compounding switch (paymentPeriod.CompoundingMethod) { case FLAT: return(pvbpSensitivtyCompoundedFlat(paymentPeriod, provider)); default: throw new System.NotSupportedException("PVBP not implemented yet for non FLAT compounding"); } } }
/// <summary> /// Test present value sensitivity for AFMA FRA discounting method. /// </summary> public virtual void test_presentValueSensitivity_AFMA() { RateComputationFn<RateComputation> mockObs = mock(typeof(RateComputationFn)); DiscountFactors mockDf = mock(typeof(DiscountFactors)); SimpleRatesProvider simpleProv = new SimpleRatesProvider(VAL_DATE, mockDf); ResolvedFra fraExp = RFRA_AFMA; double forwardRate = 0.05; double discountRate = 0.025; double paymentTime = 0.3; double discountFactor = Math.Exp(-discountRate * paymentTime); LocalDate fixingDate = FRA_AFMA.StartDate; IborIndexObservation obs = IborIndexObservation.of(FRA.Index, fixingDate, REF_DATA); PointSensitivityBuilder sens = IborRateSensitivity.of(obs, 1d); when(mockDf.discountFactor(fraExp.PaymentDate)).thenReturn(discountFactor); when(mockDf.zeroRatePointSensitivity(fraExp.PaymentDate)).thenReturn(ZeroRateSensitivity.of(fraExp.Currency, paymentTime, -discountFactor * paymentTime)); when(mockObs.rateSensitivity(fraExp.FloatingRate, fraExp.StartDate, fraExp.EndDate, simpleProv)).thenReturn(sens); when(mockObs.rate(fraExp.FloatingRate, FRA_AFMA.StartDate, FRA_AFMA.EndDate, simpleProv)).thenReturn(forwardRate); DiscountingFraProductPricer test = new DiscountingFraProductPricer(mockObs); PointSensitivities sensitivity = test.presentValueSensitivity(fraExp, simpleProv); double eps = 1.e-7; double fdDscSense = dscSensitivity(RFRA_AFMA, forwardRate, discountFactor, paymentTime, eps); double fdSense = presentValueFwdSensitivity(RFRA_AFMA, forwardRate, discountFactor, eps); ImmutableList<PointSensitivity> sensitivities = sensitivity.Sensitivities; assertEquals(sensitivities.size(), 2); IborRateSensitivity sensitivity0 = (IborRateSensitivity) sensitivities.get(0); assertEquals(sensitivity0.Index, FRA_AFMA.Index); assertEquals(sensitivity0.Observation.FixingDate, fixingDate); assertEquals(sensitivity0.Sensitivity, fdSense, FRA_AFMA.Notional * eps); ZeroRateSensitivity sensitivity1 = (ZeroRateSensitivity) sensitivities.get(1); assertEquals(sensitivity1.Currency, FRA_AFMA.Currency); assertEquals(sensitivity1.YearFraction, paymentTime); assertEquals(sensitivity1.Sensitivity, fdDscSense, FRA_AFMA.Notional * eps); }
/// <summary> /// Compute the present value curve sensitivity of the payment. /// <para> /// The present value sensitivity of the payment is the sensitivity of the /// present value to the discount factor curve. /// There is no sensitivity if the payment date is before the valuation date. /// </para> /// <para> /// The specified discount factors should be for the payment currency, however this is not validated. /// /// </para> /// </summary> /// <param name="payment"> the payment </param> /// <param name="discountFactors"> the discount factors to price against </param> /// <returns> the point sensitivity of the present value </returns> public virtual PointSensitivityBuilder presentValueSensitivity(Payment payment, DiscountFactors discountFactors) { if (discountFactors.ValuationDate.isAfter(payment.Date)) { return(PointSensitivityBuilder.none()); } return(discountFactors.zeroRatePointSensitivity(payment.Date).multipliedBy(payment.Amount)); }
/// <summary> /// Calculates the present value sensitivity of the Ibor fixing product. /// <para> /// The present value sensitivity of the product is the sensitivity of the present value to /// the underlying curves. /// /// </para> /// </summary> /// <param name="deposit"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the point sensitivity of the present value </returns> public virtual PointSensitivities presentValueSensitivity(ResolvedIborFixingDeposit deposit, RatesProvider provider) { double forwardRate = this.forwardRate(deposit, provider); DiscountFactors discountFactors = provider.discountFactors(deposit.Currency); double discountFactor = discountFactors.discountFactor(deposit.EndDate); // sensitivity PointSensitivityBuilder sensiFwd = forwardRateSensitivity(deposit, provider).multipliedBy(-discountFactor * deposit.Notional * deposit.YearFraction); PointSensitivityBuilder sensiDsc = discountFactors.zeroRatePointSensitivity(deposit.EndDate).multipliedBy(deposit.Notional * deposit.YearFraction * (deposit.FixedRate - forwardRate)); return(sensiFwd.combinedWith(sensiDsc).build()); }
public virtual PointSensitivityBuilder presentValueSensitivity(FxResetNotionalExchange @event, RatesProvider provider) { DiscountFactors discountFactors = provider.discountFactors(@event.Currency); PointSensitivityBuilder sensiDsc = discountFactors.zeroRatePointSensitivity(@event.PaymentDate); sensiDsc = sensiDsc.multipliedBy(forecastValue(@event, provider)); PointSensitivityBuilder sensiFx = forecastValueSensitivity(@event, provider); sensiFx = sensiFx.multipliedBy(discountFactors.discountFactor(@event.PaymentDate)); return(sensiDsc.combinedWith(sensiFx)); }
//------------------------------------------------------------------------- /// <summary> /// Compute the present value curve sensitivity of the payment. /// <para> /// The present value sensitivity of the payment is the sensitivity of the /// present value to the discount factor curve. /// There is no sensitivity if the payment date is before the valuation date. /// /// </para> /// </summary> /// <param name="payment"> the payment </param> /// <param name="provider"> the provider </param> /// <returns> the point sensitivity of the present value </returns> public virtual PointSensitivityBuilder presentValueSensitivity(Payment payment, BaseProvider provider) { // duplicated code to avoid looking up in the provider when not necessary if (provider.ValuationDate.isAfter(payment.Date)) { return(PointSensitivityBuilder.none()); } DiscountFactors discountFactors = provider.discountFactors(payment.Currency); return(discountFactors.zeroRatePointSensitivity(payment.Date).multipliedBy(payment.Amount)); }
/// <summary> /// Calculates the present value sensitivity of the FRA product. /// <para> /// The present value sensitivity of the product is the sensitivity of the present value to /// the underlying curves. /// /// </para> /// </summary> /// <param name="fra"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the point sensitivity of the present value </returns> public virtual PointSensitivities presentValueSensitivity(ResolvedFra fra, RatesProvider provider) { DiscountFactors discountFactors = provider.discountFactors(fra.Currency); double df = discountFactors.discountFactor(fra.PaymentDate); double notional = fra.Notional; double unitAmount = this.unitAmount(fra, provider); double derivative = this.derivative(fra, provider); PointSensitivityBuilder iborSens = forwardRateSensitivity(fra, provider).multipliedBy(derivative * df * notional); PointSensitivityBuilder discSens = discountFactors.zeroRatePointSensitivity(fra.PaymentDate).multipliedBy(unitAmount * notional); return(iborSens.withCurrency(fra.Currency).combinedWith(discSens).build()); }
//------------------------------------------------------------------------- public virtual PointSensitivityBuilder presentValueSensitivity(RatePaymentPeriod period, RatesProvider provider) { Currency ccy = period.Currency; DiscountFactors discountFactors = provider.discountFactors(ccy); LocalDate paymentDate = period.PaymentDate; double df = discountFactors.discountFactor(paymentDate); PointSensitivityBuilder forecastSensitivity = forecastValueSensitivity(period, provider); forecastSensitivity = forecastSensitivity.multipliedBy(df); double forecastValue = this.forecastValue(period, provider); PointSensitivityBuilder dscSensitivity = discountFactors.zeroRatePointSensitivity(paymentDate); dscSensitivity = dscSensitivity.multipliedBy(forecastValue); return(forecastSensitivity.combinedWith(dscSensitivity)); }
//------------------------------------------------------------------------- // creates a simple provider private SimpleRatesProvider createProvider(NotionalExchange ne) { LocalDate paymentDate = ne.PaymentDate; double paymentTime = DAY_COUNT.relativeYearFraction(VAL_DATE, paymentDate); Currency currency = ne.Currency; DiscountFactors mockDf = mock(typeof(DiscountFactors)); when(mockDf.discountFactor(paymentDate)).thenReturn(DISCOUNT_FACTOR); ZeroRateSensitivity sens = ZeroRateSensitivity.of(currency, paymentTime, -DISCOUNT_FACTOR * paymentTime); when(mockDf.zeroRatePointSensitivity(paymentDate)).thenReturn(sens); SimpleRatesProvider prov = new SimpleRatesProvider(VAL_DATE, mockDf); prov.DayCount = DAY_COUNT; return(prov); }
//------------------------------------------------------------------------- // creates a simple provider private SimpleRatesProvider createProvider(FxResetNotionalExchange ne) { LocalDate paymentDate = ne.PaymentDate; double paymentTime = ACT_360.relativeYearFraction(VAL_DATE, paymentDate); Currency currency = ne.Currency; DiscountFactors mockDf = mock(typeof(DiscountFactors)); when(mockDf.discountFactor(paymentDate)).thenReturn(DISCOUNT_FACTOR); ZeroRateSensitivity sens = ZeroRateSensitivity.of(currency, paymentTime, -DISCOUNT_FACTOR * paymentTime); when(mockDf.zeroRatePointSensitivity(paymentDate)).thenReturn(sens); FxIndexRates mockFxRates = mock(typeof(FxIndexRates)); when(mockFxRates.rate(ne.Observation, ne.ReferenceCurrency)).thenReturn(FX_RATE); SimpleRatesProvider prov = new SimpleRatesProvider(VAL_DATE); prov.DiscountFactors = mockDf; prov.FxIndexRates = mockFxRates; prov.DayCount = ACT_360; return(prov); }
//------------------------------------------------------------------------- public CurrencyParameterSensitivities parameterSensitivity(FxForwardSensitivity pointSensitivity) { // use the specified base currency to determine the desired currency pair // then derive sensitivity from discount factors based off desired currency pair, not that of the index CurrencyPair currencyPair = pointSensitivity.CurrencyPair; Currency refBaseCurrency = pointSensitivity.ReferenceCurrency; Currency refCounterCurrency = pointSensitivity.ReferenceCounterCurrency; Currency sensitivityCurrency = pointSensitivity.Currency; LocalDate referenceDate = pointSensitivity.ReferenceDate; bool inverse = refBaseCurrency.Equals(currencyPair.Counter); DiscountFactors discountFactorsRefBase = (inverse ? counterCurrencyDiscountFactors : baseCurrencyDiscountFactors); DiscountFactors discountFactorsRefCounter = (inverse ? baseCurrencyDiscountFactors : counterCurrencyDiscountFactors); double dfCcyBaseAtMaturity = discountFactorsRefBase.discountFactor(referenceDate); double dfCcyCounterAtMaturityInv = 1d / discountFactorsRefCounter.discountFactor(referenceDate); double fxRate = fxRateProvider.fxRate(refBaseCurrency, refCounterCurrency); ZeroRateSensitivity dfCcyBaseAtMaturitySensitivity = discountFactorsRefBase.zeroRatePointSensitivity(referenceDate, sensitivityCurrency).multipliedBy(fxRate * dfCcyCounterAtMaturityInv * pointSensitivity.Sensitivity); ZeroRateSensitivity dfCcyCounterAtMaturitySensitivity = discountFactorsRefCounter.zeroRatePointSensitivity(referenceDate, sensitivityCurrency).multipliedBy(-fxRate * dfCcyBaseAtMaturity * dfCcyCounterAtMaturityInv * dfCcyCounterAtMaturityInv * pointSensitivity.Sensitivity); return(discountFactorsRefBase.parameterSensitivity(dfCcyBaseAtMaturitySensitivity).combinedWith(discountFactorsRefCounter.parameterSensitivity(dfCcyCounterAtMaturitySensitivity))); }