public virtual void test_price_presentValue_atExpiry()
        {
            double         df           = RATES_PROVIDER_EXPIRY.discountFactor(USD, PAYMENT_DATE);
            double         forward      = PRICER.DiscountingFxSingleProductPricer.forwardFxRate(FX_PRODUCT_HIGH, RATES_PROVIDER_EXPIRY).fxRate(CURRENCY_PAIR);
            double         priceCallOtm = PRICER.price(CALL_OTM, RATES_PROVIDER_EXPIRY, VOLS_EXPIRY);
            CurrencyAmount pvCallOtm    = PRICER.presentValue(CALL_OTM, RATES_PROVIDER_EXPIRY, VOLS_EXPIRY);

            assertEquals(priceCallOtm, 0d, TOL);
            assertEquals(pvCallOtm.Amount, 0d, NOTIONAL * TOL);
            double         priceCallItm = PRICER.price(CALL_ITM, RATES_PROVIDER_EXPIRY, VOLS_EXPIRY);
            CurrencyAmount pvCallItm    = PRICER.presentValue(CALL_ITM, RATES_PROVIDER_EXPIRY, VOLS_EXPIRY);

            assertEquals(priceCallItm, df * (forward - STRIKE_RATE_LOW), TOL);
            assertEquals(pvCallItm.Amount, df * (forward - STRIKE_RATE_LOW) * NOTIONAL, NOTIONAL * TOL);
            double         pricePutOtm = PRICER.price(PUT_OTM, RATES_PROVIDER_EXPIRY, VOLS_EXPIRY);
            CurrencyAmount pvPutOtm    = PRICER.presentValue(PUT_OTM, RATES_PROVIDER_EXPIRY, VOLS_EXPIRY);

            assertEquals(pricePutOtm, 0d, TOL);
            assertEquals(pvPutOtm.Amount, 0d, NOTIONAL * TOL);
            double         pricePutItm = PRICER.price(PUT_ITM, RATES_PROVIDER_EXPIRY, VOLS_EXPIRY);
            CurrencyAmount pvPutItm    = PRICER.presentValue(PUT_ITM, RATES_PROVIDER_EXPIRY, VOLS_EXPIRY);

            assertEquals(pricePutItm, df * (STRIKE_RATE_HIGH - forward), TOL);
            assertEquals(pvPutItm.Amount, df * (STRIKE_RATE_HIGH - forward) * NOTIONAL, NOTIONAL * TOL);
        }
        public virtual void test_presentValue()
        {
            CurrencyAmount computed = PRICER.presentValue(NDF, PROVIDER);
            double         dscUsd   = PROVIDER.discountFactor(USD, NDF.PaymentDate);
            double         dscKrw   = PROVIDER.discountFactor(KRW, NDF.PaymentDate);
            double         expected = NOMINAL_USD * (dscUsd - dscKrw * FX_RATE / PROVIDER.fxRate(CurrencyPair.of(USD, KRW)));

            assertEquals(computed.Currency, USD);
            assertEquals(computed.Amount, expected, NOMINAL_USD * TOL);
        }
        /// <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());
        }
        //-------------------------------------------------------------------------
        public virtual void test_presentValue_beforeStart()
        {
            MultiCurrencyAmount computed = PRICER.presentValue(SWAP_PRODUCT, PROVIDER);
            double expected_usd          = NOMINAL_USD * (PROVIDER.discountFactor(USD, PAYMENT_DATE_NEAR) - PROVIDER.discountFactor(USD, PAYMENT_DATE_FAR));
            double expected_krw          = NOMINAL_USD * (-FX_RATE * PROVIDER.discountFactor(KRW, PAYMENT_DATE_NEAR) + (FX_RATE + FX_FWD_POINTS) * PROVIDER.discountFactor(KRW, PAYMENT_DATE_FAR));

            assertEquals(computed.getAmount(USD).Amount, expected_usd, NOMINAL_USD * TOL);
            assertEquals(computed.getAmount(KRW).Amount, expected_krw, NOMINAL_USD * FX_RATE * TOL);

            // currency exposure
            MultiCurrencyAmount exposure = PRICER.currencyExposure(SWAP_PRODUCT, PROVIDER);

            assertEquals(exposure, computed);
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the currency exposure by discounting each payment in its own currency.
        /// </summary>
        /// <param name="ndf">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the currency exposure </returns>
        public virtual MultiCurrencyAmount currencyExposure(ResolvedFxNdf ndf, RatesProvider provider)
        {
            if (provider.ValuationDate.isAfter(ndf.PaymentDate))
            {
                return(MultiCurrencyAmount.empty());
            }
            Currency       ccySettle      = ndf.SettlementCurrency;
            CurrencyAmount notionalSettle = ndf.SettlementCurrencyNotional;
            double         dfSettle       = provider.discountFactor(ccySettle, ndf.PaymentDate);
            Currency       ccyOther       = ndf.NonDeliverableCurrency;
            double         agreedRate     = ndf.AgreedFxRate.fxRate(ccySettle, ccyOther);
            double         dfOther        = provider.discountFactor(ccyOther, ndf.PaymentDate);

            return(MultiCurrencyAmount.of(notionalSettle.multipliedBy(dfSettle)).plus(CurrencyAmount.of(ccyOther, -notionalSettle.Amount * agreedRate * dfOther)));
        }
        //-------------------------------------------------------------------------
        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)));
            }
        }
Beispiel #7
0
        //-------------------------------------------------------------------------
        public virtual double presentValue(RatePaymentPeriod period, RatesProvider provider)
        {
            // forecastValue * discountFactor
            double df = provider.discountFactor(period.Currency, period.PaymentDate);

            return(forecastValue(period, provider) * df);
        }
Beispiel #8
0
        public virtual double pvbp(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);
                double            df            = provider.discountFactor(paymentPeriod.Currency, paymentPeriod.PaymentDate);
                return(df * accrualPeriod.YearFraction * paymentPeriod.Notional);
            }
            else
            {
                // Flat compounding
                switch (paymentPeriod.CompoundingMethod)
                {
                case FLAT:
                    return(pvbpCompoundedFlat(paymentPeriod, provider));

                default:
                    throw new System.NotSupportedException("PVBP not implemented yet for non FLAT compounding");
                }
            }
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity of the swaption product to the rate curves.
        /// <para>
        /// The present value sensitivity is computed in a "sticky model parameter" style, i.e. the sensitivity to the
        /// curve nodes with the SABR model parameters unchanged. This sensitivity does not include a potential
        /// re-calibration of the model parameters to the raw market data.
        ///
        /// </para>
        /// </summary>
        /// <param name="swaption">  the swaption product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the volatilities </param>
        /// <returns> the point sensitivity to the rate curves </returns>
        public virtual PointSensitivityBuilder presentValueSensitivityRatesStickyModel(ResolvedSwaption swaption, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            validate(swaption, ratesProvider, swaptionVolatilities);
            ZonedDateTime   expiryDateTime = swaption.Expiry;
            double          expiry         = swaptionVolatilities.relativeTime(expiryDateTime);
            ResolvedSwap    underlying     = swaption.Underlying;
            ResolvedSwapLeg fixedLeg       = this.fixedLeg(underlying);

            if (expiry < 0d)
            {     // Option has expired already
                return(PointSensitivityBuilder.none());
            }
            double                  forward           = SwapPricer.parRate(underlying, ratesProvider);
            ValueDerivatives        annuityDerivative = SwapPricer.LegPricer.annuityCashDerivative(fixedLeg, forward);
            double                  annuityCash       = annuityDerivative.Value;
            double                  annuityCashDr     = annuityDerivative.getDerivative(0);
            LocalDate               settlementDate    = ((CashSwaptionSettlement)swaption.SwaptionSettlement).SettlementDate;
            double                  discountSettle    = ratesProvider.discountFactor(fixedLeg.Currency, settlementDate);
            double                  strike            = calculateStrike(fixedLeg);
            double                  tenor             = swaptionVolatilities.tenor(fixedLeg.StartDate, fixedLeg.EndDate);
            double                  shift             = swaptionVolatilities.shift(expiry, tenor);
            ValueDerivatives        volatilityAdj     = swaptionVolatilities.volatilityAdjoint(expiry, tenor, strike, forward);
            bool                    isCall            = fixedLeg.PayReceive.Pay;
            double                  shiftedForward    = forward + shift;
            double                  shiftedStrike     = strike + shift;
            double                  price             = BlackFormulaRepository.price(shiftedForward, shiftedStrike, expiry, volatilityAdj.Value, isCall);
            double                  delta             = BlackFormulaRepository.delta(shiftedForward, shiftedStrike, expiry, volatilityAdj.Value, isCall);
            double                  vega                = BlackFormulaRepository.vega(shiftedForward, shiftedStrike, expiry, volatilityAdj.Value);
            PointSensitivityBuilder forwardSensi        = SwapPricer.parRateSensitivity(underlying, ratesProvider);
            PointSensitivityBuilder discountSettleSensi = ratesProvider.discountFactors(fixedLeg.Currency).zeroRatePointSensitivity(settlementDate);
            double                  sign                = swaption.LongShort.sign();

            return(forwardSensi.multipliedBy(sign * discountSettle * (annuityCash * (delta + vega * volatilityAdj.getDerivative(0)) + annuityCashDr * price)).combinedWith(discountSettleSensi.multipliedBy(sign * annuityCash * price)));
        }
        //-------------------------------------------------------------------------
        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)));
            }
        }
        //-------------------------------------------------------------------------
        public virtual double presentValue(FxResetNotionalExchange @event, RatesProvider provider)
        {
            // forecastValue * discountFactor
            double df = provider.discountFactor(@event.Currency, @event.PaymentDate);

            return(forecastValue(@event, provider) * df);
        }
        //-------------------------------------------------------------------------
        /// <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>
        /// Calculates the present value of the FRA product.
        /// <para>
        /// The present value of the product is the value on the valuation date.
        /// This is the discounted forecast value.
        ///
        /// </para>
        /// </summary>
        /// <param name="fra">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the present value of the product </returns>
        public virtual CurrencyAmount presentValue(ResolvedFra fra, RatesProvider provider)
        {
            // forecastValue * discountFactor
            double df = provider.discountFactor(fra.Currency, fra.PaymentDate);
            double pv = forecastValue0(fra, provider) * df;

            return(CurrencyAmount.of(fra.Currency, pv));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the price of the deliverable swap futures product.
        /// <para>
        /// The price of the product is the price on the valuation date.
        ///
        /// </para>
        /// </summary>
        /// <param name="future">  the future </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <returns> the price of the product, in decimal form </returns>
        public double price(ResolvedDsf future, RatesProvider ratesProvider)
        {
            ResolvedSwap   swap     = future.UnderlyingSwap;
            Currency       currency = future.Currency;
            CurrencyAmount pvSwap   = swapPricer.presentValue(swap, currency, ratesProvider);
            double         df       = ratesProvider.discountFactor(currency, future.DeliveryDate);

            return(1d + pvSwap.Amount / df);
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the future cash flow of the FRA product.
        /// <para>
        /// There is only one cash flow on the payment date for the FRA product.
        /// The expected currency amount of the cash flow is the same as <seealso cref="#forecastValue(ResolvedFra, RatesProvider)"/>.
        ///
        /// </para>
        /// </summary>
        /// <param name="fra">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the cash flows </returns>
        public virtual CashFlows cashFlows(ResolvedFra fra, RatesProvider provider)
        {
            LocalDate paymentDate   = fra.PaymentDate;
            double    forecastValue = forecastValue0(fra, provider);
            double    df            = provider.discountFactor(fra.Currency, paymentDate);
            CashFlow  cashFlow      = CashFlow.ofForecastValue(paymentDate, fra.Currency, forecastValue, df);

            return(CashFlows.of(cashFlow));
        }
Beispiel #16
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the par spread.
        /// <para>
        /// The par spread is the spread that should be added to the FX forward points to have a zero value.
        ///
        /// </para>
        /// </summary>
        /// <param name="swap">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the spread </returns>
        public virtual double parSpread(ResolvedFxSwap swap, RatesProvider provider)
        {
            Payment             counterPaymentNear = swap.NearLeg.CounterCurrencyPayment;
            MultiCurrencyAmount pv = presentValue(swap, provider);
            double pvCounterCcy    = pv.convertedTo(counterPaymentNear.Currency, provider).Amount;
            double dfEnd           = provider.discountFactor(counterPaymentNear.Currency, swap.FarLeg.PaymentDate);
            double notionalBaseCcy = swap.NearLeg.BaseCurrencyPayment.Amount;

            return(-pvCounterCcy / (notionalBaseCcy * dfEnd));
        }
Beispiel #17
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the par spread.
        /// <para>
        /// This is the spread that should be added to the FX points to have a zero value.
        ///
        /// </para>
        /// </summary>
        /// <param name="fx">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the spread </returns>
        public virtual double parSpread(ResolvedFxSingle fx, RatesProvider provider)
        {
            Payment             basePayment    = fx.BaseCurrencyPayment;
            Payment             counterPayment = fx.CounterCurrencyPayment;
            MultiCurrencyAmount pv             = presentValue(fx, provider);
            double pvCounterCcy    = pv.convertedTo(counterPayment.Currency, provider).Amount;
            double dfEnd           = provider.discountFactor(counterPayment.Currency, fx.PaymentDate);
            double notionalBaseCcy = basePayment.Amount;

            return(pvCounterCcy / (notionalBaseCcy * dfEnd));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the price sensitivity of the deliverable swap futures product.
        /// <para>
        /// The price sensitivity of the product is the sensitivity of the price to the underlying curves.
        ///
        /// </para>
        /// </summary>
        /// <param name="future">  the future </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <returns> the price curve sensitivity of the product </returns>
        public PointSensitivities priceSensitivity(ResolvedDsf future, RatesProvider ratesProvider)
        {
            ResolvedSwap            swap        = future.UnderlyingSwap;
            Currency                currency    = future.Currency;
            double                  pvSwap      = swapPricer.presentValue(swap, currency, ratesProvider).Amount;
            double                  dfInv       = 1d / ratesProvider.discountFactor(currency, future.DeliveryDate);
            PointSensitivityBuilder sensiSwapPv = swapPricer.presentValueSensitivity(swap, ratesProvider).multipliedBy(dfInv);
            PointSensitivityBuilder sensiDf     = ratesProvider.discountFactors(currency).zeroRatePointSensitivity(future.DeliveryDate).multipliedBy(-pvSwap * dfInv * dfInv);

            return(sensiSwapPv.combinedWith(sensiDf).build());
        }
        //-------------------------------------------------------------------------
        public virtual void currency_exposure_GBP()
        {
            LocalDate               startDate     = LocalDate.of(2016, 8, 2);
            LocalDate               fixingDate    = LocalDate.of(2016, 11, 2);
            LocalDate               endDate       = LocalDate.of(2016, 11, 4);
            double                  yearFraction  = 0.25;
            double                  rate          = 0.10;
            RateAccrualPeriod       accrual       = RateAccrualPeriod.builder().startDate(startDate).endDate(endDate).yearFraction(yearFraction).rateComputation(FixedRateComputation.of(rate)).build();
            double                  notional      = 1000000;
            RatePaymentPeriod       fixedFx       = RatePaymentPeriod.builder().accrualPeriods(accrual).fxReset(FxReset.of(FxIndexObservation.of(FxIndices.GBP_USD_WM, fixingDate, REF_DATA), GBP)).notional(notional).paymentDate(endDate).dayCount(DayCounts.ONE_ONE).currency(USD).build(); // 1_000_000 GBP paid in USD at maturity
            PointSensitivityBuilder pts           = PERIOD_PRICER.presentValueSensitivity(fixedFx, PROVIDER);
            MultiCurrencyAmount     ceComputed    = PERIOD_PRICER.currencyExposure(fixedFx, PROVIDER);
            double                  dfGbp         = PROVIDER.discountFactor(GBP, endDate);
            double                  ceGbpExpected = notional * yearFraction * rate * dfGbp;

            assertEquals(ceComputed.getAmount(GBP).Amount, ceGbpExpected, 1.0E-6);
            MultiCurrencyAmount ceWithoutPvComputed = PROVIDER.currencyExposure(pts.build().convertedTo(GBP, PROVIDER));
            CurrencyAmount      pvComputed          = CurrencyAmount.of(USD, PERIOD_PRICER.presentValue(fixedFx, PROVIDER));
            MultiCurrencyAmount ceComputed2         = ceWithoutPvComputed.plus(pvComputed);

            assertEquals(ceComputed2.getAmount(GBP).Amount, ceGbpExpected, TOLERANCE);
            assertEquals(ceComputed2.getAmount(USD).Amount, 0.0, TOLERANCE);
        }
        public virtual void test_presentValue()
        {
            MultiCurrencyAmount computed = PRICER.presentValue(FWD, PROVIDER);
            double expected1             = NOMINAL_USD * PROVIDER.discountFactor(USD, PAYMENT_DATE);
            double expected2             = -NOMINAL_USD *FX_RATE *PROVIDER.discountFactor(KRW, PAYMENT_DATE);

            assertEquals(computed.getAmount(USD).Amount, expected1, NOMINAL_USD * TOL);
            assertEquals(computed.getAmount(KRW).Amount, expected2, NOMINAL_USD * TOL);
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value of the Ibor fixing deposit product.
        /// <para>
        /// The present value of the product is the value on the valuation date.
        ///
        /// </para>
        /// </summary>
        /// <param name="deposit">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the present value of the product </returns>
        public virtual CurrencyAmount presentValue(ResolvedIborFixingDeposit deposit, RatesProvider provider)
        {
            Currency currency = deposit.Currency;

            if (provider.ValuationDate.isAfter(deposit.EndDate))
            {
                return(CurrencyAmount.of(currency, 0.0d));
            }
            double forwardRate    = this.forwardRate(deposit, provider);
            double discountFactor = provider.discountFactor(currency, deposit.EndDate);
            double fv             = deposit.Notional * deposit.YearFraction * (deposit.FixedRate - forwardRate);
            double pv             = discountFactor * fv;

            return(CurrencyAmount.of(currency, pv));
        }
        //-------------------------------------------------------------------------
        /// <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)));
        }
        //-------------------------------------------------------------------------
        public virtual MultiCurrencyAmount currencyExposure(FxResetNotionalExchange @event, RatesProvider provider)
        {
            LocalDate    fixingDate = @event.Observation.FixingDate;
            FxIndexRates rates      = provider.fxIndexRates(@event.Observation.Index);
            double       df         = provider.discountFactor(@event.Currency, @event.PaymentDate);

            if (!fixingDate.isAfter(provider.ValuationDate) && rates.Fixings.get(fixingDate).HasValue)
            {
                double fxRate = rates.rate(@event.Observation, @event.ReferenceCurrency);
                return(MultiCurrencyAmount.of(CurrencyAmount.of(@event.Currency, @event.Notional * df * fxRate)));
            }
            LocalDate maturityDate          = @event.Observation.MaturityDate;
            double    fxRateSpotSensitivity = rates.FxForwardRates.rateFxSpotSensitivity(@event.ReferenceCurrency, maturityDate);

            return(MultiCurrencyAmount.of(CurrencyAmount.of(@event.ReferenceCurrency, @event.Notional * df * fxRateSpotSensitivity)));
        }
Beispiel #24
0
        /// <summary>
        /// Calculates the par spread sensitivity to the curves.
        /// <para>
        /// The sensitivity is reported in the counter currency of the product, but is actually dimensionless.
        ///
        /// </para>
        /// </summary>
        /// <param name="swap">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the spread curve sensitivity </returns>
        public virtual PointSensitivities parSpreadSensitivity(ResolvedFxSwap swap, RatesProvider provider)
        {
            Payment             counterPaymentNear = swap.NearLeg.CounterCurrencyPayment;
            MultiCurrencyAmount pv = presentValue(swap, provider);
            double pvCounterCcy    = pv.convertedTo(counterPaymentNear.Currency, provider).Amount;
            double dfEnd           = provider.discountFactor(counterPaymentNear.Currency, swap.FarLeg.PaymentDate);
            double notionalBaseCcy = swap.NearLeg.BaseCurrencyPayment.Amount;
            double ps = -pvCounterCcy / (notionalBaseCcy * dfEnd);
            // backward sweep
            double psBar                       = 1d;
            double pvCounterCcyBar             = -1d / (notionalBaseCcy * dfEnd) * psBar;
            double dfEndBar                    = -ps / dfEnd * psBar;
            ZeroRateSensitivity ddfEnddr       = provider.discountFactors(counterPaymentNear.Currency).zeroRatePointSensitivity(swap.FarLeg.PaymentDate);
            PointSensitivities  result         = ddfEnddr.multipliedBy(dfEndBar).build();
            PointSensitivities  dpvdr          = presentValueSensitivity(swap, provider);
            PointSensitivities  dpvdrConverted = dpvdr.convertedTo(counterPaymentNear.Currency, provider);

            return(result.combinedWith(dpvdrConverted.multipliedBy(pvCounterCcyBar)));
        }
Beispiel #25
0
        //-------------------------------------------------------------------------
        // sensitivity to the spread for a payment period with FLAT compounding type
        private double pvbpCompoundedFlat(RatePaymentPeriod paymentPeriod, RatesProvider provider)
        {
            int nbCmp = paymentPeriod.AccrualPeriods.size();

            double[] rate = paymentPeriod.AccrualPeriods.Select(ap => rawRate(ap, provider)).ToArray();
            double   df   = provider.discountFactor(paymentPeriod.Currency, paymentPeriod.PaymentDate);
            double   rBar = 1.0;

            double[] cpaAccumulatedBar = new double[nbCmp + 1];
            cpaAccumulatedBar[nbCmp] = paymentPeriod.Notional * df * rBar;
            double spreadBar = 0.0d;

            for (int j = nbCmp - 1; j >= 0; j--)
            {
                cpaAccumulatedBar[j] = (1.0d + paymentPeriod.AccrualPeriods.get(j).YearFraction *rate[j] * paymentPeriod.AccrualPeriods.get(j).Gearing) * cpaAccumulatedBar[j + 1];
                spreadBar           += paymentPeriod.AccrualPeriods.get(j).YearFraction *cpaAccumulatedBar[j + 1];
            }
            return(spreadBar);
        }
Beispiel #26
0
        //-------------------------------------------------------------------------
        public virtual MultiCurrencyAmount currencyExposure(RatePaymentPeriod period, RatesProvider provider)
        {
            double df = provider.discountFactor(period.Currency, period.PaymentDate);

            if (period.FxReset.Present)
            {
                FxReset      fxReset    = period.FxReset.get();
                LocalDate    fixingDate = fxReset.Observation.FixingDate;
                FxIndexRates rates      = provider.fxIndexRates(fxReset.Observation.Index);
                if (!fixingDate.isAfter(provider.ValuationDate) && rates.Fixings.get(fixingDate).HasValue)
                {
                    double fxRate = rates.rate(fxReset.Observation, fxReset.ReferenceCurrency);
                    return(MultiCurrencyAmount.of(period.Currency, accrualWithNotional(period, period.Notional * fxRate * df, provider)));
                }
                double fxRateSpotSensitivity = rates.FxForwardRates.rateFxSpotSensitivity(fxReset.ReferenceCurrency, fxReset.Observation.MaturityDate);
                return(MultiCurrencyAmount.of(fxReset.ReferenceCurrency, accrualWithNotional(period, period.Notional * fxRateSpotSensitivity * df, provider)));
            }
            return(MultiCurrencyAmount.of(period.Currency, accrualWithNotional(period, period.Notional * df, provider)));
        }
        /// <summary>
        /// Calculates the present value curve sensitivity of the NDF product.
        /// <para>
        /// The present value sensitivity of the product is the sensitivity of the present value to
        /// the underlying curves.
        ///
        /// </para>
        /// </summary>
        /// <param name="ndf">  the product </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the point sensitivity of the present value </returns>
        public virtual PointSensitivities presentValueSensitivity(ResolvedFxNdf ndf, RatesProvider provider)
        {
            if (provider.ValuationDate.isAfter(ndf.PaymentDate))
            {
                return(PointSensitivities.empty());
            }
            Currency ccySettle               = ndf.SettlementCurrency;
            Currency ccyOther                = ndf.NonDeliverableCurrency;
            double   notionalSettle          = ndf.SettlementNotional;
            double   agreedRate              = ndf.AgreedFxRate.fxRate(ccySettle, ccyOther);
            double   forwardRate             = provider.fxIndexRates(ndf.Index).rate(ndf.Observation, ccySettle);
            double   dfSettle                = provider.discountFactor(ccySettle, ndf.PaymentDate);
            double   ratio                   = agreedRate / forwardRate;
            double   dscBar                  = (1d - ratio) * notionalSettle;
            PointSensitivityBuilder sensiDsc = provider.discountFactors(ccySettle).zeroRatePointSensitivity(ndf.PaymentDate).multipliedBy(dscBar);
            double forwardRateBar            = dfSettle * notionalSettle * ratio / forwardRate;
            PointSensitivityBuilder sensiFx  = provider.fxIndexRates(ndf.Index).ratePointSensitivity(ndf.Observation, ccySettle).withCurrency(ccySettle).multipliedBy(forwardRateBar);

            return(sensiDsc.combinedWith(sensiFx).build());
        }
Beispiel #28
0
        //-------------------------------------------------------------------------
        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)));
            }
        }
Beispiel #29
0
        // sensitivity to the spread for a payment period with FLAT compounding type
        private PointSensitivityBuilder pvbpSensitivtyCompoundedFlat(RatePaymentPeriod paymentPeriod, RatesProvider provider)
        {
            Currency ccy   = paymentPeriod.Currency;
            int      nbCmp = paymentPeriod.AccrualPeriods.size();

            double[] rate = paymentPeriod.AccrualPeriods.Select(ap => rawRate(ap, provider)).ToArray();
            double   df   = provider.discountFactor(ccy, paymentPeriod.PaymentDate);
            double   rB1  = 1.0;

            double[] cpaAccumulatedB1 = new double[nbCmp + 1];
            cpaAccumulatedB1[nbCmp] = paymentPeriod.Notional * df * rB1;
            for (int j = nbCmp - 1; j >= 0; j--)
            {
                RateAccrualPeriod accrualPeriod = paymentPeriod.AccrualPeriods.get(j);
                cpaAccumulatedB1[j] = (1.0d + accrualPeriod.YearFraction * rate[j] * accrualPeriod.Gearing) * cpaAccumulatedB1[j + 1];
            }
            // backward sweep
            double pvbpB2 = 1.0d;

            double[] cpaAccumulatedB1B2 = new double[nbCmp + 1];
            double[] rateB2             = new double[nbCmp];
            for (int j = 0; j < nbCmp; j++)
            {
                RateAccrualPeriod accrualPeriod = paymentPeriod.AccrualPeriods.get(j);
                cpaAccumulatedB1B2[j + 1] += accrualPeriod.YearFraction * pvbpB2;
                cpaAccumulatedB1B2[j + 1] += (1.0d + accrualPeriod.YearFraction * rate[j] * accrualPeriod.Gearing) * cpaAccumulatedB1B2[j];
                rateB2[j] += accrualPeriod.YearFraction * accrualPeriod.Gearing * cpaAccumulatedB1[j + 1] * cpaAccumulatedB1B2[j];
            }
            double dfB2 = paymentPeriod.Notional * rB1 * cpaAccumulatedB1B2[nbCmp];
            PointSensitivityBuilder dfdr   = provider.discountFactors(ccy).zeroRatePointSensitivity(paymentPeriod.PaymentDate);
            PointSensitivityBuilder pvbpdr = dfdr.multipliedBy(dfB2);

            for (int j = 0; j < nbCmp; j++)
            {
                RateAccrualPeriod accrualPeriod = paymentPeriod.AccrualPeriods.get(j);
                pvbpdr = pvbpdr.combinedWith(rateComputationFn.rateSensitivity(accrualPeriod.RateComputation, accrualPeriod.StartDate, accrualPeriod.EndDate, provider).multipliedBy(rateB2[j]));
            }
            return(pvbpdr);
        }
        //-------------------------------------------------------------------------
        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)));
            }
        }