//------------------------------------------------------------------------- /// <summary> /// Explains the present value of the FRA product. /// <para> /// This returns explanatory information about the calculation. /// /// </para> /// </summary> /// <param name="fra"> the FRA product for which present value should be computed </param> /// <param name="provider"> the rates provider </param> /// <returns> the explanatory information </returns> public virtual ExplainMap explainPresentValue(ResolvedFra fra, RatesProvider provider) { ExplainMapBuilder builder = ExplainMap.builder(); Currency currency = fra.Currency; builder.put(ExplainKey.ENTRY_TYPE, "FRA"); builder.put(ExplainKey.PAYMENT_DATE, fra.PaymentDate); builder.put(ExplainKey.START_DATE, fra.StartDate); builder.put(ExplainKey.END_DATE, fra.EndDate); builder.put(ExplainKey.ACCRUAL_YEAR_FRACTION, fra.YearFraction); builder.put(ExplainKey.DAYS, (int)DAYS.between(fra.StartDate, fra.EndDate)); builder.put(ExplainKey.PAYMENT_CURRENCY, currency); builder.put(ExplainKey.NOTIONAL, CurrencyAmount.of(currency, fra.Notional)); builder.put(ExplainKey.TRADE_NOTIONAL, CurrencyAmount.of(currency, fra.Notional)); if (fra.PaymentDate.isBefore(provider.ValuationDate)) { builder.put(ExplainKey.COMPLETED, true); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.zero(currency)); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.zero(currency)); } else { double rate = rateComputationFn.explainRate(fra.FloatingRate, fra.StartDate, fra.EndDate, provider, builder); builder.put(ExplainKey.FIXED_RATE, fra.FixedRate); builder.put(ExplainKey.DISCOUNT_FACTOR, provider.discountFactor(currency, fra.PaymentDate)); builder.put(ExplainKey.PAY_OFF_RATE, rate); builder.put(ExplainKey.UNIT_AMOUNT, unitAmount(fra, provider)); builder.put(ExplainKey.FORECAST_VALUE, forecastValue(fra, provider)); builder.put(ExplainKey.PRESENT_VALUE, presentValue(fra, provider)); } return(builder.build()); }
/// <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 explainPresentValue(FxResetNotionalExchange @event, RatesProvider provider, ExplainMapBuilder builder) { Currency currency = @event.Currency; LocalDate paymentDate = @event.PaymentDate; builder.put(ExplainKey.ENTRY_TYPE, "FxResetNotionalExchange"); builder.put(ExplainKey.PAYMENT_DATE, paymentDate); builder.put(ExplainKey.PAYMENT_CURRENCY, currency); builder.put(ExplainKey.TRADE_NOTIONAL, @event.NotionalAmount); if (paymentDate.isBefore(provider.ValuationDate)) { builder.put(ExplainKey.COMPLETED, true); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.zero(currency)); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.zero(currency)); } else { builder.addListEntry(ExplainKey.OBSERVATIONS, child => { child.put(ExplainKey.ENTRY_TYPE, "FxObservation"); child.put(ExplainKey.INDEX, @event.Observation.Index); child.put(ExplainKey.FIXING_DATE, @event.Observation.FixingDate); child.put(ExplainKey.INDEX_VALUE, fxRate(@event, provider)); }); builder.put(ExplainKey.DISCOUNT_FACTOR, provider.discountFactor(currency, paymentDate)); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.of(currency, forecastValue(@event, provider))); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.of(currency, presentValue(@event, provider))); } }
public virtual void test_of_positiveNegative() { assertThrowsIllegalArg(() => FxSingle.of(GBP_P1000, USD_P1600, DATE_2015_06_30)); assertThrowsIllegalArg(() => FxSingle.of(GBP_M1000, USD_M1600, DATE_2015_06_30)); assertThrowsIllegalArg(() => FxSingle.of(CurrencyAmount.zero(GBP), USD_M1600, DATE_2015_06_30)); assertThrowsIllegalArg(() => FxSingle.of(CurrencyAmount.zero(GBP), USD_P1600, DATE_2015_06_30)); }
//------------------------------------------------------------------------- public virtual void explainPresentValue(KnownAmountSwapPaymentPeriod period, RatesProvider provider, ExplainMapBuilder builder) { Currency currency = period.Currency; LocalDate paymentDate = period.PaymentDate; builder.put(ExplainKey.ENTRY_TYPE, "KnownAmountPaymentPeriod"); 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.StartDate, period.EndDate)); if (paymentDate.isBefore(provider.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, provider.discountFactor(currency, paymentDate)); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.of(currency, forecastValue(period, provider))); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.of(currency, presentValue(period, provider))); } }
//------------------------------------------------------------------------- /// <summary> /// Computes the forecast value of the payment. /// <para> /// The present value is zero 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 forecast value </returns> public virtual CurrencyAmount forecastValue(Payment payment, BaseProvider provider) { if (provider.ValuationDate.isAfter(payment.Date)) { return(CurrencyAmount.zero(payment.Currency)); } return(payment.Value); }
public virtual void test_currentCash() { MultiCurrencyAmount cc1 = PRODUCT_PRICER.currentCash(CMS_ONE_LEG, RATES_PROVIDER, VOLATILITIES); MultiCurrencyAmount cc2 = PRODUCT_PRICER.currentCash(CMS_TWO_LEGS, RATES_PROVIDER, VOLATILITIES); assertEquals(cc1, MultiCurrencyAmount.of(CurrencyAmount.zero(EUR))); assertEquals(cc2, MultiCurrencyAmount.of(CurrencyAmount.zero(EUR))); }
/// <summary> /// Calculates the current cash. /// </summary> /// <param name="payment"> the payment </param> /// <param name="provider"> the provider </param> /// <returns> the current cash </returns> public virtual CurrencyAmount currentCash(Payment payment, BaseProvider provider) { if (payment.Date.isEqual(provider.ValuationDate)) { return(payment.Value); } return(CurrencyAmount.zero(payment.Currency)); }
public virtual void test_currentCash() { MultiCurrencyAmount cc1 = PRICER.currentCash(CAP_ONE_LEG, RATES, VOLS); MultiCurrencyAmount cc2 = PRICER.currentCash(CAP_TWO_LEGS, RATES, VOLS); assertEquals(cc1, MultiCurrencyAmount.of(CurrencyAmount.zero(EUR))); assertEquals(cc2, MultiCurrencyAmount.of(CurrencyAmount.zero(EUR))); }
public virtual void test_currentCash() { MultiCurrencyAmount computedWithPayLeg = PRICER.currentCash(TRADE_PAYLEG, RATES, VOLS); MultiCurrencyAmount computedWithPremium = PRICER.currentCash(TRADE_PREMIUM, RATES, VOLS); assertEquals(computedWithPayLeg, MultiCurrencyAmount.of(CurrencyAmount.zero(EUR))); assertEquals(computedWithPremium, MultiCurrencyAmount.of(PREMIUM.Value)); }
public virtual void test_currentCash() { MultiCurrencyAmount cc1 = TRADE_PRICER.currentCash(CMS_TRADE_PREMIUM, RATES_PROVIDER, VOLATILITIES); MultiCurrencyAmount cc2 = TRADE_PRICER.currentCash(CMS_TRADE, RATES_PROVIDER, VOLATILITIES); assertEquals(cc1, MultiCurrencyAmount.of(PREMIUM.Value)); assertEquals(cc2, MultiCurrencyAmount.of(CurrencyAmount.zero(EUR))); }
/// <summary> /// Computes the present value of the payment by discounting. /// <para> /// The present value is zero 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 present value </returns> public virtual CurrencyAmount presentValue(Payment payment, DiscountFactors discountFactors) { if (discountFactors.ValuationDate.isAfter(payment.Date)) { return(CurrencyAmount.zero(payment.Currency)); } return(payment.Value.multipliedBy(discountFactors.discountFactor(payment.Date))); }
/// <summary> /// Computes the present value of the payment with z-spread by discounting. /// <para> /// The present value is zero 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> /// <para> /// The z-spread is a parallel shift applied to continuously compounded rates or periodic /// compounded rates of the discounting curve. /// /// </para> /// </summary> /// <param name="payment"> the payment </param> /// <param name="discountFactors"> the discount factors to price against </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> /// <returns> the present value </returns> public virtual CurrencyAmount presentValueWithSpread(Payment payment, DiscountFactors discountFactors, double zSpread, CompoundedRateType compoundedRateType, int periodsPerYear) { if (discountFactors.ValuationDate.isAfter(payment.Date)) { return(CurrencyAmount.zero(payment.Currency)); } double df = discountFactors.discountFactorWithSpread(payment.Date, zSpread, compoundedRateType, periodsPerYear); return(payment.Value.multipliedBy(df)); }
public virtual void test_of_amounts_bothZero() { ResolvedFxSingle test = ResolvedFxSingle.of(CurrencyAmount.zero(GBP), CurrencyAmount.zero(USD), DATE_2015_06_30); assertEquals(test.BaseCurrencyPayment, Payment.of(CurrencyAmount.zero(GBP), DATE_2015_06_30)); assertEquals(test.CounterCurrencyPayment, Payment.of(CurrencyAmount.zero(USD), DATE_2015_06_30)); assertEquals(test.PaymentDate, DATE_2015_06_30); assertEquals(test.CurrencyPair, CurrencyPair.of(GBP, USD)); assertEquals(test.ReceiveCurrencyAmount, CurrencyAmount.zero(USD)); }
public virtual void test_of_rate_bothZero() { FxSingle test = FxSingle.of(CurrencyAmount.zero(GBP), FxRate.of(USD, GBP, 1.6d), DATE_2015_06_30); assertEquals(test.BaseCurrencyAmount, CurrencyAmount.zero(GBP)); assertEquals(test.CounterCurrencyAmount.Amount, CurrencyAmount.zero(USD).Amount, 1e-12); assertEquals(test.PaymentDate, DATE_2015_06_30); assertEquals(test.CurrencyPair, CurrencyPair.of(GBP, USD)); assertEquals(test.ReceiveCurrencyAmount, CurrencyAmount.of(USD, 0d)); }
/// <summary> /// Calculates the current cash of the FRA trade. /// </summary> /// <param name="trade"> the trade </param> /// <param name="provider"> the rates provider </param> /// <returns> the current cash </returns> public virtual CurrencyAmount currentCash(ResolvedFraTrade trade, RatesProvider provider) { ResolvedFra fra = trade.Product; if (fra.PaymentDate.isEqual(provider.ValuationDate)) { return(productPricer.presentValue(fra, provider)); } return(CurrencyAmount.zero(fra.Currency)); }
public virtual void presentValue_afterPayment() { CurrencyAmount pv = PRICER_CMS.presentValue(COUPON, RATES_PROVIDER_AFTER_PAY); CurrencyAmount pvCaplet = PRICER_CMS.presentValue(CAPLET, RATES_PROVIDER_AFTER_PAY); CurrencyAmount pvFloorlet = PRICER_CMS.presentValue(FLOORLET, RATES_PROVIDER_AFTER_PAY); assertEquals(pv, CurrencyAmount.zero(EUR)); assertEquals(pvCaplet, CurrencyAmount.zero(EUR)); assertEquals(pvFloorlet, CurrencyAmount.zero(EUR)); }
//------------------------------------------------------------------------- /// <summary> /// Computes the present value of the payment by discounting. /// <para> /// The present value is zero 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 present value </returns> public virtual CurrencyAmount presentValue(Payment payment, BaseProvider provider) { // duplicated code to avoid looking up in the provider when not necessary if (provider.ValuationDate.isAfter(payment.Date)) { return(CurrencyAmount.zero(payment.Currency)); } double df = provider.discountFactor(payment.Currency, payment.Date); return(payment.Value.multipliedBy(df)); }
/// <summary> /// Calculates the current cash of a bill trade. /// </summary> /// <param name="trade"> the trade </param> /// <param name="valuationDate"> the valuation date </param> /// <returns> the current cash amount </returns> public virtual CurrencyAmount currentCash(ResolvedBillTrade trade, LocalDate valuationDate) { if (trade.Product.Notional.Date.Equals(valuationDate)) { return(trade.Product.Notional.Value.multipliedBy(trade.Quantity)); } if (trade.Settlement.Present && trade.Settlement.get().Date.Equals(valuationDate)) { return(trade.Settlement.get().Value); } return(CurrencyAmount.zero(trade.Product.Currency)); }
//------------------------------------------------------------------------- private CurrencyAmount presentValueSettlement(ResolvedCapitalIndexedBondTrade trade, RatesProvider ratesProvider, LegalEntityDiscountingProvider discountingProvider) { if (!trade.Settlement.Present) { // position has no settlement, thus it has no value return(CurrencyAmount.zero(trade.Product.Currency)); } BondPaymentPeriod settlePeriod = trade.Settlement.get().Payment; ResolvedCapitalIndexedBond product = trade.Product; CurrencyAmount netAmount = this.netAmount(trade, ratesProvider); RepoCurveDiscountFactors repoDf = DiscountingCapitalIndexedBondProductPricer.repoCurveDf(product, discountingProvider); return(netAmount.multipliedBy(repoDf.discountFactor(settlePeriod.PaymentDate))); }
/// <summary> /// Calculates the current cash of the NDF product. /// </summary> /// <param name="ndf"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the current cash of the product in the settlement currency </returns> public virtual CurrencyAmount currentCash(ResolvedFxNdf ndf, RatesProvider provider) { Currency ccySettle = ndf.SettlementCurrency; if (provider.ValuationDate.isEqual(ndf.PaymentDate)) { Currency ccyOther = ndf.NonDeliverableCurrency; CurrencyAmount notionalSettle = ndf.SettlementCurrencyNotional; double agreedRate = ndf.AgreedFxRate.fxRate(ccySettle, ccyOther); double rate = provider.fxIndexRates(ndf.Index).rate(ndf.Observation, ccySettle); return(notionalSettle.multipliedBy(1d - agreedRate / rate)); } return(CurrencyAmount.zero(ccySettle)); }
/// <summary> /// Calculates the current cash. /// </summary> /// <param name="trade"> the trade </param> /// <param name="provider"> the rates provider </param> /// <returns> the current cash </returns> public virtual CurrencyAmount currentCash(ResolvedTermDepositTrade trade, RatesProvider provider) { ResolvedTermDeposit product = trade.Product; if (product.StartDate.isEqual(provider.ValuationDate)) { return(CurrencyAmount.of(product.Currency, -product.Notional)); } if (product.EndDate.isEqual(provider.ValuationDate)) { return(CurrencyAmount.of(product.Currency, product.Notional + product.Interest)); } return(CurrencyAmount.zero(product.Currency)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of the NDF product. /// <para> /// The present value of the product is the value on the valuation date. /// The present value is returned in the settlement currency. /// /// </para> /// </summary> /// <param name="ndf"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the present value of the product in the settlement currency </returns> public virtual CurrencyAmount presentValue(ResolvedFxNdf ndf, RatesProvider provider) { Currency ccySettle = ndf.SettlementCurrency; if (provider.ValuationDate.isAfter(ndf.PaymentDate)) { return(CurrencyAmount.zero(ccySettle)); } Currency ccyOther = ndf.NonDeliverableCurrency; CurrencyAmount notionalSettle = ndf.SettlementCurrencyNotional; double agreedRate = ndf.AgreedFxRate.fxRate(ccySettle, ccyOther); double forwardRate = provider.fxIndexRates(ndf.Index).rate(ndf.Observation, ccySettle); double dfSettle = provider.discountFactor(ccySettle, ndf.PaymentDate); return(notionalSettle.multipliedBy(dfSettle * (1d - agreedRate / forwardRate))); }
/// <summary> /// Explains the present value of a single fixed coupon payment period with z-spread. /// <para> /// This adds information to the <seealso cref="ExplainMapBuilder"/> to aid understanding of the calculation. /// </para> /// <para> /// The z-spread is a parallel shift applied to continuously compounded rates or periodic /// compounded rates of the discounting curve. /// /// </para> /// </summary> /// <param name="period"> the period to price </param> /// <param name="discountFactors"> 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 explainPresentValueWithSpread(FixedCouponBondPaymentPeriod period, IssuerCurveDiscountFactors discountFactors, ExplainMapBuilder builder, double zSpread, CompoundedRateType compoundedRateType, int periodsPerYear) { 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.DiscountFactors.discountFactorWithSpread(paymentDate, zSpread, compoundedRateType, periodsPerYear)); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.of(currency, forecastValue(period, discountFactors))); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.of(currency, presentValueWithSpread(period, discountFactors, zSpread, compoundedRateType, periodsPerYear))); } }
//------------------------------------------------------------------------- /// <summary> /// Calculates the payment that was made for the trade. /// <para> /// This is the payment that was made on the settlement date, based on the quantity and clean price. /// /// </para> /// </summary> /// <param name="trade"> the trade </param> /// <returns> the payment that was made </returns> public virtual Payment upfrontPayment(ResolvedFixedCouponBondTrade trade) { ResolvedFixedCouponBond product = trade.Product; Currency currency = product.Currency; if (!trade.Settlement.Present) { return(Payment.of(CurrencyAmount.zero(currency), product.StartDate)); // date doesn't matter as it is zero } // payment is based on the dirty price ResolvedFixedCouponBondSettlement settlement = trade.Settlement.get(); LocalDate settlementDate = settlement.SettlementDate; double cleanPrice = settlement.Price; double dirtyPrice = productPricer.dirtyPriceFromCleanPrice(product, settlementDate, cleanPrice); // calculate payment double quantity = trade.Quantity; double notional = product.Notional; return(Payment.of(CurrencyAmount.of(currency, -quantity * notional * dirtyPrice), settlementDate)); }
//------------------------------------------------------------------------- public virtual void explainPresentValue(RatePaymentPeriod paymentPeriod, RatesProvider provider, ExplainMapBuilder builder) { Currency currency = paymentPeriod.Currency; LocalDate paymentDate = paymentPeriod.PaymentDate; double fxRate = this.fxRate(paymentPeriod, provider); double notional = paymentPeriod.Notional * fxRate; builder.put(ExplainKey.ENTRY_TYPE, "RatePaymentPeriod"); builder.put(ExplainKey.PAYMENT_DATE, paymentDate); builder.put(ExplainKey.PAYMENT_CURRENCY, currency); builder.put(ExplainKey.NOTIONAL, CurrencyAmount.of(currency, notional)); builder.put(ExplainKey.TRADE_NOTIONAL, paymentPeriod.NotionalAmount); if (paymentDate.isBefore(provider.ValuationDate)) { builder.put(ExplainKey.COMPLETED, true); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.zero(currency)); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.zero(currency)); } else { paymentPeriod.FxReset.ifPresent(fxReset => { builder.addListEntry(ExplainKey.OBSERVATIONS, child => { child.put(ExplainKey.ENTRY_TYPE, "FxObservation"); child.put(ExplainKey.INDEX, fxReset.Observation.Index); child.put(ExplainKey.FIXING_DATE, fxReset.Observation.FixingDate); child.put(ExplainKey.INDEX_VALUE, fxRate); }); }); foreach (RateAccrualPeriod accrualPeriod in paymentPeriod.AccrualPeriods) { builder.addListEntry(ExplainKey.ACCRUAL_PERIODS, child => explainPresentValue(accrualPeriod, paymentPeriod.DayCount, currency, notional, provider, child)); } builder.put(ExplainKey.COMPOUNDING, paymentPeriod.CompoundingMethod); builder.put(ExplainKey.DISCOUNT_FACTOR, provider.discountFactor(currency, paymentDate)); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.of(currency, forecastValue(paymentPeriod, provider))); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.of(currency, presentValue(paymentPeriod, provider))); } }
//------------------------------------------------------------------------- /// <summary> /// Calculates the net amount of the settlement of the bond trade. /// <para> /// Since the sign of the settlement notional is opposite to that of the product, negative amount will be returned /// for positive quantity of trade. /// /// </para> /// </summary> /// <param name="trade"> the trade </param> /// <param name="ratesProvider"> the rates provider, used to determine price index values </param> /// <returns> the net amount </returns> public virtual CurrencyAmount netAmount(ResolvedCapitalIndexedBondTrade trade, RatesProvider ratesProvider) { if (!trade.Settlement.Present) { // position has no settlement, thus it has no value return(CurrencyAmount.zero(trade.Product.Currency)); } BondPaymentPeriod settlePeriod = trade.Settlement.get().Payment; if (settlePeriod is KnownAmountBondPaymentPeriod) { Payment payment = ((KnownAmountBondPaymentPeriod)settlePeriod).Payment; return(payment.Value); } else if (settlePeriod is CapitalIndexedBondPaymentPeriod) { CapitalIndexedBondPaymentPeriod casted = (CapitalIndexedBondPaymentPeriod)settlePeriod; double netAmount = productPricer.PeriodPricer.forecastValue(casted, ratesProvider); return(CurrencyAmount.of(casted.Currency, netAmount)); } throw new System.NotSupportedException("unsupported settlement type"); }
//------------------------------------------------------------------------- public virtual void explainPresentValue(NotionalExchange @event, RatesProvider provider, ExplainMapBuilder builder) { Currency currency = @event.Currency; LocalDate paymentDate = @event.PaymentDate; builder.put(ExplainKey.ENTRY_TYPE, "NotionalExchange"); builder.put(ExplainKey.PAYMENT_DATE, paymentDate); builder.put(ExplainKey.PAYMENT_CURRENCY, currency); builder.put(ExplainKey.TRADE_NOTIONAL, @event.PaymentAmount); if (paymentDate.isBefore(provider.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, provider.discountFactor(currency, paymentDate)); builder.put(ExplainKey.FORECAST_VALUE, CurrencyAmount.of(currency, forecastValue(@event, provider))); builder.put(ExplainKey.PRESENT_VALUE, CurrencyAmount.of(currency, presentValue(@event, provider))); } }
/// <summary> /// Calculates the current cash of the fixed coupon bond trade. /// </summary> /// <param name="trade"> the trade </param> /// <param name="valuationDate"> the valuation date </param> /// <returns> the current cash amount </returns> public virtual CurrencyAmount currentCash(ResolvedFixedCouponBondTrade trade, LocalDate valuationDate) { Payment upfrontPayment = this.upfrontPayment(trade); Currency currency = upfrontPayment.Currency; // assumes single currency is involved in trade CurrencyAmount currentCash = CurrencyAmount.zero(currency); if (upfrontPayment.Date.Equals(valuationDate)) { currentCash = currentCash.plus(upfrontPayment.Value); } if (trade.Settlement.Present) { LocalDate settlementDate = trade.Settlement.get().SettlementDate; ResolvedFixedCouponBond product = trade.Product; if (!settlementDate.isAfter(valuationDate)) { double cashCoupon = product.hasExCouponPeriod() ? 0d : currentCashCouponPayment(product, valuationDate); Payment payment = product.NominalPayment; double cashNominal = payment.Date.isEqual(valuationDate) ? payment.Amount : 0d; currentCash = currentCash.plus(CurrencyAmount.of(currency, (cashCoupon + cashNominal) * trade.Quantity)); } } return(currentCash); }
/// <summary> /// Explains the present value of the payment. /// <para> /// This returns explanatory information about the calculation. /// /// </para> /// </summary> /// <param name="payment"> the payment </param> /// <param name="provider"> the provider </param> /// <returns> the explanatory information </returns> public virtual ExplainMap explainPresentValue(Payment payment, BaseProvider provider) { Currency currency = payment.Currency; LocalDate paymentDate = payment.Date; ExplainMapBuilder builder = ExplainMap.builder(); builder.put(ExplainKey.ENTRY_TYPE, "Payment"); builder.put(ExplainKey.PAYMENT_DATE, paymentDate); builder.put(ExplainKey.PAYMENT_CURRENCY, currency); if (paymentDate.isBefore(provider.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, provider.discountFactor(currency, paymentDate)); builder.put(ExplainKey.FORECAST_VALUE, forecastValue(payment, provider)); builder.put(ExplainKey.PRESENT_VALUE, presentValue(payment, provider)); } return(builder.build()); }