/// <summary> /// Explains the present value of a single payment period with z-spread. /// <para> /// This adds information to the <seealso cref="ExplainMapBuilder"/> to aid understanding of the calculation. /// /// </para> /// </summary> /// <param name="period"> the period to price </param> /// <param name="ratesProvider"> the rates provider, used to determine price index values </param> /// <param name="issuerDiscountFactors"> the discount factor provider </param> /// <param name="zSpread"> the z-spread </param> /// <param name="compoundedRateType"> the compounded rate type </param> /// <param name="periodsPerYear"> the number of periods per year </param> /// <param name="builder"> the builder to populate </param> public virtual void explainPresentValueWithZSpread(CapitalIndexedBondPaymentPeriod period, RatesProvider ratesProvider, IssuerCurveDiscountFactors issuerDiscountFactors, ExplainMapBuilder builder, double zSpread, CompoundedRateType compoundedRateType, int periodsPerYear) { Currency currency = period.Currency; LocalDate paymentDate = period.PaymentDate; builder.put(ExplainKey.ENTRY_TYPE, "CapitalIndexedBondPaymentPeriod"); builder.put(ExplainKey.PAYMENT_DATE, paymentDate); builder.put(ExplainKey.PAYMENT_CURRENCY, currency); builder.put(ExplainKey.START_DATE, period.StartDate); builder.put(ExplainKey.UNADJUSTED_START_DATE, period.UnadjustedStartDate); builder.put(ExplainKey.END_DATE, period.EndDate); builder.put(ExplainKey.UNADJUSTED_END_DATE, period.UnadjustedEndDate); builder.put(ExplainKey.DAYS, (int)DAYS.between(period.UnadjustedStartDate, period.UnadjustedEndDate)); if (paymentDate.isBefore(ratesProvider.ValuationDate)) { builder.put(ExplainKey.COMPLETED, true); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.zero(currency)); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.zero(currency)); } else { builder.put(ExplainKey.DISCOUNT_FACTOR, issuerDiscountFactors.discountFactor(paymentDate)); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.of(currency, forecastValue(period, ratesProvider))); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.of(currency, presentValueWithZSpread(period, ratesProvider, issuerDiscountFactors, zSpread, compoundedRateType, periodsPerYear))); } }
//------------------------------------------------------------------------- public virtual void test_presentValue_beforeStart() { double computedInterp = PRICER.presentValue(PERIOD_INTERP, IRP_BEFORE_START, ICDF_BEFORE_START); double computedMonthly = PRICER.presentValue(PERIOD_MONTHLY, IRP_BEFORE_START, ICDF_BEFORE_START); double computedFvInterp = PRICER.forecastValue(PERIOD_INTERP, IRP_BEFORE_START); double computedFvMonthly = PRICER.forecastValue(PERIOD_MONTHLY, IRP_BEFORE_START); double index1 = IRP_BEFORE_START.priceIndexValues(US_CPI_U).value(OBS); double index2 = IRP_BEFORE_START.priceIndexValues(US_CPI_U).value(OBS_PLUS1); double df = ICDF_BEFORE_START.discountFactor(END); double expectedFvInterp = (index1 * WEIGHT + (1d - WEIGHT) * index2) / START_INDEX * REAL_COUPON * NOTIONAL; double expectedFvMonthly = index1 / START_INDEX * REAL_COUPON * NOTIONAL; assertEquals(computedFvInterp, expectedFvInterp, TOL * expectedFvInterp); assertEquals(computedFvMonthly, expectedFvMonthly, TOL * expectedFvMonthly); assertEquals(computedInterp, expectedFvInterp * df, TOL * expectedFvInterp * df); assertEquals(computedMonthly, expectedFvMonthly * df, TOL * expectedFvMonthly * df); }
public virtual void test_of() { IssuerCurveDiscountFactors test = IssuerCurveDiscountFactors.of(DSC_FACTORS, GROUP); assertEquals(test.LegalEntityGroup, GROUP); assertEquals(test.Currency, GBP); assertEquals(test.ValuationDate, DATE); assertEquals(test.discountFactor(DATE_AFTER), DSC_FACTORS.discountFactor(DATE_AFTER)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of a single fixed coupon payment period. /// <para> /// The amount is expressed in the currency of the period. /// This returns the value of the period with discounting. /// </para> /// <para> /// The payment date of the period should not be in the past. /// The result of this method for payment dates in the past is undefined. /// /// </para> /// </summary> /// <param name="period"> the period to price </param> /// <param name="discountFactors"> the discount factor provider </param> /// <returns> the present value of the period </returns> public virtual double presentValue(FixedCouponBondPaymentPeriod period, IssuerCurveDiscountFactors discountFactors) { if (period.PaymentDate.isBefore(discountFactors.ValuationDate)) { return(0d); } double df = discountFactors.discountFactor(period.PaymentDate); return(period.FixedRate * period.Notional * period.YearFraction * df); }
public virtual void test_presentValue_afterFix() { double computedInterp = PRICER.presentValue(PERIOD_INTERP, IRP_AFTER_FIX, ICDF_AFTER_FIX); double computedMonthly = PRICER.presentValue(PERIOD_MONTHLY, IRP_AFTER_FIX, ICDF_AFTER_FIX); double df = ICDF_AFTER_FIX.discountFactor(END); double expectedInterp = (INDEX_END_1 * WEIGHT + (1d - WEIGHT) * INDEX_END_2) / START_INDEX * REAL_COUPON * NOTIONAL * df; double expectedMonthly = INDEX_END_1 / START_INDEX * REAL_COUPON * NOTIONAL * df; assertEquals(computedInterp, expectedInterp, TOL * expectedInterp); assertEquals(computedMonthly, expectedMonthly, TOL * expectedMonthly); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of the bill product. /// <para> /// The present value of the product is the value on the valuation date. /// The result is expressed using the payment currency of the bill. /// </para> /// <para> /// Coupon payments of the product are considered based on the valuation date. /// /// </para> /// </summary> /// <param name="bill"> the product </param> /// <param name="provider"> the discounting provider </param> /// <returns> the present value of the bill product </returns> public virtual CurrencyAmount presentValue(ResolvedBill bill, LegalEntityDiscountingProvider provider) { if (provider.ValuationDate.isAfter(bill.Notional.Date)) { return(CurrencyAmount.of(bill.Currency, 0.0d)); } IssuerCurveDiscountFactors issuerDf = issuerCurveDf(bill, provider); double dfMaturity = issuerDf.discountFactor(bill.Notional.Date); return(bill.Notional.Value.multipliedBy(dfMaturity)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the price for settlement at a given settlement date using curves. /// </summary> /// <param name="bill"> the bill </param> /// <param name="provider"> the discounting provider </param> /// <param name="settlementDate"> the settlement date </param> /// <returns> the price </returns> public virtual double priceFromCurves(ResolvedBill bill, LegalEntityDiscountingProvider provider, LocalDate settlementDate) { ArgChecker.inOrderNotEqual(settlementDate, bill.Notional.Date, "settlementDate", "endDate"); ArgChecker.inOrderOrEqual(provider.ValuationDate, settlementDate, "valuationDate", "settlementDate"); IssuerCurveDiscountFactors issuerDf = issuerCurveDf(bill, provider); double dfMaturity = issuerDf.discountFactor(bill.Notional.Date); RepoCurveDiscountFactors repoDf = repoCurveDf(bill, provider); double dfRepoSettle = repoDf.discountFactor(settlementDate); return(dfMaturity / dfRepoSettle); }
public virtual void test_presentValue_onFix() { double computedInterp = PRICER.presentValue(PERIOD_INTERP, IRP_ON_FIX, ICDF_ON_FIX); double computedMonthly = PRICER.presentValue(PERIOD_MONTHLY, IRP_ON_FIX, ICDF_ON_FIX); double index2 = IRP_ON_FIX.priceIndexValues(US_CPI_U).value(OBS_PLUS1); double df = ICDF_ON_FIX.discountFactor(END); double expectedInterp = (INDEX_END_1 * WEIGHT + (1d - WEIGHT) * index2) / START_INDEX * REAL_COUPON * NOTIONAL * df; double expectedMonthly = INDEX_END_1 / START_INDEX * REAL_COUPON * NOTIONAL * df; assertEquals(computedInterp, expectedInterp, TOL * expectedInterp); assertEquals(computedMonthly, expectedMonthly, TOL * expectedMonthly); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value sensitivity of a single payment period. /// <para> /// The present value sensitivity of the period is the sensitivity of the present value to /// the underlying curves. /// /// </para> /// </summary> /// <param name="period"> the period to price </param> /// <param name="ratesProvider"> the rates provider, used to determine price index values </param> /// <param name="issuerDiscountFactors"> the discount factor provider </param> /// <returns> the present value curve sensitivity of the period </returns> public virtual PointSensitivityBuilder presentValueSensitivity(CapitalIndexedBondPaymentPeriod period, RatesProvider ratesProvider, IssuerCurveDiscountFactors issuerDiscountFactors) { if (period.PaymentDate.isBefore(ratesProvider.ValuationDate)) { return(PointSensitivityBuilder.none()); } double rate = rateComputationFn.rate(period.RateComputation, period.StartDate, period.EndDate, ratesProvider); PointSensitivityBuilder rateSensi = rateComputationFn.rateSensitivity(period.RateComputation, period.StartDate, period.EndDate, ratesProvider); double df = issuerDiscountFactors.discountFactor(period.PaymentDate); PointSensitivityBuilder dfSensi = issuerDiscountFactors.zeroRatePointSensitivity(period.PaymentDate); double factor = period.Notional * period.RealCoupon; return(rateSensi.multipliedBy(df * factor).combinedWith(dfSensi.multipliedBy((rate + 1d) * factor))); }
//------------------------------------------------------------------------- /// <summary> /// Explains the present value of a single fixed coupon payment period. /// <para> /// This adds information to the <seealso cref="ExplainMapBuilder"/> to aid understanding of the calculation. /// /// </para> /// </summary> /// <param name="period"> the period to price </param> /// <param name="discountFactors"> the discount factor provider </param> /// <param name="builder"> the builder to populate </param> public virtual void explainPresentValue(FixedCouponBondPaymentPeriod period, IssuerCurveDiscountFactors discountFactors, ExplainMapBuilder builder) { Currency currency = period.Currency; LocalDate paymentDate = period.PaymentDate; explainBasics(period, builder, currency, paymentDate); if (paymentDate.isBefore(discountFactors.ValuationDate)) { builder.put(ExplainKey.COMPLETED, true); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.zero(currency)); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.zero(currency)); } else { builder.put(ExplainKey.DISCOUNT_FACTOR, discountFactors.discountFactor(paymentDate)); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.of(currency, forecastValue(period, discountFactors))); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.of(currency, presentValue(period, discountFactors))); } }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of a single payment period. /// <para> /// This returns the value of the period with discounting. /// If the payment date of the period is in the past, zero is returned. /// /// </para> /// </summary> /// <param name="period"> the period to price </param> /// <param name="ratesProvider"> the rates provider, used to determine price index values </param> /// <param name="issuerDiscountFactors"> the discount factor provider </param> /// <returns> the present value of the period </returns> public virtual double presentValue(CapitalIndexedBondPaymentPeriod period, RatesProvider ratesProvider, IssuerCurveDiscountFactors issuerDiscountFactors) { double df = issuerDiscountFactors.discountFactor(period.PaymentDate); return(df * forecastValue(period, ratesProvider)); }